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/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/data/scene/mercury/mercury.mod b/data/scene/mercury/mercury.mod index 75bf33560e..aa4be9675d 100644 --- a/data/scene/mercury/mercury.mod +++ b/data/scene/mercury/mercury.mod @@ -1,3 +1,5 @@ +MercuryRadius = 2.4397E6; + return { -- Mercury barycenter module { @@ -22,7 +24,7 @@ return { Body = "MERCURY", Geometry = { Type = "SimpleSphere", - Radius = { 2.440, 6 }, + Radius = {MercuryRadius, 1.0}, Segments = 100 }, Textures = { diff --git a/data/scene/saturn/saturn/saturn.mod b/data/scene/saturn/saturn/saturn.mod index aea907718b..4dc0a215c6 100644 --- a/data/scene/saturn/saturn/saturn.mod +++ b/data/scene/saturn/saturn/saturn.mod @@ -1,3 +1,6 @@ +SaturnRadius = 5.8232E7; + + return { -- Saturn barycenter module { @@ -23,7 +26,7 @@ return { Body = "SATURN BARYCENTER", Geometry = { Type = "SimpleSphere", - Radius = { 5.8232, 7 }, + Radius = {SaturnRadius, 0}, Segments = 100 }, Textures = { 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/tasks/default.task b/data/tasks/default.task new file mode 100644 index 0000000000..9f64865d8e --- /dev/null +++ b/data/tasks/default.task @@ -0,0 +1,3 @@ +return { + "kameleonmetadatatojson" +} \ No newline at end of file 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/ext/ghoul b/ext/ghoul index e0cbca16ad..445ed6353f 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit e0cbca16ad71700cf82d0d24bcf4fc14bded10ea +Subproject commit 445ed6353fe53ffc2f799de29328ca44de9e3ffb diff --git a/include/openspace/engine/configurationmanager.h b/include/openspace/engine/configurationmanager.h index abf98886d0..f67b55bc6e 100644 --- a/include/openspace/engine/configurationmanager.h +++ b/include/openspace/engine/configurationmanager.h @@ -68,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; diff --git a/include/openspace/engine/moduleengine.h b/include/openspace/engine/moduleengine.h index 1cba4abc48..ab3a118ecc 100644 --- a/include/openspace/engine/moduleengine.h +++ b/include/openspace/engine/moduleengine.h @@ -28,6 +28,8 @@ #include #include +#include + namespace ghoul { namespace systemcapabilities { @@ -40,8 +42,6 @@ namespace openspace { namespace scripting { struct LuaLibrary; } -class OpenSpaceModule; - /** * The ModuleEngine is the central repository for registering and accessing * OpenSpaceModule for the current application run. By initializing (#initialize) the diff --git a/include/openspace/rendering/abufferrenderer.h b/include/openspace/rendering/abufferrenderer.h index 798a1373a8..2a3fc3a8fd 100644 --- a/include/openspace/rendering/abufferrenderer.h +++ b/include/openspace/rendering/abufferrenderer.h @@ -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/apps/DataConverter/conversiontask.h b/include/openspace/util/distanceconstants.h similarity index 84% rename from apps/DataConverter/conversiontask.h rename to include/openspace/util/distanceconstants.h index 388088977f..a7a368f7ba 100644 --- a/apps/DataConverter/conversiontask.h +++ b/include/openspace/util/distanceconstants.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__ - -#include +#ifndef __OPENSPACE_CORE___DISTANCECONSTANTS___H__ +#define __OPENSPACE_CORE___DISTANCECONSTANTS___H__ namespace openspace { -namespace dataconverter { -class ConversionTask { -public: - virtual void perform(const std::function& onProgress) = 0; -}; +namespace distanceconstants { + const float EarthRadius = 6371; + const float LightYear = 9.4607304725808E15; + const float AstronomicalUnit = 1.495978707E11; + const float Parsec = 3.0856776E16; +} -} // namespace dataconverter -} // namespace openspace +} -#endif // __OPENSPACE_APP_DATACONVERTER___CONVERSIONTASK___H__ +#endif // __OPENSPACE_CORE___DISTANCECONSTANTS___H__ diff --git a/include/openspace/util/task.h b/include/openspace/util/task.h new file mode 100644 index 0000000000..23844f8dfe --- /dev/null +++ b/include/openspace/util/task.h @@ -0,0 +1,47 @@ +/***************************************************************************************** + * * + * 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 +#include + +namespace openspace { + +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..4b4bf18c6a --- /dev/null +++ b/include/openspace/util/taskloader.h @@ -0,0 +1,41 @@ +/***************************************************************************************** + * * + * 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); +}; + +} + +#endif // __OPENSPACE_CORE___TASKLOADER___H__ diff --git a/modules/base/basemodule.h b/modules/base/basemodule.h index 28bc2c3355..257cdec7ce 100644 --- a/modules/base/basemodule.h +++ b/modules/base/basemodule.h @@ -32,7 +32,7 @@ namespace openspace { class BaseModule : public OpenSpaceModule { public: BaseModule(); - + virtual ~BaseModule() = default; std::vector documentations() const override; protected: diff --git a/modules/galaxy/CMakeLists.txt b/modules/galaxy/CMakeLists.txt index 4a873620a4..a70b4b03d6 100644 --- a/modules/galaxy/CMakeLists.txt +++ b/modules/galaxy/CMakeLists.txt @@ -27,14 +27,18 @@ 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/apps/DataConverter/milkywayconversiontask.cpp b/modules/galaxy/tasks/milkywayconversiontask.cpp similarity index 66% rename from apps/DataConverter/milkywayconversiontask.cpp rename to modules/galaxy/tasks/milkywayconversiontask.cpp index 72482738a6..9dfd7fef38 100644 --- a/apps/DataConverter/milkywayconversiontask.cpp +++ b/modules/galaxy/tasks/milkywayconversiontask.cpp @@ -22,30 +22,63 @@ * 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) {} +namespace { + char* KeyInFilenamePrefix = "InFilenamePrefix"; + char* KeyInFilenameSuffix = "InFilenameSuffix"; + char* KeyInFirstIndex = "InFirstIndex"; + char* KeyInNSlices = "InNSlices"; + char* KeyOutFilename = "OutFilename"; + char* KeyOutDimensions = "OutDimensions"; +} + +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 inFilenamePrefix; + 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 +100,12 @@ void MilkyWayConversionTask::perform(const std::function& onProgres return value; }; - rawWriter.write(sampleFunction, onProgress); + rawWriter.write(sampleFunction, progressCallback); +} + +Documentation MilkywayConversionTask::documentation() +{ + return 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..1a37fb5950 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,18 @@ namespace openspace { -namespace dataconverter { /** * 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(); private: std::string _inFilenamePrefix; std::string _inFilenameSuffix; @@ -59,7 +55,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 81% rename from apps/DataConverter/milkywaypointsconversiontask.cpp rename to modules/galaxy/tasks/milkywaypointsconversiontask.cpp index 790d2be279..ae9891d68f 100644 --- a/apps/DataConverter/milkywaypointsconversiontask.cpp +++ b/modules/galaxy/tasks/milkywaypointsconversiontask.cpp @@ -22,38 +22,42 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#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,8 +70,9 @@ 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; } @@ -80,7 +85,9 @@ void MilkyWayPointsConversionTask::perform(const std::function& onP out.close(); } - +Documentation MilkywayPointsConversionTask::documentation() +{ + return 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..ffc1582957 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,6 @@ namespace openspace { -namespace dataconverter { /** * Converts ascii based point data @@ -42,18 +41,18 @@ 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(); 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/kameleon/src/kameleonwrapper.cpp b/modules/kameleon/src/kameleonwrapper.cpp index 2d96133ac7..e835c8b758 100644 --- a/modules/kameleon/src/kameleonwrapper.cpp +++ b/modules/kameleon/src/kameleonwrapper.cpp @@ -1008,38 +1008,34 @@ glm::vec4 KameleonWrapper::classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEn return color; } -std::string KameleonWrapper::getParent(){ - if( _type == KameleonWrapper::Model::BATSRUS || - _type == KameleonWrapper::Model::OpenGGCM || - _type == KameleonWrapper::Model::LFM) - { +std::string KameleonWrapper::getParent() { + switch (_type) { + case KameleonWrapper::Model::BATSRUS: + case KameleonWrapper::Model::OpenGGCM: + case KameleonWrapper::Model::LFM: return "Earth"; - }else if( - _type == KameleonWrapper::Model::ENLIL || - _type == KameleonWrapper::Model::MAS || - _type == KameleonWrapper::Model::Adapt3D || - _type == KameleonWrapper::Model::SWMF) - { + case KameleonWrapper::Model::ENLIL: + case KameleonWrapper::Model::MAS: + case KameleonWrapper::Model::Adapt3D: + case KameleonWrapper::Model::SWMF: return "Sun"; - }else{ + default: return ""; } } -std::string KameleonWrapper::getFrame(){ - if( _type == KameleonWrapper::Model::BATSRUS || - _type == KameleonWrapper::Model::OpenGGCM || - _type == KameleonWrapper::Model::LFM) - { +std::string KameleonWrapper::getFrame() { + switch (_type) { + case KameleonWrapper::Model::BATSRUS: + case KameleonWrapper::Model::OpenGGCM: + case KameleonWrapper::Model::LFM: return "GSM"; - }else if( - _type == KameleonWrapper::Model::ENLIL || - _type == KameleonWrapper::Model::MAS || - _type == KameleonWrapper::Model::Adapt3D || - _type == KameleonWrapper::Model::SWMF) - { + case KameleonWrapper::Model::ENLIL: + case KameleonWrapper::Model::MAS: + case KameleonWrapper::Model::Adapt3D: + case KameleonWrapper::Model::SWMF: return "HEEQ"; - }else{ + default: return ""; } } @@ -1050,8 +1046,6 @@ std::vector KameleonWrapper::getVariables(){ int numVariables = _model->getNumberOfVariables(); for(int i=0; igetVariableName(i) << " "; - // std::cout << _model->getVariableName(i) << std::endl; variableNames.push_back(_model->getVariableName(i));; } return variableNames; diff --git a/modules/kameleonvolume/CMakeLists.txt b/modules/kameleonvolume/CMakeLists.txt new file mode 100644 index 0000000000..b2321582fe --- /dev/null +++ b/modules/kameleonvolume/CMakeLists.txt @@ -0,0 +1,49 @@ +######################################################################################### +# # +# 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}/kameleonvolumereader.h + ${CMAKE_CURRENT_SOURCE_DIR}/kameleonvolumereader.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablekameleonvolume.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/kameleonvolumeraycaster.h + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleondocumentationtask.h + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleonmetadatatojsontask.h +) +source_group("Header Files" FILES ${HEADER_FILES}) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablekameleonvolume.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/kameleonvolumeraycaster.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleondocumentationtask.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/kameleonmetadatatojsontask.cpp +) +source_group("Source Files" FILES ${SOURCE_FILES}) + +create_new_module( + "KameleonVolume" + kameleonvolume_module + ${HEADER_FILES} ${SOURCE_FILES} +) diff --git a/modules/kameleonvolume/include.cmake b/modules/kameleonvolume/include.cmake new file mode 100644 index 0000000000..e01e83854b --- /dev/null +++ b/modules/kameleonvolume/include.cmake @@ -0,0 +1,6 @@ +set (DEFAULT_MODULE ON) + +set (OPENSPACE_DEPENDENCIES + kameleon + volume +) \ No newline at end of file diff --git a/modules/kameleonvolume/kameleonvolumemodule.cpp b/modules/kameleonvolume/kameleonvolumemodule.cpp new file mode 100644 index 0000000000..c521538492 --- /dev/null +++ b/modules/kameleonvolume/kameleonvolumemodule.cpp @@ -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. * + ****************************************************************************************/ + +#include + +#include + +#include +#include + +#include +#include +#include + +namespace openspace { + +KameleonVolumeModule::KameleonVolumeModule() : OpenSpaceModule("KameleonVolume") {} + +void KameleonVolumeModule::internalInitialize() { + auto fRenderable = FactoryManager::ref().factory(); + ghoul_assert(fRenderable, "No renderable factory existed"); + fRenderable->registerClass("RenderableKameleonVolume"); + + auto fTask = FactoryManager::ref().factory(); + ghoul_assert(fTask, "No task factory existed"); + fTask->registerClass("KameleonMetadataToJsonTask"); + fTask->registerClass("KameleonDocumentationTask"); + + +} + +std::vector KameleonVolumeModule::documentations() const +{ + return std::vector{KameleonMetadataToJsonTask::documentation()}; +} + +} // namespace openspace diff --git a/modules/kameleonvolume/kameleonvolumemodule.h b/modules/kameleonvolume/kameleonvolumemodule.h new file mode 100644 index 0000000000..adae6f1320 --- /dev/null +++ b/modules/kameleonvolume/kameleonvolumemodule.h @@ -0,0 +1,43 @@ +/***************************************************************************************** + * * + * 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_KAMELEONVOLUME___KAMELEONVOLUMEMODULE___H__ +#define __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMEMODULE___H__ + +#include +#include + +namespace openspace { + +class KameleonVolumeModule : public OpenSpaceModule { +public: + KameleonVolumeModule(); + virtual ~KameleonVolumeModule() = default; + void internalInitialize() override; + std::vector documentations() const override; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMEMODULE___H__ diff --git a/modules/kameleonvolume/kameleonvolumereader.cpp b/modules/kameleonvolume/kameleonvolumereader.cpp new file mode 100644 index 0000000000..8b3a13bc82 --- /dev/null +++ b/modules/kameleonvolume/kameleonvolumereader.cpp @@ -0,0 +1,195 @@ +/***************************************************************************************** + * * + * 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 + +namespace { + const char* _loggerCat = "KameleonVolumeReader"; +} + +namespace openspace { + +KameleonVolumeReader::KameleonVolumeReader(const std::string& path) + : _path(path) +{ + if (!FileSys.fileExists(path)) { + LERROR(_path << "does not exist"); + return; + } + + long status = _kameleon.open(_path); + if (status != ccmc::FileReader::OK) { + LERROR("Failed to open file " << _path << " with kameleon"); + return; + } + + _model = _kameleon.model; + _interpolator = std::unique_ptr(_model->createNewInterpolator()); +} + +std::unique_ptr> KameleonVolumeReader::readFloatVolume( + const glm::uvec3 & dimensions, + const std::string & variable, + const glm::vec3 & lowerBound, + const glm::vec3 & upperBound) const +{ + auto volume = std::make_unique>(dimensions); + const glm::vec3 dims = volume->dimensions(); + const glm::vec3 diff = upperBound - lowerBound; + + _model->loadVariable(variable); + + float* data = volume->data(); + for (size_t index = 0; index < volume->nCells(); index++) { + glm::vec3 coords = volume->indexToCoords(index); + glm::vec3 coordsZeroToOne = coords / dims; + glm::vec3 volumeCoords = lowerBound + diff * coordsZeroToOne; + + data[index] = _interpolator->interpolate( + variable, + static_cast(volumeCoords[0]), + static_cast(volumeCoords[1]), + static_cast(volumeCoords[2])); + } + + return volume; +} + +std::vector KameleonVolumeReader::gridVariableNames() const { + // get the grid system string + std::string gridSystem = _model->getGlobalAttribute("grid_system_1").getAttributeString(); + + // remove leading and trailing brackets + gridSystem = gridSystem.substr(1, gridSystem.length() - 2); + + // remove all whitespaces + gridSystem.erase(remove_if(gridSystem.begin(), gridSystem.end(), isspace), gridSystem.end()); + + // replace all comma signs with whitespaces + std::replace(gridSystem.begin(), gridSystem.end(), ',', ' '); + + // tokenize + std::istringstream iss(gridSystem); + std::vector tokens{ std::istream_iterator{iss},std::istream_iterator{} }; + + // validate + if (tokens.size() != 3) { + throw ghoul::RuntimeError( + "Expected three dimensional grid system. Got " + + std::to_string(tokens.size()) + + "dimensions"); + } + + std::string x = tokens.at(0); + std::string y = tokens.at(1); + std::string z = tokens.at(2); + + std::transform(x.begin(), x.end(), x.begin(), ::tolower); + std::transform(y.begin(), y.end(), y.begin(), ::tolower); + std::transform(z.begin(), z.end(), z.begin(), ::tolower); + + return std::vector{x, y, z}; +} + +std::vector KameleonVolumeReader::variableNames() const { + std::vector variableNames; + const int nVariables = _model->getNumberOfVariables(); + for (int i = 0; i < nVariables; ++i) { + variableNames.push_back(_model->getVariableName(i)); + } + return variableNames; +} + +std::vector KameleonVolumeReader::variableAttributeNames() const { + return _model->getVariableAttributeNames(); +} + +std::vector KameleonVolumeReader::globalAttributeNames() const { + std::vector attributeNames; + const int nAttributes = _model->getNumberOfGlobalAttributes(); + for (int i = 0; i < nAttributes; ++i) { + attributeNames.push_back(_model->getGlobalAttributeName(i)); + } + return attributeNames; +} + +void KameleonVolumeReader::addAttributeToDictionary(ghoul::Dictionary& dictionary, const std::string& key, ccmc::Attribute& attr) { + ccmc::Attribute::AttributeType type = attr.getAttributeType(); + switch (type) { + case ccmc::Attribute::AttributeType::FLOAT: + dictionary.setValue(key, attr.getAttributeFloat()); + return; + case ccmc::Attribute::AttributeType::INT: + dictionary.setValue(key, attr.getAttributeInt()); + return; + case ccmc::Attribute::AttributeType::STRING: + dictionary.setValue(key, attr.getAttributeString()); + return; + } +} + +ghoul::Dictionary KameleonVolumeReader::readMetaData() const { + ghoul::Dictionary globalAttributesDictionary; + for (const std::string& attributeName : globalAttributeNames()) { + ccmc::Attribute attribute = _model->getGlobalAttribute(attributeName); + addAttributeToDictionary(globalAttributesDictionary, attributeName, attribute); + } + + ghoul::Dictionary variableDictionary; + std::vector varAttrNames = variableAttributeNames(); + for (const std::string& variableName : variableNames()) { + ghoul::Dictionary variableAttributesDictionary; + for (const std::string& attributeName : varAttrNames) { + ccmc::Attribute attribute = _model->getVariableAttribute(variableName, attributeName); + addAttributeToDictionary(variableAttributesDictionary, attributeName, attribute); + } + variableDictionary.setValue(variableName, variableAttributesDictionary); + } + + return { + {"globalAttributes", std::move(globalAttributesDictionary) }, + {"variableAttributes", std::move(variableDictionary) } + }; +} + +float KameleonVolumeReader::minValue(const std::string & variable) const { + return _model->getVariableAttribute(variable, "actual_min").getAttributeFloat(); +} + +float KameleonVolumeReader::maxValue(const std::string & variable) const { + return _model->getVariableAttribute(variable, "actual_max").getAttributeFloat(); +} + + + + +} \ No newline at end of file diff --git a/modules/volume/rendering/renderablevolumegl.h b/modules/kameleonvolume/kameleonvolumereader.h similarity index 60% rename from modules/volume/rendering/renderablevolumegl.h rename to modules/kameleonvolume/kameleonvolumereader.h index 8e7153ce73..9666e5de80 100644 --- a/modules/volume/rendering/renderablevolumegl.h +++ b/modules/kameleonvolume/kameleonvolumereader.h @@ -22,65 +22,52 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_VOLUME___RENDERABLEVOLUMEGL___H__ -#define __OPENSPACE_MODULE_VOLUME___RENDERABLEVOLUMEGL___H__ +#ifndef __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMEREADER___H__ +#define __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMEREADER___H__ -#include -#include +#include +#include +#include +#include -// Forward declare to minimize dependencies -namespace ghoul { - namespace filesystem { - class File; - } - namespace opengl { - class ProgramObject; - class Texture; - } +#include +#include + +namespace ccmc { + class Model; } namespace openspace { -class RenderableVolumeGL: public RenderableVolume { +class KameleonVolumeReader { public: - RenderableVolumeGL(const ghoul::Dictionary& dictionary); - ~RenderableVolumeGL(); - - bool initialize() override; - bool deinitialize() override; + KameleonVolumeReader(const std::string& path); + //KameleonMetaData readMetaData(); - bool isReady() const override; + std::unique_ptr> readFloatVolume( + const glm::uvec3& dimensions, + const std::string& variable, + const glm::vec3& lowerBound, + const glm::vec3& upperBound) const; + ghoul::Dictionary readMetaData() const; + float minValue(const std::string& variable) const; + float maxValue(const std::string& variable) const; - virtual void render(const RenderData& data) override; - virtual void update(const UpdateData& data) override; + std::vector gridVariableNames() const; + std::vector gridUnits() const; + std::vector variableNames() const; + std::vector variableAttributeNames() const; + std::vector globalAttributeNames() const; private: - ghoul::Dictionary _hintsDictionary; + static void addAttributeToDictionary(ghoul::Dictionary& dictionary, const std::string& key, ccmc::Attribute& attr); + std::string _path; + ccmc::Kameleon _kameleon; + ccmc::Model* _model; + std::unique_ptr _interpolator; - std::string _filename; - - std::string _transferFunctionName; - std::string _volumeName; - - std::string _transferFunctionPath; - std::string _samplerFilename; - - ghoul::filesystem::File* _transferFunctionFile; - - ghoul::opengl::Texture* _volume; - ghoul::opengl::Texture* _transferFunction; - - GLuint _boxArray; - GLuint _vertexPositionBuffer; - ghoul::opengl::ProgramObject* _boxProgram; - glm::vec3 _boxScaling; - psc _pscOffset; - float _w; - - bool _updateTransferfunction; - int _id; }; } // namespace openspace -#endif // __OPENSPACE_MODULE_VOLUME___RENDERABLEVOLUMEGL___H__ +#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMEREADER___H__ diff --git a/modules/kameleonvolume/rendering/kameleonvolumeraycaster.cpp b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.cpp new file mode 100644 index 0000000000..10957bcb67 --- /dev/null +++ b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.cpp @@ -0,0 +1,179 @@ +/***************************************************************************************** + * * + * 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 + + +namespace { + const char* GlslRaycastPath = "${MODULES}/kameleonvolume/shaders/raycast.glsl"; + const char* GlslHelperPath = "${MODULES}/kameleonvolume/shaders/helper.glsl"; + const char* GlslBoundsVsPath = "${MODULES}/kameleonvolume/shaders/boundsvs.glsl"; + const char* GlslBoundsFsPath = "${MODULES}/kameleonvolume/shaders/boundsfs.glsl"; +} + +namespace openspace { + +KameleonVolumeRaycaster::KameleonVolumeRaycaster( + std::shared_ptr texture, + std::shared_ptr transferFunction, + std::shared_ptr clipPlanes) + : _volumeTexture(texture) + , _transferFunction(transferFunction) + , _clipPlanes(clipPlanes) + , _boundingBox(glm::vec3(1.0)) {} + +KameleonVolumeRaycaster::~KameleonVolumeRaycaster() {} + +void KameleonVolumeRaycaster::initialize() { + _boundingBox.initialize(); +} + +void KameleonVolumeRaycaster::deinitialize() { +} + +void KameleonVolumeRaycaster::renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) { + glm::dmat4 modelTransform = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation + glm::dmat4(data.modelTransform.rotation) * // Spice rotation + glm::dmat4(glm::scale(glm::dmat4(_modelTransform), glm::dvec3(data.modelTransform.scale))); + glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; + + program.setUniform("modelViewTransform", glm::mat4(modelViewTransform)); + program.setUniform("projectionTransform", data.camera.projectionMatrix()); + + // Cull back face + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + + // Render bounding geometry + _boundingBox.render(); +} + +void KameleonVolumeRaycaster::renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) { + glm::dmat4 modelTransform = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * + glm::dmat4(glm::scale(glm::dmat4(_modelTransform), glm::dvec3(data.modelTransform.scale))); + glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; + + program.setUniform("modelViewTransform", glm::mat4(modelViewTransform)); + program.setUniform("projectionTransform", data.camera.projectionMatrix()); + + // Cull front face + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + + // Render bounding geometry + _boundingBox.render(); + + // Restore defaults + glCullFace(GL_BACK); +} + +void KameleonVolumeRaycaster::preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { + std::string stepSizeUniformName = "maxStepSize" + std::to_string(data.id); + program.setUniform(stepSizeUniformName, _stepSize); + + std::string id = std::to_string(data.id); + + _tfUnit = std::make_unique(); + _tfUnit->activate(); + _transferFunction->getTexture().bind(); + program.setUniform("transferFunction_" + id, _tfUnit->unitNumber()); + + _textureUnit = std::make_unique(); + _textureUnit->activate(); + _volumeTexture->bind(); + program.setUniform("volumeTexture_" + id, _textureUnit->unitNumber()); + + program.setUniform("gridType_" + id, static_cast(_gridType)); + + std::vector clipNormals = _clipPlanes->normals(); + std::vector clipOffsets = _clipPlanes->offsets(); + int nClips = clipNormals.size(); + + program.setUniform("nClips_" + id, nClips); + program.setUniform("clipNormals_" + id, clipNormals.data(), nClips); + program.setUniform("clipOffsets_" + id, clipOffsets.data(), nClips); +} + +void KameleonVolumeRaycaster::postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { + // For example: release texture units + _textureUnit = nullptr; + _tfUnit = nullptr; +} + +bool KameleonVolumeRaycaster::cameraIsInside(const RenderData & data, glm::vec3 & localPosition) +{ + glm::dmat4 modelTransform = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * + glm::dmat4(glm::scale(glm::dmat4(_modelTransform), glm::dvec3(data.modelTransform.scale))); + glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; + + glm::vec4 modelPos = glm::inverse(modelViewTransform) * glm::vec4(0.0, 0.0, 0.0, 1.0); + + localPosition = (glm::vec3(modelPos) + glm::vec3(0.5)); + return (localPosition.x > 0 && localPosition.y > 0 && localPosition.z > 0 && localPosition.x < 1 && localPosition.y < 1 && localPosition.z < 1); +} + +std::string KameleonVolumeRaycaster::getBoundsVsPath() const { + return GlslBoundsVsPath; +} + +std::string KameleonVolumeRaycaster::getBoundsFsPath() const { + return GlslBoundsFsPath; +} + +std::string KameleonVolumeRaycaster::getRaycastPath() const { + return GlslRaycastPath; +} + +std::string KameleonVolumeRaycaster::getHelperPath() const { + return GlslHelperPath; +} + +void KameleonVolumeRaycaster::setStepSize(float stepSize) { + _stepSize = stepSize; +} + +void KameleonVolumeRaycaster::setGridType(VolumeGridType gridType) { + _gridType = gridType; +} + +void KameleonVolumeRaycaster::setModelTransform(const glm::mat4 & transform) { + _modelTransform = transform; +} + +} diff --git a/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h new file mode 100644 index 0000000000..95f4ecb656 --- /dev/null +++ b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h @@ -0,0 +1,95 @@ +/***************************************************************************************** + * * + * 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_KAMELEONVOLUME___KAMELEONVOLUMERAYCASTER___H__ +#define __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMERAYCASTER___H__ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +namespace ghoul { + namespace opengl { + class Texture; + class ProgramObject; + class TextureUnit; + } +} + +namespace openspace { + +class RenderData; +class RaycastData; + +class KameleonVolumeRaycaster : public VolumeRaycaster { +public: + + KameleonVolumeRaycaster( + std::shared_ptr texture, + std::shared_ptr transferFunction, + std::shared_ptr clipPlanes); + + virtual ~KameleonVolumeRaycaster(); + void initialize(); + void deinitialize(); + void renderEntryPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override; + void renderExitPoints(const RenderData& data, ghoul::opengl::ProgramObject& program) override; + void preRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override; + void postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) override; + bool cameraIsInside(const RenderData& data, glm::vec3& localPosition) override; + + std::string getBoundsVsPath() const override; + std::string getBoundsFsPath() const override; + std::string getRaycastPath() const override; + std::string getHelperPath() const override; + + void setStepSize(float stepSize); + void setGridType(VolumeGridType gridType); + void setModelTransform(const glm::mat4& transform); +private: + std::shared_ptr _clipPlanes; + std::shared_ptr _volumeTexture; + std::shared_ptr _transferFunction; + BoxGeometry _boundingBox; + VolumeGridType _gridType; + glm::mat4 _modelTransform; + + std::unique_ptr _tfUnit; + std::unique_ptr _textureUnit; + float _stepSize; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMERAYCASTER___H__ diff --git a/modules/kameleonvolume/rendering/renderablekameleonvolume.cpp b/modules/kameleonvolume/rendering/renderablekameleonvolume.cpp new file mode 100644 index 0000000000..45e6e8d75a --- /dev/null +++ b/modules/kameleonvolume/rendering/renderablekameleonvolume.cpp @@ -0,0 +1,392 @@ +/***************************************************************************************** + * * + * 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 + +namespace { + const char* _loggerCat = "RenderableKameleonVolume"; +} + +namespace { + const char* KeyDimensions = "Dimensions"; + const char* KeyStepSize = "StepSize"; + const char* KeyTransferFunction = "TransferFunction"; + const char* KeySource = "Source"; + const char* KeyVariable = "Variable"; + const char* KeyLowerDomainBound = "LowerDomainBound"; + const char* KeyUpperDomainBound = "UpperDomainBound"; + const char* KeyDomainScale = "DomainScale"; + const char* KeyLowerValueBound = "LowerValueBound"; + const char* KeyUpperValueBound = "UpperValueBound"; + const char* KeyClipPlanes = "ClipPlanes"; + const char* KeyCache = "Cache"; + const char* KeyGridType = "GridType"; + const char* ValueSphericalGridType = "Spherical"; +} + +namespace openspace { + +RenderableKameleonVolume::RenderableKameleonVolume(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _dimensions("dimensions", "Dimensions") + , _variable("variable", "Variable") + , _lowerDomainBound("lowerDomainBound", "Lower Domain Bound") + , _upperDomainBound("upperDomainBound", "Upper Domain Bound") + , _domainScale("domainScale", "Domain scale") + , _autoDomainBounds(false) + , _lowerValueBound("lowerValueBound", "Lower Value Bound", 0.0, 0.0, 1) + , _upperValueBound("upperValueBound", "Upper Value Bound", 1, 0.01, 1) + , _autoValueBounds(false) + , _gridType("gridType", "Grid Type", properties::OptionProperty::DisplayType::Dropdown) + , _autoGridType(false) + , _clipPlanes(nullptr) + , _stepSize("stepSize", "Step Size", 0.02, 0.01, 1) + , _sourcePath("sourcePath", "Source Path") + , _transferFunctionPath("transferFunctionPath", "Transfer Function Path") + , _raycaster(nullptr) + , _transferFunction(nullptr) + , _cache("cache", "Cache") { + + glm::vec3 dimensions; + if (dictionary.getValue(KeyDimensions, dimensions)) { + _dimensions = dimensions; + } else { + LWARNING("No dimensions specified for volumetric data, falling back to 32^3"); + _dimensions = glm::uvec3(32, 32, 32); + } + + float stepSize; + if (dictionary.getValue(KeyStepSize, stepSize)) { + _stepSize = stepSize; + } + + std::string transferFunctionPath; + if (dictionary.getValue(KeyTransferFunction, transferFunctionPath)) { + _transferFunctionPath = transferFunctionPath; + _transferFunction = std::make_shared(absPath(transferFunctionPath)); + } + + std::string sourcePath; + if (dictionary.getValue(KeySource, sourcePath)) { + _sourcePath = absPath(sourcePath); + } + + std::string variable; + if (dictionary.getValue(KeyVariable, variable)) { + _variable = variable; + } + + glm::vec3 lowerDomainBound; + if (dictionary.getValue(KeyLowerDomainBound, lowerDomainBound)) { + _lowerDomainBound = lowerDomainBound; + } + else { + _autoDomainBounds = true; + } + + glm::vec3 upperDomainBound; + if (dictionary.getValue(KeyUpperDomainBound, upperDomainBound)) { + _upperDomainBound = upperDomainBound; + } + else { + _autoDomainBounds = true; + } + + glm::vec3 domainScale; + if (dictionary.getValue(KeyDomainScale, domainScale)) { + _domainScale = domainScale; + } else { + _domainScale = glm::vec3(1, 1, 1); // Assume meters if nothing else is specified. + } + + float lowerValueBound; + if (dictionary.getValue(KeyLowerValueBound, lowerValueBound)) { + _lowerValueBound = lowerValueBound; + } + else { + _autoValueBounds = true; + } + + float upperValueBound; + if (dictionary.getValue(KeyUpperValueBound, upperValueBound)) { + _upperValueBound = upperValueBound; + } + else { + _autoValueBounds = true; + } + + ghoul::Dictionary clipPlanesDictionary; + dictionary.getValue(KeyClipPlanes, clipPlanesDictionary); + _clipPlanes = std::make_shared(clipPlanesDictionary); + _clipPlanes->setName("clipPlanes"); + + bool cache; + if (dictionary.getValue(KeyCache, cache)) { + _cache = cache; + } + + _gridType.addOption(static_cast(VolumeGridType::Cartesian), "Cartesian grid"); + _gridType.addOption(static_cast(VolumeGridType::Spherical), "Spherical grid"); + _gridType.setValue(static_cast(VolumeGridType::Cartesian)); + + std::string gridType; + if (dictionary.getValue(KeyGridType, gridType)) { + if (gridType == ValueSphericalGridType) { + _gridType.setValue(static_cast(VolumeGridType::Spherical)); + } else { + _autoGridType = true; + } + } +} + +RenderableKameleonVolume::~RenderableKameleonVolume() {} + +bool RenderableKameleonVolume::initialize() { + load(); + + _volumeTexture->uploadTexture(); + _transferFunction->update(); + + _raycaster = std::make_unique(_volumeTexture, _transferFunction, _clipPlanes); + + _raycaster->setStepSize(_stepSize); + _gridType.onChange([this] { + _raycaster->setStepSize(_stepSize); + }); + _raycaster->setGridType(static_cast(_gridType.value())); + _gridType.onChange([this] { + _raycaster->setGridType(static_cast(_gridType.value())); + }); + + updateRaycasterModelTransform(); + _lowerDomainBound.onChange([this] { + updateRaycasterModelTransform(); + }); + _upperDomainBound.onChange([this] { + updateRaycasterModelTransform(); + }); + + _raycaster->initialize(); + + OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); + + auto onChange = [&](bool enabled) { + if (enabled) { + OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); + } + else { + OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get()); + } + }; + + onEnabledChange(onChange); + + _clipPlanes->initialize(); + + addProperty(_dimensions); + addProperty(_stepSize); + addProperty(_transferFunctionPath); + addProperty(_sourcePath); + addProperty(_variable); + addProperty(_lowerDomainBound); + addProperty(_upperDomainBound); + addProperty(_domainScale); + addProperty(_lowerValueBound); + addProperty(_upperValueBound); + addProperty(_gridType); + addProperty(_cache); + addPropertySubOwner(_clipPlanes.get()); + return true; +} + +void RenderableKameleonVolume::updateRaycasterModelTransform() { + glm::vec3 lowerBoundingBoxBound = _domainScale.value() * _lowerDomainBound.value(); + glm::vec3 upperBoundingBoxBound = _domainScale.value() * _upperDomainBound.value(); + + glm::vec3 scale = upperBoundingBoxBound - lowerBoundingBoxBound; + glm::vec3 translation = (lowerBoundingBoxBound + upperBoundingBoxBound) * 0.5f; + + glm::mat4 modelTransform = glm::translate(glm::mat4(1.0), translation); + modelTransform = glm::scale(modelTransform, scale); + _raycaster->setModelTransform(modelTransform); +} + + +bool RenderableKameleonVolume::cachingEnabled() { + return _cache; +} + +void RenderableKameleonVolume::load() { + if (!FileSys.fileExists(_sourcePath)) { + LERROR("File " << _sourcePath << " does not exist."); + return; + } + if (!cachingEnabled()) { + loadFromPath(_sourcePath); + return; + } + ghoul::filesystem::File sourceFile(_sourcePath); + std::string cachePath = FileSys.cacheManager()->cachedFilename( + sourceFile.baseName(), + cacheSuffix(), + ghoul::filesystem::CacheManager::Persistent::Yes + ); + if (FileSys.fileExists(cachePath)) { + loadRaw(cachePath); + } else { + loadFromPath(_sourcePath); + storeRaw(cachePath); + } +} + +std::string RenderableKameleonVolume::cacheSuffix() { + glm::vec3 dims = _dimensions.value(); + return "." + _variable.value() + + "." + std::to_string(dims[0]) + + "x" + std::to_string(dims[1]) + + "x" + std::to_string(dims[2]); +} + +void RenderableKameleonVolume::loadFromPath(const std::string& path) { + ghoul::filesystem::File file(path); + std::string extension = file.fileExtension(); + std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); + if (extension == "cdf") { + loadCdf(path); + } else { + loadRaw(path); + } +} + +void RenderableKameleonVolume::loadRaw(const std::string& path) { + RawVolumeReader reader(path, _dimensions); + _rawVolume = reader.read(); + updateTextureFromVolume(); +} + +void RenderableKameleonVolume::loadCdf(const std::string& path) { + KameleonVolumeReader reader(path); + + if (_autoValueBounds) { + _lowerValueBound = reader.minValue(_variable); + _upperValueBound = reader.maxValue(_variable); + } + + std::vector variables = reader.gridVariableNames(); + + if (variables.size() == 3 && _autoDomainBounds) { + _lowerDomainBound = glm::vec3( + reader.minValue(variables[0]), + reader.minValue(variables[1]), + reader.minValue(variables[2])); + + _upperDomainBound = glm::vec3( + reader.maxValue(variables[0]), + reader.maxValue(variables[1]), + reader.maxValue(variables[2])); + } + + if (variables.size() == 3 && _autoGridType) { + if (variables[0] == "r" && variables[0] == "theta" && variables[0] == "phi") { + _gridType.setValue(static_cast(VolumeGridType::Spherical)); + } + else { + _gridType.setValue(static_cast(VolumeGridType::Cartesian)); + } + } + + ghoul::Dictionary dict = reader.readMetaData(); + _rawVolume = reader.readFloatVolume(_dimensions, _variable, _lowerDomainBound, _upperDomainBound); + updateTextureFromVolume(); +} + +void RenderableKameleonVolume::updateTextureFromVolume() { + _normalizedVolume = std::make_unique>(_dimensions); + float* in = _rawVolume->data(); + GLfloat* out = _normalizedVolume->data(); + float min = _lowerValueBound; + float diff = _upperValueBound - _lowerValueBound; + + for (size_t i = 0; i < _normalizedVolume->nCells(); ++i) { + out[i] = glm::clamp((in[i] - min) / diff, 0.0f, 1.0f); + } + + _volumeTexture = std::make_shared( + _dimensions, + ghoul::opengl::Texture::Format::Red, + GL_RED, + GL_FLOAT, + ghoul::opengl::Texture::FilterMode::Linear, + ghoul::opengl::Texture::WrappingMode::Repeat + ); + + void* data = reinterpret_cast(_normalizedVolume->data()); + _volumeTexture->setPixelData(data, ghoul::opengl::Texture::TakeOwnership::No); +} + +void RenderableKameleonVolume::storeRaw(const std::string& path) { + RawVolumeWriter writer(path); + writer.write(*_rawVolume); +} + +bool RenderableKameleonVolume::deinitialize() { + if (_raycaster) { + OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get()); + _raycaster = nullptr; + } + return true; +} + +bool RenderableKameleonVolume::isReady() const { + return true; +} + +void RenderableKameleonVolume::update(const UpdateData& data) { + if (_raycaster) { + _raycaster->setStepSize(_stepSize); + } +} + +void RenderableKameleonVolume::render(const RenderData& data, RendererTasks& tasks) { + tasks.raycasterTasks.push_back({ _raycaster.get(), data }); +} + +} diff --git a/modules/kameleonvolume/rendering/renderablekameleonvolume.h b/modules/kameleonvolume/rendering/renderablekameleonvolume.h new file mode 100644 index 0000000000..e96a9e2a14 --- /dev/null +++ b/modules/kameleonvolume/rendering/renderablekameleonvolume.h @@ -0,0 +1,103 @@ +/***************************************************************************************** + * * + * 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_KAMELEONVOLUME___RENDERABLEKAMELEONVOLUME___H__ +#define __OPENSPACE_MODULE_KAMELEONVOLUME___RENDERABLEKAMELEONVOLUME___H__ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + + +namespace openspace { + +struct RenderData; + +class RenderableKameleonVolume : public Renderable { +public: + RenderableKameleonVolume(const ghoul::Dictionary& dictionary); + ~RenderableKameleonVolume(); + + bool initialize() override; + bool deinitialize() override; + bool isReady() const override; + void render(const RenderData& data, RendererTasks& tasks) override; + void update(const UpdateData& data) override; + bool cachingEnabled(); + +private: + void load(); + void loadFromPath(const std::string& path); + void loadRaw(const std::string& path); + void loadCdf(const std::string& path); + void storeRaw(const std::string& path); + + std::string cacheSuffix(); + void updateTextureFromVolume(); + void updateRaycasterModelTransform(); + + properties::UVec3Property _dimensions; + properties::StringProperty _variable; + properties::Vec3Property _lowerDomainBound; + properties::Vec3Property _upperDomainBound; + properties::Vec3Property _domainScale; + bool _autoDomainBounds; + + properties::FloatProperty _lowerValueBound; + properties::FloatProperty _upperValueBound; + bool _autoValueBounds; + + properties::OptionProperty _gridType; + bool _autoGridType; + + std::shared_ptr _clipPlanes; + + properties::FloatProperty _stepSize; + properties::StringProperty _sourcePath; + properties::StringProperty _transferFunctionPath; + properties::BoolProperty _cache; + + + std::unique_ptr> _rawVolume; + std::unique_ptr> _normalizedVolume; + std::unique_ptr _raycaster; + + std::shared_ptr _volumeTexture; + std::shared_ptr _transferFunction; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___RENDERABLEKAMELEONVOLUME___H__ diff --git a/modules/kameleonvolume/shaders/boundsfs.glsl b/modules/kameleonvolume/shaders/boundsfs.glsl new file mode 100644 index 0000000000..f56b7319a7 --- /dev/null +++ b/modules/kameleonvolume/shaders/boundsfs.glsl @@ -0,0 +1,40 @@ +/***************************************************************************************** + * * + * 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. * + ****************************************************************************************/ + +in vec4 positionLocalSpace; +in vec4 positionCameraSpace; + +#include "PowerScaling/powerScaling_fs.hglsl" +#include "fragment.glsl" + +Fragment getFragment() { + vec4 fragColor = vec4(positionLocalSpace.xyz+0.5, 1.0); + vec4 position = positionCameraSpace; + float depth = pscDepth(position); + + Fragment frag; + frag.color = fragColor; + frag.depth = depth; + return frag; +} diff --git a/modules/kameleonvolume/shaders/boundsvs.glsl b/modules/kameleonvolume/shaders/boundsvs.glsl new file mode 100644 index 0000000000..4d10ec054a --- /dev/null +++ b/modules/kameleonvolume/shaders/boundsvs.glsl @@ -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. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(location = 0) in vec3 vertPosition; + +uniform mat4 modelViewTransform; +uniform mat4 projectionTransform; + +out vec4 positionLocalSpace; +out vec4 positionCameraSpace; + +#include "PowerScaling/powerScaling_vs.hglsl" + +void main() { + + positionLocalSpace = vec4(vertPosition, 1.0); + positionCameraSpace = modelViewTransform * positionLocalSpace; + + vec4 positionClipSpace = projectionTransform * positionCameraSpace; + vec4 positionScreenSpace = z_normalization(positionClipSpace); + + //positionScreenSpace.z = 1.0; + // project the position to view space + gl_Position = positionScreenSpace; +} diff --git a/modules/kameleonvolume/shaders/helper.glsl b/modules/kameleonvolume/shaders/helper.glsl new file mode 100644 index 0000000000..53b011a31d --- /dev/null +++ b/modules/kameleonvolume/shaders/helper.glsl @@ -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. * + ****************************************************************************************/ + +#define KAMELEON_PI 3.14159265358979323846 /* pi */ +#define KAMELEON_SQRT1_3 0.57735026919 /* 1/sqrt(3) */ + +vec3 kameleon_cartesianToSpherical(vec3 zeroToOneCoords) { + // Put cartesian in [-1..1] range first + const vec3 cartesian = vec3(-1.0,-1.0,-1.0) + zeroToOneCoords * 2.0f; + + const float r = length(cartesian); + float theta, phi; + + if (r == 0.0) { + theta = phi = 0.0; + } else { + theta = acos(cartesian.z/r) / KAMELEON_PI; + phi = (KAMELEON_PI + atan(cartesian.y, cartesian.x)) / (2.0*KAMELEON_PI ); + } + return vec3(r * KAMELEON_SQRT1_3, theta, phi); +} \ No newline at end of file diff --git a/modules/kameleonvolume/shaders/raycast.glsl b/modules/kameleonvolume/shaders/raycast.glsl new file mode 100644 index 0000000000..0d21ab261b --- /dev/null +++ b/modules/kameleonvolume/shaders/raycast.glsl @@ -0,0 +1,80 @@ +/***************************************************************************************** + * * + * 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 float maxStepSize#{id} = 0.02; +uniform sampler3D volumeTexture_#{id}; +uniform sampler1D transferFunction_#{id}; +uniform int gridType_#{id} = 0; + +uniform int nClips_#{id}; +uniform vec3 clipNormals_#{id}[8]; +uniform vec2 clipOffsets_#{id}[8]; + + +void sample#{id}(vec3 samplePos, + vec3 dir, + inout vec3 accumulatedColor, + inout vec3 accumulatedAlpha, + inout float stepSize) { + + vec3 transformedPos = samplePos; + if (gridType_#{id} == 1) { + transformedPos = kameleon_cartesianToSpherical(samplePos); + } + + + float clipAlpha = 1.0; + vec3 centerToPos = transformedPos - vec3(0.5); + + + for (int i = 0; i < nClips_#{id} && i < 8; i++) { + vec3 clipNormal = clipNormals_#{id}[i]; + float clipBegin = clipOffsets_#{id}[i].x; + float clipEnd = clipBegin + clipOffsets_#{id}[i].y; + clipAlpha *= smoothstep(clipBegin, clipEnd, dot(centerToPos, clipNormal)); + } + + if (clipAlpha > 0) { + float val = texture(volumeTexture_#{id}, transformedPos).r; + vec4 color = texture(transferFunction_#{id}, val); + vec3 backColor = color.rgb; + vec3 backAlpha = color.aaa; + + backColor *= stepSize * clipAlpha; + backAlpha *= stepSize * clipAlpha; + + backColor = clamp(backColor, 0.0, 1.0); + backAlpha = clamp(backAlpha, 0.0, 1.0); + + vec3 oneMinusFrontAlpha = vec3(1.0) - accumulatedAlpha; + accumulatedColor += oneMinusFrontAlpha * backColor; + accumulatedAlpha += oneMinusFrontAlpha * backAlpha; + } + + stepSize = maxStepSize#{id}; +} + +float stepSize#{id}(vec3 samplePos, vec3 dir) { + return maxStepSize#{id}; +} diff --git a/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp b/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp new file mode 100644 index 0000000000..a8c2a275fb --- /dev/null +++ b/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp @@ -0,0 +1,162 @@ +/***************************************************************************************** + * * + * 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 + +namespace { + const char* KeyInput = "Input"; + const char* KeyOutput = "Output"; + const char* MainTemplateFilename = "${OPENSPACE_DATA}/web/kameleondocumentation/main.hbs"; + const char* HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; + const char* JsFilename = "${OPENSPACE_DATA}/web/kameleondocumentation/script.js"; + const char* BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; + const char* CssFilename = "${OPENSPACE_DATA}/web/common/style.css"; +} + +namespace openspace { + +KameleonDocumentationTask::KameleonDocumentationTask(const ghoul::Dictionary& dictionary) { + openspace::documentation::testSpecificationAndThrow( + documentation(), + dictionary, + "KameleonDocumentationTask" + ); + + _inputPath = absPath(dictionary.value(KeyInput)); + _outputPath = absPath(dictionary.value(KeyOutput)); +} + +std::string KameleonDocumentationTask::description() { + return "Extract metadata from cdf-file " + _inputPath + " and output html documentation to " + _outputPath; +} + +void KameleonDocumentationTask::perform(const Task::ProgressCallback & progressCallback) { + KameleonVolumeReader reader(_inputPath); + ghoul::Dictionary kameleonDictionary = reader.readMetaData(); + progressCallback(0.33f); + ghoul::DictionaryJsonFormatter formatter; + + + ghoul::Dictionary dictionary = { + {"kameleon", std::move(kameleonDictionary)}, + {"version", + std::to_string(OPENSPACE_VERSION_MAJOR) + "." + + std::to_string(OPENSPACE_VERSION_MINOR) + "." + + std::to_string(OPENSPACE_VERSION_PATCH) + }, + {"input", _inputPath} + }; + + std::string json = formatter.format(dictionary); + progressCallback(0.66f); + + std::ifstream handlebarsInput(absPath(HandlebarsFilename)); + std::ifstream jsInput(absPath(JsFilename)); + + std::string jsContent; + std::back_insert_iterator jsInserter(jsContent); + + std::copy(std::istreambuf_iterator{handlebarsInput}, std::istreambuf_iterator(), jsInserter); + std::copy(std::istreambuf_iterator{jsInput}, std::istreambuf_iterator(), jsInserter); + + std::ifstream bootstrapInput(absPath(BootstrapFilename)); + std::ifstream cssInput(absPath(CssFilename)); + + std::string cssContent; + std::back_insert_iterator cssInserter(cssContent); + + std::copy(std::istreambuf_iterator{bootstrapInput}, std::istreambuf_iterator(), cssInserter); + std::copy(std::istreambuf_iterator{cssInput}, std::istreambuf_iterator(), cssInserter); + + std::ifstream mainTemplateInput(absPath(MainTemplateFilename)); + std::string mainTemplateContent{ std::istreambuf_iterator{mainTemplateInput}, + std::istreambuf_iterator{}}; + + std::ofstream file; + file.exceptions(~std::ofstream::goodbit); + file.open(_outputPath); + + std::stringstream html; + html << "\n" + << "\n" + << "\t\n" + << "\t\t\n" + << "\t\t\n" + << "\t\n" + << "\t\n" + << "\t\tDocumentation\n" + << "\t\n" + << "\t\n" + << "\t\n" + << "\n"; + + file << html.str(); + + progressCallback(1.0f); +} + +documentation::Documentation KameleonDocumentationTask::documentation() { + using namespace documentation; + return { + "KameleonDocumentationTask", + "kameleon_documentation_task", + { + { + "Type", + new StringEqualVerifier("KameleonDocumentationTask"), + "The type of this task" + }, + { + KeyInput, + new StringAnnotationVerifier("A file path to a cdf file"), + "The cdf file to extract data from" + }, + { + KeyOutput, + new StringAnnotationVerifier("A valid filepath"), + "The html file to write documentation to" + } + } + }; +} + +} // namespace openspace diff --git a/modules/kameleonvolume/tasks/kameleondocumentationtask.h b/modules/kameleonvolume/tasks/kameleondocumentationtask.h new file mode 100644 index 0000000000..90c133a07f --- /dev/null +++ b/modules/kameleonvolume/tasks/kameleondocumentationtask.h @@ -0,0 +1,45 @@ +/***************************************************************************************** + * * + * 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_KAMELEONVOLUME___KAMELEONDOCUMENTATIONTASK___H__ +#define __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONDOCUMENTATIONTASK___H__ + +#include + +namespace openspace { + +class KameleonDocumentationTask : public Task { +public: + KameleonDocumentationTask(const ghoul::Dictionary& dictionary); + std::string description() override; + void perform(const Task::ProgressCallback& progressCallback) override; + static documentation::Documentation documentation(); +private: + std::string _inputPath; + std::string _outputPath; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONDOCUMENTATIONTASK___H__ diff --git a/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp new file mode 100644 index 0000000000..50e1775df8 --- /dev/null +++ b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp @@ -0,0 +1,94 @@ +/***************************************************************************************** + * * + * 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 char* KeyInput = "Input"; + const char* KeyOutput = "Output"; +} + +namespace openspace { + +KameleonMetadataToJsonTask::KameleonMetadataToJsonTask(const ghoul::Dictionary& dictionary) { + openspace::documentation::testSpecificationAndThrow( + documentation(), + dictionary, + "KameleonMetadataToJsonTask" + ); + + _inputPath = absPath(dictionary.value(KeyInput)); + _outputPath = absPath(dictionary.value(KeyOutput)); +} + +std::string KameleonMetadataToJsonTask::description() { + return "Extract metadata from cdf-file " + _inputPath + " and write as json to " + _outputPath; +} + +void KameleonMetadataToJsonTask::perform(const Task::ProgressCallback & progressCallback) { + KameleonVolumeReader reader(_inputPath); + ghoul::Dictionary dictionary = reader.readMetaData(); + progressCallback(0.5f); + ghoul::DictionaryJsonFormatter formatter; + std::string json = formatter.format(dictionary); + std::ofstream output(_outputPath); + output << json; + progressCallback(1.0f); +} + +documentation::Documentation KameleonMetadataToJsonTask::documentation() +{ + using namespace documentation; + return { + "KameleonMetadataToJsonTask", + "kameleon_metadata_to_json_task", + { + { + "Type", + new StringEqualVerifier("KameleonMetadataToJsonTask"), + "The type of this task" + }, + { + KeyInput, + new StringAnnotationVerifier("A file path to a cdf file"), + "The cdf file to extract data from" + }, + { + KeyOutput, + new StringAnnotationVerifier("A valid filepath"), + "The json file to export data into" + } + } + }; +} + + + +} // namespace openspace diff --git a/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.h b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.h new file mode 100644 index 0000000000..144b9a9330 --- /dev/null +++ b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.h @@ -0,0 +1,45 @@ +/***************************************************************************************** + * * + * 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_KAMELEONVOLUME___KAMELEONMETADATATOJSONTASK___H__ +#define __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONMETADATATOJSONTASK___H__ + +#include + +namespace openspace { + +class KameleonMetadataToJsonTask : public Task { +public: + KameleonMetadataToJsonTask(const ghoul::Dictionary& dictionary); + std::string description() override; + void perform(const Task::ProgressCallback& progressCallback) override; + static documentation::Documentation documentation(); +private: + std::string _inputPath; + std::string _outputPath; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONMETADATATOJSONTASK___H__ diff --git a/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp b/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp index 5d9c2ed3ba..73b694918d 100644 --- a/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp +++ b/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp @@ -47,7 +47,8 @@ namespace { namespace openspace { -MultiresVolumeRaycaster::MultiresVolumeRaycaster(std::shared_ptr tsp, +MultiresVolumeRaycaster::MultiresVolumeRaycaster( + std::shared_ptr tsp, std::shared_ptr atlasManager, std::shared_ptr transferFunction) : _tsp(tsp) @@ -112,11 +113,9 @@ void MultiresVolumeRaycaster::preRaycast(const RaycastData& data, ghoul::opengl: _atlasManager->textureAtlas().bind(); program.setUniform("textureAtlas_" + id, _atlasUnit->unitNumber()); - _atlasMapBinding = std::make_unique>(); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, _atlasMapBinding->bindingNumber(), _atlasManager->atlasMapBuffer()); program.setSsboBinding("atlasMapBlock_" + id, _atlasMapBinding->bindingNumber()); - program.setUniform("gridType_" + id, static_cast(_tsp->header().gridType_)); program.setUniform("maxNumBricksPerAxis_" + id, static_cast(_tsp->header().xNumBricks_)); @@ -155,7 +154,8 @@ bool MultiresVolumeRaycaster::cameraIsInside(const RenderData& data, glm::vec3& } void MultiresVolumeRaycaster::postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { - // For example: release texture units + _atlasUnit = nullptr; + _tfUnit = nullptr; } std::string MultiresVolumeRaycaster::getBoundsVsPath() const { diff --git a/modules/space/spacemodule.h b/modules/space/spacemodule.h index f1f90d513b..3d954c30a9 100644 --- a/modules/space/spacemodule.h +++ b/modules/space/spacemodule.h @@ -22,8 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_SPACE___BASEMODULE___H__ -#define __OPENSPACE_MODULE_SPACE___BASEMODULE___H__ +#ifndef __OPENSPACE_MODULE_SPACE___SPACEMODULE___H__ +#define __OPENSPACE_MODULE_SPACE___SPACEMODULE___H__ #include @@ -32,7 +32,7 @@ namespace openspace { class SpaceModule : public OpenSpaceModule { public: SpaceModule(); - + virtual ~SpaceModule() = default; std::vector documentations() const override; protected: @@ -41,4 +41,4 @@ protected: } // namespace openspace -#endif // __OPENSPACE_MODULE_SPACE___BASEMODULE___H__ +#endif // __OPENSPACE_MODULE_SPACE___SPACEMODULE___H__ diff --git a/modules/volume/CMakeLists.txt b/modules/volume/CMakeLists.txt index 09c6d8efde..11da446b0e 100644 --- a/modules/volume/CMakeLists.txt +++ b/modules/volume/CMakeLists.txt @@ -35,9 +35,12 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/textureslicevolumereader.inl ${CMAKE_CURRENT_SOURCE_DIR}/lrucache.h ${CMAKE_CURRENT_SOURCE_DIR}/linearlrucache.h + ${CMAKE_CURRENT_SOURCE_DIR}/volumegridtype.h ${CMAKE_CURRENT_SOURCE_DIR}/volumesampler.h ${CMAKE_CURRENT_SOURCE_DIR}/volumesampler.inl ${CMAKE_CURRENT_SOURCE_DIR}/volumeutils.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/volumeclipplane.h + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/volumeclipplanes.h ) source_group("Header Files" FILES ${HEADER_FILES}) @@ -48,6 +51,8 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/textureslicevolumereader.inl ${CMAKE_CURRENT_SOURCE_DIR}/volumesampler.inl ${CMAKE_CURRENT_SOURCE_DIR}/volumeutils.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/volumeclipplane.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/volumeclipplanes.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/volume/rawvolume.h b/modules/volume/rawvolume.h index 065ff16faa..30be87bcd6 100644 --- a/modules/volume/rawvolume.h +++ b/modules/volume/rawvolume.h @@ -25,25 +25,31 @@ #ifndef __OPENSPACE_MODULE_VOLUME___RAWVOLUME___H__ #define __OPENSPACE_MODULE_VOLUME___RAWVOLUME___H__ +#include +#include +#include + namespace openspace { template class RawVolume { public: typedef Voxel VoxelType; - RawVolume(const glm::ivec3& dimensions); - glm::ivec3 dimensions() const; - void setDimensions(const glm::ivec3& dimensions); - VoxelType get(const glm::ivec3& coordinates) const; + RawVolume(const glm::uvec3& dimensions); + glm::uvec3 dimensions() const; + void setDimensions(const glm::uvec3& dimensions); + size_t nCells() const; + VoxelType get(const glm::uvec3& coordinates) const; VoxelType get(const size_t index) const; - void set(const glm::ivec3& coordinates, const VoxelType& value); + void set(const glm::uvec3& coordinates, const VoxelType& value); void set(size_t index, const VoxelType& value); - void forEachVoxel(const std::function& fn); + void forEachVoxel(const std::function& fn); + const VoxelType* data() const; + size_t coordsToIndex(const glm::uvec3& cartesian) const; + glm::uvec3 indexToCoords(size_t linear) const; VoxelType* data(); private: - size_t coordsToIndex(const glm::ivec3& cartesian) const; - glm::ivec3 indexToCoords(size_t linear) const; - glm::ivec3 _dimensions; + glm::uvec3 _dimensions; std::vector _data; }; diff --git a/modules/volume/rawvolume.inl b/modules/volume/rawvolume.inl index 66cfb70b37..3606e2cd0f 100644 --- a/modules/volume/rawvolume.inl +++ b/modules/volume/rawvolume.inl @@ -23,31 +23,39 @@ ****************************************************************************************/ #include +#include "rawvolume.h" namespace openspace { template -RawVolume::RawVolume(const glm::ivec3& dimensions) +RawVolume::RawVolume(const glm::uvec3& dimensions) : _dimensions(dimensions) , _data(static_cast(dimensions.x) * static_cast(dimensions.y) * static_cast(dimensions.z)) {} template -glm::ivec3 RawVolume::dimensions() const { +glm::uvec3 RawVolume::dimensions() const { return _dimensions; } template -void RawVolume::setDimensions(const glm::ivec3& dimensions) { +void RawVolume::setDimensions(const glm::uvec3& dimensions) { _dimensions = dimensions; - _data.resize(static_cast(dimensions.x) * - static_cast(dimensions.y) * - static_cast(dimensions.z)); + _data.resize(nCells()); +} + +template +size_t RawVolume::nCells() const +{ + return static_cast( + static_cast(_dimensions.x) * + static_cast(_dimensions.y) * + static_cast(_dimensions.z)); } template -VoxelType RawVolume::get(const glm::ivec3& coordinates) const { +VoxelType RawVolume::get(const glm::uvec3& coordinates) const { return get(coordsToIndex(coordinates, dimensions())); } @@ -57,7 +65,7 @@ VoxelType RawVolume::get(size_t index) const { } template -void RawVolume::set(const glm::ivec3& coordinates, const VoxelType& value) { +void RawVolume::set(const glm::uvec3& coordinates, const VoxelType& value) { return set(coordsToIndex(coordinates, dimensions()), value); } @@ -68,27 +76,21 @@ void RawVolume::set(size_t index, const VoxelType& value) { template void RawVolume::forEachVoxel( - const std::function& fn) + const std::function& fn) { - - glm::ivec3 dims = dimensions(); - size_t nVals = static_cast(dims.x) * - static_cast(dims.y) * - static_cast(dims.z); - - for (size_t i = 0; i < nVals; i++) { + for (size_t i = 0; i < nCells(); i++) { glm::ivec3 coords = indexToCoords(i); fn(coords, _data[i]); } } template -size_t RawVolume::coordsToIndex(const glm::ivec3& cartesian) const { +size_t RawVolume::coordsToIndex(const glm::uvec3& cartesian) const { return volumeutils::coordsToIndex(cartesian, dimensions()); } template -glm::ivec3 RawVolume::indexToCoords(size_t linear) const { +glm::uvec3 RawVolume::indexToCoords(size_t linear) const { return volumeutils::indexToCoords(linear, dimensions()); } @@ -96,5 +98,11 @@ template VoxelType* RawVolume::data() { return _data.data(); } + +template +const VoxelType* RawVolume::data() const { + return _data.data(); +} + } diff --git a/modules/volume/rawvolumereader.h b/modules/volume/rawvolumereader.h index 8e915477e4..d696ca763d 100644 --- a/modules/volume/rawvolumereader.h +++ b/modules/volume/rawvolumereader.h @@ -34,18 +34,18 @@ template class RawVolumeReader { public: typedef Voxel VoxelType; - RawVolumeReader(const std::string& path, const glm::ivec3& dimensions); - glm::ivec3 dimensions() const; + RawVolumeReader(const std::string& path, const glm::uvec3& dimensions); + glm::uvec3 dimensions() const; std::string path() const; void setPath(const std::string& path); - void setDimensions(const glm::ivec3& dimensions); + void setDimensions(const glm::uvec3& dimensions); //VoxelType get(const glm::ivec3& coordinates) const; // TODO: Implement this //VoxelType get(const size_t index) const; // TODO: Implement this std::unique_ptr> read(); private: - size_t coordsToIndex(const glm::ivec3& cartesian) const; - glm::ivec3 indexToCoords(size_t linear) const; - glm::ivec3 _dimensions; + size_t coordsToIndex(const glm::uvec3& cartesian) const; + glm::uvec3 indexToCoords(size_t linear) const; + glm::uvec3 _dimensions; std::string _path; }; diff --git a/modules/volume/rawvolumereader.inl b/modules/volume/rawvolumereader.inl index 601968ee95..a00a464503 100644 --- a/modules/volume/rawvolumereader.inl +++ b/modules/volume/rawvolumereader.inl @@ -28,18 +28,18 @@ namespace openspace { template RawVolumeReader::RawVolumeReader(const std::string& path, - const glm::ivec3& dimensions) + const glm::uvec3& dimensions) : _path(path) , _dimensions(dimensions) {} template -glm::ivec3 RawVolumeReader::dimensions() const { +glm::uvec3 RawVolumeReader::dimensions() const { return _dimensions; } template -void RawVolumeReader::setDimensions(const glm::ivec3& dimensions) { +void RawVolumeReader::setDimensions(const glm::uvec3& dimensions) { _dimensions = dimensions; } @@ -68,19 +68,19 @@ VoxelType RawVolumeReader::get(size_t index) const { }*/ template -size_t RawVolumeReader::coordsToIndex(const glm::ivec3& cartesian) const { +size_t RawVolumeReader::coordsToIndex(const glm::uvec3& cartesian) const { return volumeutils::coordsToIndex(cartesian, dimensions()); } template -glm::ivec3 RawVolumeReader::indexToCoords(size_t linear) const { +glm::uvec3 RawVolumeReader::indexToCoords(size_t linear) const { return volumeutils::indexToCoords(linear, dimensions()); } template std::unique_ptr> RawVolumeReader::read() { - glm::ivec3 dims = dimensions(); + glm::uvec3 dims = dimensions(); std::unique_ptr> volume = std::make_unique>(dims); diff --git a/modules/volume/rawvolumewriter.h b/modules/volume/rawvolumewriter.h index 39988edcbb..ec0cdf28f1 100644 --- a/modules/volume/rawvolumewriter.h +++ b/modules/volume/rawvolumewriter.h @@ -36,13 +36,13 @@ class RawVolumeWriter { public: RawVolumeWriter(std::string path, size_t bufferSize = 1024); void setPath(const std::string& path); - glm::ivec3 dimensions() const; - void setDimensions(const glm::ivec3& dimensions); - void write(const std::function& fn, + glm::uvec3 dimensions() const; + void setDimensions(const glm::uvec3& dimensions); + void write(const std::function& fn, const std::function& onProgress = [](float t) {}); void write(const RawVolume& volume); - size_t coordsToIndex(const glm::ivec3& coords) const; + size_t coordsToIndex(const glm::uvec3& coords) const; glm::ivec3 indexToCoords(size_t linear) const; private: glm::ivec3 _dimensions; diff --git a/modules/volume/rawvolumewriter.inl b/modules/volume/rawvolumewriter.inl index b45ff93dcc..3709368361 100644 --- a/modules/volume/rawvolumewriter.inl +++ b/modules/volume/rawvolumewriter.inl @@ -33,7 +33,7 @@ template , _bufferSize(bufferSize) {} template -size_t RawVolumeWriter::coordsToIndex(const glm::ivec3& cartesian) const { +size_t RawVolumeWriter::coordsToIndex(const glm::uvec3& cartesian) const { return volumeutils::coordsToIndex(cartesian, dimensions()); } @@ -43,21 +43,21 @@ glm::ivec3 RawVolumeWriter::indexToCoords(size_t linear) const { } template - void RawVolumeWriter::setDimensions(const glm::ivec3& dimensions) { +void RawVolumeWriter::setDimensions(const glm::uvec3& dimensions) { _dimensions = dimensions; } template - glm::ivec3 RawVolumeWriter::dimensions() const { +glm::uvec3 RawVolumeWriter::dimensions() const { return _dimensions; } template -void RawVolumeWriter::write(const std::function& fn, +void RawVolumeWriter::write(const std::function& fn, const std::function& onProgress) { - glm::ivec3 dims = dimensions(); + glm::uvec3 dims = dimensions(); size_t size = static_cast(dims.x) * static_cast(dims.y) * @@ -86,14 +86,11 @@ void RawVolumeWriter::write(const std::function void RawVolumeWriter::write(const RawVolume& volume) { - glm::ivec3 dims = dimensions(); - ghoul_assert(dims == volume.dims(), "Dimensions of input and output volume must agree"); + setDimensions(volume.dimensions()); + reinterpret_cast(volume.data()); - const char* buffer = reinterpret_cast(volume.data()); - size_t length = static_cast(dims.x) * - static_cast(dims.y) * - static_cast(dims.z) * - sizeof(VoxelType); + const char* const buffer = reinterpret_cast(volume.data()); + size_t length = volume.nCells() * sizeof(VoxelType); std::ofstream file(_path, std::ios::binary); file.write(buffer, length); diff --git a/modules/volume/rendering/renderablevolume.cpp b/modules/volume/rendering/renderablevolume.cpp deleted file mode 100644 index 558bed474f..0000000000 --- a/modules/volume/rendering/renderablevolume.cpp +++ /dev/null @@ -1,461 +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. * - ****************************************************************************************/ - -// open space includes -#include -#include -#include -#include - -// ghoul includes -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace { - const std::string _loggerCat = "RenderableVolume"; - - bool hasExtension (std::string const &filepath, std::string const &extension) - { - std::string ending = "." + extension; - if (filepath.length() > ending.length()) { - return (0 == filepath.compare (filepath.length() - ending.length(), ending.length(), ending)); - } else { - return false; - } - } - - template - T stringToNumber(const std::string& number, std::function f = nullptr) { - static_assert(std::is_integral::value || std::is_floating_point::value, - "Must be integral or floating point"); - std::stringstream ss; - T templateNumber = {0}; - ss << number; - ss >> templateNumber; - if( ! f) - return templateNumber; - - return f(templateNumber); - - } -} - -namespace openspace { - -RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary) : Renderable(dictionary) { -} - -RenderableVolume::~RenderableVolume() { -} - -ghoul::opengl::Texture* RenderableVolume::loadVolume( - const std::string& filepath, - const ghoul::Dictionary& hintsDictionary) { - - if( ! FileSys.fileExists(filepath)) { - LWARNING("Could not load volume, could not find '" << filepath << "'"); - return nullptr; - } - - if(hasExtension(filepath, "raw")) { - ghoul::RawVolumeReader::ReadHints hints = readHints(hintsDictionary); - ghoul::RawVolumeReader rawReader(hints); - return rawReader.read(filepath); - } else if(hasExtension(filepath, "cdf")) { - - ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear; - ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge; - - glm::size3_t dimensions(1,1,1); - double tempValue; - if (hintsDictionary.hasKey("Dimensions.1") && - hintsDictionary.getValue("Dimensions.1", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[0] = intVal; - } - if (hintsDictionary.hasKey("Dimensions.2") && - hintsDictionary.getValue("Dimensions.2", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[1] = intVal; - } - if (hintsDictionary.hasKey("Dimensions.3") && - hintsDictionary.getValue("Dimensions.3", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[2] = intVal; - } - - std::string variableCacheString = ""; - if (hintsDictionary.hasKey("Variable")) { - hintsDictionary.getValue("Variable", variableCacheString); - } else if(hintsDictionary.hasKey("Variables")) { - std::string xVariable, yVariable, zVariable; - bool xVar, yVar, zVar; - xVar = hintsDictionary.getValue("Variables.1", xVariable); - yVar = hintsDictionary.getValue("Variables.2", yVariable); - zVar = hintsDictionary.getValue("Variables.3", zVariable); - if (xVar && yVar && zVar) { - variableCacheString = xVariable + "." + yVariable + "." + zVariable; - } - } - - bool cache = false; - hintsDictionary.hasKey("Cache"); - if (hintsDictionary.hasKey("Cache")) - hintsDictionary.getValue("Cache", cache); - - std::stringstream ss; - ss << "." << dimensions[0] << "x" << dimensions[1] << "x" << dimensions[2] << "." << "." << variableCacheString << ".cache"; - - // = filepath + ss.str(); - ghoul::filesystem::File ghlFile(filepath); - std::string cachepath = FileSys.cacheManager()->cachedFilename(ghlFile.baseName(), - ss.str(), true); - if (cache && FileSys.fileExists(cachepath)) { - -#define VOLUME_LOAD_PROGRESSBAR - std::ifstream file(cachepath, std::ios::binary | std::ios::in); - if (file.is_open()) { - size_t length = dimensions[0] * dimensions[1] * dimensions[2]; - float* data = new float[length]; -#ifdef VOLUME_LOAD_PROGRESSBAR - LINFO("Loading cache: " << cachepath); - ProgressBar pb(static_cast(dimensions[2])); - for (size_t i = 0; i < dimensions[2]; ++i) { - size_t offset = length / dimensions[2]; - std::streamsize offsetsize = sizeof(float)*offset; - file.read(reinterpret_cast(data + offset * i), offsetsize); - pb.print(static_cast(i)); - } -#else - file.read(reinterpret_cast(data), sizeof(float)*length); -#endif - file.close(); - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, filtermode, wrappingmode); - } else { - return nullptr; - } - } - - KameleonWrapper kw(filepath); - std::string variableString; - if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) { - float* data = kw.getUniformSampledValues(variableString, dimensions); - if(cache) { - std::ofstream file(cachepath, std::ios::binary | std::ios::out); - if (file.is_open()) { - size_t length = dimensions[0] * dimensions[1] * dimensions[2]; - file.write(reinterpret_cast(data), sizeof(float)*length); - file.close(); - } - } - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, filtermode, wrappingmode); - } else if (hintsDictionary.hasKey("Variables")) { - std::string xVariable, yVariable, zVariable; - bool xVar, yVar, zVar; - xVar = hintsDictionary.getValue("Variables.1", xVariable); - yVar = hintsDictionary.getValue("Variables.2", yVariable); - zVar = hintsDictionary.getValue("Variables.3", zVariable); - - if (!xVar || !yVar || !zVar) { - LERROR("Error reading variables! Must be 3 and must exist in CDF data"); - } else { - - float* data = kw.getUniformSampledVectorValues(xVariable, yVariable, zVariable, dimensions); - if(cache) { - //FILE* file = fopen (cachepath.c_str(), "wb"); - std::ofstream file(cachepath, std::ios::in | std::ios::binary); - size_t length = dimensions[0] * dimensions[1] * dimensions[2]; - file.write(reinterpret_cast(data), sizeof(float)*length); - file.close(); - } - - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT, filtermode, wrappingmode); - } - - } else { - LWARNING("Hints does not specify a 'Variable' or 'Variables'"); - } - } else { - LWARNING("No valid file extension."); - } - return nullptr; -} - -glm::vec3 RenderableVolume::getVolumeOffset( - const std::string& filepath, - const ghoul::Dictionary& hintsDictionary) { - - KameleonWrapper kw(filepath); - return kw.getModelBarycenterOffset(); -} - -ghoul::RawVolumeReader::ReadHints RenderableVolume::readHints(const ghoul::Dictionary& dictionary) { - ghoul::RawVolumeReader::ReadHints hints; - hints._dimensions = glm::ivec3(1, 1, 1); - hints._format = ghoul::opengl::Texture::Format::Red; - hints._internalFormat = GL_R8; - - // parse hints - double tempValue; - if (dictionary.hasKey("Dimensions.1") && dictionary.getValue("Dimensions.1", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - hints._dimensions[0] = intVal; - } - if (dictionary.hasKey("Dimensions.2") && dictionary.getValue("Dimensions.2", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - hints._dimensions[1] = intVal; - } - if (dictionary.hasKey("Dimensions.3") && dictionary.getValue("Dimensions.3", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - hints._dimensions[2] = intVal; - } - - std::string format; - if (dictionary.hasKey("Format") && dictionary.getValue("Format", format)) { - if(format == "RED") { - hints._format = ghoul::opengl::Texture::Format::Red; - } else if(format == "RG") { - hints._format = ghoul::opengl::Texture::Format::RG; - } else if(format == "RGB") { - hints._format = ghoul::opengl::Texture::Format::RGB; - } else if(format == "RGBA") { - hints._format = ghoul::opengl::Texture::Format::RGBA; - } - } - - format = ""; - if (dictionary.hasKey("InternalFormat") && dictionary.getValue("InternalFormat", format)) { - if(format == "R8") { - hints._internalFormat = GL_R8; - } else if(format == "RG8") { - hints._internalFormat = GL_RG8; - } else if(format == "RGB8") { - hints._internalFormat = GL_RGB8; - } else if(format == "RGBA8") { - hints._internalFormat = GL_RGB8; - } else if(format == "R32F") { - hints._internalFormat = GL_R32F; - } else if(format == "RG32F") { - hints._internalFormat = GL_RG32F; - } else if(format == "RGB32F") { - hints._internalFormat = GL_RGB32F; - } else if(format == "RGBA32F") { - hints._internalFormat = GL_RGB32F; - } - } - return hints; -} - -ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string& filepath) { - - std::string f = absPath(filepath); - - if ( ! FileSys.fileExists(f)) { - return nullptr; - } - ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear; - ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge; - - - // check if not a txt based texture - if ( ! hasExtension(filepath, "txt")) { - ghoul::opengl::Texture* t = ghoul::io::TextureReader::ref().loadTexture(f).get(); - t->setWrapping(wrappingmode); - return t; - } - - // it is a txt based texture - std::ifstream in; - in.open(filepath.c_str()); - if (!in.is_open()) { - LERROR("Could not open file " << f); - return nullptr; - } - - int width = 512; - float lower = 0.0f; - float upper = 1.0f; - - struct mappingKey { - float position{0.0f}; - glm::vec4 color{0.0f,0.0f,0.0f,0.0f}; - - mappingKey(float p, const glm::vec4& c): position(p), color(c){}; - mappingKey(float p): position(p), color(glm::vec4(0.0f)){}; - bool operator<(const mappingKey& rhs) {return position < rhs.position;}; - }; - - std::vector mappingKeys; - - auto widthValidator = [](size_t in) { if(in > 0) return in; return static_cast(1); }; - auto upperLowerValidator = [](float in) { return glm::clamp(in, 0.0f, 1.0f); }; - auto intensityValidator = [](float in) { return glm::clamp(in, 0.0f, 1.0f); }; - - std::string line; - while (std::getline(in, line)) { - - glm::vec4 rgba = glm::vec4(0.0f); - // tokenize the line - std::istringstream iss(line); - std::vector tokens{std::istream_iterator{iss},std::istream_iterator{}}; - - size_t tokenSize =tokens.size(); - if (tokenSize > 0) { - std::string key = tokens.at(0); - if(key == "width" && tokenSize == 2) { - width = static_cast(stringToNumber(tokens.at(1), widthValidator)); - } else if(key == "lower" && tokenSize == 2) { - lower = stringToNumber(tokens.at(1), upperLowerValidator); - } else if(key == "upper" && tokenSize == 2) { - upper = stringToNumber(tokens.at(1),upperLowerValidator); - } else if(key == "mappingkey" && tokenSize == 6) { - float intensity = stringToNumber(tokens.at(1), intensityValidator); - for(int i = 0; i < 4; ++i) - rgba[i] = stringToNumber(tokens.at(i+2)); - - mappingKeys.push_back({intensity, rgba}); - } - } - } - in.close(); - - - if (mappingKeys.size() < 1) { - return nullptr; - } - - // for(auto key: mappingKeys) { - // glm::vec4 rgba = key.color; - // LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")"); - // } - // LDEBUG("insert...."); - - if (mappingKeys.front().position > lower){ - mappingKeys.insert(mappingKeys.begin(), {lower,mappingKeys.front().color}); - } - - if (mappingKeys.back().position < upper){ - mappingKeys.push_back({upper,mappingKeys.back().color}); - } - - - // for(auto key: mappingKeys) { - // glm::vec4 rgba = key.color; - // LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")"); - // } - - // allocate new float array with zeros - float* transferFunction = new float[width*4](); - for (int i = 0; i < 4*width; ++i) { - transferFunction[i] = 0.0f; - } - - size_t lowerIndex = static_cast(floorf(lower*static_cast(width-1))); - size_t upperIndex = static_cast(floorf(upper*static_cast(width-1))); - -// LDEBUG("width: " << width); -// LDEBUG("lower: " << lower); -// LDEBUG("upper: " << upper); -// LDEBUG("lowerIndex: " << lowerIndex); -// LDEBUG("upperIndex: " << upperIndex); - - - auto prevKey = mappingKeys.begin(); - auto currentKey = prevKey + 1; - auto lastKey = mappingKeys.end() -1; - - for (size_t i=lowerIndex; i<=upperIndex; i++) { - - float fpos = static_cast(i)/static_cast(width-1); - - if (fpos > (*currentKey).position) { - prevKey = currentKey; - currentKey++; - if (currentKey == mappingKeys.end()) { - currentKey = lastKey; - } - } - - float dist = fpos-(*prevKey).position; - float weight = dist/((*currentKey).position-(*prevKey).position); - - //LDEBUG("fpos: " << fpos); - //LDEBUG("(*prevKey).position: " << (*prevKey).position); - //LDEBUG("(*currentKey).position: " << (*currentKey).position); - //LDEBUG("weight: " << weight); - - for (size_t channel=0; channel<4; ++channel) { - size_t position = 4*i + channel; - // Interpolate linearly between prev and next mapping key - - //LDEBUG("i: " << i); - //LDEBUG("position: " << position); - //LDEBUG("(*prevKey).first " << (*prevKey).first); - //LDEBUG("(*currentKey).first " << (*currentKey).first); - //LDEBUG("dist: " << dist); - //LDEBUG("weight: " << weight); - float value = - ((*prevKey).color[channel]*(1.f-weight) + (*currentKey).color[channel]*weight)/255.f; - transferFunction[position] = value; - - //LDEBUG("["<< position <<"] " << value); - - } - // LDEBUG(std::fixed << std::setw(10) << std::left << std::setprecision(8) << weight << ", (" << - // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+0] << ", " << - // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+1] << ", " << - // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+2] << ", " << - // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+3] << ")"); - } - - // for (int i = 0; i <= width; ++i) { - - // LDEBUG(std::fixed << "(" << - // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+0] << ", " << - // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+1] << ", " << - // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+2] << ", " << - // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+3] << ")"); - // } - - return new ghoul::opengl::Texture(transferFunction, - glm::size3_t(width,1,1),ghoul::opengl::Texture::Format::RGBA, - GL_RGBA, GL_FLOAT,filtermode, wrappingmode); -} - -} // namespace openspace diff --git a/modules/volume/rendering/renderablevolumegl.cpp b/modules/volume/rendering/renderablevolumegl.cpp deleted file mode 100644 index 8c85e21353..0000000000 --- a/modules/volume/rendering/renderablevolumegl.cpp +++ /dev/null @@ -1,323 +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 -#include - -#include -#include -#include -#include -#include -#include - -#include - -namespace { - const std::string _loggerCat = "RenderableVolumeGL"; - const std::string KeyVolume = "Volume"; - const std::string KeyHints = "Hints"; - const std::string KeyTransferFunction = "TransferFunction"; - const std::string KeySampler = "Sampler"; - const std::string KeyBoxScaling = "BoxScaling"; - const std::string KeyVolumeName = "VolumeName"; - const std::string KeyTransferFunctionName = "TransferFunctionName"; -} - -namespace openspace { - -RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary) - : RenderableVolume(dictionary) - , _transferFunctionName("") - , _volumeName("") - , _volume(nullptr) - , _transferFunction(nullptr) - , _boxArray(0) - , _vertexPositionBuffer(0) - , _boxProgram(nullptr) - , _boxScaling(1.0, 1.0, 1.0) - , _w(0.f) - , _updateTransferfunction(false) - , _id(-1) -{ - std::string name; - bool success = dictionary.getValue(SceneGraphNode::KeyName, name); - assert(success); - - _filename = ""; - success = dictionary.getValue(KeyVolume, _filename); - if (!success) { - LERROR("Node '" << name << "' did not contain a valid '" << KeyVolume << "'"); - return; - } - _filename = absPath(_filename); - if (_filename == "") { - return; - } - - LDEBUG("Volume Filename: " << _filename); - - dictionary.getValue(KeyHints, _hintsDictionary); - - _transferFunction = nullptr; - _transferFunctionFile = nullptr; - _transferFunctionPath = ""; - success = dictionary.getValue(KeyTransferFunction, _transferFunctionPath); - if (!success) { - LERROR("Node '" << name << "' did not contain a valid '" << - KeyTransferFunction << "'"); - return; - } - _transferFunctionPath = absPath(_transferFunctionPath); - _transferFunctionFile = new ghoul::filesystem::File(_transferFunctionPath, true); - - _samplerFilename = ""; - success = dictionary.getValue(KeySampler, _samplerFilename); - if (!success) { - LERROR("Node '" << name << "' did not contain a valid '" << KeySampler << "'"); - return; - } - _samplerFilename = absPath(_samplerFilename); - - KameleonWrapper kw(_filename); - auto t = kw.getGridUnits(); - if (dictionary.hasKey(KeyBoxScaling)) { - glm::vec4 scalingVec4(_boxScaling, _w); - success = dictionary.getValue(KeyBoxScaling, scalingVec4); - if (success) { - _boxScaling = scalingVec4.xyz(); - _w = scalingVec4.w; - } - else { - success = dictionary.getValue(KeyBoxScaling, _boxScaling); - if (!success) { - LERROR("Node '" << name << "' did not contain a valid '" << - KeyBoxScaling << "'"); - return; - } - } - } - else { - // Automatic scale detection from model - _boxScaling = kw.getModelScale(); - if (std::get<0>(t) == "R" && std::get<1>(t) == "R" && std::get<2>(t) == "R") { - // Earth radius - _boxScaling.x *= 6.371f; - _boxScaling.y *= 6.371f; - _boxScaling.z *= 6.371f; - _w = 6; - } - else if (std::get<0>(t) == "m" && std::get<1>(t) == "radian" && std::get<2>(t) == "radian") { - // For spherical coordinate systems the radius is in meter - _w = -log10(1.0f/kw.getGridMax().x); - } - else { - LWARNING("Unsupported units for automatic scale detection"); - } - } - - _pscOffset = kw.getModelBarycenterOffset(); - if (std::get<0>(t) == "R" && std::get<1>(t) == "R" && std::get<2>(t) == "R") { - // Earth radius - _pscOffset[0] *= 6.371f; - _pscOffset[1] *= 6.371f; - _pscOffset[2] *= 6.371f; - _pscOffset[3] = 6; - } - else { - // Current spherical models no need for offset - } - - dictionary.getValue(KeyVolumeName, _volumeName); - dictionary.getValue(KeyTransferFunctionName, _transferFunctionName); - - setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling)*pow(10,_w))); -} - -RenderableVolumeGL::~RenderableVolumeGL() { -} - -bool RenderableVolumeGL::isReady() const { - bool ready = true; - ready &= (_boxProgram != nullptr); - ready &= (_volume != nullptr); - ready &= (_transferFunction != nullptr); - return ready; -} - -bool RenderableVolumeGL::initialize() { - // @TODO fix volume and transferfunction names --jonasstrandstedt - if(_filename != "") { - _volume = loadVolume(_filename, _hintsDictionary); - _volume->uploadTexture(); - OsEng.renderEngine().aBuffer()->addVolume(_volumeName, _volume); - } - - if(_transferFunctionPath != "") { - _transferFunction = loadTransferFunction(_transferFunctionPath); - _transferFunction->uploadTexture(); - OsEng.renderEngine().aBuffer()->addTransferFunction(_transferFunctionName, _transferFunction); - - auto textureCallback = [this](const ghoul::filesystem::File& file) { - _updateTransferfunction = true; - }; - _transferFunctionFile->setCallback(textureCallback); - } - - // add the sampler and get the ID - _id = OsEng.renderEngine().aBuffer()->addSamplerfile(_samplerFilename); - - OsEng.configurationManager().getValue("RaycastProgram", _boxProgram); - - // ============================ - // GEOMETRY (box) - // ============================ - const GLfloat size = 0.5f; - const GLfloat vertex_data[] = { - // x, y, z, s, - -size, -size, size, _w, - size, size, size, _w, - -size, size, size, _w, - -size, -size, size, _w, - size, -size, size, _w, - size, size, size, _w, - - -size, -size, -size, _w, - size, size, -size, _w, - -size, size, -size, _w, - -size, -size, -size, _w, - size, -size, -size, _w, - size, size, -size, _w, - - size, -size, -size, _w, - size, size, size, _w, - size, -size, size, _w, - size, -size, -size, _w, - size, size, -size, _w, - size, size, size, _w, - - -size, -size, -size, _w, - -size, size, size, _w, - -size, -size, size, _w, - -size, -size, -size, _w, - -size, size, -size, _w, - -size, size, size, _w, - - -size, size, -size, _w, - size, size, size, _w, - -size, size, size, _w, - -size, size, -size, _w, - size, size, -size, _w, - size, size, size, _w, - - -size, -size, -size, _w, - size, -size, size, _w, - -size, -size, size, _w, - -size, -size, -size, _w, - size, -size, -size, _w, - size, -size, size, _w, - }; - - glGenVertexArrays(1, &_boxArray); // generate array - glBindVertexArray(_boxArray); // bind array - glGenBuffers(1, &_vertexPositionBuffer); // generate buffer - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); // bind buffer - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast(0)); - glEnableVertexAttribArray(0); - - return isReady(); -} - -bool RenderableVolumeGL::deinitialize() { - if (_volume) - delete _volume; - if (_transferFunctionFile) - delete _transferFunctionFile; - if (_transferFunction) - delete _transferFunction; - _volume = nullptr; - _transferFunctionFile = nullptr; - _transferFunction = nullptr; - - glDeleteVertexArrays(1, &_boxArray); - glGenBuffers(1, &_vertexPositionBuffer); - - return true; -} - -void RenderableVolumeGL::render(const RenderData& data) { - if(_updateTransferfunction) { - _updateTransferfunction = false; - ghoul::opengl::Texture* transferFunction = loadTransferFunction(_transferFunctionPath); - if(transferFunction) { - const void* data = transferFunction->pixelData(); - glBindBuffer(GL_COPY_READ_BUFFER, *transferFunction); - _transferFunction->bind(); - glTexImage1D( GL_TEXTURE_1D, 0, _transferFunction->internalFormat(), - static_cast(_transferFunction->width()),0, _transferFunction->format(), - _transferFunction->dataType(), data); - delete transferFunction; - LDEBUG("Updated transferfunction!"); - } - } - - glm::mat4 transform = glm::mat4(1.0); - transform = glm::scale(transform, _boxScaling); - - // fetch data - psc currentPosition = data.position; - currentPosition += _pscOffset; // Move box to model barycenter - - _boxProgram->activate(); - _boxProgram->setUniform("volumeType", _id); - _boxProgram->setUniform("modelViewProjection", data.camera.viewProjectionMatrix()); - _boxProgram->setUniform("modelTransform", transform); - setPscUniforms(_boxProgram, &data.camera, currentPosition); - - // make sure GL_CULL_FACE is enabled (it should be) - glEnable(GL_CULL_FACE); - - // Draw backface - glCullFace(GL_FRONT); - glBindVertexArray(_boxArray); - glDrawArrays(GL_TRIANGLES, 0, 6*6); - - // Draw frontface (now the normal cull face is is set) - glCullFace(GL_BACK); - glDrawArrays(GL_TRIANGLES, 0, 6*6); - - _boxProgram->deactivate(); -} - -void RenderableVolumeGL::update(const UpdateData& data) { -} - -} // namespace openspace diff --git a/modules/volume/rendering/volumeclipplane.cpp b/modules/volume/rendering/volumeclipplane.cpp new file mode 100644 index 0000000000..e3ae029752 --- /dev/null +++ b/modules/volume/rendering/volumeclipplane.cpp @@ -0,0 +1,59 @@ + +/***************************************************************************************** + * * + * 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 openspace { + +VolumeClipPlane::VolumeClipPlane(const ghoul::Dictionary& dictionary) + : _normal("normal", "Normal", glm::vec3(1.0, 0.0, 0.0), glm::vec3(-1.0), glm::vec3(1.0)) + , _offsets("offsets", "Offsets", glm::vec2(-2.0, 0.0), glm::vec2(-2.0, 0.0), glm::vec2(2.0, 1.0)) +{ + glm::vec3 normal; + glm::vec2 offsets; + dictionary.getValue("Normal", normal); + dictionary.getValue("Offsets", offsets); + + _normal = normal; + _offsets = offsets; +} + +void VolumeClipPlane::initialize() +{ + addProperty(_normal); + addProperty(_offsets); +} + +glm::vec3 VolumeClipPlane::normal() { + return glm::normalize(_normal.value()); +} + +glm::vec2 VolumeClipPlane::offsets() { + return _offsets; +} + +} // namespace openspace \ No newline at end of file diff --git a/modules/volume/rendering/renderablevolume.h b/modules/volume/rendering/volumeclipplane.h similarity index 68% rename from modules/volume/rendering/renderablevolume.h rename to modules/volume/rendering/volumeclipplane.h index 8912155460..1c8721a099 100644 --- a/modules/volume/rendering/renderablevolume.h +++ b/modules/volume/rendering/volumeclipplane.h @@ -22,42 +22,32 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_VOLUME___RENDERABLEVOLUME___H__ -#define __OPENSPACE_MODULE_VOLUME___RENDERABLEVOLUME___H__ +#ifndef __OPENSPACE_MODULE_VOLUME___VOLUMECLIPPLANE___H__ +#define __OPENSPACE_MODULE_VOLUME___VOLUMECLIPPLANE___H__ -// open space includes -#include - -// ghoul includes -#include +#include +#include // Forward declare to minimize dependencies namespace ghoul { - namespace filesystem { - class File; - } - namespace opengl { - class Texture; - } + class Dictionary; } namespace openspace { -class RenderableVolume: public Renderable { +class VolumeClipPlane : public properties::PropertyOwner { public: - // constructors & destructor - RenderableVolume(const ghoul::Dictionary& dictionary); - ~RenderableVolume(); - -protected: - ghoul::opengl::Texture* loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary); - glm::vec3 getVolumeOffset(const std::string& filepath, const ghoul::Dictionary& hintsDictionary); - ghoul::RawVolumeReader::ReadHints readHints(const ghoul::Dictionary& dictionary); - ghoul::opengl::Texture* loadTransferFunction(const std::string& filepath); - + VolumeClipPlane(const ghoul::Dictionary& dictionary); + virtual ~VolumeClipPlane() = default; + virtual void initialize(); + glm::vec3 normal(); + glm::vec2 offsets(); private: + properties::Vec3Property _normal; + properties::Vec2Property _offsets; + }; -} // namespace openspace +} // namespace openspace -#endif // __OPENSPACE_MODULE_VOLUME___RENDERABLEVOLUME___H__ +#endif // __OPENSPACE_MODULE_VOLUME___VOLUMECLIPPLANE___H__ diff --git a/modules/volume/rendering/volumeclipplanes.cpp b/modules/volume/rendering/volumeclipplanes.cpp new file mode 100644 index 0000000000..3a2f14d285 --- /dev/null +++ b/modules/volume/rendering/volumeclipplanes.cpp @@ -0,0 +1,72 @@ + +/***************************************************************************************** + * * + * 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 openspace { + +VolumeClipPlanes::VolumeClipPlanes(const ghoul::Dictionary& dictionary) + : _nClipPlanes("nClipPlanes", "Number of clip planes", 0, 0, 10) +{ + std::vector keys = dictionary.keys(); + for (const std::string& key : keys) { + ghoul::Dictionary cutPlaneDictionary; + dictionary.getValue(key, cutPlaneDictionary); + auto clipPlane = std::make_shared(cutPlaneDictionary); + clipPlane->setName(key); + _clipPlanes.push_back(clipPlane); + } + _nClipPlanes = keys.size(); +} + +void VolumeClipPlanes::initialize() { + addProperty(_nClipPlanes); + for (const auto& clipPlane : _clipPlanes) { + addPropertySubOwner(clipPlane.get()); + clipPlane->initialize(); + } +} + +void VolumeClipPlanes::deinitialize() {} + +std::vector VolumeClipPlanes::normals() { + std::vector normals; + for (const auto& clipPlane : _clipPlanes) { + normals.push_back(clipPlane->normal()); + } + return normals; +} + +std::vector VolumeClipPlanes::offsets() { + std::vector offsets; + for (const auto& clipPlane : _clipPlanes) { + offsets.push_back(clipPlane->offsets()); + } + return offsets; +} + +} // namespace openspace diff --git a/modules/volume/rendering/volumeclipplanes.h b/modules/volume/rendering/volumeclipplanes.h new file mode 100644 index 0000000000..e398cac429 --- /dev/null +++ b/modules/volume/rendering/volumeclipplanes.h @@ -0,0 +1,57 @@ +/***************************************************************************************** + * * + * 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_VOLUME___VOLUMECLIPPLANES___H__ +#define __OPENSPACE_MODULE_VOLUME___VOLUMECLIPPLANES___H__ + +#include +#include + +#include + +#include +#include + +namespace ghoul { + class Dictionary; +} + +namespace openspace { + +class VolumeClipPlanes : public properties::PropertyOwner { +public: + VolumeClipPlanes(const ghoul::Dictionary& dictionary); + virtual ~VolumeClipPlanes() = default; + void initialize(); + void deinitialize(); + std::vector normals(); + std::vector offsets(); +private: + properties::IntProperty _nClipPlanes; + std::vector> _clipPlanes; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_VOLUME___VOLUMECLIPPLANES___H__ diff --git a/modules/volume/textureslicevolumereader.inl b/modules/volume/textureslicevolumereader.inl index 6a3513383e..0366096d1e 100644 --- a/modules/volume/textureslicevolumereader.inl +++ b/modules/volume/textureslicevolumereader.inl @@ -29,7 +29,7 @@ namespace openspace { template VoxelType TextureSliceVolumeReader::get(const glm::ivec3& coordinates) const { ghoul::opengl::Texture& slice = getSlice(coordinates.z); - return slice.texel(glm::ivec2(coordinates)); + return slice.texel(glm::uvec2(coordinates.x, coordinates.y)); } template @@ -52,7 +52,8 @@ void TextureSliceVolumeReader::initialize() { std::shared_ptr firstSlice = ghoul::io::TextureReader::ref().loadTexture(_paths[0]); - _sliceDimensions = firstSlice->dimensions(); + glm::uvec3 dimensions = firstSlice->dimensions(); + _sliceDimensions = glm::uvec2(dimensions.x, dimensions.y); _initialized = true; _cache.set(0, firstSlice); } @@ -72,7 +73,8 @@ ghoul::opengl::Texture& TextureSliceVolumeReader::getSlice(int sliceI std::shared_ptr texture = ghoul::io::TextureReader::ref().loadTexture(_paths[sliceIndex]); - glm::ivec2 dims = texture->dimensions(); + glm::uvec3 dimensions = texture->dimensions(); + glm::ivec2 dims = glm::uvec2(dimensions.x, dimensions.y); ghoul_assert(dims == _sliceDimensions, "Slice dimensions do not agree."); _cache.set(sliceIndex, std::move(texture)); } diff --git a/modules/volume/volumegridtype.h b/modules/volume/volumegridtype.h new file mode 100644 index 0000000000..33e39261fc --- /dev/null +++ b/modules/volume/volumegridtype.h @@ -0,0 +1,33 @@ +/***************************************************************************************** + * * + * 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_VOLUME___VOLUMEGRIDTYPE_H__ +#define __OPENSPACE_MODULE_VOLUME___VOLUMEGRIDTYPE_H__ + +enum class VolumeGridType : int { + Cartesian = 0, + Spherical = 1 +}; + +#endif // __OPENSPACE_MODULE_VOLUME___VOLUMEGRIDTYPE_H__ diff --git a/modules/volume/volumemodule.cpp b/modules/volume/volumemodule.cpp index 5513daff5a..1a2a7b9115 100644 --- a/modules/volume/volumemodule.cpp +++ b/modules/volume/volumemodule.cpp @@ -29,8 +29,6 @@ #include -#include - namespace openspace { VolumeModule::VolumeModule() @@ -38,8 +36,7 @@ VolumeModule::VolumeModule() {} void VolumeModule::internalInitialize() { - auto fRenderable = FactoryManager::ref().factory(); - ghoul_assert(fRenderable, "No renderable factory existed"); + } } // namespace openspace diff --git a/modules/volume/volumeutils.cpp b/modules/volume/volumeutils.cpp index 934a8388f7..0e4b4c60ac 100644 --- a/modules/volume/volumeutils.cpp +++ b/modules/volume/volumeutils.cpp @@ -27,7 +27,7 @@ namespace openspace { namespace volumeutils { -size_t coordsToIndex(const glm::vec3& coords, const glm::ivec3& dims) { +size_t coordsToIndex(const glm::uvec3& coords, const glm::uvec3& dims) { size_t w = dims.x; size_t h = dims.y; // size_t d = dims.z; @@ -39,7 +39,7 @@ size_t coordsToIndex(const glm::vec3& coords, const glm::ivec3& dims) { return coords.z * (h * w) + coords.y * w + coords.x; } -glm::vec3 indexToCoords(size_t index, const glm::ivec3& dims) { +glm::uvec3 indexToCoords(size_t index, const glm::uvec3& dims) { size_t w = dims.x; size_t h = dims.y; size_t d = dims.z; @@ -48,7 +48,7 @@ glm::vec3 indexToCoords(size_t index, const glm::ivec3& dims) { size_t y = (index / w) % h; size_t z = index / w / h; - return glm::ivec3(x, y, z); + return glm::uvec3(x, y, z); } } // namespace volumeutils diff --git a/modules/volume/volumeutils.h b/modules/volume/volumeutils.h index cf7aeaef13..a8cab23b72 100644 --- a/modules/volume/volumeutils.h +++ b/modules/volume/volumeutils.h @@ -30,8 +30,8 @@ namespace openspace { namespace volumeutils { -size_t coordsToIndex(const glm::vec3& coords, const glm::ivec3& dimensions); -glm::vec3 indexToCoords(size_t index, const glm::ivec3& dimensions); +size_t coordsToIndex(const glm::uvec3& coords, const glm::uvec3& dimensions); +glm::uvec3 indexToCoords(size_t index, const glm::uvec3& dimensions); } // namespace volumeutils diff --git a/openspace.cfg b/openspace.cfg index a1de1e185d..6848a95040 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -23,8 +23,8 @@ return { -- Sets the scene that is to be loaded by OpenSpace. A scene file is a description -- of all entities that will be visible during an instance of OpenSpace - Scene = "${SCENE}/default.scene", - + Scene = "${SCENE}/volumes.scene", + Task = "${TASKS}/default.task", -- Scene = "${SCENE}/globebrowsing.scene", -- Scene = "${SCENE}/rosetta.scene", -- Scene = "${SCENE}/dawn.scene", @@ -37,6 +37,7 @@ return { SHADERS = "${BASE_PATH}/shaders", OPENSPACE_DATA = "${BASE_PATH}/data", SCENE = "${OPENSPACE_DATA}/scene", + TASKS = "${OPENSPACE_DATA}/tasks", SPICE = "${OPENSPACE_DATA}/spice", MODULES = "${BASE_PATH}/modules", TESTDIR = "${BASE_PATH}/tests", diff --git a/shaders/PowerScaling/powerScalingMath.hglsl b/shaders/PowerScaling/powerScalingMath.hglsl index 58ffd0d978..b275aaf989 100644 --- a/shaders/PowerScaling/powerScalingMath.hglsl +++ b/shaders/PowerScaling/powerScalingMath.hglsl @@ -80,47 +80,6 @@ vec4 z_normalization(vec4 v_in) { return v_out; } -/** - * Compute the length of a vector. - * Supporting huge vectors, where the square of any of the components is too large to represent as a float. - */ -float safeLength(vec4 v) { - float m = max(max(max(abs(v.x), abs(v.y)), abs(v.z)), abs(v.w)); - if (m > 0.0) { - return length(v / m) * m; - } else { - return 0; - } -} - -float safeLength(vec3 v) { - float m = max(max(abs(v.x), abs(v.y)), abs(v.z)); - if (m > 0.0) { - return length(v / m) * m; - } else { - return 0; - } -} - -float safeLength(vec2 v) { - float m = max(abs(v.x), abs(v.y)); - if (m > 0.0) { - return length(v / m) * m; - } else { - return 0; - } -} - -/** - * Normalize a vector - * Supporting huge vectors, where the square of any of the components is too large to represent as a float. - */ -vec3 safeNormalize(vec3 v) { - float m = max(max(abs(v.x), abs(v.y)), abs(v.z)); - return normalize(v / m); -} - - /** * Convert a psc vector to a float */ @@ -135,27 +94,4 @@ float pscToLinear(vec2 position) { return pow(k, position.y) * position.x; } -/** - * Convert a positive floating point distance [0, 10^27] - * (size of observable universe) - * to a float in the range [-1, 1], suitable for depth buffer storage. - * Note: This needs to be a monotonic function, so that the value can - * still be used for depth comparison. - */ -float normalizeFloat(float inpt) { - if (inpt > 1.0) { - return inpt / pow(10, 27); - } else { - return inpt - 1.0; - } -} - -float denormalizeFloat(float inpt) { - if (inpt < 0.0) { - return inpt + 1.0; - } else { - return inpt * pow(10, 27); - } -} - #endif diff --git a/shaders/PowerScaling/powerScaling_fs.hglsl b/shaders/PowerScaling/powerScaling_fs.hglsl index 855c98707a..98a648eb56 100644 --- a/shaders/PowerScaling/powerScaling_fs.hglsl +++ b/shaders/PowerScaling/powerScaling_fs.hglsl @@ -25,6 +25,8 @@ #ifndef POWERSCALING_FS_H_HGLSL #define POWERSCALING_FS_H_HGLSL +#include "floatoperations.glsl" + // Observable universe is 10^27m, setting the far value to extremely high, aka 30!! ERMAHGERD! #include "powerScalingMath.hglsl" diff --git a/shaders/abuffer/abufferresources.glsl b/shaders/abuffer/abufferresources.glsl index 4241885318..efa0401c73 100644 --- a/shaders/abuffer/abufferresources.glsl +++ b/shaders/abuffer/abufferresources.glsl @@ -80,7 +80,4 @@ void storeFragments(uint nFrags) { } - - - #endif diff --git a/shaders/abuffer/renderabuffer.frag b/shaders/abuffer/renderabuffer.frag index 0dfd046983..1e94efe35f 100644 --- a/shaders/abuffer/renderabuffer.frag +++ b/shaders/abuffer/renderabuffer.frag @@ -26,6 +26,7 @@ #include <#{fragmentPath}> #include "abufferfragment.glsl" #include "abufferresources.glsl" +#include "floatoperations.glsl" out vec4 _out_color_; diff --git a/shaders/abuffer/resolveabuffer.frag b/shaders/abuffer/resolveabuffer.frag index a722c4f02d..453e656c9b 100644 --- a/shaders/abuffer/resolveabuffer.frag +++ b/shaders/abuffer/resolveabuffer.frag @@ -29,7 +29,7 @@ #include "abufferfragment.glsl" #include "abufferresources.glsl" #include "fragment.glsl" -#include "PowerScaling/powerScalingMath.hglsl" +#include "floatoperations.glsl" #include "blending.glsl" #include "rand.glsl" diff --git a/shaders/floatoperations.glsl b/shaders/floatoperations.glsl new file mode 100644 index 0000000000..c3d52a5300 --- /dev/null +++ b/shaders/floatoperations.glsl @@ -0,0 +1,93 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 _FLOATOPERATIONS_GLSL_ +#define _FLOATOPERATIONS_GLSL_ + + +/** + * Convert a positive floating point distance [0, 10^27] + * (size of observable universe) + * to a float in the range [-1, 1], suitable for depth buffer storage. + * Note: This needs to be a monotonic function, so that the value can + * still be used for depth comparison. + */ +float normalizeFloat(float inpt) { + if (inpt > 1.0) { + return inpt / pow(10, 27); + } else { + return inpt - 1.0; + } +} + +float denormalizeFloat(float inpt) { + if (inpt < 0.0) { + return inpt + 1.0; + } else { + return inpt * pow(10, 27); + } +} + +/** + * Compute the length of a vector. + * Supporting huge vectors, where the square of any of the components is too large to represent as a float. + */ +float safeLength(vec4 v) { + float m = max(max(max(abs(v.x), abs(v.y)), abs(v.z)), abs(v.w)); + if (m > 0.0) { + return length(v / m) * m; + } else { + return 0; + } +} + +float safeLength(vec3 v) { + float m = max(max(abs(v.x), abs(v.y)), abs(v.z)); + if (m > 0.0) { + return length(v / m) * m; + } else { + return 0; + } +} + +float safeLength(vec2 v) { + float m = max(abs(v.x), abs(v.y)); + if (m > 0.0) { + return length(v / m) * m; + } else { + return 0; + } +} + +/** + * Normalize a vector + * Supporting huge vectors, where the square of any of the components is too large to represent as a float. + */ +vec3 safeNormalize(vec3 v) { + float m = max(max(abs(v.x), abs(v.y)), abs(v.z)); + return normalize(v / m); +} + + +#endif diff --git a/shaders/framebuffer/exitframebuffer.frag b/shaders/framebuffer/exitframebuffer.frag index 19b44c39b6..19956df740 100644 --- a/shaders/framebuffer/exitframebuffer.frag +++ b/shaders/framebuffer/exitframebuffer.frag @@ -25,7 +25,7 @@ #version __CONTEXT__ -#include "PowerScaling/powerScalingMath.hglsl" +#include "floatoperations.glsl" #include <#{fragmentPath}> out vec4 _out_color_; diff --git a/shaders/framebuffer/inside.glsl b/shaders/framebuffer/inside.glsl new file mode 100644 index 0000000000..9c5587c325 --- /dev/null +++ b/shaders/framebuffer/inside.glsl @@ -0,0 +1,29 @@ +/***************************************************************************************** + * * + * 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. * + ****************************************************************************************/ + + +void getEntry(inout vec3 entryPos, inout float entryDepth) { + entryPos = cameraPosInRaycaster; + entryDepth = 0; +} diff --git a/shaders/framebuffer/outside.glsl b/shaders/framebuffer/outside.glsl new file mode 100644 index 0000000000..d1ebf5d7e9 --- /dev/null +++ b/shaders/framebuffer/outside.glsl @@ -0,0 +1,32 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 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 <#{fragmentPath}> + +void getEntry(inout vec3 entryPos, inout float entryDepth) { + // fetch entry point from rendered fragment + Fragment f = getFragment(); + entryPos = f.color.xyz; + entryDepth = f.depth; +} diff --git a/shaders/framebuffer/raycastframebuffer.frag b/shaders/framebuffer/raycastframebuffer.frag index 375bed06b7..eecd97baa0 100644 --- a/shaders/framebuffer/raycastframebuffer.frag +++ b/shaders/framebuffer/raycastframebuffer.frag @@ -34,9 +34,7 @@ uniform vec2 windowSize; #include "blending.glsl" #include "rand.glsl" -#include "PowerScaling/powerScalingMath.hglsl" -#include <#{fragmentPath}> - +#include "floatoperations.glsl" #for id, helperPath in helperPaths #include <#{helperPath}> @@ -46,19 +44,17 @@ uniform vec2 windowSize; out vec4 finalColor; - #define ALPHA_LIMIT 0.99 #define RAYCAST_MAX_STEPS 1000 #define MAX_AA_SAMPLES 8 uniform int nAaSamples; +#include <#{getEntryPath}> void main() { - vec2 texCoord = vec2(gl_FragCoord.xy / windowSize); - vec4 exitColorTexture = texture(exitColorTexture, texCoord); if (exitColorTexture.a < 1.0) { discard; @@ -68,22 +64,11 @@ void main() { vec3 exitPos = exitColorTexture.rgb; float exitDepth = denormalizeFloat(texture(exitDepthTexture, texCoord).x); - - float jitterFactor = 0.5 + 0.5 * rand(gl_FragCoord.xy); // should be between 0.5 and 1.0 vec3 entryPos; float entryDepth; - - if (insideRaycaster) { - entryPos = cameraPosInRaycaster; - entryDepth = 0; - } else { - // fetch entry point from rendered fragment - Fragment f = getFragment(); - entryPos = f.color.xyz; - entryDepth = f.depth; - } + getEntry(entryPos, entryDepth); vec3 position = entryPos; vec3 diff = exitPos - entryPos; diff --git a/shaders/framebuffer/renderframebuffer.frag b/shaders/framebuffer/renderframebuffer.frag index 2faeda1b26..0f671765ea 100644 --- a/shaders/framebuffer/renderframebuffer.frag +++ b/shaders/framebuffer/renderframebuffer.frag @@ -22,7 +22,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include "PowerScaling/powerScalingMath.hglsl" +#include "floatoperations.glsl" #include <#{fragmentPath}> out vec4 _out_color_; diff --git a/shaders/framebuffer/resolveframebuffer.frag b/shaders/framebuffer/resolveframebuffer.frag index df8b872298..7f32534df1 100644 --- a/shaders/framebuffer/resolveframebuffer.frag +++ b/shaders/framebuffer/resolveframebuffer.frag @@ -24,8 +24,6 @@ #version __CONTEXT__ -#include "PowerScaling/powerScalingMath.hglsl" - layout (location = 0) out vec4 finalColor; uniform float blackoutFactor; uniform int nAaSamples; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2086e77d36..d4bae91e69 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -149,6 +149,8 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/util/syncbuffer.cpp ${OPENSPACE_BASE_DIR}/src/util/syncdata.cpp ${OPENSPACE_BASE_DIR}/src/util/histogram.cpp + ${OPENSPACE_BASE_DIR}/src/util/task.cpp + ${OPENSPACE_BASE_DIR}/src/util/taskloader.cpp ${OPENSPACE_BASE_DIR}/src/util/time.cpp ${OPENSPACE_BASE_DIR}/src/util/timemanager.cpp ${OPENSPACE_BASE_DIR}/src/util/time_lua.inl @@ -288,6 +290,8 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/util/spicemanager.h ${OPENSPACE_BASE_DIR}/include/openspace/util/syncbuffer.h ${OPENSPACE_BASE_DIR}/include/openspace/util/syncdata.h + ${OPENSPACE_BASE_DIR}/include/openspace/util/task.h + ${OPENSPACE_BASE_DIR}/include/openspace/util/taskloader.h ${OPENSPACE_BASE_DIR}/include/openspace/util/time.h ${OPENSPACE_BASE_DIR}/include/openspace/util/timemanager.h ${OPENSPACE_BASE_DIR}/include/openspace/util/timerange.h diff --git a/src/engine/configurationmanager.cpp b/src/engine/configurationmanager.cpp index 0032aaebbd..dc532650d7 100644 --- a/src/engine/configurationmanager.cpp +++ b/src/engine/configurationmanager.cpp @@ -24,6 +24,8 @@ #include +#include + #include #include #include @@ -57,6 +59,7 @@ const string ConfigurationManager::KeyKeyboardShortcuts = "KeyboardShortcuts"; const string ConfigurationManager::KeyDocumentation = "Documentation"; const string ConfigurationManager::KeyFactoryDocumentation = "FactoryDocumentation"; const string ConfigurationManager::KeyConfigScene = "Scene"; +const string ConfigurationManager::KeyConfigTask = "Task"; const string ConfigurationManager::KeyLogging = "Logging"; const string ConfigurationManager::PartLogLevel = "LogLevel"; diff --git a/src/engine/configurationmanager_doc.inl b/src/engine/configurationmanager_doc.inl index 4136171bda..c00eb44b83 100644 --- a/src/engine/configurationmanager_doc.inl +++ b/src/engine/configurationmanager_doc.inl @@ -52,6 +52,14 @@ documentation::Documentation ConfigurationManager::Documentation() { "the Scene documentation.", Optional::No }, + { + ConfigurationManager::KeyConfigTask, + new StringAnnotationVerifier( + "A valid task file as described in the Task documentation"), + "The root task to be performed when launching the task runner " + "applicaition.", + Optional::Yes + }, { ConfigurationManager::KeyPaths, new StringListVerifier, diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 6ec3200fe1..71318c29b3 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,10 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName, std::make_unique>(), "Scale" ); + FactoryManager::ref().addFactory( + std::make_unique>(), + "Task" + ); SpiceManager::initialize(); Time::initialize(); diff --git a/src/rendering/abufferrenderer.cpp b/src/rendering/abufferrenderer.cpp index 39d7e66ce7..a29a4fd69f 100644 --- a/src/rendering/abufferrenderer.cpp +++ b/src/rendering/abufferrenderer.cpp @@ -268,9 +268,6 @@ void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurement RenderData data{ *_camera, psc(), doPerformanceMeasurements, renderBinMask }; RendererTasks tasks; _scene->render(data, tasks); - - _rendererTasks = std::make_unique(tasks); - _renderData = std::make_unique(data); _blackoutFactor = blackoutFactor; glBindFramebuffer(GL_FRAMEBUFFER, defaultFbo); @@ -314,10 +311,21 @@ void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurement // END TEMPORARY GAMMA CORRECTION. - preRaycast(*_resolveProgram); + _resolveProgram->setUniform("mainColorTexture", _mainColorTextureUnit->unitNumber()); + _resolveProgram->setUniform("mainDepthTexture", _mainDepthTextureUnit->unitNumber()); + _resolveProgram->setUniform("blackoutFactor", _blackoutFactor); + _resolveProgram->setUniform("nAaSamples", _nAaSamples); + + for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { + preRaycast(raycasterTask); + } + glBindVertexArray(_screenQuad); glDrawArrays(GL_TRIANGLES, 0, 6); - postRaycast(*_resolveProgram); + + for (const RaycasterTask& raycasterTask : tasks.raycasterTasks) { + postRaycast(raycasterTask); + } _resolveProgram->deactivate(); @@ -326,32 +334,27 @@ void ABufferRenderer::render(float blackoutFactor, bool doPerformanceMeasurement } -void ABufferRenderer::preRaycast(ghoul::opengl::ProgramObject& program) { +void ABufferRenderer::preRaycast(const RaycasterTask& raycasterTask) { + VolumeRaycaster& raycaster = *raycasterTask.raycaster; + const RaycastData& raycastData = _raycastData[&raycaster]; + const RenderData& renderData = raycasterTask.renderData; - program.setUniform("mainColorTexture", _mainColorTextureUnit->unitNumber()); - program.setUniform("mainDepthTexture", _mainDepthTextureUnit->unitNumber()); - - for (const auto& raycastData : _raycastData) { - raycastData.first->preRaycast(raycastData.second, program); + raycaster.preRaycast(raycastData, *_resolveProgram); - glm::vec3 localCameraPosition; - bool cameraIsInside = raycastData.first->cameraIsInside(*_renderData, localCameraPosition); - int uniformIndex = raycastData.second.id + 1; // uniforms are indexed from 1 (not from 0) - program.setUniform("insideRaycaster" + std::to_string(uniformIndex), cameraIsInside); - if (cameraIsInside) { - program.setUniform("cameraPosInRaycaster" + std::to_string(uniformIndex), localCameraPosition); - } + glm::vec3 localCameraPosition; + bool cameraIsInside = raycaster.cameraIsInside(renderData, localCameraPosition); + int uniformIndex = raycastData.id + 1; // uniforms are indexed from 1 (not from 0) + _resolveProgram->setUniform("insideRaycaster" + std::to_string(uniformIndex), cameraIsInside); + if (cameraIsInside) { + _resolveProgram->setUniform("cameraPosInRaycaster" + std::to_string(uniformIndex), localCameraPosition); } - - // 3b: Set "global" uniforms, and start the resolve pass. - program.setUniform("blackoutFactor", _blackoutFactor); - program.setUniform("nAaSamples", _nAaSamples); } -void ABufferRenderer::postRaycast(ghoul::opengl::ProgramObject& program) { - for (const auto& raycastData : _raycastData) { - raycastData.first->postRaycast(raycastData.second, program); - } +void ABufferRenderer::postRaycast(const RaycasterTask& raycasterTask) { + VolumeRaycaster& raycaster = *raycasterTask.raycaster; + const RaycastData& raycastData = _raycastData[&raycaster]; + + raycaster.postRaycast(raycastData, *_resolveProgram); } void ABufferRenderer::setScene(Scene* scene) { diff --git a/src/rendering/framebufferrenderer.cpp b/src/rendering/framebufferrenderer.cpp index c6b283556b..d5769de82f 100644 --- a/src/rendering/framebufferrenderer.cpp +++ b/src/rendering/framebufferrenderer.cpp @@ -46,6 +46,8 @@ namespace { const std::string _loggerCat = "FramebufferRenderer"; const std::string ExitFragmentShaderPath = "${SHADERS}/framebuffer/exitframebuffer.frag"; const std::string RaycastFragmentShaderPath = "${SHADERS}/framebuffer/raycastframebuffer.frag"; + const std::string GetEntryInsidePath = "${SHADERS}/framebuffer/inside.glsl"; + const std::string GetEntryOutsidePath = "${SHADERS}/framebuffer/outside.glsl"; const std::string RenderFragmentShaderPath = "${SHADERS}/framebuffer/renderframebuffer.frag"; } @@ -286,20 +288,28 @@ void FramebufferRenderer::updateRaycastData() { try { _exitPrograms[raycaster] = ghoul::opengl::ProgramObject::Build("Volume " + std::to_string(data.id) + " exit", vsPath, ExitFragmentShaderPath, dict); - } - catch (ghoul::RuntimeError e) { - LERROR(e.message); - } - try { - _raycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build("Volume " + std::to_string(data.id) + " raycast", vsPath, RaycastFragmentShaderPath, dict); } catch (ghoul::RuntimeError e) { LERROR(e.message); } try { + ghoul::Dictionary outsideDict = dict; + outsideDict.setValue("getEntryPath", GetEntryOutsidePath); + _raycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( + "Volume " + std::to_string(data.id) + " raycast", + vsPath, + RaycastFragmentShaderPath, + outsideDict); + } catch (ghoul::RuntimeError e) { + LERROR(e.message); + } + try { + ghoul::Dictionary insideDict = dict; + insideDict.setValue("getEntryPath", GetEntryInsidePath); _insideRaycastPrograms[raycaster] = ghoul::opengl::ProgramObject::Build( "Volume " + std::to_string(data.id) + " inside raycast", "${SHADERS}/framebuffer/resolveframebuffer.vert", - RaycastFragmentShaderPath, dict); + RaycastFragmentShaderPath, + insideDict); } catch (ghoul::RuntimeError e) { LERROR(e.message); @@ -359,26 +369,22 @@ void FramebufferRenderer::render(float blackoutFactor, bool doPerformanceMeasure } glBindFramebuffer(GL_FRAMEBUFFER, _mainFramebuffer); - - - ghoul::opengl::ProgramObject* insideRaycastProgram = _raycastPrograms[raycaster].get(); - glm::vec3 cameraPosition; bool cameraIsInside = raycaster->cameraIsInside(raycasterTask.renderData, cameraPosition); ghoul::opengl::ProgramObject* raycastProgram = nullptr; if (cameraIsInside) { - raycastProgram = _insideRaycastPrograms[raycaster].get(); + if (raycastProgram = _insideRaycastPrograms[raycaster].get()) { + raycastProgram->activate(); + raycastProgram->setUniform("cameraPosInRaycaster", cameraPosition); + } } else { - raycastProgram = _raycastPrograms[raycaster].get(); + if (raycastProgram = _raycastPrograms[raycaster].get()) { + raycastProgram->activate(); + } } if (raycastProgram) { - raycastProgram->activate(); - - raycastProgram->setUniform("insideRaycaster", cameraIsInside); - raycastProgram->setUniform("cameraPosInRaycaster", cameraPosition); - raycaster->preRaycast(_raycastData[raycaster], *raycastProgram); ghoul::opengl::TextureUnit exitColorTextureUnit; diff --git a/src/util/progressbar.cpp b/src/util/progressbar.cpp index 9f650e782b..3d9b78d76b 100644 --- a/src/util/progressbar.cpp +++ b/src/util/progressbar.cpp @@ -42,7 +42,7 @@ ProgressBar::~ProgressBar() { } void ProgressBar::print(int current) { - float progress = static_cast(current) / static_cast(_end - 1); + float progress = static_cast(current) / static_cast(_end); int iprogress = static_cast(progress*100.0f); if (iprogress != _previous) { int pos = static_cast(static_cast(_width)* progress); diff --git a/src/util/task.cpp b/src/util/task.cpp new file mode 100644 index 0000000000..044e8c44fd --- /dev/null +++ b/src/util/task.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 +#include +#include +#include + +namespace { + const std::string _loggerCat = "Task"; +} + +namespace openspace { + +documentation::Documentation Task::documentation() { + using namespace openspace::documentation; + return{ + "Renderable", + "renderable", + { + { + "Type", + new StringAnnotationVerifier("A valid Task created by a factory"), + "This key specifies the type of Task that gets created. It has to be one" + "of the valid Tasks that are available for creation (see the " + "FactoryDocumentation for a list of possible Tasks), which depends on " + "the configration of the application", + Optional::No + } + } + }; +} + +std::unique_ptr Task::createFromDictionary(const ghoul::Dictionary& dictionary) { + openspace::documentation::testSpecificationAndThrow(documentation::Documentation(), dictionary, "Task"); + std::string taskType = dictionary.value("Type"); + auto factory = FactoryManager::ref().factory(); + std::unique_ptr task = factory->create(taskType, dictionary); + + if (task == nullptr) { + LERROR("Failed to create a Task object of type '" << taskType << "'"); + return nullptr; + } + + return std::move(task); +} + +} \ No newline at end of file diff --git a/src/util/taskloader.cpp b/src/util/taskloader.cpp new file mode 100644 index 0000000000..b2867d27eb --- /dev/null +++ b/src/util/taskloader.cpp @@ -0,0 +1,87 @@ +/***************************************************************************************** + * * + * 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 + +namespace { + const char* _loggerCat = "TaskRunner"; +} + +namespace openspace { + +std::vector> TaskLoader::tasksFromDictionary(const ghoul::Dictionary& tasksDictionary) { + std::vector> tasks; + std::vector keys = tasksDictionary.keys(); + for (const std::string key : keys) { + std::string taskName; + ghoul::Dictionary subTask; + if (tasksDictionary.getValue(key, taskName)) { + std::string path = "${TASKS}/" + taskName + ".task"; + std::vector> subTasks = tasksFromFile(path); + std::move(subTasks.begin(), subTasks.end(), std::back_inserter(tasks)); + } else if (tasksDictionary.getValue(key, subTask)) { + std::string taskType = subTask.value("Type"); + std::unique_ptr task = Task::createFromDictionary(subTask); + if (task == nullptr) { + LERROR("Failed to create a Task object of type '" << taskType << "'"); + } + tasks.push_back(std::move(task)); + } + } + return tasks; +} + +std::vector> TaskLoader::tasksFromFile(const std::string& path) { + std::string absTasksFile = absPath(path); + using RawPath = ghoul::filesystem::FileSystem::RawPath; + if (!FileSys.fileExists(absTasksFile, RawPath::Yes)) { + LERROR("Could not load tasks file '" << absTasksFile << "'. " << + "File not found"); + return std::vector>(); + } + + ghoul::Dictionary tasksDictionary; + try { + ghoul::lua::loadDictionaryFromFile( + absTasksFile, + tasksDictionary + ); + } catch (...) { + LERROR("Could not load tasks file '" << absTasksFile << "'. " << + "Lua parse error"); + return std::vector>(); + } + return tasksFromDictionary(tasksDictionary); +} + +} // namespace openspace diff --git a/src/util/transformationmanager.cpp b/src/util/transformationmanager.cpp index 2aef61c482..53a975f09b 100644 --- a/src/util/transformationmanager.cpp +++ b/src/util/transformationmanager.cpp @@ -21,6 +21,7 @@ * 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