diff --git a/CMakeLists.txt b/CMakeLists.txt index eee822a3f8..65f32fa11d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,26 +1,26 @@ -######################################################################################### -# # -# OpenSpace # -# # -# Copyright (c) 2014-2016 # -# # -# Permission is hereby granted, free of charge, to any person obtaining a copy of this # -# software and associated documentation files (the "Software"), to deal in the Software # -# without restriction, including without limitation the rights to use, copy, modify, # -# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # -# permit persons to whom the Software is furnished to do so, subject to the following # -# conditions: # -# # -# The above copyright notice and this permission notice shall be included in all copies # -# or substantial portions of the Software. # -# # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # -# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # -# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # -# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -######################################################################################### +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2016 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +########################################################################################## cmake_minimum_required (VERSION 3.4 FATAL_ERROR) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..b025b07993 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,4 @@ +## How to contribute +The easiest way to contribute is through a separate fork of the repository and submitting a pull-request. One of the core developers will judge the pull request and integrate it into the main `master` branch. Preferably, there is an accompanying issue (created by you or not) which is solved by the PR. In this case, feel free to use the phrase "(closes #XXX)" in the text of the pull request, where `XXX` is the number of the issue that you have solved. The PR should be in its own separate branch following the naming `pr/feature`, where `feature` is a short, descripting name of the additional feature or bug contained in the PR. + +For more information we refer to the [Wiki](https://github.com/OpenSpace/OpenSpace/wiki). If there are any questions, feel free to contact us via [email](mailto:alexander.bock@me.com?subject=OpenSpace: Contributing). \ No newline at end of file diff --git a/CREDITS b/CREDITS.md similarity index 66% rename from CREDITS rename to CREDITS.md index 3bb64218eb..02aa209148 100644 --- a/CREDITS +++ b/CREDITS.md @@ -1,16 +1,26 @@ Alexander Bock Joakim Kilby Emil Axelsson +Eric Myers Jonathas Costa Matthew Territo +Gene Payne +Kalle Bladin +Erik Sundén Jonas Strandstedt Hans-Christian Helltegen Michal Marcinkowski Anton Arbring Tomas Forsyth Rosin -Kalle Bladin Erik Broberg Michael Nilsson Sebastian Piwell Niclas Hultberg +Rickard Lindtstedt +Michael Sjöström +Michael Novén +Oskar Carlbaum + +Anteige +noahdasanaike diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..57ff97f0f2 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,74 @@ +def modules = [ + "base", + "debugging", + "fieldlines", + "galaxy", + "globebrowsing", + "iswa", + "kameleon", + "kameleonvolume", + "multiresvolume", + "newhorizons", + "onscreengui", + "space", + "toyvolume", + "volume" +]; + +def flags = "-DGHOUL_USE_DEVIL=OFF " + +for (module in modules) { + flags += "-DOPENSPACE_OPENSPACE_MODULE_" + module.toUpperCase() + "=ON " +} + +echo flags + +stage('Build') { + parallel linux: { + node('linux') { + checkout scm + sh 'git submodule update --init --recursive' + sh ''' + mkdir -p build + cd build + cmake .. ''' + + flags + ''' .. + make + ''' + } + }, + windows: { + node('windows') { + checkout scm + bat ''' + git submodule update --init --recursive + if not exist "build" mkdir "build" + cd build + cmake -G "Visual Studio 14 2015 Win64" .. ''' + + flags + ''' .. + msbuild.exe OpenSpace.sln /m:8 /p:Configuration=Debug + ''' + } + }, + osx: { + node('osx') { + checkout scm + sh 'git submodule update --init --recursive' + sh ''' + export PATH=${PATH}:/usr/local/bin:/Applications/CMake.app/Contents/bin + export CMAKE_BUILD_TOOL=/Applications/CMake.app/Contents/bin/CMake + srcDir=$PWD + if [ ! -d ${srcDir} ]; then + mkdir ${srcDir} + fi + if [ ! -d ${srcDir}/build ]; then + mkdir ${srcDir}/build + fi + cd ${srcDir}/build + /Applications/CMake.app/Contents/bin/cmake -G Xcode -D NASM=/usr/local/Cellar/nasm/2.11.08/bin/nasm ${srcDir} .. ''' + + flags + ''' + xcodebuild + ''' + } + } +} \ No newline at end of file diff --git a/LICENSE b/LICENSE.md similarity index 97% rename from LICENSE rename to LICENSE.md index 0e48e547cb..9f67ee7043 100644 --- a/LICENSE +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2014-2016 +Copyright (c) 2014-2017 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software diff --git a/README.md b/README.md new file mode 100644 index 0000000000..d3c2d1e8de --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +OpenSpace is an open source, non-commercial, and freely available interactive data visualization software designed to visualize the entire known universe and portray our ongoing efforts to investigate the cosmos. Bringing the latest techniques from data visualization research to the general public, OpenSpace supports interactive presentation of dynamic data from observations, simulations, and space mission planning and operations. The software works on multiple operating systems (Windows, Linux, MacOS) with an extensible architecture powering high resolution tiled displays and planetarium domes, making use of the latest graphic card technologies for rapid data throughput. In addition, OpenSpace enables simultaneous connections across the globe creating opportunity for shared experiences among audiences worldwide. + +The project stems from the same academic collaboration between Sweden’s Linköping University (LiU) and the American Museum of Natural History (AMNH) that led to the creation of Uniview and its parent company SCISS. Development of the software began several years ago through a close collaboration with NASA Goddard’s Community Coordinated Modeling Center (CCMC) to model space weather forecasting and continued last year with visualization of NASA’s New Horizons mission to Pluto and ESA’s Rosetta mission. This promising set of preliminary work provided a foundation for recent NASA funding, which has extended the collaboration to include the University of Utah’s Scientific Computing and Imaging (SCI) Institute, New York University’s Tandon School of Engineering, multiple informal science institutions across the United States, and multiple, international vendors. Current areas of focus within OpenSpace include: + +- Visualization of dynamic simulations via interactive volumetric rendering, as a priority for communicating research in astrophysics. +- Utilization of NASA’s SPICE observational geometry system with its Planetary Data Service (PDS) to enable space mission visualization that reveal how missions are designed to gather science. +- Globe browsing techniques across spatial and temporal scales to examine scientific campaigns on multiple planets, including close up surface exploration. + +This repository contains the source code and example scenes for OpenSpace, but does not contain any data. To build and install the client, we refer to the [Wiki](https://github.com/OpenSpace/OpenSpace/wiki) pages here on GitHub, specifically [building](https://github.com/OpenSpace/OpenSpace/wiki/General-Getting-Started-Guide%3A-Compiling-OpenSpace) for [Windows](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-Windows), [Linux](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-Linux), and [MacOS](https://github.com/OpenSpace/OpenSpace/wiki/Guides-Compile-OpenSpace-on-OSX). Required preexisting dependencies are: [NASM](http://www.nasm.us/), [Boost](http://www.boost.org/), and [Qt](http://www.qt.io/download). Feel free to create issues for missing features, bug reports, or compile problems or contact us via [email](mailto:alexander.bock@me.com?subject=OpenSpace:). \ No newline at end of file diff --git a/apps/OpenSpace/CMakeLists.txt b/apps/OpenSpace/CMakeLists.txt index 45f08811fe..c5e93b08bb 100644 --- a/apps/OpenSpace/CMakeLists.txt +++ b/apps/OpenSpace/CMakeLists.txt @@ -1,26 +1,28 @@ -######################################################################################### -# # -# OpenSpace # -# # -# Copyright (c) 2014-2015 # -# # -# Permission is hereby granted, free of charge, to any person obtaining a copy of this # -# software and associated documentation files (the "Software"), to deal in the Software # -# without restriction, including without limitation the rights to use, copy, modify, # -# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # -# permit persons to whom the Software is furnished to do so, subject to the following # -# conditions: # -# # -# The above copyright notice and this permission notice shall be included in all copies # -# or substantial portions of the Software. # -# # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # -# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # -# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # -# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -######################################################################################### +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2017 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +########################################################################################## + +include(${GHOUL_BASE_DIR}/support/cmake/CopySharedLibraries.cmake) set(APPLICATION_NAME OpenSpace) set(APPLICATION_LINK_TO_OPENSPACE ON) @@ -29,15 +31,99 @@ if (WIN32) set(RESOURCE_FILE ${OPENSPACE_APPS_DIR}/OpenSpace/openspace.rc) endif () + +######################## +# OpenVR section start # +######################## +option(OPENSPACE_OPENVR_SUPPORT "Build OpenSpace application with OpenVR support" OFF) + +if (OPENSPACE_OPENVR_SUPPORT) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${OPENSPACE_EXT_DIR}/sgct/cmake/modules/") + + find_package(OpenVR REQUIRED) + + set(SGCT_OPENVR_DEFINITIONS OPENVR_SUPPORT) + + if(NOT SGCT_OPENVR_INCLUDE_DIRECTORY) + if( WIN32 ) + find_path(SGCT_OPENVR_INCLUDE_DIRECTORY + NAMES SGCTOpenVR.h + PATHS $ENV{SGCT_ROOT_DIR}/additional_includes/openvr ${OPENSPACE_EXT_DIR}/sgct/additional_includes/openvr NO_DEFAULT_PATH + REQUIRED) + else() + find_path(SGCT_OPENVR_INCLUDE_DIRECTORY + NAMES SGCTOpenVR.h + PATH_SUFFIXES SGCTOpenVR + PATHS $ENV{SGCT_ROOT_DIR}/additional_includes/openvr ${OPENSPACE_EXT_DIR}/sgct/additional_includes/openvr + REQUIRED) + endif() + else() + set(SGCT_OPENVR_FILES ${SGCT_OPENVR_INCLUDE_DIRECTORY}/SGCTOpenVR.h ${SGCT_OPENVR_INCLUDE_DIRECTORY}/SGCTOpenVR.cpp) + endif() +else() + set(OPENVR_INCLUDE_DIRS "") + set(SGCT_OPENVR_INCLUDE_DIRECTORY "") + set(OPENVR_LIBRARY "") + set(SGCT_OPENVR_DEFINITIONS "") +endif() +######################## +# OpenVR section end # +######################## + +######################## +# Spout section start # +######################## +if (WIN32) + option(OPENSPACE_SPOUT_SUPPORT "Build OpenSpace application with Spout support" OFF) +endif () + +set(SPOUT_INCLUDE_DIRS "") +set(SPOUT_LIBRARY "") +set(SPOUT_DEFINITIONS "") +if (OPENSPACE_SPOUT_SUPPORT) + set(SPOUT_INCLUDE_DIRS ${OPENSPACE_APPS_DIR}/OpenSpace/ext/spout) + set(SPOUT_LIBRARY ${OPENSPACE_APPS_DIR}/OpenSpace/ext/spout/SpoutLibrary.lib) + set(SPOUT_DEFINITIONS "OPENSPACE_HAS_SPOUT") +endif () + +######################## +# Spout section end # +######################## + add_executable(${APPLICATION_NAME} + ${SGCT_OPENVR_FILES} ${OPENSPACE_APPS_DIR}/OpenSpace/main.cpp ${RESOURCE_FILE} ) -target_include_directories(${APPLICATION_NAME} PUBLIC ${OPENSPACE_BASE_DIR}/include) -target_link_libraries(${APPLICATION_NAME} libOpenSpace) +if (OPENSPACE_SPOUT_SUPPORT) + copy_files( + ${APPLICATION_NAME} + ${OPENSPACE_APPS_DIR}/OpenSpace/ext/spout/SpoutLibrary.dll + ) +endif () + +target_include_directories( + ${APPLICATION_NAME} PUBLIC + ${OPENSPACE_BASE_DIR}/include + ${OPENVR_INCLUDE_DIRS} + ${SGCT_OPENVR_INCLUDE_DIRECTORY} + ${SPOUT_INCLUDE_DIRS} +) + +target_link_libraries(${APPLICATION_NAME} + libOpenSpace + ${OPENVR_LIBRARY} + ${SPOUT_LIBRARY} +) + +target_compile_definitions(${APPLICATION_NAME} PUBLIC + ${SGCT_OPENVR_DEFINITIONS} + ${SPOUT_DEFINITIONS} +) if (MSVC) + target_link_libraries(${APPLICATION_NAME} Dbghelp.lib) set_target_properties(${APPLICATION_NAME} PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMTD.lib /NODEFAULTLIB:LIBCMT.lib" ) -endif () +endif() diff --git a/apps/OpenSpace/ext/readme.md b/apps/OpenSpace/ext/readme.md new file mode 100644 index 0000000000..2b6c321821 --- /dev/null +++ b/apps/OpenSpace/ext/readme.md @@ -0,0 +1,8 @@ +The spout folder is a copy of the folder: +SpoutSDK/Source in the repository: +https://github.com/leadedge/Spout2.git/SpoutSDK/Source/SPOUT_LIBRARY/Binaries +and +https://github.com/leadedge/Spout2.git/SpoutSDK/Source/SPOUT_LIBRARY/Include + +Last update: +https://github.com/leadedge/Spout2/commit/28dbea6059cd7968c4d2b296d6739a5fdebe9104 diff --git a/apps/OpenSpace/ext/spout/SpoutLibrary.dll b/apps/OpenSpace/ext/spout/SpoutLibrary.dll new file mode 100644 index 0000000000..36aca87f87 Binary files /dev/null and b/apps/OpenSpace/ext/spout/SpoutLibrary.dll differ diff --git a/apps/OpenSpace/ext/spout/SpoutLibrary.h b/apps/OpenSpace/ext/spout/SpoutLibrary.h new file mode 100644 index 0000000000..d50c0a1106 --- /dev/null +++ b/apps/OpenSpace/ext/spout/SpoutLibrary.h @@ -0,0 +1,90 @@ +// +// SpoutLibrary.dll +// +// Spout SDK dll compatible with any C++ compiler +// + +#include +#include + +#define SPOUTLIBRARY_EXPORTS // defined for this DLL. The application imports rather than exports + +#ifdef SPOUTLIBRARY_EXPORTS +#define SPOUTAPI __declspec(dllexport) +#else +#define SPOUTAPI __declspec(dllimport) +#endif + +//////////////////////////////////////////////////////////////////////////////// +// +// COM-Like abstract interface. +// This interface doesn't require __declspec(dllexport/dllimport) specifier. +// Method calls are dispatched via virtual table. +// Any C++ compiler can use it. +// Instances are obtained via factory function. +// +struct SPOUTLIBRARY +{ + // Sender + virtual bool CreateSender(const char *Sendername, unsigned int width, unsigned int height, DWORD dwFormat = 0) = 0; + virtual void ReleaseSender(DWORD dwMsec = 0) = 0; + virtual bool UpdateSender(const char* Sendername, unsigned int width, unsigned int height) = 0; + virtual bool SendTexture(GLuint TextureID, GLuint TextureTarget, unsigned int width, unsigned int height, bool bInvert = true, GLuint HostFBO = 0) = 0; + virtual bool SendImage(const unsigned char* pixels, unsigned int width, unsigned int height, GLenum glFormat = GL_RGBA, bool bInvert=false) = 0; + + // Receiver + virtual bool CreateReceiver(char* Sendername, unsigned int &width, unsigned int &height, bool bUseActive = false) = 0; + virtual void ReleaseReceiver() = 0; + virtual bool ReceiveTexture(char* Sendername, unsigned int &width, unsigned int &height, GLuint TextureID = 0, GLuint TextureTarget = 0, bool bInvert = false, GLuint HostFBO = 0) = 0; + virtual bool ReceiveImage(char* Sendername, unsigned int &width, unsigned int &height, unsigned char* pixels, GLenum glFormat = GL_RGBA, bool bInvert = false, GLuint HostFBO=0) = 0; + virtual bool CheckReceiver(char* Sendername, unsigned int &width, unsigned int &height, bool &bConnected) = 0; + virtual bool GetImageSize(char* sendername, unsigned int &width, unsigned int &height, bool &bMemoryMode) = 0; + + virtual bool BindSharedTexture() = 0; + virtual bool UnBindSharedTexture() = 0; + + virtual bool DrawSharedTexture(float max_x = 1.0, float max_y = 1.0, float aspect = 1.0, bool bInvert = true) = 0; + virtual bool DrawToSharedTexture(GLuint TextureID, GLuint TextureTarget, unsigned int width, unsigned int height, float max_x = 1.0, float max_y = 1.0, float aspect = 1.0, bool bInvert = false, GLuint HostFBO = 0) = 0; + + virtual int GetSenderCount() = 0; + virtual bool GetSenderName(int index, char* sendername, int MaxSize = 256) = 0; + virtual bool GetSenderInfo(const char* sendername, unsigned int &width, unsigned int &height, HANDLE &dxShareHandle, DWORD &dwFormat) = 0; + virtual bool GetActiveSender(char* Sendername) = 0; + virtual bool SetActiveSender(const char* Sendername) = 0; + + // Utilities + virtual bool SetDX9(bool bDX9 = true) = 0; // User request to use DirectX 9 (default is DirectX 11) + virtual bool GetDX9() = 0; // Return the flag that has been set + virtual bool SetMemoryShareMode(bool bMem = true) = 0; + virtual bool GetMemoryShareMode() = 0; + virtual int GetMaxSenders() = 0; // Get maximum senders allowed + virtual void SetMaxSenders(int maxSenders) = 0; // Set maximum senders allowed + virtual bool GetHostPath(const char *sendername, char *hostpath, int maxchars) = 0; // The path of the host that produced the sender + virtual int GetVerticalSync() = 0; + virtual bool SetVerticalSync(bool bSync = true) = 0; + virtual bool SelectSenderPanel(const char* message = NULL) = 0; + + // Access to globals + virtual bool GetSpoutSenderName(char * sendername, int maxchars) = 0; // get the global sender name + virtual bool IsSpoutInitialized() = 0; // has the class been initialized + + // Adapter functions + virtual int GetNumAdapters() = 0; // Get the number of graphics adapters in the system + virtual bool GetAdapterName(int index, char *adaptername, int maxchars) = 0; // Get an adapter name + virtual bool SetAdapter(int index = 0) = 0; // Set required graphics adapter for output + virtual int GetAdapter() = 0; // Get the SpoutDirectX global adapter index + + // Library release function + virtual void Release() = 0; + +}; + + +// Handle type. In C++ language the interface type is used. +typedef SPOUTLIBRARY* SPOUTHANDLE; + +// Factory function that creates instances of the SPOUT object. +extern "C" SPOUTAPI SPOUTHANDLE WINAPI GetSpout(VOID); + + +//////////////////////////////////////////////////////////////////////////////// diff --git a/apps/OpenSpace/ext/spout/SpoutLibrary.lib b/apps/OpenSpace/ext/spout/SpoutLibrary.lib new file mode 100644 index 0000000000..435552b195 Binary files /dev/null and b/apps/OpenSpace/ext/spout/SpoutLibrary.lib differ diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 0ff4b1d46d..ec55894de0 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -25,33 +25,151 @@ #include #include #include -#include + #include #include #include + #include -#include -#include -sgct::Engine* _sgctEngine; +#ifdef WIN32 + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#endif // WIN32 + +#ifdef OPENVR_SUPPORT +#include +#endif // OPENVR_SUPPORT + +#ifdef OPENSPACE_HAS_SPOUT +#include "SpoutLibrary.h" +#endif // OPENSPACE_HAS_SPOUT + + +#define DEVELOPER_MODE + +namespace { + +const char* _loggerCat = "main"; +sgct::Engine* SgctEngine; + +const char* OpenVRTag = "OpenVR"; +const char* SpoutTag = "Spout"; + +#ifdef WIN32 + +LONG WINAPI generateMiniDump(EXCEPTION_POINTERS* exceptionPointers) { + SYSTEMTIME stLocalTime; + GetLocalTime(&stLocalTime); + + + LFATAL("Printing Stack Trace that lead to the crash:"); + std::vector stackTrace = ghoul::stackTrace(); + for (const std::string& s : stackTrace) { + LINFO(s); + } + + std::string dumpFile = fmt::format( + "OpenSpace_{}_{}_{}-{}-{}-{}-{}-{}-{}--{}--{}.dmp", + openspace::OPENSPACE_VERSION_MAJOR, + openspace::OPENSPACE_VERSION_MINOR, + openspace::OPENSPACE_VERSION_PATCH, + stLocalTime.wYear, + stLocalTime.wMonth, + stLocalTime.wDay, + stLocalTime.wHour, + stLocalTime.wMinute, + stLocalTime.wSecond, + GetCurrentProcessId(), + GetCurrentThreadId() + ); + + LINFO("Creating dump file: " << dumpFile); + + HANDLE hDumpFile = CreateFile( + dumpFile.c_str(), + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE | FILE_SHARE_READ, + 0, + CREATE_ALWAYS, + 0, + 0 + ); + + MINIDUMP_EXCEPTION_INFORMATION exceptionParameter; + exceptionParameter.ThreadId = GetCurrentThreadId(); + exceptionParameter.ExceptionPointers = exceptionPointers; + exceptionParameter.ClientPointers = TRUE; + + BOOL success = MiniDumpWriteDump( + GetCurrentProcess(), + GetCurrentProcessId(), + hDumpFile, + MiniDumpWithDataSegs, + &exceptionParameter, + nullptr, + nullptr + ); + + if (success) { + LINFO("Created successfully"); + } + else { + LERROR("Dumpfile created unsuccessfully"); + } + + return EXCEPTION_EXECUTE_HANDLER; +} + +#endif // WIN32 + +#ifdef OPENVR_SUPPORT +sgct::SGCTWindow* FirstOpenVRWindow = nullptr; +#endif + +#ifdef OPENSPACE_HAS_SPOUT +/** + * This struct stores all information about a single render window. Depending on the + * frame setup, each window can be mono or stereo, the information of which is stored in + * the \c leftOrMain and \c right members respectively. + */ +struct SpoutWindow { + struct SpoutData { + SPOUTHANDLE handle = nullptr; + bool initialized = false; + }; + + /// The left framebuffer (or main, if there is no stereo rendering) + SpoutData leftOrMain; + + /// The right framebuffer + SpoutData right; + + /// The window ID of this windows + size_t windowId = size_t(-1); +}; + +/// The list of all windows with spout senders +std::vector SpoutWindows; + +#endif // OPENSPACE_HAS_SPOUT + -int main_main(int argc, char** argv); -void mainInitFunc(); -void mainPreSyncFunc(); -void mainPostSyncPreDrawFunc(); -void mainRenderFunc(); -void mainPostDrawFunc(); -void mainKeyboardCallback(int key, int scancode, int action, int mods); -void mainCharCallback(unsigned int codepoint, int mods); -void mainMouseButtonCallback(int key, int action); -void mainMousePosCallback(double x, double y); -void mainMouseScrollCallback(double posX, double posY); -void mainEncodeFun(); -void mainDecodeFun(); -void mainExternalControlCallback(const char * receivedChars, int size); -void mainLogCallback(const char* msg); std::pair supportedOpenGLVersion() { + // Just create a window in order to retrieve the available OpenGL version before we + // create the real window glfwInit(); // On OS X we need to explicitly set the version and specify that we are using CORE @@ -66,185 +184,124 @@ std::pair supportedOpenGLVersion() { #endif glfwWindowHint(GLFW_VISIBLE, GL_FALSE); + + // By creating an offscreen window, the user will not know that we created this window GLFWwindow* offscreen = glfwCreateWindow(128, 128, "", nullptr, nullptr); glfwMakeContextCurrent(offscreen); + // Get the OpenGL version int major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); + // And get rid of the window again glfwDestroyWindow(offscreen); glfwWindowHint(GLFW_VISIBLE, GL_TRUE); + return { major, minor }; } -namespace { - const std::string _loggerCat = "main"; -} - -int main(int argc, char** argv) { - try { - return main_main(argc, argv); - } - catch (const ghoul::RuntimeError& e) { - // Write out all of the information about the exception, flush the logs, and throw - LFATALC(e.component, e.message); - LogMgr.flushLogs(); - throw; - } - catch (const std::exception& e) { - // Write out all of the information about the exception, flush the logs, and throw - LFATALC("Exception", e.what()); - LogMgr.flushLogs(); - throw; - } - catch (...) { - // Write out all of the information about the exception, flush the logs, and throw - LFATALC("Exception", "Unknown exception"); - LogMgr.flushLogs(); - throw; - } -} - -int main_main(int argc, char** argv) { - auto glVersion = supportedOpenGLVersion(); - - // create the OpenSpace engine and get arguments for the sgct engine - std::vector sgctArguments; - const bool success = openspace::OpenSpaceEngine::create( - argc, argv, - std::make_unique(), - sgctArguments - ); - if (!success) - return EXIT_FAILURE; - - LINFO("Detected OpenGL version: " << glVersion.first << "." << glVersion.second); - - // create sgct engine c arguments - int newArgc = static_cast(sgctArguments.size()); - char** newArgv = new char*[newArgc]; - for (int i = 0; i < newArgc; ++i) { - newArgv[i] = const_cast(sgctArguments.at(i).c_str()); - } - - // Need to set this before the creation of the sgct::Engine - sgct::MessageHandler::instance()->setLogToConsole(false); - sgct::MessageHandler::instance()->setShowTime(false); - sgct::MessageHandler::instance()->setLogToCallback(true); - sgct::MessageHandler::instance()->setLogCallback(mainLogCallback); - -#ifdef __APPLE__ - glfwWindowHint(GLFW_STENCIL_BITS, 8); -#endif - - LDEBUG("Creating SGCT Engine"); - _sgctEngine = new sgct::Engine(newArgc, newArgv); - - // deallocate sgct c arguments - delete[] newArgv; - - // Bind functions - _sgctEngine->setInitOGLFunction(mainInitFunc); - _sgctEngine->setPreSyncFunction(mainPreSyncFunc); - _sgctEngine->setPostSyncPreDrawFunction(mainPostSyncPreDrawFunc); - _sgctEngine->setDrawFunction(mainRenderFunc); - _sgctEngine->setPostDrawFunction(mainPostDrawFunc); - _sgctEngine->setKeyboardCallbackFunction(mainKeyboardCallback); - _sgctEngine->setMouseButtonCallbackFunction(mainMouseButtonCallback); - _sgctEngine->setMousePosCallbackFunction(mainMousePosCallback); - _sgctEngine->setMouseScrollCallbackFunction(mainMouseScrollCallback); - _sgctEngine->setExternalControlCallback(mainExternalControlCallback); - _sgctEngine->setCharCallbackFunction(mainCharCallback); - - // Disable the immediate exit of the application when the ESC key is pressed - _sgctEngine->setExitKey(SGCT_KEY_UNKNOWN); - - sgct::MessageHandler::instance()->setNotifyLevel(sgct::MessageHandler::NOTIFY_ALL); - - // set encode and decode functions - // NOTE: starts synchronizing before init functions - sgct::SharedData::instance()->setEncodeFunction(mainEncodeFun); - sgct::SharedData::instance()->setDecodeFunction(mainDecodeFun); - - // try to open a window - LDEBUG("Initialize SGCT Engine"); - std::map, sgct::Engine::RunMode> versionMapping = { - { { 3, 3 }, sgct::Engine::RunMode::OpenGL_3_3_Core_Profile }, - { { 4, 0 }, sgct::Engine::RunMode::OpenGL_4_0_Core_Profile }, - { { 4, 1 }, sgct::Engine::RunMode::OpenGL_4_1_Core_Profile }, - { { 4, 2 }, sgct::Engine::RunMode::OpenGL_4_2_Core_Profile }, - { { 4, 3 }, sgct::Engine::RunMode::OpenGL_4_3_Core_Profile }, - { { 4, 4 }, sgct::Engine::RunMode::OpenGL_4_4_Core_Profile }, - { { 4, 5 }, sgct::Engine::RunMode::OpenGL_4_5_Core_Profile } - }; - ghoul_assert( - versionMapping.find(glVersion) != versionMapping.end(), - "Unknown OpenGL version. Missing statement in version mapping map" - ); - sgct::Engine::RunMode rm = versionMapping[glVersion]; - const bool initSuccess = _sgctEngine->init(rm); - - if (!initSuccess) { - LFATAL("Initializing failed"); - // could not open a window, deallocates and exits - delete _sgctEngine; - openspace::OpenSpaceEngine::destroy(); - return EXIT_FAILURE; - } - - // Main loop - LDEBUG("Starting rendering loop"); - _sgctEngine->render(); - LDEBUG("Ending rendering loop"); - - //clear function bindings to avoid crash after destroying the OpenSpace Engine - sgct::MessageHandler::instance()->setLogToCallback(false); - sgct::MessageHandler::instance()->setLogCallback(nullptr); - - LDEBUG("Destroying OpenSpaceEngine"); - openspace::OpenSpaceEngine::destroy(); - - // Clean up (deallocate) - LDEBUG("Destroying SGCT Engine"); - delete _sgctEngine; - - // Exit program - exit(EXIT_SUCCESS); -} - void mainInitFunc() { LTRACE("main::mainInitFunc(begin)"); - //is this node the master? (must be set after call to _sgctEngine->init()) - OsEng.setMaster(_sgctEngine->isMaster()); - - LDEBUG("Initializing OpenSpace Engine"); - bool success = OsEng.initialize(); - LDEBUG("Initializing OpenGL in OpenSpace Engine"); - if (success) { - success = OsEng.initializeGL(); + LDEBUG("Initializing OpenSpace Engine started"); + OsEng.initialize(); + LDEBUG("Initializing OpenSpace Engine finished"); + + LDEBUG("Initializing OpenGL in OpenSpace Engine started"); + OsEng.initializeGL(); + LDEBUG("Initializing OpenGL in OpenSpace Engine finished"); + + // Find if we have at least one OpenVR window + // Save reference to first OpenVR window, which is the one we will copy to the HMD. + for (size_t i = 0; i < SgctEngine->getNumberOfWindows(); ++i) { + if (SgctEngine->getWindowPtr(i)->checkIfTagExists(OpenVRTag)) { +#ifdef OPENVR_SUPPORT + FirstOpenVRWindow = SgctEngine->getWindowPtr(i); + + // If we have an OpenVRWindow, initialize OpenVR. + sgct::SGCTOpenVR::initialize( + SgctEngine->getNearClippingPlane(), SgctEngine->getFarClippingPlane() + ); +#else + LWARNING( + "OpenVR was requested, but OpenSpace was compiled without VR support." + ); +#endif + + break; + } } - if (!success) { - LFATAL("Initializing OpenSpaceEngine failed"); - LogMgr.flushLogs(); - exit(EXIT_FAILURE); - } - // Set the clear color for all non-linear projection viewports - size_t nWindows = _sgctEngine->getNumberOfWindows(); + // @CLEANUP: Why is this necessary? We can set the clear color in the configuration + // files --- abock + const size_t nWindows = SgctEngine->getNumberOfWindows(); for (size_t i = 0; i < nWindows; ++i) { - sgct::SGCTWindow* w = _sgctEngine->getWindowPtr(i); - size_t nViewports = w->getNumberOfViewports(); + sgct::SGCTWindow* w = SgctEngine->getWindowPtr(i); + const size_t nViewports = w->getNumberOfViewports(); for (size_t j = 0; j < nViewports; ++j) { sgct_core::Viewport* v = w->getViewport(j); ghoul_assert(v != nullptr, "Number of reported viewports was incorrect"); sgct_core::NonLinearProjection* p = v->getNonLinearProjectionPtr(); - if (p) + if (p) { p->setClearColor(glm::vec4(0.f, 0.f, 0.f, 1.f)); + } } } + + for (size_t i = 0; i < nWindows; ++i) { + const sgct::SGCTWindow* windowPtr = SgctEngine->getWindowPtr(i); + + if (!windowPtr->checkIfTagExists(SpoutTag)) { + continue; + } + +#ifdef OPENSPACE_HAS_SPOUT + SpoutWindow w; + + w.windowId = i; + + const sgct::SGCTWindow::StereoMode sm = windowPtr->getStereoMode(); + const bool hasStereo = + (sm != sgct::SGCTWindow::No_Stereo) && + (sm < sgct::SGCTWindow::Side_By_Side_Stereo); + + if (hasStereo) { + SpoutWindow::SpoutData& left = w.leftOrMain; + left.handle = GetSpout(); + left.initialized = left.handle->CreateSender( + (windowPtr->getName() + "_left").c_str(), + windowPtr->getXFramebufferResolution(), + windowPtr->getYFramebufferResolution() + ); + + SpoutWindow::SpoutData& right = w.right; + right.handle = GetSpout(); + right.initialized = right.handle->CreateSender( + (windowPtr->getName() + "_right").c_str(), + windowPtr->getXFramebufferResolution(), + windowPtr->getYFramebufferResolution() + ); + } + else { + SpoutWindow::SpoutData& main = w.leftOrMain; + main.handle = GetSpout(); + main.initialized = main.handle->CreateSender( + windowPtr->getName().c_str(), + windowPtr->getXFramebufferResolution(), + windowPtr->getYFramebufferResolution() + ); + } + + SpoutWindows.push_back(std::move(w)); +#else + LWARNING( + "Spout was requested, but OpenSpace was compiled without Spout support." + ); + +#endif // OPENSPACE_HAS_SPOUT + } LTRACE("main::mainInitFunc(end)"); } @@ -255,59 +312,96 @@ void mainPreSyncFunc() { LTRACE("main::mainPreSyncFunc(end)"); } -volatile bool busyWaitDecode = false; void mainPostSyncPreDrawFunc() { -// if (OsEng.useBusyWaitForDecode() && !sgct::Engine::instance()->isMaster()) { -// while (minilog.str().size() && minilog.str().back() != DECODE.end) { -// std::this_thread::sleep_for(std::chrono::microseconds(10)); -// } -// } LTRACE("main::postSynchronizationPreDraw(begin)"); OsEng.postSynchronizationPreDraw(); + +#ifdef OPENVR_SUPPORT + if (FirstOpenVRWindow) { + // Update pose matrices for all tracked OpenVR devices once per frame + sgct::SGCTOpenVR::updatePoses(); + } +#endif // OPENVR_SUPPORT + LTRACE("main::postSynchronizationPreDraw(end)"); } void mainRenderFunc() { LTRACE("main::mainRenderFunc(begin)"); - using glm::mat4; - using glm::translate; - //not the most efficient, but for clarity @JK - mat4 userMatrix = translate(mat4(1.f), _sgctEngine->getDefaultUserPtr()->getPos()); - mat4 sceneMatrix = _sgctEngine->getModelMatrix(); - mat4 viewMatrix = _sgctEngine->getCurrentViewMatrix() * userMatrix; + glm::mat4 viewMatrix = + SgctEngine->getCurrentViewMatrix() * + // User matrix + glm::translate( + glm::mat4(1.f), + SgctEngine->getDefaultUserPtr()->getPos() + ) + ; - //dont shift nav-direction on master, makes it very tricky to navigate @JK - if (!OsEng.ref().isMaster()) - viewMatrix = viewMatrix * sceneMatrix; + glm::mat4 projectionMatrix = SgctEngine->getCurrentProjectionMatrix(); +#ifdef OPENVR_SUPPORT + bool currentWindowIsHMD = FirstOpenVRWindow == SgctEngine->getCurrentWindowPtr(); + if (sgct::SGCTOpenVR::isHMDActive() && currentWindowIsHMD) { + projectionMatrix = sgct::SGCTOpenVR::getHMDCurrentViewProjectionMatrix( + SgctEngine->getCurrentFrustumMode() + ); + } +#endif - mat4 projectionMatrix = _sgctEngine->getCurrentProjectionMatrix(); - OsEng.render(projectionMatrix, viewMatrix); + OsEng.render( + SgctEngine->getModelMatrix(), + viewMatrix, + projectionMatrix + ); LTRACE("main::mainRenderFunc(end)"); } void mainPostDrawFunc() { LTRACE("main::mainPostDrawFunc(begin)"); - OsEng.postDraw(); - LTRACE("main::mainPostDrawFunc(end)"); -// if (OsEng.logSGCTOutOfOrderErrors()) { -// if (sgct::Engine::instance()->isMaster()) { -// if (minilog.str() != EXPECTED_MASTER_LOG) { -// LERRORC("Minilog", "Bad combination: " << minilog.str()); -// } -// } -// else { -// if (minilog.str() != EXPECTED_SLAVE_LOG) { -// LERRORC("Minilog", "Bad combination: " << minilog.str()); -// } -// } -// } +#ifdef OPENVR_SUPPORT + if (FirstOpenVRWindow) { + // Copy the first OpenVR window to the HMD + sgct::SGCTOpenVR::copyWindowToHMD(FirstOpenVRWindow); + } +#endif // OPENVR_SUPPORT + + OsEng.postDraw(); + +#ifdef OPENSPACE_HAS_SPOUT + for (const SpoutWindow& w : SpoutWindows) { + sgct::SGCTWindow* window = SgctEngine->getWindowPtr(w.windowId); + if (w.leftOrMain.initialized) { + GLuint texId = window->getFrameBufferTexture(sgct::Engine::LeftEye); + glBindTexture(GL_TEXTURE_2D, texId); + w.leftOrMain.handle->SendTexture( + texId, + GL_TEXTURE_2D, + window->getXFramebufferResolution(), + window->getYFramebufferResolution() + ); + } + + if (w.right.initialized) { + GLuint texId = window->getFrameBufferTexture(sgct::Engine::RightEye); + glBindTexture(GL_TEXTURE_2D, texId); + w.right.handle->SendTexture( + texId, + GL_TEXTURE_2D, + window->getXFramebufferResolution(), + window->getYFramebufferResolution() + ); + } + } + glBindTexture(GL_TEXTURE_2D, 0); +#endif // OPENSPACE_HAS_SPOUT + + LTRACE("main::mainPostDrawFunc(end)"); } void mainExternalControlCallback(const char* receivedChars, int size) { LTRACE("main::mainExternalControlCallback(begin)"); - if (OsEng.isMaster()) { + if (SgctEngine->isMaster()) { OsEng.externalControlCallback(receivedChars, size, 0); } LTRACE("main::mainExternalControlCallback(end)"); @@ -315,40 +409,45 @@ void mainExternalControlCallback(const char* receivedChars, int size) { void mainKeyboardCallback(int key, int, int action, int mods) { LTRACE("main::mainKeyboardCallback(begin)"); - if (OsEng.isMaster()) { + if (SgctEngine->isMaster()) { OsEng.keyboardCallback( openspace::Key(key), openspace::KeyModifier(mods), openspace::KeyAction(action) - ); + ); } LTRACE("main::mainKeyboardCallback(begin)"); } void mainMouseButtonCallback(int key, int action) { LTRACE("main::mainMouseButtonCallback(begin)"); - if (OsEng.isMaster()) { + if (SgctEngine->isMaster()) { OsEng.mouseButtonCallback( openspace::MouseButton(key), openspace::MouseAction(action) - ); + ); } LTRACE("main::mainMouseButtonCallback(end)"); } void mainMousePosCallback(double x, double y) { - if (OsEng.isMaster()) + if (SgctEngine->isMaster()) { OsEng.mousePositionCallback(x, y); + } } -void mainMouseScrollCallback(double posX, double posY) { - if (OsEng.isMaster()) +void mainMouseScrollCallback(double, double posY) { + LTRACE("main::mainMouseScrollCallback(begin"); + if (SgctEngine->isMaster()) { OsEng.mouseScrollWheelCallback(posY); + } + LTRACE("main::mainMouseScrollCallback(end)"); } void mainCharCallback(unsigned int codepoint, int mods) { - if (OsEng.isMaster()) + if (SgctEngine->isMaster()) { OsEng.charCallback(codepoint, openspace::KeyModifier(mods)); + } } void mainEncodeFun() { @@ -365,10 +464,189 @@ void mainDecodeFun() { void mainLogCallback(const char* msg) { std::string message = msg; - if (message.empty() || message == ".") + if (message.empty() || message == ".") { // We don't want the empty '.' message that SGCT sends while it is waiting for // connections from other network nodes return; + } // Remove the trailing \n that is passed along - LINFOC("SGCT", message.substr(0, std::max(message.size() - 1, 0))); + LINFOC("SGCT", message.substr(0, message.size() - 1)); +} + +int main_main(int argc, char** argv) { + std::pair glVersion = supportedOpenGLVersion(); + + // Create the OpenSpace engine and get arguments for the SGCT engine + // @CLEANUP: Replace the return valua with throwing an exception --abock + std::vector sgctArguments; + bool requestQuit = false; + openspace::OpenSpaceEngine::create( + argc, argv, + std::make_unique(), + sgctArguments, + requestQuit + ); + + if (requestQuit) { + return EXIT_SUCCESS; + } + + LINFO("Detected OpenGL version: " << glVersion.first << "." << glVersion.second); + + // Create sgct engine c arguments + int newArgc = static_cast(sgctArguments.size()); + + char** newArgv = new char*[newArgc]; + for (int i = 0; i < newArgc; ++i) { + newArgv[i] = const_cast(sgctArguments.at(i).c_str()); + } + + // Need to set this before the creation of the sgct::Engine + sgct::MessageHandler::instance()->setLogToConsole(false); + sgct::MessageHandler::instance()->setShowTime(false); + sgct::MessageHandler::instance()->setLogToCallback(true); + sgct::MessageHandler::instance()->setLogCallback(mainLogCallback); + +#ifdef __APPLE__ + glfwWindowHint(GLFW_STENCIL_BITS, 8); +#endif + + LDEBUG("Creating SGCT Engine"); + SgctEngine = new sgct::Engine(newArgc, newArgv); + + // Deallocate sgct c arguments + delete[] newArgv; + + // Bind functions + SgctEngine->setInitOGLFunction(mainInitFunc); + SgctEngine->setPreSyncFunction(mainPreSyncFunc); + SgctEngine->setPostSyncPreDrawFunction(mainPostSyncPreDrawFunc); + SgctEngine->setDrawFunction(mainRenderFunc); + SgctEngine->setPostDrawFunction(mainPostDrawFunc); + SgctEngine->setKeyboardCallbackFunction(mainKeyboardCallback); + SgctEngine->setMouseButtonCallbackFunction(mainMouseButtonCallback); + SgctEngine->setMousePosCallbackFunction(mainMousePosCallback); + SgctEngine->setMouseScrollCallbackFunction(mainMouseScrollCallback); + SgctEngine->setExternalControlCallback(mainExternalControlCallback); + SgctEngine->setCharCallbackFunction(mainCharCallback); + + // Disable the immediate exit of the application when the ESC key is pressed + SgctEngine->setExitKey(SGCT_KEY_UNKNOWN); + + sgct::MessageHandler::instance()->setNotifyLevel(sgct::MessageHandler::NOTIFY_ALL); + + // Set encode and decode functions + // NOTE: starts synchronizing before init functions + sgct::SharedData::instance()->setEncodeFunction(mainEncodeFun); + sgct::SharedData::instance()->setDecodeFunction(mainDecodeFun); + + // Try to open a window + LDEBUG("Initialize SGCT Engine"); + std::map, sgct::Engine::RunMode> versionMapping = { + { { 3, 3 }, sgct::Engine::RunMode::OpenGL_3_3_Core_Profile }, + { { 4, 0 }, sgct::Engine::RunMode::OpenGL_4_0_Core_Profile }, + { { 4, 1 }, sgct::Engine::RunMode::OpenGL_4_1_Core_Profile }, + { { 4, 2 }, sgct::Engine::RunMode::OpenGL_4_2_Core_Profile }, + { { 4, 3 }, sgct::Engine::RunMode::OpenGL_4_3_Core_Profile }, + { { 4, 4 }, sgct::Engine::RunMode::OpenGL_4_4_Core_Profile }, + { { 4, 5 }, sgct::Engine::RunMode::OpenGL_4_5_Core_Profile } + }; + ghoul_assert( + versionMapping.find(glVersion) != versionMapping.end(), + "Unknown OpenGL version. Missing statement in version mapping map" + ); + + auto cleanup = [&](){ + OsEng.deinitialize(); + + // Clear function bindings to avoid crash after destroying the OpenSpace Engine + sgct::MessageHandler::instance()->setLogToCallback(false); + sgct::MessageHandler::instance()->setLogCallback(nullptr); + + LDEBUG("Destroying OpenSpaceEngine"); + openspace::OpenSpaceEngine::destroy(); + + LDEBUG("Destroying SGCT Engine"); + delete SgctEngine; + + +#ifdef OPENVR_SUPPORT + // Clean up OpenVR + sgct::SGCTOpenVR::shutdown(); +#endif + +#ifdef OPENSPACE_HAS_SPOUT + for (SpoutWindow& w : SpoutWindows) { + if (w.leftOrMain.handle) { + w.leftOrMain.handle->ReleaseReceiver(); + w.leftOrMain.handle->Release(); + } + if (w.right.handle) { + w.right.handle->ReleaseReceiver(); + w.right.handle->Release(); + } + } +#endif // OPENSPACE_HAS_SPOUT + }; + + bool initSuccess = SgctEngine->init(versionMapping[glVersion]); + + if (!initSuccess) { + LFATAL("Initializing failed"); + cleanup(); + return EXIT_FAILURE; + } + + // Main loop + LDEBUG("Starting rendering loop"); + SgctEngine->render(); + LDEBUG("Ending rendering loop"); + + cleanup(); + + // Exit program + exit(EXIT_SUCCESS); +} + +} // namespace + +int main(int argc, char** argv) { +#ifdef WIN32 + SetUnhandledExceptionFilter(generateMiniDump); +#endif // WIN32 + + // If we are working as a developer, we don't want to catch the exceptions in order to + // find the locations where the exceptions are raised. + // If we are not in developer mode, we want to catch and at least log the error before + // dying +#ifdef DEVELOPER_MODE + return main_main(argc, argv); +#else + // We wrap the actual main function in a try catch block so that we can get and print + // some additional information in case an exception is raised + try { + return main_main(argc, argv); + } + catch (const ghoul::RuntimeError& e) { + // Write out all of the information about the exception and flush the logs + LFATALC(e.component, e.message); + LogMgr.flushLogs(); + return EXIT_FAILURE; + } + catch (const ghoul::AssertionException& e) { + // We don't want to catch the assertion exception as we won't be able to add a + // breakpoint for debugging + LFATALC("Assertion failed", e.what()); + throw; + } catch (const std::exception& e) { + LFATALC("Exception", e.what()); + LogMgr.flushLogs(); + return EXIT_FAILURE; + } + catch (...) { + LFATALC("Exception", "Unknown exception"); + LogMgr.flushLogs(); + return EXIT_FAILURE; + } +#endif // DEVELOPER_MODE } diff --git a/apps/DataConverter/CMakeLists.txt b/apps/TaskRunner/CMakeLists.txt similarity index 85% rename from apps/DataConverter/CMakeLists.txt rename to apps/TaskRunner/CMakeLists.txt index 24bfdc7968..69f23771d3 100644 --- a/apps/DataConverter/CMakeLists.txt +++ b/apps/TaskRunner/CMakeLists.txt @@ -22,26 +22,18 @@ # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # ######################################################################################### -set(APPLICATION_NAME DataConverter) +set(APPLICATION_NAME TaskRunner) set(APPLICATION_LINK_TO_OPENSPACE ON) include (${GHOUL_BASE_DIR}/support/cmake/handle_external_library.cmake) -set(application_path ${OPENSPACE_APPS_DIR}/DataConverter) +set(application_path ${OPENSPACE_APPS_DIR}/TaskRunner) set(SOURCE_FILES ${application_path}/main.cpp - ${application_path}/milkywayconversiontask.cpp - ${application_path}/milkywaypointsconversiontask.cpp -) -set(HEADER_FILES - ${application_path}/conversiontask.h - ${application_path}/milkywayconversiontask.h - ${application_path}/milkywaypointsconversiontask.h ) add_executable(${APPLICATION_NAME} MACOSX_BUNDLE ${SOURCE_FILES} - ${HEADER_FILES} ) diff --git a/apps/DataConverter/main.cpp b/apps/TaskRunner/main.cpp similarity index 54% rename from apps/DataConverter/main.cpp rename to apps/TaskRunner/main.cpp index eb147ec43d..5edbd82b41 100644 --- a/apps/DataConverter/main.cpp +++ b/apps/TaskRunner/main.cpp @@ -33,50 +33,98 @@ #include #include +#include + +#include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include -#include - -int main(int argc, char** argv) { - using namespace openspace; - using namespace dataconverter; - - ghoul::initialize(); +namespace { + const std::string ConfigurationFile = "openspace.cfg"; + const std::string _loggerCat = "TaskRunner Main"; +} +void initTextureReaders() { #ifdef GHOUL_USE_DEVIL ghoul::io::TextureReader::ref().addReader(std::make_shared()); #endif // GHOUL_USE_DEVIL #ifdef GHOUL_USE_FREEIMAGE ghoul::io::TextureReader::ref().addReader(std::make_shared()); #endif // GHOUL_USE_FREEIMAGE +} - openspace::ProgressBar pb(100); - std::function onProgress = [&](float progress) { - pb.print(progress * 100); - }; +int main(int argc, char** argv) { + using namespace openspace; - // TODO: Make the converter configurable using either - // config files (json, lua dictionaries), - // lua scripts, - // or at the very least: a command line interface. - - MilkyWayConversionTask mwConversionTask( - "F:/mw_june2016/volumeslices/img/comp/v003/frames/primary/0100/cam2_main.", - ".exr", - 1385, - 512, - "F:/mw_june2016/mw_512_512_64_june.rawvolume", - glm::vec3(512, 512, 64)); + ghoul::initialize(); + initTextureReaders(); + + FactoryManager::initialize(); + FactoryManager::ref().addFactory( + std::make_unique>(), + "Renderable" + ); + FactoryManager::ref().addFactory( + std::make_unique>(), + "Task" + ); + FactoryManager::ref().addFactory( + std::make_unique>(), + "Translation" + ); + + FactoryManager::ref().addFactory( + std::make_unique>(), + "Rotation" + ); + + FactoryManager::ref().addFactory( + std::make_unique>(), + "Scale" + ); + + openspace::ConfigurationManager configuration; + std::string configurationFile = configuration.findConfiguration(ConfigurationFile); + configuration.loadFromFile(configurationFile); + + ModuleEngine moduleEngine; + moduleEngine.initialize(); + + std::string tasksPath; + configuration.getValue(ConfigurationManager::KeyConfigTask, tasksPath); + + LINFO("Initialization done."); + + TaskLoader taskLoader; + std::vector> tasks = taskLoader.tasksFromFile(tasksPath); - //MilkyWayPointsConversionTask mwpConversionTask("F:/mw_june2016/points.off", "F:/mw_june2016/points.off.binary"); + size_t nTasks = tasks.size(); + if (nTasks == 1) { + LINFO("Task queue has 1 item"); + } else { + LINFO("Task queue has " << tasks.size() << " items"); + } + for (size_t i = 0; i < tasks.size(); i++) { + Task& task = *tasks[i].get(); + LINFO("Performing task " << (i+1) << " out of " << tasks.size() << ": " << task.description()); + ProgressBar progressBar(100); + auto onProgress = [&progressBar](float progress) { + progressBar.print(progress * 100); + }; + task.perform(onProgress); + } - mwConversionTask.perform(onProgress); - //mwpConversionTask.perform(onProgress); - - - std::cout << "Done." << std::endl; + std::cout << "Done performing tasks." << std::endl; std::cin.get(); return 0; diff --git a/config/sgct/VRArenaSimCenter.xml b/config/sgct/VRArenaSimCenter.xml deleted file mode 100644 index f57ec51789..0000000000 --- a/config/sgct/VRArenaSimCenter.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/config/sgct/ccmc_lab_all.xml b/config/sgct/ccmc_lab_all.xml deleted file mode 100644 index 9c2fcd4958..0000000000 --- a/config/sgct/ccmc_lab_all.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/config/sgct/ccmc_lab_work.xml b/config/sgct/ccmc_lab_work.xml deleted file mode 100644 index 0c9f4069b6..0000000000 --- a/config/sgct/ccmc_lab_work.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/config/sgct/openvr_htcVive.xml b/config/sgct/openvr_htcVive.xml new file mode 100644 index 0000000000..e663b11521 --- /dev/null +++ b/config/sgct/openvr_htcVive.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/sgct/openvr_oculusRiftCv1.xml b/config/sgct/openvr_oculusRiftCv1.xml new file mode 100644 index 0000000000..e264dd3788 --- /dev/null +++ b/config/sgct/openvr_oculusRiftCv1.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config/sgct/single.xml b/config/sgct/single.xml index 7b20bcb10c..6f8f58b23b 100644 --- a/config/sgct/single.xml +++ b/config/sgct/single.xml @@ -4,7 +4,7 @@ - + diff --git a/config/sgct/single_4k.xml b/config/sgct/single_4k.xml deleted file mode 100644 index cb4dd6339c..0000000000 --- a/config/sgct/single_4k.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/config/sgct/single_gui.xml b/config/sgct/single_gui.xml index a3956e40f6..129232a9ea 100644 --- a/config/sgct/single_gui.xml +++ b/config/sgct/single_gui.xml @@ -4,7 +4,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/config/sgct/single_sbs_stereo.xml b/config/sgct/single_sbs_stereo.xml deleted file mode 100644 index d92f95ed66..0000000000 --- a/config/sgct/single_sbs_stereo.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/config/sgct/single_stereo.xml b/config/sgct/single_stereo.xml deleted file mode 100644 index 8497af6188..0000000000 --- a/config/sgct/single_stereo.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/config/sgct/single_two_win.xml b/config/sgct/single_two_win.xml index 4cd802423a..2f7f49efc6 100644 --- a/config/sgct/single_two_win.xml +++ b/config/sgct/single_two_win.xml @@ -3,34 +3,26 @@ - + - - - - - - - - + + + + - + - - - - - - - - + + + + diff --git a/config/sgct/two_nodes.xml b/config/sgct/two_nodes.xml index 9ec00bf7bc..b4ae20f8c0 100644 --- a/config/sgct/two_nodes.xml +++ b/config/sgct/two_nodes.xml @@ -4,18 +4,14 @@ - + - - - - - - - - + + + + @@ -23,18 +19,14 @@ - + - - - - - - - - + + + + diff --git a/data/scene/atmosphereearth.scene b/data/scene/atmosphereearth.scene index 914c040ca7..e00b18fc74 100644 --- a/data/scene/atmosphereearth.scene +++ b/data/scene/atmosphereearth.scene @@ -6,7 +6,7 @@ function preInitialization() critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") openspace.time.setTime(openspace.time.currentWallTime()) diff --git a/data/scene/atmosphereearth/atmosphereearth.mod b/data/scene/atmosphereearth/atmosphereearth.mod index f5c98aaf3f..b019c71241 100644 --- a/data/scene/atmosphereearth/atmosphereearth.mod +++ b/data/scene/atmosphereearth/atmosphereearth.mod @@ -30,15 +30,15 @@ return { Source1 = { Name = "Sun", -- All radius in meters - Radius = {696.3, 6} + Radius = 696.3E6 }, - --Source2 = { Name = "Monolith", Radius = {0.01, 6} }, + --Source2 = { Name = "Monolith", Radius = 0.01E6 }, Caster1 = { Name = "Moon", -- All radius in meters - Radius = {1.737, 6} + Radius = 1.737E6 }, - --Caster2 = { Name = "Independency Day Ship", Radius = {0.0, 0.0} } + --Caster2 = { Name = "Independency Day Ship", Radius = 0 } }, Textures = { Type = "simple", @@ -127,7 +127,7 @@ return { Parent = "Earth", Renderable = { Type = "RenderablePlane", - Size = {3.0, 11.0}, + Size = 3.0E11.0, Origin = "Center", Billboard = true, Texture = "textures/marker.png", @@ -145,7 +145,7 @@ return { -- Renderable = { -- Type = "RenderablePlane", -- Billboard = true, - -- Size = { 6.371, 6 }, + -- Size = 6.371E6, -- Texture = "textures/graph.jpg", -- Atmosphere = { -- Type = "Nishita", -- for example, values missing etc etc diff --git a/data/scene/dawn.scene b/data/scene/dawn.scene index 6ae70e3fb9..78c03cece5 100644 --- a/data/scene/dawn.scene +++ b/data/scene/dawn.scene @@ -6,7 +6,7 @@ function preInitialization() critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") openspace.time.setTime("2011 AUG 06 00:00:00") diff --git a/data/scene/default.scene b/data/scene/default.scene index d2344f3ab0..3714385858 100644 --- a/data/scene/default.scene +++ b/data/scene/default.scene @@ -6,12 +6,11 @@ function preInitialization() critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") openspace.time.setTime(openspace.time.currentWallTime()) dofile(openspace.absPath('${SCRIPTS}/bind_common_keys.lua')) - end function postInitialization() @@ -28,6 +27,8 @@ function postInitialization() openspace.setPropertyValue("MilkyWay.renderable.transparency", 0.55) openspace.setPropertyValue("MilkyWay.renderable.segments", 50) + openspace.addVirtualProperty("BoolProperty", "Show Trails", "*Trail.renderable.enabled", true, nil, nil) + openspace.resetCameraDirection() openspace.printInfo("Done setting default values") diff --git a/data/scene/earth/earth.mod b/data/scene/earth/earth.mod index 78b3a3bb90..3e293f6f3d 100644 --- a/data/scene/earth/earth.mod +++ b/data/scene/earth/earth.mod @@ -34,7 +34,7 @@ return { Body = "EARTH", Geometry = { Type = "SimpleSphere", - Radius = { 6.371, 6 }, + Radius = 6.371E6, Segments = 100 }, Textures = { @@ -49,6 +49,7 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = {"planet_solarSystem", "planet_terrestrial"}, Transform = { Rotation = { Type = "SpiceRotation", @@ -78,9 +79,10 @@ return { -- EndTime = "2017 JAN 01 12:00:00.000", -- SampleInterval = 3600 Period = 365.242, - Resolution = 1000 + Resolution = 1000, + Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"} }, - GuiName = "/Solar/EarthTrail" + GuiName = "/Solar/EarthTrail", }, --[[ { @@ -88,7 +90,7 @@ return { Parent = "Earth", Renderable = { Type = "RenderablePlane", - Size = {3.0, 11.0}, + Size = 3.0E11, Origin = "Center", Billboard = true, Texture = "textures/marker.png", diff --git a/data/scene/fieldlines.scene b/data/scene/fieldlines.scene index 3cee4bf1e3..cf494fe43c 100644 --- a/data/scene/fieldlines.scene +++ b/data/scene/fieldlines.scene @@ -6,7 +6,7 @@ function preInitialization() critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") openspace.time.setTime("2015 JAN 01 12:00:00.000") diff --git a/data/scene/globebrowsing.scene b/data/scene/globebrowsing.scene index c03c92d1b7..23506f5df1 100644 --- a/data/scene/globebrowsing.scene +++ b/data/scene/globebrowsing.scene @@ -7,7 +7,7 @@ function preInitialization() ]]-- --openspace.time.setTime(openspace.time.currentWallTime()) - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") openspace.time.setTime(openspace.time.currentWallTime()) diff --git a/data/scene/juno.scene b/data/scene/juno.scene index f63276e744..403b508435 100755 --- a/data/scene/juno.scene +++ b/data/scene/juno.scene @@ -5,7 +5,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") openspace.time.setTime("2016-07-05T10:05:00.00") diff --git a/data/scene/jupiter/callisto/callisto.mod b/data/scene/jupiter/callisto/callisto.mod index 74c3360adf..aa6122bd47 100644 --- a/data/scene/jupiter/callisto/callisto.mod +++ b/data/scene/jupiter/callisto/callisto.mod @@ -9,7 +9,7 @@ return { Body = "CALLISTO", Geometry = { Type = "SimpleSphere", - Radius = { 2.631, 6}, + Radius = 2.631E6, Segments = 100 }, Textures = { diff --git a/data/scene/jupiter/europa/europa.mod b/data/scene/jupiter/europa/europa.mod index 54df372720..fea16b4627 100644 --- a/data/scene/jupiter/europa/europa.mod +++ b/data/scene/jupiter/europa/europa.mod @@ -9,7 +9,7 @@ return { Body = "EUROPA", Geometry = { Type = "SimpleSphere", - Radius = { 1.561, 6}, + Radius = 1.561E6, Segments = 100 }, Textures = { diff --git a/data/scene/jupiter/ganymede/ganymede.mod b/data/scene/jupiter/ganymede/ganymede.mod index c2c9fdca08..16aa1c175a 100644 --- a/data/scene/jupiter/ganymede/ganymede.mod +++ b/data/scene/jupiter/ganymede/ganymede.mod @@ -9,7 +9,7 @@ return { Body = "JUPITER BARYCENTER", Geometry = { Type = "SimpleSphere", - Radius = { 2.631, 6}, + Radius = 2.631E6, Segments = 100 }, Textures = { diff --git a/data/scene/jupiter/io/io.mod b/data/scene/jupiter/io/io.mod index 03d28e60d1..98e5e88e7f 100644 --- a/data/scene/jupiter/io/io.mod +++ b/data/scene/jupiter/io/io.mod @@ -9,7 +9,7 @@ return { Body = "IO", Geometry = { Type = "SimpleSphere", - Radius = { 1.8213, 6 }, + Radius = 1.8213E6, Segments = 100 }, Textures = { diff --git a/data/scene/jupiter/jupiter/jupiter.mod b/data/scene/jupiter/jupiter/jupiter.mod index 6302b66739..f9030b25f1 100644 --- a/data/scene/jupiter/jupiter/jupiter.mod +++ b/data/scene/jupiter/jupiter/jupiter.mod @@ -22,7 +22,7 @@ return { Body = "JUPITER BARYCENTER", Geometry = { Type = "SimpleSphere", - Radius = { 0.71492, 8 }, + Radius = 0.71492E8, Segments = 200 }, Textures = { @@ -35,6 +35,7 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = "planet_solarSystem", Transform = { Translation = { Type = "StaticTranslation", @@ -64,7 +65,8 @@ return { }, Color = { 0.8, 0.7, 0.7 }, Period = 4330.595, - Resolution = 1000 - } + Resolution = 1000, + }, + Tag = "planetTrail_solarSystem" } } diff --git a/data/scene/lodglobes/earth/earth.mod b/data/scene/lodglobes/earth/earth.mod index 1df4498c85..5660cff113 100644 --- a/data/scene/lodglobes/earth/earth.mod +++ b/data/scene/lodglobes/earth/earth.mod @@ -56,13 +56,14 @@ return { SegmentsPerPatch = 64, Layers = { ColorLayers = { + { Name = "ESRI VIIRS Combo", Type = "ByLevel", LevelTileProviders = { { - MaxLevel = 7, - TileProvider = { FilePath = "map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml", }, + MaxLevel = 3, + TileProvider = { Type = "Temporal", FilePath = "map_service_configs/GIBS/Temporal_VIIRS_SNPP_CorrectedReflectance_TrueColor.xml", }, }, { MaxLevel = 22, @@ -71,6 +72,10 @@ return { }, Enabled = true, }, + { + Name = "ESRI Imagery World", + FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms" + }, { Type = "Temporal", Name = "Temporal VIIRS SNPP", @@ -81,6 +86,11 @@ return { Name = "Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature", FilePath = "map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml", }, + { + Type = "Temporal", + Name = "Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration", + FilePath = "map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml", + }, -- { -- Type = "SingleImage", -- Name = "Debug Tiles", @@ -104,6 +114,11 @@ return { FilePath = "map_service_configs/GIBS/VIIRS_CityLights_2012.xml", Enabled = true, }, + { + Type = "Temporal", + Name = "Temporal Earth at Night", + FilePath = "map_service_configs/GIBS/Temporal_VIIRS_SNPP_DayNightBand_ENCC.xml" + } }, WaterMasks = { { @@ -159,7 +174,7 @@ return { Name = "Terrain tileset", FilePath = "map_service_configs/ESRI/TERRAIN.wms", Enabled = true, - MinimumPixelSize = 64, + TilePixelSize = 64, DoPreProcessing = true, }, }, diff --git a/data/scene/lodglobes/earth/map_service_configs/ESRI/ESRI_Imagery_World_2D.wms b/data/scene/lodglobes/earth/map_service_configs/ESRI/ESRI_Imagery_World_2D.wms index dfaa82712b..d7d7263f5c 100644 --- a/data/scene/lodglobes/earth/map_service_configs/ESRI/ESRI_Imagery_World_2D.wms +++ b/data/scene/lodglobes/earth/map_service_configs/ESRI/ESRI_Imagery_World_2D.wms @@ -14,8 +14,8 @@ 3 5 - ./GDAL_Cache_ESRI_Imagery_World_2d - 10 + ./GDAL_Cache/ESRI_Imagery_World_2d + 4 .jpg false diff --git a/data/scene/lodglobes/earth/map_service_configs/ESRI/TERRAIN.wms b/data/scene/lodglobes/earth/map_service_configs/ESRI/TERRAIN.wms index 86f039232e..3937681945 100644 --- a/data/scene/lodglobes/earth/map_service_configs/ESRI/TERRAIN.wms +++ b/data/scene/lodglobes/earth/map_service_configs/ESRI/TERRAIN.wms @@ -1,14 +1,21 @@ - - http://198.102.45.23/arcgis/rest/services/worldelevation3d/terrain3d? - GCS_Elevation - - - -180.0 - 90.0 - 180.0 - -90.0 - bottom - - 2 + + http://198.102.45.23/arcgis/rest/services/worldelevation3d/terrain3d? + GCS_Elevation + + + -180.0 + 90.0 + 180.0 + -90.0 + bottom + + 2 + 5 + + ./GDAL_Cache/TERRAIN + 4 + .jpg + + false diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Coastlines.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Coastlines.xml index c9578ad205..830e32da8a 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Coastlines.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Coastlines.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/Coastlines/default/2013-08-21/EPSG4326_250m/${z}/${y}/${x}.png + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/Coastlines/default/2013-08-21/250m/${z}/${y}/${x}.png -180.0 @@ -16,4 +16,14 @@ 512 512 4 - \ No newline at end of file + true + 400 + true + 5 + + ./GDAL_Cache/Coastlines + 4 + .png + + false + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/GIBS_Aqua_MODIS_true.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/GIBS_Aqua_MODIS_true.xml index 8d3196deff..19bbcdb9c5 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/GIBS_Aqua_MODIS_true.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/GIBS_Aqua_MODIS_true.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/MODIS_Aqua_CorrectedReflectance_TrueColor/default/2013-08-21/EPSG4326_250m/${z}/${y}/${x}.jpg + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/MODIS_Aqua_CorrectedReflectance_TrueColor/default/2013-08-21/250m/${z}/${y}/${x}.jpg -180.0 @@ -16,4 +16,14 @@ 512 512 3 - \ No newline at end of file + 5 + + ./GDAL_Cache/GIBS_Aqua_MODIS_true + 4 + .jpg + + false + true + 400 + true + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_Brightness_Temp_Band31_Day.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_Brightness_Temp_Band31_Day.xml index c63f815618..46a1189c43 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_Brightness_Temp_Band31_Day.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_Brightness_Temp_Band31_Day.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/MODIS_Terra_Brightness_Temp_Band31_Day/default/2013-08-21/EPSG4326_1km/${z}/${y}/${x}.png + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/MODIS_Terra_Brightness_Temp_Band31_Day/default/2013-08-21/1km/${z}/${y}/${x}.png -180.0 @@ -16,4 +16,14 @@ 512 512 4 - \ No newline at end of file + 5 + + ./GDAL_Cache/MODIS_Terra_Brightness_Temp_Band31_Day + 4 + .png + + false + true + 400 + true + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor.xml index faf07ccced..a0d82a02b0 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/MODIS_Terra_CorrectedReflectance_TrueColor/default/2016-05-16/EPSG4326_250m/${z}/${y}/${x}.jpg + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/MODIS_Terra_CorrectedReflectance_TrueColor/default/2013-08-21/250m/${z}/${y}/${x}.jpg -180.0 @@ -16,4 +16,14 @@ 512 512 3 - \ No newline at end of file + 5 + + ./GDAL_Cache/MODIS_Terra_CorrectedReflectance_TrueColor + 4 + .jpg + + false + true + 400 + true + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor_temporal.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor_temporal.xml deleted file mode 100644 index 36013e4a3a..0000000000 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Terra_CorrectedReflectance_TrueColor_temporal.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - http://map1.vis.earthdata.nasa.gov/wmts-geo/MODIS_Terra_CorrectedReflectance_TrueColor/default/${t}/EPSG4326_250m/${z}/${y}/${x}.jpg - - - -180.0 - 90 - 396.0 - -198 - 8 - 2 - 1 - top - - EPSG:4326 - 512 - 512 - 3 - \ No newline at end of file diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Water_Mask.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Water_Mask.xml index 0f9c24b540..b3b90a2f48 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Water_Mask.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/MODIS_Water_Mask.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/MODIS_Water_Mask/default/2013-08-21/EPSG4326_250m/${z}/${y}/${x}.png + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/MODIS_Water_Mask/default/2013-08-21/250m/${z}/${y}/${x}.png -180.0 @@ -16,4 +16,14 @@ 512 512 4 - \ No newline at end of file + 5 + + ./GDAL_Cache/MODIS_Water_Mask + 4 + .png + + false + true + 400 + true + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Features.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Features.xml index 6cc0348f36..7cb0e23db1 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Features.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Features.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/Reference_Features/default/2013-08-21/EPSG4326_250m/${z}/${y}/${x}.png + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/Reference_Features/default/2013-08-21/250m/${z}/${y}/${x}.png -180.0 @@ -16,4 +16,14 @@ 512 512 4 - \ No newline at end of file + 5 + + ./GDAL_Cache/Reference_Features + 4 + .png + + false + true + 400 + true + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Labels.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Labels.xml index 0a13e11f23..2731893a09 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Labels.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Reference_Labels.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/Reference_Labels/default/2013-08-21/EPSG4326_250m/${z}/${y}/${x}.png + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/Reference_Labels/default/2013-08-21/250m/${z}/${y}/${x}.png -180.0 @@ -16,4 +16,14 @@ 512 512 4 - \ No newline at end of file + 5 + + ./GDAL_Cache/Reference_Labels + 4 + .png + + false + true + 400 + true + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/TERRA_CR_B143_2016-04-12.wms b/data/scene/lodglobes/earth/map_service_configs/GIBS/TERRA_CR_B143_2016-04-12.wms index 974c7da85f..ea8427a9a4 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/TERRA_CR_B143_2016-04-12.wms +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/TERRA_CR_B143_2016-04-12.wms @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/twms-geo/twms.cgi? + https://gibs.earthdata.nasa.gov/twms/twms.cgi? MODIS TERRA tileset 2016-04-12 diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml new file mode 100644 index 0000000000..c838cf1667 --- /dev/null +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml @@ -0,0 +1,28 @@ + + 2012-05-08 + + 1d + YYYY-MM-DD + + + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/AMSR2_Sea_Ice_Concentration_12km/default/${OpenSpaceTimeId}/2km/${z}/${y}/${x}.png + + + -180.0 + 90 + 396.0 + -198 + 8 + 2 + 1 + top + + EPSG:4326 + 512 + 512 + 3 + true + 400 + true + + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_Aqua_Orbit_Asc.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_Aqua_Orbit_Asc.xml index e2253fabc9..a0c7ed6f8f 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_Aqua_Orbit_Asc.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_Aqua_Orbit_Asc.xml @@ -6,7 +6,7 @@ 1.1.1 - http://map2.vis.earthdata.nasa.gov/wms/wms.php?TIME=${OpenSpaceTimeId} + https://gibs.earthdata.nasa.gov/wms/wms.php?TIME=${OpenSpaceTimeId} EPSG:4326 image/png TRUE @@ -26,11 +26,8 @@ 512 512 3 + true + 400 + true - diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml index 2a4f525511..d28ad2d84f 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml @@ -5,7 +5,7 @@ YYYY-MM-DD - http://map1.vis.earthdata.nasa.gov/wmts-geo/GHRSST_L4_MUR_Sea_Surface_Temperature/default/${OpenSpaceTimeId}/EPSG4326_1km/${z}/${y}/${x}.png + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/GHRSST_L4_MUR_Sea_Surface_Temperature/default/${OpenSpaceTimeId}/250m/${z}/${y}/${x}.png -180.0 @@ -21,5 +21,8 @@ 512 512 4 + true + 400 + true - \ No newline at end of file + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_MODIS_Aqua_CorrectedReflectance_TrueColor.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_MODIS_Aqua_CorrectedReflectance_TrueColor.xml index d09c0e9615..1637409c25 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_MODIS_Aqua_CorrectedReflectance_TrueColor.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_MODIS_Aqua_CorrectedReflectance_TrueColor.xml @@ -5,7 +5,7 @@ YYYY-MM-DD - http://map1.vis.earthdata.nasa.gov/wmts-geo/MODIS_Aqua_CorrectedReflectance_TrueColor/default/${OpenSpaceTimeId}/EPSG4326_250m/${z}/${y}/${x}.jpg + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/MODIS_Aqua_CorrectedReflectance_TrueColor/default/${OpenSpaceTimeId}/250m/${z}/${y}/${x}.jpg -180.0 @@ -21,5 +21,8 @@ 512 512 3 + true + 400 + true - \ No newline at end of file + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_MODIS_Terra_CorrectedReflectance_TrueColor.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_MODIS_Terra_CorrectedReflectance_TrueColor.xml new file mode 100644 index 0000000000..fb8ffbf297 --- /dev/null +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_MODIS_Terra_CorrectedReflectance_TrueColor.xml @@ -0,0 +1,28 @@ + + 2012-05-08 + + 1d + YYYY-MM-DD + + + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/MODIS_Terra_CorrectedReflectance_TrueColor/default/${OpenSpaceTimeId}/250m/${z}/${y}/${x}.jpg + + + -180.0 + 90 + 396.0 + -198 + 8 + 2 + 1 + top + + EPSG:4326 + 512 + 512 + 3 + true + 400 + true + + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_VIIRS_SNPP_CorrectedReflectance_TrueColor.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_VIIRS_SNPP_CorrectedReflectance_TrueColor.xml index 311f2ec097..c656c8866e 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_VIIRS_SNPP_CorrectedReflectance_TrueColor.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_VIIRS_SNPP_CorrectedReflectance_TrueColor.xml @@ -5,7 +5,7 @@ YYYY-MM-DD - http://map1.vis.earthdata.nasa.gov/wmts-geo/VIIRS_SNPP_CorrectedReflectance_TrueColor/default/${OpenSpaceTimeId}/EPSG4326_250m/${z}/${y}/${x}.jpg + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/VIIRS_SNPP_CorrectedReflectance_TrueColor/default/${OpenSpaceTimeId}/250m/${z}/${y}/${x}.jpg -180.0 @@ -21,5 +21,8 @@ 512 512 3 + true + 400 + true - \ No newline at end of file + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_VIIRS_SNPP_DayNightBand_ENCC.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_VIIRS_SNPP_DayNightBand_ENCC.xml new file mode 100644 index 0000000000..d2e093a97c --- /dev/null +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/Temporal_VIIRS_SNPP_DayNightBand_ENCC.xml @@ -0,0 +1,28 @@ + + 2012-05-08 + + 1d + YYYY-MM-DD + + + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/VIIRS_SNPP_DayNightBand_ENCC/default/${OpenSpaceTimeId}/500m/${z}/${y}/${x}.png + + + -180.0 + 90 + 396.0 + -198 + 8 + 2 + 1 + top + + EPSG:4326 + 512 + 512 + 3 + true + 400 + true + + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_CityLights_2012.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_CityLights_2012.xml index cf0c6a1866..91645c3d59 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_CityLights_2012.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_CityLights_2012.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/VIIRS_CityLights_2012/default/2012-01-01/EPSG4326_500m/${z}/${y}/${x}.jpg + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/VIIRS_CityLights_2012/default/2013-08-21/500m/${z}/${y}/${x}.jpg -180.0 @@ -16,4 +16,14 @@ 512 512 4 - \ No newline at end of file + 5 + + ./GDAL_Cache/VIIRS_CityLights_2012 + 4 + .jpg + + false + true + 400 + true + diff --git a/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml b/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml index 28499cabbd..b6ffc234fa 100644 --- a/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml +++ b/data/scene/lodglobes/earth/map_service_configs/GIBS/VIIRS_SNPP_CorrectedReflectance_TrueColor.xml @@ -1,6 +1,6 @@ - http://map1.vis.earthdata.nasa.gov/wmts-geo/VIIRS_SNPP_CorrectedReflectance_TrueColor/default/2016-10-01/EPSG4326_250m/${z}/${y}/${x}.jpg + https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/VIIRS_SNPP_CorrectedReflectance_TrueColor/default/2016-08-21/250m/${z}/${y}/${x}.jpg -180.0 @@ -16,4 +16,14 @@ 512 512 3 + 5 + + ./GDAL_Cache/VIIRS_SNPP_CorrectedReflectance_TrueColor + 4 + .jpg + + false + true + 400 + true \ No newline at end of file diff --git a/data/scene/lodglobes/jupiter/callisto/callisto.mod b/data/scene/lodglobes/jupiter/callisto/callisto.mod index 8aa1bda8f0..c86a629158 100644 --- a/data/scene/lodglobes/jupiter/callisto/callisto.mod +++ b/data/scene/lodglobes/jupiter/callisto/callisto.mod @@ -32,7 +32,7 @@ return { Name = "Callisto Texture", FilePath = "textures/callisto.jpg", Enabled = true, - MinimumPixelSize = 112, + TilePixelSize = 112, }, }, GrayScaleLayers = { }, diff --git a/data/scene/lodglobes/jupiter/europa/europa.mod b/data/scene/lodglobes/jupiter/europa/europa.mod index cd32cdd332..b3f4c1a8df 100644 --- a/data/scene/lodglobes/jupiter/europa/europa.mod +++ b/data/scene/lodglobes/jupiter/europa/europa.mod @@ -32,7 +32,7 @@ return { Name = "Europa Texture", FilePath = "textures/europa.jpg", Enabled = true, - MinimumPixelSize = 256, + TilePixelSize = 256, }, }, GrayScaleLayers = { }, diff --git a/data/scene/lodglobes/jupiter/ganymede/ganymede.mod b/data/scene/lodglobes/jupiter/ganymede/ganymede.mod index be1bb1274c..0099a57786 100644 --- a/data/scene/lodglobes/jupiter/ganymede/ganymede.mod +++ b/data/scene/lodglobes/jupiter/ganymede/ganymede.mod @@ -32,7 +32,7 @@ return { Name = "Ganymede Texture", FilePath = "textures/ganymede.jpg", Enabled = true, - MinimumPixelSize = 112, + TilePixelSize = 112, }, }, GrayScaleLayers = { }, diff --git a/data/scene/lodglobes/mars/map_service_configs/Utah/Mola_Elevation.xml b/data/scene/lodglobes/mars/map_service_configs/Utah/Mola_Elevation.xml index a0294879cf..79332d59c9 100644 --- a/data/scene/lodglobes/mars/map_service_configs/Utah/Mola_Elevation.xml +++ b/data/scene/lodglobes/mars/map_service_configs/Utah/Mola_Elevation.xml @@ -12,6 +12,7 @@ 6 top + Int16 GEOGCS["GCS_Mars_2000_Sphere",DATUM["D_Mars_2000_Sphere",SPHEROID["Mars_2000_Sphere_IAU_IAG",3396190.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]] 360 360 diff --git a/data/scene/lodglobes/mars/mars.mod b/data/scene/lodglobes/mars/mars.mod index 040fc570e8..375954c010 100644 --- a/data/scene/lodglobes/mars/mars.mod +++ b/data/scene/lodglobes/mars/mars.mod @@ -32,20 +32,36 @@ return { Type = "RenderableGlobe", Radii = marsEllipsoid, CameraMinHeight = 10, + SegmentsPerPatch = 90, + -- Allows camera to go down 10000 meters below the reference ellipsoid InteractionDepthBelowEllipsoid = 10000, -- Useful when having negative height map values - SegmentsPerPatch = 64, Layers = { ColorLayers = { + { + Name = "Viking combo", + Type = "ByLevel", + LevelTileProviders = { + { + MaxLevel = 3, + TileProvider = { FilePath = "textures/mars.jpg", }, + }, + { + MaxLevel = 22, + TileProvider = { FilePath = "map_service_configs/MARS_Viking_MDIM21.xml" }, + }, + }, + Enabled = true, + }, -- { -- Type = "SingleImage", -- Name = "Debug Tiles", -- FilePath = "../../debugglobe/textures/test_tile.png", -- }, - { - Name = "MARS_Viking", - FilePath = "map_service_configs/MARS_Viking_MDIM21.xml", - Enabled = true, - }, + --{ + -- Name = "MARS_Viking", + -- FilePath = "map_service_configs/MARS_Viking_MDIM21.xml", + -- Enabled = true, + --}, { Name = "MOLA Pseudo Color", FilePath = "map_service_configs/Utah/MolaPseudoColor.xml", @@ -66,16 +82,22 @@ return { { Name = "CTX Mosaic [Europe]", FilePath = "map_service_configs/CTX_Mosaic.xml", - Enabled = true, - }, { + --Enabled = true, + }, + { Name = "CTX Mosaic [Utah]", FilePath = "map_service_configs/Utah/CTX_Mosaic.xml", }, + { + Name = "West Candor Chasma", + FilePath = "map_datasets/CTX/West_Candor_Chasma_longlat_global.vrt", + --Enabled = true, + }, { Name = "Layered Rock Outcrops in Southwest Candor Chasma", FilePath = "map_datasets/HiRISE/Layered_Rock_Outcrops_in_Southwest_Candor_Chasma_Texture.vrt", }, - { + --[[{ Name = "Themis IR Day", FilePath = "map_service_configs/Utah/ThemisIRDay.xml", }, @@ -83,12 +105,7 @@ return { Name = "Themis IR Night", FilePath = "map_service_configs/Utah/ThemisIRNight.xml", }, - --[[ - { - Name = "West Candor Chasma", - FilePath = "map_datasets/CTX/West_Candor_Chasma_longlat_global.vrt", - --Enabled = true, - }, + { Name = "MER_Meridianni_Endeavor_Basemap_25cm", FilePath = "map_datasets/Basemap/MER_Meridianni_Endeavor_Basemap_25cm.vrt", @@ -115,41 +132,49 @@ return { }, HeightLayers = { { - Name = "Mola Elevation", - FilePath = "map_service_configs/Utah/Mola_Elevation.xml", + Name = "Mola Elevation [Europe]", + FilePath = "map_service_configs/Mola_Elevation.xml", Enabled = true, - MinimumPixelSize = 90, + TilePixelSize = 90, + DoPreProcessing = true, + }, + --[[ + { + Name = "Mola Elevation [Utah]", + FilePath = "map_service_configs/Utah/Mola_Elevation.xml", + Enabled = false, + TilePixelSize = 90, DoPreProcessing = true, }, { Name = "Mola Elevation CTX", FilePath = "map_service_configs/Utah/MolaCTX_Elevation.xml", -- Enabled = true, - MinimumPixelSize = 90, + TilePixelSize = 90, DoPreProcessing = true, - }, + },]] { - Name = "Layered Rock Outcrops in Southwest Candor Chasma", - FilePath = "map_datasets/HiRISE/Layered_Rock_Outcrops_in_Southwest_Candor_Chasma_Heightmap.vrt", - MinimumPixelSize = 90, - DoPreProcessing = true, - }, - --[[ - { - Name = "Mola Elevation", - FilePath = "map_service_configs/Mars_MGS_MOLA_DEM.xml", - Enabled = true, - MinimumPixelSize = 64, - DoPreProcessing = true, - }, ---]] ---[[ { Name = "West Candor Chasma", FilePath = "map_datasets/CTX/West_Candor_Chasma_DEM_longlat_global.vrt", --Enabled = true, MinimumPixelSize = 90, DoPreProcessing = true, }, + { + Name = "Layered Rock Outcrops in Southwest Candor Chasma", + FilePath = "map_datasets/HiRISE/Layered_Rock_Outcrops_in_Southwest_Candor_Chasma_Heightmap.vrt", + TilePixelSize = 90, + DoPreProcessing = true, + }, + --[[ + { + Name = "West Candor Chasma", + FilePath = "map_datasets/CTX/West_Candor_Chasma_DEM_longlat_global.vrt", + --Enabled = true, + TilePixelSize = 90, + DoPreProcessing = true, + },]] + --[[ { Name = "Part of Area Traversed by the Mars Exploration Rover", FilePath = "map_datasets/HiRISE/Part_of_Area_Traversed_by_the_Mars_Exploration_Rover_Heightmap.vrt", diff --git a/data/scene/lodglobes/mercury/lodmercury.mod b/data/scene/lodglobes/mercury/lodmercury.mod index 8e211d3c5e..17f7383c80 100644 --- a/data/scene/lodglobes/mercury/lodmercury.mod +++ b/data/scene/lodglobes/mercury/lodmercury.mod @@ -42,7 +42,7 @@ return { Name = "Simple Texture", FilePath = "textures/mercury.jpg", Enabled = true, - MinimumPixelSize = 256, + TilePixelSize = 256, }, { Name = "Messenger_Mosaic", diff --git a/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml b/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml index 5ba619a141..6eae17b3cf 100644 --- a/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml +++ b/data/scene/lodglobes/moon/map_service_configs/OnMoonColor.xml @@ -62,4 +62,10 @@ 512 512 + + + ./GDAL_Cache/OnMoonColor + 4 + .png + \ No newline at end of file diff --git a/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml b/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml index 9fe0516d15..cdfd4114e1 100644 --- a/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml +++ b/data/scene/lodglobes/moon/map_service_configs/OnMoonHeight.xml @@ -16,4 +16,9 @@ 1 top + + ./GDAL_Cache/OnMoonHeight + 4 + .png + \ No newline at end of file diff --git a/data/scene/lodglobes/moon/map_service_configs/Utah/LolaDem.wms b/data/scene/lodglobes/moon/map_service_configs/Utah/LolaDem.wms index 1ef0f4be0e..9465278db8 100644 --- a/data/scene/lodglobes/moon/map_service_configs/Utah/LolaDem.wms +++ b/data/scene/lodglobes/moon/map_service_configs/Utah/LolaDem.wms @@ -12,6 +12,7 @@ 7 top + Int16 GEOGCS["GCS_Moon_2000",DATUM["D_Moon_2000",SPHEROID["Moon_2000_IAU_IAG",1737400.0,0.0]],PRIMEM["Reference_Meridian",0.0],UNIT["Degree",0.0174532925199433]] 360 360 diff --git a/data/scene/lodglobes/moon/moon.mod b/data/scene/lodglobes/moon/moon.mod index 54c525ea6d..1247ae7187 100644 --- a/data/scene/lodglobes/moon/moon.mod +++ b/data/scene/lodglobes/moon/moon.mod @@ -20,8 +20,9 @@ return { Type = "RenderableGlobe", Radii = {1738140, 1738140, 1735970}, -- Moons's radius CameraMinHeight = 300, - InteractionDepthBelowEllipsoid = 5000, -- Useful when having negative height map values SegmentsPerPatch = 64, + -- Allows camera to go down 10000 meters below the reference ellipsoid + InteractionDepthBelowEllipsoid = 10000, -- Useful when having negative height map values Layers = { ColorLayers = { @@ -63,10 +64,13 @@ return { FilePath = "map_service_configs/OnMoonHeight.xml", Enabled = true, DoPreProcessing = true, + TileSize = 64, }, { Name = "LolaDem", - FilePath = "map_service_configs/Utah/LolaDem.wms" + FilePath = "map_service_configs/Utah/LolaDem.wms", + DoPreProcessing = true, + TileSize = 64, } }, }, diff --git a/data/scene/lodglobes/neptune/neptune.mod b/data/scene/lodglobes/neptune/neptune.mod index 9f3c9f854f..cfb74029b9 100644 --- a/data/scene/lodglobes/neptune/neptune.mod +++ b/data/scene/lodglobes/neptune/neptune.mod @@ -40,7 +40,7 @@ return { Name = "Texture", FilePath = "textures/neptune.jpg", Enabled = true, - MinimumPixelSize = 256, + TilePixelSize = 256, }, }, GrayScaleLayers = { }, diff --git a/data/scene/lodglobes/saturn/saturn.mod b/data/scene/lodglobes/saturn/saturn.mod index 6ce3287d0e..da471b0979 100644 --- a/data/scene/lodglobes/saturn/saturn.mod +++ b/data/scene/lodglobes/saturn/saturn.mod @@ -40,7 +40,7 @@ return { Name = "Saturn Texture", FilePath = "textures/saturn.jpg", Enabled = true, - MinimumPixelSize = 256, + TilePixelSize = 256, }, }, GrayScaleLayers = { }, diff --git a/data/scene/lodglobes/uranus/uranus.mod b/data/scene/lodglobes/uranus/uranus.mod index 9825a16459..06b2160647 100644 --- a/data/scene/lodglobes/uranus/uranus.mod +++ b/data/scene/lodglobes/uranus/uranus.mod @@ -40,7 +40,7 @@ return { Name = "Texture", FilePath = "textures/uranus.jpg", Enabled = true, - MinimumPixelSize = 256, + TilePixelSize = 256, }, }, GrayScaleLayers = { }, diff --git a/data/scene/lodglobes/venus/venus.mod b/data/scene/lodglobes/venus/venus.mod index ba6e050a33..2ac91197ed 100644 --- a/data/scene/lodglobes/venus/venus.mod +++ b/data/scene/lodglobes/venus/venus.mod @@ -45,7 +45,7 @@ return { Name = "Venus Texture", FilePath = "textures/venus.jpg", Enabled = true, - MinimumPixelSize = 256, + TilePixelSize = 256, }, }, GrayScaleLayers = { }, diff --git a/data/scene/mars/mars.mod b/data/scene/mars/mars.mod index 54e33cbd6c..301f510e5f 100644 --- a/data/scene/mars/mars.mod +++ b/data/scene/mars/mars.mod @@ -22,7 +22,7 @@ return { Body = "MARS BARYCENTER", Geometry = { Type = "SimpleSphere", - Radius = { 6.390, 6 }, + Radius = 6.390E6, Segments = 100 }, Textures = { @@ -35,12 +35,17 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = {"planet_solarSystem", "planet_terrestrial"}, Transform = { Rotation = { Type = "SpiceRotation", SourceFrame = "IAU_MARS", DestinationFrame = "GALACTIC", }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, } }, -- MarsTrail module @@ -56,7 +61,8 @@ return { }, Color = { 0.814, 0.305, 0.220 }, Period = 686.973, - Resolution = 1000 + Resolution = 1000, + Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"} } } } diff --git a/data/scene/mercury/mercury.mod b/data/scene/mercury/mercury.mod index 75bf33560e..61d5c6ff8b 100644 --- a/data/scene/mercury/mercury.mod +++ b/data/scene/mercury/mercury.mod @@ -22,7 +22,7 @@ return { Body = "MERCURY", Geometry = { Type = "SimpleSphere", - Radius = { 2.440, 6 }, + Radius = 2.4397E6, Segments = 100 }, Textures = { @@ -35,6 +35,7 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = {"planet_solarSystem", "planet_terrestrial"}, Transform = { Rotation = { Type = "SpiceRotation", @@ -60,7 +61,8 @@ return { }, Color = {0.6, 0.5, 0.5 }, Period = 87.968, - Resolution = 100 + Resolution = 100, + Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"} } } } diff --git a/data/scene/missions/dawn/ceres/ceres.mod b/data/scene/missions/dawn/ceres/ceres.mod index ff9c413a2a..0c29ae852b 100644 --- a/data/scene/missions/dawn/ceres/ceres.mod +++ b/data/scene/missions/dawn/ceres/ceres.mod @@ -10,7 +10,7 @@ return { Body = "CERES", Geometry = { Type = "SimpleSphere", - Radius = { 6.390, 5 }, + Radius = 6.390E5, Segments = 100 }, Textures = { diff --git a/data/scene/missions/juno/juno/juno.mod b/data/scene/missions/juno/juno/juno.mod index 12c2d45131..c9e4cc56df 100644 --- a/data/scene/missions/juno/juno/juno.mod +++ b/data/scene/missions/juno/juno/juno.mod @@ -126,19 +126,16 @@ return { Name = "JunoTrail", Parent = "JupiterBarycenter", Renderable = { - Type = "RenderableTrail", - Body = "JUNO", - Frame = "GALACTIC", - Observer = "JUPITER BARYCENTER", - RGB = { 0.70,0.50,0.20 }, - TropicalOrbitPeriod = 394250.0, - EarthOrbitRatio = 4.5, - DayLength = 9.9259, - TimeStamps = false, - Textures = { - Type = "simple", - Color = "textures/glare_blue.png", - }, + Type = "RenderableTrailTrajectory", + Translation = { + Type = "SpiceTranslation", + Body = "JUNO", + Observer = "JUPITER BARYCENTER" + }, + Color = { 0.70, 0.50, 0.20 }, + StartTime = "2016 JUN 28", + EndTime = "2016 APR 01", + SampleInterval = 3600 }, }, } diff --git a/data/scene/missions/newhorizons/jupiter/callisto/callisto.mod b/data/scene/missions/newhorizons/jupiter/callisto/callisto.mod index acf03fd873..c99c354d59 100644 --- a/data/scene/missions/newhorizons/jupiter/callisto/callisto.mod +++ b/data/scene/missions/newhorizons/jupiter/callisto/callisto.mod @@ -9,7 +9,7 @@ return { Body = "CALLISTO", Geometry = { Type = "SimpleSphere", - Radius = { 1.8213, 6 }, + Radius = 1.8213E6, Segments = 100 }, Textures = { @@ -58,7 +58,7 @@ return { Parent = "Callisto", Renderable = { Type = "RenderablePlane", - Size = {1.0, 7.4}, + Size = 10^7.4, Origin = "Center", Billboard = true, Texture = "textures/Callisto-Text.png", diff --git a/data/scene/missions/newhorizons/jupiter/europa/europa.mod b/data/scene/missions/newhorizons/jupiter/europa/europa.mod index 1bec7e5c9b..21e07a2703 100644 --- a/data/scene/missions/newhorizons/jupiter/europa/europa.mod +++ b/data/scene/missions/newhorizons/jupiter/europa/europa.mod @@ -9,7 +9,7 @@ return { Body = "EUROPA", Geometry = { Type = "SimpleSphere", - Radius = { 1.8213, 6 }, + Radius = 1.8213E6, Segments = 100 }, Textures = { @@ -58,7 +58,7 @@ return { Parent = "Europa", Renderable = { Type = "RenderablePlane", - Size = {1.0, 7.4}, + Size = 10^7.4, Origin = "Center", Billboard = true, Texture = "textures/Europa-Text.png", diff --git a/data/scene/missions/newhorizons/jupiter/ganymede/ganymede.mod b/data/scene/missions/newhorizons/jupiter/ganymede/ganymede.mod index 401babcca6..5fa473d332 100644 --- a/data/scene/missions/newhorizons/jupiter/ganymede/ganymede.mod +++ b/data/scene/missions/newhorizons/jupiter/ganymede/ganymede.mod @@ -9,7 +9,7 @@ return { Body = "GANYMEDE", Geometry = { Type = "SimpleSphere", - Radius = { 1.8213, 6 }, + Radius = 1.8213E6, Segments = 100 }, Textures = { @@ -58,7 +58,7 @@ return { Parent = "Ganymede", Renderable = { Type = "RenderablePlane", - Size = {1.0, 7.4}, + Size = 10^7.4, Origin = "Center", Billboard = true, Texture = "textures/Ganymede-Text.png", diff --git a/data/scene/missions/newhorizons/jupiter/io/io.mod b/data/scene/missions/newhorizons/jupiter/io/io.mod index c41b45f29b..d4e5260cbd 100644 --- a/data/scene/missions/newhorizons/jupiter/io/io.mod +++ b/data/scene/missions/newhorizons/jupiter/io/io.mod @@ -9,7 +9,7 @@ return { Body = "IO", Geometry = { Type = "SimpleSphere", - Radius = { 1.8213, 6 }, + Radius = 1.8213E6, Segments = 100 }, Textures = { diff --git a/data/scene/missions/newhorizons/jupiter/jupiter/jupiter.mod b/data/scene/missions/newhorizons/jupiter/jupiter/jupiter.mod index 079357b2ad..17f3a6afea 100644 --- a/data/scene/missions/newhorizons/jupiter/jupiter/jupiter.mod +++ b/data/scene/missions/newhorizons/jupiter/jupiter/jupiter.mod @@ -22,7 +22,7 @@ return { Body = "JUPITER", Geometry = { Type = "SimpleSphere", - Radius = { 0.71492, 8 }, + Radius = 0.71492E8, Segments = 200, }, Textures = { @@ -101,7 +101,7 @@ return { Parent = "JupiterProjection", Renderable = { Type = "RenderablePlane", - Size = {1.0, 7.5}, + Size = 10^7.5, Origin = "Center", Billboard = true, Texture = "textures/Jupiter-text.png", diff --git a/data/scene/missions/newhorizons/newhorizonsfov/newhorizonsfov.mod b/data/scene/missions/newhorizons/newhorizonsfov/newhorizonsfov.mod index 7fdccdf6cc..7ece77d4e9 100644 --- a/data/scene/missions/newhorizons/newhorizonsfov/newhorizonsfov.mod +++ b/data/scene/missions/newhorizons/newhorizonsfov/newhorizonsfov.mod @@ -295,9 +295,9 @@ return { Type = "RenderableCrawlingLine", Source = "NH_REX", Target = "EARTH", - -- Body = "NEW HORIZONS", + -- Body = "NEW HORIZONS", Frame = "GALACTIC", - RGB = { 1.0, 0.7, 0.0 }, + Color = { 1.0, 0.7, 0.0 }, Instrument = "NH_REX" }, } diff --git a/data/scene/missions/newhorizons/pluto/charon/charon.mod b/data/scene/missions/newhorizons/pluto/charon/charon.mod index 4cfff1d131..7cc7544f84 100644 --- a/data/scene/missions/newhorizons/pluto/charon/charon.mod +++ b/data/scene/missions/newhorizons/pluto/charon/charon.mod @@ -24,7 +24,7 @@ return { Type = "RenderablePlanetProjection", Geometry = { Type = "SimpleSphere", - Radius = { 6.035 , 5 }, + Radius = 6.035E5, Segments = 100 }, Textures = { @@ -72,7 +72,7 @@ return { Parent = "Charon", Renderable = { Type = "RenderablePlane", - Size = {1.0, 6.3}, + Size = 10^6.3, Origin = "Center", Billboard = true, Texture = "textures/Charon-Text.png", diff --git a/data/scene/missions/newhorizons/pluto/hydra/hydra.mod b/data/scene/missions/newhorizons/pluto/hydra/hydra.mod index 8dcf6d2d0f..dbffd9a8a2 100644 --- a/data/scene/missions/newhorizons/pluto/hydra/hydra.mod +++ b/data/scene/missions/newhorizons/pluto/hydra/hydra.mod @@ -46,7 +46,7 @@ return { Parent = "Hydra", Renderable = { Type = "RenderablePlane", - Size = {1.0, 6.3}, + Size = 10.0^6.3, Origin = "Center", Billboard = true, Texture = "textures/Hydra-Text.png" diff --git a/data/scene/missions/newhorizons/pluto/kerberos/kerberos.mod b/data/scene/missions/newhorizons/pluto/kerberos/kerberos.mod index 595baf13e8..5710783747 100644 --- a/data/scene/missions/newhorizons/pluto/kerberos/kerberos.mod +++ b/data/scene/missions/newhorizons/pluto/kerberos/kerberos.mod @@ -46,7 +46,7 @@ return { Parent = "Kerberos", Renderable = { Type = "RenderablePlane", - Size = {1.0, 6.3}, + Size = 10^6.3, Origin = "Center", Billboard = true, Texture = "textures/Kerberos-Text.png" diff --git a/data/scene/missions/newhorizons/pluto/nix/nix.mod b/data/scene/missions/newhorizons/pluto/nix/nix.mod index da05401b4e..8a4373431c 100644 --- a/data/scene/missions/newhorizons/pluto/nix/nix.mod +++ b/data/scene/missions/newhorizons/pluto/nix/nix.mod @@ -19,7 +19,7 @@ return { Body = "NIX", Geometry = { Type = "SimpleSphere", - Radius = { 0.45 , 5 }, + Radius = 0.45E5, Segments = 100 }, Textures = { @@ -46,7 +46,7 @@ return { Parent = "Nix", Renderable = { Type = "RenderablePlane", - Size = {1.0, 6.3}, + Size = 10^6.3, Origin = "Center", Billboard = true, Texture = "textures/Nix-Text.png" diff --git a/data/scene/missions/newhorizons/pluto/pluto/pluto.mod b/data/scene/missions/newhorizons/pluto/pluto/pluto.mod index e512b74708..6709f03fdb 100644 --- a/data/scene/missions/newhorizons/pluto/pluto/pluto.mod +++ b/data/scene/missions/newhorizons/pluto/pluto/pluto.mod @@ -30,15 +30,15 @@ return { }, }, }, - -- PlutoProjection module + -- Pluto module { - Name = "PlutoProjection", + Name = "Pluto", Parent = "PlutoBarycenter", Renderable = { Type = "RenderablePlanetProjection", Geometry = { Type = "SimpleSphere", - Radius = { 1.173 , 6 }, + Radius = 1.173E6, Segments = 100 }, Textures = { @@ -173,7 +173,7 @@ return { Renderable = { Type = "RenderablePlane", Billboard = true, - Size = { 5, 4 }, + Size = 5E4, Texture = "textures/barycenter.png", Atmosphere = { Type = "Nishita", -- for example, values missing etc etc @@ -184,10 +184,10 @@ return { }, { Name = "PlutoText", - Parent = "PlutoProjection", + Parent = "Pluto", Renderable = { Type = "RenderablePlane", - Size = {1.0, 6.3}, + Size = 10^6.3, Origin = "Center", Billboard = true, Texture = "textures/Pluto-Text.png", @@ -202,7 +202,7 @@ return { }, { Name = "PlutoTexture", - Parent = "PlutoProjection", + Parent = "Pluto", Renderable = { Type = "RenderablePlane", Size = {1.0, 6.4}, @@ -220,7 +220,7 @@ return { }, { Name = "PlutoShadow", - Parent = "PlutoProjection", + Parent = "Pluto", Renderable = { Type = "RenderableShadowCylinder", TerminatorType = "PENUMBRAL", diff --git a/data/scene/missions/newhorizons/pluto/styx/styx.mod b/data/scene/missions/newhorizons/pluto/styx/styx.mod index 559062be97..8637601452 100644 --- a/data/scene/missions/newhorizons/pluto/styx/styx.mod +++ b/data/scene/missions/newhorizons/pluto/styx/styx.mod @@ -19,7 +19,7 @@ return { Body = "STYX", Geometry = { Type = "SimpleSphere", - Radius = { 0.75 , 4 }, + Radius = 0.75E4, Segments = 100 }, Textures = { @@ -46,7 +46,7 @@ return { Parent = "Styx", Renderable = { Type = "RenderablePlane", - Size = {1.0, 6.3}, + Size = 10^6.3, Origin = "Center", Billboard = true, Texture = "textures/Styx-Text.png", diff --git a/data/scene/moon/moon.mod b/data/scene/moon/moon.mod index b58b056dcb..534adf617c 100644 --- a/data/scene/moon/moon.mod +++ b/data/scene/moon/moon.mod @@ -9,17 +9,17 @@ return { Body = "MOON", Geometry = { Type = "SimpleSphere", - Radius = { 1.737, 6}, + Radius = 1.737E6, Segments = 100 }, Shadow_Group = { Source1 = { Name = "Sun", - Radius = {696.3, 6} + Radius = 696.3E6 }, Caster1 = { Name = "Earth", - Radius = {6.371, 6} + Radius = 6.371E6 }, }, Textures = { diff --git a/data/scene/neptune/neptune.mod b/data/scene/neptune/neptune.mod index 5967f0a8fe..38e698c9ea 100644 --- a/data/scene/neptune/neptune.mod +++ b/data/scene/neptune/neptune.mod @@ -23,20 +23,25 @@ return { Body = "NEPTUNE BARYCENTER", Geometry = { Type = "SimpleSphere", - Radius = { 2.4622 , 7 }, + Radius = 2.4622E7, Segments = 100 }, Textures = { Type = "simple", Color = "textures/neptune.jpg", - }, + } }, - Translation = { + Tag = "planet_solarSystem", + Transform = { Rotation = { Type = "SpiceRotation", SourceFrame = "IAU_NEPTUNE", DestinationFrame = "GALACTIC" }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, } }, -- NeptuneTrail module @@ -52,7 +57,8 @@ return { }, Color = {0.2, 0.5, 1.0 }, Period = 60200, - Resolution = 1000 - }, + Resolution = 1000, + Tag = "planetTrail_solarSystem" + } } } diff --git a/data/scene/newhorizons.scene b/data/scene/newhorizons.scene index ca5e4106c9..3ce05ababc 100644 --- a/data/scene/newhorizons.scene +++ b/data/scene/newhorizons.scene @@ -11,7 +11,7 @@ function preInitialization() critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") openspace.time.setTime("2015-07-14T10:05:00.00") diff --git a/data/scene/osirisrex.scene b/data/scene/osirisrex.scene index e59ce808d3..f5fff215a9 100644 --- a/data/scene/osirisrex.scene +++ b/data/scene/osirisrex.scene @@ -9,7 +9,7 @@ function preInitialization() critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") dofile(openspace.absPath('${SCRIPTS}/bind_keys_osirisrex.lua')) @@ -61,7 +61,7 @@ return { "sun", "mercury", "venus", - "lodglobes/lodearth", + "lodglobes/earth", "moon", "mars", "jupiter", diff --git a/data/scene/pluto/pluto.mod b/data/scene/pluto/pluto.mod index 88346771ef..27f540d731 100644 --- a/data/scene/pluto/pluto.mod +++ b/data/scene/pluto/pluto.mod @@ -25,7 +25,7 @@ return { Body = "PLUTO", Geometry = { Type = "SimpleSphere", - Radius = { 1.173 , 6 }, + Radius = 1.173E6, Segments = 100 }, Textures = { @@ -61,7 +61,7 @@ return { Body = "CHARON", Geometry = { Type = "SimpleSphere", - Radius = { 6.035 , 5 }, + Radius = 6.035E5, Segments = 100 }, Textures = { diff --git a/data/scene/rosetta.scene b/data/scene/rosetta.scene index 361397876f..3ba32966e7 100644 --- a/data/scene/rosetta.scene +++ b/data/scene/rosetta.scene @@ -6,7 +6,7 @@ function preInitialization() critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") -- Usual start diff --git a/data/scene/saturn/dione/dione.mod b/data/scene/saturn/dione/dione.mod index d132bea897..477705ea2b 100644 --- a/data/scene/saturn/dione/dione.mod +++ b/data/scene/saturn/dione/dione.mod @@ -8,7 +8,7 @@ return { Body = "DIONE", Geometry = { Type = "SimpleSphere", - Radius = { 0.563, 3 }, + Radius = 0.563E3, Segments = 50 }, Textures = { diff --git a/data/scene/saturn/enceladus/enceladus.mod b/data/scene/saturn/enceladus/enceladus.mod index 1d3011e4c8..f49104d3ca 100644 --- a/data/scene/saturn/enceladus/enceladus.mod +++ b/data/scene/saturn/enceladus/enceladus.mod @@ -8,7 +8,7 @@ return { Body = "ENCELADUS", Geometry = { Type = "SimpleSphere", - Radius = { 0.257, 3 }, + Radius = 0.257E3, Segments = 50 }, Textures = { diff --git a/data/scene/saturn/iapetus/iapetus.mod b/data/scene/saturn/iapetus/iapetus.mod index a390af3ec4..0bcc6b8c38 100644 --- a/data/scene/saturn/iapetus/iapetus.mod +++ b/data/scene/saturn/iapetus/iapetus.mod @@ -8,7 +8,7 @@ return { Body = "IAPETUS", Geometry = { Type = "SimpleSphere", - Radius = { 0.746, 3 }, + Radius = 0.746E3, Segments = 50 }, Textures = { diff --git a/data/scene/saturn/mimas/mimas.mod b/data/scene/saturn/mimas/mimas.mod index bf7b451d83..9f8e5242e6 100644 --- a/data/scene/saturn/mimas/mimas.mod +++ b/data/scene/saturn/mimas/mimas.mod @@ -8,7 +8,7 @@ return { Body = "MIMAS", Geometry = { Type = "SimpleSphere", - Radius = { 0.28, 3 }, + Radius = 0.28E3, Segments = 50 }, Textures = { diff --git a/data/scene/saturn/rhea/rhea.mod b/data/scene/saturn/rhea/rhea.mod index 623dd479a6..8bb6c61393 100644 --- a/data/scene/saturn/rhea/rhea.mod +++ b/data/scene/saturn/rhea/rhea.mod @@ -8,7 +8,7 @@ return { Body = "RHEA", Geometry = { Type = "SimpleSphere", - Radius = { 0.765, 3 }, + Radius = 0.765E3, Segments = 50 }, Textures = { diff --git a/data/scene/saturn/saturn/saturn.mod b/data/scene/saturn/saturn/saturn.mod index aea907718b..675910faab 100644 --- a/data/scene/saturn/saturn/saturn.mod +++ b/data/scene/saturn/saturn/saturn.mod @@ -23,7 +23,7 @@ return { Body = "SATURN BARYCENTER", Geometry = { Type = "SimpleSphere", - Radius = { 5.8232, 7 }, + Radius = 5.8232E7, Segments = 100 }, Textures = { @@ -36,6 +36,7 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = "planet_solarSystem", Transform = { Rotation = { Type = "SpiceRotation", @@ -73,7 +74,8 @@ return { }, Color = {0.85,0.75,0.51 }, Period = 10746.94, - Resolution = 1000 + Resolution = 1000, + Tag = "planetTrail_solarSystem" }, } } diff --git a/data/scene/saturn/tethys/tethys.mod b/data/scene/saturn/tethys/tethys.mod index eb2a84b3f9..8fe16fa3cd 100644 --- a/data/scene/saturn/tethys/tethys.mod +++ b/data/scene/saturn/tethys/tethys.mod @@ -8,7 +8,7 @@ return { Body = "TETHYS", Geometry = { Type = "SimpleSphere", - Radius = { 0.538, 3 }, + Radius = 0.538E3, Segments = 50 }, Textures = { diff --git a/data/scene/saturn/titan/titan.mod b/data/scene/saturn/titan/titan.mod index 83e366c7ba..12cc0d6034 100644 --- a/data/scene/saturn/titan/titan.mod +++ b/data/scene/saturn/titan/titan.mod @@ -8,7 +8,7 @@ return { Body = "TITAN", Geometry = { Type = "SimpleSphere", - Radius = { 0.2575, 4 }, + Radius = 0.2575E4, Segments = 50 }, Textures = { diff --git a/data/scene/sun/sun.mod b/data/scene/sun/sun.mod index 3bd4e2218e..11b0e1516d 100644 --- a/data/scene/sun/sun.mod +++ b/data/scene/sun/sun.mod @@ -1,4 +1,9 @@ return { + -- Solar system module + { + Name = "SolarSystem", + Parent = "Root" + }, -- Sun barycenter module { Name = "SolarSystemBarycenter", @@ -15,7 +20,8 @@ return { Body = "SUN", Geometry = { Type = "SimpleSphere", - Radius = { 2.783200, 9 }, + --Radius = 2.783200E9, + Radius = 6.957E8, Segments = 100 }, Textures = { @@ -24,7 +30,7 @@ return { }, PerformShading = false, }, - Transformation = { + Transform = { Translation = { Type = "SpiceTranslation", Body = "SUN", @@ -44,13 +50,13 @@ return { Parent = "SolarSystemBarycenter", Renderable = { Type = "RenderablePlane", - Size = {1.3, 10.5}, + Size = 1.3*10^10.5, Origin = "Center", Billboard = true, Texture = "textures/sun-glare.png", BlendMode = "Additive" }, - Transformation = { + Transform = { Translation = { Type = "SpiceTranslation", Body = "SUN", @@ -65,7 +71,7 @@ return { Parent = "Sun", Renderable = { Type = "RenderablePlane", - Size = {3.0, 11.0}, + Size = 3.0E11, Origin = "Center", Billboard = true, Texture = "textures/marker.png", diff --git a/data/scene/uranus/uranus.mod b/data/scene/uranus/uranus.mod index 7d0a559780..28e4568118 100644 --- a/data/scene/uranus/uranus.mod +++ b/data/scene/uranus/uranus.mod @@ -23,7 +23,7 @@ return { Body = "URANUS BARYCENTER", Geometry = { Type = "SimpleSphere", - Radius = { 2.5362 , 7 }, + Radius = 2.5362E7, Segments = 100 }, Textures = { @@ -36,12 +36,17 @@ return { MieColor = {1.0, 1.0, 1.0} } }, + Tag = "planet_solarSystem", Transform = { Rotation = { Type = "SpiceRotation", SourceFrame = "IAU_URANUS", DestinationFrame = "ECLIPJ2000", - } + }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, }, }, @@ -58,7 +63,8 @@ return { }, Color = {0.60, 0.95, 1.00 }, Period = 30588.740, - Resolution = 1000 - }, + Resolution = 1000, + Tag = "planetTrail_solarSystem" + } } } diff --git a/data/scene/venus/venus.mod b/data/scene/venus/venus.mod index c7943047d3..7badb32f9c 100644 --- a/data/scene/venus/venus.mod +++ b/data/scene/venus/venus.mod @@ -23,7 +23,7 @@ return { Body = "VENUS", Geometry = { Type = "SimpleSphere", - Radius = { 3.760, 6 }, + Radius = 3.760E6, Segments = 100 }, Textures = { @@ -36,10 +36,17 @@ return { MieColor = {1.0, 1.0, 1.0} } }, - Rotation = { - Type = "SpiceRotation", - Frame = "IAU_VENUS", - Reference = "GALACTIC" + Tag = {"planet_solarSystem", "planet_terrestrial"}, + Transform = { + Rotation = { + Type = "SpiceRotation", + SourceFrame = "IAU_VENUS", + DestinationFrame = "GALACTIC" + }, + Scale = { + Type = "StaticScale", + Scale = 1, + }, }, }, @@ -56,7 +63,8 @@ return { }, Color = { 1.0, 0.5, 0.2 }, Period = 224.695, - Resolution = 1000 + Resolution = 1000, + Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"} } } } diff --git a/data/scene/volumetricmilkyway.scene b/data/scene/volumetricmilkyway.scene index 9d6c9ba91d..3a4f4d71c2 100644 --- a/data/scene/volumetricmilkyway.scene +++ b/data/scene/volumetricmilkyway.scene @@ -6,7 +6,7 @@ function preInitialization() critical objects. ]]-- - openspace.spice.loadKernel("${SPICE}/naif0011.tls") + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") openspace.time.setTime(openspace.time.currentWallTime()) diff --git a/data/spice/iSWAKernels/openspace_mercury.ti b/data/spice/iSWAKernels/openspace_mercury.ti new file mode 100644 index 0000000000..218f8c3ec2 --- /dev/null +++ b/data/spice/iSWAKernels/openspace_mercury.ti @@ -0,0 +1,33 @@ +OpenSpace ecliptic frames: +Mercury-centric Solar Ecliptic (MERCURYSE) frame + +These frames are only defined as helper frames for OpenSpace. + + +X is parallel to the geometric planet-sun position vector. + + -Y axis is the normalized component of the planet's orbital vector + + +Z axis is parallel to the cross product of the frame's +X axis + and the frame's +Y axis. + +\begindata + + FRAME_MERCURYSE = 4600199 + FRAME_4600199_NAME = 'MERCURYSE' + FRAME_4600199_CLASS = 5 + FRAME_4600199_CLASS_ID = 4600199 + FRAME_4600199_CENTER = 199 + FRAME_4600199_RELATIVE = 'J2000' + FRAME_4600199_DEF_STYLE = 'PARAMETERIZED' + FRAME_4600199_FAMILY = 'TWO-VECTOR' + FRAME_4600199_PRI_AXIS = 'X' + FRAME_4600199_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_4600199_PRI_OBSERVER = 'MERCURY' + FRAME_4600199_PRI_TARGET = 'SUN' + FRAME_4600199_PRI_ABCORR = 'NONE' + FRAME_4600199_SEC_AXIS = 'Y' + FRAME_4600199_SEC_VECTOR_DEF = 'OBSERVER_TARGET_VELOCITY' + FRAME_4600199_SEC_OBSERVER = 'MERCURY' + FRAME_4600199_SEC_TARGET = 'SUN' + FRAME_4600199_SEC_ABCORR = 'NONE' + FRAME_4600199_SEC_FRAME = 'J2000' diff --git a/data/spice/iSWAKernels/openspace_saturn.ti b/data/spice/iSWAKernels/openspace_saturn.ti new file mode 100644 index 0000000000..46a81299ef --- /dev/null +++ b/data/spice/iSWAKernels/openspace_saturn.ti @@ -0,0 +1,33 @@ +OpenSpace ecliptic frames: +Saturn-centric Solar Ecliptic (SATURNSE) frame + +These frames are only defined as helper frames for OpenSpace. + + +X is parallel to the geometric planet-sun position vector. + + -Y axis is the normalized component of the planet's orbital vector + + +Z axis is parallel to the cross product of the frame's +X axis + and the frame's +Y axis. + +\begindata + + FRAME_SATURNSE = 4500699 + FRAME_4500699_NAME = 'SATURNSE' + FRAME_4500699_CLASS = 5 + FRAME_4500699_CLASS_ID = 4500699 + FRAME_4500699_CENTER = 6 + FRAME_4500699_RELATIVE = 'J2000' + FRAME_4500699_DEF_STYLE = 'PARAMETERIZED' + FRAME_4500699_FAMILY = 'TWO-VECTOR' + FRAME_4500699_PRI_AXIS = 'X' + FRAME_4500699_PRI_VECTOR_DEF = 'OBSERVER_TARGET_POSITION' + FRAME_4500699_PRI_OBSERVER = 'SATURN BARYCENTER' + FRAME_4500699_PRI_TARGET = 'SUN' + FRAME_4500699_PRI_ABCORR = 'NONE' + FRAME_4500699_SEC_AXIS = 'Y' + FRAME_4500699_SEC_VECTOR_DEF = 'OBSERVER_TARGET_VELOCITY' + FRAME_4500699_SEC_OBSERVER = 'SATURN BARYCENTER' + FRAME_4500699_SEC_TARGET = 'SUN' + FRAME_4500699_SEC_ABCORR = 'NONE' + FRAME_4500699_SEC_FRAME = 'J2000' diff --git a/data/spice/naif0011.tls b/data/spice/naif0012.tls similarity index 95% rename from data/spice/naif0011.tls rename to data/spice/naif0012.tls index 58fcbcbd7f..e1afdee1b6 100644 --- a/data/spice/naif0011.tls +++ b/data/spice/naif0012.tls @@ -7,6 +7,9 @@ LEAPSECONDS KERNEL FILE Modifications: -------------- +2016, Jul. 14 NJB Modified file to account for the leapsecond that + will occur on December 31, 2016. + 2015, Jan. 5 NJB Modified file to account for the leapsecond that will occur on June 30, 2015. @@ -141,7 +144,8 @@ DELTET/DELTA_AT = ( 10, @1972-JAN-1 33, @2006-JAN-1 34, @2009-JAN-1 35, @2012-JUL-1 - 36, @2015-JUL-1 ) + 36, @2015-JUL-1 + 37, @2017-JAN-1 ) \begintext diff --git a/data/tasks/default.task b/data/tasks/default.task new file mode 100644 index 0000000000..1170166620 --- /dev/null +++ b/data/tasks/default.task @@ -0,0 +1,3 @@ +return { + "kameleonmetadatatojson" +} diff --git a/data/web/kameleondocumentation/main.hbs b/data/web/kameleondocumentation/main.hbs new file mode 100644 index 0000000000..a12a1a9931 --- /dev/null +++ b/data/web/kameleondocumentation/main.hbs @@ -0,0 +1,59 @@ +
+ +
+
+

OpenSpace Kameleon Documentation

+

Version: {{version}}

+

CDF File: {{input}}

+

Global Attributes

+ {{#each kameleon.globalAttributes}} +
+
+
+

+ + {{@key}} + +

{{this}}

+

+
+
+
+ {{/each}} +

Variable Attributes

+ {{#each kameleon.variableAttributes}} +

{{@key}}

+ {{#each this}} +
+
+
+

+ + {{@key}} + +

{{this}}

+

+
+
+
+ {{/each}} + {{/each}} +
+
+
\ No newline at end of file diff --git a/data/web/kameleondocumentation/script.js b/data/web/kameleondocumentation/script.js new file mode 100644 index 0000000000..84f9665e59 --- /dev/null +++ b/data/web/kameleondocumentation/script.js @@ -0,0 +1,23 @@ +window.onload = function () { + var mainTemplateElement = document.getElementById('mainTemplate'); + var mainTemplate = Handlebars.compile(mainTemplateElement.innerHTML); + + Handlebars.registerHelper('urlify', function(options, context) { + var data = context.data; + var identifier = options.replace(" ", "-").toLowerCase(); + + while (data = data._parent) { + if (data.key !== undefined) { + identifier = data.key + "-" + identifier; + } + } + + return identifier; + }); + + var dataElement = document.getElementById('data'); + var data = JSON.parse(dataElement.innerHTML); + + var contents = mainTemplate(data); + document.body.innerHTML = contents; +} \ No newline at end of file diff --git a/data/web/keybindings/keybinding.hbs b/data/web/keybindings/keybinding.hbs index 29773e357e..4873cdef05 100644 --- a/data/web/keybindings/keybinding.hbs +++ b/data/web/keybindings/keybinding.hbs @@ -6,6 +6,7 @@ {{key}} {{#if remoteScripting}}Remote scripting{{else}}Local scripting{{/if}}

{{script}}

+

{{documentation}}

diff --git a/data/web/properties/main.hbs b/data/web/properties/main.hbs index fc56bca0b8..6af37752cd 100644 --- a/data/web/properties/main.hbs +++ b/data/web/properties/main.hbs @@ -18,7 +18,6 @@

OpenSpace Scene Properties

Version: {{version.[0]}}.{{version.[1]}}.{{version.[2]}}

-

Scene name: {{sceneFilename}}

Generated: {{generationTime}}

{{#each propertyOwners}} diff --git a/data/web/properties/script.js b/data/web/properties/script.js index f7302a5e0b..52b8a468fa 100644 --- a/data/web/properties/script.js +++ b/data/web/properties/script.js @@ -53,7 +53,7 @@ window.onload = function () { var data = { propertyOwners: propertyOwners, version: version, - sceneFilename: sceneFilename, + // sceneFilename: sceneFilename, generationTime: generationTime } diff --git a/ext/curl/lib/libcurl.dll b/ext/curl/lib/libcurl.dll index 1c912ca6ad..3bb272359f 100644 Binary files a/ext/curl/lib/libcurl.dll and b/ext/curl/lib/libcurl.dll differ diff --git a/ext/curl/lib/libcurl_imp.lib b/ext/curl/lib/libcurl_imp.lib index 917274da36..1b3d959654 100644 Binary files a/ext/curl/lib/libcurl_imp.lib and b/ext/curl/lib/libcurl_imp.lib differ diff --git a/ext/curl/lib/libeay32.dll b/ext/curl/lib/libeay32.dll new file mode 100644 index 0000000000..84ea405801 Binary files /dev/null and b/ext/curl/lib/libeay32.dll differ diff --git a/ext/curl/lib/ssleay32.dll b/ext/curl/lib/ssleay32.dll new file mode 100644 index 0000000000..b5d2864366 Binary files /dev/null and b/ext/curl/lib/ssleay32.dll differ diff --git a/ext/ghoul b/ext/ghoul index c007df9d95..a2f58b3085 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit c007df9d955b934624f4374505aa5912ab483dab +Subproject commit a2f58b30857be62ff13ee4128dec28037d940be7 diff --git a/ext/sgct b/ext/sgct index b3bf32e8bd..55e6eb877d 160000 --- a/ext/sgct +++ b/ext/sgct @@ -1 +1 @@ -Subproject commit b3bf32e8bd59c7a79e899face441a26a361fe982 +Subproject commit 55e6eb877d8fc02d3e3851e94fc5417a5b856217 diff --git a/ext/spice b/ext/spice index 1c9bb9e4dd..63e382ac76 160000 --- a/ext/spice +++ b/ext/spice @@ -1 +1 @@ -Subproject commit 1c9bb9e4dd562e3085c8a519c8a90668439a34ac +Subproject commit 63e382ac76e0ef37d46a8a0ec3d1980e480f3f88 diff --git a/include/openspace/documentation/documentation.h b/include/openspace/documentation/documentation.h index 28f777cbef..5e64e3b4bc 100644 --- a/include/openspace/documentation/documentation.h +++ b/include/openspace/documentation/documentation.h @@ -26,13 +26,14 @@ #define __OPENSPACE_CORE___DOCUMENTATION___H__ #include -#include #include #include #include #include +namespace ghoul { class Dictionary; } + namespace openspace { namespace documentation { @@ -304,10 +305,6 @@ void testSpecificationAndThrow(const Documentation& documentation, } // namespace documentation -// We want to make it easier for people to use it, so we pull the Documentation class into -// the openspace namespace -using documentation::Documentation; - } // namespace openspace // Make the overload for std::to_string available for the Offense::Reason for easier diff --git a/include/openspace/documentation/documentationengine.h b/include/openspace/documentation/documentationengine.h index 4841c3efc4..5ab18d9f03 100644 --- a/include/openspace/documentation/documentationengine.h +++ b/include/openspace/documentation/documentationengine.h @@ -26,8 +26,9 @@ #define __OPENSPACE_CORE___DOCUMENTATIONENGINE___H__ #include - +#include #include + #include namespace openspace { @@ -38,7 +39,9 @@ namespace documentation { * produced in the application an write them out as a documentation file for human * consumption. */ -class DocumentationEngine : public ghoul::Singleton { +class DocumentationEngine : public ghoul::Singleton + , public DocumentationGenerator +{ public: /** * This exception is thrown by the addDocumentation method if a provided Documentation @@ -57,16 +60,7 @@ public: Documentation documentation; }; - /** - * Write the collected Documentation%s to disk at the \p filename in the specified - * \p type. A new file is created and silently overwritten in the location that - * \p filename is pointed to. - * \param filename The file that is to be created containing all the Documentation - * information. - * \param type The type of documentation that is written. Currently allowed values are - * \c text and \c html - */ - void writeDocumentation(const std::string& filename, const std::string& type); + DocumentationEngine(); /** * Adds the \p documentation to the list of Documentation%s that are written to a @@ -90,8 +84,12 @@ public: static DocumentationEngine& ref(); private: + std::string generateJson() const override; + /// The list of all Documentation%s that are stored by the DocumentationEngine std::vector _documentations; + + static DocumentationEngine* _instance; }; } // namespace documentation diff --git a/include/openspace/documentation/documentationgenerator.h b/include/openspace/documentation/documentationgenerator.h new file mode 100644 index 0000000000..ca91bc9eff --- /dev/null +++ b/include/openspace/documentation/documentationgenerator.h @@ -0,0 +1,105 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___DOCUMENTATIONGENERATOR___H__ +#define __OPENSPACE_CORE___DOCUMENTATIONGENERATOR___H__ + +#include +#include + +namespace openspace { + +/* + * This abstract class is used for instances when another class has the ability to + * generate a Handlebar generated documentation file that contains valuable information + * for the user. Instances of this are the DocumentationEngine results, the list of + * Property%s generated by the Scene, or the FactoryEngine results. The documentation is + * generated through the writeDocumentation method. + * + * The concrete subclass needs to overload the generateJson class that will return the + * Json that is parsed by Handlebar to generate the webpage. + * + * A list of Handlebar templates, the variable name for the result of the generateJson + * method, and the Javascript file that contains additional logic is passed in the + * constructor. + */ +class DocumentationGenerator { +public: + /// This struct contains a single Handlebar template, with the name and the filename + struct HandlebarTemplate { + std::string name; ///< The name of the Handlebar template defined in \m filename + std::string filename; ///< The filename referenced in the \m name + }; + + /** + * The constructor that is used to set the member variables later used in the + * writeDocumentation method. + * \param name The name of the written documentation + * \param jsonName The variable name of the value generated by the generateJson + * \param handlebarTemplates A list of Handlebar templates that is added to the + * documentation file + * \param javascriptFilename The path to a Javascript source file that is added to the + * documentation and that can contain additional functionality + * \pre name must not be empty + * \pre jsonName must not be empty + * \pre Each handlebarTemplates' \c name must not be empty + * \pre javascriptFilename must not be empty + */ + DocumentationGenerator(std::string name, std::string jsonName, + std::vector handlebarTemplates, + std::string javascriptFilename); + + /// Default constructor + virtual ~DocumentationGenerator() = default; + + /** + * Create the documentation into the provided filename. Any existing file will be + * silently overwritten. This method will call the generateJson method that can be + * used by concrete subclasses to provide the actual data that is provided in the + * documentation. + * \param filename The filename in which the documentation is written + */ + void writeDocumentation(const std::string& filename); + +protected: + /** + * This abstract method is used by concrete subclasses to provide the actual data that + * is used in the documentation written by this DocumentationGenerator class. The JSON + * string returned by this function will be stored in the variable with the + * \c jsonName as passed in the constructor. + * \return A JSON script that is parsed and stored in the variable passed in the + * DocumentationGenerator constructor + */ + virtual std::string generateJson() const = 0; + +private: + const std::string _name; + const std::string _jsonName; + const std::vector _handlebarTemplates; + const std::string _javascriptFile; +}; + +} // namespace openspace + +#endif // __OPENSPACE_CORE___DOCUMENTATIONGENERATOR___H__ diff --git a/include/openspace/documentation/verifier.h b/include/openspace/documentation/verifier.h index 07579a747d..ddf39e6c9a 100644 --- a/include/openspace/documentation/verifier.h +++ b/include/openspace/documentation/verifier.h @@ -27,6 +27,8 @@ #include +#include + #include #include @@ -42,6 +44,8 @@ namespace documentation { * description of the Verifier subclass and what it tests for. */ struct Verifier { + virtual ~Verifier() = default; + /** * This method tests whether the \p key contained in the \p dictionary adheres to * whatever the concrete Verifer needs to test. The actual testing depends on the @@ -212,6 +216,19 @@ struct StringListVerifier : public TableVerifier { std::string type() const override; }; +/** +* A Verifier that checks whether all values contained in a Table are of type \c int. +*/ +struct IntListVerifier : public TableVerifier { + /** + * Constructor for a IntListVerifier. + * \param elementDocumentation The documentation for each string in the list + */ + IntListVerifier(std::string elementDocumentation = ""); + + std::string type() const override; +}; + //---------------------------------------------------------------------------------------- // Vector verifiers //---------------------------------------------------------------------------------------- diff --git a/include/openspace/documentation/verifier.inl b/include/openspace/documentation/verifier.inl index d03a05a2b9..70751ac380 100644 --- a/include/openspace/documentation/verifier.inl +++ b/include/openspace/documentation/verifier.inl @@ -22,7 +22,10 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#include + #include +#include namespace std { std::string to_string(std::string value); @@ -55,86 +58,62 @@ std::string TemplateVerifier::documentation() const { template std::string Vector2Verifier::type() const { - using namespace std::string_literals; - - return "Vector2<"s + typeid(T).name() + ">"; + return std::string("Vector2<") + typeid(T).name() + ">"; } template std::string Vector3Verifier::type() const { - using namespace std::string_literals; - - return "Vector3<"s + typeid(T).name() + ">"; + return std::string("Vector3<") + typeid(T).name() + ">"; } template std::string Vector4Verifier::type() const { - using namespace std::string_literals; - - return "Vector4<"s + typeid(T).name() + ">"; + return std::string("Vector4<") + typeid(T).name() + ">"; } template std::string Matrix2x2Verifier::type() const { - using namespace std::string_literals; - - return "Matrix2x2<"s + typeid(T).name() + ">"; + return std::string("Matrix2x2<") + typeid(T).name() + ">"; } template std::string Matrix2x3Verifier::type() const { - using namespace std::string_literals; - - return "Matrix2x3<"s + typeid(T).name() + ">"; + return std::string("Matrix2x3<") + typeid(T).name() + ">"; } template std::string Matrix2x4Verifier::type() const { - using namespace std::string_literals; - - return "Matrix2x4<"s + typeid(T).name() + ">"; + return std::string("Matrix2x4<") + typeid(T).name() + ">"; } template std::string Matrix3x2Verifier::type() const { - using namespace std::string_literals; - - return "Matrix3x2<"s + typeid(T).name() + ">"; + return std::string("Matrix3x2<") + typeid(T).name() + ">"; } template std::string Matrix3x3Verifier::type() const { - using namespace std::string_literals; - - return "Matrix3x3<"s + typeid(T).name() + ">"; + return std::string("Matrix3x3<") + typeid(T).name() + ">"; } template std::string Matrix3x4Verifier::type() const { - using namespace std::string_literals; - - return "Matrix3x4<"s + typeid(T).name() + ">"; + return std::string("Matrix3x4<") + typeid(T).name() + ">"; } template std::string Matrix4x2Verifier::type() const { - using namespace std::string_literals; - - return "Matrix4x2<"s + typeid(T).name() + ">"; + return std::string("Matrix4x2<") + typeid(T).name() + ">"; } template std::string Matrix4x3Verifier::type() const { - using namespace std::string_literals; - - return "Matrix4x3<"s + typeid(T).name() + ">"; + return std::string("Matrix4x3<") + typeid(T).name() + ">"; } template std::string Matrix4x4Verifier::type() const { - using namespace std::string_literals; - - return "Matrix4x4<"s + typeid(T).name() + ">"; + return std::string("Matrix4x4<") + typeid(T).name() + ">"; } template diff --git a/include/openspace/engine/configurationmanager.h b/include/openspace/engine/configurationmanager.h index d65892b076..8ec3aa167d 100644 --- a/include/openspace/engine/configurationmanager.h +++ b/include/openspace/engine/configurationmanager.h @@ -25,11 +25,10 @@ #ifndef __OPENSPACE_CORE___CONFIGURATIONMANAGER___H__ #define __OPENSPACE_CORE___CONFIGURATIONMANAGER___H__ -#include - #include namespace openspace { +namespace documentation { struct Documentation; } /** * The ConfigurationManager takes care of loading the major configuration file @@ -69,6 +68,8 @@ public: static const std::string KeyFactoryDocumentation; /// The key that stores the location of the scene file that is initially loaded static const std::string KeyConfigScene; + /// The key that stores the location of the tasks file that is initially loaded + static const std::string KeyConfigTask; /// The key that stores the subdirectory containing a list of all startup scripts to /// be executed on application start before the scene file is loaded static const std::string KeyStartupScript; @@ -105,6 +106,8 @@ public: /// The key that stores whether the master node should perform rendering just function /// as a pure manager static const std::string KeyDisableMasterRendering; + /// The key that stores whether the master node should apply the scene transformation + static const std::string KeyDisableSceneOnMaster; /// The key that sets the request URL that is used to request additional data to be /// downloaded static const std::string KeyDownloadRequestURL; @@ -125,7 +128,22 @@ public: static const std::string PartHttpProxyUser; /// The key that stores the password to use for authentication to access the http proxy static const std::string PartHttpProxyPassword; - + /// The key that stores the dictionary containing information about debug contexts + static const std::string KeyOpenGLDebugContext; + /// The part of the key storing whether an OpenGL Debug context should be created + static const std::string PartActivate; + /// The part of the key storing whether the debug callbacks are performed synchronous + static const std::string PartSynchronous; + /// The part of the key storing a list of identifiers that should be filtered out + static const std::string PartFilterIdentifier; + /// The part of the key that stores the source of the ignored identifier + static const std::string PartFilterIdentifierSource; + /// The part of the key that stores the type of the ignored identifier + static const std::string PartFilterIdentifierType; + /// The part of the key that stores the identifier of the ignored identifier + static const std::string PartFilterIdentifierIdentifier; + /// The part of the key storing a list of severities that should be filtered out + static const std::string PartFilterSeverity; /** * Iteratively walks the directory structure starting with \p filename to find the @@ -144,27 +162,17 @@ public: * that are specified in the configuration file will automatically be registered in * the ghoul::filesystem::FileSystem. * \param filename The filename to be loaded - * \throw ghoul::FileNotFoundException If the \p filename did not exist - * \throw ghoul::RuntimeError If the configuration file was not complete (i.e., did + * \throw SpecificationError If the configuration file was not complete (i.e., did * not specify the necessary keys KeyPaths, KeyPaths.KeyCache, KeyFonts, and * KeyConfigSgct) * \throw ghoul::lua::LuaRuntimeException If there was Lua-based error loading the * configuration file * \pre \p filename must not be empty + * \pre \p filename must exist */ void loadFromFile(const std::string& filename); - static openspace::Documentation Documentation(); - -private: - /** - * Checks whether the loaded configuration file is complete, that is specifying the - * necessary keys KeyPaths, KeyPaths.KeyCache, KeyFonts, and KeyConfigSgct. The method - * will log fatal errors if a key is missing. - * \return true if the configuration file was complete; - * false otherwise - */ - bool checkCompleteness() const; + static documentation::Documentation Documentation(); }; } // namespace openspace diff --git a/include/openspace/engine/logfactory.h b/include/openspace/engine/logfactory.h index b32d3c6380..026208f33d 100644 --- a/include/openspace/engine/logfactory.h +++ b/include/openspace/engine/logfactory.h @@ -28,12 +28,16 @@ #include namespace ghoul { + class Dictionary; namespace logging { class Log; } -} + +} // namespace ghoul namespace openspace { +namespace documentation { struct Documentation; } + /** * This function provides the capabilities to create a new ghoul::logging::Log from the * provided ghoul::Dictionary%. The Dictionary must at least contain a Type @@ -44,15 +48,24 @@ namespace openspace { * created . Both logs can be customized using the Append, * TimeStamping, DateStamping, CategoryStamping, * and LogLevelStamping values. - * \param dictionary The dictionary from which the ghoul::logging::Log should be created + * + * \param dictionary The dictionary from which the ghoul::logging::Log should be created * \return The created ghoul::logging::Log - * \post The return value will not be nullptr - * \throw ghoul::RuntimeError If there was an error creating the ghoul::logging::Log - * \sa ghoul::logging::TextLeg - * \sa ghoul::logging::HTMLLog + * \post The return value will not be nullptr + * \throw ghoul::RuntimeError If there was an error creating the ghoul::logging::Log + * \sa ghoul::logging::TextLog + * \sa ghoul::logging::HTMLLog */ std::unique_ptr createLog(const ghoul::Dictionary& dictionary); +/** + * Returns the Documentation that describes a Dictionary used to create a log by using the + * function createLog. + * \return The Documentation that describes an acceptable Dictionary for the method + * createLog + */ +documentation::Documentation LogFactoryDocumentation(); + } // namespace openspace #endif // __OPENSPACE_CORE___LOGFACTORY___H__ diff --git a/include/openspace/engine/moduleengine.h b/include/openspace/engine/moduleengine.h index cb6d6357c0..ab3a118ecc 100644 --- a/include/openspace/engine/moduleengine.h +++ b/include/openspace/engine/moduleengine.h @@ -25,14 +25,23 @@ #ifndef __OPENSPACE_CORE___MODULEENGINE___H__ #define __OPENSPACE_CORE___MODULEENGINE___H__ -#include -#include - #include #include +#include + +namespace ghoul { +namespace systemcapabilities { + +struct Version; + +} // namespace systemcapabilities +} // namespace ghoul + namespace openspace { +namespace scripting { struct LuaLibrary; } + /** * The ModuleEngine is the central repository for registering and accessing * OpenSpaceModule for the current application run. By initializing (#initialize) the @@ -80,8 +89,7 @@ public: * version of all registered modules' OpenGL versions. * \return The combined minimum OpenGL version */ - ghoul::systemcapabilities::OpenGLCapabilitiesComponent::Version - requiredOpenGLVersion() const; + ghoul::systemcapabilities::Version requiredOpenGLVersion() const; /** * Returns the Lua library that contains all Lua functions available to affect the diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 1c7ac2db50..dfc04f409b 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -36,71 +36,60 @@ #include namespace ghoul { + class Dictionary; + namespace cmdparser { class CommandlineParser; } namespace fontrendering { class FontManager; } -} + +} // namespace ghoul namespace openspace { class ConfigurationManager; class DownloadManager; -class LuaConsole; -class NetworkEngine; class GUI; -class RenderEngine; +class LuaConsole; class ModuleEngine; -class WindowWrapper; -class SettingsEngine; -class TimeManager; -class SyncEngine; +class NetworkEngine; class ParallelConnection; +class RenderEngine; +class SettingsEngine; +class SceneManager; +class VirtualPropertyManager; + +class SyncEngine; +class TimeManager; +class WindowWrapper; namespace interaction { class InteractionHandler; } namespace gui { class GUI; } -//namespace scripting { class ScriptEngine; } namespace properties { class PropertyOwner; } -namespace scripting { struct LuaLibrary; } -namespace scripting { class ScriptScheduler; } -namespace scripting { class ScriptEngine; } - +namespace scripting { + struct LuaLibrary; + class ScriptEngine; + class ScriptScheduler; +} // namespace scripting + class OpenSpaceEngine { public: - static bool create(int argc, char** argv, + static void create(int argc, char** argv, std::unique_ptr windowWrapper, - std::vector& sgctArguments); + std::vector& sgctArguments, bool& requestClose); static void destroy(); - static bool isInitialized(); static OpenSpaceEngine& ref(); - bool isMaster(); - void setMaster(bool master); double runTime(); void setRunTime(double t); - // Guaranteed to return a valid pointer - ConfigurationManager& configurationManager(); - interaction::InteractionHandler& interactionHandler(); - RenderEngine& renderEngine(); - scripting::ScriptEngine& scriptEngine(); - scripting::ScriptScheduler& scriptScheduler(); - NetworkEngine& networkEngine(); - LuaConsole& console(); - ModuleEngine& moduleEngine(); - ParallelConnection& parallelConnection(); - properties::PropertyOwner& globalPropertyOwner(); - WindowWrapper& windowWrapper(); - ghoul::fontrendering::FontManager& fontManager(); - DownloadManager& downloadManager(); - TimeManager& timeManager(); - SettingsEngine& settingsEngine(); - - // SGCT callbacks - bool initialize(); - bool initializeGL(); + // callbacks + void initialize(); + void initializeGL(); + void deinitialize(); void preSynchronization(); void postSynchronizationPreDraw(); - void render(const glm::mat4& projectionMatrix, const glm::mat4& viewMatrix); + void render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix, + const glm::mat4& projectionMatrix); void postDraw(); void keyboardCallback(Key key, KeyModifier mod, KeyAction action); void charCallback(unsigned int codepoint, KeyModifier mod); @@ -111,21 +100,36 @@ public: void encode(); void decode(); + void scheduleLoadScene(std::string scenePath); + void enableBarrier(); void disableBarrier(); - + void writeDocumentation(); void toggleShutdownMode(); - bool useBusyWaitForDecode(); - bool logSGCTOutOfOrderErrors(); - void runPostInitializationScripts(const std::string& sceneDescription); + // Guaranteed to return a valid pointer + ConfigurationManager& configurationManager(); + LuaConsole& console(); + DownloadManager& downloadManager(); + ModuleEngine& moduleEngine(); + NetworkEngine& networkEngine(); + ParallelConnection& parallelConnection(); + RenderEngine& renderEngine(); + SettingsEngine& settingsEngine(); + TimeManager& timeManager(); + WindowWrapper& windowWrapper(); + ghoul::fontrendering::FontManager& fontManager(); + interaction::InteractionHandler& interactionHandler(); + properties::PropertyOwner& globalPropertyOwner(); + scripting::ScriptEngine& scriptEngine(); + scripting::ScriptScheduler& scriptScheduler(); + VirtualPropertyManager& virtualPropertyManager(); // This method is only to be called from Modules - enum class CallbackOption { Initialize = 0, // Callback for the end of the initialization Deinitialize, // Callback for the end of the deinitialization @@ -138,34 +142,7 @@ public: }; // Registers a callback for a specific CallbackOption - void registerModuleCallback(CallbackOption option, std::function function) { - switch (option) { - case CallbackOption::Initialize: - _moduleCallbacks.initialize.push_back(std::move(function)); - break; - case CallbackOption::Deinitialize: - _moduleCallbacks.deinitialize.push_back(std::move(function)); - break; - case CallbackOption::InitializeGL: - _moduleCallbacks.initializeGL.push_back(std::move(function)); - break; - case CallbackOption::DeinitializeGL: - _moduleCallbacks.deinitializeGL.push_back(std::move(function)); - break; - case CallbackOption::PreSync: - _moduleCallbacks.preSync.push_back(std::move(function)); - break; - case CallbackOption::PostSyncPreDraw: - _moduleCallbacks.postSyncPreDraw.push_back(std::move(function)); - break; - case CallbackOption::Render: - _moduleCallbacks.render.push_back(std::move(function)); - break; - case CallbackOption::PostDraw: - _moduleCallbacks.postDraw.push_back(std::move(function)); - break; - } - } + void registerModuleCallback(CallbackOption option, std::function function); // Registers a callback that is called when a new keyboard event is received void registerModuleKeyboardCallback( @@ -187,43 +164,47 @@ public: void registerModuleMouseScrollWheelCallback(std::function function); /** - * Returns the Lua library that contains all Lua functions available to affect the - * application. - */ + * Returns the Lua library that contains all Lua functions available to affect the + * application. + */ static scripting::LuaLibrary luaLibrary(); private: - OpenSpaceEngine(std::string programName, std::unique_ptr windowWrapper); - ~OpenSpaceEngine(); + OpenSpaceEngine(std::string programName, + std::unique_ptr windowWrapper); - void clearAllWindows(); + void loadScene(const std::string& scenePath); void gatherCommandlineArguments(); void loadFonts(); - void runScripts(const ghoul::Dictionary& scripts); void runPreInitializationScripts(const std::string& sceneDescription); void configureLogging(); // Components std::unique_ptr _configurationManager; - std::unique_ptr _interactionHandler; - std::unique_ptr _renderEngine; - std::unique_ptr _scriptEngine; - std::unique_ptr _scriptScheduler; - std::unique_ptr _networkEngine; - std::unique_ptr _syncEngine; - std::unique_ptr _commandlineParser; + std::unique_ptr _sceneManager; + std::unique_ptr _downloadManager; std::unique_ptr _console; std::unique_ptr _moduleEngine; - std::unique_ptr _settingsEngine; - std::unique_ptr _timeManager; - std::unique_ptr _downloadManager; + std::unique_ptr _networkEngine; std::unique_ptr _parallelConnection; + std::unique_ptr _renderEngine; + std::unique_ptr _settingsEngine; + std::unique_ptr _syncEngine; + std::unique_ptr _timeManager; std::unique_ptr _windowWrapper; + std::unique_ptr _commandlineParser; std::unique_ptr _fontManager; + std::unique_ptr _interactionHandler; + std::unique_ptr _scriptEngine; + std::unique_ptr _scriptScheduler; + std::unique_ptr _virtualPropertyManager; // Others std::unique_ptr _globalPropertyNamespace; + bool _scheduledSceneSwitch; + std::string _scenePath; + struct { std::vector> initialize; std::vector> deinitialize; @@ -242,25 +223,24 @@ private: std::vector> mouseButton; std::vector> mousePosition; std::vector> mouseScrollWheel; - - - - } _moduleCallbacks; - bool _isMaster; double _runTime; - // Whether the application is currently in shutdown mode (i.e. counting down the timer - // and closing it at '0' - bool _isInShutdownMode; - // The total amount of time the application will wait before actually shutting down - float _shutdownWait; - // The current state of the countdown; if it reaches '0', the application will close - float _shutdownCountdown; + // Structure that is responsible for the delayed shutdown of the application + struct { + // Whether the application is currently in shutdown mode (i.e. counting down the + // timer and closing it at '0' + bool inShutdown; + // Total amount of time the application will wait before actually shutting down + float waitTime; + // Current state of the countdown; if it reaches '0', the application will + // close + float timer; + } _shutdown; // The first frame might take some more time in the update loop, so we need to know to - // disable the synchronization; otherwise a hardware sync will kill us after 1 sec + // disable the synchronization; otherwise a hardware sync will kill us after 1 minute bool _isFirstRenderingFirstFrame; static OpenSpaceEngine* _engine; diff --git a/include/openspace/engine/settingsengine.h b/include/openspace/engine/settingsengine.h index bcce9884f5..e040192928 100644 --- a/include/openspace/engine/settingsengine.h +++ b/include/openspace/engine/settingsengine.h @@ -43,28 +43,18 @@ public: void initialize(); - void setModules(std::vector modules); + void setModules(const std::vector& modules); bool busyWaitForDecode(); bool logSGCTOutOfOrderErrors(); bool useDoubleBuffering(); private: - void initEyeSeparation(); - void initSceneFiles(); - void initShowFrameNumber(); - void initBusyWaitForDecode(); - void initLogSGCTOutOfOrderErrors(); - void initUseDoubleBuffering(); - - properties::FloatProperty _eyeSeparation; properties::OptionProperty _scenes; - properties::BoolProperty _showFrameNumber; properties::BoolProperty _busyWaitForDecode; properties::BoolProperty _logSGCTOutOfOrderErrors; properties::BoolProperty _useDoubleBuffering; properties::BoolProperty _spiceUseExceptions; - }; } // namespace openspace diff --git a/include/openspace/engine/syncengine.h b/include/openspace/engine/syncengine.h index 77f8a7c51b..8d2c92711e 100644 --- a/include/openspace/engine/syncengine.h +++ b/include/openspace/engine/syncengine.h @@ -25,80 +25,87 @@ #ifndef __OPENSPACE_CORE___SYNCENGINE___H__ #define __OPENSPACE_CORE___SYNCENGINE___H__ +#include + +#include + #include #include namespace openspace { class Syncable; -class SyncBuffer; /** -* Manages a collection of Syncables and ensures they are synchronized -* over SGCT nodes. Encoding/Decoding order is handles internally. -*/ + * Manages a collection of Syncables and ensures they are synchronized + * over SGCT nodes. Encoding/Decoding order is handles internally. + */ class SyncEngine { public: + using IsMaster = ghoul::Boolean; /** - * Dependency injection: a SyncEngine relies on a SyncBuffer to encode the sync data. - */ - SyncEngine(SyncBuffer* syncBuffer); - + * Creates a new SyncEngine which a buffer size of \p syncBufferSize + * \pre syncBufferSize must be bigger than 0 + */ + SyncEngine(unsigned int syncBufferSize); /** - * Encodes all added Syncables in the injected SyncBuffer. - * This method is only called on the SGCT master node - */ + * Encodes all added Syncables in the injected SyncBuffer. + * This method is only called on the SGCT master node + */ void encodeSyncables(); /** - * Decodes the SyncBuffer into the added Syncables. - * This method is only called on the SGCT slave nodes - */ + * Decodes the SyncBuffer into the added Syncables. + * This method is only called on the SGCT slave nodes + */ void decodeSyncables(); /** - * Invokes the presync method of all added Syncables - */ - void presync(bool isMaster); + * Invokes the presync method of all added Syncables + */ + void preSynchronization(IsMaster isMaster); /** - * Invokes the postsync method of all added Syncables - */ - void postsync(bool isMaster); + * Invokes the postsync method of all added Syncables + */ + void postSynchronization(IsMaster isMaster); - - /** - * Add a Syncable to be synchronized over the SGCT cluster - */ + * Add a Syncable to be synchronized over the SGCT cluster. + * \pre syncable must not be nullptr + */ void addSyncable(Syncable* syncable); /** - * Add multiple Syncables to be synchronized over the SGCT cluster - */ + * Add multiple Syncables to be synchronized over the SGCT cluster + * \pre syncables must not contain any nullptr + */ void addSyncables(const std::vector& syncables); /** - * Remove a Syncable from being synchronized over the SGCT cluster - */ + * Remove a Syncable from being synchronized over the SGCT cluster + */ void removeSyncable(Syncable* syncable); -private: - - /** - * Vector of Syncables. The vectors ensures consistent encode/decode order + /** + * Remove multiple Syncables from being synchronized over the SGCT cluster */ + void removeSyncables(const std::vector& syncables); + +private: + /** + * Vector of Syncables. The vectors ensures consistent encode/decode order + */ std::vector _syncables; /** - * Databuffer used in encoding/decoding - */ - std::unique_ptr _syncBuffer; + * Databuffer used in encoding/decoding + */ + SyncBuffer _syncBuffer; }; - } // namespace openspace #endif // __OPENSPACE_CORE___SYNCENGINE___H__ diff --git a/include/openspace/interaction/keyboardcontroller.h b/include/openspace/engine/virtualpropertymanager.h similarity index 72% rename from include/openspace/interaction/keyboardcontroller.h rename to include/openspace/engine/virtualpropertymanager.h index b222f9058d..5c1192ede0 100644 --- a/include/openspace/interaction/keyboardcontroller.h +++ b/include/openspace/engine/virtualpropertymanager.h @@ -22,36 +22,29 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_CORE___KEYBOARDCONTROLLER___H__ -#define __OPENSPACE_CORE___KEYBOARDCONTROLLER___H__ +#ifndef __OPENSPACE_CORE___VIRTUALPROPERTYMANAGER___H__ +#define __OPENSPACE_CORE___VIRTUALPROPERTYMANAGER___H__ -#include +#include -#include +#include + +#include +#include namespace openspace { -namespace interaction { -class KeyboardController : public Controller { +class VirtualPropertyManager : public properties::PropertyOwner { public: - virtual ~KeyboardController() {}; - virtual void keyPressed(KeyAction action, Key key, KeyModifier modifier) = 0; + VirtualPropertyManager(); + + void addProperty(std::unique_ptr prop); + void removeProperty(properties::Property* prop); + +private: + std::vector> _properties; }; -class KeyboardControllerFixed : public KeyboardController { -public: - void keyPressed(KeyAction action, Key key, KeyModifier modifier); -}; - -class KeyboardControllerLua : public KeyboardController { -public: - void keyPressed(KeyAction action, Key key, KeyModifier modifier); - -protected: - std::string keyToString(Key key, KeyModifier mod) const; -}; - -} // namespace interaction } // namespace openspace -#endif // __OPENSPACE_CORE___KEYBOARDCONTROLLER___H__ +#endif // __OPENSPACE_CORE___VIRTUALPROPERTYMANAGER___H__ diff --git a/include/openspace/engine/wrapper/sgctwindowwrapper.h b/include/openspace/engine/wrapper/sgctwindowwrapper.h index 3a0fd67131..7dc3db262b 100644 --- a/include/openspace/engine/wrapper/sgctwindowwrapper.h +++ b/include/openspace/engine/wrapper/sgctwindowwrapper.h @@ -27,6 +27,9 @@ #include +#include +#include + namespace openspace { /** @@ -36,6 +39,8 @@ namespace openspace { */ class SGCTWindowWrapper : public WindowWrapper { public: + SGCTWindowWrapper(); + void terminate() override; void setBarrier(bool enabled) override; void setSynchronization(bool enabled) override; @@ -55,6 +60,7 @@ public: bool isRegularRendering() const override; bool hasGuiWindow() const override; bool isGuiWindow() const override; + bool isMaster() const override; bool isUsingSwapGroups() const override; bool isSwapGroupMaster() const override; @@ -71,6 +77,10 @@ public: bool isSimpleRendering() const override; void takeScreenshot(bool applyWarping = false) const override; + +private: + properties::FloatProperty _eyeSeparation; + properties::BoolProperty _showStatsGraph; }; } // namespace openspace diff --git a/include/openspace/engine/wrapper/windowwrapper.h b/include/openspace/engine/wrapper/windowwrapper.h index b3ed6797fb..252eb4258a 100644 --- a/include/openspace/engine/wrapper/windowwrapper.h +++ b/include/openspace/engine/wrapper/windowwrapper.h @@ -25,6 +25,8 @@ #ifndef __OPENSPACE_CORE___WINDOWWRAPPER___H__ #define __OPENSPACE_CORE___WINDOWWRAPPER___H__ +#include + #include #include @@ -42,8 +44,11 @@ namespace scripting { struct LuaLibrary; } * Every new windowing framework needs to have its own WindowWrapper subclass exposing the * required features. */ -class WindowWrapper { +class WindowWrapper : public properties::PropertyOwner { public: + /// Default constructor + WindowWrapper(); + /** * Returns the Lua library that contains all Lua functions available to affect the * windowing system. @@ -175,6 +180,13 @@ public: * \return Whether the current rendering window is GUI-only */ virtual bool isGuiWindow() const; + + /** + * Returns true if this application is the master for a clustered + * environment. + * \return Whether this applicaiton is the master for a clustered environment. + */ + virtual bool isMaster() const; /** * Returns true if the current rendering window is using swap groups. diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index aa9e04fc43..891dfca494 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -25,10 +25,11 @@ #ifndef __OPENSPACE_CORE___INTERACTIONHANDLER___H__ #define __OPENSPACE_CORE___INTERACTIONHANDLER___H__ -#include +#include +#include + #include #include -#include #include #include #include @@ -48,8 +49,7 @@ class SceneGraphNode; namespace interaction { - -class InteractionHandler : public properties::PropertyOwner +class InteractionHandler : public properties::PropertyOwner, public DocumentationGenerator { public: InteractionHandler(); @@ -66,6 +66,7 @@ public: // Interaction mode setters void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict); void setInteractionMode(const std::string& interactionModeKey); + InteractionMode* interactionMode(); void goToChunk(int x, int y, int level); void goToGeo(double latitude, double longitude); @@ -73,7 +74,9 @@ public: void resetKeyBindings(); void addKeyframe(const datamessagestructures::CameraKeyframe &kf); + void removeKeyframesAfter(double timestamp); void clearKeyframes(); + const std::vector& keyframes() const; void bindKeyLocal( Key key, @@ -96,8 +99,10 @@ public: // Accessors ghoul::Dictionary getCameraStateDictionary(); - SceneGraphNode* const focusNode() const; - Camera* const camera() const; + SceneGraphNode* focusNode() const; + glm::dvec3 focusNodeToCameraVector() const; + glm::quat focusNodeToCameraRotation() const; + Camera* camera() const; const InputState& inputState() const; /** @@ -117,7 +122,6 @@ public: void saveCameraStateToFile(const std::string& filepath); void restoreCameraStateFromFile(const std::string& filepath); - void writeKeyboardDocumentation(const std::string& type, const std::string& file); private: using Synchronized = ghoul::Boolean; @@ -127,6 +131,8 @@ private: Synchronized synchronization; std::string documentation; }; + + std::string generateJson() const override; void setInteractionMode(std::shared_ptr interactionMode); @@ -144,7 +150,6 @@ private: // Properties properties::StringProperty _origin; - properties::StringProperty _coordinateSystem; properties::BoolProperty _rotationalFriction; properties::BoolProperty _horizontalFriction; diff --git a/include/openspace/interaction/interactionmode.h b/include/openspace/interaction/interactionmode.h index f383866c73..0698e2992e 100644 --- a/include/openspace/interaction/interactionmode.h +++ b/include/openspace/interaction/interactionmode.h @@ -25,7 +25,6 @@ #ifndef __OPENSPACE_CORE___INTERACTIONMODE___H__ #define __OPENSPACE_CORE___INTERACTIONMODE___H__ -#include #include #include #include @@ -83,9 +82,12 @@ namespace interaction { // Mutators void addKeyframe(const datamessagestructures::CameraKeyframe &kf); + void removeKeyframesAfter(double timestamp); void clearKeyframes(); void clearOldKeyframes(); + static bool compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b); + // Accessors const std::list >& getPressedKeys() const; const std::list& getPressedMouseButtons() const; @@ -109,11 +111,10 @@ namespace interaction { -class InteractionMode -{ +class InteractionMode { public: InteractionMode(); - ~InteractionMode(); + virtual ~InteractionMode(); // Mutators virtual void setFocusNode(SceneGraphNode* focusNode); @@ -121,6 +122,7 @@ public: // Accessors SceneGraphNode* focusNode(); Interpolator& rotateToFocusNodeInterpolator(); + virtual bool followingNodeRotation() const = 0; virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime) = 0; virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime) = 0; @@ -197,6 +199,7 @@ public: virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime); virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); + bool followingNodeRotation() const override; private: std::vector _keyframes; @@ -247,6 +250,7 @@ public: virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime); virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); + bool followingNodeRotation() const override; protected: //void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); @@ -262,6 +266,7 @@ public: virtual void setFocusNode(SceneGraphNode* focusNode); //virtual void update(Camera& camera, const InputState& inputState, double deltaTime); virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); + bool followingNodeRotation() const override; #ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED void goToChunk(Camera& camera, globebrowsing::TileIndex ti, glm::vec2 uv, bool resetCameraDirection); diff --git a/include/openspace/interaction/luaconsole.h b/include/openspace/interaction/luaconsole.h index 00890d18fb..77beaf3109 100644 --- a/include/openspace/interaction/luaconsole.h +++ b/include/openspace/interaction/luaconsole.h @@ -25,9 +25,10 @@ #ifndef __OPENSPACE_CORE___LUACONSOLE___H__ #define __OPENSPACE_CORE___LUACONSOLE___H__ -#include #include - +#include +#include +#include #include #include @@ -35,50 +36,35 @@ namespace openspace { -class LuaConsole { +class LuaConsole : public properties::PropertyOwner { public: LuaConsole(); void initialize(); void deinitialize(); - void keyboardCallback(Key key, KeyModifier modifier, KeyAction action); + bool keyboardCallback(Key key, KeyModifier modifier, KeyAction action); void charCallback(unsigned int codepoint, KeyModifier modifier); void render(); - Key commandInputButton(); - - bool isVisible() const; - void setVisible(bool visible); - bool isRemoteScripting() const; - void setRemoteScripting(bool remoteScripting); - - void toggleMode(); - - static scripting::LuaLibrary luaLibrary(); - - private: void parallelConnectionChanged(const ParallelConnection::Status& status); void addToCommand(std::string c); - std::string UnicodeToUTF8(unsigned int codepoint); + + properties::BoolProperty _isVisible; + properties::BoolProperty _remoteScripting; size_t _inputPosition; std::vector _commandsHistory; size_t _activeCommand; std::vector _commands; - std::string _filename; - struct { int lastIndex; bool hasInitialValue; std::string initialValue; } _autoCompleteInfo; - - bool _isVisible; - bool _remoteScripting; }; } // namespace openspace diff --git a/include/openspace/mission/mission.h b/include/openspace/mission/mission.h index 24d89829d1..b5dfe70f50 100644 --- a/include/openspace/mission/mission.h +++ b/include/openspace/mission/mission.h @@ -25,7 +25,6 @@ #ifndef __OPENSPACE_CORE___MISSION___H__ #define __OPENSPACE_CORE___MISSION___H__ -#include #include #include @@ -35,6 +34,7 @@ namespace ghoul { class Dictionary; } namespace openspace { +namespace documentation { struct Documentation; } /** * Used to represent a named period of time within a mission. Allows nested phases, i.e. @@ -62,26 +62,25 @@ public: * Returns the name of the MissionPhase. * \return The name of the MissionPhase */ - const std::string& name() const; + std::string name() const; /** * Returns the TimeRange of the MissionPhase. * \return The TimeRange of the MissionPhase */ - const TimeRange& timeRange() const; + TimeRange timeRange() const; /** * Returns the description of the MissionPhase. * \return The description of the MissionPhase */ - const std::string& description() const; + std::string description() const; /** * Returns all subphases sorted by start time. * \return All subphases sorted by start time */ - const std::vector& phases() const; - + std::vector phases() const; using Trace = std::vector>; @@ -101,7 +100,7 @@ public: * MissionPhase can be constructed from. * \return The Documentation that describes the required structure for a Dictionary */ - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); protected: /** @@ -111,6 +110,7 @@ protected: * \param time The time which the subphases have to cover to be added to the \p trace * \param trace The list of MissionPhase%s that are active during the time \p time * \param maxDepth The maximum depth of levels that will be considered + * \pre maxDepth must not be negative */ void phaseTrace(double time, Trace& trace, int maxDepth) const; @@ -139,7 +139,7 @@ using Mission = MissionPhase; * \pre \p filename must not contain tokens * \pre \p filename must exist */ -Mission missionFromFile(std::string filename); +Mission missionFromFile(const std::string& filename); } // namespace openspace diff --git a/include/openspace/network/messagestructures.h b/include/openspace/network/messagestructures.h index 5f85c57bcb..ee2ffc71a9 100644 --- a/include/openspace/network/messagestructures.h +++ b/include/openspace/network/messagestructures.h @@ -51,16 +51,28 @@ struct CameraKeyframe { glm::dvec3 _position; glm::dquat _rotation; + bool _followNodeRotation; + std::string _focusNode; + double _timestamp; void serialize(std::vector &buffer){ - //add position + // Add position buffer.insert(buffer.end(), reinterpret_cast(&_position), reinterpret_cast(&_position) + sizeof(_position)); - //add orientation + // Add orientation buffer.insert(buffer.end(), reinterpret_cast(&_rotation), reinterpret_cast(&_rotation) + sizeof(_rotation)); - - //add timestamp + + // Follow focus node rotation? + buffer.insert(buffer.end(), reinterpret_cast(&_followNodeRotation), reinterpret_cast(&_followNodeRotation) + sizeof(_followNodeRotation)); + + int nodeNameLength = _focusNode.size(); + + // Add focus node + buffer.insert(buffer.end(), reinterpret_cast(&nodeNameLength), reinterpret_cast(&nodeNameLength) + sizeof(nodeNameLength)); + buffer.insert(buffer.end(), _focusNode.data(), _focusNode.data() + nodeNameLength); + + // Add timestamp buffer.insert(buffer.end(), reinterpret_cast(&_timestamp), reinterpret_cast(&_timestamp) + sizeof(_timestamp)); }; @@ -68,17 +80,31 @@ struct CameraKeyframe { int offset = 0; int size = 0; - //position + // Position size = sizeof(_position); memcpy(&_position, buffer.data() + offset, size); offset += size; - - //orientation + + // Orientation size = sizeof(_rotation); memcpy(&_rotation, buffer.data() + offset, size); offset += size; + + // Follow focus node rotation? + size = sizeof(_followNodeRotation); + memcpy(&_followNodeRotation, buffer.data() + offset, size); + offset += size; + + // Focus node + int nodeNameLength; + size = sizeof(int); + memcpy(&nodeNameLength, buffer.data() + offset, size); + offset += size; + size = nodeNameLength; + _focusNode = std::string(buffer.data() + offset, buffer.data() + offset + size); + offset += size; - //timestamp + // Timestamp size = sizeof(_timestamp); memcpy(&_timestamp, buffer.data() + offset, size); }; @@ -97,19 +123,19 @@ struct TimeKeyframe { double _timestamp; void serialize(std::vector &buffer){ - //add current time + // Add current time buffer.insert(buffer.end(), reinterpret_cast(&_time), reinterpret_cast(&_time) + sizeof(_time)); - //add delta time + // Add delta time buffer.insert(buffer.end(), reinterpret_cast(&_dt), reinterpret_cast(&_dt) + sizeof(_dt)); - //add wether time is paused or not + // Add whether time is paused or not buffer.insert(buffer.end(), reinterpret_cast(&_paused), reinterpret_cast(&_paused) + sizeof(_paused)); - //add wether a time jump is necessary (recompute paths etc) + // Add whether a time jump is necessary (recompute paths etc) buffer.insert(buffer.end(), reinterpret_cast(&_requiresTimeJump), reinterpret_cast(&_requiresTimeJump) + sizeof(_requiresTimeJump)); - //add timestamp + // Add timestamp buffer.insert(buffer.end(), reinterpret_cast(&_timestamp), reinterpret_cast(&_timestamp) + sizeof(_timestamp)); }; @@ -117,27 +143,27 @@ struct TimeKeyframe { int offset = 0; int size = 0; - //current time + // Current time size = sizeof(_time); memcpy(&_time, buffer.data() + offset, size); offset += size; - //delta time + // Delta time size = sizeof(_dt); memcpy(&_dt, buffer.data() + offset, size); offset += size; - //is time paused? + // Is time paused? size = sizeof(_paused); memcpy(&_paused, buffer.data() + offset, size); offset += sizeof(_paused); - //is a time jump required? + // Is a time jump required? size = sizeof(_requiresTimeJump); memcpy(&_requiresTimeJump, buffer.data() + offset, size); offset += size; - // timestamp + // Timestamp size = sizeof(_timestamp); memcpy(&_timestamp, buffer.data() + offset, size); offset += size; diff --git a/include/openspace/network/parallelconnection.h b/include/openspace/network/parallelconnection.h index d95060d7c0..db3d000413 100644 --- a/include/openspace/network/parallelconnection.h +++ b/include/openspace/network/parallelconnection.h @@ -27,6 +27,9 @@ //openspace includes #include +#include +#include +#include //glm includes #include @@ -57,7 +60,7 @@ struct addrinfo; namespace openspace { -class ParallelConnection { +class ParallelConnection : public properties::PropertyOwner { public: enum class Status : uint32_t { Disconnected = 0, @@ -99,17 +102,21 @@ class ParallelConnection { ParallelConnection(); ~ParallelConnection(); void clientConnect(); - void setPort(const std::string &port); - void setAddress(const std::string &address); - void setName(const std::string& name); + void setPort(std::string port); + void setAddress(std::string address); + void setName(std::string name); bool isHost(); const std::string& hostName(); - void requestHostship(const std::string &password); + void requestHostship(); void resignHostship(); - void setPassword(const std::string &password); + void setPassword(std::string password); + void setHostPassword(std::string hostPassword); void signalDisconnect(); void preSynchronization(); - void sendScript(const std::string& script); + void sendScript(std::string script); + void resetTimeOffset(); + double latencyStandardDeviation() const; + double timeTolerance() const; /** * Returns the Lua library that contains all Lua functions available to affect the @@ -120,7 +127,7 @@ class ParallelConnection { */ static scripting::LuaLibrary luaLibrary(); Status status(); - size_t nConnections(); + int nConnections(); std::shared_ptr> connectionEvent(); @@ -145,7 +152,6 @@ private: void connectionStatusMessageReceived(const std::vector& messageContent); void nConnectionsMessageReceived(const std::vector& messageContent); - void broadcast(); void sendCameraKeyframe(); void sendTimeKeyframe(); @@ -158,10 +164,18 @@ private: double calculateBufferedKeyframeTime(double originalTime); - uint32_t _passCode; - std::string _port; - std::string _address; - std::string _name; + properties::StringProperty _password; + properties::StringProperty _hostPassword; + properties::StringProperty _port; + properties::StringProperty _address; + properties::StringProperty _name; + properties::FloatProperty _bufferTime; + properties::FloatProperty _timeKeyframeInterval; + properties::FloatProperty _cameraKeyframeInterval; + properties::FloatProperty _timeTolerance; + + double _lastTimeKeyframeTimestamp; + double _lastCameraKeyframeTimestamp; _SOCKET _clientSocket; @@ -191,7 +205,6 @@ private: double _initialTimeDiff; std::unique_ptr _connectionThread; - std::unique_ptr _broadcastThread; std::unique_ptr _sendThread; std::unique_ptr _listenThread; std::unique_ptr _handlerThread; diff --git a/include/openspace/openspace.h b/include/openspace/openspace.h index 199359475a..58ba149440 100644 --- a/include/openspace/openspace.h +++ b/include/openspace/openspace.h @@ -32,10 +32,10 @@ namespace openspace { std::string licenseText(); const int OPENSPACE_VERSION_MAJOR = 0; -const int OPENSPACE_VERSION_MINOR = 7; +const int OPENSPACE_VERSION_MINOR = 8; const int OPENSPACE_VERSION_PATCH = 0; -const std::string OPENSPACE_VERSION_STRING = "prerelease-12 (NAOJ)"; +const std::string OPENSPACE_VERSION_STRING = "prerelease-13 (Earth Day)"; } // namespace openspace diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index 80b224bf76..54e7a07532 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -64,13 +64,13 @@ class Property { public: /** * The visibility classes for Property%s. The classes are strictly ordered as - * All > Developer > User > None + * All > Developer > User > Hidden */ enum class Visibility { All = 3, ///< Visible for all types, no matter what Developer = 2, ///< Visible in Developer mode User = 1, ///< Visible in User mode - None = 0 ///< Never visible + Hidden = 0 ///< Never visible }; /** @@ -314,10 +314,10 @@ public: * Property::ViewOptions::PowerScaledCoordinate = powerScaledCoordinate. */ struct ViewOptions { - static const std::string Color; - static const std::string LightPosition; - static const std::string PowerScaledScalar; - static const std::string PowerScaledCoordinate; + static const char* Color; + static const char* LightPosition; + static const char* PowerScaledScalar; + static const char* PowerScaledCoordinate; }; /** @@ -329,10 +329,10 @@ public: const ghoul::Dictionary& metaData() const; protected: - static const std::string IdentifierKey; - static const std::string NameKey; - static const std::string TypeKey; - static const std::string MetaDataKey; + static const char* IdentifierKey; + static const char* NameKey; + static const char* TypeKey; + static const char* MetaDataKey; /** * Creates the information that is general to every Property and adds the diff --git a/include/openspace/properties/propertyowner.h b/include/openspace/properties/propertyowner.h index 09f6f0cc0b..4fdec7bb12 100644 --- a/include/openspace/properties/propertyowner.h +++ b/include/openspace/properties/propertyowner.h @@ -25,7 +25,6 @@ #ifndef __OPENSPACE_CORE___PROPERTYOWNER___H__ #define __OPENSPACE_CORE___PROPERTYOWNER___H__ -#include #include #include #include @@ -33,6 +32,8 @@ namespace openspace { namespace properties { +class Property; + /** * A PropertyOwner can own Propertys or other PropertyOwner and provide access to both in * a unified way. The identifiers and names of Propertys and @@ -53,7 +54,7 @@ public: static const char URISeparator = '.'; /// The constructor initializing the PropertyOwner's name to "" - PropertyOwner(); + PropertyOwner(std::string name = ""); /** * The destructor will remove all Propertys and PropertyOwners it owns along with @@ -206,6 +207,20 @@ public: /// \see PropertyOwner::removePropertySubOwner(PropertyOwner*) void removePropertySubOwner(PropertyOwner& owner); + /** + * Returns a list of all tags that have been assigned to the Property. Useful for + * trying to find a match for a desired batch operation on Properties. + * \return Pointer to vector of string tags that were assigned to the Property + */ + std::vector tags() const; + + /** + * Adds a tag to the Property's list of assigned tags. Tags are useful for creating + * groups of Properties that can be used in batch operations. + * \param tag The string that is to be assigned to the Property + */ + void addTag(std::string tag); + private: /// The name of this PropertyOwner std::string _name; @@ -217,6 +232,8 @@ private: std::vector _subOwners; /// The associations between group identifiers of Property's and human-readable names std::map _groupNames; + /// Collection of string tag(s) assigned to this property + std::vector _tags; }; } // namespace properties diff --git a/include/openspace/rendering/abufferrenderer.h b/include/openspace/rendering/abufferrenderer.h index 042c0380dd..2a3fc3a8fd 100644 --- a/include/openspace/rendering/abufferrenderer.h +++ b/include/openspace/rendering/abufferrenderer.h @@ -43,14 +43,14 @@ namespace ghoul { - namespace filesystem { - class File; - } - namespace opengl { - class ProgramObject; - class Texture; - } -} +namespace filesystem { class File; } + +namespace opengl { + class ProgramObject; + class Texture; +} // namepsace opengl + +} // namespace ghoul namespace openspace { @@ -71,8 +71,8 @@ public: void setResolution(glm::ivec2 res) override; void setNAaSamples(int nAaSamples) override; - void preRaycast(ghoul::opengl::ProgramObject& programObject); - void postRaycast(ghoul::opengl::ProgramObject& programObject); + void preRaycast(const RaycasterTask& raycasterTask); + void postRaycast(const RaycasterTask& raycasterTask); void update(); void render(float blackoutFactor, bool doPerformanceMeasurements) override; @@ -130,9 +130,6 @@ private: GLuint _vertexPositionBuffer; int _nAaSamples; - - std::unique_ptr _rendererTasks; - std::unique_ptr _renderData; float _blackoutFactor; ghoul::Dictionary _rendererData; diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index 3c77d09fbe..b2abbb7710 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -28,14 +28,10 @@ #include #include -#include #include #include -#include - - // Forward declare to minimize dependencies namespace ghoul { namespace opengl { @@ -46,6 +42,8 @@ namespace ghoul { namespace openspace { +namespace documentation { struct Documentation; } + // Forward declare to minimize dependencies class Camera; @@ -60,7 +58,7 @@ public: Overlay = 8 }; - static Renderable* createFromDictionary(const ghoul::Dictionary& dictionary); + static std::unique_ptr createFromDictionary(const ghoul::Dictionary& dictionary); // constructors & destructor Renderable(); @@ -73,8 +71,8 @@ public: virtual bool isReady() const = 0; bool isEnabled() const; - void setBoundingSphere(PowerScaledScalar boundingSphere); - PowerScaledScalar getBoundingSphere(); + void setBoundingSphere(float boundingSphere); + float boundingSphere() const; virtual void render(const RenderData& data); virtual void render(const RenderData& data, RendererTasks& rendererTask); @@ -93,14 +91,14 @@ public: static void setPscUniforms(ghoul::opengl::ProgramObject& program, const Camera& camera, const PowerScaledCoordinate& position); - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); protected: properties::BoolProperty _enabled; private: RenderBin _renderBin; - PowerScaledScalar boundingSphere_; + float _boundingSphere; std::string _startTime; std::string _endTime; bool _hasTimeInterval; diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index a9644fd41c..cb5cdb8382 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -25,11 +25,18 @@ #ifndef __OPENSPACE_CORE___RENDERENGINE___H__ #define __OPENSPACE_CORE___RENDERENGINE___H__ -#include - +#include #include #include #include +#include +#include + +#include +#include +#include + +#include #include @@ -46,17 +53,11 @@ class SharedMemory; namespace openspace { -namespace performance { -class PerformanceManager; -} - // Forward declare to minimize dependencies class Camera; class SyncBuffer; - class Scene; -class Renderer; -class RaycasterManager; +class SceneManager; class ScreenLog; class ScreenSpaceRenderable; @@ -74,18 +75,16 @@ public: FPSAvg }; - static const std::string KeyFontMono; - static const std::string KeyFontLight; - static const std::vector FrametimeTypes; - RenderEngine(); - ~RenderEngine(); + ~RenderEngine() = default; - bool initialize(); - bool deinitialize(); + void initialize(); + void initializeGL(); + void deinitialize(); - void setSceneGraph(Scene* sceneGraph); + void setScene(Scene* scene); Scene* scene(); + void updateScene(); Camera* camera() const; Renderer* renderer() const; @@ -93,32 +92,25 @@ public: RaycasterManager& raycasterManager(); // sgct wrapped functions - bool initializeGL(); - void updateSceneGraph(); + void updateShaderPrograms(); void updateFade(); void updateRenderer(); void updateScreenSpaceRenderables(); - void render(const glm::mat4& projectionMatrix, const glm::mat4& viewMatrix); + void render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix, + const glm::mat4& projectionMatrix); void renderScreenLog(); void renderShutdownInformation(float timer, float fullTime); void postDraw(); - void takeScreenshot(bool applyWarping = false); - void toggleInfoText(bool b); - // Performance measurements bool doesPerformanceMeasurements() const; performance::PerformanceManager* performanceManager(); float globalBlackOutFactor(); void setGlobalBlackOutFactor(float factor); - void setNAaSamples(int nAaSamples); - void setShowFrameNumber(bool enabled); - - void setDisableRenderingOnMaster(bool enabled); void registerScreenSpaceRenderable(std::shared_ptr s); void unregisterScreenSpaceRenderable(std::shared_ptr s); @@ -153,6 +145,11 @@ public: */ void postRaycast(ghoul::opengl::ProgramObject& programObject); + /** + * Set the camera to use for rendering + */ + void setCamera(Camera* camera); + void setRendererFromString(const std::string& method); @@ -174,9 +171,6 @@ public: */ static scripting::LuaLibrary luaLibrary(); - // This is a temporary method to change the origin of the coordinate system ---abock - void changeViewPoint(std::string origin); - // Temporary fade functionality void startFading(int direction, float fadeDuration); @@ -193,9 +187,9 @@ private: void renderInformation(); - Camera* _mainCamera; - Scene* _sceneGraph; - RaycasterManager* _raycasterManager; + Camera* _camera; + Scene* _scene; + std::unique_ptr _raycasterManager; properties::BoolProperty _performanceMeasurements; std::unique_ptr _performanceManager; @@ -210,18 +204,23 @@ private: //FrametimeType _frametimeType; - bool _showInfo; - bool _showLog; - bool _takeScreenshot; - bool _applyWarping; - bool _showFrameNumber; + properties::BoolProperty _showDate; + properties::BoolProperty _showInfo; + properties::BoolProperty _showLog; + + properties::TriggerProperty _takeScreenshot; + bool _shouldTakeScreenshot; + properties::BoolProperty _applyWarping; + properties::BoolProperty _showFrameNumber; + properties::BoolProperty _disableMasterRendering; + properties::BoolProperty _disableSceneTranslationOnMaster; float _globalBlackOutFactor; float _fadeDuration; float _currentFadeTime; int _fadeDirection; - int _nAaSamples; - unsigned int _frameNumber; + properties::IntProperty _nAaSamples; + uint64_t _frameNumber; std::vector _programs; std::vector> _screenSpaceRenderables; @@ -230,8 +229,6 @@ private: std::shared_ptr _fontInfo = nullptr; std::shared_ptr _fontDate = nullptr; std::shared_ptr _fontLog = nullptr; - - bool _disableMasterRendering = false; }; } // namespace openspace diff --git a/include/openspace/rendering/screenspacerenderable.h b/include/openspace/rendering/screenspacerenderable.h index ec24a67848..bd9b4ebafc 100644 --- a/include/openspace/rendering/screenspacerenderable.h +++ b/include/openspace/rendering/screenspacerenderable.h @@ -36,10 +36,12 @@ #include #include -#include +#include namespace openspace { +namespace documentation { struct Documentation; } + /** * The base class for screen space images and screen space framebuffers. * This base class handles general functionality specific to planes that are rendered in @@ -49,7 +51,7 @@ namespace openspace { */ class ScreenSpaceRenderable : public properties::PropertyOwner { public: - static ScreenSpaceRenderable* createFromDictionary( + static std::unique_ptr createFromDictionary( const ghoul::Dictionary& dictionary); ScreenSpaceRenderable(const ghoul::Dictionary& dictionary); @@ -66,7 +68,7 @@ public: glm::vec3 sphericalPosition() const; float depth() const; - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); protected: void createPlane(); diff --git a/include/openspace/rendering/volumeraycaster.h b/include/openspace/rendering/volumeraycaster.h index 4315ebc5cc..e9cb1674b0 100644 --- a/include/openspace/rendering/volumeraycaster.h +++ b/include/openspace/rendering/volumeraycaster.h @@ -38,8 +38,8 @@ namespace ghoul { namespace openspace { -class RenderData; -class RaycastData; +struct RenderData; +struct RaycastData; class VolumeRaycaster { public: diff --git a/include/openspace/scene/rotation.h b/include/openspace/scene/rotation.h index b09883d2f6..18d1f0a7c1 100644 --- a/include/openspace/scene/rotation.h +++ b/include/openspace/scene/rotation.h @@ -27,24 +27,29 @@ #include -#include -#include +#include -#include +#include + +namespace ghoul { class Dictionary; } namespace openspace { +struct UpdateData; + +namespace documentation { struct Documentation; } + class Rotation : public properties::PropertyOwner { public: - static Rotation* createFromDictionary(const ghoul::Dictionary& dictionary); + static std::unique_ptr createFromDictionary(const ghoul::Dictionary& dictionary); Rotation(const ghoul::Dictionary& dictionary); - virtual ~Rotation(); + virtual ~Rotation() = default; virtual bool initialize(); const glm::dmat3& matrix() const; virtual void update(const UpdateData& data); - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); protected: Rotation(); diff --git a/include/openspace/scene/scale.h b/include/openspace/scene/scale.h index 91a2bfcf30..147fed31f1 100644 --- a/include/openspace/scene/scale.h +++ b/include/openspace/scene/scale.h @@ -27,23 +27,29 @@ #include -#include -#include +#include -#include +#include + +namespace ghoul { class Dictionary; } namespace openspace { +struct UpdateData; + +namespace documentation { struct Documentation; }; + class Scale : public properties::PropertyOwner { public: - static Scale* createFromDictionary(const ghoul::Dictionary& dictionary); + static std::unique_ptr createFromDictionary(const ghoul::Dictionary& dictionary); - virtual ~Scale(); + Scale(); + virtual ~Scale() = default; virtual bool initialize(); virtual double scaleValue() const = 0; virtual void update(const UpdateData& data); - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); }; } // namespace openspace diff --git a/include/openspace/scene/scene.h b/include/openspace/scene/scene.h index 7ebc087e0d..dcd77be9dc 100644 --- a/include/openspace/scene/scene.h +++ b/include/openspace/scene/scene.h @@ -25,84 +25,117 @@ #ifndef __OPENSPACE_CORE___SCENE___H__ #define __OPENSPACE_CORE___SCENE___H__ +#include + #include #include #include #include -#include - #include #include #include -#include - #include -#include + +namespace ghoul { class Dictionary; } namespace openspace { +namespace documentation { struct Documentation; } + class SceneGraphNode; // Notifications: // SceneGraphFinishedLoading -class Scene { +class Scene : public DocumentationGenerator { public: + + using UpdateDependencies = ghoul::Boolean; + + struct InvalidSceneError : ghoul::RuntimeError { + /** + * \param message The reason that caused this exception to be thrown + * \param component The optional compoment that caused this exception to be thrown + * \pre message may not be empty + */ + explicit InvalidSceneError(const std::string& message, const std::string& component = ""); + }; + // constructors & destructor Scene(); - ~Scene(); /** - * Initalizes the SceneGraph by loading modules from the ${SCENEPATH} directory + * Initalizes the SceneGraph */ - bool initialize(); + void initialize(); - /* - * Clean up everything + /** + * Clear the scene graph, + * i.e. set the root node to nullptr and deallocate all scene graph nodes. */ - bool deinitialize(); + void clear(); - /* - * Load the scenegraph from the provided folder + /** + * Set the root node of the scene */ - void scheduleLoadSceneFile(const std::string& sceneDescriptionFilePath); - void clearSceneGraph(); + void setRoot(std::unique_ptr root); - void loadModule(const std::string& modulePath); + /** + * Set the camera of the scene + */ + void setCamera(std::unique_ptr camera); - /* + /** + * Return the camera + */ + Camera* camera() const; + + /** * Updates all SceneGraphNodes relative positions */ void update(const UpdateData& data); - /* - * Evaluates if the SceneGraphNodes are visible to the provided camera - */ - void evaluate(Camera* camera); - - /* - * Render visible SceneGraphNodes using the provided camera + /** + * Render visible SceneGraphNodes using the provided camera. */ void render(const RenderData& data, RendererTasks& tasks); - /* - * Returns the root SceneGraphNode + /** + * Return the root SceneGraphNode. */ SceneGraphNode* root() const; /** * Return the scenegraph node with the specified name or nullptr if that - * name does not exist + * name does not exist. */ SceneGraphNode* sceneGraphNode(const std::string& name) const; - std::vector allSceneGraphNodes() const; + /** + * Add a node and all its children to the scene. + */ + void addNode(SceneGraphNode* node, UpdateDependencies updateDeps = UpdateDependencies::Yes); - SceneGraph& sceneGraph(); + /** + * Remove a node and all its children from the scene. + */ + void removeNode(SceneGraphNode* node, UpdateDependencies updateDeps = UpdateDependencies::Yes); + + /** + * Update dependencies. + */ + void updateDependencies(); + + /** + * Return a vector of all scene graph nodes in the scene. + */ + const std::vector& allSceneGraphNodes() const; + + /** + * Return a a map from name to scene graph node. + */ + const std::map& nodesByName() const; - void addSceneGraphNode(SceneGraphNode* node){ - _graph.addSceneGraphNode(node); - } /** * Returns the Lua library that contains all Lua functions available to change the * scene graph. The functions contained are @@ -116,38 +149,19 @@ public: static documentation::Documentation Documentation(); private: - bool loadSceneInternal(const std::string& sceneDescriptionFilePath); + std::string generateJson() const override; - void writePropertyDocumentation(const std::string& filename, const std::string& type, const std::string& sceneFilename); + void sortTopologically(); - std::string _focus; - - // actual scenegraph - SceneGraph _graph; - //SceneGraphNode* _root; - //std::vector _nodes; - //std::map _allNodes; - - std::string _sceneGraphToLoad; + std::unique_ptr _root; + std::unique_ptr _camera; + std::vector _topologicallySortedNodes; + std::vector _circularNodes; + std::map _nodesByName; std::mutex _programUpdateLock; std::set _programsToUpdate; std::vector> _programs; - - typedef std::map NodeMap; - typedef std::multimap DependencyMap; - typedef std::vector LoadedList; - - struct LoadMaps { - NodeMap nodes; - DependencyMap dependencies; - LoadedList loadedNodes; - }; - - void loadModules(const std::string& directory, const ghoul::Dictionary& dictionary); - void loadModule(LoadMaps& m,const std::string& modulePath, lua_State* state); - void loadNodes(const std::string& parentName, LoadMaps& m); - void loadNode(const ghoul::Dictionary& dictionary); }; } // namespace openspace diff --git a/include/openspace/scene/scenegraphnode.h b/include/openspace/scene/scenegraphnode.h index 9f178aa530..9298e670ae 100644 --- a/include/openspace/scene/scenegraphnode.h +++ b/include/openspace/scene/scenegraphnode.h @@ -25,9 +25,6 @@ #ifndef __OPENSPACE_CORE___SCENEGRAPHNODE___H__ #define __OPENSPACE_CORE___SCENEGRAPHNODE___H__ -// open space includes -#include - #include #include #include @@ -35,19 +32,23 @@ #include #include -#include #include -// std includes #include #include #include #include +namespace ghoul { class Dictionary; } + namespace openspace { +namespace documentation { struct Documentation; } + class SceneGraphNode : public properties::PropertyOwner { public: + using UpdateScene = ghoul::Boolean; + struct PerformanceRecord { long long renderTime; // time in ns long long updateTimeRenderable; // time in ns @@ -60,25 +61,36 @@ public: static const std::string KeyName; static const std::string KeyParentName; static const std::string KeyDependencies; + static const std::string KeyTag; SceneGraphNode(); ~SceneGraphNode(); - static SceneGraphNode* createFromDictionary(const ghoul::Dictionary& dictionary); + static std::unique_ptr createFromDictionary(const ghoul::Dictionary& dictionary); bool initialize(); bool deinitialize(); + void traversePreOrder(std::function fn); + void traversePostOrder(std::function fn); void update(const UpdateData& data); - void evaluate(const Camera* camera, const psc& parentPosition = psc()); void render(const RenderData& data, RendererTasks& tasks); void updateCamera(Camera* camera) const; - //void addNode(SceneGraphNode* child); + void attachChild(std::unique_ptr child, UpdateScene updateScene = UpdateScene::Yes); + std::unique_ptr detachChild(SceneGraphNode& child, UpdateScene updateScene = UpdateScene::Yes); + void setParent(SceneGraphNode& parent, UpdateScene updateScene = UpdateScene::Yes); - void addChild(SceneGraphNode* child); - void setParent(SceneGraphNode* parent); - //bool abandonChild(SceneGraphNode* child); + void addDependency(SceneGraphNode& dependency, UpdateScene updateScene = UpdateScene::Yes); + void removeDependency(SceneGraphNode& dependency, UpdateScene updateScene = UpdateScene::Yes); + void clearDependencies(UpdateScene updateScene = UpdateScene::Yes); + void setDependencies(const std::vector& dependencies, UpdateScene updateScene = UpdateScene::Yes); + + const std::vector& dependencies() const; + const std::vector& dependentNodes() const; + + Scene* scene(); + void setScene(Scene* scene); glm::dvec3 position() const; const glm::dmat3& rotationMatrix() const; @@ -86,41 +98,39 @@ public: glm::dvec3 worldPosition() const; const glm::dmat3& worldRotationMatrix() const; + glm::dmat4 modelTransform() const; + glm::dmat4 inverseModelTransform() const; double worldScale() const; SceneGraphNode* parent() const; - const std::vector& children() const; + std::vector children() const; - PowerScaledScalar calculateBoundingSphere(); - PowerScaledScalar boundingSphere() const; + float boundingSphere() const; SceneGraphNode* childNode(const std::string& name); const PerformanceRecord& performanceRecord() const { return _performanceRecord; } - void setRenderable(Renderable* renderable); + void setRenderable(std::unique_ptr renderable); const Renderable* renderable() const; Renderable* renderable(); static documentation::Documentation Documentation(); private: - bool sphereInsideFrustum(const psc& s_pos, const PowerScaledScalar& s_rad, const Camera* camera); - glm::dvec3 calculateWorldPosition() const; glm::dmat3 calculateWorldRotation() const; double calculateWorldScale() const; - std::vector _children; + std::vector> _children; SceneGraphNode* _parent; + std::vector _dependencies; + std::vector _dependentNodes; + Scene* _scene; PerformanceRecord _performanceRecord; - Renderable* _renderable; - bool _renderableVisible; - - bool _boundingSphereVisible; - PowerScaledScalar _boundingSphere; + std::unique_ptr _renderable; // Transformation defined by ephemeris, rotation and scale struct { @@ -133,6 +143,9 @@ private: glm::dvec3 _worldPositionCached; glm::dmat3 _worldRotationCached; double _worldScaleCached; + + glm::dmat4 _modelTransformCached; + glm::dmat4 _inverseModelTransformCached; }; } // namespace openspace diff --git a/include/openspace/scene/sceneloader.h b/include/openspace/scene/sceneloader.h new file mode 100644 index 0000000000..ee828985a4 --- /dev/null +++ b/include/openspace/scene/sceneloader.h @@ -0,0 +1,119 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___SCENELOADER___H__ +#define __OPENSPACE_CORE___SCENELOADER___H__ + +#include +#include + +#include +#include + +#include +#include + +namespace openspace { + +class Scene; + +class SceneLoader { +public: + SceneLoader() = default; + ~SceneLoader() = default; + + /** + * Load a scene file. + */ + std::unique_ptr loadScene(const std::string& path); + + /** + * Import a directory of scene contents into an existing scene. + */ + std::vector importDirectory(Scene& scene, const std::string& directory); + + /** + * Import a scene graph node from a dictionary into an existing scene. + */ + SceneGraphNode* importNodeDictionary(Scene& scene, const ghoul::Dictionary& dictionary); + +private: + struct LoadedNode { + LoadedNode( + const std::string& nodeName, + const std::string& parentName, + const std::vector& deps, + std::unique_ptr n + ) + : name(nodeName) + , parent(parentName) + , dependencies(deps) + , node(std::move(n)) {} + + std::string name; + std::string parent; + std::vector dependencies; + std::unique_ptr node; + }; + + struct LoadedCamera { + LoadedCamera( + const std::string& parentName, + std::unique_ptr c + ) + : parent(parentName) + , camera(std::move(c)) {} + std::string parent; + std::unique_ptr camera; + }; + + /** + * Load a scene graph node from a dictionary + */ + SceneLoader::LoadedNode loadNode(const ghoul::Dictionary& dictionary); + + /** + * Load a mod file. + */ + std::vector loadModule(const std::string& path, lua_State* luaState); + + /** + * Load a directory. + */ + std::vector loadDirectory(const std::string& path, lua_State* luaState); + + /** + * Load a camera from a dictionary + */ + SceneLoader::LoadedCamera loadCamera(const ghoul::Dictionary& dictionary); + + /** + * Add loaded nodes to an existing scene + */ + std::vector addLoadedNodes(Scene& scene, std::vector&& nodes); +}; + +} // namespace openspace + +#endif // __OPENSPACE_CORE___SCENELOADER___H__ diff --git a/include/openspace/scene/scenemanager.h b/include/openspace/scene/scenemanager.h new file mode 100644 index 0000000000..26e73d9857 --- /dev/null +++ b/include/openspace/scene/scenemanager.h @@ -0,0 +1,48 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___SCENEMANAGER___H__ +#define __OPENSPACE_CORE___SCENEMANAGER___H__ + +#include +#include + +namespace openspace { + +class Scene; + +class SceneManager { +public: + SceneManager() = default; + ~SceneManager() = default; + Scene* loadScene(const std::string& path); + void unloadScene(Scene& scene); + void unloadAll(); +private: + std::vector> _scenes; +}; + +} // namespace + +#endif // __OPENSPACE_CORE___SCENEMANAGER___H__ diff --git a/include/openspace/scene/translation.h b/include/openspace/scene/translation.h index c7abb4ba6c..21ce0515b4 100644 --- a/include/openspace/scene/translation.h +++ b/include/openspace/scene/translation.h @@ -27,18 +27,25 @@ #include -#include -#include +#include -#include +#include +#include + +namespace ghoul { class Dictionary; } namespace openspace { +struct UpdateData; + +namespace documentation { struct Documentation; } + class Translation : public properties::PropertyOwner { public: - static Translation* createFromDictionary(const ghoul::Dictionary& dictionary); + static std::unique_ptr createFromDictionary(const ghoul::Dictionary& dictionary); - virtual ~Translation(); + Translation(); + virtual ~Translation() = default; virtual bool initialize(); virtual glm::dvec3 position() const = 0; @@ -50,7 +57,7 @@ public: // invalidates potentially stored points, for example in trails void onParameterChange(std::function callback); - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); protected: void notifyObservers(); diff --git a/include/openspace/scripting/lualibrary.h b/include/openspace/scripting/lualibrary.h index 07e0b54794..4f881f21ad 100644 --- a/include/openspace/scripting/lualibrary.h +++ b/include/openspace/scripting/lualibrary.h @@ -27,6 +27,9 @@ #include +#include +#include + namespace openspace { namespace scripting { diff --git a/include/openspace/scripting/scriptengine.h b/include/openspace/scripting/scriptengine.h index 5dad097168..c35bc3cbb9 100644 --- a/include/openspace/scripting/scriptengine.h +++ b/include/openspace/scripting/scriptengine.h @@ -25,10 +25,14 @@ #ifndef __OPENSPACE_CORE___SCRIPTENGINE___H__ #define __OPENSPACE_CORE___SCRIPTENGINE___H__ -#include +#include #include +#include + #include +#include +#include #include #include @@ -48,9 +52,12 @@ namespace scripting { * openspace namespac prefix in Lua. The same functions can be exposed to * other Lua states by passing them to the #initializeLuaState method. */ -class ScriptEngine : public Syncable { +class ScriptEngine : public Syncable, public DocumentationGenerator { public: using RemoteScripting = ghoul::Boolean; + + ScriptEngine(); + /** * Initializes the internal Lua state and registers a common set of library functions * \throw LuaRuntimeException If the creation of the new Lua state fails @@ -71,8 +78,6 @@ public: bool runScript(const std::string& script); bool runScriptFile(const std::string& filename); - void writeDocumentation(const std::string& filename, const std::string& type) const; - bool writeLog(const std::string& script); virtual void presync(bool isMaster); @@ -93,8 +98,9 @@ public: //bool shouldScriptBeSent(const std::string &library, const std::string &function); //void cacheScript(const std::string &library, const std::string &function, const std::string &script); + static std::string OpenSpaceLibraryName; + private: - bool registerLuaLibrary(lua_State* state, const LuaLibrary& library); void addLibraryFunctions(lua_State* state, const LuaLibrary& library, bool replace); @@ -103,7 +109,9 @@ private: void addBaseLibrary(); void remapPrintFunction(); - lua_State* _state = nullptr; + std::string generateJson() const override; + + ghoul::lua::LuaState _state; std::set _registeredLibraries; //sync variables diff --git a/include/openspace/scripting/scriptscheduler.h b/include/openspace/scripting/scriptscheduler.h index cd30739b90..fce3028caf 100644 --- a/include/openspace/scripting/scriptscheduler.h +++ b/include/openspace/scripting/scriptscheduler.h @@ -25,7 +25,6 @@ #ifndef __OPENSPACE_CORE___SCRIPTSCHEDULER___H__ #define __OPENSPACE_CORE___SCRIPTSCHEDULER___H__ -#include #include #include @@ -36,6 +35,7 @@ class Dictionary; } // namespace ghoul namespace openspace { +namespace documentation { struct Documentation; } namespace scripting { /** @@ -111,7 +111,7 @@ public: static LuaLibrary luaLibrary(); - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); private: std::vector _timings; diff --git a/apps/DataConverter/conversiontask.h b/include/openspace/scripting/systemcapabilitiesbinding.h similarity index 85% rename from apps/DataConverter/conversiontask.h rename to include/openspace/scripting/systemcapabilitiesbinding.h index 388088977f..107b97b5c3 100644 --- a/apps/DataConverter/conversiontask.h +++ b/include/openspace/scripting/systemcapabilitiesbinding.h @@ -22,20 +22,18 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_APP_DATACONVERTER___CONVERSIONTASK___H__ -#define __OPENSPACE_APP_DATACONVERTER___CONVERSIONTASK___H__ +#ifndef __OPENSPACE_CORE___SYSTEMCAPABILITIESBINDING___H__ +#define __OPENSPACE_CORE___SYSTEMCAPABILITIESBINDING___H__ -#include +#include namespace openspace { -namespace dataconverter { +namespace scripting { -class ConversionTask { -public: - virtual void perform(const std::function& onProgress) = 0; -}; +LuaLibrary generalSystemCapabilities(); +LuaLibrary openglSystemCapabilities(); -} // namespace dataconverter +} // namespace scripting } // namespace openspace -#endif // __OPENSPACE_APP_DATACONVERTER___CONVERSIONTASK___H__ +#endif // __OPENSPACE_CORE___SYSTEMCAPABILITIESBINDING___H__ diff --git a/include/openspace/util/camera.h b/include/openspace/util/camera.h index b67d82feab..d2436ab93d 100644 --- a/include/openspace/util/camera.h +++ b/include/openspace/util/camera.h @@ -39,6 +39,7 @@ namespace openspace { class SyncBuffer; +class SceneGraphNode; /** * This class still needs some more love. Suggested improvements: @@ -92,6 +93,7 @@ public: void setRotation(Quat rotation); void setScaling(glm::vec2 scaling); void setMaxFov(float fov); + void setParent(SceneGraphNode* parent); // Relative mutators void rotate(Quat rotation); @@ -109,6 +111,7 @@ public: const Quat& rotationQuaternion() const; float maxFov() const; float sinMaxFov() const; + SceneGraphNode* parent() const; // @TODO this should simply be called viewMatrix! // Or it needs to be changed so that it actually is combined. Right now it is @@ -181,6 +184,7 @@ private: SyncData _position; SyncData _rotation; SyncData _scaling; + SceneGraphNode* _parent; // _focusPosition to be removed diff --git a/include/openspace/util/distanceconstants.h b/include/openspace/util/distanceconstants.h new file mode 100644 index 0000000000..daa2a1bba1 --- /dev/null +++ b/include/openspace/util/distanceconstants.h @@ -0,0 +1,39 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___DISTANCECONSTANTS___H__ +#define __OPENSPACE_CORE___DISTANCECONSTANTS___H__ + +namespace openspace { + +namespace distanceconstants { + const float EarthRadius = 6371; + const float LightYear = 9.4607304725808E15; + const float AstronomicalUnit = 1.495978707E11; + const float Parsec = 3.0856776E16; +} + +} + +#endif // __OPENSPACE_CORE___DISTANCECONSTANTS___H__ diff --git a/include/openspace/util/factorymanager.h b/include/openspace/util/factorymanager.h index 7b815ca065..900cbbd6ac 100644 --- a/include/openspace/util/factorymanager.h +++ b/include/openspace/util/factorymanager.h @@ -25,6 +25,8 @@ #ifndef __OPENSPACE_CORE___FACTORYMANAGER___H__ #define __OPENSPACE_CORE___FACTORYMANAGER___H__ +#include + #include #include @@ -37,7 +39,7 @@ namespace openspace { * them available through the #addFactory and #factory methods. Each * ghoul::TemplateFactory can only be added once and can be accessed by its type. */ -class FactoryManager { +class FactoryManager : public DocumentationGenerator { public: /// This exception is thrown if the ghoul::TemplateFactory could not be found in the /// #factory method @@ -55,6 +57,8 @@ public: /// The type describing the ghoul::TemplateFactory that could not be found std::string type; }; + + FactoryManager(); /** * Static initializer that initializes the static member. This needs to be done before @@ -104,17 +108,9 @@ public: template ghoul::TemplateFactory* factory() const; - /** - * Writes a documentation for the FactoryMananger that contains all of the registered - * factories and for each factory all registered class names. - * \param file The file to which the documentation will be written - * \param type The type of documentation that will be written - * \pre \p file must not be empty - * \pre \p type must not be empty - */ - void writeDocumentation(const std::string& file, const std::string& type); - private: + std::string generateJson() const override; + /// Singleton member for the Factory Manager static FactoryManager* _manager; diff --git a/include/openspace/util/factorymanager.inl b/include/openspace/util/factorymanager.inl index dde01bcef5..56034150b8 100644 --- a/include/openspace/util/factorymanager.inl +++ b/include/openspace/util/factorymanager.inl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * diff --git a/include/openspace/util/gpudata.h b/include/openspace/util/gpudata.h index 2a3af70d21..31b7ff8e03 100644 --- a/include/openspace/util/gpudata.h +++ b/include/openspace/util/gpudata.h @@ -34,9 +34,6 @@ namespace openspace { -using namespace ghoul::opengl; - - /** * Very simple class maintaining a uniform location. */ @@ -47,7 +44,7 @@ public: * Updates the uniform location of the uniform variable named * in the provided shader program. */ - void bind(ProgramObject* program, const std::string& name); + void bind(ghoul::opengl::ProgramObject* program, const std::string& name); protected: GLint _uniformLocation = -1; @@ -67,7 +64,7 @@ public: * Sets the value of T to its corresponding GPU value. * OBS! Users must ensure bind has been called before using this method */ - void setValue(ProgramObject* program, T val){ + void setValue(ghoul::opengl::ProgramObject* program, T val){ program->setUniform(_uniformLocation, val); } @@ -86,8 +83,8 @@ public: * program. * OBS! Users must ensure bind has been called before using this method. */ - void setValue(ProgramObject* program, std::shared_ptr texture){ - _texUnit = std::make_unique(); + void setValue(ghoul::opengl::ProgramObject* program, std::shared_ptr texture){ + _texUnit = std::make_unique(); _texUnit->activate(); texture->bind(); program->setUniform(_uniformLocation, *_texUnit); @@ -99,7 +96,7 @@ public: private: - std::unique_ptr _texUnit; + std::unique_ptr _texUnit; }; diff --git a/include/openspace/util/histogram.h b/include/openspace/util/histogram.h index 20ee8304cd..408cc2222c 100644 --- a/include/openspace/util/histogram.h +++ b/include/openspace/util/histogram.h @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2015-2017 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -34,7 +34,7 @@ class Histogram { public: Histogram(); Histogram(float minValue, float maxValue, int numBins); - Histogram(float minValue, float maxValue, int numBins, float *data); + Histogram(float minValue, float maxValue, int numBins, float* data); Histogram(Histogram&& other); ~Histogram(); diff --git a/include/openspace/util/keys.h b/include/openspace/util/keys.h index 8294cad88f..3f53df38bf 100644 --- a/include/openspace/util/keys.h +++ b/include/openspace/util/keys.h @@ -218,7 +218,6 @@ struct KeyWithModifier { KeyWithModifier stringToKey(std::string str); bool operator<(const KeyWithModifier& lhs, const KeyWithModifier& rhs); - static const std::map KeyModifierMapping = { { "SHIFT", KeyModifier::Shift }, { "ALT", KeyModifier::Alt }, diff --git a/include/openspace/util/openspacemodule.h b/include/openspace/util/openspacemodule.h index 992bd8459d..ee8ff15e83 100644 --- a/include/openspace/util/openspacemodule.h +++ b/include/openspace/util/openspacemodule.h @@ -27,15 +27,15 @@ #include -#include #include -#include +#include #include #include namespace openspace { +namespace documentation { struct Documentation; } /** * This class is the base class for an OpenSpace module. A module groups functionality @@ -73,7 +73,7 @@ public: * Returns a list of Documentation classes that are valid for this OpenSpaceModule. * \return A list of Documentation classes that are valid for this OpenSapceModule */ - virtual std::vector documentations() const; + virtual std::vector documentations() const; /** * Returns the Lua library with functions defined by this OpenSpaceModule. The default @@ -87,8 +87,7 @@ public: * overwritten, it returns an OpenGL version of 3.3. * \return The minimum required OpenGL version of this OpenSpaceModule */ - virtual ghoul::systemcapabilities::OpenGLCapabilitiesComponent::Version - requiredOpenGLVersion() const; + virtual ghoul::systemcapabilities::Version requiredOpenGLVersion() const; protected: /** diff --git a/include/openspace/util/powerscaledsphere.h b/include/openspace/util/powerscaledsphere.h index 0e51bb4364..7c18782b8c 100644 --- a/include/openspace/util/powerscaledsphere.h +++ b/include/openspace/util/powerscaledsphere.h @@ -38,8 +38,8 @@ public: // initializers PowerScaledSphere(const PowerScaledScalar& radius, int segments = 8); - PowerScaledSphere(properties::Vec4Property &radius, - int segments, std::string planetName); + + PowerScaledSphere(glm::vec3 radius, int segments); ~PowerScaledSphere(); PowerScaledSphere(const PowerScaledSphere& cpy); diff --git a/include/openspace/util/spicemanager.h b/include/openspace/util/spicemanager.h index 5327b8004a..158ee9562e 100644 --- a/include/openspace/util/spicemanager.h +++ b/include/openspace/util/spicemanager.h @@ -74,7 +74,7 @@ public: /** * Default constructor initializing the AberrationCorrection to Type::None with a - * Drection::Reception + * Direction::Reception */ AberrationCorrection() = default; @@ -461,6 +461,33 @@ public: AberrationCorrection aberrationCorrection, double ephemerisTime, double& lightTime) const; + /** + * Returns the \p position of a \p target body relative to an \p observer in a + * specific \p referenceFrame, optionally corrected for \p lightTime (planetary + * aberration) and stellar aberration (\p aberrationCorrection). + * \param target The target body name or the target body's NAIF ID + * \param observer The observing body name or the observing body's NAIF ID + * \param referenceFrame The reference frame of the output position vector + * \param aberrationCorrection The aberration correction used for the position + * calculation + * \param ephemerisTime The time at which the position is to be queried + * \return The position of the \p target relative to the \p observer in the specified + * \p referenceFrame + * \throws SpiceException If the \p target or \p observer do not name a valid + * NAIF object, \p referenceFrame does not name a valid reference frame or if there is + * not sufficient data available to compute the position or neither the target nor the + * observer have coverage. + * \pre \p target must not be empty. + * \pre \p observer must not be empty. + * \pre \p referenceFrame must not be empty. + * \post If an exception is thrown, \p lightTime will not be modified. + * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/spkpos_c.html + * \sa http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html + */ + glm::dvec3 targetPosition(const std::string& target, + const std::string& observer, const std::string& referenceFrame, + AberrationCorrection aberrationCorrection, double ephemerisTime) const; + /** * This method returns the transformation matrix that defines the transformation from * the reference frame \p from to the reference frame \p to. As both reference frames diff --git a/include/openspace/util/task.h b/include/openspace/util/task.h new file mode 100644 index 0000000000..dc5cc69c7f --- /dev/null +++ b/include/openspace/util/task.h @@ -0,0 +1,53 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___TASK___H__ +#define __OPENSPACE_CORE___TASK___H__ + +#include +#include + +namespace ghoul { class Dictionary; } + +namespace openspace { + +namespace documentation { struct Documentation; } + +class Task { +public: + using ProgressCallback = std::function; + + virtual ~Task() = default; + virtual void perform(const ProgressCallback& onProgress) = 0; + virtual std::string description() = 0; + + static std::unique_ptr createFromDictionary( + const ghoul::Dictionary& dictionary + ); + static documentation::Documentation documentation(); +}; + +} // namespace openspace + +#endif // __OPENSPACE_CORE___TASK___H__ diff --git a/include/openspace/util/taskloader.h b/include/openspace/util/taskloader.h new file mode 100644 index 0000000000..4081523c7d --- /dev/null +++ b/include/openspace/util/taskloader.h @@ -0,0 +1,42 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___TASKLOADER___H__ +#define __OPENSPACE_CORE___TASKLOADER___H__ + +#include +#include +#include + +namespace openspace { + +class TaskLoader { +public: + std::vector> tasksFromDictionary(const ghoul::Dictionary& dictionary); + std::vector> tasksFromFile(const std::string& path); +}; + +} // namespace openspace + +#endif // __OPENSPACE_CORE___TASKLOADER___H__ diff --git a/include/openspace/util/timemanager.h b/include/openspace/util/timemanager.h index 376e8d35e5..018765fbf6 100644 --- a/include/openspace/util/timemanager.h +++ b/include/openspace/util/timemanager.h @@ -25,6 +25,7 @@ #ifndef __OPENSPACE_CORE___TIMEMANAGER___H__ #define __OPENSPACE_CORE___TIMEMANAGER___H__ +#include #include #include @@ -35,7 +36,9 @@ public: void preSynchronization(double dt); void addKeyframe(const datamessagestructures::TimeKeyframe& kf); void removeKeyframesBefore(double timestamp); + void removeKeyframesAfter(double timestamp); void clearKeyframes(); + const std::deque& keyframes() const; private: void consumeKeyframes(double dt); std::deque _keyframes; diff --git a/include/openspace/util/timerange.h b/include/openspace/util/timerange.h index 2bd19e9274..b7739f1322 100644 --- a/include/openspace/util/timerange.h +++ b/include/openspace/util/timerange.h @@ -25,12 +25,12 @@ #ifndef __OPENSPACE_CORE___TIMERANGE___H__ #define __OPENSPACE_CORE___TIMERANGE___H__ -#include - namespace ghoul { class Dictionary; } namespace openspace { +namespace documentation { struct Documentation; } + struct TimeRange { /** @@ -70,7 +70,7 @@ struct TimeRange { bool includes(const TimeRange& o) const; - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); double start; double end; diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index 87bfff60d8..751cb25587 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -1,26 +1,26 @@ -######################################################################################### -# # -# OpenSpace # -# # -# Copyright (c) 2014-2016 # -# # -# Permission is hereby granted, free of charge, to any person obtaining a copy of this # -# software and associated documentation files (the "Software"), to deal in the Software # -# without restriction, including without limitation the rights to use, copy, modify, # -# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # -# permit persons to whom the Software is furnished to do so, subject to the following # -# conditions: # -# # -# The above copyright notice and this permission notice shall be included in all copies # -# or substantial portions of the Software. # -# # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # -# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # -# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # -# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -######################################################################################### +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2017 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +########################################################################################## include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) diff --git a/modules/base/basemodule.cpp b/modules/base/basemodule.cpp index 3a55a853fb..d0138eb781 100644 --- a/modules/base/basemodule.cpp +++ b/modules/base/basemodule.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -96,15 +97,19 @@ void BaseModule::internalInitialize() { auto fScale = FactoryManager::ref().factory(); ghoul_assert(fScale, "Scale factory was not created"); - fScale->registerClass ("StaticScale"); + fScale->registerClass("StaticScale"); auto fModelGeometry = FactoryManager::ref().factory(); ghoul_assert(fModelGeometry, "Model geometry factory was not created"); fModelGeometry->registerClass("MultiModelGeometry"); } -std::vector BaseModule::documentations() const { +std::vector BaseModule::documentations() const { return { + RenderableModel::Documentation(), + ScreenSpaceFramebuffer::Documentation(), + ScreenSpaceImage::Documentation(), + StaticRotation::Documentation(), StaticScale::Documentation(), StaticTranslation::Documentation(), RenderableTrailOrbit::Documentation(), diff --git a/modules/base/basemodule.h b/modules/base/basemodule.h index a49a4ebf8f..257cdec7ce 100644 --- a/modules/base/basemodule.h +++ b/modules/base/basemodule.h @@ -32,8 +32,8 @@ namespace openspace { class BaseModule : public OpenSpaceModule { public: BaseModule(); - - std::vector documentations() const override; + virtual ~BaseModule() = default; + std::vector documentations() const override; protected: void internalInitialize() override; diff --git a/modules/base/rendering/modelgeometry.cpp b/modules/base/rendering/modelgeometry.cpp index 3244fe062a..b74f44bd59 100644 --- a/modules/base/rendering/modelgeometry.cpp +++ b/modules/base/rendering/modelgeometry.cpp @@ -28,12 +28,13 @@ #include #include #include +#include #include namespace { - const std::string _loggerCat = "ModelGeometry"; - const std::string keyGeomModelFile = "GeometryFile"; + const char* _loggerCat = "ModelGeometry"; + const char* keyGeomModelFile = "GeometryFile"; const int8_t CurrentCacheVersion = 3; const char* keyType = "Type"; const char* keyName = "Name"; @@ -42,7 +43,7 @@ namespace { namespace openspace { namespace modelgeometry { -Documentation ModelGeometry::Documentation() { +documentation:: Documentation ModelGeometry::Documentation() { using namespace documentation; return { "Model Geometry", @@ -67,7 +68,9 @@ Documentation ModelGeometry::Documentation() { } -ModelGeometry* ModelGeometry::createFromDictionary(const ghoul::Dictionary& dictionary) { +std::unique_ptr ModelGeometry::createFromDictionary( + const ghoul::Dictionary& dictionary) +{ if (!dictionary.hasKeyAndValue(keyType)) { throw ghoul::RuntimeError("Dictionary did not contain a key 'Type'"); } @@ -75,7 +78,7 @@ ModelGeometry* ModelGeometry::createFromDictionary(const ghoul::Dictionary& dict std::string geometryType = dictionary.value(keyType); auto factory = FactoryManager::ref().factory(); - ModelGeometry* result = factory->create(geometryType, dictionary); + std::unique_ptr result = factory->create(geometryType, dictionary); if (result == nullptr) { throw ghoul::RuntimeError( "Failed to create a ModelGeometry object of type '" + geometryType + "'" @@ -85,7 +88,8 @@ ModelGeometry* ModelGeometry::createFromDictionary(const ghoul::Dictionary& dict } ModelGeometry::ModelGeometry(const ghoul::Dictionary& dictionary) - : _parent(nullptr) + : properties::PropertyOwner("ModelGeometry") + , _parent(nullptr) , _mode(GL_TRIANGLES) { documentation::testSpecificationAndThrow( @@ -94,8 +98,6 @@ ModelGeometry::ModelGeometry(const ghoul::Dictionary& dictionary) "ModelGeometry" ); - setName("ModelGeometry"); - std::string name; bool success = dictionary.getValue(keyName, name); ghoul_assert(success, "Name tag was not present"); @@ -142,7 +144,7 @@ bool ModelGeometry::initialize(Renderable* parent) { glm::pow(v.location[1], 2.f) + glm::pow(v.location[2], 2.f), maximumDistanceSquared); } - _parent->setBoundingSphere(PowerScaledScalar(glm::sqrt(maximumDistanceSquared), 0.0)); + _parent->setBoundingSphere(glm::sqrt(maximumDistanceSquared)); if (_vertices.empty()) return false; @@ -285,8 +287,7 @@ bool ModelGeometry::getIndices(std::vector* indexList) { return !(indexList->empty()); } -void ModelGeometry::setUniforms(ghoul::opengl::ProgramObject& program) { -} +void ModelGeometry::setUniforms(ghoul::opengl::ProgramObject&) {} } // namespace modelgeometry } // namespace openspace diff --git a/modules/base/rendering/modelgeometry.h b/modules/base/rendering/modelgeometry.h index 690e7271c3..508b523101 100644 --- a/modules/base/rendering/modelgeometry.h +++ b/modules/base/rendering/modelgeometry.h @@ -27,17 +27,20 @@ #include -#include #include -#include + +namespace ghoul { class Dictionary; } namespace openspace { +namespace documentation { struct Documentation; } namespace modelgeometry { class ModelGeometry : public properties::PropertyOwner { public: - static ModelGeometry* createFromDictionary(const ghoul::Dictionary& dictionary); + static std::unique_ptr createFromDictionary( + const ghoul::Dictionary& dictionary + ); struct Vertex { GLfloat location[4]; @@ -59,7 +62,7 @@ public: virtual void setUniforms(ghoul::opengl::ProgramObject& program); - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); protected: Renderable* _parent; diff --git a/modules/base/rendering/multimodelgeometry.cpp b/modules/base/rendering/multimodelgeometry.cpp index 49e5b77e43..5428bd5724 100644 --- a/modules/base/rendering/multimodelgeometry.cpp +++ b/modules/base/rendering/multimodelgeometry.cpp @@ -62,12 +62,6 @@ bool MultiModelGeometry::loadModel(const std::string& filename) { _vertices.reserve(vertices.size()); for (const auto & v : vertices) { - psc p = PowerScaledCoordinate::CreatePowerScaledCoordinate( - v.location[0], - v.location[1], - v.location[2] - ); - Vertex vv; memcpy(vv.location, v.location, sizeof(GLfloat) * 3); vv.location[3] = 1.0; diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index 2b5746f21b..d1d2cfebee 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -24,6 +24,8 @@ #include +#include +#include #include #include #include @@ -34,6 +36,7 @@ #include #include +#include #include @@ -42,19 +45,44 @@ namespace { const std::string _loggerCat = "RenderableModel"; - const char* keyGeometry = "Geometry"; + + const char* KeyGeometry = "Geometry"; + const char* KeyTexture = "Textures.Color"; + + const char* keyBody = "Body"; const char* keyStart = "StartTime"; const char* keyEnd = "EndTime"; const char* keyFading = "Shading.Fadeable"; const char* keyModelTransform = "Rotation.ModelTransform"; - //const std::string keyGhosting = "Shading.Ghosting"; - -} +} // namespace namespace openspace { +documentation::Documentation RenderableModel::Documentation() { + using namespace documentation; + return { + "RenderableModel", + "base_renderable_model", + { + { + KeyGeometry, + new ReferencingVerifier("base_geometry_model"), + "This specifies the model that is rendered by the Renderable.", + Optional::No + }, + { + KeyTexture, + new StringVerifier, + "A color texture that can be applied to the model specified bny the " + "Geometry.", + Optional::Yes + } + } + }; +} + RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _colorTexturePath("colorTexture", "Color Texture") @@ -65,44 +93,45 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary) , _texture(nullptr) , _geometry(nullptr) , _alpha(1.f) - //, _isGhost(false) , _performShading("performShading", "Perform Shading", true) , _frameCount(0) { - std::string name; - bool success = dictionary.getValue(SceneGraphNode::KeyName, name); - ghoul_assert(success, "Name was not passed to RenderableModel"); + ghoul_precondition( + dictionary.hasKeyAndValue(SceneGraphNode::KeyName), + "Name was not passed to RenderableModel" + ); - ghoul::Dictionary geometryDictionary; - success = dictionary.getValue(keyGeometry, geometryDictionary); - if (success) { - geometryDictionary.setValue(SceneGraphNode::KeyName, name); - _geometry = modelgeometry::ModelGeometry::createFromDictionary(geometryDictionary); + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableModel" + ); + + + if (dictionary.hasKey(KeyGeometry)) { + std::string name = dictionary.value(SceneGraphNode::KeyName); + ghoul::Dictionary dict = dictionary.value(KeyGeometry); + dict.setValue(SceneGraphNode::KeyName, name); + _geometry = modelgeometry::ModelGeometry::createFromDictionary(dict); } - std::string texturePath = ""; - success = dictionary.getValue("Textures.Color", texturePath); - if (success) - _colorTexturePath = absPath(texturePath); + if (dictionary.hasKey(KeyTexture)) { + _colorTexturePath = absPath(dictionary.value(KeyTexture)); + } - addPropertySubOwner(_geometry); + addPropertySubOwner(_geometry.get()); addProperty(_colorTexturePath); _colorTexturePath.onChange(std::bind(&RenderableModel::loadTexture, this)); addProperty(_debugModelRotation); - //dictionary.getValue(keySource, _source); - //dictionary.getValue(keyDestination, _destination); - if (dictionary.hasKeyAndValue(keyModelTransform)) + if (dictionary.hasKeyAndValue(keyModelTransform)) { dictionary.getValue(keyModelTransform, _modelTransform); - else + } + else { _modelTransform = glm::dmat3(1.f); - dictionary.getValue(keyBody, _target); - - //openspace::SpiceManager::ref().addFrame(_target, _source); - - //setBoundingSphere(pss(1.f, 9.f)); + } addProperty(_performShading); if (dictionary.hasKeyAndValue(keyFading)) { @@ -111,12 +140,6 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary) _performFade = fading; } addProperty(_performFade); - - //if (dictionary.hasKeyAndValue(keyGhosting)) { - // bool ghosting; - // dictionary.getValue(keyGhosting, ghosting); - // _isGhost = ghosting; - //} } bool RenderableModel::isReady() const { @@ -153,7 +176,6 @@ bool RenderableModel::initialize() { bool RenderableModel::deinitialize() { if (_geometry) { _geometry->deinitialize(); - delete _geometry; _geometry = nullptr; } _texture = nullptr; @@ -171,8 +193,6 @@ bool RenderableModel::deinitialize() { void RenderableModel::render(const RenderData& data) { _programObject->activate(); - double lt; - // Fading if (_performFade && _fading > 0.f) { _fading = _fading - 0.01f; @@ -224,9 +244,10 @@ void RenderableModel::render(const RenderData& data) { } void RenderableModel::update(const UpdateData& data) { - if (_programObject->isDirty()) + if (_programObject->isDirty()) { _programObject->rebuildFromFile(); - double _time = data.time; + } +// double _time = data.time; //if (_isGhost){ // futureTime = openspace::ImageSequencer::ref().getNextCaptureTime(); @@ -244,14 +265,13 @@ void RenderableModel::update(const UpdateData& data) { // _time = futureTime; //} - double lt; _sunPos = OsEng.renderEngine().scene()->sceneGraphNode("Sun")->worldPosition(); } void RenderableModel::loadTexture() { _texture = nullptr; if (_colorTexturePath.value() != "") { - _texture = std::move(ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath))); + _texture = ghoul::io::TextureReader::ref().loadTexture(absPath(_colorTexturePath)); if (_texture) { LDEBUG("Loaded texture from '" << absPath(_colorTexturePath) << "'"); _texture->uploadTexture(); diff --git a/modules/base/rendering/renderablemodel.h b/modules/base/rendering/renderablemodel.h index c885b8dd84..03f1798f99 100644 --- a/modules/base/rendering/renderablemodel.h +++ b/modules/base/rendering/renderablemodel.h @@ -36,8 +36,12 @@ #include #include +#include + namespace openspace { +namespace documentation { struct Documentation; } + namespace modelgeometry { class ModelGeometry; } @@ -54,6 +58,7 @@ public: void render(const RenderData& data) override; void update(const UpdateData& data) override; + static documentation::Documentation Documentation(); protected: void loadTexture(); @@ -65,18 +70,12 @@ private: std::unique_ptr _programObject; std::unique_ptr _texture; - modelgeometry::ModelGeometry* _geometry; + std::unique_ptr _geometry; glm::dmat3 _modelTransform; float _alpha; - //glm::dmat3 _stateMatrix; - //std::string _source; - //std::string _destination; - std::string _target; - - //bool _isGhost; int _frameCount; glm::dvec3 _sunPos; diff --git a/modules/base/rendering/renderablepath.cpp b/modules/base/rendering/renderablepath.cpp index ebea0891cb..081abb3b9f 100644 --- a/modules/base/rendering/renderablepath.cpp +++ b/modules/base/rendering/renderablepath.cpp @@ -76,7 +76,7 @@ RenderablePath::RenderablePath(const ghoul::Dictionary& dictionary) float fPointSteps; // Dictionary can not pick out ints... if (!dictionary.getValue(keyPointSteps, fPointSteps)) fPointSteps = 4; - _pointSteps = fPointSteps; + _pointSteps = static_cast(fPointSteps); glm::vec3 color(0.f); if (dictionary.hasKeyAndValue(keyColor)) @@ -145,7 +145,7 @@ void RenderablePath::render(const RenderData& data) { return; - int nPointsToDraw = _vertexArray.size();// (time - _start) / (_stop - _start) * (_vertexArray.size()) + 1 + 0.5; + size_t nPointsToDraw = _vertexArray.size();// (time - _start) / (_stop - _start) * (_vertexArray.size()) + 1 + 0.5; _programObject->activate(); diff --git a/modules/base/rendering/renderableplane.cpp b/modules/base/rendering/renderableplane.cpp index 744c94e83e..25e80ffd59 100644 --- a/modules/base/rendering/renderableplane.cpp +++ b/modules/base/rendering/renderableplane.cpp @@ -55,7 +55,7 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) , _texturePath("texture", "Texture") , _billboard("billboard", "Billboard", false) , _projectionListener("projectionListener", "DisplayProjections", false) - , _size("size", "Size", glm::vec2(1,1), glm::vec2(0.f), glm::vec2(1.f, 25.f)) + , _size("size", "Size", 10, 0, std::pow(10, 25)) , _origin(Origin::Center) , _shader(nullptr) , _textureIsDirty(false) @@ -64,9 +64,7 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) , _quad(0) , _vertexPositionBuffer(0) { - glm::vec2 size; - dictionary.getValue("Size", size); - _size = size; + dictionary.getValue("Size", _size); if (dictionary.hasKey("Name")) { dictionary.getValue("Name", _nodeName); @@ -127,7 +125,7 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) //_size.onChange(std::bind(&RenderablePlane::createPlane, this)); _size.onChange([this](){ _planeIsDirty = true; }); - setBoundingSphere(_size.value()); + setBoundingSphere(_size); } RenderablePlane::~RenderablePlane() { @@ -203,9 +201,9 @@ void RenderablePlane::render(const RenderData& data) { if (textureNode != nullptr){ RenderablePlanetProjection* t = static_cast(textureNode->renderable()); _texture = std::unique_ptr(&(t->baseTexture())); - float h = _texture->height(); - float w = _texture->width(); - float scale = h / w; + unsigned int h = _texture->height(); + unsigned int w = _texture->width(); + float scale = static_cast(h) / static_cast(w); scaleTransform = glm::scale(glm::mat4(1.0), glm::vec3(1.f, scale, 1.f)); } } @@ -263,7 +261,7 @@ void RenderablePlane::render(const RenderData& data) { _shader->deactivate(); } -void RenderablePlane::update(const UpdateData& data) { +void RenderablePlane::update(const UpdateData&) { if (_shader->isDirty()) _shader->rebuildFromFile(); @@ -299,16 +297,15 @@ void RenderablePlane::createPlane() { // ============================ // GEOMETRY (quad) // ============================ - const GLfloat size = _size.value()[0]; - const GLfloat w = _size.value()[1]; + const GLfloat size = _size; const GLfloat vertex_data[] = { // x y z w s t - -size, -size, 0.f, w, 0.f, 0.f, - size, size, 0.f, w, 1.f, 1.f, - -size, size, 0.f, w, 0.f, 1.f, - -size, -size, 0.f, w, 0.f, 0.f, - size, -size, 0.f, w, 1.f, 0.f, - size, size, 0.f, w, 1.f, 1.f, + -size, -size, 0.f, 0.f, 0.f, 0.f, + size, size, 0.f, 0.f, 1.f, 1.f, + -size, size, 0.f, 0.f, 0.f, 1.f, + -size, -size, 0.f, 0.f, 0.f, 0.f, + size, -size, 0.f, 0.f, 1.f, 0.f, + size, size, 0.f, 0.f, 1.f, 1.f, }; glBindVertexArray(_quad); // bind array diff --git a/modules/base/rendering/renderableplane.h b/modules/base/rendering/renderableplane.h index 3c26807882..a14e340f9e 100644 --- a/modules/base/rendering/renderableplane.h +++ b/modules/base/rendering/renderableplane.h @@ -29,7 +29,6 @@ #include #include -#include #include namespace ghoul { @@ -75,7 +74,7 @@ private: properties::StringProperty _texturePath; properties::BoolProperty _billboard; properties::BoolProperty _projectionListener; - properties::Vec2Property _size; + properties::FloatProperty _size; Origin _origin; std::string _nodeName; diff --git a/modules/base/rendering/renderablesphere.cpp b/modules/base/rendering/renderablesphere.cpp index 5453db84c6..3383aa594b 100644 --- a/modules/base/rendering/renderablesphere.cpp +++ b/modules/base/rendering/renderablesphere.cpp @@ -178,7 +178,7 @@ void RenderableSphere::render(const RenderData& data) { _shader->deactivate(); } -void RenderableSphere::update(const UpdateData& data) { +void RenderableSphere::update(const UpdateData&) { if (_shader->isDirty()) _shader->rebuildFromFile(); diff --git a/modules/base/rendering/renderablesphericalgrid.cpp b/modules/base/rendering/renderablesphericalgrid.cpp index 4af5bc3a82..7a3ad7d2e6 100644 --- a/modules/base/rendering/renderablesphericalgrid.cpp +++ b/modules/base/rendering/renderablesphericalgrid.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #define _USE_MATH_DEFINES #include @@ -39,12 +40,10 @@ namespace { const char* KeyGridSegments = "GridSegments"; const char* KeyGridRadius = "GridRadius"; const char* KeyGridParentsRotation = "ParentsRotation"; + const glm::vec2 GridRadius = { 1.f, 20.f }; } namespace openspace { -// needs to be set from dictionary - REMEMBER -const PowerScaledScalar radius = PowerScaledScalar(1.f, 20.f); - RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _gridProgram(nullptr) @@ -78,14 +77,14 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio int nr = 0; const float fsegments = static_cast(_segments); - const float r = static_cast(radius[0]); + const float r = static_cast(GridRadius[0]); //int nr2 = 0; - for (int i = 0; i <= _segments; i++) { + for (int nSegment = 0; nSegment <= _segments; ++nSegment) { // define an extra vertex around the y-axis due to texture mapping for (int j = 0; j <= _segments; j++) { - const float fi = static_cast(i); + const float fi = static_cast(nSegment); const float fj = static_cast(j); // inclination angle (north to south) @@ -117,7 +116,7 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio _varray[nr].location[i] = tmp[i]; _varray[nr].normal[i] = normal[i]; } - _varray[nr].location[3] = static_cast(radius[1]); + _varray[nr].location[3] = static_cast(GridRadius[1]); ++nr; } } diff --git a/modules/base/rendering/renderablesphericalgrid.h b/modules/base/rendering/renderablesphericalgrid.h index 1980018c48..f5290bc1d5 100644 --- a/modules/base/rendering/renderablesphericalgrid.h +++ b/modules/base/rendering/renderablesphericalgrid.h @@ -62,7 +62,6 @@ protected: bool staticGrid; std::string _parentsRotation; glm::dmat3 _parentMatrix; - PowerScaledScalar _radius; GLuint _vaoID = 3; GLuint _vBufferID = 4; diff --git a/modules/base/rendering/renderabletrail.cpp b/modules/base/rendering/renderabletrail.cpp index 59b16a2ec5..4dd118eb1b 100644 --- a/modules/base/rendering/renderabletrail.cpp +++ b/modules/base/rendering/renderabletrail.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -56,8 +57,8 @@ namespace { namespace openspace { -Documentation RenderableTrail::Documentation() { -using namespace documentation; +documentation::Documentation RenderableTrail::Documentation() { + using namespace documentation; return { "RenderableTrail", "base_renderable_renderabletrail", @@ -154,17 +155,17 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary) addProperty(_useLineFade); if (dictionary.hasKeyAndValue(KeyFade)) { - _lineFade = dictionary.value(KeyFade); + _lineFade = static_cast(dictionary.value(KeyFade)); } addProperty(_lineFade); if (dictionary.hasKeyAndValue(KeyLineWidth)) { - _lineWidth = dictionary.value(KeyLineWidth); + _lineWidth = static_cast(dictionary.value(KeyLineWidth)); } addProperty(_lineWidth); if (dictionary.hasKeyAndValue(KeyPointSize)) { - _pointSize = dictionary.value(KeyPointSize); + _pointSize = static_cast(dictionary.value(KeyPointSize)); } addProperty(_pointSize); @@ -246,12 +247,12 @@ void RenderableTrail::render(const RenderData & data) { } bool renderLines = - _renderingModes == RenderingModeLines | - _renderingModes == RenderingModeLinesPoints; + (_renderingModes == RenderingModeLines) | + (_renderingModes == RenderingModeLinesPoints); bool renderPoints = - _renderingModes == RenderingModePoints | - _renderingModes == RenderingModeLinesPoints; + (_renderingModes == RenderingModePoints) | + (_renderingModes == RenderingModeLinesPoints); if (renderLines) { glLineWidth(_lineWidth); diff --git a/modules/base/rendering/renderabletrail.h b/modules/base/rendering/renderabletrail.h index 661c7524ad..c8a73fdb10 100644 --- a/modules/base/rendering/renderabletrail.h +++ b/modules/base/rendering/renderabletrail.h @@ -27,7 +27,6 @@ #include -#include #include #include #include @@ -41,11 +40,13 @@ namespace ghoul { namespace opengl { class ProgramObject; class Texture; -} -} +} // namespace opengl +} // namespace ghoul namespace openspace { +namespace documentation { struct Documentation; } + class Translation; /** @@ -89,7 +90,7 @@ protected: explicit RenderableTrail(const ghoul::Dictionary& dictionary); /// Returns the documentation entries that the con - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); /// The layout of the VBOs struct TrailVBOLayout { diff --git a/modules/base/rendering/renderabletrailorbit.cpp b/modules/base/rendering/renderabletrailorbit.cpp index 422d4eb8ce..2f21fd320a 100644 --- a/modules/base/rendering/renderabletrailorbit.cpp +++ b/modules/base/rendering/renderabletrailorbit.cpp @@ -24,6 +24,7 @@ #include +#include #include #include @@ -83,9 +84,9 @@ namespace { namespace openspace { -openspace::Documentation RenderableTrailOrbit::Documentation() { +documentation::Documentation RenderableTrailOrbit::Documentation() { using namespace documentation; - openspace::Documentation doc{ + documentation::Documentation doc { "RenderableTrailOrbit", "base_renderable_renderabletrailorbit", { @@ -118,7 +119,7 @@ openspace::Documentation RenderableTrailOrbit::Documentation() { // Insert the parents documentation entries until we have a verifier that can deal // with class hierarchy - openspace::Documentation parentDoc = RenderableTrail::Documentation(); + documentation::Documentation parentDoc = RenderableTrail::Documentation(); doc.entries.insert( doc.entries.end(), parentDoc.entries.begin(), @@ -131,7 +132,7 @@ openspace::Documentation RenderableTrailOrbit::Documentation() { RenderableTrailOrbit::RenderableTrailOrbit(const ghoul::Dictionary& dictionary) : RenderableTrail(dictionary) , _period("period", "Period in days", 0.0, 0.0, 1e9) - , _resolution("resolution", "Number of Samples along Orbit", 10000, 1, 1e6) + , _resolution("resolution", "Number of Samples along Orbit", 10000, 1, 1000000) , _needsFullSweep(true) , _indexBufferDirty(true) { @@ -147,7 +148,7 @@ RenderableTrailOrbit::RenderableTrailOrbit(const ghoul::Dictionary& dictionary) // Period is in days using namespace std::chrono; - int factor = duration_cast(hours(24)).count(); + long long factor = duration_cast(hours(24)).count(); _period = dictionary.value(KeyPeriod) * factor; _period.onChange([&] { _needsFullSweep = true; _indexBufferDirty = true; }); addProperty(_period); @@ -336,19 +337,19 @@ RenderableTrailOrbit::UpdateReport RenderableTrailOrbit::updateTrails( // This might become a bigger issue if we are starting to look at very short time // intervals const double Epsilon = 1e-7; - if (abs(delta) < Epsilon) { + if (std::abs(delta) < Epsilon) { return { false, 0 }; } if (delta > 0.0) { // Check whether we need to drop a new permanent point. This is only the case if // enough (> secondsPerPoint) time has passed since the last permanent point - if (abs(delta) < secondsPerPoint) { + if (std::abs(delta) < secondsPerPoint) { return { false, 0 }; } // See how many points we need to drop - int nNewPoints = floor(delta / secondsPerPoint); + int nNewPoints = static_cast(floor(delta / secondsPerPoint)); // If we would need to generate more new points than there are total points in the // array, it is faster to regenerate the entire array @@ -383,7 +384,7 @@ RenderableTrailOrbit::UpdateReport RenderableTrailOrbit::updateTrails( else { // See how many new points needs to be generated. Delta is negative, so we need // to invert the ratio - int nNewPoints = -(floor(delta / secondsPerPoint)); + int nNewPoints = -(static_cast(floor(delta / secondsPerPoint))); // If we would need to generate more new points than there are total points in the // array, it is faster to regenerate the entire array diff --git a/modules/base/rendering/renderabletrailorbit.h b/modules/base/rendering/renderabletrailorbit.h index 66703e1c76..5bcd5b0887 100644 --- a/modules/base/rendering/renderabletrailorbit.h +++ b/modules/base/rendering/renderabletrailorbit.h @@ -27,12 +27,13 @@ #include -#include #include #include namespace openspace { +namespace documentation { struct Documentation; } + /** * This concrete implementation of a RenderableTrail renders an updated trail behind an * object that is likely to have an orbit-like path. However, this is not required and @@ -52,7 +53,7 @@ public: void update(const UpdateData& data) override; - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); private: /** diff --git a/modules/base/rendering/renderabletrailtrajectory.cpp b/modules/base/rendering/renderabletrailtrajectory.cpp index 2e987f592a..25f5fc686d 100644 --- a/modules/base/rendering/renderabletrailtrajectory.cpp +++ b/modules/base/rendering/renderabletrailtrajectory.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -51,9 +52,10 @@ namespace { namespace openspace { -openspace::Documentation RenderableTrailTrajectory::Documentation() { +documentation::Documentation RenderableTrailTrajectory::Documentation() { using namespace documentation; - openspace::Documentation doc { + + documentation::Documentation doc { "RenderableTrailTrajectory", "base_renderable_renderabletrailtrajectory", { @@ -110,7 +112,7 @@ openspace::Documentation RenderableTrailTrajectory::Documentation() { // Insert the parents documentation entries until we have a verifier that can deal // with class hierarchy - openspace::Documentation parentDoc = RenderableTrail::Documentation(); + documentation::Documentation parentDoc = RenderableTrail::Documentation(); doc.entries.insert( doc.entries.end(), parentDoc.entries.begin(), @@ -128,7 +130,7 @@ RenderableTrailTrajectory::RenderableTrailTrajectory(const ghoul::Dictionary& di , _timeStampSubsamplingFactor( "subSample", "Time Stamp Subsampling Factor", - 1, 1, 1e9 + 1, 1, 1000000000 ) , _renderFullTrail("renderFullTrail", "Render Full Trail", false) , _needsFullSweep(true) @@ -157,7 +159,9 @@ RenderableTrailTrajectory::RenderableTrailTrajectory(const ghoul::Dictionary& di addProperty(_sampleInterval); if (dictionary.hasKeyAndValue(KeyTimeStampSubsample)) { - _timeStampSubsamplingFactor = dictionary.value(KeyTimeStampSubsample); + _timeStampSubsamplingFactor = static_cast( + dictionary.value(KeyTimeStampSubsample) + ); } _timeStampSubsamplingFactor.onChange([this] { _subsamplingIsDirty = true; }); addProperty(_timeStampSubsamplingFactor); @@ -206,7 +210,7 @@ void RenderableTrailTrajectory::update(const UpdateData& data) { double totalSampleInterval = _sampleInterval / _timeStampSubsamplingFactor; // How many values do we need to compute given the distance between the start and // end date and the desired sample interval - int nValues = (_end - _start) / totalSampleInterval; + int nValues = static_cast((_end - _start) / totalSampleInterval); // Make space for the vertices _vertexArray.clear(); @@ -244,16 +248,16 @@ void RenderableTrailTrajectory::update(const UpdateData& data) { // If the full trail should be rendered at all times, we can directly render the // entire set _primaryRenderInformation.first = 0; - _primaryRenderInformation.count = _vertexArray.size(); + _primaryRenderInformation.count = static_cast(_vertexArray.size()); } else { // If only trail so far should be rendered, we need to find the corresponding time // in the array and only render it until then _primaryRenderInformation.first = 0; double t = (data.time - _start) / (_end - _start); - _primaryRenderInformation.count = std::min( - ceil(_vertexArray.size() * t), - _vertexArray.size() - 1 + _primaryRenderInformation.count = std::min( + static_cast(ceil(_vertexArray.size() * t)), + static_cast(_vertexArray.size() - 1) ); } diff --git a/modules/base/rendering/renderabletrailtrajectory.h b/modules/base/rendering/renderabletrailtrajectory.h index 2d3d8cf12a..2e02ee6f3a 100644 --- a/modules/base/rendering/renderabletrailtrajectory.h +++ b/modules/base/rendering/renderabletrailtrajectory.h @@ -27,7 +27,6 @@ #include -#include #include #include #include @@ -35,6 +34,8 @@ namespace openspace { +namespace documentation { struct Documentation; } + /** * This concrete implementation of a RenderableTrail renders a fixed trail, regardless of * its shape. The trail is sampled equitemporal (with an interval of _sampleInterval in @@ -55,7 +56,7 @@ public: void update(const UpdateData& data) override; - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); private: /// The start time of the trail diff --git a/modules/base/rendering/screenspaceframebuffer.cpp b/modules/base/rendering/screenspaceframebuffer.cpp index 630bb6d39b..1f4d6fe118 100644 --- a/modules/base/rendering/screenspaceframebuffer.cpp +++ b/modules/base/rendering/screenspaceframebuffer.cpp @@ -23,6 +23,8 @@ ****************************************************************************************/ #include + +#include #include #include #include @@ -34,11 +36,27 @@ namespace openspace { +documentation::Documentation ScreenSpaceFramebuffer::Documentation() { + using namespace documentation; + return { + "ScreenSpace Framebuffer", + "base_screenspace_framebuffer", + {}, + Exhaustive::Yes + }; +} + ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictionary) : ScreenSpaceRenderable(dictionary) , _size("size", "Size", glm::vec4(0), glm::vec4(0), glm::vec4(2000)) , _framebuffer(nullptr) { + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "ScreenSpaceFramebuffer" + ); + _id = id(); setName("ScreenSpaceFramebuffer" + std::to_string(_id)); @@ -82,15 +100,20 @@ bool ScreenSpaceFramebuffer::deinitialize(){ return true; } -void ScreenSpaceFramebuffer::render(){ +void ScreenSpaceFramebuffer::render() { glm::vec2 resolution = OsEng.windowWrapper().currentWindowResolution(); glm::vec4 size = _size.value(); float xratio = _originalViewportSize.x / (size.z-size.x); float yratio = _originalViewportSize.y / (size.w-size.y);; - if(!_renderFunctions.empty()){ - glViewport (-size.x*xratio, -size.y*yratio, _originalViewportSize.x*xratio, _originalViewportSize.y*yratio); + if (!_renderFunctions.empty()) { + glViewport( + static_cast(-size.x * xratio), + static_cast(-size.y * yratio), + static_cast(_originalViewportSize.x * xratio), + static_cast(_originalViewportSize.y * yratio) + ); GLint defaultFBO = _framebuffer->getActiveObject(); _framebuffer->activate(); @@ -103,7 +126,12 @@ void ScreenSpaceFramebuffer::render(){ _framebuffer->deactivate(); glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); - glViewport (0, 0, resolution.x, resolution.y); + glViewport( + 0, + 0, + static_cast(resolution.x), + static_cast(resolution.y) + ); glm::mat4 rotation = rotationMatrix(); glm::mat4 translation = translationMatrix(); diff --git a/modules/base/rendering/screenspaceframebuffer.h b/modules/base/rendering/screenspaceframebuffer.h index 33a04a3655..772e19e99b 100644 --- a/modules/base/rendering/screenspaceframebuffer.h +++ b/modules/base/rendering/screenspaceframebuffer.h @@ -34,6 +34,9 @@ #include namespace openspace { + +namespace documentation { struct Documentation; } + /** * @brief Creates a texture by rendering to a framebuffer, this is then used on a screen space plane. * @details This class lets you ass renderfunctions that should render to a framebuffer with an attached texture. @@ -54,6 +57,8 @@ public: void addRenderFunction(std::shared_ptr> renderFunction); void removeAllRenderFunctions(); + static documentation::Documentation Documentation(); + private: void createFragmentbuffer(); static int id(); diff --git a/modules/base/rendering/screenspaceimage.cpp b/modules/base/rendering/screenspaceimage.cpp index d5822c567c..7d81e60faa 100644 --- a/modules/base/rendering/screenspaceimage.cpp +++ b/modules/base/rendering/screenspaceimage.cpp @@ -24,6 +24,9 @@ #include +#include +#include + #include #include #include @@ -33,43 +36,69 @@ #include namespace { - const std::string _loggerCat = "ScreenSpaceImage"; - const char* KeyName = "Name"; const char* KeyTexturePath = "TexturePath"; const char* KeyUrl = "URL"; -} +} // namespace namespace openspace { +documentation::Documentation ScreenSpaceImage::Documentation() { + using namespace openspace::documentation; + return { + "ScreenSpace Image", + "base_screenspace_image", + { + { + KeyName, + new StringVerifier, + "Specifies the GUI name of the ScreenspaceImage", + Optional::Yes + }, + { + KeyTexturePath, + new StringVerifier, + "Specifies the image that is shown on the screenspace-aligned plane. If " + "this value is set and the URL is not, the disk image is used.", + Optional::Yes + } + } + }; +} + ScreenSpaceImage::ScreenSpaceImage(const ghoul::Dictionary& dictionary) : ScreenSpaceRenderable(dictionary) - , _texturePath("texturePath", "Texture path", "") , _downloadImage(false) + , _textureIsDirty(false) + , _texturePath("texturePath", "Texture path", "") { - std::string name; - if (dictionary.getValue(KeyName, name)) { - setName(name); - } else { + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "ScreenSpaceImage" + ); + + if (dictionary.hasKey(KeyName)) { + setName(dictionary.value(KeyName)); + } + else { static int id = 0; setName("ScreenSpaceImage " + std::to_string(id)); ++id; } - addProperty(_texturePath); - std::string texturePath; if (dictionary.getValue(KeyTexturePath, texturePath)) { - _texturePath = texturePath; - _texturePath.onChange([this](){ loadTexture(); }); + _texturePath = dictionary.value(KeyTexturePath); } if (dictionary.getValue(KeyUrl, _url)) { _downloadImage = true; } -} -ScreenSpaceImage::~ScreenSpaceImage() {} + _texturePath.onChange([this]() { _textureIsDirty = true; }); + addProperty(_texturePath); +} bool ScreenSpaceImage::initialize() { _originalViewportSize = OsEng.windowWrapper().currentWindowResolution(); @@ -82,7 +111,6 @@ bool ScreenSpaceImage::initialize() { } bool ScreenSpaceImage::deinitialize() { - glDeleteVertexArrays(1, &_quad); _quad = 0; @@ -106,7 +134,7 @@ void ScreenSpaceImage::render() { void ScreenSpaceImage::update() { bool download = _downloadImage ? (_futureImage.valid() && DownloadManager::futureReady(_futureImage)) : true; - if (download) { + if (download && _textureIsDirty) { loadTexture(); } } @@ -118,9 +146,9 @@ bool ScreenSpaceImage::isReady() const { void ScreenSpaceImage::loadTexture() { std::unique_ptr texture = nullptr; if (!_downloadImage) - texture = std::move(loadFromDisk()); + texture = loadFromDisk(); else - texture = std::move(loadFromMemory()); + texture = loadFromMemory(); if (texture) { // LDEBUG("Loaded texture from '" << absPath(_texturePath) << "'"); @@ -130,6 +158,7 @@ void ScreenSpaceImage::loadTexture() { texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); _texture = std::move(texture); + _textureIsDirty = false; } } @@ -157,30 +186,39 @@ void ScreenSpaceImage::updateTexture() { if (_futureImage.valid() && DownloadManager::futureReady(_futureImage)) { DownloadManager::MemoryFile imageFile = _futureImage.get(); - if (imageFile.corrupted) + if (imageFile.corrupted) { return nullptr; + } return (ghoul::io::TextureReader::ref().loadTexture( reinterpret_cast(imageFile.buffer), imageFile.size, imageFile.format) ); - + } + else { + return nullptr; } } std::future ScreenSpaceImage::downloadImageToMemory( std::string url) { - return std::move(OsEng.downloadManager().fetchFile( + return OsEng.downloadManager().fetchFile( url, - [url](const DownloadManager::MemoryFile& file) { - LDEBUG("Download to memory finished for screen space image"); + [url](const DownloadManager::MemoryFile&) { + LDEBUGC( + "ScreenSpaceImage", + "Download to memory finished for screen space image" + ); }, [url](const std::string& err) { - LDEBUG("Download to memory failer for screen space image: " +err); + LDEBUGC( + "ScreenSpaceImage", + "Download to memory failer for screen space image: " + err + ); } - )); + ); } } // namespace openspace diff --git a/modules/base/rendering/screenspaceimage.h b/modules/base/rendering/screenspaceimage.h index 7316722608..9130627ee9 100644 --- a/modules/base/rendering/screenspaceimage.h +++ b/modules/base/rendering/screenspaceimage.h @@ -33,11 +33,12 @@ #include namespace openspace { + +namespace documentation { struct Documentation; } class ScreenSpaceImage : public ScreenSpaceRenderable { public: ScreenSpaceImage(const ghoul::Dictionary& dictionary); - ~ScreenSpaceImage(); bool initialize() override; bool deinitialize() override; @@ -45,12 +46,15 @@ public: void update() override; bool isReady() const override; + static documentation::Documentation Documentation(); + protected: void loadTexture(); void updateTexture(); std::string _url; bool _downloadImage; + bool _textureIsDirty; std::future _futureImage; private: @@ -59,6 +63,8 @@ private: std::unique_ptr loadFromMemory(); properties::StringProperty _texturePath; + + }; } // namespace openspace diff --git a/modules/base/rotation/staticrotation.cpp b/modules/base/rotation/staticrotation.cpp index 39d4cd4232..e8aa408dd8 100644 --- a/modules/base/rotation/staticrotation.cpp +++ b/modules/base/rotation/staticrotation.cpp @@ -24,6 +24,7 @@ #include +#include #include namespace { @@ -32,7 +33,7 @@ namespace { namespace openspace { -Documentation StaticRotation::Documentation() { +documentation::Documentation StaticRotation::Documentation() { using namespace openspace::documentation; return { "Static Rotation", diff --git a/modules/base/rotation/staticrotation.h b/modules/base/rotation/staticrotation.h index 7cf5f7af8f..f03fa79681 100644 --- a/modules/base/rotation/staticrotation.h +++ b/modules/base/rotation/staticrotation.h @@ -27,17 +27,18 @@ #include -#include #include namespace openspace { +namespace documentation { struct Documentation; } + class StaticRotation : public Rotation { public: StaticRotation(); StaticRotation(const ghoul::Dictionary& dictionary); - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); private: properties::DMat3Property _rotationMatrix; diff --git a/modules/base/scale/staticscale.cpp b/modules/base/scale/staticscale.cpp index b546751f72..6eb819e419 100644 --- a/modules/base/scale/staticscale.cpp +++ b/modules/base/scale/staticscale.cpp @@ -24,25 +24,27 @@ #include +#include #include namespace { - const char* _loggerCat = "StaticScale"; const char* KeyValue = "Scale"; } namespace openspace { -Documentation StaticScale::Documentation() { +documentation::Documentation StaticScale::Documentation() { using namespace openspace::documentation; return { "Static Scaling", "base_scale_static", - {{ - KeyValue, - new DoubleVerifier, - "The scaling factor by which the scenegraph node is scaled." - }} + { + { + KeyValue, + new DoubleVerifier, + "The scaling factor by which the scenegraph node is scaled." + } + } }; } @@ -58,7 +60,7 @@ StaticScale::StaticScale(const ghoul::Dictionary& dictionary) { documentation::testSpecificationAndThrow(Documentation(), dictionary, "StaticScale"); - _scaleValue = dictionary.value(KeyValue); + _scaleValue = static_cast(dictionary.value(KeyValue)); } double StaticScale::scaleValue() const { diff --git a/modules/base/scale/staticscale.h b/modules/base/scale/staticscale.h index f7be8ecfeb..d2c14ab760 100644 --- a/modules/base/scale/staticscale.h +++ b/modules/base/scale/staticscale.h @@ -27,18 +27,19 @@ #include -#include #include namespace openspace { +namespace documentation { struct Documentation; } + class StaticScale : public Scale { public: StaticScale(); StaticScale(const ghoul::Dictionary& dictionary); double scaleValue() const; - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); private: properties::FloatProperty _scaleValue; diff --git a/modules/base/shaders/pscstandard_fs.glsl b/modules/base/shaders/pscstandard_fs.glsl index c32305121c..8eb494e4d5 100644 --- a/modules/base/shaders/pscstandard_fs.glsl +++ b/modules/base/shaders/pscstandard_fs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * diff --git a/modules/base/shaders/pscstandard_vs.glsl b/modules/base/shaders/pscstandard_vs.glsl index 030d74cc15..936d7cece4 100644 --- a/modules/base/shaders/pscstandard_vs.glsl +++ b/modules/base/shaders/pscstandard_vs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -54,4 +54,4 @@ void main() vs_position = tmp; position = ViewProjection * position; gl_Position = z_normalization(position); -} \ No newline at end of file +} diff --git a/modules/base/shaders/screenspace_fs.glsl b/modules/base/shaders/screenspace_fs.glsl index 9ab37b56af..22b09a4987 100644 --- a/modules/base/shaders/screenspace_fs.glsl +++ b/modules/base/shaders/screenspace_fs.glsl @@ -1,27 +1,27 @@ /***************************************************************************************** -* * -* OpenSpace * -* * -* Copyright (c) 2014-2016 * -* * -* Permission is hereby granted, free of charge, to any person obtaining a copy of this * -* software and associated documentation files (the "Software"), to deal in the Software * -* without restriction, including without limitation the rights to use, copy, modify, * -* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * -* permit persons to whom the Software is furnished to do so, subject to the following * -* conditions: * -* * -* The above copyright notice and this permission notice shall be included in all copies * -* or substantial portions of the Software. * -* * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * -* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * -* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * -* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * -****************************************************************************************/ -//#version __CONTEXT__ + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + uniform sampler2D texture1; uniform float OcclusionDepth; uniform float Alpha; diff --git a/modules/base/shaders/screenspace_vs.glsl b/modules/base/shaders/screenspace_vs.glsl index 02849b3537..cdeafae745 100644 --- a/modules/base/shaders/screenspace_vs.glsl +++ b/modules/base/shaders/screenspace_vs.glsl @@ -1,27 +1,26 @@ - /***************************************************************************************** -* * -* OpenSpace * -* * -* Copyright (c) 2014-2016 * -* * -* Permission is hereby granted, free of charge, to any person obtaining a copy of this * -* software and associated documentation files (the "Software"), to deal in the Software * -* without restriction, including without limitation the rights to use, copy, modify, * -* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * -* permit persons to whom the Software is furnished to do so, subject to the following * -* conditions: * -* * -* The above copyright notice and this permission notice shall be included in all copies * -* or substantial portions of the Software. * -* * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * -* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * -* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * -* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * -****************************************************************************************/ + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #version __CONTEXT__ diff --git a/modules/base/translation/statictranslation.cpp b/modules/base/translation/statictranslation.cpp index 3cabdbf7b5..069c64e10e 100644 --- a/modules/base/translation/statictranslation.cpp +++ b/modules/base/translation/statictranslation.cpp @@ -24,6 +24,7 @@ #include +#include #include namespace { @@ -32,8 +33,8 @@ namespace { namespace openspace { -Documentation StaticTranslation::Documentation() { - using namespace openspace::documentation; +documentation::Documentation StaticTranslation::Documentation() { + using namespace documentation; return { "Static Translation", "base_transform_translation_static", @@ -81,8 +82,6 @@ StaticTranslation::StaticTranslation(const ghoul::Dictionary& dictionary) _position = dictionary.value(KeyPosition); } -StaticTranslation::~StaticTranslation() {} - glm::dvec3 StaticTranslation::position() const { return _position; } diff --git a/modules/base/translation/statictranslation.h b/modules/base/translation/statictranslation.h index d5c1f64a48..fd92a76645 100644 --- a/modules/base/translation/statictranslation.h +++ b/modules/base/translation/statictranslation.h @@ -27,20 +27,20 @@ #include -#include #include namespace openspace { + +namespace documentation { struct Documentation; } class StaticTranslation : public Translation { public: StaticTranslation(); StaticTranslation(const ghoul::Dictionary& dictionary); - virtual ~StaticTranslation(); virtual glm::dvec3 position() const; virtual void update(const UpdateData& data) override; - static openspace::Documentation Documentation(); + static documentation::Documentation Documentation(); private: properties::DVec3Property _position; diff --git a/modules/debugging/CMakeLists.txt b/modules/debugging/CMakeLists.txt index a79423ab84..0b2400b4f9 100644 --- a/modules/debugging/CMakeLists.txt +++ b/modules/debugging/CMakeLists.txt @@ -1,26 +1,26 @@ -######################################################################################### -# # -# OpenSpace # -# # -# Copyright (c) 2014-2016 # -# # -# Permission is hereby granted, free of charge, to any person obtaining a copy of this # -# software and associated documentation files (the "Software"), to deal in the Software # -# without restriction, including without limitation the rights to use, copy, modify, # -# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # -# permit persons to whom the Software is furnished to do so, subject to the following # -# conditions: # -# # -# The above copyright notice and this permission notice shall be included in all copies # -# or substantial portions of the Software. # -# # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # -# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # -# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # -# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -######################################################################################### +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2017 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +########################################################################################## include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) diff --git a/modules/debugging/rendering/debugrenderer.cpp b/modules/debugging/rendering/debugrenderer.cpp index 3f028ecb6a..a84a0ff170 100644 --- a/modules/debugging/rendering/debugrenderer.cpp +++ b/modules/debugging/rendering/debugrenderer.cpp @@ -111,7 +111,7 @@ void DebugRenderer::renderVertices(const Vertices& clippingSpacePoints, GLenum m glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(clippingSpacePoints[0]), 0); // Draw the vertices - glDrawArrays(mode, 0, clippingSpacePoints.size()); + glDrawArrays(mode, 0, static_cast(clippingSpacePoints.size())); // Check for errors GLenum error = glGetError(); @@ -200,7 +200,7 @@ void DebugRenderer::renderCameraFrustum(const RenderData& data, const Camera& ot RGBA rgba) const { using namespace glm; - dmat4 modelTransform = translate(dmat4(1), data.position.dvec3()); +// dmat4 modelTransform = translate(dmat4(1), data.position.dvec3()); dmat4 viewTransform = dmat4(data.camera.combinedViewMatrix()); dmat4 vp = dmat4(data.camera.projectionMatrix()) * viewTransform; @@ -266,7 +266,7 @@ const DebugRenderer::Vertices DebugRenderer::verticesFor( vertices[i] = glm::vec4(x, y, z, 1); } - return std::move(vertices); + return vertices; } #endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED diff --git a/modules/debugging/rendering/debugshader_fs.glsl b/modules/debugging/rendering/debugshader_fs.glsl index 5a395b10e7..e119339bef 100644 --- a/modules/debugging/rendering/debugshader_fs.glsl +++ b/modules/debugging/rendering/debugshader_fs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -35,4 +35,4 @@ Fragment getFragment(){ frag.color = color; frag.depth = fs_vertexPosition.w; return frag; -} \ No newline at end of file +} diff --git a/modules/debugging/rendering/debugshader_vs.glsl b/modules/debugging/rendering/debugshader_vs.glsl index b68e20f682..45f4357ad8 100644 --- a/modules/debugging/rendering/debugshader_vs.glsl +++ b/modules/debugging/rendering/debugshader_vs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -33,4 +33,4 @@ out vec4 fs_vertexPosition; void main(){ fs_vertexPosition = z_normalization(vertexPositionClippingSpace); gl_Position = fs_vertexPosition; -} \ No newline at end of file +} diff --git a/modules/debugging/rendering/renderabledebugplane.cpp b/modules/debugging/rendering/renderabledebugplane.cpp index e40dd68cd5..53278c1c42 100644 --- a/modules/debugging/rendering/renderabledebugplane.cpp +++ b/modules/debugging/rendering/renderabledebugplane.cpp @@ -49,15 +49,13 @@ RenderableDebugPlane::RenderableDebugPlane(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _texture("texture", "Texture", -1, -1, 255) , _billboard("billboard", "Billboard", false) - , _size("size", "Size", glm::vec2(1,1), glm::vec2(0.f), glm::vec2(1.f, 25.f)) + , _size("size", "Size", 10, 0, std::pow(10, 25)) , _origin(Origin::Center) , _shader(nullptr) , _quad(0) , _vertexPositionBuffer(0) { - glm::vec2 size; - dictionary.getValue("Size", size); - _size = size; + dictionary.getValue("Size", _size); if (dictionary.hasKey("Name")){ dictionary.getValue("Name", _nodeName); @@ -104,7 +102,7 @@ RenderableDebugPlane::RenderableDebugPlane(const ghoul::Dictionary& dictionary) addProperty(_size); _size.onChange([this](){ _planeIsDirty = true; }); - setBoundingSphere(_size.value()); + setBoundingSphere(_size); } RenderableDebugPlane::~RenderableDebugPlane() { @@ -189,16 +187,16 @@ void RenderableDebugPlane::createPlane() { // ============================ // GEOMETRY (quad) // ============================ - const GLfloat size = _size.value()[0]; - const GLfloat w = _size.value()[1]; + const GLfloat size = _size; + const GLfloat vertex_data[] = { // x y z w s t - -size, -size, 0.f, w, 0.f, 0.f, - size, size, 0.f, w, 1.f, 1.f, - -size, size, 0.f, w, 0.f, 1.f, - -size, -size, 0.f, w, 0.f, 0.f, - size, -size, 0.f, w, 1.f, 0.f, - size, size, 0.f, w, 1.f, 1.f, + -size, -size, 0.f, 0.f, 0.f, 0.f, + size, size, 0.f, 0.f, 1.f, 1.f, + -size, size, 0.f, 0.f, 0.f, 1.f, + -size, -size, 0.f, 0.f, 0.f, 0.f, + size, -size, 0.f, 0.f, 1.f, 0.f, + size, size, 0.f, 0.f, 1.f, 1.f, }; glBindVertexArray(_quad); // bind array diff --git a/modules/debugging/rendering/renderabledebugplane.h b/modules/debugging/rendering/renderabledebugplane.h index 96df652354..b007cef5dd 100644 --- a/modules/debugging/rendering/renderabledebugplane.h +++ b/modules/debugging/rendering/renderabledebugplane.h @@ -28,7 +28,6 @@ #include #include -#include #include namespace ghoul { @@ -67,7 +66,7 @@ private: properties::IntProperty _texture; properties::BoolProperty _billboard; - properties::Vec2Property _size; + properties::FloatProperty _size; Origin _origin; std::string _nodeName; diff --git a/modules/fieldlines/CMakeLists.txt b/modules/fieldlines/CMakeLists.txt index e8c847c274..ca28a3c37e 100644 --- a/modules/fieldlines/CMakeLists.txt +++ b/modules/fieldlines/CMakeLists.txt @@ -1,26 +1,26 @@ -######################################################################################### -# # -# OpenSpace # -# # -# Copyright (c) 2014-2015 # -# # -# Permission is hereby granted, free of charge, to any person obtaining a copy of this # -# software and associated documentation files (the "Software"), to deal in the Software # -# without restriction, including without limitation the rights to use, copy, modify, # -# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # -# permit persons to whom the Software is furnished to do so, subject to the following # -# conditions: # -# # -# The above copyright notice and this permission notice shall be included in all copies # -# or substantial portions of the Software. # -# # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # -# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # -# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # -# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -######################################################################################### +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2017 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +########################################################################################## include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) diff --git a/modules/fieldlines/rendering/renderablefieldlines.cpp b/modules/fieldlines/rendering/renderablefieldlines.cpp index 1d855b278a..060701141a 100644 --- a/modules/fieldlines/rendering/renderablefieldlines.cpp +++ b/modules/fieldlines/rendering/renderablefieldlines.cpp @@ -121,7 +121,7 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) } // @TODO a non-magic number perhaps ---abock - setBoundingSphere(PowerScaledScalar::CreatePSS(250.f*6371000.f)); + setBoundingSphere(250.f*6371000.f); _seedPointSource.addOption(SeedPointSourceFile, "File"); _seedPointSource.addOption(SeedPointSourceTable, "Lua Table"); diff --git a/modules/fieldlines/shaders/fieldline_fs.glsl b/modules/fieldlines/shaders/fieldline_fs.glsl index 1bbaf74cba..879b1cfbc7 100644 --- a/modules/fieldlines/shaders/fieldline_fs.glsl +++ b/modules/fieldlines/shaders/fieldline_fs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -69,4 +69,4 @@ Fragment getFragment() // float depth = pscDepth(gs_position); // ABufferStruct_t frag = createGeometryFragment(fragColor, gs_position, depth); // addToBuffer(frag); -// } \ No newline at end of file +// } diff --git a/modules/fieldlines/shaders/fieldline_gs.glsl b/modules/fieldlines/shaders/fieldline_gs.glsl index 32be0f108c..35845bcc4e 100644 --- a/modules/fieldlines/shaders/fieldline_gs.glsl +++ b/modules/fieldlines/shaders/fieldline_gs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -96,4 +96,4 @@ void main() { gs_normal = normals[2]; ABufferEmitVertex(prismoid[2]); EndPrimitive(); -} \ No newline at end of file +} diff --git a/modules/fieldlines/shaders/fieldline_vs.glsl b/modules/fieldlines/shaders/fieldline_vs.glsl index 9fcdcb5bcb..394a48c14b 100644 --- a/modules/fieldlines/shaders/fieldline_vs.glsl +++ b/modules/fieldlines/shaders/fieldline_vs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -37,4 +37,4 @@ out vec4 vs_color; void main() { vs_color = in_color; gl_Position = vec4(in_position, 0); -} \ No newline at end of file +} diff --git a/modules/galaxy/CMakeLists.txt b/modules/galaxy/CMakeLists.txt index afb55cfbb3..a70b4b03d6 100644 --- a/modules/galaxy/CMakeLists.txt +++ b/modules/galaxy/CMakeLists.txt @@ -1,40 +1,44 @@ -######################################################################################### -# # -# OpenSpace # -# # -# Copyright (c) 2014-2015 # -# # -# Permission is hereby granted, free of charge, to any person obtaining a copy of this # -# software and associated documentation files (the "Software"), to deal in the Software # -# without restriction, including without limitation the rights to use, copy, modify, # -# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # -# permit persons to whom the Software is furnished to do so, subject to the following # -# conditions: # -# # -# The above copyright notice and this permission notice shall be included in all copies # -# or substantial portions of the Software. # -# # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # -# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # -# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # -# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -######################################################################################### +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2017 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +########################################################################################## include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/galaxymodule.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/galaxyraycaster.h - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegalaxy.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegalaxy.h + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywayconversiontask.h + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywaypointsconversiontask.h ) source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/galaxymodule.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/galaxyraycaster.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegalaxy.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablegalaxy.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywayconversiontask.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywaypointsconversiontask.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/galaxy/galaxymodule.cpp b/modules/galaxy/galaxymodule.cpp index 1555ddc184..636055634c 100644 --- a/modules/galaxy/galaxymodule.cpp +++ b/modules/galaxy/galaxymodule.cpp @@ -27,6 +27,8 @@ #include #include #include +#include +#include namespace openspace { @@ -36,6 +38,11 @@ void GalaxyModule::internalInitialize() { auto fRenderable = FactoryManager::ref().factory(); ghoul_assert(fRenderable, "No renderable factory existed"); fRenderable->registerClass("RenderableGalaxy"); + + auto fTask = FactoryManager::ref().factory(); + ghoul_assert(fRenderable, "No task factory existed"); + fTask->registerClass("MilkywayConversionTask"); + fTask->registerClass("MilkywayPointsConversionTask"); } } // namespace openspace diff --git a/modules/galaxy/rendering/galaxyraycaster.h b/modules/galaxy/rendering/galaxyraycaster.h index dcd34063e6..b65e08eff6 100644 --- a/modules/galaxy/rendering/galaxyraycaster.h +++ b/modules/galaxy/rendering/galaxyraycaster.h @@ -44,7 +44,7 @@ namespace ghoul { namespace openspace { -class RenderData; +struct RenderData; class RaycastData; class GalaxyRaycaster : public VolumeRaycaster { diff --git a/apps/DataConverter/milkywayconversiontask.cpp b/modules/galaxy/tasks/milkywayconversiontask.cpp similarity index 64% rename from apps/DataConverter/milkywayconversiontask.cpp rename to modules/galaxy/tasks/milkywayconversiontask.cpp index 72482738a6..9a32d4cce8 100644 --- a/apps/DataConverter/milkywayconversiontask.cpp +++ b/modules/galaxy/tasks/milkywayconversiontask.cpp @@ -22,30 +22,67 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include + #include #include #include -namespace openspace { -namespace dataconverter { - -MilkyWayConversionTask::MilkyWayConversionTask( - const std::string& inFilenamePrefix, - const std::string& inFilenameSuffix, - size_t inFirstIndex, - size_t inNSlices, - const std::string& outFilename, - const glm::ivec3& outDimensions) - : _inFilenamePrefix(inFilenamePrefix) - , _inFilenameSuffix(inFilenameSuffix) - , _inFirstIndex(inFirstIndex) - , _inNSlices(inNSlices) - , _outFilename(outFilename) - , _outDimensions(outDimensions) {} +#include +#include + +namespace { + const char* KeyInFilenamePrefix = "InFilenamePrefix"; + const char* KeyInFilenameSuffix = "InFilenameSuffix"; + const char* KeyInFirstIndex = "InFirstIndex"; + const char* KeyInNSlices = "InNSlices"; + const char* KeyOutFilename = "OutFilename"; + const char* KeyOutDimensions = "OutDimensions"; +} // namespace + +namespace openspace { -void MilkyWayConversionTask::perform(const std::function& onProgress) { +MilkywayConversionTask::MilkywayConversionTask(const ghoul::Dictionary& dictionary) { + std::string inFilenamePrefix; + if (dictionary.getValue(KeyInFilenamePrefix, inFilenamePrefix)) { + _inFilenamePrefix = inFilenamePrefix; + } + + std::string inFilenameSuffix; + if (dictionary.getValue(KeyInFilenameSuffix, inFilenameSuffix)) { + _inFilenameSuffix = inFilenameSuffix; + } + + size_t inFirstIndex; + if (dictionary.getValue(KeyInFirstIndex, inFirstIndex)) { + _inFirstIndex = inFirstIndex; + } + + size_t inNSlices; + if (dictionary.getValue(KeyInNSlices, inNSlices)) { + _inNSlices = inNSlices; + } + + std::string outFilename; + if (dictionary.getValue(KeyOutFilename, outFilename)) { + _outFilename = outFilename; + } + + glm::ivec3 outDimensions; + if (dictionary.getValue(KeyOutDimensions, outDimensions)) { + _outDimensions = outDimensions; + } +} + +MilkywayConversionTask::~MilkywayConversionTask() {} + +std::string MilkywayConversionTask::description() +{ + return std::string(); +} + +void MilkywayConversionTask::perform(const Task::ProgressCallback& progressCallback) { std::vector filenames; for (int i = 0; i < _inNSlices; i++) { filenames.push_back(_inFilenamePrefix + std::to_string(i + _inFirstIndex) + _inFilenameSuffix); @@ -67,8 +104,12 @@ void MilkyWayConversionTask::perform(const std::function& onProgres return value; }; - rawWriter.write(sampleFunction, onProgress); + rawWriter.write(sampleFunction, progressCallback); +} + +documentation::Documentation MilkywayConversionTask::documentation() +{ + return documentation::Documentation(); } } -} diff --git a/apps/DataConverter/milkywayconversiontask.h b/modules/galaxy/tasks/milkywayconversiontask.h similarity index 76% rename from apps/DataConverter/milkywayconversiontask.h rename to modules/galaxy/tasks/milkywayconversiontask.h index 6eb7233c75..4e00b9c975 100644 --- a/apps/DataConverter/milkywayconversiontask.h +++ b/modules/galaxy/tasks/milkywayconversiontask.h @@ -22,10 +22,10 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_APP_DATACONVERTER___MILKYWAYCONVERSIONTASK___H__ -#define __OPENSPACE_APP_DATACONVERTER___MILKYWAYCONVERSIONTASK___H__ +#ifndef __OPENSPACE_MODULE_GALAXY___MILKYWAYCONVERSIONTASK___H__ +#define __OPENSPACE_MODULE_GALAXY___MILKYWAYCONVERSIONTASK___H__ -#include +#include #include #include #include @@ -34,22 +34,21 @@ namespace openspace { -namespace dataconverter { + +namespace documentation { struct Documentation; } /** * Converts a set of exr image slices to a raw volume * with floating point RGBA data (32 bit per channel). */ -class MilkyWayConversionTask : public ConversionTask { +class MilkywayConversionTask : public Task { public: - MilkyWayConversionTask(const std::string& inFilenamePrefix, - const std::string& inFilenameSuffix, - size_t inFirstIndex, - size_t inNSlices, - const std::string& outFilename, - const glm::ivec3& outDimensions); - - void perform(const std::function& onProgress) override; + MilkywayConversionTask(const ghoul::Dictionary& dictionary); + virtual ~MilkywayConversionTask(); + std::string description() override; + void perform(const Task::ProgressCallback& onProgress) override; + static documentation::Documentation documentation(); + private: std::string _inFilenamePrefix; std::string _inFilenameSuffix; @@ -59,7 +58,6 @@ private: glm::ivec3 _outDimensions; }; -} // namespace dataconverter -} // namespace openspace +} -#endif // __OPENSPACE_APP_DATACONVERTER___MILKYWAYCONVERSIONTASK___H__ +#endif // __OPENSPACE_MODULE_GALAXY___MILKYWAYCONVERSIONTASK___H__ diff --git a/apps/DataConverter/milkywaypointsconversiontask.cpp b/modules/galaxy/tasks/milkywaypointsconversiontask.cpp similarity index 77% rename from apps/DataConverter/milkywaypointsconversiontask.cpp rename to modules/galaxy/tasks/milkywaypointsconversiontask.cpp index 790d2be279..0df1bcdb1f 100644 --- a/apps/DataConverter/milkywaypointsconversiontask.cpp +++ b/modules/galaxy/tasks/milkywaypointsconversiontask.cpp @@ -22,38 +22,46 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include + #include #include #include + +#include + #include #include +#include namespace openspace { -namespace dataconverter { - - -MilkyWayPointsConversionTask::MilkyWayPointsConversionTask( +/*MilkywayPointsConversionTask::MilkywayPointsConversionTask( const std::string& inFilename, const std::string& outFilename) : _inFilename(inFilename) - , _outFilename(outFilename) {} + , _outFilename(outFilename) {}*/ +MilkywayPointsConversionTask::MilkywayPointsConversionTask(const ghoul::Dictionary & dictionary) {} -void MilkyWayPointsConversionTask::perform(const std::function& onProgress) { +MilkywayPointsConversionTask::~MilkywayPointsConversionTask() {} + +std::string MilkywayPointsConversionTask::description() +{ + return std::string(); +} + +void MilkywayPointsConversionTask::perform(const Task::ProgressCallback & progressCallback) { std::ifstream in(_inFilename, std::ios::in); std::ofstream out(_outFilename, std::ios::out | std::ios::binary); - + std::string format; int64_t nPoints; in >> format >> nPoints; - - size_t nFloats = nPoints * 7; - float* pointData = new float[nFloats]; + std::vector pointData(nFloats); float x, y, z, r, g, b, a; for (size_t i = 0; i < nPoints; ++i) { @@ -66,21 +74,24 @@ void MilkyWayPointsConversionTask::perform(const std::function& onP pointData[i * 7 + 4] = g; pointData[i * 7 + 5] = b; pointData[i * 7 + 6] = a; - onProgress(static_cast(i + 1) / nPoints); - } else { + progressCallback(static_cast(i + 1) / nPoints); + } + else { std::cout << "Failed to convert point data."; return; } } out.write(reinterpret_cast(&nPoints), sizeof(int64_t)); - out.write(reinterpret_cast(pointData), nFloats * sizeof(float)); + out.write(reinterpret_cast(pointData.data()), nFloats * sizeof(float)); in.close(); out.close(); } - +documentation::Documentation MilkywayPointsConversionTask::documentation() +{ + return documentation::Documentation(); +} -} } diff --git a/apps/DataConverter/milkywaypointsconversiontask.h b/modules/galaxy/tasks/milkywaypointsconversiontask.h similarity index 80% rename from apps/DataConverter/milkywaypointsconversiontask.h rename to modules/galaxy/tasks/milkywaypointsconversiontask.h index a11bc64230..d20eb4bcef 100644 --- a/apps/DataConverter/milkywaypointsconversiontask.h +++ b/modules/galaxy/tasks/milkywaypointsconversiontask.h @@ -22,10 +22,10 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_APP_DATACONVERTER___MILKYWAYPOINTSCONVERSIONTASK___H__ -#define __OPENSPACE_APP_DATACONVERTER___MILKYWAYPOINTSCONVERSIONTASK___H__ +#ifndef __OPENSPACE_MODULE_GALAXY___MILKYWAYPOINTSCONVERSIONTASK_H__ +#define __OPENSPACE_MODULE_GALAXY___MILKYWAYPOINTSCONVERSIONTASK_H__ -#include +#include #include #include #include @@ -34,7 +34,8 @@ namespace openspace { -namespace dataconverter { + +namespace documentation { struct Documentation; } /** * Converts ascii based point data @@ -42,18 +43,19 @@ namespace dataconverter { * (float x, float y, float z, float r, float g, float b) * n * to a binary (floating point) representation with the same layout. */ -class MilkyWayPointsConversionTask : public ConversionTask { +class MilkywayPointsConversionTask : public Task { public: - MilkyWayPointsConversionTask(const std::string& inFilename, - const std::string& outFilename); - - void perform(const std::function& onProgress) override; + MilkywayPointsConversionTask(const ghoul::Dictionary& dictionary); + virtual ~MilkywayPointsConversionTask(); + std::string description() override; + void perform(const Task::ProgressCallback& progressCallback) override; + static documentation::Documentation documentation(); + private: std::string _inFilename; std::string _outFilename; }; -} // namespace dataconverter -} // namespace openspace +} -#endif // __OPENSPACE_APP_DATACONVERTER___MILKYWAYPOINTSCONVERSIONTASK___H__ +#endif // __OPENSPACE_MODULE_GALAXY___MILKYWAYPOINTSCONVERSIONTASK_H__ diff --git a/modules/globebrowsing/CMakeLists.txt b/modules/globebrowsing/CMakeLists.txt index c91053e164..beb70af6ec 100644 --- a/modules/globebrowsing/CMakeLists.txt +++ b/modules/globebrowsing/CMakeLists.txt @@ -1,30 +1,37 @@ -######################################################################################### -# # -# OpenSpace # -# # -# Copyright (c) 2014-2016 # -# # -# Permission is hereby granted, free of charge, to any person obtaining a copy of this # -# software and associated documentation files (the "Software"), to deal in the Software # -# without restriction, including without limitation the rights to use, copy, modify, # -# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # -# permit persons to whom the Software is furnished to do so, subject to the following # -# conditions: # -# # -# The above copyright notice and this permission notice shall be included in all copies # -# or substantial portions of the Software. # -# # -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # -# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # -# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # -# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # -# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -######################################################################################### +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2017 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +########################################################################################## include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/cache/lrucache.h + ${CMAKE_CURRENT_SOURCE_DIR}/cache/lrucache.inl + ${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawarecacheable.h + ${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawarelrucache.h + ${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawarelrucache.inl + ${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawaretilecache.h + ${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunk.h ${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunknode.h ${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/chunklevelevaluator.h @@ -57,8 +64,6 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentqueue.h ${CMAKE_CURRENT_SOURCE_DIR}/other/concurrentqueue.inl ${CMAKE_CURRENT_SOURCE_DIR}/other/distanceswitch.h - ${CMAKE_CURRENT_SOURCE_DIR}/other/lrucache.h - ${CMAKE_CURRENT_SOURCE_DIR}/other/lrucache.inl ${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.h ${CMAKE_CURRENT_SOURCE_DIR}/other/statscollector.inl ${CMAKE_CURRENT_SOURCE_DIR}/other/threadpool.h @@ -79,15 +84,13 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layermanager.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layerrendersettings.h - ${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctilereader.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctiledataprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/chunktile.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/pixelregion.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtile.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/textureformat.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tile.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledatalayout.h - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledataset.h - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledatatype.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledepthtransform.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tilediskcache.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileindex.h @@ -98,6 +101,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/loadjob.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/tileloadjob.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.h @@ -106,19 +110,26 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileprovider.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbyindex.h ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.h + + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/rawtiledatareader.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/gdalrawtiledatareader.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/simplerawtiledatareader.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/gdalwrapper.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/iodescription.h + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/tiledatatype.h ) set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/cache/memoryawaretilecache.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunk.cpp ${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunknode.cpp ${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/availabletiledataevaluator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/distanceevaluator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/chunk/chunklevelevaluator/projectedareaevaluator.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/chunk/culling/frustumculler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/chunk/culling/horizonculler.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/geometry/aabb.cpp ${CMAKE_CURRENT_SOURCE_DIR}/geometry/ellipsoid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/geometry/geodetic2.cpp @@ -153,13 +164,11 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layermanager.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/layer/layerrendersettings.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctilereader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctiledataprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/pixelregion.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tile.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledatalayout.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledataset.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/tile/tiledatatype.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tilediskcache.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileindex.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tilemetadata.cpp @@ -167,6 +176,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/diskcachedtileloadjob.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/tileloadjob.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.cpp @@ -175,6 +185,13 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileprovider.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbyindex.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/tileproviderbylevel.cpp + + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/rawtiledatareader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/gdalrawtiledatareader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/simplerawtiledatareader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/gdalwrapper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/iodescription.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtiledatareader/tiledatatype.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) @@ -201,31 +218,34 @@ create_new_module( ${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES} ) -if (WIN32) - target_include_directories( - openspace-module-globebrowsing - SYSTEM PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/include - ) +option(OPENSPACE_MODULE_GLOBEBROWSING_USE_GDAL "Use GDAL" ON) - target_link_libraries( - openspace-module-globebrowsing - ${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/lib/gdal_i.lib - ) +if (OPENSPACE_MODULE_GLOBEBROWSING_USE_GDAL) + if (WIN32) + target_include_directories( + openspace-module-globebrowsing + SYSTEM PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/include + ) - set(EXTERNAL_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/lib/gdal201.dll" PARENT_SCOPE) + target_link_libraries( + openspace-module-globebrowsing + ${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/lib/gdal_i.lib + ) + set(EXTERNAL_LIBRARY "${CMAKE_CURRENT_SOURCE_DIR}/ext/gdal/lib/gdal201.dll" PARENT_SCOPE) + else (WIN32) + find_package(GDAL REQUIRED) -else (WIN32) - find_package(GDAL REQUIRED) + target_include_directories( + openspace-module-globebrowsing + SYSTEM PUBLIC + ${GDAL_INCLUDE_DIR} + ) - target_include_directories( - openspace-module-globebrowsing - SYSTEM PUBLIC - ${GDAL_INCLUDE_DIR} - ) - - target_link_libraries( - openspace-module-globebrowsing - ${GDAL_LIBRARY} - ) -endif () + target_link_libraries( + openspace-module-globebrowsing + ${GDAL_LIBRARY} + ) + endif () # WIN32 + target_compile_definitions(openspace-module-globebrowsing PRIVATE GLOBEBROWSING_USE_GDAL) +endif () # OPENSPACE_MODULE_GLOBEBROWSING_USE_GDAL diff --git a/modules/globebrowsing/other/lrucache.h b/modules/globebrowsing/cache/lrucache.h similarity index 90% rename from modules/globebrowsing/other/lrucache.h rename to modules/globebrowsing/cache/lrucache.h index d410ab4985..4857761995 100644 --- a/modules/globebrowsing/other/lrucache.h +++ b/modules/globebrowsing/cache/lrucache.h @@ -30,11 +30,18 @@ namespace openspace { namespace globebrowsing { +namespace cache { -// Templated class implementing a Least-Recently-Used Cache +/** + * Templated class implementing a Least-Recently-Used Cache. + * KeyType needs to be an enumerable type. + */ template class LRUCache { public: + /** + * \param size is the maximum size of the cache given in number of cached items. + */ LRUCache(size_t size); void put(const KeyType& key, const ValueType& value); @@ -51,9 +58,10 @@ private: size_t _cacheSize; }; +} // namespace cache } // namespace globebrowsing } // namespace openspace -#include +#include #endif // __OPENSPACE_MODULE_GLOBEBROWSING___LRU_CACHE___H__ diff --git a/modules/globebrowsing/other/lrucache.inl b/modules/globebrowsing/cache/lrucache.inl similarity index 99% rename from modules/globebrowsing/other/lrucache.inl rename to modules/globebrowsing/cache/lrucache.inl index 4aacc3132e..4bc88bca4f 100644 --- a/modules/globebrowsing/other/lrucache.inl +++ b/modules/globebrowsing/cache/lrucache.inl @@ -26,6 +26,7 @@ namespace openspace { namespace globebrowsing { +namespace cache { template LRUCache::LRUCache(size_t size) @@ -78,5 +79,6 @@ void LRUCache::clean() { } } +} // namespace cache } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/cache/memoryawarecacheable.h b/modules/globebrowsing/cache/memoryawarecacheable.h new file mode 100644 index 0000000000..ccd2c253c7 --- /dev/null +++ b/modules/globebrowsing/cache/memoryawarecacheable.h @@ -0,0 +1,58 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_CACHEABLE___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_CACHEABLE___H__ + +namespace openspace { +namespace globebrowsing { +namespace cache { + +/** + * Base class to be extended by classes that need to be cached and make use of the + * memoryImpact interface. A class extending MemoryAwareCacheable needs to + * know its memory impact at initialization and hence provide the memory impact in its + * constructors. The memory impact can not change during the lifetime of an object that is + * a MemoryAwareCacheable. + */ +class MemoryAwareCacheable { +public: + /** + * \param memoryImpact is the memory impact of the object. Can for example be given + * in kilobytes. + */ + MemoryAwareCacheable(size_t memoryImpact) : _memoryImpact(memoryImpact) {}; + ~MemoryAwareCacheable() {}; + + size_t memoryImpact() { return _memoryImpact; }; + +protected: + size_t _memoryImpact; +}; + +} // namespace cache +} // namespace globebrowsing +} // namespace openspace + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_CACHEABLE___H__ diff --git a/modules/globebrowsing/cache/memoryawarelrucache.h b/modules/globebrowsing/cache/memoryawarelrucache.h new file mode 100644 index 0000000000..c4aaef71a7 --- /dev/null +++ b/modules/globebrowsing/cache/memoryawarelrucache.h @@ -0,0 +1,83 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_LRU_CACHE___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_LRU_CACHE___H__ + +#include +#include + +namespace openspace { +namespace globebrowsing { +namespace cache { + +/** + * Least recently used cache that knows about its memory impact. This class is templated + * and the second template argument ValueType needs to have a function + * void memoryImpact() that returns the size of the object given in whatever + * unit is used for size in the creation of the MemoryAwareLRUCache. + * It can for example be given in kilobytes. + * KeyType needs to be a size comparable type. + */ + +template +class MemoryAwareLRUCache { +public: + /** + * \param maximumSize is the maximum size of the MemoryAwareLRUCache + * Once the maximum size is reached, the cache will start removing objects that were + * least recently used. The maximum size can for example be given in kilobytes. It + * must be the same size unit as used by the cached object class + * ValueType. + */ + MemoryAwareLRUCache(size_t maximumSize); + + void put(const KeyType& key, const ValueType& value); + void clear(); + bool exist(const KeyType& key) const; + ValueType get(const KeyType& key); + size_t size() const; + size_t maximumSize() const; + + void setMaximumSize(size_t maximumSize); + +private: + void clean(); + + using Item = std::pair; + using Items = std::list; + Items _itemList; + std::unordered_map _itemMap; + + size_t _cacheSize; + size_t _maximumCacheSize; +}; + +} // namespace cache +} // namespace globebrowsing +} // namespace openspace + +#include + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_LRU_CACHE___H__ diff --git a/modules/globebrowsing/cache/memoryawarelrucache.inl b/modules/globebrowsing/cache/memoryawarelrucache.inl new file mode 100644 index 0000000000..28e0a1ec6e --- /dev/null +++ b/modules/globebrowsing/cache/memoryawarelrucache.inl @@ -0,0 +1,100 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +namespace openspace { +namespace globebrowsing { +namespace cache { + +template +MemoryAwareLRUCache::MemoryAwareLRUCache(size_t maximumSize) + : _maximumCacheSize(maximumSize) + , _cacheSize(0) +{} + +template +void MemoryAwareLRUCache::clear() { + _itemList.clear(); + _itemMap.clear(); + _cacheSize = 0; +} + +template +void MemoryAwareLRUCache::put(const KeyType& key, const ValueType& value) { + auto it = _itemMap.find(key); + if (it != _itemMap.end()) { + _cacheSize -= it->second->second.memoryImpact(); + _itemList.erase(it->second); + _itemMap.erase(it); + } + _itemList.emplace_front(key, value); + _itemMap.emplace(key, _itemList.begin()); + _cacheSize += _itemList.begin()->second.memoryImpact(); + clean(); +} + +template +bool MemoryAwareLRUCache::exist(const KeyType& key) const { + return _itemMap.count(key) > 0; +} + +template +ValueType MemoryAwareLRUCache::get(const KeyType& key) { + //ghoul_assert(exist(key), "Key " << key << " must exist"); + auto it = _itemMap.at(key); + // Move list iterator pointing to value + _itemList.splice(_itemList.begin(), _itemList, it); + return it->second; +} + +template +size_t MemoryAwareLRUCache::size() const { + return _cacheSize; +} + +template +size_t MemoryAwareLRUCache::maximumSize() const { + return _maximumCacheSize; +} + +template +void MemoryAwareLRUCache::setMaximumSize(size_t maximumSize) { + _maximumCacheSize = maximumSize; +} + +template +void MemoryAwareLRUCache::clean() { + while (_cacheSize > _maximumCacheSize) { + auto last_it = _itemList.end(); + last_it--; + _itemMap.erase(last_it->first); + _cacheSize -= last_it->second.memoryImpact(); + _itemList.pop_back(); + } +} + +} // namespace cache +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/cache/memoryawaretilecache.cpp b/modules/globebrowsing/cache/memoryawaretilecache.cpp new file mode 100644 index 0000000000..e45daf6452 --- /dev/null +++ b/modules/globebrowsing/cache/memoryawaretilecache.cpp @@ -0,0 +1,84 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +namespace openspace { +namespace globebrowsing { +namespace cache { + +MemoryAwareTileCache* MemoryAwareTileCache::_singleton = nullptr; +std::mutex MemoryAwareTileCache::_mutexLock; + +void MemoryAwareTileCache::create(size_t cacheSize) { + std::lock_guard guard(_mutexLock); + _singleton = new MemoryAwareTileCache(cacheSize); +} + +void MemoryAwareTileCache::destroy() { + std::lock_guard guard(_mutexLock); + delete _singleton; +} + +MemoryAwareTileCache& MemoryAwareTileCache::ref() { + std::lock_guard guard(_mutexLock); + ghoul_assert(_singleton, "MemoryAwareTileCache not created"); + return *_singleton; +} + +void MemoryAwareTileCache::clear() { + std::lock_guard guard(_mutexLock); + _tileCache.clear(); +} + +bool MemoryAwareTileCache::exist(ProviderTileKey key) const { + std::lock_guard guard(_mutexLock); + return _tileCache.exist(key); +} + +Tile MemoryAwareTileCache::get(ProviderTileKey key) { + std::lock_guard guard(_mutexLock); + return _tileCache.get(key); +} + +void MemoryAwareTileCache::put(ProviderTileKey key, Tile tile) { + std::lock_guard guard(_mutexLock); + _tileCache.put(key, tile); +} + +void MemoryAwareTileCache::setMaximumSize(size_t maximumSize) { + std::lock_guard guard(_mutexLock); + _tileCache.setMaximumSize(maximumSize); +} + +MemoryAwareTileCache::MemoryAwareTileCache(size_t cacheSize) + : _tileCache(cacheSize) {} + +} // namespace cache +} // namespace globebrowsing +} // namespace openspace + diff --git a/modules/globebrowsing/cache/memoryawaretilecache.h b/modules/globebrowsing/cache/memoryawaretilecache.h new file mode 100644 index 0000000000..114be6f69b --- /dev/null +++ b/modules/globebrowsing/cache/memoryawaretilecache.h @@ -0,0 +1,113 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_TILE_CACHE___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_TILE_CACHE___H__ + +#include +#include +#include + +#include +#include + +namespace openspace { +namespace globebrowsing { +namespace cache { + +struct ProviderTileKey { + TileIndex tileIndex; + unsigned int providerID; + + bool operator==(const ProviderTileKey& r) const { + return (providerID == r.providerID) && + (tileIndex == r.tileIndex); + } +}; + +struct ProviderTileHasher { + /** + Creates a hash which can be used as key in hash maps. + First set the bits to be unique for all tiles. + +-------+------------+-------+------------+ + | USAGE | BIT RANGE | #BITS | MAX VALUE | + +-------+------------+-------+------------+ + | level | 0 - 5 | 5 | 31 | + | x | 5 - 35 | 30 | 1073741824 | + | y | 35 - 64 | 29 | 536870912 | + +-------+------------+-------+------------+ + + Bits are then shifted depending on the tile provider used. + */ + unsigned long long operator()(const ProviderTileKey& t) const { + unsigned long long key = 0; + key |= static_cast(t.tileIndex.level); + key |= static_cast(t.tileIndex.x << 5); + key |= static_cast(t.tileIndex.y << 35); + // Now the key is unique for all tiles, however not for all tile providers. + // Add to the key depending on the tile provider to avoid some hash collisions. + // (All hash collisions can not be avoided due to the limit in 64 bit for the + // hash key) + // Idea: make some offset in the place of the bits for the x value. Lesser chance + // of having different x-value than having different tile provider ids. + key += static_cast(t.providerID << 25); + return key; + } +}; + + +/** + * Singleton class used to cache tiles for all CachingTileProviders. + */ +class MemoryAwareTileCache { +public: + static void create(size_t cacheSize); + static void destroy(); + + void clear(); + bool exist(ProviderTileKey key) const; + Tile get(ProviderTileKey key); + void put(ProviderTileKey key, Tile tile); + + void setMaximumSize(size_t maximumSize); + + static MemoryAwareTileCache& ref(); + +private: + /** + * \param cacheSize is the cache size given in bytes. + */ + MemoryAwareTileCache(size_t cacheSize); + ~MemoryAwareTileCache() = default; + + static MemoryAwareTileCache* _singleton; + MemoryAwareLRUCache _tileCache; + static std::mutex _mutexLock; +}; + +} // namespace cache +} // namespace globebrowsing +} // namespace openspace + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___MEMORY_AWARE_TILE_CACHE___H__ diff --git a/modules/globebrowsing/chunk/chunk.cpp b/modules/globebrowsing/chunk/chunk.cpp index 54284da290..5e140bfc3b 100644 --- a/modules/globebrowsing/chunk/chunk.cpp +++ b/modules/globebrowsing/chunk/chunk.cpp @@ -29,6 +29,8 @@ #include #include #include +#include + namespace openspace { namespace globebrowsing { @@ -83,6 +85,8 @@ Chunk::Status Chunk::update(const RenderData& data) { } Chunk::BoundingHeights Chunk::getBoundingHeights() const { + using ChunkTileSettingsPair = std::pair; + BoundingHeights boundingHeights { 0.f, 0.f, false @@ -90,50 +94,58 @@ Chunk::BoundingHeights Chunk::getBoundingHeights() const { // In the future, this should be abstracted away and more easily queryable. // One must also handle how to sample pick one out of multiplte heightmaps - auto layerManager = owner().chunkedLodGlobe()->layerManager(); - + std::shared_ptr layerManager = + owner().chunkedLodGlobe()->layerManager(); + // The raster of a height map is the first one. We assume that the height map is // a single raster image. If it is not we will just use the first raster // (that is channel 0). const size_t HeightChannel = 0; const LayerGroup& heightmaps = layerManager->layerGroup(LayerManager::HeightLayers); - std::vector chunkTiles = tileselector::getTilesSortedByHighestResolution( - heightmaps, _tileIndex - ); + std::vector chunkTileSettingPairs = + tileselector::getTilesAndSettingsSortedByHighestResolution( + heightmaps, _tileIndex); bool lastHadMissingData = true; - for (const auto& chunkTile : chunkTiles) { - bool goodTile = (chunkTile.tile.status == Tile::Status::OK); - bool hasTileMetaData = (chunkTile.tile.metaData != nullptr); + for (const ChunkTileSettingsPair& chunkTileSettingsPair : chunkTileSettingPairs) { + ChunkTile chunkTile = chunkTileSettingsPair.first; + const LayerRenderSettings* settings = chunkTileSettingsPair.second; + bool goodTile = (chunkTile.tile.status() == Tile::Status::OK); + bool hasTileMetaData = (chunkTile.tile.metaData() != nullptr); if (goodTile && hasTileMetaData) { - auto tileMetaData = chunkTile.tile.metaData; + std::shared_ptr tileMetaData = chunkTile.tile.metaData(); + + float minValue = + settings->performLayerSettings(tileMetaData->minValues[HeightChannel]); + float maxValue = + settings->performLayerSettings(tileMetaData->maxValues[HeightChannel]); if (!boundingHeights.available) { if (tileMetaData->hasMissingData[HeightChannel]) { boundingHeights.min = std::min( DEFAULT_HEIGHT, - tileMetaData->minValues[HeightChannel] + minValue ); boundingHeights.max = std::max( DEFAULT_HEIGHT, - tileMetaData->maxValues[HeightChannel] + maxValue ); } else { - boundingHeights.min = tileMetaData->minValues[HeightChannel]; - boundingHeights.max = tileMetaData->maxValues[HeightChannel]; + boundingHeights.min = minValue; + boundingHeights.max = maxValue; } boundingHeights.available = true; } else { boundingHeights.min = std::min( boundingHeights.min, - tileMetaData->minValues[HeightChannel] + minValue ); boundingHeights.max = std::max( boundingHeights.max, - tileMetaData->maxValues[HeightChannel] + maxValue ); } lastHadMissingData = tileMetaData->hasMissingData[HeightChannel]; diff --git a/modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.cpp b/modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.cpp index d1cc671b49..e7ce4379d7 100644 --- a/modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.cpp +++ b/modules/globebrowsing/chunk/chunklevelevaluator/distanceevaluator.cpp @@ -66,7 +66,7 @@ int Distance::getDesiredLevel(const Chunk& chunk, const RenderData& data) const double scaleFactor = globe.generalProperties().lodScaleFactor * ellipsoid.minimumRadius(); double projectedScaleFactor = scaleFactor / distance; - int desiredLevel = ceil(log2(projectedScaleFactor)); + int desiredLevel = static_cast(ceil(log2(projectedScaleFactor))); return desiredLevel; } diff --git a/modules/globebrowsing/chunk/chunknode.cpp b/modules/globebrowsing/chunk/chunknode.cpp index 408fd613a9..6b64a7e02c 100644 --- a/modules/globebrowsing/chunk/chunknode.cpp +++ b/modules/globebrowsing/chunk/chunknode.cpp @@ -33,9 +33,9 @@ namespace openspace { namespace globebrowsing { ChunkNode::ChunkNode(const Chunk& chunk, ChunkNode* parent) - : _chunk(chunk) - , _parent(parent) + : _parent(parent) , _children({ nullptr, nullptr, nullptr, nullptr }) + , _chunk(chunk) {} bool ChunkNode::isRoot() const { @@ -159,20 +159,20 @@ const ChunkNode& ChunkNode::getChild(Quad quad) const { void ChunkNode::split(int depth) { if (depth > 0 && isLeaf()) { for (size_t i = 0; i < _children.size(); ++i) { - Chunk chunk(_chunk.owner(), _chunk.tileIndex().child((Quad)i)); + Chunk chunk(_chunk.owner(), _chunk.tileIndex().child(static_cast(i))); _children[i] = std::make_unique(chunk, this); } } if (depth - 1 > 0) { - for (int i = 0; i < _children.size(); ++i) { + for (size_t i = 0; i < _children.size(); ++i) { _children[i]->split(depth - 1); } } } void ChunkNode::merge() { - for (int i = 0; i < _children.size(); ++i) { + for (size_t i = 0; i < _children.size(); ++i) { if (_children[i] != nullptr) { _children[i]->merge(); } diff --git a/modules/globebrowsing/ext/gdal/gdal.h b/modules/globebrowsing/ext/gdal/gdal.h new file mode 100644 index 0000000000..7153331b6a --- /dev/null +++ b/modules/globebrowsing/ext/gdal/gdal.h @@ -0,0 +1,36 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GDAL___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___GDAL___H__ + +#ifdef WIN32 +#pragma warning(push, 0) +#endif // WIN32 + +#include + +#ifdef WIN32 +#pragma warning(pop) +#endif // WIN32 diff --git a/modules/globebrowsing/geometry/ellipsoid.cpp b/modules/globebrowsing/geometry/ellipsoid.cpp index 4f756f575b..9d51d762d2 100644 --- a/modules/globebrowsing/geometry/ellipsoid.cpp +++ b/modules/globebrowsing/geometry/ellipsoid.cpp @@ -78,7 +78,7 @@ glm::dvec3 Ellipsoid::geodeticSurfaceProjection(const glm::dvec3& p) const { dSdA = -2.0 * glm::dot(p2 / (_cached._radiiToTheFourth * d3), glm::dvec3(1.0)); } - while (abs(s) > epsilon); + while (std::abs(s) > epsilon); return p / d; } diff --git a/modules/globebrowsing/geometry/geodeticpatch.cpp b/modules/globebrowsing/geometry/geodeticpatch.cpp index 8aca1219fb..b302e30b1d 100644 --- a/modules/globebrowsing/geometry/geodeticpatch.cpp +++ b/modules/globebrowsing/geometry/geodeticpatch.cpp @@ -27,6 +27,8 @@ #include #include +#include + namespace openspace { namespace globebrowsing { @@ -90,6 +92,7 @@ Geodetic2 GeodeticPatch::getCorner(Quad q) const { case NORTH_EAST: return Geodetic2(maxLat(), maxLon());// northEastCorner(); case SOUTH_WEST: return Geodetic2(minLat(), minLon());// southWestCorner(); case SOUTH_EAST: return Geodetic2(minLat(), maxLon());// southEastCorner(); + default: ghoul_assert(false, "Missing case label"); } } diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index 808e5ce072..71dc2c07c6 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -24,8 +24,10 @@ #include +#include #include #include +#include #include #include #include @@ -35,20 +37,69 @@ #include #include #include +#include +#include #include #include #include #include +#include + namespace openspace { -GlobeBrowsingModule::GlobeBrowsingModule() : OpenSpaceModule("GlobeBrowsing") {} +GlobeBrowsingModule::GlobeBrowsingModule() + : OpenSpaceModule("GlobeBrowsing") + , _openSpaceMaximumTileCacheSize( + "maximumTileCacheSize", "Maximum tile cache size", + 512, // Default: 512 MB + 0, // Minimum: No caching + 1024, // Maximum: 1024 MB + 1) // Step: One MB + , _clearTileCache("clearTileCache", "Clear tile cache") {} void GlobeBrowsingModule::internalInitialize() { using namespace globebrowsing; + OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Initialize, [&] { + // Set maximum cache size to 25% of total RAM + _openSpaceMaximumTileCacheSize.setMaxValue(CpuCap.installedMainMemory() * 0.25); + + // Convert from MB to KB + cache::MemoryAwareTileCache::create(_openSpaceMaximumTileCacheSize * 1024); + _openSpaceMaximumTileCacheSize.onChange( + [&]{ + // Convert from MB to KB + cache::MemoryAwareTileCache::ref().setMaximumSize( + _openSpaceMaximumTileCacheSize * 1024); + }); + _clearTileCache.onChange( + [&]{ + cache::MemoryAwareTileCache::ref().clear(); + }); + + addProperty(_openSpaceMaximumTileCacheSize); + addProperty(_clearTileCache); + +#ifdef GLOBEBROWSING_USE_GDAL + // Convert from MB to Bytes + GdalWrapper::create( + 16ULL * 1024ULL * 1024ULL, // 16 MB + CpuCap.installedMainMemory() * 0.25 * 1024 * 1024); // 25% of total RAM + addPropertySubOwner(GdalWrapper::ref()); +#endif // GLOBEBROWSING_USE_GDAL + }); + + OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Deinitialize, [&]{ + cache::MemoryAwareTileCache::ref().clear(); + cache::MemoryAwareTileCache::ref().destroy(); +#ifdef GLOBEBROWSING_USE_GDAL + GdalWrapper::ref().destroy(); +#endif // GLOBEBROWSING_USE_GDAL + }); + auto fRenderable = FactoryManager::ref().factory(); ghoul_assert(fRenderable, "Renderable factory was not created"); fRenderable->registerClass("RenderableGlobe"); @@ -58,14 +109,17 @@ void GlobeBrowsingModule::internalInitialize() { fTileProvider->registerClass("LRUCaching"); fTileProvider->registerClass("SingleImage"); +#ifdef GLOBEBROWSING_USE_GDAL fTileProvider->registerClass("Temporal"); +#endif // GLOBEBROWSING_USE_GDAL + fTileProvider->registerClass("TileIndex"); fTileProvider->registerClass("SizeReference"); // Combining Tile Providers fTileProvider->registerClass("ByLevel"); fTileProvider->registerClass("ByIndex"); - + fTileProvider->registerClass("PresentationSlides"); FactoryManager::ref().addFactory(std::move(fTileProvider)); } diff --git a/modules/globebrowsing/globebrowsingmodule.h b/modules/globebrowsing/globebrowsingmodule.h index 942aea1819..9996c8876e 100644 --- a/modules/globebrowsing/globebrowsingmodule.h +++ b/modules/globebrowsing/globebrowsingmodule.h @@ -26,6 +26,10 @@ #define __OPENSPACE_MODULE_GLOBEBROWSING___GLOBEBROWSING_MODULE___H__ #include +#include +#include + +#include namespace openspace { @@ -35,6 +39,9 @@ public: protected: void internalInitialize() override; +private: + properties::IntProperty _openSpaceMaximumTileCacheSize; + properties::TriggerProperty _clearTileCache; }; } // namespace openspace diff --git a/modules/globebrowsing/globes/chunkedlodglobe.cpp b/modules/globebrowsing/globes/chunkedlodglobe.cpp index a4a6c6e823..24430afaa5 100644 --- a/modules/globebrowsing/globes/chunkedlodglobe.cpp +++ b/modules/globebrowsing/globes/chunkedlodglobe.cpp @@ -143,7 +143,8 @@ int ChunkedLodGlobe::getDesiredLevel( int desiredLevelByAvailableData = _chunkEvaluatorByAvailableTiles->getDesiredLevel( chunk, renderData ); - if (desiredLevelByAvailableData != chunklevelevaluator::Evaluator::UnknownDesiredLevel) { + if (desiredLevelByAvailableData != chunklevelevaluator::Evaluator::UnknownDesiredLevel && + _owner.debugProperties().limitLevelByAvailableData) { desiredLevel = glm::min(desiredLevel, desiredLevelByAvailableData); } @@ -180,14 +181,14 @@ float ChunkedLodGlobe::getHeight(glm::dvec3 position) const { const auto& tile = chunkTile.tile; const auto& uvTransform = chunkTile.uvTransform; const auto& depthTransform = tileProvider->depthTransform(); - if (tile.status != Tile::Status::OK) { + if (tile.status() != Tile::Status::OK) { return 0; } glm::vec2 transformedUv = Tile::TileUvToTextureSamplePosition( uvTransform, patchUV, - glm::uvec2(tile.texture->dimensions()) + glm::uvec2(tile.texture()->dimensions()) ); // Sample and do linear interpolation @@ -195,7 +196,7 @@ float ChunkedLodGlobe::getHeight(glm::dvec3 position) const { // Suggestion: a function in ghoul::opengl::Texture that takes uv coordinates // in range [0,1] and uses the set interpolation method and clamping. - glm::uvec3 dimensions = tile.texture->dimensions(); + glm::uvec3 dimensions = tile.texture()->dimensions(); glm::vec2 samplePos = transformedUv * glm::vec2(dimensions); glm::uvec2 samplePos00 = samplePos; @@ -219,10 +220,10 @@ float ChunkedLodGlobe::getHeight(glm::dvec3 position) const { glm::uvec2(dimensions) - glm::uvec2(1) ); - float sample00 = tile.texture->texelAsFloat(samplePos00).x; - float sample10 = tile.texture->texelAsFloat(samplePos10).x; - float sample01 = tile.texture->texelAsFloat(samplePos01).x; - float sample11 = tile.texture->texelAsFloat(samplePos11).x; + float sample00 = tile.texture()->texelAsFloat(samplePos00).x; + float sample10 = tile.texture()->texelAsFloat(samplePos10).x; + float sample01 = tile.texture()->texelAsFloat(samplePos01).x; + float sample11 = tile.texture()->texelAsFloat(samplePos11).x; // In case the texture has NaN or no data values don't use this height map. bool anySampleIsNaN = @@ -248,6 +249,10 @@ float ChunkedLodGlobe::getHeight(glm::dvec3 position) const { // Perform depth transform to get the value in meters height = depthTransform.depthOffset + depthTransform.depthScale * sample; + // Make sure that the height value follows the layer settings. + // For example if the multiplier is set to a value bigger than one, + // the sampled height should be modified as well. + height = layer->renderSettings().performLayerSettings(height); } // Return the result return height; @@ -276,7 +281,6 @@ void ChunkedLodGlobe::render(const RenderData& data) { stats.i["leafs chunk nodes"]++; if (chunk.isVisible()) { stats.i["rendered chunks"]++; - double t0 = Time::now().j2000Seconds(); _renderer->renderChunk(chunkNode.getChunk(), data); debugRenderChunk(chunk, mvp); } diff --git a/modules/globebrowsing/globes/pointglobe.cpp b/modules/globebrowsing/globes/pointglobe.cpp index d4d796c18f..7e1887a3e2 100644 --- a/modules/globebrowsing/globes/pointglobe.cpp +++ b/modules/globebrowsing/globes/pointglobe.cpp @@ -117,7 +117,5 @@ void PointGlobe::render(const RenderData& data) { _programObject->deactivate(); } -void PointGlobe::update(const UpdateData& data) {} - } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/globes/pointglobe.h b/modules/globebrowsing/globes/pointglobe.h index 2c41a38e8a..b52c151821 100644 --- a/modules/globebrowsing/globes/pointglobe.h +++ b/modules/globebrowsing/globes/pointglobe.h @@ -46,7 +46,6 @@ public: bool isReady() const override; void render(const RenderData& data) override; - void update(const UpdateData& data) override; private: const RenderableGlobe& _owner; diff --git a/modules/globebrowsing/globes/renderableglobe.cpp b/modules/globebrowsing/globes/renderableglobe.cpp index 6c050a57aa..6b43aca744 100644 --- a/modules/globebrowsing/globes/renderableglobe.cpp +++ b/modules/globebrowsing/globes/renderableglobe.cpp @@ -44,14 +44,7 @@ using namespace properties; namespace globebrowsing { RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary) - : _generalProperties({ - BoolProperty("enabled", "Enabled", true), - BoolProperty("performShading", "perform shading", true), - BoolProperty("atmosphere", "atmosphere", false), - FloatProperty("lodScaleFactor", "lodScaleFactor",10.0f, 1.0f, 50.0f), - FloatProperty("cameraMinHeight", "cameraMinHeight", 100.0f, 0.0f, 1000.0f) - }) - , _debugProperties({ + : _debugProperties({ BoolProperty("saveOrThrowCamera", "save or throw camera", false), BoolProperty("showChunkEdges", "show chunk edges", false), BoolProperty("showChunkBounds", "show chunk bounds", false), @@ -60,12 +53,22 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary) BoolProperty("showHeightIntensities", "show height intensities", false), BoolProperty("performFrustumCulling", "perform frustum culling", true), BoolProperty("performHorizonCulling", "perform horizon culling", true), - BoolProperty("levelByProjectedAreaElseDistance", "level by projected area (else distance)",false), + BoolProperty("levelByProjectedAreaElseDistance", "level by projected area (else distance)", true), BoolProperty("resetTileProviders", "reset tile providers", false), BoolProperty("toggleEnabledEveryFrame", "toggle enabled every frame", false), BoolProperty("collectStats", "collect stats", false), - BoolProperty("onlyModelSpaceRendering", "Only Model Space Rendering", false) + BoolProperty("limitLevelByAvailableData", "Limit level by available data", true), + IntProperty("modelSpaceRenderingCutoffLevel", "Model Space Rendering Cutoff Level", 10, 1, 22) }) + , _generalProperties({ + BoolProperty("enabled", "Enabled", true), + BoolProperty("performShading", "perform shading", true), + BoolProperty("atmosphere", "atmosphere", false), + FloatProperty("lodScaleFactor", "lodScaleFactor",10.0f, 1.0f, 50.0f), + FloatProperty("cameraMinHeight", "cameraMinHeight", 100.0f, 0.0f, 1000.0f) + }) + , _debugPropertyOwner("Debug") + , _texturePropertyOwner("Textures") { setName("RenderableGlobe"); @@ -75,23 +78,28 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary) glm::dvec3 radii; dictionary.getValue(keyRadii, radii); _ellipsoid = Ellipsoid(radii); - setBoundingSphere(pss(_ellipsoid.averageRadius(), 0.0)); + setBoundingSphere(_ellipsoid.averageRadius()); // Ghoul can't read ints from lua dictionaries... double patchSegmentsd; dictionary.getValue(keySegmentsPerPatch, patchSegmentsd); int patchSegments = patchSegmentsd; - dictionary.getValue(keyInteractionDepthBelowEllipsoid, - _interactionDepthBelowEllipsoid); + if (!dictionary.getValue(keyInteractionDepthBelowEllipsoid, + _interactionDepthBelowEllipsoid)) { + _interactionDepthBelowEllipsoid = 0; + } + float cameraMinHeight; dictionary.getValue(keyCameraMinHeight, cameraMinHeight); _generalProperties.cameraMinHeight.set(cameraMinHeight); // Init layer manager ghoul::Dictionary layersDictionary; - if (!dictionary.getValue(keyLayers, layersDictionary)) - throw ghoul::RuntimeError(std::string(keyLayers) + " must be specified specified!"); + if (!dictionary.getValue(keyLayers, layersDictionary)) { + throw ghoul::RuntimeError( + std::string(keyLayers) + " must be specified specified!"); + } _layerManager = std::make_shared(layersDictionary); @@ -105,9 +113,6 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary) double distance = res * _ellipsoid.maximumRadius() / tan(fov / 2); _distanceSwitch.addSwitchValue(_chunkedLodGlobe, distance); - _debugPropertyOwner.setName("Debug"); - _texturePropertyOwner.setName("Textures"); - addProperty(_generalProperties.isEnabled); addProperty(_generalProperties.atmosphereEnabled); addProperty(_generalProperties.performShading); @@ -128,8 +133,9 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary) _debugPropertyOwner.addProperty(_debugProperties.resetTileProviders); _debugPropertyOwner.addProperty(_debugProperties.toggleEnabledEveryFrame); _debugPropertyOwner.addProperty(_debugProperties.collectStats); - _debugPropertyOwner.addProperty(_debugProperties.onlyModelSpaceRendering); - + _debugPropertyOwner.addProperty(_debugProperties.limitLevelByAvailableData); + _debugPropertyOwner.addProperty(_debugProperties.modelSpaceRenderingCutoffLevel); + addPropertySubOwner(_debugPropertyOwner); addPropertySubOwner(_layerManager.get()); } diff --git a/modules/globebrowsing/globes/renderableglobe.h b/modules/globebrowsing/globes/renderableglobe.h index bd5c5b4ea3..b90e01eec2 100644 --- a/modules/globebrowsing/globes/renderableglobe.h +++ b/modules/globebrowsing/globes/renderableglobe.h @@ -31,6 +31,7 @@ #include #include +#include namespace openspace { namespace globebrowsing { @@ -64,7 +65,8 @@ public: properties::BoolProperty resetTileProviders; properties::BoolProperty toggleEnabledEveryFrame; properties::BoolProperty collectStats; - properties::BoolProperty onlyModelSpaceRendering; + properties::BoolProperty limitLevelByAvailableData; + properties::IntProperty modelSpaceRenderingCutoffLevel; }; struct GeneralProperties { diff --git a/modules/globebrowsing/meshes/basicgrid.cpp b/modules/globebrowsing/meshes/basicgrid.cpp index 88d33512d6..7bd91dea3d 100644 --- a/modules/globebrowsing/meshes/basicgrid.cpp +++ b/modules/globebrowsing/meshes/basicgrid.cpp @@ -64,8 +64,11 @@ int BasicGrid::ySegments() const { } void BasicGrid::validate(int xSegments, int ySegments) { - ghoul_assert(xSegments > 0 && ySegments > 0, - "Resolution must be at least 1x1. (" << xSegments << ", " << ySegments << ")"); + ghoul_assert( + xSegments > 0 && ySegments > 0, + std::string("Resolution must be at least 1x1. (") + + std::to_string(xSegments) + ", " + std::to_string(ySegments) + ")" + ); } inline size_t BasicGrid::numElements(int xSegments, int ySegments) { diff --git a/modules/globebrowsing/meshes/skirtedgrid.cpp b/modules/globebrowsing/meshes/skirtedgrid.cpp index ee632af4b6..822c3dd63e 100644 --- a/modules/globebrowsing/meshes/skirtedgrid.cpp +++ b/modules/globebrowsing/meshes/skirtedgrid.cpp @@ -26,10 +26,6 @@ #include -namespace { - const char*_loggerCat = "SkirtedGrid"; -} - namespace openspace { namespace globebrowsing { diff --git a/modules/globebrowsing/other/distanceswitch.cpp b/modules/globebrowsing/other/distanceswitch.cpp index 971f2e32d0..18f4644643 100644 --- a/modules/globebrowsing/other/distanceswitch.cpp +++ b/modules/globebrowsing/other/distanceswitch.cpp @@ -23,7 +23,6 @@ ****************************************************************************************/ #include - #include namespace openspace { @@ -32,6 +31,7 @@ namespace globebrowsing { DistanceSwitch::~DistanceSwitch() {} bool DistanceSwitch::initialize() { + _objectScale = 1.0; for (int i = 0; i < _renderables.size(); ++i) { _renderables[i]->initialize(); } @@ -51,16 +51,15 @@ void DistanceSwitch::render(const RenderData& data) { return; } - pss pssDistanceToCamera = (data.camera.position() - data.position).length(); - double distanceToCamera = pssDistanceToCamera.lengthd(); + double distanceToCamera = (data.camera.positionVec3() - data.position.dvec3()).length(); - if (distanceToCamera > _maxDistances.back()) { + if (distanceToCamera > _maxDistances.back() * _objectScale) { return; } // linear search through nodes to find which Renderable to render for (int i = 0; i < _renderables.size(); ++i) { - if (distanceToCamera < _maxDistances[i]) { + if (distanceToCamera < _maxDistances[i] * _objectScale) { _renderables[i]->render(data); return; } @@ -68,6 +67,7 @@ void DistanceSwitch::render(const RenderData& data) { } void DistanceSwitch::update(const UpdateData& data) { + _objectScale = data.modelTransform.scale; for (int i = 0; i < _renderables.size(); ++i) { _renderables[i]->update(data); } diff --git a/modules/globebrowsing/other/distanceswitch.h b/modules/globebrowsing/other/distanceswitch.h index 59a87d41c8..9f26e35f43 100644 --- a/modules/globebrowsing/other/distanceswitch.h +++ b/modules/globebrowsing/other/distanceswitch.h @@ -63,6 +63,7 @@ public: private: std::vector> _renderables; std::vector _maxDistances; + double _objectScale; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/other/statscollector.inl b/modules/globebrowsing/other/statscollector.inl index bafbc02366..f1ce37ec71 100644 --- a/modules/globebrowsing/other/statscollector.inl +++ b/modules/globebrowsing/other/statscollector.inl @@ -1,4 +1,3 @@ -#include "statscollector.h" /***************************************************************************************** * * * OpenSpace * diff --git a/modules/globebrowsing/rendering/chunkrenderer.cpp b/modules/globebrowsing/rendering/chunkrenderer.cpp index 05af587eec..717c0c4038 100644 --- a/modules/globebrowsing/rendering/chunkrenderer.cpp +++ b/modules/globebrowsing/rendering/chunkrenderer.cpp @@ -30,6 +30,7 @@ #include #include #include +#include namespace { const char* keyFrame = "Frame"; @@ -64,7 +65,8 @@ ChunkRenderer::ChunkRenderer(std::shared_ptr grid, void ChunkRenderer::renderChunk(const Chunk& chunk, const RenderData& data) { // A little arbitrary with 10 but it works - if (chunk.owner().debugProperties().onlyModelSpaceRendering || chunk.tileIndex().level < 10) { + if (chunk.tileIndex().level < + chunk.owner().debugProperties().modelSpaceRenderingCutoffLevel) { renderChunkGlobally(chunk, data); } else { @@ -98,21 +100,28 @@ ghoul::opengl::ProgramObject* ChunkRenderer::getActivatedProgramWithTileData( const auto& debugProps = chunk.owner().debugProperties(); auto& pairs = layeredTexturePreprocessingData.keyValuePairs; - pairs.push_back(std::make_pair("useAtmosphere", - std::to_string(generalProps.atmosphereEnabled))); - pairs.push_back(std::make_pair("performShading", - std::to_string(generalProps.performShading))); - pairs.push_back(std::make_pair("showChunkEdges", - std::to_string(debugProps.showChunkEdges))); - pairs.push_back(std::make_pair("showHeightResolution", - std::to_string(debugProps.showHeightResolution))); - pairs.push_back(std::make_pair("showHeightIntensities", - std::to_string(debugProps.showHeightIntensities))); - pairs.push_back(std::make_pair("defaultHeight", - std::to_string(Chunk::DEFAULT_HEIGHT))); + pairs.emplace_back("useAtmosphere", std::to_string(generalProps.atmosphereEnabled)); + pairs.emplace_back("performShading", std::to_string(generalProps.performShading)); + pairs.emplace_back("showChunkEdges", std::to_string(debugProps.showChunkEdges)); + pairs.emplace_back("showHeightResolution", + std::to_string(debugProps.showHeightResolution)); + pairs.emplace_back("showHeightIntensities", + std::to_string(debugProps.showHeightIntensities)); + pairs.emplace_back("defaultHeight", std::to_string(Chunk::DEFAULT_HEIGHT)); + + pairs.emplace_back("tilePaddingStart", + "ivec2(" + + std::to_string(RawTileDataReader::padding.start.x) + "," + + std::to_string(RawTileDataReader::padding.start.y) + ")" + ); + pairs.emplace_back("tilePaddingSizeDiff", + "ivec2(" + + std::to_string(RawTileDataReader::padding.numPixels.x) + "," + + std::to_string(RawTileDataReader::padding.numPixels.y) + ")" + ); // Now the shader program can be accessed - ProgramObject* programObject = + ghoul::opengl::ProgramObject* programObject = layeredShaderManager->programObject( layeredTexturePreprocessingData); @@ -143,7 +152,7 @@ ghoul::opengl::ProgramObject* ChunkRenderer::getActivatedProgramWithTileData( void ChunkRenderer::renderChunkGlobally(const Chunk& chunk, const RenderData& data){ - ProgramObject* programObject = getActivatedProgramWithTileData( + ghoul::opengl::ProgramObject* programObject = getActivatedProgramWithTileData( _globalLayerShaderManager, _globalGpuLayerManager, chunk); @@ -194,7 +203,6 @@ void ChunkRenderer::renderChunkGlobally(const Chunk& chunk, const RenderData& da glm::normalize(-data.modelTransform.translation); glm::vec3 directionToSunCameraSpace = (viewTransform * glm::dvec4(directionToSunWorldSpace, 0)); - data.modelTransform.translation; programObject->setUniform("modelViewTransform", modelViewTransform); programObject->setUniform( "lightDirectionCameraSpace", -directionToSunCameraSpace); @@ -217,7 +225,7 @@ void ChunkRenderer::renderChunkGlobally(const Chunk& chunk, const RenderData& da void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& data) { - ProgramObject* programObject = getActivatedProgramWithTileData( + ghoul::opengl::ProgramObject* programObject = getActivatedProgramWithTileData( _localLayerShaderManager, _localGpuLayerManager, chunk); @@ -276,7 +284,6 @@ void ChunkRenderer::renderChunkLocally(const Chunk& chunk, const RenderData& dat glm::normalize(-data.modelTransform.translation); glm::vec3 directionToSunCameraSpace = (viewTransform * glm::dvec4(directionToSunWorldSpace, 0)); - data.modelTransform.translation; programObject->setUniform( "lightDirectionCameraSpace", -directionToSunCameraSpace); } diff --git a/modules/globebrowsing/rendering/gpu/gpuchunktile.cpp b/modules/globebrowsing/rendering/gpu/gpuchunktile.cpp index 4467241bfa..9efcdd9f74 100644 --- a/modules/globebrowsing/rendering/gpu/gpuchunktile.cpp +++ b/modules/globebrowsing/rendering/gpu/gpuchunktile.cpp @@ -30,12 +30,16 @@ namespace openspace { namespace globebrowsing { -void GPUChunkTile::setValue(ProgramObject* programObject, const ChunkTile& chunkTile) { - gpuTexture.setValue(programObject, chunkTile.tile.texture); +void GPUChunkTile::setValue(ghoul::opengl::ProgramObject* programObject, + const ChunkTile& chunkTile) +{ + gpuTexture.setValue(programObject, chunkTile.tile.texture()); gpuTileUvTransform.setValue(programObject, chunkTile.uvTransform); } -void GPUChunkTile::bind(ProgramObject* programObject, const std::string& nameBase) { +void GPUChunkTile::bind(ghoul::opengl::ProgramObject* programObject, + const std::string& nameBase) +{ gpuTexture.bind(programObject, nameBase + "textureSampler"); gpuTileUvTransform.bind(programObject, nameBase + "uvTransform."); } diff --git a/modules/globebrowsing/rendering/gpu/gpuchunktile.h b/modules/globebrowsing/rendering/gpu/gpuchunktile.h index 4a85ab13ad..490c7a81bd 100644 --- a/modules/globebrowsing/rendering/gpu/gpuchunktile.h +++ b/modules/globebrowsing/rendering/gpu/gpuchunktile.h @@ -51,14 +51,15 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - void setValue(ProgramObject* programObject, const ChunkTile& chunkTile); + void setValue(ghoul::opengl::ProgramObject* programObject, + const ChunkTile& chunkTile); /** * Binds GLSL variables with identifiers starting with * nameBase within the provided shader program with this object. * After this method has been called, users may invoke setValue. */ - void bind(ProgramObject* programObject, const std::string& nameBase); + void bind(ghoul::opengl::ProgramObject* programObject, const std::string& nameBase); /** * Deactivates any TextureUnits assigned by this object. diff --git a/modules/globebrowsing/rendering/gpu/gpuchunktilepile.cpp b/modules/globebrowsing/rendering/gpu/gpuchunktilepile.cpp index 52562ac90a..a07cd46857 100644 --- a/modules/globebrowsing/rendering/gpu/gpuchunktilepile.cpp +++ b/modules/globebrowsing/rendering/gpu/gpuchunktilepile.cpp @@ -28,31 +28,31 @@ namespace openspace { namespace globebrowsing { -void GPUChunkTilePile::setValue(ProgramObject* programObject, +void GPUChunkTilePile::setValue(ghoul::opengl::ProgramObject* programObject, const ChunkTilePile& chunkTilePile) { ghoul_assert( - gpuChunkTiles.size() == chunkTilePile.size(), + _gpuChunkTiles.size() == chunkTilePile.size(), "GPU and CPU ChunkTilePile must have same size!" ); - for (size_t i = 0; i < gpuChunkTiles.size(); ++i) { - gpuChunkTiles[i].setValue(programObject, chunkTilePile[i]); + for (size_t i = 0; i < _gpuChunkTiles.size(); ++i) { + _gpuChunkTiles[i].setValue(programObject, chunkTilePile[i]); } } -void GPUChunkTilePile::bind(ProgramObject* programObject, const std::string& nameBase, - int pileSize) +void GPUChunkTilePile::bind(ghoul::opengl::ProgramObject* programObject, + const std::string& nameBase, int pileSize) { - gpuChunkTiles.resize(pileSize); - for (size_t i = 0; i < gpuChunkTiles.size(); ++i) { + _gpuChunkTiles.resize(pileSize); + for (size_t i = 0; i < _gpuChunkTiles.size(); ++i) { std::string nameExtension = "chunkTile" + std::to_string(i) + "."; - gpuChunkTiles[i].bind(programObject, nameBase + nameExtension); + _gpuChunkTiles[i].bind(programObject, nameBase + nameExtension); } } void GPUChunkTilePile::deactivate() { - for (auto& gpuChunkTile : gpuChunkTiles) { - gpuChunkTile.deactivate(); + for (auto& t : _gpuChunkTiles) { + t.deactivate(); } } diff --git a/modules/globebrowsing/rendering/gpu/gpuchunktilepile.h b/modules/globebrowsing/rendering/gpu/gpuchunktilepile.h index 76d34ac1b9..e09b516370 100644 --- a/modules/globebrowsing/rendering/gpu/gpuchunktilepile.h +++ b/modules/globebrowsing/rendering/gpu/gpuchunktilepile.h @@ -51,15 +51,16 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - void setValue(ProgramObject* programObject, const ChunkTilePile& chunkTilePile); + void setValue(ghoul::opengl::ProgramObject* programObject, + const ChunkTilePile& chunkTilePile); /** * Binds this object with GLSL variables with identifiers starting * with nameBase within the provided shader program. * After this method has been called, users may invoke setValue. */ - void bind(ProgramObject* programObject, const std::string& nameBase, - int pileSize); + void bind(ghoul::opengl::ProgramObject* programObject, const std::string& nameBase, + int pileSize); /** * Deactivates any TextureUnits assigned by this object. * This method should be called after the OpenGL draw call. @@ -67,7 +68,7 @@ public: void deactivate(); private: - std::vector gpuChunkTiles; + std::vector _gpuChunkTiles; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp b/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp index 2db24d540f..5b77c34f9b 100644 --- a/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp +++ b/modules/globebrowsing/rendering/gpu/gpuheightlayer.cpp @@ -33,18 +33,19 @@ namespace openspace { namespace globebrowsing { -void GPUHeightLayer::setValue(ProgramObject* programObject, const Layer& layer, - const TileIndex& tileIndex, int pileSize) +void GPUHeightLayer::setValue(ghoul::opengl::ProgramObject* programObject, + const Layer& layer, const TileIndex& tileIndex, + int pileSize) { GPULayer::setValue(programObject, layer, tileIndex, pileSize); - gpuDepthTransform.setValue(programObject, layer.tileProvider()->depthTransform()); + _gpuDepthTransform.setValue(programObject, layer.tileProvider()->depthTransform()); } -void GPUHeightLayer::bind(ProgramObject* programObject, const Layer& layer, +void GPUHeightLayer::bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer, const std::string& nameBase, int pileSize) { GPULayer::bind(programObject, layer, nameBase, pileSize); - gpuDepthTransform.bind(programObject, nameBase + "depthTransform."); + _gpuDepthTransform.bind(programObject, nameBase + "depthTransform."); } diff --git a/modules/globebrowsing/rendering/gpu/gpuheightlayer.h b/modules/globebrowsing/rendering/gpu/gpuheightlayer.h index 466fb0909f..d2fca786cf 100644 --- a/modules/globebrowsing/rendering/gpu/gpuheightlayer.h +++ b/modules/globebrowsing/rendering/gpu/gpuheightlayer.h @@ -53,19 +53,19 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - virtual void setValue(ProgramObject* programObject, const Layer& layer, - const TileIndex& tileIndex, int pileSize); + virtual void setValue(ghoul::opengl::ProgramObject* programObject, const Layer& layer, + const TileIndex& tileIndex, int pileSize); /** * Binds this object with GLSL variables with identifiers starting * with nameBase within the provided shader program. * After this method has been called, users may invoke setValue. */ - virtual void bind(ProgramObject* programObject, const Layer& layer, - const std::string& nameBase, int pileSize); + virtual void bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer, + const std::string& nameBase, int pileSize); private: - GPUTileDepthTransform gpuDepthTransform; + GPUTileDepthTransform _gpuDepthTransform; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/gpu/gpulayer.cpp b/modules/globebrowsing/rendering/gpu/gpulayer.cpp index b54d9586f8..99fb35e915 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayer.cpp +++ b/modules/globebrowsing/rendering/gpu/gpulayer.cpp @@ -29,7 +29,7 @@ namespace openspace { namespace globebrowsing { -void GPULayer::setValue(ProgramObject* programObject, const Layer& layer, +void GPULayer::setValue(ghoul::opengl::ProgramObject* programObject, const Layer& layer, const TileIndex& tileIndex, int pileSize) { ChunkTilePile chunkTilePile = layer.getChunkTilePile(tileIndex, pileSize); @@ -37,7 +37,7 @@ void GPULayer::setValue(ProgramObject* programObject, const Layer& layer, gpuRenderSettings.setValue(programObject, layer.renderSettings()); } -void GPULayer::bind(ProgramObject* programObject, const Layer& layer, +void GPULayer::bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer, const std::string& nameBase, int pileSize) { gpuChunkTilePile.bind(programObject, nameBase + "pile.", pileSize); diff --git a/modules/globebrowsing/rendering/gpu/gpulayer.h b/modules/globebrowsing/rendering/gpu/gpulayer.h index bd07af9d6b..7fb7f2914c 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayer.h +++ b/modules/globebrowsing/rendering/gpu/gpulayer.h @@ -51,16 +51,16 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - virtual void setValue(ProgramObject* programObject, const Layer& layer, - const TileIndex& tileIndex, int pileSize); + virtual void setValue(ghoul::opengl::ProgramObject* programObject, const Layer& layer, + const TileIndex& tileIndex, int pileSize); /** * Binds this object with GLSL variables with identifiers starting * with nameBase within the provided shader program. * After this method has been called, users may invoke setValue. */ - virtual void bind(ProgramObject* programObject, const Layer& layer, - const std::string& nameBase, int pileSize); + virtual void bind(ghoul::opengl::ProgramObject* programObject, const Layer& layer, + const std::string& nameBase, int pileSize); /** * Deactivates any TextureUnits assigned by this object. diff --git a/modules/globebrowsing/rendering/gpu/gpulayergroup.cpp b/modules/globebrowsing/rendering/gpu/gpulayergroup.cpp index 0a14a317b5..f18d21e52c 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayergroup.cpp +++ b/modules/globebrowsing/rendering/gpu/gpulayergroup.cpp @@ -31,16 +31,16 @@ namespace openspace { namespace globebrowsing { -void GPULayerGroup::setValue(ProgramObject* programObject, const LayerGroup& layerGroup, - const TileIndex& tileIndex) +void GPULayerGroup::setValue(ghoul::opengl::ProgramObject* programObject, + const LayerGroup& layerGroup, const TileIndex& tileIndex) { auto& activeLayers = layerGroup.activeLayers(); ghoul_assert( - activeLayers.size() == gpuActiveLayers.size(), + activeLayers.size() == _gpuActiveLayers.size(), "GPU and CPU active layers must have same size!" ); for (int i = 0; i < activeLayers.size(); ++i) { - gpuActiveLayers[i]->setValue( + _gpuActiveLayers[i]->setValue( programObject, *activeLayers[i], tileIndex, @@ -49,19 +49,20 @@ void GPULayerGroup::setValue(ProgramObject* programObject, const LayerGroup& lay } } -void GPULayerGroup::bind(ProgramObject* programObject, const LayerGroup& layerGroup, - const std::string& nameBase, int category) +void GPULayerGroup::bind(ghoul::opengl::ProgramObject* programObject, + const LayerGroup& layerGroup, const std::string& nameBase, + int category) { auto activeLayers = layerGroup.activeLayers(); - gpuActiveLayers.resize(activeLayers.size()); + _gpuActiveLayers.resize(activeLayers.size()); int pileSize = layerGroup.pileSize(); - for (size_t i = 0; i < gpuActiveLayers.size(); ++i) { + for (size_t i = 0; i < _gpuActiveLayers.size(); ++i) { // should maybe a proper GPULayer factory - gpuActiveLayers[i] = (category == LayerManager::HeightLayers) ? + _gpuActiveLayers[i] = (category == LayerManager::HeightLayers) ? std::make_unique() : std::make_unique(); std::string nameExtension = "[" + std::to_string(i) + "]."; - gpuActiveLayers[i]->bind( + _gpuActiveLayers[i]->bind( programObject, *activeLayers[i], nameBase + nameExtension, @@ -71,8 +72,8 @@ void GPULayerGroup::bind(ProgramObject* programObject, const LayerGroup& layerGr } void GPULayerGroup::deactivate() { - for (size_t i = 0; i < gpuActiveLayers.size(); ++i) { - gpuActiveLayers[i]->deactivate(); + for (std::unique_ptr& l : _gpuActiveLayers) { + l->deactivate(); } } diff --git a/modules/globebrowsing/rendering/gpu/gpulayergroup.h b/modules/globebrowsing/rendering/gpu/gpulayergroup.h index 8d93755b3f..753cd6a6e5 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayergroup.h +++ b/modules/globebrowsing/rendering/gpu/gpulayergroup.h @@ -59,16 +59,16 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - virtual void setValue(ProgramObject* programObject, const LayerGroup& layerGroup, - const TileIndex& tileIndex); + virtual void setValue(ghoul::opengl::ProgramObject* programObject, + const LayerGroup& layerGroup, const TileIndex& tileIndex); /** * Binds this object with GLSL variables with identifiers starting * with nameBase within the provided shader program. * After this method has been called, users may invoke setValue. */ - virtual void bind(ProgramObject* programObject, const LayerGroup& layerGroup, - const std::string& nameBase, int category); + virtual void bind(ghoul::opengl::ProgramObject* programObject, + const LayerGroup& layerGroup, const std::string& nameBase, int category); /** * Deactivates any TextureUnits assigned by this object. @@ -77,7 +77,7 @@ public: virtual void deactivate(); private: - std::vector> gpuActiveLayers; + std::vector> _gpuActiveLayers; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/gpu/gpulayermanager.cpp b/modules/globebrowsing/rendering/gpu/gpulayermanager.cpp index ab68ae2bec..0f908031a6 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayermanager.cpp +++ b/modules/globebrowsing/rendering/gpu/gpulayermanager.cpp @@ -29,35 +29,36 @@ namespace openspace { namespace globebrowsing { -void GPULayerManager::setValue(ProgramObject* programObject, +void GPULayerManager::setValue(ghoul::opengl::ProgramObject* programObject, const LayerManager& layerManager, const TileIndex& tileIndex) { auto layerGroups = layerManager.layerGroups(); for (size_t i = 0; i < layerGroups.size(); ++i) { - gpuLayerGroups[i]->setValue(programObject, *layerGroups[i], tileIndex); + _gpuLayerGroups[i]->setValue(programObject, *layerGroups[i], tileIndex); } } -void GPULayerManager::bind(ProgramObject* programObject, const LayerManager& layerManager) +void GPULayerManager::bind(ghoul::opengl::ProgramObject* programObject, + const LayerManager& layerManager) { auto layerGroups = layerManager.layerGroups(); - if (gpuLayerGroups.size() != layerGroups.size()) { - gpuLayerGroups.resize(layerGroups.size()); - for (auto& gpuLayerGroup : gpuLayerGroups){ + if (_gpuLayerGroups.size() != layerGroups.size()) { + _gpuLayerGroups.resize(layerGroups.size()); + for (auto& gpuLayerGroup : _gpuLayerGroups){ gpuLayerGroup = std::make_unique(); } } for (size_t i = 0; i < layerGroups.size(); ++i) { std::string nameBase = LayerManager::LAYER_GROUP_NAMES[i]; - gpuLayerGroups[i]->bind(programObject, *layerGroups[i], nameBase, i); + _gpuLayerGroups[i]->bind(programObject, *layerGroups[i], nameBase, i); } } void GPULayerManager::deactivate() { - for (size_t i = 0; i < gpuLayerGroups.size(); ++i) { - gpuLayerGroups[i]->deactivate(); + for (std::unique_ptr& l : _gpuLayerGroups) { + l->deactivate(); } } diff --git a/modules/globebrowsing/rendering/gpu/gpulayermanager.h b/modules/globebrowsing/rendering/gpu/gpulayermanager.h index 6da1c15160..ee065e8f2f 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayermanager.h +++ b/modules/globebrowsing/rendering/gpu/gpulayermanager.h @@ -49,15 +49,16 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - virtual void setValue(ProgramObject* programObject, const LayerManager& layerManager, - const TileIndex& tileIndex); + virtual void setValue(ghoul::opengl::ProgramObject* programObject, + const LayerManager& layerManager, const TileIndex& tileIndex); /** * Binds this object with GLSL variables with identifiers starting * with nameBase within the provided shader program. * After this method has been called, users may invoke setValue. */ - virtual void bind(ProgramObject* programObject, const LayerManager& layerManager); + virtual void bind(ghoul::opengl::ProgramObject* programObject, + const LayerManager& layerManager); /** * Deactivates any TextureUnits assigned by this object. @@ -66,7 +67,7 @@ public: virtual void deactivate(); private: - std::vector> gpuLayerGroups; + std::vector> _gpuLayerGroups; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/gpu/gpulayerrendersettings.cpp b/modules/globebrowsing/rendering/gpu/gpulayerrendersettings.cpp index 6edbabb209..f849df1c20 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayerrendersettings.cpp +++ b/modules/globebrowsing/rendering/gpu/gpulayerrendersettings.cpp @@ -29,7 +29,7 @@ namespace openspace { namespace globebrowsing { -void GPULayerRenderSettings::setValue(ProgramObject* programObject, +void GPULayerRenderSettings::setValue(ghoul::opengl::ProgramObject* programObject, const LayerRenderSettings& layerSettings) { gpuOpacity.setValue(programObject, layerSettings.opacity.value()); @@ -37,7 +37,7 @@ void GPULayerRenderSettings::setValue(ProgramObject* programObject, gpuMultiplier.setValue(programObject, layerSettings.multiplier.value()); } -void GPULayerRenderSettings::bind(ProgramObject* programObject, +void GPULayerRenderSettings::bind(ghoul::opengl::ProgramObject* programObject, const std::string& nameBase) { gpuOpacity.bind(programObject, nameBase + "opacity"); diff --git a/modules/globebrowsing/rendering/gpu/gpulayerrendersettings.h b/modules/globebrowsing/rendering/gpu/gpulayerrendersettings.h index deee12bbc6..53ba536b42 100644 --- a/modules/globebrowsing/rendering/gpu/gpulayerrendersettings.h +++ b/modules/globebrowsing/rendering/gpu/gpulayerrendersettings.h @@ -48,14 +48,15 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - void setValue(ProgramObject* programObject, const LayerRenderSettings& layerSettings); + void setValue(ghoul::opengl::ProgramObject* programObject, + const LayerRenderSettings& layerSettings); /** * Binds this object with GLSL variables with identifiers starting * with nameBase within the provided shader program. * After this method has been called, users may invoke setValue. */ - void bind(ProgramObject* programObject, const std::string& nameBase); + void bind(ghoul::opengl::ProgramObject* programObject, const std::string& nameBase); private: GPUData gpuOpacity; diff --git a/modules/globebrowsing/rendering/gpu/gputiledepthtransform.cpp b/modules/globebrowsing/rendering/gpu/gputiledepthtransform.cpp index 9ae18d0191..deb14fabc7 100644 --- a/modules/globebrowsing/rendering/gpu/gputiledepthtransform.cpp +++ b/modules/globebrowsing/rendering/gpu/gputiledepthtransform.cpp @@ -29,18 +29,18 @@ namespace openspace { namespace globebrowsing { -void GPUTileDepthTransform::setValue(ProgramObject* programObject, +void GPUTileDepthTransform::setValue(ghoul::opengl::ProgramObject* programObject, const TileDepthTransform& depthTransform) { - gpuDepthOffset.setValue(programObject, depthTransform.depthOffset); - gpuDepthScale.setValue(programObject, depthTransform.depthScale); + _gpuDepthOffset.setValue(programObject, depthTransform.depthOffset); + _gpuDepthScale.setValue(programObject, depthTransform.depthScale); } -void GPUTileDepthTransform::bind(ProgramObject* programObject, +void GPUTileDepthTransform::bind(ghoul::opengl::ProgramObject* programObject, const std::string& nameBase) { - gpuDepthOffset.bind(programObject, nameBase + "depthOffset"); - gpuDepthScale.bind(programObject, nameBase + "depthScale"); + _gpuDepthOffset.bind(programObject, nameBase + "depthOffset"); + _gpuDepthScale.bind(programObject, nameBase + "depthScale"); } } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/gpu/gputiledepthtransform.h b/modules/globebrowsing/rendering/gpu/gputiledepthtransform.h index 8f1c943cc1..4e16940280 100644 --- a/modules/globebrowsing/rendering/gpu/gputiledepthtransform.h +++ b/modules/globebrowsing/rendering/gpu/gputiledepthtransform.h @@ -48,18 +48,20 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - void setValue(ProgramObject* programObject, const TileDepthTransform& depthTransform); + void setValue(ghoul::opengl::ProgramObject* programObject, + const TileDepthTransform& depthTransform); /** * Binds GLSL variables with identifiers starting with * nameBase within the provided shader program with this object. * After this method has been called, users may invoke setValue. */ - void bind(ProgramObject* programObject, const std::string& nameBase); + void bind(ghoul::opengl::ProgramObject* programObject, + const std::string& nameBase); private: - GPUData gpuDepthOffset; - GPUData gpuDepthScale; + GPUData _gpuDepthOffset; + GPUData _gpuDepthScale; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/gpu/gputileuvtransform.cpp b/modules/globebrowsing/rendering/gpu/gputileuvtransform.cpp index ab9e3cd51d..477b02b75b 100644 --- a/modules/globebrowsing/rendering/gpu/gputileuvtransform.cpp +++ b/modules/globebrowsing/rendering/gpu/gputileuvtransform.cpp @@ -33,16 +33,18 @@ namespace openspace { namespace globebrowsing { -void GPUTileUvTransform::setValue(ProgramObject* programObject, +void GPUTileUvTransform::setValue(ghoul::opengl::ProgramObject* programObject, const TileUvTransform& tileUvTransform) { - gpuUvOffset.setValue(programObject, tileUvTransform.uvOffset); - gpuUvScale.setValue(programObject, tileUvTransform.uvScale); + _gpuUvOffset.setValue(programObject, tileUvTransform.uvOffset); + _gpuUvScale.setValue(programObject, tileUvTransform.uvScale); } -void GPUTileUvTransform::bind(ProgramObject* programObject, const std::string& nameBase) { - gpuUvOffset.bind(programObject, nameBase + "uvOffset"); - gpuUvScale.bind(programObject, nameBase + "uvScale"); +void GPUTileUvTransform::bind(ghoul::opengl::ProgramObject* programObject, + const std::string& nameBase) +{ + _gpuUvOffset.bind(programObject, nameBase + "uvOffset"); + _gpuUvScale.bind(programObject, nameBase + "uvScale"); } } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/gpu/gputileuvtransform.h b/modules/globebrowsing/rendering/gpu/gputileuvtransform.h index df7b838e17..066eebfc47 100644 --- a/modules/globebrowsing/rendering/gpu/gputileuvtransform.h +++ b/modules/globebrowsing/rendering/gpu/gputileuvtransform.h @@ -48,18 +48,20 @@ public: * GPU struct. OBS! Users must ensure bind has been * called before setting using this method. */ - void setValue(ProgramObject* programObject, const TileUvTransform& uvTransform); + void setValue(ghoul::opengl::ProgramObject* programObject, + const TileUvTransform& uvTransform); /** * Binds GLSL variables with identifiers starting with * nameBase within the provided shader program with this object. * After this method has been called, users may invoke setValue. */ - void bind(ProgramObject* programObject, const std::string& nameBase); + void bind(ghoul::opengl::ProgramObject* programObject, + const std::string& nameBase); private: - GPUData gpuUvOffset; - GPUData gpuUvScale; + GPUData _gpuUvOffset; + GPUData _gpuUvScale; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/layer/layer.cpp b/modules/globebrowsing/rendering/layer/layer.cpp index e4f0aab166..b6b6b1c9fc 100644 --- a/modules/globebrowsing/rendering/layer/layer.cpp +++ b/modules/globebrowsing/rendering/layer/layer.cpp @@ -30,12 +30,9 @@ namespace openspace { namespace globebrowsing { Layer::Layer(const ghoul::Dictionary& layerDict) - : _enabled(properties::BoolProperty("enabled", "enabled", false)) + : properties::PropertyOwner(layerDict.value("Name")) + , _enabled(properties::BoolProperty("enabled", "enabled", false)) { - std::string layerName = "error!"; - layerDict.getValue("Name", layerName); - setName(layerName); - _tileProvider = std::shared_ptr( tileprovider::TileProvider::createFromDictionary(layerDict)); @@ -50,10 +47,11 @@ Layer::Layer(const ghoul::Dictionary& layerDict) addProperty(_enabled); addPropertySubOwner(_renderSettings); + addPropertySubOwner(*_tileProvider); } ChunkTilePile Layer::getChunkTilePile(const TileIndex& tileIndex, int pileSize) const { - return std::move(_tileProvider->getChunkTilePile(tileIndex, pileSize)); + return _tileProvider->getChunkTilePile(tileIndex, pileSize); } } // namespace globebrowsing diff --git a/modules/globebrowsing/rendering/layer/layergroup.cpp b/modules/globebrowsing/rendering/layer/layergroup.cpp index f6ab83687b..171b3a6b38 100644 --- a/modules/globebrowsing/rendering/layer/layergroup.cpp +++ b/modules/globebrowsing/rendering/layer/layergroup.cpp @@ -30,9 +30,9 @@ namespace openspace { namespace globebrowsing { LayerGroup::LayerGroup(std::string name) - : _levelBlendingEnabled("blendTileLevels", "blend tile levels", true) + : properties::PropertyOwner(std::move(name)) + , _levelBlendingEnabled("blendTileLevels", "blend tile levels", false) { - setName(std::move(name)); addProperty(_levelBlendingEnabled); } diff --git a/modules/globebrowsing/rendering/layer/layermanager.cpp b/modules/globebrowsing/rendering/layer/layermanager.cpp index d8ea7b4a3b..3dce21ede6 100644 --- a/modules/globebrowsing/rendering/layer/layermanager.cpp +++ b/modules/globebrowsing/rendering/layer/layermanager.cpp @@ -40,9 +40,9 @@ const char* LayerManager::LAYER_GROUP_NAMES[NUM_LAYER_GROUPS] = { "WaterMasks" }; -LayerManager::LayerManager(const ghoul::Dictionary& layerGroupsDict) { - setName("Layers"); - +LayerManager::LayerManager(const ghoul::Dictionary& layerGroupsDict) + : properties::PropertyOwner("Layers") +{ if (NUM_LAYER_GROUPS != layerGroupsDict.size()) { throw ghoul::RuntimeError( "Number of Layer Groups must be equal to " + NUM_LAYER_GROUPS); diff --git a/modules/globebrowsing/rendering/layer/layerrendersettings.cpp b/modules/globebrowsing/rendering/layer/layerrendersettings.cpp index 3a8427da8f..19c7c9d62f 100644 --- a/modules/globebrowsing/rendering/layer/layerrendersettings.cpp +++ b/modules/globebrowsing/rendering/layer/layerrendersettings.cpp @@ -28,16 +28,35 @@ namespace openspace { namespace globebrowsing { LayerRenderSettings::LayerRenderSettings() - : opacity(properties::FloatProperty("opacity", "opacity", 1.f, 0.f, 1.f)) + : properties::PropertyOwner("Settings") + , opacity(properties::FloatProperty("opacity", "opacity", 1.f, 0.f, 1.f)) , gamma(properties::FloatProperty("gamma", "gamma", 1, 0, 5)) , multiplier(properties::FloatProperty("multiplier", "multiplier", 1.f, 0.f, 20.f)) { - setName("settings"); - addProperty(opacity); addProperty(gamma); addProperty(multiplier); } +float LayerRenderSettings::performLayerSettings(float currentValue) const { + float newValue = currentValue; + + newValue = glm::sign(newValue) * glm::pow(glm::abs(newValue), gamma); + newValue = newValue * multiplier; + newValue = newValue * opacity; + + return newValue; +} + +glm::vec4 LayerRenderSettings::performLayerSettings(glm::vec4 currentValue) const { + glm::vec4 newValue = glm::vec4( + performLayerSettings(currentValue.r), + performLayerSettings(currentValue.g), + performLayerSettings(currentValue.b), + performLayerSettings(currentValue.a)); + + return newValue; +} + } // namespace globebrowsing } // namespace openspace diff --git a/modules/globebrowsing/rendering/layer/layerrendersettings.h b/modules/globebrowsing/rendering/layer/layerrendersettings.h index 7b794d8b3b..a737f19b90 100644 --- a/modules/globebrowsing/rendering/layer/layerrendersettings.h +++ b/modules/globebrowsing/rendering/layer/layerrendersettings.h @@ -37,6 +37,13 @@ struct LayerRenderSettings : public properties::PropertyOwner { properties::FloatProperty opacity; properties::FloatProperty gamma; properties::FloatProperty multiplier; + + /// This function matches the function with the same name in the + /// shader code + float performLayerSettings(float currentValue) const; + /// This function matches the function with the same name in the + /// shader code + glm::vec4 performLayerSettings(glm::vec4 currentValue) const; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/shaders/blending.hglsl b/modules/globebrowsing/shaders/blending.hglsl index 595758cfe6..e6b6b64bfd 100644 --- a/modules/globebrowsing/shaders/blending.hglsl +++ b/modules/globebrowsing/shaders/blending.hglsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -145,4 +145,4 @@ vec3 hsv2rgb(vec3 c) return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } -#endif \ No newline at end of file +#endif diff --git a/modules/globebrowsing/shaders/ellipsoid.hglsl b/modules/globebrowsing/shaders/ellipsoid.hglsl index 779c951de8..19c702e2e2 100644 --- a/modules/globebrowsing/shaders/ellipsoid.hglsl +++ b/modules/globebrowsing/shaders/ellipsoid.hglsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -103,4 +103,4 @@ Intersection rayIntersectEllipsoid( return Intersection(true, min(root1, root2), max(root1, root2)); } -#endif // ELLIPSOID_HGLSL \ No newline at end of file +#endif // ELLIPSOID_HGLSL diff --git a/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl b/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl index 9b1764e690..0bdf633ec6 100644 --- a/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl +++ b/modules/globebrowsing/shaders/globalchunkedlodpatch_fs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * diff --git a/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl b/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl index f9aefe6daf..86904a5db8 100644 --- a/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl +++ b/modules/globebrowsing/shaders/globalchunkedlodpatch_vs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -85,4 +85,4 @@ void main() { gl_Position = fs_position; ellipsoidNormalCameraSpace = mat3(modelViewTransform) * pair.normal; positionCameraSpace = vec3(modelViewTransform * vec4(pair.position, 1)); -} \ No newline at end of file +} diff --git a/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl b/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl index 7776e071db..4601915b0c 100644 --- a/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl +++ b/modules/globebrowsing/shaders/localchunkedlodpatch_fs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * diff --git a/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl b/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl index 901c2c3b67..8665e88030 100644 --- a/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl +++ b/modules/globebrowsing/shaders/localchunkedlodpatch_vs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -91,4 +91,4 @@ void main() { gl_Position = fs_position; ellipsoidNormalCameraSpace = patchNormalCameraSpace; positionCameraSpace = p; -} \ No newline at end of file +} diff --git a/modules/globebrowsing/shaders/pointglobe_fs.glsl b/modules/globebrowsing/shaders/pointglobe_fs.glsl index 539f2bacb3..cafeb66d3b 100644 --- a/modules/globebrowsing/shaders/pointglobe_fs.glsl +++ b/modules/globebrowsing/shaders/pointglobe_fs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * diff --git a/modules/globebrowsing/shaders/pointglobe_vs.glsl b/modules/globebrowsing/shaders/pointglobe_vs.glsl index 041d021d01..011e9bdf07 100644 --- a/modules/globebrowsing/shaders/pointglobe_vs.glsl +++ b/modules/globebrowsing/shaders/pointglobe_vs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -51,4 +51,4 @@ void main() { gl_PointSize = pointSizeNDC.x * 2 * windowWidth; gl_Position = vs_positionClipSpace; -} \ No newline at end of file +} diff --git a/modules/globebrowsing/shaders/texturetilemapping.hglsl b/modules/globebrowsing/shaders/texturetilemapping.hglsl index ffc8e8ebf8..ed1fe063d0 100644 --- a/modules/globebrowsing/shaders/texturetilemapping.hglsl +++ b/modules/globebrowsing/shaders/texturetilemapping.hglsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -386,4 +386,4 @@ vec4 calculateWater( return currentColor + vec4(specularTotal, 1); } -#endif // TEXTURETILEMAPPING_HGLSL \ No newline at end of file +#endif // TEXTURETILEMAPPING_HGLSL diff --git a/modules/globebrowsing/shaders/tile.hglsl b/modules/globebrowsing/shaders/tile.hglsl index 8f390c07ca..7f0f4e3958 100644 --- a/modules/globebrowsing/shaders/tile.hglsl +++ b/modules/globebrowsing/shaders/tile.hglsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -28,8 +28,8 @@ // Must match the values in tiledataset.cpp // (could be set as shader preprocessing data so that multiple definitions // are not needed) -#define TILE_PIXEL_START_OFFSET ivec2(-2) -#define TILE_PIXEL_SIZE_DIFFERENCE ivec2(4) +#define TILE_PIXEL_START_OFFSET #{tilePaddingStart} +#define TILE_PIXEL_SIZE_DIFFERENCE #{tilePaddingSizeDiff} vec4 patchBorderOverlay(vec2 uv, vec3 borderColor, float borderSize) { vec2 uvOffset = uv - vec2(0.5); @@ -87,7 +87,7 @@ vec2 compensateSourceTextureSampling(vec2 startOffset, vec2 sizeDiff, const Chun vec2 TileUVToTextureSamplePosition(const ChunkTile chunkTile, vec2 tileUV){ vec2 uv = chunkTile.uvTransform.uvOffset + chunkTile.uvTransform.uvScale * tileUV; - uv = compensateSourceTextureSampling(vec2(-2), vec2(4), chunkTile, uv); + uv = compensateSourceTextureSampling(TILE_PIXEL_START_OFFSET, TILE_PIXEL_SIZE_DIFFERENCE, chunkTile, uv); return uv; } @@ -156,4 +156,4 @@ vec4 getTexVal(const ChunkTilePile chunkTilePile, const LevelWeights w, const ve } -#endif // TEXTURETILE_HGLSL \ No newline at end of file +#endif // TEXTURETILE_HGLSL diff --git a/modules/globebrowsing/shaders/tilefragcolor.hglsl b/modules/globebrowsing/shaders/tilefragcolor.hglsl index 26fa48c32e..2b3252becd 100644 --- a/modules/globebrowsing/shaders/tilefragcolor.hglsl +++ b/modules/globebrowsing/shaders/tilefragcolor.hglsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -232,4 +232,4 @@ vec4 getTileFragColor(){ } -#endif ///TILE_FRAG_COLOR_HGLSL \ No newline at end of file +#endif ///TILE_FRAG_COLOR_HGLSL diff --git a/modules/globebrowsing/shaders/tilevertexheight.hglsl b/modules/globebrowsing/shaders/tilevertexheight.hglsl index ac4e4d4bf1..6733b30c96 100644 --- a/modules/globebrowsing/shaders/tilevertexheight.hglsl +++ b/modules/globebrowsing/shaders/tilevertexheight.hglsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014 * + * Copyright (c) 2014-2017 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -123,4 +123,4 @@ float getTileVertexSkirtLength(){ return tileVertexIsSkirtVertex() ? skirtLength : 0.0; } -#endif // TILE_VERTEX_HEIGHT_HGLSL \ No newline at end of file +#endif // TILE_VERTEX_HEIGHT_HGLSL diff --git a/modules/globebrowsing/tile/asynctilereader.cpp b/modules/globebrowsing/tile/asynctiledataprovider.cpp similarity index 81% rename from modules/globebrowsing/tile/asynctilereader.cpp rename to modules/globebrowsing/tile/asynctiledataprovider.cpp index 893bf70b58..537178d498 100644 --- a/modules/globebrowsing/tile/asynctilereader.cpp +++ b/modules/globebrowsing/tile/asynctiledataprovider.cpp @@ -22,28 +22,29 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include #include -#include +#include #include namespace openspace { namespace globebrowsing { -AsyncTileDataProvider::AsyncTileDataProvider(std::shared_ptr tileDataset, - std::shared_ptr pool) - : _tileDataset(tileDataset) +AsyncTileDataProvider::AsyncTileDataProvider( + const std::shared_ptr rawTileDataReader, + std::shared_ptr pool) + : _rawTileDataReader(rawTileDataReader) , _concurrentJobManager(pool) {} -std::shared_ptr AsyncTileDataProvider::getTextureDataProvider() const { - return _tileDataset; +std::shared_ptr AsyncTileDataProvider::getRawTileDataReader() const { + return _rawTileDataReader; } bool AsyncTileDataProvider::enqueueTileIO(const TileIndex& tileIndex) { if (satisfiesEnqueueCriteria(tileIndex)) { - auto job = std::make_shared(_tileDataset, tileIndex); + auto job = std::make_shared(_rawTileDataReader, tileIndex); //auto job = std::make_shared(_tileDataset, tileIndex, tileDiskCache, "ReadAndWrite"); _concurrentJobManager.enqueueJob(job); _enqueuedTileRequests[tileIndex.hashKey()] = tileIndex; @@ -61,6 +62,13 @@ std::vector> AsyncTileDataProvider::getRawTiles() { return readyResults; } +std::shared_ptr AsyncTileDataProvider::popFinishedRawTile() { + if (_concurrentJobManager.numFinishedJobs() > 0) + return _concurrentJobManager.popFinishedJob()->product(); + else + return nullptr; +} + bool AsyncTileDataProvider::satisfiesEnqueueCriteria(const TileIndex& tileIndex) const { // only allow tile to be enqueued if it's not already enqueued //return _futureTileIOResults.find(tileIndex.hashKey()) == _futureTileIOResults.end(); @@ -77,7 +85,7 @@ void AsyncTileDataProvider::reset() { while (_concurrentJobManager.numFinishedJobs() > 0) { _concurrentJobManager.popFinishedJob(); } - getTextureDataProvider()->reset(); + _rawTileDataReader->reset(); } void AsyncTileDataProvider::clearRequestQueue() { @@ -87,8 +95,8 @@ void AsyncTileDataProvider::clearRequestQueue() { _enqueuedTileRequests.clear(); } -float AsyncTileDataProvider::noDataValueAsFloat() { - return _tileDataset->noDataValueAsFloat(); +float AsyncTileDataProvider::noDataValueAsFloat() const { + return _rawTileDataReader->noDataValueAsFloat(); } } // namespace globebrowsing diff --git a/modules/globebrowsing/tile/asynctilereader.h b/modules/globebrowsing/tile/asynctiledataprovider.h similarity index 83% rename from modules/globebrowsing/tile/asynctilereader.h rename to modules/globebrowsing/tile/asynctiledataprovider.h index 445cd0c6f0..2863454f9c 100644 --- a/modules/globebrowsing/tile/asynctilereader.h +++ b/modules/globebrowsing/tile/asynctiledataprovider.h @@ -22,11 +22,10 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___ASYNC_TILE_READER___H__ -#define __OPENSPACE_MODULE_GLOBEBROWSING___ASYNC_TILE_READER___H__ +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___ASYNC_TILE_DATAPROVIDER___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___ASYNC_TILE_DATAPROVIDER___H__ #include - #include #include @@ -34,28 +33,29 @@ namespace openspace { namespace globebrowsing { -class RawTile; -class TileDataset; +struct RawTile; +class RawTileDataReader; class AsyncTileDataProvider { public: - AsyncTileDataProvider(std::shared_ptr textureDataProvider, + AsyncTileDataProvider(std::shared_ptr textureDataProvider, std::shared_ptr pool); bool enqueueTileIO(const TileIndex& tileIndex); std::vector> getRawTiles(); - + std::shared_ptr popFinishedRawTile(); + void reset(); void clearRequestQueue(); - std::shared_ptr getTextureDataProvider() const; - float noDataValueAsFloat(); + std::shared_ptr getRawTileDataReader() const; + float noDataValueAsFloat() const; protected: virtual bool satisfiesEnqueueCriteria(const TileIndex&) const; private: - std::shared_ptr _tileDataset; + std::shared_ptr _rawTileDataReader; ConcurrentJobManager _concurrentJobManager; std::unordered_map _enqueuedTileRequests; }; @@ -63,4 +63,4 @@ private: } // namespace globebrowsing } // namespace openspace -#endif // __OPENSPACE_MODULE_GLOBEBROWSING___ASYNC_TILE_READER___H__ +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___ASYNC_TILE_DATAPROVIDER___H__ diff --git a/modules/globebrowsing/tile/chunktile.h b/modules/globebrowsing/tile/chunktile.h index 5679123b9a..3fa3bcde07 100644 --- a/modules/globebrowsing/tile/chunktile.h +++ b/modules/globebrowsing/tile/chunktile.h @@ -34,6 +34,12 @@ namespace openspace { namespace globebrowsing { struct ChunkTile { + ChunkTile() : tile(Tile::TileUnavailable) {}; + ChunkTile(Tile tile, TileUvTransform uvTransform, TileDepthTransform depthTransform) : + tile(tile), + uvTransform(uvTransform), + depthTransform(depthTransform) {}; + Tile tile; TileUvTransform uvTransform; TileDepthTransform depthTransform; diff --git a/modules/globebrowsing/tile/loadjob/diskcachedtileloadjob.cpp b/modules/globebrowsing/tile/loadjob/diskcachedtileloadjob.cpp index 41a16afb6b..5e1911da69 100644 --- a/modules/globebrowsing/tile/loadjob/diskcachedtileloadjob.cpp +++ b/modules/globebrowsing/tile/loadjob/diskcachedtileloadjob.cpp @@ -25,17 +25,16 @@ #include #include -#include +#include #include namespace openspace { namespace globebrowsing { DiskCachedTileLoadJob::DiskCachedTileLoadJob( - std::shared_ptr textureDataProvider, - const TileIndex& tileIndex, - std::shared_ptr tdc, - CacheMode m) + std::shared_ptr textureDataProvider, + const TileIndex& tileIndex, std::shared_ptr tdc, + CacheMode m) : TileLoadJob(textureDataProvider, tileIndex) , _tileDiskCache(tdc) , _mode(m) @@ -46,26 +45,26 @@ void DiskCachedTileLoadJob::execute() { switch (_mode) { case CacheMode::Disabled: - _rawTile = _tileDataset->readTileData(_chunkIndex); + _rawTile = _rawTileDataReader->readTileData(_chunkIndex); break; case CacheMode::ReadOnly: _rawTile = _tileDiskCache->get(_chunkIndex); if (_rawTile == nullptr) { - _rawTile = _tileDataset->readTileData(_chunkIndex); + _rawTile = _rawTileDataReader->readTileData(_chunkIndex); } break; case CacheMode::ReadAndWrite: _rawTile = _tileDiskCache->get(_chunkIndex); if (_rawTile == nullptr) { - _rawTile = _tileDataset->readTileData(_chunkIndex); + _rawTile = _rawTileDataReader->readTileData(_chunkIndex); _tileDiskCache->put(_chunkIndex, _rawTile); } break; case CacheMode::WriteOnly: - _rawTile = _tileDataset->readTileData(_chunkIndex); + _rawTile = _rawTileDataReader->readTileData(_chunkIndex); _tileDiskCache->put(_chunkIndex, _rawTile); break; diff --git a/modules/globebrowsing/tile/loadjob/diskcachedtileloadjob.h b/modules/globebrowsing/tile/loadjob/diskcachedtileloadjob.h index 98c25e8598..4f20d98d65 100644 --- a/modules/globebrowsing/tile/loadjob/diskcachedtileloadjob.h +++ b/modules/globebrowsing/tile/loadjob/diskcachedtileloadjob.h @@ -41,7 +41,7 @@ struct DiskCachedTileLoadJob : public TileLoadJob { CacheHitsOnly, }; - DiskCachedTileLoadJob(std::shared_ptr textureDataProvider, + DiskCachedTileLoadJob(std::shared_ptr rawTileDataReader, const TileIndex& tileIndex, std::shared_ptr tdc, CacheMode cacheMode = CacheMode::ReadOnly); diff --git a/modules/globebrowsing/tile/loadjob/loadjob.h b/modules/globebrowsing/tile/loadjob/loadjob.h index 28aec76b70..ef1a5291dc 100644 --- a/modules/globebrowsing/tile/loadjob/loadjob.h +++ b/modules/globebrowsing/tile/loadjob/loadjob.h @@ -32,7 +32,7 @@ namespace openspace { namespace globebrowsing { -class RawTile; +struct RawTile; struct LoadJob : public Job { virtual void execute() = 0; diff --git a/modules/globebrowsing/tile/loadjob/tileloadjob.cpp b/modules/globebrowsing/tile/loadjob/tileloadjob.cpp index 20be5d229b..47c2e6030b 100644 --- a/modules/globebrowsing/tile/loadjob/tileloadjob.cpp +++ b/modules/globebrowsing/tile/loadjob/tileloadjob.cpp @@ -24,13 +24,18 @@ #include -#include +#include namespace openspace { namespace globebrowsing { +TileLoadJob::TileLoadJob(std::shared_ptr rawTileDataReader, + const TileIndex& tileIndex) + : _rawTileDataReader(rawTileDataReader) + , _chunkIndex(tileIndex) {} + void TileLoadJob::execute() { - _rawTile = _tileDataset->readTileData(_chunkIndex); + _rawTile = _rawTileDataReader->readTileData(_chunkIndex); } std::shared_ptr TileLoadJob::product() const { diff --git a/modules/globebrowsing/tile/loadjob/tileloadjob.h b/modules/globebrowsing/tile/loadjob/tileloadjob.h index a02538d1b7..68d59dce38 100644 --- a/modules/globebrowsing/tile/loadjob/tileloadjob.h +++ b/modules/globebrowsing/tile/loadjob/tileloadjob.h @@ -33,15 +33,12 @@ namespace openspace { namespace globebrowsing { -class TileDataset; -class RawTile; +class RawTileDataReader; +struct RawTile; struct TileLoadJob : LoadJob { - TileLoadJob(std::shared_ptr textureDataProvider, - const TileIndex& tileIndex) - : _tileDataset(textureDataProvider) - , _chunkIndex(tileIndex) - {} + TileLoadJob(std::shared_ptr rawTileDataReader, + const TileIndex& tileIndex); virtual ~TileLoadJob() = default; @@ -51,7 +48,7 @@ struct TileLoadJob : LoadJob { protected: TileIndex _chunkIndex; - std::shared_ptr _tileDataset; + std::shared_ptr _rawTileDataReader; std::shared_ptr _rawTile; }; diff --git a/modules/globebrowsing/tile/pixelregion.cpp b/modules/globebrowsing/tile/pixelregion.cpp index 7130b5d318..b24d7b263d 100644 --- a/modules/globebrowsing/tile/pixelregion.cpp +++ b/modules/globebrowsing/tile/pixelregion.cpp @@ -119,10 +119,12 @@ void PixelRegion::scale(double s) { void PixelRegion::downscalePow2(int exponent, PixelCoordinate wrt) { start += wrt; - start.x >>= exponent; - start.y >>= exponent; - numPixels.x >>= exponent; - numPixels.y >>= exponent; + start.x = ceil(start.x / static_cast(pow(2, exponent)));// >>= exponent; + start.y = ceil(start.y / static_cast(pow(2, exponent)));// >>= exponent; + numPixels.x = + ceil(numPixels.x / static_cast(pow(2, exponent)));// >>= exponent; + numPixels.y = + ceil(numPixels.y / static_cast(pow(2, exponent)));// >>= exponent; start -= wrt; } @@ -165,20 +167,25 @@ void PixelRegion::clampTo(const PixelRegion& boundingRegion) { void PixelRegion::forceNumPixelToDifferByNearestMultipleOf(unsigned int multiple) { ghoul_assert(multiple > 0, "multiple must be 1 or larger"); int sizeDiff = numPixels.x - numPixels.y; - if (std::abs(sizeDiff) > 0) { + if (static_cast(std::abs(static_cast(sizeDiff))) > 0) { if (sizeDiff > 0) { numPixels.y += sizeDiff % multiple; } else { - numPixels.x += std::abs(sizeDiff) % multiple; + numPixels.x += static_cast( + std::abs(static_cast(sizeDiff))) % multiple; } } } void PixelRegion::roundUpNumPixelToNearestMultipleOf(unsigned int multiple) { ghoul_assert(multiple > 0, "multiple must be 1 or larger"); - numPixels.x += numPixels.x % multiple; - numPixels.y += numPixels.y % multiple; + numPixels.x += (numPixels.x % multiple == 0) ? 0 : + (multiple - (numPixels.x % multiple)); + numPixels.y += (numPixels.y % multiple == 0) ? 0 : + (multiple - (numPixels.y % multiple)); + ghoul_assert((numPixels.x % multiple) == 0, "Round to nearest multiple failed"); + ghoul_assert((numPixels.y % multiple) == 0, "Round to nearest multiple failed"); } void PixelRegion::roundDownToQuadratic() { @@ -241,6 +248,8 @@ int PixelRegion::edge(Side side) const { return start.x + numPixels.x; case Side::BOTTOM: return start.y + numPixels.y; + default: + ghoul_assert(false, "Missing case label"); } } diff --git a/modules/globebrowsing/tile/pixelregion.h b/modules/globebrowsing/tile/pixelregion.h index 9a86a82270..e85f2a84b1 100644 --- a/modules/globebrowsing/tile/pixelregion.h +++ b/modules/globebrowsing/tile/pixelregion.h @@ -73,8 +73,8 @@ struct PixelRegion { void scale(const glm::dvec2& s); void scale(double s); - void downscalePow2(int exponent, PixelCoordinate wrt = {0,0}); - void upscalePow2(int exponent, PixelCoordinate wrt = { 0,0 }); + void downscalePow2(int exponent, PixelCoordinate wrt = { 0, 0 }); + void upscalePow2(int exponent, PixelCoordinate wrt = { 0, 0 }); void move(Side side, int amount); void pad(const PixelRegion& padding); diff --git a/modules/globebrowsing/tile/rawtile.cpp b/modules/globebrowsing/tile/rawtile.cpp index a0a3f4c00c..009019bc44 100644 --- a/modules/globebrowsing/tile/rawtile.cpp +++ b/modules/globebrowsing/tile/rawtile.cpp @@ -26,12 +26,6 @@ #include -#include - -namespace { - const std::string _loggerCat = "Tile"; -} - namespace openspace { namespace globebrowsing { @@ -40,7 +34,7 @@ RawTile::RawTile() , dimensions(0, 0, 0) , tileMetaData(nullptr) , tileIndex(0, 0, 0) - , error(CE_None) + , error(ReadError::None) , nBytesImageData(0) {} @@ -52,13 +46,13 @@ RawTile RawTile::createDefaultRes() { defaultRes.nBytesImageData = w * h * 1 * 3 * 4; // assume max 3 channels, max 4 bytes per pixel defaultRes.imageData = new char[defaultRes.nBytesImageData]; std::fill_n((char*)defaultRes.imageData, defaultRes.nBytesImageData, 0); - return std::move(defaultRes); + return defaultRes; } void RawTile::serializeMetaData(std::ostream& os) { os << dimensions.x << " " << dimensions.y << " " << dimensions.z << std::endl; os << tileIndex.x << " " << tileIndex.y << " " << tileIndex.level << std::endl; - os << error << std::endl; + os << static_cast(error) << std::endl; // preprocess data os << (tileMetaData != nullptr) << std::endl; @@ -73,7 +67,7 @@ RawTile RawTile::deserializeMetaData(std::istream& is) { RawTile res; is >> res.dimensions.x >> res.dimensions.y >> res.dimensions.z; is >> res.tileIndex.x >> res.tileIndex.y >> res.tileIndex.level; - int err; is >> err; res.error = (CPLErr) err; + int err; is >> err; res.error = static_cast(err); res.tileMetaData = nullptr; bool hastileMetaData; @@ -88,8 +82,8 @@ RawTile RawTile::deserializeMetaData(std::istream& is) { char binaryDataSeparator; is >> binaryDataSeparator; // not used - char* buffer = new char[res.nBytesImageData](); - return std::move(res); +// char* buffer = new char[res.nBytesImageData](); + return res; } } // namespace globebrowsing diff --git a/modules/globebrowsing/tile/rawtile.h b/modules/globebrowsing/tile/rawtile.h index fa436957f1..eb1d401ef0 100644 --- a/modules/globebrowsing/tile/rawtile.h +++ b/modules/globebrowsing/tile/rawtile.h @@ -26,28 +26,38 @@ #define __OPENSPACE_MODULE_GLOBEBROWSING___RAWTILE___H__ #include +#include #include #include #include -#include - namespace openspace { namespace globebrowsing { struct TileMetaData; struct RawTile { + + enum class ReadError { + None = 0, + Debug = 1, + Warning = 2, + Failure = 3, + Fatal = 4 + }; + RawTile(); char* imageData; glm::uvec3 dimensions; std::shared_ptr tileMetaData; TileIndex tileIndex; - CPLErr error; + ReadError error; size_t nBytesImageData; + GLuint glType; + TextureFormat textureFormat; void serializeMetaData(std::ostream& s); static RawTile deserializeMetaData(std::istream& s); diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp new file mode 100644 index 0000000000..9a2b454eb9 --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.cpp @@ -0,0 +1,412 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ +#ifdef GLOBEBROWSING_USE_GDAL + +#include + +#include +#include +#include +#include + +#include +#include // abspath +#include +#include +#include + +#include +#include +#include + +#include + +namespace { + const std::string _loggerCat = "GdalRawTileDataReader"; +} + +namespace openspace { +namespace globebrowsing { + +std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) { + return os << pr.start.x << ", " << pr.start.y << " with size " << pr.numPixels.x << + ", " << pr.numPixels.y; +} + +GdalRawTileDataReader::GdalRawTileDataReader(const std::string& filePath, + const Configuration& config, + const std::string& baseDirectory) + : RawTileDataReader(config) + , _dataset(nullptr) +{ + + std::string initDir = baseDirectory.empty() ? CPLGetCurrentDir() : baseDirectory; + + _initData = { initDir, filePath, config.tilePixelSize, config.dataType }; + ensureInitialized(); +} + +GdalRawTileDataReader::~GdalRawTileDataReader() { + if (_dataset != nullptr) { + GDALClose(_dataset); + _dataset = nullptr; + } +} + +void GdalRawTileDataReader::reset() { + _cached._maxLevel = -1; + if (_dataset != nullptr) { + GDALClose(_dataset); + _dataset = nullptr; + } + initialize(); +} + +int GdalRawTileDataReader::maxChunkLevel() { + ensureInitialized(); + if (_cached._maxLevel < 0) { + int numOverviews = _dataset->GetRasterBand(1)->GetOverviewCount(); + _cached._maxLevel = -_cached._tileLevelDifference; + if (numOverviews > 0) { + _cached._maxLevel += numOverviews - 1; + } + } + return _cached._maxLevel; +} + +float GdalRawTileDataReader::noDataValueAsFloat() const { + float noDataValue; + if (_dataset && _dataset->GetRasterBand(1)) { + noDataValue = _dataset->GetRasterBand(1)->GetNoDataValue();; + } + else { + noDataValue = std::numeric_limits::min(); + } + return noDataValue; +} + +int GdalRawTileDataReader::rasterXSize() const { + return _dataset->GetRasterXSize(); +} + +int GdalRawTileDataReader::rasterYSize() const { + return _dataset->GetRasterYSize(); +} + +float GdalRawTileDataReader::depthOffset() const { + return _dataset->GetRasterBand(1)->GetOffset(); +} + +float GdalRawTileDataReader::depthScale() const { + return _dataset->GetRasterBand(1)->GetScale(); +} + +std::array GdalRawTileDataReader::getGeoTransform() const { + std::array padfTransform; + CPLErr err = _dataset->GetGeoTransform(&padfTransform[0]); + if (err == CE_Failure) { + return RawTileDataReader::getGeoTransform(); + } + return padfTransform; +} + +IODescription GdalRawTileDataReader::getIODescription(const TileIndex& tileIndex) const { + IODescription io; + io.read.region = highestResPixelRegion(tileIndex); + + // write region starts in origin + io.write.region.start = PixelRegion::PixelCoordinate(0, 0); + io.write.region.numPixels = PixelRegion::PixelCoordinate(_initData.tilePixelSize, _initData.tilePixelSize); + + io.read.overview = 0; + io.read.fullRegion = gdalPixelRegion( + _dataset->GetRasterBand(1)); + // For correct sampling in dataset, we need to pad the texture tile + + PixelRegion scaledPadding = padding; + double scale = io.read.region.numPixels.x / static_cast(io.write.region.numPixels.x); + scaledPadding.numPixels *= scale; + scaledPadding.start *= scale; + + io.read.region.pad(scaledPadding); + io.write.region.pad(padding); + io.write.region.start = PixelRegion::PixelCoordinate(0, 0); + + + + io.write.bytesPerLine = _dataLayout.bytesPerPixel * io.write.region.numPixels.x; + io.write.totalNumBytes = io.write.bytesPerLine * io.write.region.numPixels.y; + + // OpenGL does not like if the number of bytes per line is not 4 + if (io.write.bytesPerLine % 4 != 0) { + io.write.region.roundUpNumPixelToNearestMultipleOf(4); + io.write.bytesPerLine = _dataLayout.bytesPerPixel * io.write.region.numPixels.x; + io.write.totalNumBytes = io.write.bytesPerLine * io.write.region.numPixels.y; + } + + return io; +} + +void GdalRawTileDataReader::initialize() { + _dataset = openGdalDataset(_initData.datasetFilePath); + + //Do any other initialization needed for the GdalRawTileDataReader + _dataLayout = getTileDataLayout(_initData.dataType); + _depthTransform = calculateTileDepthTransform(); + _cached._tileLevelDifference = + calculateTileLevelDifference(_initData.tilePixelSize); +} + +char* GdalRawTileDataReader::readImageData( + IODescription& io, RawTile::ReadError& worstError) const { + // allocate memory for the image + char* imageData = new char[io.write.totalNumBytes]; + + // In case there are extra channels not existing in the GDAL dataset + // we set the bytes to 255 (for example an extra alpha channel that) + // needs to be 1. + if (_dataLayout.numRasters > _dataLayout.numRastersAvailable) { + memset(imageData, 255, io.write.totalNumBytes); + } + + if (_dataLayout.numRastersAvailable == 3) // RGB -> BGR + { + for (size_t i = 0; i < _dataLayout.numRastersAvailable; i++) { + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageData + (i * _dataLayout.bytesPerDatum); + + RawTile::ReadError err = repeatedRasterRead(3 - i, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + } + else if (_dataLayout.numRastersAvailable == 4) // RGBA -> BGRA + { + for (size_t i = 0; i < 3; i++) { + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageData + (i * _dataLayout.bytesPerDatum); + + RawTile::ReadError err = repeatedRasterRead(3 - i, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageData + (3 * _dataLayout.bytesPerDatum); + + RawTile::ReadError err = repeatedRasterRead(4, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + else + { + // Read the data (each rasterband is a separate channel) + for (size_t i = 0; i < _dataLayout.numRastersAvailable; i++) { + GDALRasterBand* rasterBand = _dataset->GetRasterBand(i + 1); + + // The final destination pointer is offsetted by one datum byte size + // for every raster (or data channel, i.e. R in RGB) + char* dataDestination = imageData + (i * _dataLayout.bytesPerDatum); + + RawTile::ReadError err = repeatedRasterRead(i + 1, io, dataDestination); + + // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 + worstError = std::max(worstError, err); + } + } + + // GDAL reads pixel lines top to bottom, we want the opposite + return imageData; +} + +RawTile::ReadError GdalRawTileDataReader::rasterRead( + int rasterBand, const IODescription& io, char* dataDestination) const +{ + ghoul_assert(io.read.region.isInside(io.read.fullRegion), "write region of bounds!"); + ghoul_assert( + io.write.region.start.x >= 0 && io.write.region.start.y >= 0, + "Invalid write region" + ); + + PixelRegion::PixelCoordinate end = io.write.region.end(); + size_t largestIndex = + (end.y - 1) * io.write.bytesPerLine + (end.x - 1) * _dataLayout.bytesPerPixel; + ghoul_assert(largestIndex <= io.write.totalNumBytes, "Invalid write region"); + + char* dataDest = dataDestination; + + // GDAL reads pixels top to bottom, but we want our pixels bottom to top. + // Therefore, we increment the destination pointer to the last line on in the + // buffer, and the we specify in the rasterIO call that we want negative line + // spacing. Doing this compensates the flipped Y axis + dataDest += (io.write.totalNumBytes - io.write.bytesPerLine); + + // handle requested write region. Note -= since flipped y axis + dataDest -= io.write.region.start.y * io.write.bytesPerLine; + dataDest += io.write.region.start.x * _dataLayout.bytesPerPixel; + + CPLErr readError = _dataset->GetRasterBand(rasterBand)->RasterIO( + GF_Read, + io.read.region.start.x, // Begin read x + io.read.region.start.y, // Begin read y + io.read.region.numPixels.x, // width to read x + io.read.region.numPixels.y, // width to read y + dataDest, // Where to put data + io.write.region.numPixels.x, // width to write x in destination + io.write.region.numPixels.y, // width to write y in destination + _gdalType, // Type + _dataLayout.bytesPerPixel, // Pixel spacing + -io.write.bytesPerLine // Line spacing + ); + + // Convert error to RawTile::ReadError + RawTile::ReadError error; + switch (readError) { + case CE_None: error = RawTile::ReadError::None; break; + case CE_Debug: error = RawTile::ReadError::Debug; break; + case CE_Warning: error = RawTile::ReadError::Warning; break; + case CE_Failure: error = RawTile::ReadError::Failure; break; + case CE_Fatal: error = RawTile::ReadError::Fatal; break; + default: error = RawTile::ReadError::Failure; break; + } + return error; +} + +GDALDataset* GdalRawTileDataReader::openGdalDataset(const std::string& filePath) { + GDALDataset* dataset = static_cast(GDALOpen(filePath.c_str(), GA_ReadOnly)); + if (!dataset) { + using namespace ghoul::filesystem; + std::string correctedPath = FileSystem::ref().pathByAppendingComponent( + _initData.initDirectory, filePath + ); + + dataset = (GDALDataset *)GDALOpen(correctedPath.c_str(), GA_ReadOnly); + if (!dataset) { + throw ghoul::RuntimeError("Failed to load dataset:\n" + filePath); + } + } + return dataset; +} + +int GdalRawTileDataReader::calculateTileLevelDifference(int minimumPixelSize) { + GDALRasterBand* firstBand = _dataset->GetRasterBand(1); + GDALRasterBand* maxOverview; + int numOverviews = firstBand->GetOverviewCount(); + int sizeLevel0; + if (numOverviews <= 0) { // No overviews. Use first band. + maxOverview = firstBand; + } + else { // Pick the highest overview. + maxOverview = firstBand->GetOverview(numOverviews - 1); + } + sizeLevel0 = maxOverview->GetXSize(); + double diff = log2(minimumPixelSize) - log2(sizeLevel0); + return diff; +} + +bool GdalRawTileDataReader::gdalHasOverviews() const { + return _dataset->GetRasterBand(1)->GetOverviewCount() > 0; +} + +int GdalRawTileDataReader::gdalOverview( + const PixelRegion::PixelRange& regionSizeOverviewZero) const { + GDALRasterBand* firstBand = _dataset->GetRasterBand(1); + + int minNumPixels0 = glm::min(regionSizeOverviewZero.x, regionSizeOverviewZero.y); + + int overviews = firstBand->GetOverviewCount(); + GDALRasterBand* maxOverview = + overviews ? firstBand->GetOverview(overviews - 1) : firstBand; + + int sizeLevel0 = maxOverview->GetXSize(); + // The dataset itself may not have overviews but even if it does not, an overview + // for the data region can be calculated and possibly be used to sample greater + // Regions of the original dataset. + int ov = std::log2(minNumPixels0) - std::log2(sizeLevel0 + 1) - + _cached._tileLevelDifference; + ov = glm::clamp(ov, 0, overviews - 1); + + return ov; +} + +int GdalRawTileDataReader::gdalOverview(const TileIndex& tileIndex) const { + int overviews = _dataset->GetRasterBand(1)->GetOverviewCount(); + int ov = overviews - (tileIndex.level + _cached._tileLevelDifference + 1); + return glm::clamp(ov, 0, overviews - 1); +} + +int GdalRawTileDataReader::gdalVirtualOverview(const TileIndex& tileIndex) const { + int overviews = _dataset->GetRasterBand(1)->GetOverviewCount(); + int ov = overviews - (tileIndex.level + _cached._tileLevelDifference + 1); + return ov; +} + +PixelRegion GdalRawTileDataReader::gdalPixelRegion(GDALRasterBand* rasterBand) const { + PixelRegion gdalRegion; + gdalRegion.start.x = 0; + gdalRegion.start.y = 0; + gdalRegion.numPixels.x = rasterBand->GetXSize(); + gdalRegion.numPixels.y = rasterBand->GetYSize(); + return gdalRegion; +} + +TileDataLayout GdalRawTileDataReader::getTileDataLayout(GLuint preferredGlType) { + TileDataLayout layout; + + // Assume all raster bands have the same data type + _gdalType = preferredGlType != 0 ? + tiledatatype::getGdalDataType(preferredGlType) : + _dataset->GetRasterBand(1)->GetRasterDataType(); + + layout.glType = tiledatatype::getOpenGLDataType(_gdalType); + layout.numRastersAvailable = _dataset->GetRasterCount(); + layout.numRasters = layout.numRastersAvailable; + + // This is to avoid corrupted textures that can appear when the number of + // bytes per row is not a multiplie of 4. + // Info here: https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout + // This also mean that we need to make sure not to read from non existing + // rasters from the GDAL dataset + if (layout.numRasters == 3) { + layout.numRasters = 4; + } + + layout.bytesPerDatum = tiledatatype::numberOfBytes(_gdalType); + layout.bytesPerPixel = layout.bytesPerDatum * layout.numRasters; + layout.textureFormat = tiledatatype::getTextureFormatOptimized(layout.numRasters, _gdalType); + + return layout; +} + + +} // namespace globebrowsing +} // namespace openspace + +#endif // GLOBEBROWSING_USE_GDAL diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h new file mode 100644 index 0000000000..338f3f5a90 --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalrawtiledatareader.h @@ -0,0 +1,125 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_RAW_TILE_DATA_READER___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_RAW_TILE_DATA_READER___H__ + +#ifdef GLOBEBROWSING_USE_GDAL + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +class GDALDataset; +class GDALRasterBand; + +namespace openspace { +namespace globebrowsing { + +class GeodeticPatch; + +class GdalRawTileDataReader : public RawTileDataReader { +public: + + /** + * Opens a GDALDataset in readonly mode and calculates meta data required for + * reading tile using a TileIndex. + * + * \param filePath, a path to a specific file GDAL can read + * \param config, Configuration used for initialization + * \param baseDirectory, the base directory to use in future loading operations + */ + GdalRawTileDataReader(const std::string& filePath, const Configuration& config, + const std::string& baseDirectory = ""); + + virtual ~GdalRawTileDataReader() override; + + // Public virtual function overloading + virtual void reset() override; + virtual int maxChunkLevel() override; + virtual float noDataValueAsFloat() const override; + virtual int rasterXSize() const override; + virtual int rasterYSize() const override; + virtual float depthOffset() const override; + virtual float depthScale() const override; + +protected: + + /** + * Returns the geo transform from raster space to projection coordinates as defined + * by GDAL. + * If the transform is not available, the function returns a transform to map + * the pixel coordinates to cover the whole geodetic lat long space. + */ + virtual std::array getGeoTransform() const override; + virtual IODescription getIODescription(const TileIndex& tileIndex) const override; + +private: + // Private virtual function overloading + virtual void initialize() override; + virtual char* readImageData( + IODescription& io, RawTile::ReadError& worstError) const override; + virtual RawTile::ReadError rasterRead( + int rasterBand, const IODescription& io, char* dst) const override; + + // GDAL Helper methods + GDALDataset* openGdalDataset(const std::string& filePath); + int calculateTileLevelDifference(int minimumPixelSize); + bool gdalHasOverviews() const; + int gdalOverview(const PixelRegion::PixelRange& baseRegionSize) const; + int gdalOverview(const TileIndex& tileIndex) const; + int gdalVirtualOverview(const TileIndex& tileIndex) const; + PixelRegion gdalPixelRegion(GDALRasterBand* rasterBand) const; + TileDataLayout getTileDataLayout(GLuint prefferedGLType); + + // Member variables + struct InitData { + std::string initDirectory; + std::string datasetFilePath; + int tilePixelSize; + GLuint dataType; + } _initData; + + GDALDataset* _dataset; + GDALDataType _gdalType; // The type to reinterpret to when reading +}; + +} // namespace globebrowsing +} // namespace openspace + +#endif // GLOBEBROWSING_USE_GDAL + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_RAW_TILE_DATA_READER___H__ diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.cpp b/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.cpp new file mode 100644 index 0000000000..952dbb93f8 --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.cpp @@ -0,0 +1,190 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifdef GLOBEBROWSING_USE_GDAL + +#include + +#include +#include + +#include // abspath +#include +#include + +#include + +namespace { + const char* _loggerCat = "GdalWrapper"; +} + +namespace openspace { +namespace globebrowsing { + +void gdalErrorHandler(CPLErr eErrClass, int errNo, const char *msg) { + if (GdalWrapper::ref().logGdalErrors()) { + switch (eErrClass) { + case CE_None: break; + case CE_Debug: LDEBUG ("GDAL " << msg); break; + case CE_Warning: LWARNING("GDAL " << msg); break; + case CE_Failure: LERROR ("GDAL " << msg); break; + case CE_Fatal: LFATAL ("GDAL " << msg); break; + } + } +} + +GdalWrapper* GdalWrapper::_singleton = nullptr; +std::mutex GdalWrapper::_mutexLock; + +void GdalWrapper::create(size_t maximumCacheSize, + size_t maximumMaximumCacheSize) { + std::lock_guard guard(_mutexLock); + _singleton = new GdalWrapper(maximumCacheSize, maximumMaximumCacheSize); +} + +void GdalWrapper::destroy() { + std::lock_guard guard(_mutexLock); + ghoul_assert(_singleton, "Cannot delete null"); + delete _singleton; +} + +GdalWrapper& GdalWrapper::ref() { + ghoul_assert(_singleton, "GdalWrapper not created"); + return *_singleton; +} + +size_t GDALCacheUsed() { + return GDALGetCacheUsed64(); +} + +size_t GDALMaximumCacheSize() { + return GDALGetCacheMax64(); +} + +bool GdalWrapper::logGdalErrors() const { + return _logGdalErrors; +} + +GdalWrapper::GdalWrapper(size_t maximumCacheSize, + size_t maximumMaximumCacheSize) + : PropertyOwner("GdalWrapper") + , _logGdalErrors("logGdalErrors", "Log GDAL errors", true) + , _gdalMaximumCacheSize ( + "gdalMaximumCacheSize", "GDAL maximum cache size", + maximumCacheSize / (1024 * 1024), // Default + 0, // Minimum: No caching + maximumMaximumCacheSize / (1024 * 1024), // Maximum + 1 // Step: One MB + ) { + addProperty(_logGdalErrors); + addProperty(_gdalMaximumCacheSize); + + GDALAllRegister(); + CPLSetConfigOption( + "GDAL_DATA", + absPath("${MODULE_GLOBEBROWSING}/gdal_data").c_str() + ); + CPLSetConfigOption( + "CPL_TMPDIR", + absPath("${BASE_PATH}").c_str() + ); + setGdalProxyConfiguration(); + CPLSetErrorHandler(gdalErrorHandler); + + _gdalMaximumCacheSize.onChange([&] { + // MB to Bytes + GDALSetCacheMax64( + static_cast(_gdalMaximumCacheSize) * + 1024ULL * 1024ULL + ); + }); +} + +void GdalWrapper::setGdalProxyConfiguration() { + ghoul::Dictionary proxySettings; + bool proxyEnabled = OsEng.configurationManager().getValue( + ConfigurationManager::KeyHttpProxy, proxySettings + ); + if (proxyEnabled) { + std::string proxyAddress, proxyPort, proxyUser, proxyPassword, + proxyAuth; + + bool success = proxySettings.getValue( + ConfigurationManager::PartHttpProxyAddress, + proxyAddress + ); + success &= proxySettings.getValue( + ConfigurationManager::PartHttpProxyPort, + proxyPort + ); + proxySettings.getValue( + ConfigurationManager::PartHttpProxyAuthentication, + proxyAuth + ); + + std::string proxyAuthString = "BASIC"; + if (proxyAuth == "basic" || proxyAuth == "") { + proxyAuthString = "BASIC"; + } else if (proxyAuth == "ntlm") { + proxyAuthString = "NTLM"; + } else if (proxyAuth == "digest") { + proxyAuthString = "DIGEST"; + } else if (proxyAuth == "any") { + proxyAuthString = "ANY"; + } else { + success = false; + } + + bool userAndPassword = proxySettings.getValue( + ConfigurationManager::PartHttpProxyUser, + proxyUser + ); + userAndPassword &= proxySettings.getValue( + ConfigurationManager::PartHttpProxyPassword, + proxyPassword + ); + + if (success) { + std::string proxy = proxyAddress + ":" + proxyPort; + CPLSetConfigOption("GDAL_HTTP_PROXY", proxy.c_str()); + LDEBUG("Using proxy server " << proxy); + if (userAndPassword) { + std::string proxyUserPwd = proxyUser + ":" + proxyPassword; + CPLSetConfigOption("GDAL_HTTP_PROXYUSERPWD", proxyUserPwd.c_str()); + CPLSetConfigOption("GDAL_HTTP_PROXYAUTH", proxyAuthString.c_str()); + LDEBUG("Using authentication method: " << proxyAuthString); + } + } else { + LERROR("Invalid proxy settings for GDAL"); + } + } else { + LDEBUG("Setting up GDAL without proxy server"); + } +} + + +} // namespace globebrowsing +} // namespace openspace + +#endif // GLOBEBROWSING_USE_GDAL diff --git a/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.h b/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.h new file mode 100644 index 0000000000..c47818cd29 --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/gdalwrapper.h @@ -0,0 +1,96 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_WRAPPER___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_WRAPPER___H__ + +#ifdef GLOBEBROWSING_USE_GDAL + +#include +#include +#include + +#include + +#include +#include + +namespace openspace { +namespace globebrowsing { + +/** + * Function for passing GDAL error messages to the GHOUL logging system. + */ +static void gdalErrorHandler(CPLErr eErrClass, int errNo, const char* msg); + +/** + * Singleton class interfacing with global GDAL functions. + */ +class GdalWrapper : public properties::PropertyOwner { +public: + /** + * Create the singleton. Must be called before the class can be used. + * \param maximumCacheSize is the current maximum cache size GDAL can use + * for caching blocks in memory given in bytes. + * \param maximumMaximumCacheSize is the maximum cache size GDAL can use + * for caching blocks in memory given in bytes. + */ + static void create(size_t maximumCacheSize, size_t maximumMaximumCacheSize); + static void destroy(); + + static GdalWrapper& ref(); + + /** + * Get the current size of the GDAL in memory cache. + * \returns the number of bytes currently in the GDAL memory cache. + */ + static size_t GDALCacheUsed(); + + /** + * Get the maximum GDAL in memory cache size. + * \returns the maximum number of bytes allowed for the GDAL cache. + */ + static size_t GDALMaximumCacheSize(); + + bool logGdalErrors() const; + +private: + GdalWrapper(size_t maximumCacheSize, size_t maximumMaximumCacheSize); + ~GdalWrapper() = default; + + void setGdalProxyConfiguration(); + + properties::IntProperty _gdalMaximumCacheSize; + properties::BoolProperty _logGdalErrors; + + static GdalWrapper* _singleton; + static std::mutex _mutexLock; +}; + +} // namespace globebrowsing +} // namespace openspace + +#endif // GLOBEBROWSING_USE_GDAL + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___GDAL_WRAPPER___H__ diff --git a/modules/globebrowsing/tile/rawtiledatareader/iodescription.cpp b/modules/globebrowsing/tile/rawtiledatareader/iodescription.cpp new file mode 100644 index 0000000000..66b0fd1fcd --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/iodescription.cpp @@ -0,0 +1,70 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +namespace { + const char* _loggerCat = "IODescription"; +} + +namespace openspace { +namespace globebrowsing { + +IODescription IODescription::cut(PixelRegion::Side side, int pos) { + PixelRegion readPreCut = read.region; + PixelRegion writePreCut = write.region; + + glm::dvec2 ratio; + ratio.x = write.region.numPixels.x / static_cast(read.region.numPixels.x); + ratio.y = write.region.numPixels.y / static_cast(read.region.numPixels.y); + + IODescription whatCameOff = *this; + whatCameOff.read.region = read.region.globalCut(side, pos); + + PixelRegion::PixelRange cutSize = whatCameOff.read.region.numPixels; + PixelRegion::PixelRange localWriteCutSize = ratio * glm::dvec2(cutSize); + + if (cutSize.x == 0 || cutSize.y == 0) { + ghoul_assert( + read.region.equals(readPreCut), + "Read region should not have been modified" + ); + ghoul_assert( + write.region.equals(writePreCut), + "Write region should not have been modified" + ); + } + + int localWriteCutPos = + (side == PixelRegion::Side::LEFT || side == PixelRegion::Side::RIGHT) + ? localWriteCutSize.x : localWriteCutSize.y; + whatCameOff.write.region = write.region.localCut(side, localWriteCutPos); + + return whatCameOff; +} + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/rawtiledatareader/iodescription.h b/modules/globebrowsing/tile/rawtiledatareader/iodescription.h new file mode 100644 index 0000000000..5905a8a57c --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/iodescription.h @@ -0,0 +1,63 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___IO_DESCRIPTION___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___IO_DESCRIPTION___H__ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace openspace { +namespace globebrowsing { + +struct IODescription { + struct ReadData { + int overview; + PixelRegion region; + PixelRegion fullRegion; + } read; + + struct WriteData { + PixelRegion region; + size_t bytesPerLine; + size_t totalNumBytes; + } write; + + IODescription cut(PixelRegion::Side side, int pos); +}; + +} // namespace globebrowsing +} // namespace openspace + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___IO_DESCRIPTION___H__ diff --git a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp new file mode 100644 index 0000000000..18b8a381e5 --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.cpp @@ -0,0 +1,395 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +namespace openspace { +namespace globebrowsing { + +const glm::ivec2 RawTileDataReader::tilePixelStartOffset = glm::ivec2(-2); +const glm::ivec2 RawTileDataReader::tilePixelSizeDifference = glm::ivec2(4); + +const PixelRegion RawTileDataReader::padding = PixelRegion( + tilePixelStartOffset, + tilePixelSizeDifference +); + +RawTileDataReader::RawTileDataReader(const Configuration& config) + : _config(config) + , _hasBeenInitialized(false) +{} + +void RawTileDataReader::ensureInitialized() { + if (!_hasBeenInitialized) { + initialize(); + _hasBeenInitialized = true; + } +} + +std::shared_ptr RawTileDataReader::defaultTileData() { + PixelRegion pixelRegion = { + PixelRegion::PixelCoordinate(0, 0), + PixelRegion::PixelRange(16, 16) + }; + int bytesPerPixel = 1; // GL_R -> 1 bpp + std::shared_ptr rawTile = std::make_shared(); + rawTile->tileIndex = { 0, 0, 0 }; + rawTile->dimensions = glm::uvec3(pixelRegion.numPixels, 1); + rawTile->nBytesImageData = + rawTile->dimensions.x * rawTile->dimensions.y * bytesPerPixel; + rawTile->imageData = new char[rawTile->nBytesImageData]; + rawTile->glType = GL_UNSIGNED_BYTE; + rawTile->textureFormat = { ghoul::opengl::Texture::Format::Red, GL_R }; + + for (size_t i = 0; i < rawTile->nBytesImageData; ++i) { + rawTile->imageData[i] = 0; + } + rawTile->error = RawTile::ReadError::None; + + return rawTile; +} + +std::shared_ptr RawTileDataReader::readTileData(TileIndex tileIndex) { + ensureInitialized(); + IODescription io = getIODescription(tileIndex); + RawTile::ReadError worstError = RawTile::ReadError::None; + + // Build the RawTile from the data we querred + std::shared_ptr rawTile = std::make_shared(); + rawTile->imageData = readImageData(io, worstError); + rawTile->error = worstError; + rawTile->tileIndex = tileIndex; + rawTile->dimensions = glm::uvec3(io.write.region.numPixels, 1); + rawTile->nBytesImageData = io.write.totalNumBytes; + rawTile->glType = _dataLayout.glType; + rawTile->textureFormat = _dataLayout.textureFormat; + + if (_config.doPreProcessing) { + rawTile->tileMetaData = getTileMetaData(rawTile, io.write.region); + rawTile->error = std::max(rawTile->error, postProcessErrorCheck(rawTile, io)); + } + + return rawTile; +} + +TileDepthTransform RawTileDataReader::getDepthTransform() const { + return _depthTransform; +} + +std::array RawTileDataReader::getGeoTransform() const { + std::array padfTransform; + + GeodeticPatch globalCoverage(Geodetic2(0,0), Geodetic2(M_PI / 2.0, M_PI)); + padfTransform[1] = Angle::fromRadians( + globalCoverage.size().lon).asDegrees() / rasterXSize(); + padfTransform[5] = -Angle::fromRadians( + globalCoverage.size().lat).asDegrees() / rasterYSize(); + padfTransform[0] = Angle::fromRadians( + globalCoverage.getCorner(Quad::NORTH_WEST).lon).asDegrees(); + padfTransform[3] = Angle::fromRadians( + globalCoverage.getCorner(Quad::NORTH_WEST).lat).asDegrees(); + padfTransform[2] = 0; + padfTransform[4] = 0; + return padfTransform; +} + +PixelRegion::PixelCoordinate RawTileDataReader::geodeticToPixel( + const Geodetic2& geo) const { + std::array padfTransform = getGeoTransform(); + + double Y = Angle::fromRadians(geo.lat).asDegrees(); + double X = Angle::fromRadians(geo.lon).asDegrees(); + + // convert from pixel and line to geodetic coordinates + // Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2]; + // Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5]; + + // <=> + double* a = &(padfTransform[0]); + double* b = &(padfTransform[3]); + + // Xp = a[0] + P*a[1] + L*a[2]; + // Yp = b[0] + P*b[1] + L*b[2]; + + // <=> + double divisor = (a[2] * b[1] - a[1] * b[2]); + ghoul_assert(divisor != 0.0, "Division by zero!"); + //ghoul_assert(a[2] != 0.0, "a2 must not be zero!"); + double P = (a[0] * b[2] - a[2] * b[0] + a[2] * Y - b[2] * X) / divisor; + double L = (-a[0] * b[1] + a[1] * b[0] - a[1] * Y + b[1] * X) / divisor; + // ref: https://www.wolframalpha.com/input/?i=X+%3D+a0+%2B+a1P+%2B+a2L,+Y+%3D+b0+%2B+b1P+%2B+b2L,+solve+for+P+and+L + + double Xp = a[0] + P*a[1] + L*a[2]; + double Yp = b[0] + P*b[1] + L*b[2]; + + ghoul_assert(std::abs(X - Xp) < 1e-10, "inverse should yield X as before"); + ghoul_assert(std::abs(Y - Yp) < 1e-10, "inverse should yield Y as before"); + + return PixelRegion::PixelCoordinate(glm::round(P), glm::round(L)); +} + +Geodetic2 RawTileDataReader::pixelToGeodetic( + const PixelRegion::PixelCoordinate& p) const { + std::array padfTransform = getGeoTransform(); + Geodetic2 geodetic; + // Should be using radians and not degrees? + geodetic.lon = padfTransform[0] + p.x * padfTransform[1] + p.y * padfTransform[2]; + geodetic.lat = padfTransform[3] + p.x * padfTransform[4] + p.y * padfTransform[5]; + return geodetic; +} + +PixelRegion RawTileDataReader::highestResPixelRegion(const GeodeticPatch& geodeticPatch) const { + Geodetic2 nwCorner = geodeticPatch.getCorner(Quad::NORTH_WEST); + Geodetic2 swCorner = geodeticPatch.getCorner(Quad::SOUTH_EAST); + PixelRegion::PixelCoordinate pixelStart = geodeticToPixel(nwCorner); + PixelRegion::PixelCoordinate pixelEnd = geodeticToPixel(swCorner); + PixelRegion region(pixelStart, pixelEnd - pixelStart); + return region; +} + +RawTile::ReadError RawTileDataReader::repeatedRasterRead( + int rasterBand, const IODescription& fullIO, char* dataDestination, + int depth) const +{ + RawTile::ReadError worstError = RawTile::ReadError::None; + + // NOTE: + // Ascii graphics illustrates the implementation details of this method, for one + // specific case. Even though the illustrated case is specific, readers can + // hopefully find it useful to get the general idea. + + // Make a copy of the full IO desription as we will have to modify it + IODescription io = fullIO; + + // Example: + // We have an io description that defines a WRITE and a READ region. + // In this case the READ region extends outside of the defined io.read.fullRegion, + // meaning we will have to perform wrapping + + // io.write.region io.read.region + // | | + // V V + // +-------+ +-------+ + // | | | |--------+ + // | | | | | + // | | | | | + // +-------+ +-------+ | + // | | <-- io.read.fullRegion + // | | + // +--------------+ + + if (!io.read.region.isInside(io.read.fullRegion)) { + // Loop through each side: left, top, right, bottom + for (int i = 0; i < 4; ++i) { + + // Example: + // We are currently considering the left side of the pixel region + PixelRegion::Side side = static_cast(i); + IODescription cutoff = io.cut(side, io.read.fullRegion.edge(side)); + + // Example: + // We cut off the left part that was outside the io.read.fullRegion, and we + // now have an additional io description for the cut off region. + // Note that the cut-method used above takes care of the corresponding + // WRITE region for us. + + // cutoff.write.region cutoff.read.region + // | io.write.region | io.read.region + // | | | | + // V V V V + // +-+-----+ +-+-----+ + // | | | | | |--------+ + // | | | | | | | + // | | | | | | | + // +-+-----+ +-+-----+ | + // | | <-- io.read.fullRegion + // | | + // +--------------+ + + if (cutoff.read.region.area() > 0) { + // Wrap by repeating + PixelRegion::Side oppositeSide = static_cast((i + 2) % 4); + + cutoff.read.region.align( + oppositeSide, io.read.fullRegion.edge(oppositeSide)); + + // Example: + // The cut off region is wrapped to the opposite side of the region, + // i.e. "repeated". Note that we don't want WRITE region to change, + // we're only wrapping the READ region. + + // cutoff.write.region io.read.region cutoff.read.region + // | io.write.region | | + // | | V V + // V V +-----+ +-+ + // +-+-----+ | |------| | + // | | | | | | | + // | | | | | | | + // | | | +-----+ +-+ + // +-+-----+ | | <-- io.read.fullRegion + // | | + // +--------------+ + + // Example: + // The cutoff region has been repeated along one of its sides, but + // as we can see in this example, it still has a top part outside the + // defined gdal region. This is handled through recursion. + RawTile::ReadError err = repeatedRasterRead( + rasterBand, cutoff, dataDestination, depth + 1); + + worstError = std::max(worstError, err); + } + } + } + + RawTile::ReadError err = rasterRead(rasterBand, io, dataDestination); + + // The return error from a repeated rasterRead is ONLY based on the main region, + // which in the usual case will cover the main area of the patch anyway + return err; +} + +std::shared_ptr RawTileDataReader::getTileMetaData( + std::shared_ptr rawTile, const PixelRegion& region) +{ + ensureInitialized(); + size_t bytesPerLine = _dataLayout.bytesPerPixel * region.numPixels.x; + + TileMetaData* preprocessData = new TileMetaData(); + preprocessData->maxValues.resize(_dataLayout.numRasters); + preprocessData->minValues.resize(_dataLayout.numRasters); + preprocessData->hasMissingData.resize(_dataLayout.numRasters); + + std::vector noDataValues; + noDataValues.resize(_dataLayout.numRasters); + + for (size_t raster = 0; raster < _dataLayout.numRasters; ++raster) { + preprocessData->maxValues[raster] = -FLT_MAX; + preprocessData->minValues[raster] = FLT_MAX; + preprocessData->hasMissingData[raster] = false; + noDataValues[raster] = noDataValueAsFloat(); + } + + for (size_t y = 0; y < region.numPixels.y; ++y) { + size_t yi = (region.numPixels.y - 1 - y) * bytesPerLine; + size_t i = 0; + for (size_t x = 0; x < region.numPixels.x; ++x) { + for (size_t raster = 0; raster < _dataLayout.numRasters; ++raster) { + float noDataValue = noDataValueAsFloat(); + float val = tiledatatype::interpretFloat( + _dataLayout.glType, + &(rawTile->imageData[yi + i]) + ); + if (val != noDataValue) { + preprocessData->maxValues[raster] = std::max( + val, + preprocessData->maxValues[raster] + ); + preprocessData->minValues[raster] = std::min( + val, + preprocessData->minValues[raster] + ); + } + else { + preprocessData->hasMissingData[raster] = true; + } + i += _dataLayout.bytesPerDatum; + } + } + } + + return std::shared_ptr(preprocessData); +} + +float RawTileDataReader::depthOffset() const { + return 0.0f; +} + +float RawTileDataReader::depthScale() const { + return 1.0f; +} + +TileDepthTransform RawTileDataReader::calculateTileDepthTransform() { + bool isFloat = + (_dataLayout.glType == GL_FLOAT || _dataLayout.glType == GL_DOUBLE); + double maximumValue = + isFloat ? 1.0 : tiledatatype::getMaximumValue(_dataLayout.glType); + + TileDepthTransform transform; + transform.depthOffset = depthOffset(); + transform.depthScale = depthScale() * maximumValue; + return transform; +} + +RawTile::ReadError RawTileDataReader::postProcessErrorCheck( + std::shared_ptr rawTile, const IODescription& io) +{ + ensureInitialized(); + + double missingDataValue = noDataValueAsFloat(); + + bool hasMissingData = false; + + for (size_t c = 0; c < _dataLayout.numRasters; c++) { + hasMissingData |= rawTile->tileMetaData->maxValues[c] == missingDataValue; + } + + bool onHighLevel = rawTile->tileIndex.level > 6; + if (hasMissingData && onHighLevel) { + return RawTile::ReadError::Fatal; + } + return RawTile::ReadError::None; +} + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h new file mode 100644 index 0000000000..5a6d2ea3ae --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/rawtiledatareader.h @@ -0,0 +1,180 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___RAW_TILE_DATA_READER___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___RAW_TILE_DATA_READER___H__ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace openspace { +namespace globebrowsing { + +class GeodeticPatch; + +class RawTileDataReader { +public: + struct Configuration { + bool doPreProcessing; + int tilePixelSize; + GLuint dataType = 0; // default = no datatype reinterpretation + }; + + RawTileDataReader(const Configuration& config); + virtual ~RawTileDataReader() = default; + + /** + * Reads data from the current dataset and initializes a RawTile + * which gets returned. + */ + std::shared_ptr readTileData(TileIndex tileIndex); + TileDepthTransform getDepthTransform() const; + + /** + * \returns the maximum chunk level available in the dataset. Should be a value + * between 2 and 31. + */ + virtual int maxChunkLevel() = 0; + + /** + * Reset the dataset to its initial state. This is the place to clear any cache used. + */ + virtual void reset() = 0; + virtual float noDataValueAsFloat() const = 0; + virtual int rasterXSize() const = 0; + virtual int rasterYSize() const = 0; + virtual float depthOffset() const; + virtual float depthScale() const; + + /** + * Returns a single channeled empty RawTile of size 16 * 16 pixels. + */ + std::shared_ptr defaultTileData(); + + const static glm::ivec2 tilePixelStartOffset; + const static glm::ivec2 tilePixelSizeDifference; + + /// Padding around all tiles to read to make sure edge blending works. + const static PixelRegion padding; // same as the two above + +protected: + + /** + * This function should set the variables _cached, + * _dataLayout and _depthTransform. + */ + virtual void initialize() = 0; + + /** + * Call this in the constructor of the class extending RawTileDataReader + */ + void ensureInitialized(); + + /** + * The function returns a transform to map + * the pixel coordinates to cover the whole geodetic lat long space. + */ + virtual std::array getGeoTransform() const; + + /** + * Read image data as described by the given IODescription. + * \param io describes how to read the data. + * \param worstError should be set to the error code returned when + * reading the data. + */ + virtual char* readImageData( + IODescription& io, RawTile::ReadError& worstError) const = 0; + + virtual RawTile::ReadError rasterRead( + int rasterBand, const IODescription& io, char* dst) const = 0; + + virtual IODescription getIODescription(const TileIndex& tileIndex) const = 0; + + /** + * Get the pixel corresponding to a specific position on the globe defined by the + * Geodetic2 coordinate geo. If the dataset has overviews + * the function returns the pixel at the lowest overview (highest resolution). + * \param geo is the position on the globe to convert to pixel space. + * \returns a pixel coordinate in the dataset. + */ + PixelRegion::PixelCoordinate geodeticToPixel(const Geodetic2& geo) const; + + /** + * Get the geodetic coordinate corresponding to the given pixel in the dataset. If + * The dataset has overviews it is the lowest overview that is used. That is the + * one with highest resolution. + */ + Geodetic2 pixelToGeodetic(const PixelRegion::PixelCoordinate& p) const; + + /** + * Get a pixel region corresponding to the given GeodeticPatch. If the + * dataset has overviews the function returns the pixel region at the lowest overview + * (highest resolution). + * \param geodeticPatch is a patch covering an area in geodetic + * coordinates + * \returns a PixelRegion covering the given geodetic patch at highest + * resolution. + */ + PixelRegion highestResPixelRegion(const GeodeticPatch& geodeticPatch) const; + + /** + * A recursive function that is able to perform wrapping in case the read region of + * the given IODescription is outside of the given write region. + */ + RawTile::ReadError repeatedRasterRead( + int rasterBand, const IODescription& io, char* dst, int depth = 0) const; + + std::shared_ptr getTileMetaData( + std::shared_ptr result, const PixelRegion& region); + TileDepthTransform calculateTileDepthTransform(); + RawTile::ReadError postProcessErrorCheck( + std::shared_ptr ioResult, const IODescription& io); + + struct Cached { + int _maxLevel = -1; + double _tileLevelDifference; + } _cached; + const Configuration _config; + TileDataLayout _dataLayout; + TileDepthTransform _depthTransform; + +private: + bool _hasBeenInitialized; +}; + +} // namespace globebrowsing +} // namespace openspace + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___RAW_TILE_DATA_READER___H__ diff --git a/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.cpp b/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.cpp new file mode 100644 index 0000000000..096624fc25 --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.cpp @@ -0,0 +1,184 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include // abspath +#include +#include +#include + +#include + +namespace { + const std::string _loggerCat = "SimpleRawTileDataReader"; +} + +namespace openspace { +namespace globebrowsing { + +SimpleRawTileDataReader::SimpleRawTileDataReader( + const std::string& filePath, const Configuration& config) + : RawTileDataReader(config) +{ + _datasetFilePath = filePath; + ensureInitialized(); +} + +void SimpleRawTileDataReader::reset() { + initialize(); +} + +int SimpleRawTileDataReader::maxChunkLevel() { + return _cached._maxLevel; +} + +float SimpleRawTileDataReader::noDataValueAsFloat() const { + return 0.0f; +} + +int SimpleRawTileDataReader::rasterXSize() const { + return _dataTexture->dimensions().x; +} + +int SimpleRawTileDataReader::rasterYSize() const { + return _dataTexture->dimensions().y; +} + +float SimpleRawTileDataReader::depthOffset() const { + return 0.0f; +} + +float SimpleRawTileDataReader::depthScale() const { + return 1.0f; +} + +IODescription SimpleRawTileDataReader::getIODescription(const TileIndex& tileIndex) const { + IODescription io; + io.read.overview = 0; + io.read.region = highestResPixelRegion(tileIndex); + io.read.fullRegion = PixelRegion({0, 0}, {rasterXSize(), rasterYSize()}); + io.write.region = PixelRegion({0, 0}, io.read.region.numPixels); + io.write.bytesPerLine = _dataTexture->bytesPerPixel() * io.write.region.numPixels.x; + io.write.totalNumBytes = io.write.bytesPerLine * io.write.region.numPixels.y; + + return io; +} + +void SimpleRawTileDataReader::initialize() { + _dataTexture = ghoul::io::TextureReader::ref().loadTexture(_datasetFilePath); + if (_dataTexture == nullptr) { + throw ghoul::RuntimeError( + "Unable to read dataset: " + _datasetFilePath + + ".\nCompiling OpenSpace with GDAL will allow for better support for different" + "formats." + ); + } + float exponentX = log2(_dataTexture->dimensions().x); + float exponentY = log2(_dataTexture->dimensions().y); + if ( (exponentX - static_cast(exponentX)) > 0.0001 || + (exponentY - static_cast(exponentY)) > 0.0001 ) { + throw ghoul::RuntimeError( + "Unable to read dataset: " + _datasetFilePath + + ".\nCurrently only supporting power of 2 textures." + ); + } + + _cached._maxLevel = 2; + _cached._tileLevelDifference = 0; + + _dataLayout.glType = _dataTexture->dataType(); + _dataLayout.bytesPerDatum = tiledatatype::numberOfBytes(_dataLayout.glType); + _dataLayout.numRasters = tiledatatype::numberOfRasters(_dataTexture->format()); + _dataLayout.numRastersAvailable = _dataLayout.numRasters; + _dataLayout.bytesPerPixel = _dataLayout.bytesPerDatum * _dataLayout.numRasters; + _dataLayout.textureFormat = {_dataTexture->format(), _dataTexture->internalFormat()}; + + _depthTransform = {depthScale(), depthOffset()}; +} + +char* SimpleRawTileDataReader::readImageData( + IODescription& io, RawTile::ReadError& worstError) const { + // allocate memory for the image + char* imageData = new char[io.write.totalNumBytes]; + + // In case there are extra channels not existing in the dataset + // we set the bytes to 255 (for example an extra alpha channel that) + // needs to be 1. + if (_dataLayout.numRasters > _dataLayout.numRastersAvailable) { + memset(imageData, 255, io.write.totalNumBytes); + } + + // Modify to match OpenGL texture layout: + IODescription modifiedIO = io; + modifiedIO.read.region.start.y = modifiedIO.read.fullRegion.numPixels.y - modifiedIO.read.region.numPixels.y - modifiedIO.read.region.start.y; + + RawTile::ReadError err = repeatedRasterRead(0, modifiedIO, imageData); + + // None = 0, Debug = 1, Warning = 2, Failure = 3, Fatal = 4 + worstError = std::max(worstError, err); + + return imageData; +} + +RawTile::ReadError SimpleRawTileDataReader::rasterRead( + int rasterBand, const IODescription& io, char* dataDestination) const +{ + ghoul_assert(io.read.fullRegion.numPixels.x == _dataTexture->dimensions().x, + "IODescription does not match data texture."); + ghoul_assert(io.read.fullRegion.numPixels.y == _dataTexture->dimensions().y, + "IODescription does not match data texture."); + ghoul_assert(io.read.region.numPixels.x == io.write.region.numPixels.x, + "IODescription does not match data texture."); + ghoul_assert(io.read.region.numPixels.y == io.write.region.numPixels.y, + "IODescription does not match data texture."); + + char* pixelWriteRow = dataDestination; + try { + // For each row + for (int y = 0; y < io.read.region.numPixels.y; y++) { + int bytesPerLineDataTexture = + _dataTexture->bytesPerPixel() * _dataTexture->dimensions().x; + const char* textureRow = (static_cast(_dataTexture->pixelData()) + + io.read.region.start.x * _dataTexture->bytesPerPixel()) + + io.read.region.start.y * bytesPerLineDataTexture + + y * bytesPerLineDataTexture; + memcpy(pixelWriteRow, textureRow, io.write.bytesPerLine); + pixelWriteRow += io.write.bytesPerLine; + } + } catch (const std::exception&) { + return RawTile::ReadError::Failure; + } + return RawTile::ReadError::None; +} + + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tiledatalayout.cpp b/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h similarity index 61% rename from modules/globebrowsing/tile/tiledatalayout.cpp rename to modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h index f20a626f3e..cd3a86831e 100644 --- a/modules/globebrowsing/tile/tiledatalayout.cpp +++ b/modules/globebrowsing/tile/rawtiledatareader/simplerawtiledatareader.h @@ -22,71 +22,61 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include - -#include - -#include -#include - -#include -#include // abspath -#include +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___SIMPLE_RAW_TILE_DATA_READER___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___SIMPLE_RAW_TILE_DATA_READER___H__ +#include #include -#include - - -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include #include +#include #include #include -#include -#include -#include -namespace { - const std::string _loggerCat = "TileDataset"; -} +#include + +#include +#include +#include + +#include namespace openspace { namespace globebrowsing { -TileDataLayout::TileDataLayout() {} +class GeodeticPatch; -TileDataLayout::TileDataLayout(GDALDataset* dataSet, GLuint preferredGlType) { - // Assume all raster bands have the same data type - gdalType =preferredGlType != 0 ? - tiledatatype::getGdalDataType(preferredGlType) : - dataSet->GetRasterBand(1)->GetRasterDataType(); +class SimpleRawTileDataReader : public RawTileDataReader { +public: + + SimpleRawTileDataReader(const std::string& filePath, const Configuration& config); + + // Public virtual function overloading + virtual void reset() override; + virtual int maxChunkLevel() override; + virtual float noDataValueAsFloat() const override; + virtual int rasterXSize() const override; + virtual int rasterYSize() const override; + virtual float depthOffset() const override; + virtual float depthScale() const override; + +protected: + + virtual IODescription getIODescription(const TileIndex& tileIndex) const override; + +private: + // Private virtual function overloading + virtual void initialize() override; + virtual char* readImageData( + IODescription& io, RawTile::ReadError& worstError) const override; + virtual RawTile::ReadError rasterRead( + int rasterBand, const IODescription& io, char* dst) const override; + + // Member variables + std::string _datasetFilePath; + std::unique_ptr _dataTexture; +}; - glType = tiledatatype::getOpenGLDataType(gdalType); - numRasters = dataSet->GetRasterCount(); - bytesPerDatum = tiledatatype::numberOfBytes(gdalType); - bytesPerPixel = bytesPerDatum * numRasters; - textureFormat = tiledatatype::getTextureFormat(numRasters, gdalType); -} - } // namespace globebrowsing } // namespace openspace + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___SIMPLE_RAW_TILE_DATA_READER___H__ diff --git a/modules/globebrowsing/tile/rawtiledatareader/tiledatatype.cpp b/modules/globebrowsing/tile/rawtiledatareader/tiledatatype.cpp new file mode 100644 index 0000000000..9530ebe676 --- /dev/null +++ b/modules/globebrowsing/tile/rawtiledatareader/tiledatatype.cpp @@ -0,0 +1,474 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#ifdef GLOBEBROWSING_USE_GDAL +#include +#include +#endif // GLOBEBROWSING_USE_GDAL + +#include +#include // abspath +#include + +#include + +#include + +#include +#include + +namespace { + const char* _loggerCat = "TileDataType"; +} + +namespace openspace { +namespace globebrowsing { +namespace tiledatatype { + +#ifdef GLOBEBROWSING_USE_GDAL + +float interpretFloat(GDALDataType gdalType, const char* src) { + switch (gdalType) { + case GDT_Byte: + return static_cast(*reinterpret_cast(src)); + case GDT_UInt16: + return static_cast(*reinterpret_cast(src)); + case GDT_Int16: + return static_cast(*reinterpret_cast(src)); + case GDT_UInt32: + return static_cast(*reinterpret_cast(src)); + case GDT_Int32: + return static_cast(*reinterpret_cast(src)); + case GDT_Float32: + return static_cast(*reinterpret_cast(src)); + case GDT_Float64: + return static_cast(*reinterpret_cast(src)); + default: + ghoul_assert(false, "Unknown data type"); + } +} + +size_t numberOfBytes(GDALDataType gdalType) { + switch (gdalType) { + case GDT_Byte: + return sizeof(GLubyte); + case GDT_UInt16: + return sizeof(GLushort); + case GDT_Int16: + return sizeof(GLshort); + case GDT_UInt32: + return sizeof(GLuint); + case GDT_Int32: + return sizeof(GLint); + case GDT_Float32: + return sizeof(GLfloat); + case GDT_Float64: + return sizeof(GLdouble); + default: + ghoul_assert(false, "Unknown data type"); + } +} + +size_t getMaximumValue(GDALDataType gdalType) { + switch (gdalType) { + case GDT_Byte: + return 1 << 8; + case GDT_UInt16: + return 1 << 16; + case GDT_Int16: + return 1 << 15; + case GDT_UInt32: + return size_t(1) << 32; + case GDT_Int32: + return 1 << 31; + default: + ghoul_assert(false, "Unknown data type"); + } +} + +TextureFormat getTextureFormat(int rasterCount, GDALDataType gdalType) { + TextureFormat format; + + switch (rasterCount) { + case 1: // Red + format.ghoulFormat = ghoul::opengl::Texture::Format::Red; + switch (gdalType) { + case GDT_Byte: + format.glFormat = GL_R8; + break; + case GDT_UInt16: + format.glFormat = GL_R16UI; + break; + case GDT_Int16: + format.glFormat = GL_R16_SNORM; + break; + case GDT_UInt32: + format.glFormat = GL_R32UI; + break; + case GDT_Int32: + format.glFormat = GL_R32I; + break; + case GDT_Float32: + format.glFormat = GL_R32F; + break; + // No representation of 64 bit float? + //case GDT_Float64: + // format.glFormat = GL_RED; + // break; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + } + break; + case 2: + format.ghoulFormat = ghoul::opengl::Texture::Format::RG; + switch (gdalType) { + case GDT_Byte: + format.glFormat = GL_RG8; + break; + case GDT_UInt16: + format.glFormat = GL_RG16UI; + break; + case GDT_Int16: + format.glFormat = GL_RG16_SNORM; + break; + case GDT_UInt32: + format.glFormat = GL_RG32UI; + break; + case GDT_Int32: + format.glFormat = GL_RG32I; + break; + case GDT_Float32: + format.glFormat = GL_RG32F; + break; + case GDT_Float64: + format.glFormat = GL_RED; + break; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + } + break; + case 3: + format.ghoulFormat = ghoul::opengl::Texture::Format::RGB; + switch (gdalType) { + case GDT_Byte: + format.glFormat = GL_RGB8; + break; + case GDT_UInt16: + format.glFormat = GL_RGB16UI; + break; + case GDT_Int16: + format.glFormat = GL_RGB16_SNORM; + break; + case GDT_UInt32: + format.glFormat = GL_RGB32UI; + break; + case GDT_Int32: + format.glFormat = GL_RGB32I; + break; + case GDT_Float32: + format.glFormat = GL_RGB32F; + break; + // No representation of 64 bit float? + //case GDT_Float64: + // format.glFormat = GL_RED; + // break; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + } + break; + case 4: + format.ghoulFormat = ghoul::opengl::Texture::Format::RGBA; + switch (gdalType) { + case GDT_Byte: + format.glFormat = GL_RGBA8; + break; + case GDT_UInt16: + format.glFormat = GL_RGBA16UI; + break; + case GDT_Int16: + format.glFormat = GL_RGB16_SNORM; + break; + case GDT_UInt32: + format.glFormat = GL_RGBA32UI; + break; + case GDT_Int32: + format.glFormat = GL_RGBA32I; + break; + case GDT_Float32: + format.glFormat = GL_RGBA32F; + break; + // No representation of 64 bit float? + //case GDT_Float64: + // format.glFormat = GL_RED; + // break; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + } + break; + default: + LERROR("Unknown number of channels for OpenGL texture: " << rasterCount); + break; + } + return format; +} + +TextureFormat getTextureFormatOptimized(int rasterCount, GDALDataType gdalType) { + TextureFormat format; + + switch (rasterCount) { + case 1: // Red + format.ghoulFormat = ghoul::opengl::Texture::Format::Red; + switch (gdalType) { + case GDT_Byte: + format.glFormat = GL_R8; + break; + case GDT_UInt16: + format.glFormat = GL_R16UI; + break; + case GDT_Int16: + format.glFormat = GL_R16_SNORM; + break; + case GDT_UInt32: + format.glFormat = GL_R32UI; + break; + case GDT_Int32: + format.glFormat = GL_R32I; + break; + case GDT_Float32: + format.glFormat = GL_R32F; + break; + // No representation of 64 bit float? + //case GDT_Float64: + // format.glFormat = GL_RED; + // break; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + } + break; + case 2: + format.ghoulFormat = ghoul::opengl::Texture::Format::RG; + switch (gdalType) { + case GDT_Byte: + format.glFormat = GL_RG8; + break; + case GDT_UInt16: + format.glFormat = GL_RG16UI; + break; + case GDT_Int16: + format.glFormat = GL_RG16_SNORM; + break; + case GDT_UInt32: + format.glFormat = GL_RG32UI; + break; + case GDT_Int32: + format.glFormat = GL_RG32I; + break; + case GDT_Float32: + format.glFormat = GL_RG32F; + break; + case GDT_Float64: + format.glFormat = GL_RED; + break; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + } + break; + case 3: + format.ghoulFormat = ghoul::opengl::Texture::Format::BGR; + switch (gdalType) { + case GDT_Byte: + format.glFormat = GL_RGB8; + break; + case GDT_UInt16: + format.glFormat = GL_RGB16UI; + break; + case GDT_Int16: + format.glFormat = GL_RGB16_SNORM; + break; + case GDT_UInt32: + format.glFormat = GL_RGB32UI; + break; + case GDT_Int32: + format.glFormat = GL_RGB32I; + break; + case GDT_Float32: + format.glFormat = GL_RGB32F; + break; + // No representation of 64 bit float? + //case GDT_Float64: + // format.glFormat = GL_RED; + // break; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + } + break; + case 4: + format.ghoulFormat = ghoul::opengl::Texture::Format::BGRA; + switch (gdalType) { + case GDT_Byte: + format.glFormat = GL_RGBA8; + break; + case GDT_UInt16: + format.glFormat = GL_RGBA16UI; + break; + case GDT_Int16: + format.glFormat = GL_RGB16_SNORM; + break; + case GDT_UInt32: + format.glFormat = GL_RGBA32UI; + break; + case GDT_Int32: + format.glFormat = GL_RGBA32I; + break; + case GDT_Float32: + format.glFormat = GL_RGBA32F; + break; + // No representation of 64 bit float? + //case GDT_Float64: + // format.glFormat = GL_RED; + // break; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + } + break; + default: + LERROR("Unknown number of channels for OpenGL texture: " << rasterCount); + break; + } + return format; +} + +GLuint getOpenGLDataType(GDALDataType gdalType) { + switch (gdalType) { + case GDT_Byte: + return GL_UNSIGNED_BYTE; + case GDT_UInt16: + return GL_UNSIGNED_SHORT; + case GDT_Int16: + return GL_SHORT; + case GDT_UInt32: + return GL_UNSIGNED_INT; + case GDT_Int32: + return GL_INT; + case GDT_Float32: + return GL_FLOAT; + case GDT_Float64: + return GL_DOUBLE; + default: + LERROR("GDAL data type unknown to OpenGL: " << gdalType); + return GL_UNSIGNED_BYTE; + } +} + +GDALDataType getGdalDataType(GLuint glType) { + switch (glType) { + case GL_UNSIGNED_BYTE: + return GDT_Byte; + case GL_UNSIGNED_SHORT: + return GDT_UInt16; + case GL_SHORT: + return GDT_Int16; + case GL_UNSIGNED_INT: + return GDT_UInt32; + case GL_INT: + return GDT_Int32; + case GL_FLOAT: + return GDT_Float32; + case GL_DOUBLE: + return GDT_Float64; + default: + LERROR("OpenGL data type unknown to GDAL: " << glType); + return GDT_Unknown; + } +} + +#endif // GLOBEBROWSING_USE_GDAL + +size_t numberOfRasters(ghoul::opengl::Texture::Format format) { + switch (format) { + case ghoul::opengl::Texture::Format::Red: return 1; + case ghoul::opengl::Texture::Format::RG: return 2; + case ghoul::opengl::Texture::Format::RGB: return 3; + case ghoul::opengl::Texture::Format::RGBA: return 4; + default: ghoul_assert(false, "Unknown format"); + } +} + +size_t numberOfBytes(GLuint glType) { + switch (glType) { + case GL_UNSIGNED_BYTE: return sizeof(GLubyte); + case GL_UNSIGNED_SHORT: return sizeof(GLushort); + case GL_SHORT: return sizeof(GLshort); + case GL_UNSIGNED_INT: return sizeof(GLuint); + case GL_INT: return sizeof(GLint); + case GL_FLOAT: return sizeof(GLfloat); + case GL_DOUBLE: return sizeof(GLdouble); + default: + ghoul_assert(false, "Unknown data type"); + } +} + +size_t getMaximumValue(GLuint glType) { + switch (glType) { + case GL_UNSIGNED_BYTE: + return 1 << 8; + case GL_UNSIGNED_SHORT: + return 1 << 16; + case GL_SHORT: + return 1 << 15; + case GL_UNSIGNED_INT: + return size_t(1) << 32; + case GL_INT: + return 1 << 31; + default: + ghoul_assert(false, "Unknown data type"); + } +} + +float interpretFloat(GLuint glType, const char* src) { + switch (glType) { + case GL_UNSIGNED_BYTE: + return static_cast(*reinterpret_cast(src)); + case GL_UNSIGNED_SHORT: + return static_cast(*reinterpret_cast(src)); + case GL_SHORT: + return static_cast(*reinterpret_cast(src)); + case GL_UNSIGNED_INT: + return static_cast(*reinterpret_cast(src)); + case GL_INT: + return static_cast(*reinterpret_cast(src)); + case GL_FLOAT: + return static_cast(*reinterpret_cast(src)); + case GL_DOUBLE: + return static_cast(*reinterpret_cast(src)); + default: + ghoul_assert(false, "Unknown data type"); + } +} + +} // namespace tiledatatype +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tiledatatype.h b/modules/globebrowsing/tile/rawtiledatareader/tiledatatype.h similarity index 87% rename from modules/globebrowsing/tile/tiledatatype.h rename to modules/globebrowsing/tile/rawtiledatareader/tiledatatype.h index fd92aa07e0..26bee1a670 100644 --- a/modules/globebrowsing/tile/tiledatatype.h +++ b/modules/globebrowsing/tile/rawtiledatareader/tiledatatype.h @@ -26,28 +26,32 @@ #define __OPENSPACE_MODULE_GLOBEBROWSING___TILE_DATA_TYPE___H__ #include - #include #include +#ifdef GLOBEBROWSING_USE_GDAL #include +#endif // GLOBEBROWSING_USE_GDAL namespace openspace { namespace globebrowsing { namespace tiledatatype { +#ifdef GLOBEBROWSING_USE_GDAL GLuint getOpenGLDataType(GDALDataType gdalType); - GDALDataType getGdalDataType(GLuint glType); - TextureFormat getTextureFormat(int rasterCount, GDALDataType gdalType); - +TextureFormat getTextureFormatOptimized(int rasterCount, GDALDataType gdalType); size_t getMaximumValue(GDALDataType gdalType); - size_t numberOfBytes(GDALDataType gdalType); - float interpretFloat(GDALDataType gdalType, const char* src); +#endif // GLOBEBROWSING_USE_GDAL + +size_t numberOfRasters(ghoul::opengl::Texture::Format format); +size_t numberOfBytes(GLuint glType); +size_t getMaximumValue(GLuint glType); +float interpretFloat(GLuint glType, const char* src); } // namespace tiledatatype } // namespace globebrowsing diff --git a/modules/globebrowsing/tile/textureformat.h b/modules/globebrowsing/tile/textureformat.h index 4149b14a33..f90867213d 100644 --- a/modules/globebrowsing/tile/textureformat.h +++ b/modules/globebrowsing/tile/textureformat.h @@ -33,7 +33,7 @@ namespace globebrowsing { struct TextureFormat { ghoul::opengl::Texture::Format ghoulFormat; - GLuint glFormat; + GLint glFormat; }; diff --git a/modules/globebrowsing/tile/tile.cpp b/modules/globebrowsing/tile/tile.cpp index fb9307557e..6b0cd1ad53 100644 --- a/modules/globebrowsing/tile/tile.cpp +++ b/modules/globebrowsing/tile/tile.cpp @@ -22,9 +22,10 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include -#include +#include +#include namespace { const std::string _loggerCat = "Tile"; @@ -33,8 +34,22 @@ namespace { namespace openspace { namespace globebrowsing { -const Tile Tile::TileUnavailable = {nullptr, nullptr, Tile::Status::Unavailable }; - +const Tile Tile::TileUnavailable = Tile(nullptr, nullptr, Tile::Status::Unavailable); + +Tile::Tile(std::shared_ptr texture, + std::shared_ptr metaData, Status status) + : MemoryAwareCacheable( + (sizeof(Tile) + + (metaData ? sizeof(TileMetaData) : 0) + + (texture ? sizeof(ghoul::opengl::Texture) + texture->expectedPixelDataSize() * 2 : 0)) + // Multiply by two since double memory is used when creating mip maps. + / 1000 // Convert from bytes to kilobytes + ) + , _texture(texture) + , _metaData(metaData) + , _status(status) +{} + Tile Tile::createPlainTile(const glm::uvec2& size, const glm::uvec4& color) { using namespace ghoul::opengl; @@ -58,13 +73,9 @@ Tile Tile::createPlainTile(const glm::uvec2& size, const glm::uvec4& color) { texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); // Create tile - Tile tile; - tile.status = Tile::Status::OK; - tile.metaData = nullptr; - tile.texture = texture; - + Tile tile(texture, nullptr, Tile::Status::OK); return tile; -} +} glm::vec2 Tile::compensateSourceTextureSampling(glm::vec2 startOffset, glm::vec2 sizeDiff, glm::uvec2 resolution, glm::vec2 tileUV) @@ -81,8 +92,8 @@ glm::vec2 Tile::TileUvToTextureSamplePosition(const TileUvTransform& uvTransform { glm::vec2 uv = uvTransform.uvOffset + uvTransform.uvScale * tileUV; uv = compensateSourceTextureSampling( - TileDataset::tilePixelStartOffset, - TileDataset::tilePixelSizeDifference, + RawTileDataReader::tilePixelStartOffset, + RawTileDataReader::tilePixelSizeDifference, resolution, uv); return uv; diff --git a/modules/globebrowsing/tile/tile.h b/modules/globebrowsing/tile/tile.h index 5db9f53385..211c11d9c1 100644 --- a/modules/globebrowsing/tile/tile.h +++ b/modules/globebrowsing/tile/tile.h @@ -26,9 +26,10 @@ #define __OPENSPACE_MODULE_GLOBEBROWSING___TILE___H__ #include - #include +#include + #include namespace ghoul { namespace opengl { @@ -44,42 +45,49 @@ struct TileUvTransform; /** * Defines a status and may have a Texture and TileMetaData */ -struct Tile { - std::shared_ptr texture; - std::shared_ptr metaData; - - /** +class Tile : public cache::MemoryAwareCacheable { +public: + /** * Describe if this Tile is good for usage (OK) or otherwise * the reason why it is not. */ - enum class Status { - /** - * E.g when texture data is not currently in memory. + enum class Status { + /** + * E.g when texture data is not currently in memory. * texture and tileMetaData are both null */ - Unavailable, + Unavailable, /** - * Can be set by TileProviders if the requested - * TileIndex is undefined for that particular - * provider. + * Can be set by TileProviders if the requested + * TileIndex is undefined for that particular + * provider. * texture and metaData are both null */ - OutOfRange, + OutOfRange, /** * An IO Error happend * texture and metaData are both null */ - IOError, + IOError, /** * The Texture is uploaded to the GPU and good for usage. * texture is defined. metaData may be defined. */ - OK - } status; - + OK + }; + + Tile(std::shared_ptr texture, + std::shared_ptr metaData, + Status status); + ~Tile() = default; + + std::shared_ptr metaData() const { return _metaData; }; + Status status() const { return _status; }; + std::shared_ptr texture() const { return _texture; }; + /** * Instantiates a new tile with a single color. * @@ -90,18 +98,20 @@ struct Tile { * with the requested size and color */ static Tile createPlainTile(const glm::uvec2& size, const glm::uvec4& color); - static glm::vec2 compensateSourceTextureSampling(glm::vec2 startOffset, glm::vec2 sizeDiff, glm::uvec2 resolution, glm::vec2 tileUV); - static glm::vec2 TileUvToTextureSamplePosition(const TileUvTransform& uvTransform, glm::vec2 tileUV, glm::uvec2 resolution); - /** - * A tile with status unavailable that any user can return to - * indicate that a tile was unavailable. - */ + * A tile with status unavailable that any user can return to + * indicate that a tile was unavailable. + */ static const Tile TileUnavailable; + +private: + std::shared_ptr _texture; + std::shared_ptr _metaData; + Status _status; }; } // namespace globebrowsing diff --git a/modules/globebrowsing/tile/tiledatalayout.h b/modules/globebrowsing/tile/tiledatalayout.h index a030b13c13..06108e8f46 100644 --- a/modules/globebrowsing/tile/tiledatalayout.h +++ b/modules/globebrowsing/tile/tiledatalayout.h @@ -30,22 +30,21 @@ #include #include -#include - class GDALDataset; namespace openspace { namespace globebrowsing { struct TileDataLayout { - TileDataLayout(); - TileDataLayout(GDALDataset* dataSet, GLuint preferredGlType); - - GDALDataType gdalType; GLuint glType; size_t bytesPerDatum; size_t numRasters; + /// Number of rasters available in the GDAL dataset. + /// Does not necessarily have to be equal to numRasters. + /// In case an extra alpha channel needs to be added that + /// does not exist in the GDAL dataset for example + size_t numRastersAvailable; size_t bytesPerPixel; TextureFormat textureFormat; diff --git a/modules/globebrowsing/tile/tiledatareader/tiledatareader.cpp b/modules/globebrowsing/tile/tiledatareader/tiledatareader.cpp new file mode 100644 index 0000000000..b6f3a14033 --- /dev/null +++ b/modules/globebrowsing/tile/tiledatareader/tiledatareader.cpp @@ -0,0 +1,150 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +namespace { + const char* _loggerCat = "TileDataReader"; +} + +namespace openspace { +namespace globebrowsing { + +std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) { + return os << pr.start.x << ", " << pr.start.y << + " with size " << pr.numPixels.x << ", " << pr.numPixels.y; +} + +TileDataReader::TileDataReader(const Configuration& config) + : _config(config) +{} + +std::shared_ptr TileDataReader::defaultTileData() { + ensureInitialized(); + PixelRegion pixelRegion = { + PixelRegion::PixelCoordinate(0, 0), + PixelRegion::PixelRange(16, 16) + }; + std::shared_ptr rawTile = std::make_shared(); + rawTile->tileIndex = { 0, 0, 0 }; + rawTile->dimensions = glm::uvec3(pixelRegion.numPixels, 1); + rawTile->nBytesImageData = + rawTile->dimensions.x * rawTile->dimensions.y * _dataLayout.bytesPerPixel; + rawTile->imageData = new char[rawTile->nBytesImageData]; + for (size_t i = 0; i < rawTile->nBytesImageData; ++i) { + rawTile->imageData[i] = 0; + } + rawTile->error = RawTile::ReadError::None; + + if (_config.doPreProcessing) { + rawTile->tileMetaData = getTileMetaData(rawTile, pixelRegion); + } + + return rawTile; +} + +std::array TileDataset::getGeoTransform() const { + std::array padfTransform; + + // Global coverage of the whole latlon space + GeodeticPatch globalCoverage(Geodetic2(0,0), Geodetic2(M_PI / 2, M_PI)); + padfTransform[1] = Angle::fromRadians( + globalCoverage.size().lon).asDegrees() / rasterXSize(); + padfTransform[5] = -Angle::fromRadians( + globalCoverage.size().lat).asDegrees() / rasterYSize(); + padfTransform[0] = Angle::fromRadians( + globalCoverage.getCorner(Quad::NORTH_WEST).lon).asDegrees(); + padfTransform[3] = Angle::fromRadians( + globalCoverage.getCorner(Quad::NORTH_WEST).lat).asDegrees(); + padfTransform[2] = 0; + padfTransform[4] = 0; + + return padfTransform; +} + +PixelRegion::PixelCoordinate TileDataReader::geodeticToPixel(const Geodetic2& geo) const { + std::array padfTransform = getGeoTransform(); + + double Y = Angle::fromRadians(geo.lat).asDegrees(); + double X = Angle::fromRadians(geo.lon).asDegrees(); + + // convert from pixel and line to geodetic coordinates + // Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2]; + // Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5]; + + // <=> + double* a = &(padfTransform[0]); + double* b = &(padfTransform[3]); + + // Xp = a[0] + P*a[1] + L*a[2]; + // Yp = b[0] + P*b[1] + L*b[2]; + + // <=> + double divisor = (a[2] * b[1] - a[1] * b[2]); + ghoul_assert(divisor != 0.0, "Division by zero!"); + //ghoul_assert(a[2] != 0.0, "a2 must not be zero!"); + double P = (a[0] * b[2] - a[2] * b[0] + a[2] * Y - b[2] * X) / divisor; + double L = (-a[0] * b[1] + a[1] * b[0] - a[1] * Y + b[1] * X) / divisor; + // ref: https://www.wolframalpha.com/input/?i=X+%3D+a0+%2B+a1P+%2B+a2L,+Y+%3D+b0+%2B+b1P+%2B+b2L,+solve+for+P+and+L + + double Xp = a[0] + P*a[1] + L*a[2]; + double Yp = b[0] + P*b[1] + L*b[2]; + + ghoul_assert(abs(X - Xp) < 1e-10, "inverse should yield X as before"); + ghoul_assert(abs(Y - Yp) < 1e-10, "inverse should yield Y as before"); + + return PixelRegion::PixelCoordinate(glm::round(P), glm::round(L)); +} + +Geodetic2 TileDataReader::pixelToGeodetic(const PixelRegion::PixelCoordinate& p) const { + std::array padfTransform = getGeoTransform(); + Geodetic2 geodetic; + // Should be using radians and not degrees? + geodetic.lon = padfTransform[0] + p.x * padfTransform[1] + p.y * padfTransform[2]; + geodetic.lat = padfTransform[3] + p.x * padfTransform[4] + p.y * padfTransform[5]; + return geodetic; +} + +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tiledatareader/tiledatareader.h b/modules/globebrowsing/tile/tiledatareader/tiledatareader.h new file mode 100644 index 0000000000..316db41839 --- /dev/null +++ b/modules/globebrowsing/tile/tiledatareader/tiledatareader.h @@ -0,0 +1,92 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILE_DATAREADER___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___TILE_DATAREADER___H__ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace openspace { +namespace globebrowsing { + +struct RawTile; +class GeodeticPatch; + +/** + * Interface for reading RawTiles given a TileIndex + */ +class TileDataReader { +public: + struct Configuration { + bool doPreProcessing; + int minimumTilePixelSize; + GLuint dataType = 0; // default = no datatype reinterpretation + }; + + virtual TileDataReader(const Configuration& config); + + std::shared_ptr defaultTileData(); + + virtual std::shared_ptr readTileData(TileIndex tileIndex) = 0; + virtual int maxChunkLevel() = 0; + virtual TileDepthTransform getDepthTransform() = 0; + virtual const TileDataLayout& getDataLayout() = 0; + virtual void reset() = 0; + virtual float noDataValueAsFloat() = 0; + virtual size_t rasterXSize() = 0; + virtual size_t rasterYSize() = 0; + + const static glm::ivec2 tilePixelStartOffset; + const static glm::ivec2 tilePixelSizeDifference; + const static PixelRegion padding; // same as the two above + + const static glm::ivec2 tilePixelStartOffset; + const static glm::ivec2 tilePixelSizeDifference; + const static PixelRegion padding; // same as the two above + + static bool logReadErrors; + +protected: + Configuration _config; + + virtual std::array padfTransform getGeoTransform(); + PixelRegion::PixelCoordinate geodeticToPixel(const Geodetic2& geo) const; + Geodetic2 pixelToGeodetic(const PixelRegion::PixelCoordinate& p) const; +}; + +} // namespace globebrowsing +} // namespace openspace + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILE_DATAREADER___H__ diff --git a/modules/globebrowsing/tile/tiledataset.cpp b/modules/globebrowsing/tile/tiledataset.cpp deleted file mode 100644 index 67cb2a5dcd..0000000000 --- a/modules/globebrowsing/tile/tiledataset.cpp +++ /dev/null @@ -1,823 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2017 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include - -#include - -#include -#include - -#include -#include // abspath -#include - -#include -#include - - -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - const std::string _loggerCat = "TileDataset"; -} - -namespace openspace { -namespace globebrowsing { - -std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) { - return os << pr.start.x << ", " << pr.start.y << " with size " << pr.numPixels.x << ", " << pr.numPixels.y; -} - -TileDataset::IODescription TileDataset::IODescription::cut(PixelRegion::Side side, int pos) { - PixelRegion readPreCut = read.region; - PixelRegion writePreCut = write.region; - - glm::dvec2 ratio; - ratio.x = write.region.numPixels.x / (double) read.region.numPixels.x; - ratio.y = write.region.numPixels.y / (double) read.region.numPixels.y; - - double ratioRatio = ratio.x / ratio.y; - - //ghoul_assert(glm::abs(ratioRatio - 1.0) < 0.01, "Different read/write aspect ratio!"); - - IODescription whatCameOff = *this; - whatCameOff.read.region = read.region.globalCut(side, pos); - - PixelRegion::PixelRange cutSize = whatCameOff.read.region.numPixels; - PixelRegion::PixelRange localWriteCutSize = ratio * glm::dvec2(cutSize); - - if (cutSize.x == 0 || cutSize.y == 0) { - ghoul_assert( - read.region.equals(readPreCut), - "Read region should not have been modified" - ); - ghoul_assert( - write.region.equals(writePreCut), - "Write region should not have been modified" - ); - } - - int localWriteCutPos = (side == PixelRegion::Side::LEFT || side == PixelRegion::Side::RIGHT) - ? localWriteCutSize.x : localWriteCutSize.y; - whatCameOff.write.region = write.region.localCut(side, localWriteCutPos); - - return whatCameOff; -} - -const glm::ivec2 TileDataset::tilePixelStartOffset = glm::ivec2(-2); -const glm::ivec2 TileDataset::tilePixelSizeDifference = glm::ivec2(4); - -const PixelRegion TileDataset::padding = PixelRegion( - tilePixelStartOffset, - tilePixelSizeDifference -); - -bool TileDataset::GdalHasBeenInitialized = false; - -TileDataset::TileDataset(const std::string& gdalDatasetDesc, const Configuration& config) - : _config(config) - , hasBeenInitialized(false) -{ - _initData = { "", gdalDatasetDesc, config.minimumTilePixelSize, config.dataType }; - ensureInitialized(); - _initData.initDirectory = CPLGetCurrentDir(); -} - -void TileDataset::reset() { - _cached._maxLevel = -1; - if (_dataset != nullptr) { - GDALClose((GDALDatasetH)_dataset); - } - - initialize(); -} - -float TileDataset::noDataValueAsFloat() { - float noDataValue; - if (_dataset && _dataset->GetRasterBand(1)) { - noDataValue = _dataset->GetRasterBand(1)->GetNoDataValue();; - } - else { - noDataValue = std::numeric_limits::min(); - } - return noDataValue; -} - -void TileDataset::ensureInitialized() { - if (!hasBeenInitialized) { - initialize(); - hasBeenInitialized = true; - } - -} - -void TileDataset::initialize() { - gdalEnsureInitialized(); - - _dataset = gdalDataset(_initData.gdalDatasetDesc); - - //Do any other initialization needed for the TileDataset - _dataLayout = TileDataLayout(_dataset, _initData.dataType); - _depthTransform = calculateTileDepthTransform(); - _cached._tileLevelDifference = calculateTileLevelDifference(_initData.minimumPixelSize); -} - -void TileDataset::gdalEnsureInitialized() { - if (!GdalHasBeenInitialized) { - GDALAllRegister(); - CPLSetConfigOption( - "GDAL_DATA", - absPath("${MODULE_GLOBEBROWSING}/gdal_data").c_str() - ); - setGdalProxyConfiguration(); - GdalHasBeenInitialized = true; - } -} - -void TileDataset::setGdalProxyConfiguration() { - ghoul::Dictionary proxySettings; - bool proxyEnabled = OsEng.configurationManager().getValue( - ConfigurationManager::KeyHttpProxy, proxySettings - ); - if (proxyEnabled) { - std::string proxyAddress, proxyPort, proxyUser, proxyPassword, proxyAuth; - - bool success = proxySettings.getValue( - ConfigurationManager::PartHttpProxyAddress, - proxyAddress - ); - success &= proxySettings.getValue( - ConfigurationManager::PartHttpProxyPort, - proxyPort - ); - proxySettings.getValue( - ConfigurationManager::PartHttpProxyAuthentication, - proxyAuth - ); - - std::string proxyAuthString = "BASIC"; - if (proxyAuth == "basic" || proxyAuth == "") { - proxyAuthString = "BASIC"; - } else if (proxyAuth == "ntlm") { - proxyAuthString = "NTLM"; - } else if (proxyAuth == "digest") { - proxyAuthString = "DIGEST"; - } else if (proxyAuth == "any") { - proxyAuthString = "ANY"; - } else { - success = false; - } - - bool userAndPassword = proxySettings.getValue( - ConfigurationManager::PartHttpProxyUser, - proxyUser - ); - userAndPassword &= proxySettings.getValue( - ConfigurationManager::PartHttpProxyPassword, - proxyPassword - ); - - if (success) { - std::string proxy = proxyAddress + ":" + proxyPort; - CPLSetConfigOption("GDAL_HTTP_PROXY", proxy.c_str()); - LDEBUG("Using proxy server " << proxy); - if (userAndPassword) { - std::string proxyUserPwd = proxyUser + ":" + proxyPassword; - CPLSetConfigOption("GDAL_HTTP_PROXYUSERPWD", proxyUserPwd.c_str()); - CPLSetConfigOption("GDAL_HTTP_PROXYAUTH", proxyAuthString.c_str()); - LDEBUG("Using authentication method: " << proxyAuthString); - } - } else { - LERROR("Invalid proxy settings for GDAL"); - } - } else { - LDEBUG("Setting up GDAL without proxy server"); - } -} - -GDALDataset* TileDataset::gdalDataset(const std::string& gdalDatasetDesc) { - GDALDataset* dataset = (GDALDataset *)GDALOpen(gdalDatasetDesc.c_str(), GA_ReadOnly); - if (!dataset) { - using namespace ghoul::filesystem; - std::string correctedPath = FileSystem::ref().pathByAppendingComponent( - _initData.initDirectory, gdalDatasetDesc - ); - dataset = (GDALDataset *)GDALOpen(correctedPath.c_str(), GA_ReadOnly); - if (!dataset) { - throw ghoul::RuntimeError("Failed to load dataset:\n" + gdalDatasetDesc); - } - } - - // Commenting away the following for now since it is not supported for older - // versions of GDAL. Only used for debug info. - /* - const std::string originalDriverName = dataset->GetDriverName(); - - if (originalDriverName != "WMS") { - LDEBUG(" " << originalDriverName); - LDEBUG(" " << dataset->GetGCPProjection()); - LDEBUG(" " << dataset->GetProjectionRef()); - - GDALDriver* driver = dataset->GetDriver(); - char** metadata = driver->GetMetadata(); - for (int i = 0; metadata[i] != nullptr; i++) { - LDEBUG(" " << metadata[i]); - } - - const char* in_memory = ""; - //GDALDataset* vrtDataset = driver->CreateCopy(in_memory, dataset, false, nullptr, nullptr, nullptr); - } - */ - - return dataset; -} - -TileDataset::~TileDataset() { - delete _dataset; -} - -std::shared_ptr TileDataset::readTileData(TileIndex tileIndex) { - ensureInitialized(); - IODescription io = getIODescription(tileIndex); - CPLErr worstError = CPLErr::CE_None; - - // Build the RawTile from the data we querred - std::shared_ptr rawTile = std::make_shared(); - rawTile->imageData = readImageData(io, worstError); - rawTile->error = worstError; - rawTile->tileIndex = tileIndex; - rawTile->dimensions = glm::uvec3(io.write.region.numPixels, 1); - rawTile->nBytesImageData = io.write.totalNumBytes; - - if (_config.doPreProcessing) { - rawTile->tileMetaData = getTileMetaData(rawTile, io.write.region); - rawTile->error = std::max(rawTile->error, postProcessErrorCheck(rawTile, io)); - } - - return rawTile; -} - -std::shared_ptr TileDataset::defaultTileData() { - ensureInitialized(); - PixelRegion pixelRegion = { - PixelRegion::PixelCoordinate(0, 0), - PixelRegion::PixelRange(16, 16) - }; - std::shared_ptr rawTile = std::make_shared(); - rawTile->tileIndex = { 0, 0, 0 }; - rawTile->dimensions = glm::uvec3(pixelRegion.numPixels, 1); - rawTile->nBytesImageData = - rawTile->dimensions.x * rawTile->dimensions.y * _dataLayout.bytesPerPixel; - rawTile->imageData = new char[rawTile->nBytesImageData]; - for (size_t i = 0; i < rawTile->nBytesImageData; ++i) { - rawTile->imageData[i] = 0; - } - rawTile->error = CPLErr::CE_None; - - if (_config.doPreProcessing) { - rawTile->tileMetaData = getTileMetaData(rawTile, pixelRegion); - //rawTile->error = std::max(rawTile->error, postProcessErrorCheck(rawTile, io)); - } - - return rawTile; -} - -int TileDataset::maxChunkLevel() { - ensureInitialized(); - if (_cached._maxLevel < 0) { - int numOverviews = _dataset->GetRasterBand(1)->GetOverviewCount(); - _cached._maxLevel = -_cached._tileLevelDifference; - if (numOverviews > 0) { - _cached._maxLevel += numOverviews - 1; - } - } - return _cached._maxLevel; -} - -TileDepthTransform TileDataset::getDepthTransform() { - ensureInitialized(); - return _depthTransform; -} - -const TileDataLayout& TileDataset::getDataLayout() { - ensureInitialized(); - return _dataLayout; -} - -int TileDataset::calculateTileLevelDifference(int minimumPixelSize) { - GDALRasterBand* firstBand = _dataset->GetRasterBand(1); - GDALRasterBand* maxOverview; - int numOverviews = firstBand->GetOverviewCount(); - int sizeLevel0; - if (numOverviews <= 0) { // No overviews. Use first band. - maxOverview = firstBand; - } - else { // Pick the highest overview. - maxOverview = firstBand->GetOverview(numOverviews - 1); - } - sizeLevel0 = maxOverview->GetXSize(); - double diff = log2(minimumPixelSize) - log2(sizeLevel0); - return diff; -} - -TileDepthTransform TileDataset::calculateTileDepthTransform() { - GDALRasterBand* firstBand = _dataset->GetRasterBand(1); - - bool isFloat = - (_dataLayout.gdalType == GDT_Float32 || _dataLayout.gdalType == GDT_Float64); - double maximumValue = - isFloat ? 1.0 : tiledatatype::getMaximumValue(_dataLayout.gdalType); - - TileDepthTransform transform; - transform.depthOffset = firstBand->GetOffset(); - transform.depthScale = firstBand->GetScale() * maximumValue; - return transform; -} - -bool TileDataset::gdalHasOverviews() const { - return _dataset->GetRasterBand(1)->GetOverviewCount() > 0; -} - -int TileDataset::gdalOverview(const PixelRegion::PixelRange& regionSizeOverviewZero) const { - GDALRasterBand* firstBand = _dataset->GetRasterBand(1); - - int minNumPixels0 = glm::min(regionSizeOverviewZero.x, regionSizeOverviewZero.y); - - int overviews = firstBand->GetOverviewCount(); - GDALRasterBand* maxOverview = - overviews ? firstBand->GetOverview(overviews - 1) : firstBand; - - int sizeLevel0 = maxOverview->GetXSize(); - // The dataset itself may not have overviews but even if it does not, an overview - // for the data region can be calculated and possibly be used to sample greater - // Regions of the original dataset. - int ov = std::log2(minNumPixels0) - std::log2(sizeLevel0 + 1) - - _cached._tileLevelDifference; - ov = glm::clamp(ov, 0, overviews - 1); - - return ov; -} - -int TileDataset::gdalOverview(const TileIndex& tileIndex) const { - int overviews = _dataset->GetRasterBand(1)->GetOverviewCount(); - int ov = overviews - (tileIndex.level + _cached._tileLevelDifference + 1); - return glm::clamp(ov, 0, overviews - 1); -} - -int TileDataset::gdalVirtualOverview(const TileIndex& tileIndex) const { - int overviews = _dataset->GetRasterBand(1)->GetOverviewCount(); - int ov = overviews - (tileIndex.level + _cached._tileLevelDifference + 1); - return ov; -} - -PixelRegion TileDataset::gdalPixelRegion(GDALRasterBand* rasterBand) const { - PixelRegion gdalRegion; - gdalRegion.start.x = 0; - gdalRegion.start.y = 0; - gdalRegion.numPixels.x = rasterBand->GetXSize(); - gdalRegion.numPixels.y = rasterBand->GetYSize(); - return gdalRegion; -} - -PixelRegion TileDataset::gdalPixelRegion(const GeodeticPatch& geodeticPatch) const { - Geodetic2 nwCorner = geodeticPatch.getCorner(Quad::NORTH_WEST); - Geodetic2 swCorner = geodeticPatch.getCorner(Quad::SOUTH_EAST); - PixelRegion::PixelCoordinate pixelStart = geodeticToPixel(nwCorner); - PixelRegion::PixelCoordinate pixelEnd = geodeticToPixel(swCorner); - PixelRegion gdalRegion(pixelStart, pixelEnd - pixelStart); - return gdalRegion; -} - -GDALRasterBand* TileDataset::gdalRasterBand(int overview, int raster) const { - GDALRasterBand* rasterBand = _dataset->GetRasterBand(raster); - int numberOfOverviews = rasterBand->GetOverviewCount(); - rasterBand = gdalHasOverviews() ? rasterBand->GetOverview(overview) : rasterBand; - ghoul_assert(rasterBand != nullptr, "Rasterband is null"); - return rasterBand; -} - -std::array TileDataset::getGeoTransform() const { - std::array padfTransform; - CPLErr err = _dataset->GetGeoTransform(&padfTransform[0]); - if (err == CE_Failure) { - GeodeticPatch globalCoverage(Geodetic2(0,0), Geodetic2(M_PI / 2, M_PI)); - padfTransform[1] = Angle::fromRadians( - globalCoverage.size().lon).asDegrees() / _dataset->GetRasterXSize(); - padfTransform[5] = -Angle::fromRadians( - globalCoverage.size().lat).asDegrees() / _dataset->GetRasterYSize(); - padfTransform[0] = Angle::fromRadians( - globalCoverage.getCorner(Quad::NORTH_WEST).lon).asDegrees(); - padfTransform[3] = Angle::fromRadians( - globalCoverage.getCorner(Quad::NORTH_WEST).lat).asDegrees(); - padfTransform[2] = 0; - padfTransform[4] = 0; - } - return padfTransform; -} - -PixelRegion::PixelCoordinate TileDataset::geodeticToPixel(const Geodetic2& geo) const { - std::array padfTransform = getGeoTransform(); - - double Y = Angle::fromRadians(geo.lat).asDegrees(); - double X = Angle::fromRadians(geo.lon).asDegrees(); - - // convert from pixel and line to geodetic coordinates - // Xp = padfTransform[0] + P*padfTransform[1] + L*padfTransform[2]; - // Yp = padfTransform[3] + P*padfTransform[4] + L*padfTransform[5]; - - // <=> - double* a = &(padfTransform[0]); - double* b = &(padfTransform[3]); - - // Xp = a[0] + P*a[1] + L*a[2]; - // Yp = b[0] + P*b[1] + L*b[2]; - - // <=> - double divisor = (a[2] * b[1] - a[1] * b[2]); - ghoul_assert(divisor != 0.0, "Division by zero!"); - //ghoul_assert(a[2] != 0.0, "a2 must not be zero!"); - double P = (a[0] * b[2] - a[2] * b[0] + a[2] * Y - b[2] * X) / divisor; - double L = (-a[0] * b[1] + a[1] * b[0] - a[1] * Y + b[1] * X) / divisor; - // ref: https://www.wolframalpha.com/input/?i=X+%3D+a0+%2B+a1P+%2B+a2L,+Y+%3D+b0+%2B+b1P+%2B+b2L,+solve+for+P+and+L - - double Xp = a[0] + P*a[1] + L*a[2]; - double Yp = b[0] + P*b[1] + L*b[2]; - - ghoul_assert(abs(X - Xp) < 1e-10, "inverse should yield X as before"); - ghoul_assert(abs(Y - Yp) < 1e-10, "inverse should yield Y as before"); - - return PixelRegion::PixelCoordinate(glm::round(P), glm::round(L)); -} - -Geodetic2 TileDataset::pixelToGeodetic(const PixelRegion::PixelCoordinate& p) const { - std::array padfTransform = getGeoTransform(); - Geodetic2 geodetic; - // Should be using radians and not degrees? - geodetic.lon = padfTransform[0] + p.x * padfTransform[1] + p.y * padfTransform[2]; - geodetic.lat = padfTransform[3] + p.x * padfTransform[4] + p.y * padfTransform[5]; - return geodetic; -} - -TileDataset::IODescription TileDataset::getIODescription(const TileIndex& tileIndex) const { - IODescription io; - io.read.region = gdalPixelRegion(tileIndex); - - if (gdalHasOverviews()) { - int overview = gdalOverview(tileIndex); - io.read.overview = overview; - io.read.region.downscalePow2(overview + 1); - io.write.region = io.read.region; - io.read.region.pad(padding); - } - else { - io.read.overview = 0; - io.write.region = io.read.region; - int virtualOverview = gdalVirtualOverview(tileIndex); - io.write.region.downscalePow2(virtualOverview + 1); - PixelRegion scaledPadding = padding; - - scaledPadding.upscalePow2(std::max(virtualOverview + 1, 0)); - io.read.region.pad(scaledPadding); - } - - // For correct sampling in height dataset, we need to pad the texture tile - io.write.region.pad(padding); - PixelRegion::PixelRange preRound = io.write.region.numPixels; - io.write.region.roundDownToQuadratic(); - io.write.region.roundUpNumPixelToNearestMultipleOf(2); - if (preRound != io.write.region.numPixels) { - LDEBUG(tileIndex << " | " << preRound.x << ", " << preRound.y << " --> " << io.write.region.numPixels.x << ", " << io.write.region.numPixels.y); - } - - io.write.region.start = PixelRegion::PixelCoordinate(0, 0); // write region starts in origin - io.write.bytesPerLine = _dataLayout.bytesPerPixel * io.write.region.numPixels.x; - io.write.totalNumBytes = io.write.bytesPerLine * io.write.region.numPixels.y; - - return io; -} - -char* TileDataset::readImageData(IODescription& io, CPLErr& worstError) const { - // allocate memory for the image - char* imageData = new char[io.write.totalNumBytes]; - - // Read the data (each rasterband is a separate channel) - for (size_t i = 0; i < _dataLayout.numRasters; i++) { - GDALRasterBand* rasterBand = gdalRasterBand(io.read.overview, i + 1); - - // The final destination pointer is offsetted by one datum byte size - // for every raster (or data channel, i.e. R in RGB) - char* dataDestination = imageData + (i * _dataLayout.bytesPerDatum); - - CPLErr err = repeatedRasterIO(rasterBand, io, dataDestination); - - // CE_None = 0, CE_Debug = 1, CE_Warning = 2, CE_Failure = 3, CE_Fatal = 4 - worstError = std::max(worstError, err); - } - - // GDAL reads pixel lines top to bottom, we want the opposit - return imageData; -} - -CPLErr TileDataset::repeatedRasterIO(GDALRasterBand* rasterBand, const IODescription& fullIO, char* dataDestination, int depth) const { - std::string spaces = " "; - std::string indentation = spaces.substr(0, 2 * depth); - - CPLErr worstError = CPLErr::CE_None; - - // NOTE: - // Ascii graphics illustrates the implementation details of this method, for one - // specific case. Even though the illustrated case is specific, readers can - // hopefully find it useful to get the general idea. - - // Make a copy of the full IO desription as we will have to modify it - IODescription io = fullIO; - PixelRegion gdalRegion = gdalPixelRegion(rasterBand); - - - // Example: - // We have an io description that defines a WRITE and a READ region. - // In this case the READ region extends outside of the defined gdal region, - // meaning we will have to do wrapping - - - // io.write.region io.read.region - // | | - // V V - // +-------+ +-------+ - // | | | |--------+ - // | | | | | - // | | | | | - // +-------+ +-------+ | - // | | <-- gdalRegion - // | | - // +--------------+ - - - //LDEBUG(indentation << "-"); - //LDEBUG(indentation << "repeated read: " << io.read.region); - //LDEBUG(indentation << "repeated write: " << io.write.region); - - bool didCutOff = false; - - if (!io.read.region.isInside(gdalRegion)) { - // Loop through each side: left, top, right, bottom - for (int i = 0; i < 4; ++i) { - - // Example: - // We are currently considering the left side of the pixel region - PixelRegion::Side side = (PixelRegion::Side) i; - IODescription cutoff = io.cut(side, gdalRegion.edge(side)); - - // Example: - // We cut off the left part that was outside the gdal region, and we now - // have an additional io description for the cut off region. - // Note that the cut-method used above takes care of the corresponding - // WRITE region for us. - - // cutoff.write.region cutoff.read.region - // | io.write.region | io.read.region - // | | | | - // V V V V - // +-+-----+ +-+-----+ - // | | | | | |--------+ - // | | | | | | | - // | | | | | | | - // +-+-----+ +-+-----+ | - // | | <-- gdalRegion - // | | - // +--------------+ - - if (cutoff.read.region.area() > 0) { - didCutOff = true; - - // Wrap by repeating - PixelRegion::Side oppositeSide = (PixelRegion::Side) ((i + 2) % 4); - - cutoff.read.region.align(oppositeSide, gdalRegion.edge(oppositeSide)); - - // Example: - // The cut off region is wrapped to the opposite side of the region, - // i.e. "repeated". Note that we don't want WRITE region to change, - // we're only wrapping the READ region. - - // cutoff.write.region io.read.region cutoff.read.region - // | io.write.region | | - // | | V V - // V V +-----+ +-+ - // +-+-----+ | |------| | - // | | | | | | | - // | | | | | | | - // | | | +-----+ +-+ - // +-+-----+ | | <-- gdalRegion - // | | - // +--------------+ - - // Example: - // The cutoff region has been repeated along one of its sides, but - // as we can see in this example, it still has a top part outside the - // defined gdal region. This is handled through recursion. - CPLErr err = repeatedRasterIO(rasterBand, cutoff, dataDestination, depth + 1); - - worstError = std::max(worstError, err); - } - } - } - else if (worstError > CPLErr::CE_None) { - LDEBUG(indentation << "Error reading padding: " << worstError); - } - - CPLErr err = rasterIO(rasterBand, io, dataDestination); - worstError = std::max(worstError, err); - - // The return error from a repeated rasterIO is ONLY based on the main region, - // which in the usual case will cover the main area of the patch anyway - - return err; -} - -CPLErr TileDataset::rasterIO(GDALRasterBand* rasterBand, const IODescription& io, - char* dataDestination) const -{ - PixelRegion gdalRegion = gdalPixelRegion(rasterBand); - - ghoul_assert(io.read.region.isInside(gdalRegion), "write region of bounds!"); - ghoul_assert( - io.write.region.start.x >= 0 && io.write.region.start.y >= 0, - "Invalid write region" - ); - - PixelRegion::PixelCoordinate end = io.write.region.end(); - size_t largestIndex = - (end.y - 1) * io.write.bytesPerLine + (end.x - 1) * _dataLayout.bytesPerPixel; - ghoul_assert(largestIndex <= io.write.totalNumBytes, "Invalid write region"); - - char* dataDest = dataDestination; - - // OBS! GDAL reads pixels top to bottom, but we want our pixels bottom to top. - // Therefore, we increment the destination pointer to the last line on in the - // buffer, and the we specify in the rasterIO call that we want negative line - // spacing. Doing this compensates the flipped Y axis - dataDest += (io.write.totalNumBytes - io.write.bytesPerLine); - - // handle requested write region - dataDest -= io.write.region.start.y * io.write.bytesPerLine; // note -= since flipped y axis - dataDest += io.write.region.start.x * _dataLayout.bytesPerPixel; - - return rasterBand->RasterIO( - GF_Read, - io.read.region.start.x, // Begin read x - io.read.region.start.y, // Begin read y - io.read.region.numPixels.x, // width to read x - io.read.region.numPixels.y, // width to read y - dataDest, // Where to put data - io.write.region.numPixels.x, // width to write x in destination - io.write.region.numPixels.y, // width to write y in destination - _dataLayout.gdalType, // Type - _dataLayout.bytesPerPixel, // Pixel spacing - -io.write.bytesPerLine // Line spacing - ); -} - -std::shared_ptr TileDataset::getTileMetaData( - std::shared_ptr rawTile, - const PixelRegion& region) const -{ - size_t bytesPerLine = _dataLayout.bytesPerPixel * region.numPixels.x; - size_t totalNumBytes = bytesPerLine * region.numPixels.y; - - TileMetaData* preprocessData = new TileMetaData(); - preprocessData->maxValues.resize(_dataLayout.numRasters); - preprocessData->minValues.resize(_dataLayout.numRasters); - preprocessData->hasMissingData.resize(_dataLayout.numRasters); - - std::vector noDataValues; - noDataValues.resize(_dataLayout.numRasters); - - for (size_t c = 0; c < _dataLayout.numRasters; c++) { - preprocessData->maxValues[c] = -FLT_MAX; - preprocessData->minValues[c] = FLT_MAX; - preprocessData->hasMissingData[c] = false; - noDataValues[c] = _dataset->GetRasterBand(1)->GetNoDataValue(); - } - - for (size_t y = 0; y < region.numPixels.y; y++) { - size_t yi = (region.numPixels.y - 1 - y) * bytesPerLine; - size_t i = 0; - for (size_t x = 0; x < region.numPixels.x; x++) { - for (size_t c = 0; c < _dataLayout.numRasters; c++) { - float noDataValue = _dataset->GetRasterBand(c + 1)->GetNoDataValue(); - float val = tiledatatype::interpretFloat( - _dataLayout.gdalType, - &(rawTile->imageData[yi + i]) - ); - if (val != noDataValue) { - preprocessData->maxValues[c] = std::max( - val, - preprocessData->maxValues[c] - ); - preprocessData->minValues[c] = std::min( - val, - preprocessData->minValues[c] - ); - } - else { - preprocessData->hasMissingData[c] = true; - } - i += _dataLayout.bytesPerDatum; - } - } - } - - for (size_t c = 0; c < _dataLayout.numRasters; c++) { - if (preprocessData->maxValues[c] > 8800.0f) { - //LDEBUG("Bad preprocess data: " << preprocessData->maxValues[c] << " at " << region.tileIndex); - } - } - - return std::shared_ptr(preprocessData); -} - -CPLErr TileDataset::postProcessErrorCheck(std::shared_ptr rawTile, - const IODescription& io) const -{ - int success; - - double missingDataValue = gdalRasterBand(io.read.overview)->GetNoDataValue(&success); - if (!success) { - // missing data value for TERRAIN.wms. Should be specified in XML - missingDataValue = 32767; - } - - bool hasMissingData = false; - - for (size_t c = 0; c < _dataLayout.numRasters; c++) { - hasMissingData |= rawTile->tileMetaData->maxValues[c] == missingDataValue; - } - - bool onHighLevel = rawTile->tileIndex.level > 6; - if (hasMissingData && onHighLevel) { - return CE_Fatal; - } - // ugly test for heightmap overlay - if (_dataLayout.textureFormat.ghoulFormat == ghoul::opengl::Texture::Format::RG) { - // check the alpha - if (rawTile->tileMetaData->maxValues[1] == 0.0 - && rawTile->tileMetaData->minValues[1] == 0.0) - { - //return CE_Warning; - } - } - return CE_None; -} - -} // namespace globebrowsing -} // namespace openspace diff --git a/modules/globebrowsing/tile/tiledataset.h b/modules/globebrowsing/tile/tiledataset.h deleted file mode 100644 index 6bc692884d..0000000000 --- a/modules/globebrowsing/tile/tiledataset.h +++ /dev/null @@ -1,188 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2017 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILE_DATASET___H__ -#define __OPENSPACE_MODULE_GLOBEBROWSING___TILE_DATASET___H__ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -class GDALDataset; -class GDALRasterBand; - -namespace openspace { -namespace globebrowsing { - -class RawTile; -class GeodeticPatch; - -class TileDataset { -public: - struct Configuration { - bool doPreProcessing; - int minimumTilePixelSize; - GLuint dataType = 0; // default = no datatype reinterpretation - }; - - - /** - * Opens a GDALDataset in readonly mode and calculates meta data required for - * reading tile using a TileIndex. - * - * \param gdalDatasetDesc - A path to a specific file or raw XML describing the dataset - * \param minimumPixelSize - minimum number of pixels per side per tile requested - * \param datatype - datatype for storing pixel data in requested tile - */ - TileDataset(const std::string& gdalDatasetDesc, const Configuration& config); - - ~TileDataset(); - - - ////////////////////////////////////////////////////////////////////////////////// - // Public interface // - ////////////////////////////////////////////////////////////////////////////////// - std::shared_ptr readTileData(TileIndex tileIndex); - std::shared_ptr defaultTileData(); - int maxChunkLevel(); - TileDepthTransform getDepthTransform(); - const TileDataLayout& getDataLayout(); - void reset(); - float noDataValueAsFloat(); - - - const static glm::ivec2 tilePixelStartOffset; - const static glm::ivec2 tilePixelSizeDifference; - const static PixelRegion padding; // same as the two above - - -private: - struct IODescription { - struct ReadData { - int overview; - PixelRegion region; - } read; - - struct WriteData { - PixelRegion region; - size_t bytesPerLine; - size_t totalNumBytes; - } write; - - IODescription cut(PixelRegion::Side side, int pos); - }; - - - ////////////////////////////////////////////////////////////////////////////////// - // Initialization // - ////////////////////////////////////////////////////////////////////////////////// - - void initialize(); - void ensureInitialized(); - TileDepthTransform calculateTileDepthTransform(); - int calculateTileLevelDifference(int minimumPixelSize); - - - ////////////////////////////////////////////////////////////////////////////////// - // GDAL helper methods // - ////////////////////////////////////////////////////////////////////////////////// - - void gdalEnsureInitialized(); - void setGdalProxyConfiguration(); - GDALDataset* gdalDataset(const std::string& gdalDatasetDesc); - bool gdalHasOverviews() const; - int gdalOverview(const PixelRegion::PixelRange& baseRegionSize) const; - int gdalOverview(const TileIndex& tileIndex) const; - int gdalVirtualOverview(const TileIndex& tileIndex) const; - PixelRegion gdalPixelRegion(const GeodeticPatch& geodeticPatch) const; - PixelRegion gdalPixelRegion(GDALRasterBand* rasterBand) const; - GDALRasterBand* gdalRasterBand(int overview, int raster = 1) const; - - - ////////////////////////////////////////////////////////////////////////////////// - // ReadTileData helper functions // - ////////////////////////////////////////////////////////////////////////////////// - - /** - Returns the geo transform from raster space to projection coordinates as defined - by GDAL. - - If the transform is not available, the function returns a transform to map - the pixel coordinates to cover the whole geodetic lat long space. - */ - std::array getGeoTransform() const; - - PixelRegion::PixelCoordinate geodeticToPixel(const Geodetic2& geo) const; - Geodetic2 pixelToGeodetic(const PixelRegion::PixelCoordinate& p) const; - IODescription getIODescription(const TileIndex& tileIndex) const; - char* readImageData(IODescription& io, CPLErr& worstError) const; - CPLErr rasterIO(GDALRasterBand* rasterBand, const IODescription& io, char* dst) const; - CPLErr repeatedRasterIO(GDALRasterBand* rasterBand, const IODescription& io, char* dst, int depth = 0) const; - std::shared_ptr getTileMetaData(std::shared_ptr result, const PixelRegion& region) const; - CPLErr postProcessErrorCheck(std::shared_ptr ioResult, const IODescription& io) const; - - - - ////////////////////////////////////////////////////////////////////////////////// - // Member variables // - ////////////////////////////////////////////////////////////////////////////////// - - // init data - struct InitData { - std::string initDirectory; - std::string gdalDatasetDesc; - int minimumPixelSize; - GLuint dataType; - } _initData; - - struct Cached { - int _maxLevel = -1; - double _tileLevelDifference; - } _cached; - - const Configuration _config; - - - GDALDataset* _dataset; - TileDepthTransform _depthTransform; - TileDataLayout _dataLayout; - - static bool GdalHasBeenInitialized; - bool hasBeenInitialized; -}; - -} // namespace globebrowsing -} // namespace openspace - -#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILE_DATASET___H__ diff --git a/modules/globebrowsing/tile/tiledatatype.cpp b/modules/globebrowsing/tile/tiledatatype.cpp deleted file mode 100644 index 675751876c..0000000000 --- a/modules/globebrowsing/tile/tiledatatype.cpp +++ /dev/null @@ -1,282 +0,0 @@ - /***************************************************************************************** -* * -* OpenSpace * -* * -* Copyright (c) 2014-2016 * -* * -* Permission is hereby granted, free of charge, to any person obtaining a copy of this * -* software and associated documentation files (the "Software"), to deal in the Software * -* without restriction, including without limitation the rights to use, copy, modify, * -* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * -* permit persons to whom the Software is furnished to do so, subject to the following * -* conditions: * -* * -* The above copyright notice and this permission notice shall be included in all copies * -* or substantial portions of the Software. * -* * -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * -* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * -* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * -* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * -* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * -* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * -****************************************************************************************/ - -#include - -#include -#include - -#include -#include // abspath -#include - -#include - -#include - -#include -#include - -namespace { - const std::string _loggerCat = "RawTile"; -} - -namespace openspace { -namespace globebrowsing { -namespace tiledatatype { - -float interpretFloat(GDALDataType gdalType, const char* src) { - switch (gdalType) { - case GDT_Byte: - return static_cast(*reinterpret_cast(src)); - case GDT_UInt16: - return static_cast(*reinterpret_cast(src)); - case GDT_Int16: - return static_cast(*reinterpret_cast(src)); - case GDT_UInt32: - return static_cast(*reinterpret_cast(src)); - case GDT_Int32: - return static_cast(*reinterpret_cast(src)); - case GDT_Float32: - return static_cast(*reinterpret_cast(src)); - case GDT_Float64: - return static_cast(*reinterpret_cast(src)); - default: - ghoul_assert(false, "Unknown data type"); - } -} - -size_t numberOfBytes(GDALDataType gdalType) { - switch (gdalType) { - case GDT_Byte: - return sizeof(GLubyte); - case GDT_UInt16: - return sizeof(GLushort); - case GDT_Int16: - return sizeof(GLshort); - case GDT_UInt32: - return sizeof(GLuint); - case GDT_Int32: - return sizeof(GLint); - case GDT_Float32: - return sizeof(GLfloat); - case GDT_Float64: - return sizeof(GLdouble); - default: - ghoul_assert(false, "Unknown data type"); - - } -} - -size_t getMaximumValue(GDALDataType gdalType) { - switch (gdalType) { - case GDT_Byte: - return 1 << 8; - case GDT_UInt16: - return 1 << 16; - case GDT_Int16: - return 1 << 15; - case GDT_UInt32: - return 1 << 32; - case GDT_Int32: - return 1 << 31; - default: - ghoul_assert(false, "Unknown data type"); - - } -} - -TextureFormat getTextureFormat(int rasterCount, GDALDataType gdalType) { - TextureFormat format; - - switch (rasterCount) { - case 1: // Red - format.ghoulFormat = ghoul::opengl::Texture::Format::Red; - switch (gdalType) { - case GDT_Byte: - format.glFormat = GL_R8; - break; - case GDT_UInt16: - format.glFormat = GL_R16UI; - break; - case GDT_Int16: - format.glFormat = GL_R16_SNORM; - break; - case GDT_UInt32: - format.glFormat = GL_R32UI; - break; - case GDT_Int32: - format.glFormat = GL_R32I; - break; - case GDT_Float32: - format.glFormat = GL_R32F; - break; - // No representation of 64 bit float? - //case GDT_Float64: - // format.glFormat = GL_RED; - // break; - default: - LERROR("GDAL data type unknown to OpenGL: " << gdalType); - } - break; - case 2: - format.ghoulFormat = ghoul::opengl::Texture::Format::RG; - switch (gdalType) { - case GDT_Byte: - format.glFormat = GL_RG8; - break; - case GDT_UInt16: - format.glFormat = GL_RG16UI; - break; - case GDT_Int16: - format.glFormat = GL_RG16_SNORM; - break; - case GDT_UInt32: - format.glFormat = GL_RG32UI; - break; - case GDT_Int32: - format.glFormat = GL_RG32I; - break; - case GDT_Float32: - format.glFormat = GL_RG32F; - break; - case GDT_Float64: - format.glFormat = GL_RED; - break; - default: - LERROR("GDAL data type unknown to OpenGL: " << gdalType); - } - break; - case 3: - format.ghoulFormat = ghoul::opengl::Texture::Format::RGB; - switch (gdalType) { - case GDT_Byte: - format.glFormat = GL_RGB8; - break; - case GDT_UInt16: - format.glFormat = GL_RGB16UI; - break; - case GDT_Int16: - format.glFormat = GL_RGB16_SNORM; - break; - case GDT_UInt32: - format.glFormat = GL_RGB32UI; - break; - case GDT_Int32: - format.glFormat = GL_RGB32I; - break; - case GDT_Float32: - format.glFormat = GL_RGB32F; - break; - // No representation of 64 bit float? - //case GDT_Float64: - // format.glFormat = GL_RED; - // break; - default: - LERROR("GDAL data type unknown to OpenGL: " << gdalType); - } - break; - case 4: - format.ghoulFormat = ghoul::opengl::Texture::Format::RGBA; - switch (gdalType) { - case GDT_Byte: - format.glFormat = GL_RGBA8; - break; - case GDT_UInt16: - format.glFormat = GL_RGBA16UI; - break; - case GDT_Int16: - format.glFormat = GL_RGB16_SNORM; - break; - case GDT_UInt32: - format.glFormat = GL_RGBA32UI; - break; - case GDT_Int32: - format.glFormat = GL_RGBA32I; - break; - case GDT_Float32: - format.glFormat = GL_RGBA32F; - break; - // No representation of 64 bit float? - //case GDT_Float64: - // format.glFormat = GL_RED; - // break; - default: - LERROR("GDAL data type unknown to OpenGL: " << gdalType); - } - break; - default: - LERROR("Unknown number of channels for OpenGL texture: " << rasterCount); - break; - } - return format; -} - -GLuint getOpenGLDataType(GDALDataType gdalType) { - switch (gdalType) { - case GDT_Byte: - return GL_UNSIGNED_BYTE; - case GDT_UInt16: - return GL_UNSIGNED_SHORT; - case GDT_Int16: - return GL_SHORT; - case GDT_UInt32: - return GL_UNSIGNED_INT; - case GDT_Int32: - return GL_INT; - case GDT_Float32: - return GL_FLOAT; - case GDT_Float64: - return GL_DOUBLE; - default: - LERROR("GDAL data type unknown to OpenGL: " << gdalType); - return GL_UNSIGNED_BYTE; - } -} - -GDALDataType getGdalDataType(GLuint glType) { - switch (glType) { - case GL_UNSIGNED_BYTE: - return GDT_Byte; - case GL_UNSIGNED_SHORT: - return GDT_UInt16; - case GL_SHORT: - return GDT_Int16; - case GL_UNSIGNED_INT: - return GDT_UInt32; - case GL_INT: - return GDT_Int32; - case GL_FLOAT: - return GDT_Float32; - case GL_DOUBLE: - return GDT_Float64; - default: - LERROR("OpenGL data type unknown to GDAL: " << glType); - return GDT_Unknown; - } -} - -} // namespace tiledatatype -} // namespace globebrowsing -} // namespace openspace diff --git a/modules/globebrowsing/tile/tileindex.cpp b/modules/globebrowsing/tile/tileindex.cpp index 44d0ef8b44..f5ca66ab3a 100644 --- a/modules/globebrowsing/tile/tileindex.cpp +++ b/modules/globebrowsing/tile/tileindex.cpp @@ -28,6 +28,8 @@ #include +#include + namespace { const char* KeyLevel = "Level"; const char* KeyX = "X"; diff --git a/modules/globebrowsing/tile/tilemetadata.cpp b/modules/globebrowsing/tile/tilemetadata.cpp index 6c6c2b344e..2b7e20d9eb 100644 --- a/modules/globebrowsing/tile/tilemetadata.cpp +++ b/modules/globebrowsing/tile/tilemetadata.cpp @@ -24,8 +24,6 @@ #include -#include - namespace openspace { namespace globebrowsing { @@ -53,7 +51,7 @@ TileMetaData TileMetaData::deserialize(std::istream& is) { is >> res.minValues[i]; } - return std::move(res); + return res; } } // namespace globebrowsing diff --git a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp index 5cbacec25f..509bd60bf1 100644 --- a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.cpp @@ -24,21 +24,23 @@ #include -#include -#include +#include +#include +#include +#include #include +#include #include #include namespace { - const char* _loggerCat = "CachingTileProvider"; - const char* KeyDoPreProcessing = "DoPreProcessing"; - const char* KeyMinimumPixelSize = "MinimumPixelSize"; + const char* KeyTilePixelSize = "TilePixelSize"; const char* KeyFilePath = "FilePath"; - const char* KeyCacheSize = "CacheSize"; + const char* KeyBasePath = "BasePath"; const char* KeyFlushInterval = "FlushInterval"; + const char* KeyPreCacheLevel = "PreCacheLevel"; } namespace openspace { @@ -46,7 +48,9 @@ namespace globebrowsing { namespace tileprovider { CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary) - : _framesSinceLastRequestFlush(0) + : TileProvider(dictionary) + , _framesSinceLastRequestFlush(0) + , _defaultTile(Tile::TileUnavailable) { std::string name = "Name unspecified"; dictionary.getValue("Name", name); @@ -59,33 +63,36 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary) } // 2. Initialize default values for any optional Keys - TileDataset::Configuration config; + RawTileDataReader::Configuration config; config.doPreProcessing = false; - config.minimumTilePixelSize = 512; + config.tilePixelSize = 512; // getValue does not work for integers - double minimumPixelSize; - double cacheSize = 512; + double minimumPixelSize; double framesUntilRequestFlush = 60; // 3. Check for used spcified optional keys if (dictionary.getValue(KeyDoPreProcessing, config.doPreProcessing)) { LDEBUG("Default doPreProcessing overridden: " << config.doPreProcessing); } - if (dictionary.getValue(KeyMinimumPixelSize, minimumPixelSize)) { + if (dictionary.getValue(KeyTilePixelSize, minimumPixelSize)) { LDEBUG("Default minimumPixelSize overridden: " << minimumPixelSize); - config.minimumTilePixelSize = static_cast(minimumPixelSize); - } - if (dictionary.getValue(KeyCacheSize, cacheSize)) { - LDEBUG("Default cacheSize overridden: " << cacheSize); + config.tilePixelSize = static_cast(minimumPixelSize); } if (dictionary.getValue(KeyFlushInterval, framesUntilRequestFlush)) { LDEBUG("Default framesUntilRequestFlush overridden: " << framesUntilRequestFlush); } + std::string basePath; + dictionary.getValue(KeyBasePath, basePath); + // Initialize instance variables - auto tileDataset = std::make_shared(filePath, config); +#ifdef GLOBEBROWSING_USE_GDAL + auto tileDataset = std::make_shared(filePath, config, basePath); +#else // GLOBEBROWSING_USE_GDAL + auto tileDataset = std::make_shared(filePath, config); +#endif // GLOBEBROWSING_USE_GDAL // only one thread per provider supported atm // (GDAL does not handle multiple threads for a single dataset very well @@ -94,18 +101,28 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary) _asyncTextureDataProvider = std::make_shared( tileDataset, threadPool); - _tileCache = std::make_shared(static_cast(cacheSize)); _framesUntilRequestFlush = framesUntilRequestFlush; + + if (dictionary.hasKeyAndValue(KeyPreCacheLevel)) { + int preCacheLevel = static_cast(dictionary.value(KeyPreCacheLevel)); + LDEBUG("Precaching '" << filePath << "' with level '" << preCacheLevel << "'"); + for (int level = 0; level <= preCacheLevel; ++level) { + for (int x = 0; x <= level * 2; ++x) { + for (int y = 0; y <= level; ++y) { + _asyncTextureDataProvider->enqueueTileIO({ x, y, level }); + } + } + } + } } CachingTileProvider::CachingTileProvider( std::shared_ptr tileReader, - std::shared_ptr tileCache, int framesUntilFlushRequestQueue) : _asyncTextureDataProvider(tileReader) - , _tileCache(tileCache) , _framesUntilRequestFlush(framesUntilFlushRequestQueue) , _framesSinceLastRequestFlush(0) + , _defaultTile(Tile::TileUnavailable) {} CachingTileProvider::~CachingTileProvider(){ @@ -120,32 +137,29 @@ void CachingTileProvider::update() { } void CachingTileProvider::reset() { - _tileCache->clear(); - _asyncTextureDataProvider->reset(); + cache::MemoryAwareTileCache::ref().clear(); + //_asyncTextureDataProvider->reset(); } int CachingTileProvider::maxLevel() { - return _asyncTextureDataProvider->getTextureDataProvider()->maxChunkLevel(); + return _asyncTextureDataProvider->getRawTileDataReader()->maxChunkLevel(); } Tile CachingTileProvider::getTile(const TileIndex& tileIndex) { - Tile tile = Tile::TileUnavailable; - if (tileIndex.level > maxLevel()) { - tile.status = Tile::Status::OutOfRange; - return tile; + return Tile(nullptr, nullptr, Tile::Status::OutOfRange); } - TileIndex::TileHashKey key = tileIndex.hashKey(); + cache::ProviderTileKey key = { tileIndex, uniqueIdentifier() }; - if (_tileCache->exist(key)) { - return _tileCache->get(key); + if (cache::MemoryAwareTileCache::ref().exist(key)) { + return cache::MemoryAwareTileCache::ref().get(key); } else { _asyncTextureDataProvider->enqueueTileIO(tileIndex); } - return tile; + return Tile::TileUnavailable; } float CachingTileProvider::noDataValueAsFloat() { @@ -153,20 +167,20 @@ float CachingTileProvider::noDataValueAsFloat() { } Tile CachingTileProvider::getDefaultTile() { - if (_defaultTile.texture == nullptr) { + if (_defaultTile.texture() == nullptr) { _defaultTile = createTile( - _asyncTextureDataProvider->getTextureDataProvider()->defaultTileData() + _asyncTextureDataProvider->getRawTileDataReader()->defaultTileData() ); } return _defaultTile; } void CachingTileProvider::initTexturesFromLoadedData() { - auto rawTiles = _asyncTextureDataProvider->getRawTiles(); - for (auto rawTile : rawTiles){ - TileIndex::TileHashKey key = rawTile->tileIndex.hashKey(); + std::shared_ptr rawTile = _asyncTextureDataProvider->popFinishedRawTile(); + if (rawTile) { + cache::ProviderTileKey key = { rawTile->tileIndex, uniqueIdentifier() }; Tile tile = createTile(rawTile); - _tileCache->put(key, tile); + cache::MemoryAwareTileCache::ref().put(key, tile); } } @@ -176,56 +190,49 @@ void CachingTileProvider::clearRequestQueue() { } Tile::Status CachingTileProvider::getTileStatus(const TileIndex& tileIndex) { - auto tileDataset = _asyncTextureDataProvider->getTextureDataProvider(); - if (tileIndex.level > tileDataset->maxChunkLevel()) { + auto rawTileDataReader = _asyncTextureDataProvider->getRawTileDataReader(); + if (tileIndex.level > rawTileDataReader->maxChunkLevel()) { return Tile::Status::OutOfRange; } - TileIndex::TileHashKey key = tileIndex.hashKey(); + cache::ProviderTileKey key = { tileIndex, uniqueIdentifier() }; - if (_tileCache->exist(key)) { - return _tileCache->get(key).status; + if (cache::MemoryAwareTileCache::ref().exist(key)) { + return cache::MemoryAwareTileCache::ref().get(key).status(); } return Tile::Status::Unavailable; } TileDepthTransform CachingTileProvider::depthTransform() { - return _asyncTextureDataProvider->getTextureDataProvider()->getDepthTransform(); + return _asyncTextureDataProvider->getRawTileDataReader()->getDepthTransform(); } Tile CachingTileProvider::createTile(std::shared_ptr rawTile) { - if (rawTile->error != CE_None) { - return{ nullptr, nullptr, Tile::Status::IOError }; + if (rawTile->error != RawTile::ReadError::None) { + return Tile(nullptr, nullptr, Tile::Status::IOError); } - TileIndex::TileHashKey key = rawTile->tileIndex.hashKey(); - TileDataLayout dataLayout = - _asyncTextureDataProvider->getTextureDataProvider()->getDataLayout(); + //TileDataLayout dataLayout = + // _asyncTextureDataProvider->getTextureDataProvider()->getDataLayout(); // The texture should take ownership of the data using ghoul::opengl::Texture; std::shared_ptr texture = std::make_shared( rawTile->imageData, rawTile->dimensions, - dataLayout.textureFormat.ghoulFormat, - dataLayout.textureFormat.glFormat, - dataLayout.glType, + rawTile->textureFormat.ghoulFormat, + rawTile->textureFormat.glFormat, + rawTile->glType, Texture::FilterMode::Linear, Texture::WrappingMode::ClampToEdge); texture->uploadTexture(); - // AnisotropicMipMap must be set after texture is uploaded. Why?! + // AnisotropicMipMap must be set after texture is uploaded texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); - Tile tile = { - texture, - rawTile->tileMetaData, - Tile::Status::OK - }; - - return tile; + return Tile(texture, rawTile->tileMetaData, Tile::Status::OK); } } // namespace tileprovider diff --git a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.h b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.h index 8a1669cf96..b8f836f03e 100644 --- a/modules/globebrowsing/tile/tileprovider/cachingtileprovider.h +++ b/modules/globebrowsing/tile/tileprovider/cachingtileprovider.h @@ -26,12 +26,13 @@ #define __OPENSPACE_MODULE_GLOBEBROWSING___CACHING_TILE_PROVIDER___H__ #include +#include namespace openspace { namespace globebrowsing { class AsyncTileDataProvider; -class RawTile; +struct RawTile; namespace tileprovider { @@ -44,8 +45,7 @@ public: CachingTileProvider(const ghoul::Dictionary& dictionary); CachingTileProvider( - std::shared_ptr tileReader, - std::shared_ptr tileCache, + std::shared_ptr tileReader, int framesUntilFlushRequestQueue); virtual ~CachingTileProvider(); @@ -87,7 +87,7 @@ private: void clearRequestQueue(); std::shared_ptr _asyncTextureDataProvider; - std::shared_ptr _tileCache; + //std::shared_ptr _tileCache; int _framesSinceLastRequestFlush; int _framesUntilRequestFlush; diff --git a/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp new file mode 100644 index 0000000000..40c2708ea3 --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp @@ -0,0 +1,118 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include + +namespace { + const std::string _loggerCat = "PresentationSlideProvider"; + + const std::string KeyDefaultProvider = "DefaultProvider"; + const std::string KeySlideProviders = "SlideProviders"; + const std::string KeyTileIndex = "TileIndex"; + const std::string KeyTileProvider = "TileProvider"; +} + +namespace openspace { +namespace globebrowsing { +namespace tileprovider { + +PresentationSlideProvider::PresentationSlideProvider(const ghoul::Dictionary& dictionary) + : _slideIndex("slideIndex", "slideIndex", 0, 0, _slideProviders.size() - 1) +{ + setName("SlideProvider"); + ghoul::Dictionary defaultProviderDict = dictionary.value(KeyDefaultProvider); + _defaultProvider = TileProvider::createFromDictionary(defaultProviderDict); + + ghoul::Dictionary tileIndexDict = dictionary.value(KeyTileIndex); + _tileIndex = TileIndex(tileIndexDict); + + ghoul::Dictionary slideProvidersDict = dictionary.value(KeySlideProviders); + _slideProviders.resize(slideProvidersDict.size()); + for (size_t i = 0; i < slideProvidersDict.size(); i++) { + std::string dictKey = std::to_string(i + 1); + ghoul::Dictionary providerDict = slideProvidersDict.value(dictKey); + _slideProviders[i] = TileProvider::createFromDictionary(providerDict); + } + + _slideIndex.setMaxValue(_slideProviders.size() - 1); + addProperty(_slideIndex); +} + +Tile PresentationSlideProvider::getTile(const TileIndex& tileIndex) { + if(tileIndex == _tileIndex){ + return slideProvider()->getTile(tileIndex); + } + return Tile::TileUnavailable; + +} + +Tile PresentationSlideProvider::getDefaultTile() { + return _defaultProvider->getDefaultTile(); +} + +Tile::Status PresentationSlideProvider::getTileStatus(const TileIndex& tileIndex) { + if(tileIndex == _tileIndex){ + return slideProvider()->getTileStatus(tileIndex); + } + return Tile::Status::Unavailable; +} + +TileDepthTransform PresentationSlideProvider::depthTransform() { + return slideProvider()->depthTransform(); +} + +void PresentationSlideProvider::update() { + slideProvider()->update(); + _defaultProvider->update(); +} + +void PresentationSlideProvider::reset() { + for(auto& tp : _slideProviders){ + tp->reset(); + } + _defaultProvider->reset(); +} + +int PresentationSlideProvider::maxLevel() { + return _defaultProvider->maxLevel(); +} + +TileProvider* PresentationSlideProvider::slideProvider() { + int maxIndex = (int)_slideProviders.size() - 1; + int clampedIndex = std::max(0, std::min(_slideIndex.value(), maxIndex)); + _slideIndex.setValue(clampedIndex); + return _slideProviders[clampedIndex].get(); +} + +} // namespace tileprovider +} // namespace globebrowsing +} // namespace openspace diff --git a/include/openspace/interaction/deviceidentifier.h b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h similarity index 61% rename from include/openspace/interaction/deviceidentifier.h rename to modules/globebrowsing/tile/tileprovider/presentationslideprovider.h index 6f714d9de0..facfba7966 100644 --- a/include/openspace/interaction/deviceidentifier.h +++ b/modules/globebrowsing/tile/tileprovider/presentationslideprovider.h @@ -22,58 +22,49 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_CORE___DEVICEIDENTIFIER___H__ -#define __OPENSPACE_CORE___DEVICEIDENTIFIER___H__ +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__ + +#include +#include + +#include +#include + +#include -// std includes -#include -#include #include +#include namespace openspace { +namespace globebrowsing { +namespace tileprovider { -#define MAXDEVICES 16 - -enum class InputDevice {NONE, UNKNOWN, SPACENAVIGATOR, XBOX}; - -class DeviceIdentifier { +class PresentationSlideProvider : public TileProvider { public: - static DeviceIdentifier& ref(); - virtual ~DeviceIdentifier(); + PresentationSlideProvider(const ghoul::Dictionary& dictionary); + PresentationSlideProvider(const std::string& imagePath); + virtual ~PresentationSlideProvider() { } - static void init(); - static void deinit(); - static bool isInitialized(); - - void scanDevices(); - const int numberOfDevices() const; - const InputDevice type(const int device) const; - - void update(); - void update(const int device); + virtual Tile getTile(const TileIndex& tileIndex); + virtual Tile getDefaultTile(); + virtual Tile::Status getTileStatus(const TileIndex& index); + virtual TileDepthTransform depthTransform(); + virtual void update(); + virtual void reset(); + virtual int maxLevel(); - const int getButtons(const int device, unsigned char **buttons = nullptr) const; - const int getAxes(const int device, float **axespos = nullptr) const; - void get(const int device, unsigned char **buttons, float **axespos) const; - private: - // singleton - static DeviceIdentifier* this_; - DeviceIdentifier(void); - DeviceIdentifier(const DeviceIdentifier& src); - DeviceIdentifier& operator=(const DeviceIdentifier& rhs); - - - // member variables - int devices_; - std::array inputDevice_; - std::array numberOfAxes_; - std::array numberOfButtons_; - std::array axesPos_; - std::array buttons_; + TileProvider* slideProvider(); + TileIndex _tileIndex; + properties::IntProperty _slideIndex; + std::vector> _slideProviders; + std::unique_ptr _defaultProvider; }; +} // namespace tileprovider +} // namespace globebrowsing } // namespace openspace -#endif // __OPENSPACE_CORE___DEVICEIDENTIFIER___H__ +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___PRESENTATION_SLIDE_PROVIDER___H__ diff --git a/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp b/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp new file mode 100644 index 0000000000..944c4594ed --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/projectiontileprovider.cpp @@ -0,0 +1,385 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace { + const char* _loggerCat = "ProjectionTileProvider"; + + const char* keyGeometry = "Geometry"; + const char* keyProjection = "Projection"; + const char* keyMeridianShift = "Textures.MeridianShift"; + const char* keyColorTexture = "Textures.Color"; + const char* keyHeightTexture = "Textures.Height"; + + const char* keyRadius = "Geometry.Radius"; + const char* keyShading = "PerformShading"; + const char* _mainFrame = "GALACTIC"; +} + +namespace openspace { +namespace globebrowsing { +namespace tileprovider { + +/* +documentation::Documentation ProjectionTileProvider::Documentation() { + using namespace openspace::documentation; + return { + "Renderable Planet Projection", + "newhorizons_renderable_planetprojection", + { + { + "Type", + new StringEqualVerifier("RenderablePlanetProjection"), + "", + Optional::No + }, + { + keyGeometry, + new ReferencingVerifier("space_geometry_planet"), + "The geometry that is used for rendering this planet.", + Optional::No + }, + { + keyProjection, + new ReferencingVerifier("newhorizons_projectioncomponent"), + "Contains information about projecting onto this planet.", + Optional::No + }, + { + keyMeridianShift, + new BoolVerifier, + "Determines whether the meridian of the planet should be shifted by 180 " + "degrees. The default value is 'false'", + Optional::Yes + }, + { + keyColorTexture, + new StringVerifier, + "The path to the base color texture that is used on the planet prior to " + "any image projection. The path can use tokens of the form '${...}' or " + "be specified relative to the directory of the mod file.", + Optional::No + }, + { + keyHeightTexture, + new StringVerifier, + "The path to the height map texture that is used on the planet. The path " + "can use tokens of the form '${...}' or be specified relative to the " + "directory of the mod file. If no height map is specified the planet " + "does not use a height field.", + Optional::Yes + } + } + }; +} +*/ + +ProjectionTileProvider::ProjectionTileProvider(const ghoul::Dictionary& dictionary) + : _fboProgramObject(nullptr) + , _capture(false) + , _defaultTile(Tile::TileUnavailable) +{ + + ghoul::Dictionary geometryDictionary; + bool success = dictionary.getValue( + keyGeometry, geometryDictionary); + if (success) { + geometryDictionary.setValue(SceneGraphNode::KeyName, "TestGeometry"); + using planetgeometry::PlanetGeometry; + _geometry = std::unique_ptr( + PlanetGeometry::createFromDictionary(geometryDictionary) + ); + } + + _projectionComponent.initialize(dictionary.value(keyProjection)); + + + addPropertySubOwner(_geometry.get()); + addPropertySubOwner(_projectionComponent); +} + +ProjectionTileProvider::~ProjectionTileProvider(){ + +} + +bool ProjectionTileProvider::initialize() { + bool completeSuccess = true; + completeSuccess &= TileProvider::initialize(); + + _fboProgramObject = ghoul::opengl::ProgramObject::Build("fboPassProgram", + "${MODULE_NEWHORIZONS}/shaders/renderablePlanetProjection_vs.glsl", + "${MODULE_NEWHORIZONS}/shaders/renderablePlanetProjection_fs.glsl" + ); + + completeSuccess &= _projectionComponent.initializeGL(); + completeSuccess &= _geometry->initialize(nullptr); + + if (completeSuccess) { + //completeSuccess &= auxiliaryRendertarget(); + // SCREEN-QUAD + const GLfloat size = 1.f; + const GLfloat w = 1.f; + const GLfloat vertex_data[] = { + -size, -size, 0.f, w, 0.f, 0.f, + size, size, 0.f, w, 1.f, 1.f, + -size, size, 0.f, w, 0.f, 1.f, + -size, -size, 0.f, w, 0.f, 0.f, + size, -size, 0.f, w, 1.f, 0.f, + size, size, 0.f, w, 1.f, 1.f, + }; + + glGenVertexArrays(1, &_quad); + glBindVertexArray(_quad); + glGenBuffers(1, &_vertexPositionBuffer); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(0)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, reinterpret_cast(sizeof(GLfloat) * 4)); + + glBindVertexArray(0); + } + + return completeSuccess; +} + +bool ProjectionTileProvider::deinitialize() { + _projectionComponent.deinitialize(); + _geometry = nullptr; + + glDeleteVertexArrays(1, &_quad); + glDeleteBuffers(1, &_vertexPositionBuffer); + + _fboProgramObject = nullptr; + + return true; +} + +void ProjectionTileProvider::update() { + // Update + if (_fboProgramObject->isDirty()) { + _fboProgramObject->rebuildFromFile(); + } + + _projectionComponent.update(); + + _time = Time::ref().j2000Seconds(); + _capture = false; + + if (openspace::ImageSequencer::ref().isReady()){ + openspace::ImageSequencer::ref().updateSequencer(_time); + if (_projectionComponent.doesPerformProjection()) { + _capture = openspace::ImageSequencer::ref().getImagePaths( + _imageTimes, + _projectionComponent.projecteeId(), + _projectionComponent.instrumentId() + ); + } + } + + _stateMatrix = glm::dmat3(1.0); + + + + + + + + + + + + + + + // Projection + + if (_projectionComponent.needsClearProjection()) + _projectionComponent.clearAllProjections(); + + _camScaling = glm::vec2(1.0);// data.camera.scaling(); + _up = glm::vec3(0,1,0);// data.camera.lookUpVectorCameraSpace(); + + if (_capture && _projectionComponent.doesPerformProjection()) { + for (const Image& img : _imageTimes) { + attitudeParameters(img.timeRange.start); + imageProjectGPU(_projectionComponent.loadProjectionTexture(img.path)); + } + _capture = false; + } + attitudeParameters(_time); + _imageTimes.clear(); + +} + +void ProjectionTileProvider::reset() { +} + +int ProjectionTileProvider::maxLevel() { + return 3; +} + +Tile ProjectionTileProvider::getTile(const TileIndex& tileIndex) { + _projectionComponent.projectionTexture(); +} + +float ProjectionTileProvider::noDataValueAsFloat() { + +} + +Tile ProjectionTileProvider::getDefaultTile() { + +} + +Tile::Status ProjectionTileProvider::getTileStatus(const TileIndex& tileIndex) { + return Tile::Status::OK; +} + +TileDepthTransform ProjectionTileProvider::depthTransform() { + +} + +void ProjectionTileProvider::attitudeParameters(double time) { + // precomputations for shader + _instrumentMatrix = SpiceManager::ref().positionTransformMatrix( + _projectionComponent.instrumentId(), _mainFrame, time + ); + + _transform = glm::mat4(1); + //90 deg rotation w.r.t spice req. + glm::mat4 rot = glm::rotate( + _transform, + static_cast(M_PI_2), + glm::vec3(1, 0, 0) + ); + glm::mat4 roty = glm::rotate( + _transform, + static_cast(M_PI_2), + glm::vec3(0, -1, 0) + ); + + _transform = glm::mat4(_stateMatrix); + + glm::dvec3 bs; + try { + SpiceManager::FieldOfViewResult res = SpiceManager::ref().fieldOfView(_projectionComponent.instrumentId()); + bs = std::move(res.boresightVector); + } + catch (const SpiceManager::SpiceException& e) { + LERRORC(e.component, e.what()); + return; + } + + double lightTime; + glm::dvec3 p = SpiceManager::ref().targetPosition( + _projectionComponent.projectorId(), + _projectionComponent.projecteeId(), + _mainFrame, + _projectionComponent.aberration(), + time, + lightTime + ); + psc position = PowerScaledCoordinate::CreatePowerScaledCoordinate(p.x, p.y, p.z); + + //change to KM and add psc camera scaling. + position[3] += (3 + _camScaling[1]); + //position[3] += 3; + glm::vec3 cpos = position.vec3(); + + float distance = glm::length(cpos); + float radius = 1185000.0f; + + _projectorMatrix = _projectionComponent.computeProjectorMatrix( + cpos, + bs, + _up, + _instrumentMatrix, + _projectionComponent.fieldOfViewY(), + _projectionComponent.aspectRatio(), + distance - radius, + distance + radius, + _boresight + ); +} + +void ProjectionTileProvider::imageProjectGPU( + std::shared_ptr projectionTexture) +{ + _projectionComponent.imageProjectBegin(); + + _fboProgramObject->activate(); + + ghoul::opengl::TextureUnit unitFbo; + unitFbo.activate(); + projectionTexture->bind(); + _fboProgramObject->setUniform("projectionTexture", unitFbo); + + _fboProgramObject->setUniform("ProjectorMatrix", _projectorMatrix); + _fboProgramObject->setUniform("ModelTransform" , _transform); + _fboProgramObject->setUniform("_scaling" , _camScaling); + _fboProgramObject->setUniform("boresight" , _boresight); + + if (_geometry->hasProperty("radius")){ + ghoul::any r = _geometry->property("radius")->get(); + if (glm::vec4* radius = ghoul::any_cast(&r)){ + _fboProgramObject->setUniform("_radius", radius); + } + }else{ + LERROR("Geometry object needs to provide radius"); + } + if (_geometry->hasProperty("segments")){ + ghoul::any s = _geometry->property("segments")->get(); + if (int* segments = ghoul::any_cast(&s)){ + _fboProgramObject->setUniform("_segments", segments[0]); + } + }else{ + LERROR("Geometry object needs to provide segment count"); + } + + glBindVertexArray(_quad); + glDrawArrays(GL_TRIANGLES, 0, 6); + _fboProgramObject->deactivate(); + + _projectionComponent.imageProjectEnd(); +} + + +} // namespace tileprovider +} // namespace globebrowsing +} // namespace openspace diff --git a/modules/globebrowsing/tile/tileprovider/projectiontileprovider.h b/modules/globebrowsing/tile/tileprovider/projectiontileprovider.h new file mode 100644 index 0000000000..4b555c4f95 --- /dev/null +++ b/modules/globebrowsing/tile/tileprovider/projectiontileprovider.h @@ -0,0 +1,121 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___PROJECTION_TILE_PROVIDER___H__ +#define __OPENSPACE_MODULE_GLOBEBROWSING___PROJECTION_TILE_PROVIDER___H__ + +#include +#include + +#include +#include +#include + +namespace openspace { +namespace globebrowsing { + +class AsyncTileDataProvider; +class RawTile; + +namespace tileprovider { + +class ProjectionTileProvider : public TileProvider { +public: + ProjectionTileProvider(const ghoul::Dictionary& dictionary); + + virtual ~ProjectionTileProvider() override; + + virtual Tile getTile(const TileIndex& tileIndex) override; + + virtual Tile getDefaultTile() override; + virtual Tile::Status getTileStatus(const TileIndex& tileIndex) override; + virtual TileDepthTransform depthTransform() override; + virtual void update() override; + virtual void reset() override; + virtual int maxLevel() override; + virtual float noDataValueAsFloat() override; + + bool initialize() override; + bool deinitialize() override; + + //static documentation::Documentation Documentation(); + +protected: + bool loadTextures(); + void attitudeParameters(double time); + +private: + void imageProjectGPU(std::shared_ptr projectionTexture); + + ProjectionComponent _projectionComponent; + + //properties::StringProperty _colorTexturePath; + //properties::StringProperty _heightMapTexturePath; + + //properties::IntProperty _rotation; + + std::unique_ptr _fboProgramObject; + + //std::unique_ptr _baseTexture; + //std::unique_ptr _heightMapTexture; + + //properties::BoolProperty _shiftMeridianBy180; + + //properties::FloatProperty _heightExaggeration; + //properties::FloatProperty _debugProjectionTextureRotation; + + std::unique_ptr _geometry; + + glm::vec2 _camScaling; + glm::vec3 _up; + glm::mat4 _transform; + glm::mat4 _projectorMatrix; + + glm::dmat3 _stateMatrix; + glm::dmat3 _instrumentMatrix; + glm::vec3 _boresight; + + double _time; + + std::vector _imageTimes; + + std::string _frame; + + bool _capture; + + GLuint _quad; + GLuint _vertexPositionBuffer; + + + + +private: + Tile _defaultTile; +}; + +} // namespace tileprovider +} // namespace globebrowsing +} // namespace openspace + +#endif // __OPENSPACE_MODULE_GLOBEBROWSING___PROJECTION_TILE_PROVIDER___H__ diff --git a/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp b/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp index 5157f60072..4c996337f6 100644 --- a/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/singleimageprovider.cpp @@ -36,7 +36,9 @@ namespace openspace { namespace globebrowsing { namespace tileprovider { -SingleImageProvider::SingleImageProvider(const ghoul::Dictionary& dictionary) { +SingleImageProvider::SingleImageProvider(const ghoul::Dictionary& dictionary) + : _tile(nullptr, nullptr, Tile::Status::Unavailable) +{ // Required input if (!dictionary.getValue(KeyFilePath, _imagePath)) { throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'"); @@ -47,6 +49,7 @@ SingleImageProvider::SingleImageProvider(const ghoul::Dictionary& dictionary) { SingleImageProvider::SingleImageProvider(const std::string& imagePath) : _imagePath(imagePath) + , _tile(nullptr, nullptr, Tile::Status::Unavailable) { reset(); } @@ -60,7 +63,7 @@ Tile SingleImageProvider::getDefaultTile() { } Tile::Status SingleImageProvider::getTileStatus(const TileIndex& index) { - return _tile.status; + return _tile.status(); } TileDepthTransform SingleImageProvider::depthTransform() { @@ -75,13 +78,16 @@ void SingleImageProvider::update() { } void SingleImageProvider::reset() { - _tile = Tile(); - _tile.texture = std::shared_ptr(ghoul::io::TextureReader::ref().loadTexture(_imagePath).release()); - _tile.status = _tile.texture != nullptr ? Tile::Status::OK : Tile::Status::IOError; - _tile.metaData = nullptr; + auto tileTexture = std::shared_ptr( + ghoul::io::TextureReader::ref().loadTexture(_imagePath) + ); + auto tileStatus = tileTexture != nullptr ? Tile::Status::OK : Tile::Status::IOError; + auto tileMetaData = nullptr; - _tile.texture->uploadTexture(); - _tile.texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); + tileTexture->uploadTexture(); + tileTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); + + _tile = Tile(tileTexture, tileMetaData, tileStatus); } int SingleImageProvider::maxLevel() { diff --git a/modules/globebrowsing/tile/tileprovider/singleimageprovider.h b/modules/globebrowsing/tile/tileprovider/singleimageprovider.h index 0f79d4ace9..eacf9d63d8 100644 --- a/modules/globebrowsing/tile/tileprovider/singleimageprovider.h +++ b/modules/globebrowsing/tile/tileprovider/singleimageprovider.h @@ -31,8 +31,6 @@ namespace openspace { namespace globebrowsing { namespace tileprovider { -using namespace ghoul::opengl; - class SingleImageProvider : public TileProvider { public: SingleImageProvider(const ghoul::Dictionary& dictionary); diff --git a/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp b/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp index 80a944405e..552b9c9a11 100644 --- a/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/sizereferencetileprovider.cpp @@ -46,6 +46,7 @@ namespace { } SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& dictionary) + : _backgroundTile(Tile::TileUnavailable) { _fontSize = 50; _font = OsEng.fontManager().font("Mono", _fontSize); @@ -56,16 +57,19 @@ SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& di } _ellipsoid = Ellipsoid(radii); - _backgroundTile.status = Tile::Status::Unavailable; + auto backgroundTileStatus = Tile::Status::Unavailable; + std::shared_ptr backgroundTileTexture; + std::string backgroundImagePath; if (dictionary.getValue(KeyBackgroundImagePath, backgroundImagePath)) { using namespace ghoul::io; std::string imgAbsPath = absPath(backgroundImagePath); - _backgroundTile.texture = TextureReader::ref().loadTexture(imgAbsPath); - _backgroundTile.texture->uploadTexture(); - _backgroundTile.texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); - _backgroundTile.status = Tile::Status::OK; + backgroundTileTexture = TextureReader::ref().loadTexture(imgAbsPath); + backgroundTileTexture->uploadTexture(); + backgroundTileTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear); + backgroundTileStatus = Tile::Status::OK; } + _backgroundTile = Tile(backgroundTileTexture, nullptr, backgroundTileStatus); } void SizeReferenceTileProvider::renderText(const ghoul::fontrendering::FontRenderer& @@ -124,12 +128,11 @@ TileIndex::TileHashKey SizeReferenceTileProvider::toHash(const TileIndex& tileIn } Tile SizeReferenceTileProvider::backgroundTile(const TileIndex& tileIndex) const { - if (_backgroundTile.status == Tile::Status::OK) { - Tile tile; - auto t = _backgroundTile.texture; + if (_backgroundTile.status() == Tile::Status::OK) { + auto t = _backgroundTile.texture(); void* pixelData = new char[t->expectedPixelDataSize()]; memcpy(pixelData, t->pixelData(), t->expectedPixelDataSize()); - tile.texture = std::make_shared( + auto tileTexture = std::make_shared( pixelData, t->dimensions(), t->format(), @@ -138,10 +141,10 @@ Tile SizeReferenceTileProvider::backgroundTile(const TileIndex& tileIndex) const t->filter(), t->wrapping() ); - tile.texture->uploadTexture(); - tile.texture->setDataOwnership(ghoul::opengl::Texture::TakeOwnership::Yes); - tile.status = Tile::Status::OK; - return tile; + tileTexture->uploadTexture(); + tileTexture->setDataOwnership(ghoul::opengl::Texture::TakeOwnership::Yes); + auto tileStatus = Tile::Status::OK; + return Tile(tileTexture, nullptr, tileStatus); } else { // use default background diff --git a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp index 7e5e213611..4e8fbb2d28 100644 --- a/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp +++ b/modules/globebrowsing/tile/tileprovider/temporaltileprovider.cpp @@ -22,13 +22,17 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#ifdef GLOBEBROWSING_USE_GDAL + #include #include +#include #include #include "cpl_minixml.h" +#include #include namespace { @@ -37,8 +41,11 @@ namespace { const char* KeyDoPreProcessing = "DoPreProcessing"; const char* KeyMinimumPixelSize = "MinimumPixelSize"; const char* KeyFilePath = "FilePath"; + const char* KeyBasePath = "BasePath"; const char* KeyCacheSize = "CacheSize"; const char* KeyFlushInterval = "FlushInterval"; + const char* KeyPreCacheStartTime = "PreCacheStartTime"; + const char* KeyPreCacheEndTime = "PreCacheEndTime"; } namespace openspace { @@ -56,11 +63,12 @@ const char* TemporalTileProvider::TemporalXMLTags::TIME_FORMAT = "OpenSpaceTimeI TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary) : _initDict(dictionary) { - if (!dictionary.getValue(KeyFilePath, _datasetFile)) { throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'"); } + _datasetFile = absPath(_datasetFile); + std::ifstream in(_datasetFile.c_str()); if (!in.is_open()) { throw ghoul::FileNotFoundError(_datasetFile); @@ -71,8 +79,29 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary) std::istreambuf_iterator(in), (std::istreambuf_iterator()) ); + + _initDict.setValue( + KeyBasePath, + ghoul::filesystem::File(_datasetFile).directoryName() + ); + _gdalXmlTemplate = consumeTemporalMetaData(xml); - _defaultTile = getTileProvider()->getDefaultTile(); + + const bool hasStart = dictionary.hasKeyAndValue(KeyPreCacheStartTime); + const bool hasEnd = dictionary.hasKeyAndValue(KeyPreCacheEndTime); + if (hasStart && hasEnd) { + const std::string start = dictionary.value(KeyPreCacheStartTime); + const std::string end = dictionary.value(KeyPreCacheEndTime); + std::vector