From cb7e81cf3dd41e1175d1d31adfb355367dc9f957 Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Mon, 24 Oct 2016 10:26:00 +0200 Subject: [PATCH] Add support for converting and rendering volumetric data in the cdf format. Replace DataConverter by a more general purpose TaskRunner. Conflicts: modules/volume/CMakeLists.txt modules/volume/linearlrucache.h src/engine/openspaceengine.cpp --- .../CMakeLists.txt | 12 +- apps/{DataConverter => TaskRunner}/main.cpp | 96 +++-- data/tasks/default.task | 3 + data/web/kameleondocumentation/main.hbs | 59 +++ data/web/kameleondocumentation/script.js | 23 ++ .../openspace/engine/configurationmanager.h | 2 + include/openspace/util/distanceconstants.h | 34 ++ include/openspace/util/task.h | 23 ++ include/openspace/util/taskloader.h | 17 + modules/galaxy/CMakeLists.txt | 3 + modules/galaxy/galaxymodule.cpp | 7 + .../galaxy/tasks}/milkywayconversiontask.cpp | 2 +- .../galaxy/tasks}/milkywayconversiontask.h | 4 +- .../tasks}/milkywaypointsconversiontask.cpp | 2 +- .../tasks}/milkywaypointsconversiontask.h | 4 +- modules/kameleonvolume/CMakeLists.txt | 49 +++ modules/kameleonvolume/include.cmake | 6 + .../kameleonvolume/kameleonvolumemodule.cpp | 58 +++ .../kameleonvolume/kameleonvolumemodule.h | 18 +- .../kameleonvolume/kameleonvolumereader.cpp | 188 ++++++++++ modules/kameleonvolume/kameleonvolumereader.h | 77 ++++ .../kameleonvolume/kameleonvolumereader.inl | 52 +++ .../rendering/kameleonvolumeraycaster.cpp | 142 ++++++++ .../rendering/kameleonvolumeraycaster.h | 89 +++++ .../rendering/renderablekameleonvolume.cpp | 344 ++++++++++++++++++ .../rendering/renderablekameleonvolume.h | 95 +++++ modules/kameleonvolume/shaders/boundsfs.glsl | 40 ++ modules/kameleonvolume/shaders/boundsvs.glsl | 46 +++ modules/kameleonvolume/shaders/helper.glsl | 19 + modules/kameleonvolume/shaders/raycast.glsl | 62 ++++ .../tasks/kameleondocumentationtask.cpp | 162 +++++++++ .../tasks/kameleondocumentationtask.h | 46 +++ .../tasks/kameleonmetadatatojsontask.cpp | 94 +++++ .../tasks/kameleonmetadatatojsontask.h | 46 +++ .../rendering/multiresvolumeraycaster.cpp | 8 +- modules/volume/CMakeLists.txt | 3 + modules/volume/rawvolume.h | 24 +- modules/volume/rawvolume.inl | 44 ++- modules/volume/rawvolumereader.h | 12 +- modules/volume/rawvolumereader.inl | 12 +- modules/volume/rawvolumewriter.h | 8 +- modules/volume/rawvolumewriter.inl | 21 +- modules/volume/volumegridtype.h | 33 ++ modules/volume/volumeutils.cpp | 6 +- modules/volume/volumeutils.h | 4 +- openspace.cfg | 5 +- src/CMakeLists.txt | 4 + src/engine/configurationmanager.cpp | 1 + src/engine/configurationmanager_doc.inl | 8 + src/engine/openspaceengine.cpp | 5 + src/util/progressbar.cpp | 2 +- src/util/task.cpp | 70 ++++ src/util/taskloader.cpp | 89 +++++ 53 files changed, 2161 insertions(+), 122 deletions(-) rename apps/{DataConverter => TaskRunner}/CMakeLists.txt (85%) rename apps/{DataConverter => TaskRunner}/main.cpp (57%) create mode 100644 data/tasks/default.task create mode 100644 data/web/kameleondocumentation/main.hbs create mode 100644 data/web/kameleondocumentation/script.js create mode 100644 include/openspace/util/distanceconstants.h create mode 100644 include/openspace/util/task.h create mode 100644 include/openspace/util/taskloader.h rename {apps/DataConverter => modules/galaxy/tasks}/milkywayconversiontask.cpp (98%) rename {apps/DataConverter => modules/galaxy/tasks}/milkywayconversiontask.h (97%) rename {apps/DataConverter => modules/galaxy/tasks}/milkywaypointsconversiontask.cpp (98%) rename {apps/DataConverter => modules/galaxy/tasks}/milkywaypointsconversiontask.h (96%) create mode 100644 modules/kameleonvolume/CMakeLists.txt create mode 100644 modules/kameleonvolume/include.cmake create mode 100644 modules/kameleonvolume/kameleonvolumemodule.cpp rename apps/DataConverter/conversiontask.h => modules/kameleonvolume/kameleonvolumemodule.h (83%) create mode 100644 modules/kameleonvolume/kameleonvolumereader.cpp create mode 100644 modules/kameleonvolume/kameleonvolumereader.h create mode 100644 modules/kameleonvolume/kameleonvolumereader.inl create mode 100644 modules/kameleonvolume/rendering/kameleonvolumeraycaster.cpp create mode 100644 modules/kameleonvolume/rendering/kameleonvolumeraycaster.h create mode 100644 modules/kameleonvolume/rendering/renderablekameleonvolume.cpp create mode 100644 modules/kameleonvolume/rendering/renderablekameleonvolume.h create mode 100644 modules/kameleonvolume/shaders/boundsfs.glsl create mode 100644 modules/kameleonvolume/shaders/boundsvs.glsl create mode 100644 modules/kameleonvolume/shaders/helper.glsl create mode 100644 modules/kameleonvolume/shaders/raycast.glsl create mode 100644 modules/kameleonvolume/tasks/kameleondocumentationtask.cpp create mode 100644 modules/kameleonvolume/tasks/kameleondocumentationtask.h create mode 100644 modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp create mode 100644 modules/kameleonvolume/tasks/kameleonmetadatatojsontask.h create mode 100644 modules/volume/volumegridtype.h create mode 100644 src/util/task.cpp create mode 100644 src/util/taskloader.cpp 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 57% rename from apps/DataConverter/main.cpp rename to apps/TaskRunner/main.cpp index eb147ec43d..de8315bd31 100644 --- a/apps/DataConverter/main.cpp +++ b/apps/TaskRunner/main.cpp @@ -33,50 +33,86 @@ #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" + ); + + 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/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/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/util/distanceconstants.h b/include/openspace/util/distanceconstants.h new file mode 100644 index 0000000000..e9bf243f2d --- /dev/null +++ b/include/openspace/util/distanceconstants.h @@ -0,0 +1,34 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* Permission is hereby granted, free of charge, to any person obtaining a copy of this * +* software and associated documentation files (the "Software"), to deal in the Software * +* without restriction, including without limitation the rights to use, copy, modify, * +* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * +* permit persons to whom the Software is furnished to do so, subject to the following * +* conditions: * +* * +* The above copyright notice and this permission notice shall be included in all copies * +* or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +****************************************************************************************/ + +namespace openspace { + +namespace distanceconstants { + const float EarthRadius = 6371; + const float LightYear = 9.4607304725808E15; + const float AstronomicalUnit = 1.495978707E11; + const float Parsec = 3.0856776E16; +} + +} \ No newline at end of file diff --git a/include/openspace/util/task.h b/include/openspace/util/task.h new file mode 100644 index 0000000000..20fd7e51be --- /dev/null +++ b/include/openspace/util/task.h @@ -0,0 +1,23 @@ +#ifndef __CONVERSIONTASK_H__ +#define __CONVERSIONTASK_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 openspace::Documentation documentation(); +}; + +} + +#endif diff --git a/include/openspace/util/taskloader.h b/include/openspace/util/taskloader.h new file mode 100644 index 0000000000..7982ed667e --- /dev/null +++ b/include/openspace/util/taskloader.h @@ -0,0 +1,17 @@ +#ifndef __TASKRUNNER_H__ +#define __TASKRUNNER_H__ + +#include +#include +#include + +namespace openspace { +class TaskLoader { +public: + std::vector> tasksFromDictionary(const ghoul::Dictionary& dictionary); + std::vector> tasksFromFile(const std::string& path); +}; + +} + +#endif diff --git a/modules/galaxy/CMakeLists.txt b/modules/galaxy/CMakeLists.txt index 4a873620a4..e77c3e699f 100644 --- a/modules/galaxy/CMakeLists.txt +++ b/modules/galaxy/CMakeLists.txt @@ -28,6 +28,8 @@ 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}/tasks/milkywayconversiontask.h + ${CMAKE_CURRENT_SOURCE_DIR}/tasks/milkywaypointsconversiontask.h ) source_group("Header Files" FILES ${HEADER_FILES}) @@ -35,6 +37,7 @@ 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}/tasks/milkywaypointsconversiontask.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/galaxy/galaxymodule.cpp b/modules/galaxy/galaxymodule.cpp index 1555ddc184..1a20cbce44 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("MilkywayPointsConversionTask"); + fTask->registerClass("MilkywayPointsConversionTask"); } } // namespace openspace diff --git a/apps/DataConverter/milkywayconversiontask.cpp b/modules/galaxy/tasks/milkywayconversiontask.cpp similarity index 98% rename from apps/DataConverter/milkywayconversiontask.cpp rename to modules/galaxy/tasks/milkywayconversiontask.cpp index 72482738a6..907684bbcc 100644 --- a/apps/DataConverter/milkywayconversiontask.cpp +++ b/modules/galaxy/tasks/milkywayconversiontask.cpp @@ -22,7 +22,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include #include #include #include diff --git a/apps/DataConverter/milkywayconversiontask.h b/modules/galaxy/tasks/milkywayconversiontask.h similarity index 97% rename from apps/DataConverter/milkywayconversiontask.h rename to modules/galaxy/tasks/milkywayconversiontask.h index 6eb7233c75..d9a32e5cb1 100644 --- a/apps/DataConverter/milkywayconversiontask.h +++ b/modules/galaxy/tasks/milkywayconversiontask.h @@ -25,7 +25,7 @@ #ifndef __OPENSPACE_APP_DATACONVERTER___MILKYWAYCONVERSIONTASK___H__ #define __OPENSPACE_APP_DATACONVERTER___MILKYWAYCONVERSIONTASK___H__ -#include +#include #include #include #include @@ -40,7 +40,7 @@ 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, diff --git a/apps/DataConverter/milkywaypointsconversiontask.cpp b/modules/galaxy/tasks/milkywaypointsconversiontask.cpp similarity index 98% rename from apps/DataConverter/milkywaypointsconversiontask.cpp rename to modules/galaxy/tasks/milkywaypointsconversiontask.cpp index 790d2be279..1a25b36c14 100644 --- a/apps/DataConverter/milkywaypointsconversiontask.cpp +++ b/modules/galaxy/tasks/milkywaypointsconversiontask.cpp @@ -22,7 +22,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include #include #include #include diff --git a/apps/DataConverter/milkywaypointsconversiontask.h b/modules/galaxy/tasks/milkywaypointsconversiontask.h similarity index 96% rename from apps/DataConverter/milkywaypointsconversiontask.h rename to modules/galaxy/tasks/milkywaypointsconversiontask.h index a11bc64230..6da5a42cd4 100644 --- a/apps/DataConverter/milkywaypointsconversiontask.h +++ b/modules/galaxy/tasks/milkywaypointsconversiontask.h @@ -25,7 +25,7 @@ #ifndef __OPENSPACE_APP_DATACONVERTER___MILKYWAYPOINTSCONVERSIONTASK___H__ #define __OPENSPACE_APP_DATACONVERTER___MILKYWAYPOINTSCONVERSIONTASK___H__ -#include +#include #include #include #include @@ -42,7 +42,7 @@ 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); diff --git a/modules/kameleonvolume/CMakeLists.txt b/modules/kameleonvolume/CMakeLists.txt new file mode 100644 index 0000000000..9e574540f4 --- /dev/null +++ b/modules/kameleonvolume/CMakeLists.txt @@ -0,0 +1,49 @@ +######################################################################################### +# # +# OpenSpace # +# # +# Copyright (c) 2014-2016 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +######################################################################################### + +include(${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..15a0508b6d --- /dev/null +++ b/modules/kameleonvolume/kameleonvolumemodule.cpp @@ -0,0 +1,58 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +#include +#include + +#include +#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/apps/DataConverter/conversiontask.h b/modules/kameleonvolume/kameleonvolumemodule.h similarity index 83% rename from apps/DataConverter/conversiontask.h rename to modules/kameleonvolume/kameleonvolumemodule.h index 388088977f..46f8404eea 100644 --- a/apps/DataConverter/conversiontask.h +++ b/modules/kameleonvolume/kameleonvolumemodule.h @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2017 * + * Copyright (c) 2014-2016 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -22,20 +22,20 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_APP_DATACONVERTER___CONVERSIONTASK___H__ -#define __OPENSPACE_APP_DATACONVERTER___CONVERSIONTASK___H__ +#ifndef __KAMELEONVOLUMEMODULE_H__ +#define __KAMELEONVOLUMEMODULE_H__ -#include +#include namespace openspace { -namespace dataconverter { -class ConversionTask { +class KameleonVolumeModule : public OpenSpaceModule { public: - virtual void perform(const std::function& onProgress) = 0; + KameleonVolumeModule(); + void internalInitialize() override; + std::vector KameleonVolumeModule::documentations() const override; }; -} // namespace dataconverter } // namespace openspace -#endif // __OPENSPACE_APP_DATACONVERTER___CONVERSIONTASK___H__ +#endif // __KAMELEONVOLUMEMODULE_H__ diff --git a/modules/kameleonvolume/kameleonvolumereader.cpp b/modules/kameleonvolume/kameleonvolumereader.cpp new file mode 100644 index 0000000000..f9803a8fdf --- /dev/null +++ b/modules/kameleonvolume/kameleonvolumereader.cpp @@ -0,0 +1,188 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include +#include + +//#include + + + +namespace { + const std::string _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); + glm::vec3 dims = volume->dimensions(); + 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) { + return std::vector(); + } + + 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; + 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; + 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(); + if (type == ccmc::Attribute::AttributeType::FLOAT) { + dictionary.setValue(key, attr.getAttributeFloat()); + } + else if (type == ccmc::Attribute::AttributeType::INT) { + dictionary.setValue(key, attr.getAttributeInt()); + } + else if (type == ccmc::Attribute::AttributeType::STRING) { + dictionary.setValue(key, attr.getAttributeString()); + } +} + +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); + } + + ghoul::Dictionary metaData; + metaData.setValue("globalAttributes", globalAttributesDictionary); + metaData.setValue("variableAttributes", variableDictionary); + return metaData; +} + +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/kameleonvolume/kameleonvolumereader.h b/modules/kameleonvolume/kameleonvolumereader.h new file mode 100644 index 0000000000..785d7b5dca --- /dev/null +++ b/modules/kameleonvolume/kameleonvolumereader.h @@ -0,0 +1,77 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __KAMELEONVOLUMEREADER_H__ +#define __KAMELEONVOLUMEREADER_H__ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace openspace { + +class KameleonVolumeReader { +public: + KameleonVolumeReader(const std::string& path); + //KameleonMetaData readMetaData(); + + 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; + + std::vector gridVariableNames() const; + std::vector gridUnits() const; + std::vector variableNames() const; + std::vector variableAttributeNames() const; + std::vector globalAttributeNames() const; + +private: + 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; + +}; + +} + +#include + +#endif diff --git a/modules/kameleonvolume/kameleonvolumereader.inl b/modules/kameleonvolume/kameleonvolumereader.inl new file mode 100644 index 0000000000..3e6e4b3d9d --- /dev/null +++ b/modules/kameleonvolume/kameleonvolumereader.inl @@ -0,0 +1,52 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 - 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + + + +namespace openspace { + + //KameleonMetaData KameleonVolumeReader::getMetaData() { + /* + using GridUnits = std::tuple; + GridUnits units = _kameleonWrapper.getGridUnits(); + std::string unit0 = std::get<0>(units); + std::string unit1 = std::get<1>(units); + std::string unit2 = std::get<2>(units); + + glm::vec3 scaling; + if (unit0 == 'R' && unit1 == 'R' && unit2 == 'R') { + scaling.x = scaling.y = scaling.z = openspace::distanceconstants::EarthRadius; + } + if (unit0 == '') + + VolumeMetaData metaData(VolumeMetaData::GridType::Cartesian, scaling ); + */ + + + //} + + + + +} \ No newline at end of file diff --git a/modules/kameleonvolume/rendering/kameleonvolumeraycaster.cpp b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.cpp new file mode 100644 index 0000000000..c514626243 --- /dev/null +++ b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.cpp @@ -0,0 +1,142 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace { + const std::string GlslRaycastPath = "${MODULES}/kameleonvolume/shaders/raycast.glsl"; + const std::string GlslHelperPath = "${MODULES}/kameleonvolume/shaders/helper.glsl"; + const std::string GlslBoundsVsPath = "${MODULES}/kameleonvolume/shaders/boundsvs.glsl"; + const std::string GlslBoundsFsPath = "${MODULES}/kameleonvolume/shaders/boundsfs.glsl"; +} + +namespace openspace { + +KameleonVolumeRaycaster::KameleonVolumeRaycaster( + std::shared_ptr texture, + std::shared_ptr transferFunction) + : _volumeTexture(texture) + , _transferFunction(transferFunction) + , _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) { + //program.setUniform("modelTransform", _modelTransform); + program.setUniform("viewProjection", data.camera.viewProjectionMatrix()); + Renderable::setPscUniforms(program, data.camera, data.position); + + // 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) { + // Uniforms + //program.setUniform("modelTransform", _modelTransform); + program.setUniform("viewProjection", data.camera.viewProjectionMatrix()); + Renderable::setPscUniforms(program, data.camera, data.position); + + // 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)); +} + +void KameleonVolumeRaycaster::postRaycast(const RaycastData& data, ghoul::opengl::ProgramObject& program) { + // For example: release texture units + _textureUnit = nullptr; + _tfUnit = nullptr; +} + +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; // no helper file +} + +void KameleonVolumeRaycaster::setStepSize(float stepSize) { + _stepSize = stepSize; +} + +void KameleonVolumeRaycaster::setGridType(VolumeGridType gridType) +{ + _gridType = gridType; +} + +} diff --git a/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h new file mode 100644 index 0000000000..89d83aca49 --- /dev/null +++ b/modules/kameleonvolume/rendering/kameleonvolumeraycaster.h @@ -0,0 +1,89 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __KAMELEONVOLUMERAYCASTER_H__ +#define __KAMELEONVOLUMERAYCASTER_H__ + + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +namespace ghoul { + namespace opengl { + class Texture; + class ProgramObject; + } +} + +namespace openspace { + +class RenderData; +class RaycastData; + +class KameleonVolumeRaycaster : public VolumeRaycaster { +public: + + KameleonVolumeRaycaster( + std::shared_ptr texture, + std::shared_ptr transferFunction); + + 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; + + 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); +private: + std::shared_ptr _volumeTexture; + std::shared_ptr _transferFunction; + BoxGeometry _boundingBox; + VolumeGridType _gridType; + + std::unique_ptr _tfUnit; + std::unique_ptr _textureUnit; + float _stepSize; +}; + +} // openspace + +#endif // __KAMELEONVOLUMERAYCASTER_H__ diff --git a/modules/kameleonvolume/rendering/renderablekameleonvolume.cpp b/modules/kameleonvolume/rendering/renderablekameleonvolume.cpp new file mode 100644 index 0000000000..a5912cc27f --- /dev/null +++ b/modules/kameleonvolume/rendering/renderablekameleonvolume.cpp @@ -0,0 +1,344 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace { + const std::string _loggerCat = "RenderableKameleonVolume"; +} + +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") + , _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) + , _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("Dimensions", 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("StepSize", stepSize)) { + _stepSize = stepSize; + } + + std::string transferFunctionPath; + if (dictionary.getValue("TransferFunction", transferFunctionPath)) { + _transferFunctionPath = transferFunctionPath; + _transferFunction = std::make_shared(absPath(transferFunctionPath)); + } + + std::string sourcePath; + if (dictionary.getValue("Source", sourcePath)) { + _sourcePath = absPath(sourcePath); + } + + std::string variable; + if (dictionary.getValue("Variable", variable)) { + _variable = variable; + } + + glm::vec3 lowerDomainBound; + if (dictionary.getValue("LowerDomainBound", lowerDomainBound)) { + _lowerDomainBound = lowerDomainBound; + } + else { + _autoDomainBounds = true; + } + + glm::vec3 upperDomainBound; + if (dictionary.getValue("UpperDomainBound", upperDomainBound)) { + _upperDomainBound = upperDomainBound; + } + else { + _autoDomainBounds = true; + } + + float lowerValueBound; + if (dictionary.getValue("LowerValueBound", lowerValueBound)) { + _lowerValueBound = lowerValueBound; + } + else { + _autoValueBounds = true; + } + + float upperValueBound; + if (dictionary.getValue("UpperValueBound", upperValueBound)) { + _upperValueBound = upperValueBound; + } + else { + _autoValueBounds = true; + } + + + bool cache; + if (dictionary.getValue("Cache", 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("GridType", gridType)) { + if (gridType == "Spherical") { + _gridType.setValue(static_cast(VolumeGridType::Spherical)); + } else { + _autoGridType = true; + } + } + + // TODO: read transformation: position/rotation/scale from dictionary. +} + +RenderableKameleonVolume::~RenderableKameleonVolume() {} + +bool RenderableKameleonVolume::initialize() { + load(); + + _volumeTexture->uploadTexture(); + _transferFunction->update(); + + _raycaster = std::make_unique(_volumeTexture, _transferFunction); + + _raycaster->setStepSize(_stepSize); + _gridType.onChange([this] { + _raycaster->setStepSize(_stepSize); + }); + _raycaster->setGridType(static_cast(_gridType.value())); + _gridType.onChange([this] { + _raycaster->setGridType(static_cast(_gridType.value())); + }); + + + + _raycaster->initialize(); + + + OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); + + std::function onChange = [&](bool enabled) { + if (enabled) { + OsEng.renderEngine().raycasterManager().attachRaycaster(*_raycaster.get()); + } + else { + OsEng.renderEngine().raycasterManager().detachRaycaster(*_raycaster.get()); + } + }; + + onEnabledChange(onChange); + + addProperty(_dimensions); + addProperty(_stepSize); + addProperty(_transferFunctionPath); + addProperty(_sourcePath); + addProperty(_variable); + addProperty(_lowerDomainBound); + addProperty(_upperDomainBound); + addProperty(_lowerValueBound); + addProperty(_upperValueBound); + addProperty(_gridType); + addProperty(_cache); + + + return true; +} + +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) { + RaycasterTask task{ _raycaster.get(), data }; + tasks.raycasterTasks.push_back(task); +} + +} diff --git a/modules/kameleonvolume/rendering/renderablekameleonvolume.h b/modules/kameleonvolume/rendering/renderablekameleonvolume.h new file mode 100644 index 0000000000..96b7febd7d --- /dev/null +++ b/modules/kameleonvolume/rendering/renderablekameleonvolume.h @@ -0,0 +1,95 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __RENDERABLEKAMELEONVOLUME_H__ +#define __RENDERABLEKAMELEONVOLUME_H__ + +#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(); + + properties::UVec3Property _dimensions; + properties::StringProperty _variable; + properties::Vec3Property _lowerDomainBound; + properties::Vec3Property _upperDomainBound; + bool _autoDomainBounds; + + properties::FloatProperty _lowerValueBound; + properties::FloatProperty _upperValueBound; + bool _autoValueBounds; + + properties::OptionProperty _gridType; + bool _autoGridType; + + 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; +}; +} + +#endif // __RENDERABLETOYVOLUME_H__ diff --git a/modules/kameleonvolume/shaders/boundsfs.glsl b/modules/kameleonvolume/shaders/boundsfs.glsl new file mode 100644 index 0000000000..bb4f9c8cd3 --- /dev/null +++ b/modules/kameleonvolume/shaders/boundsfs.glsl @@ -0,0 +1,40 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +in vec3 vPosition; +in vec4 worldPosition; + +#include "PowerScaling/powerScaling_fs.hglsl" +#include "fragment.glsl" + +Fragment getFragment() { + vec4 fragColor = vec4(vPosition+0.5, 1.0); + vec4 position = worldPosition; + 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..8bde15f7f9 --- /dev/null +++ b/modules/kameleonvolume/shaders/boundsvs.glsl @@ -0,0 +1,46 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#version __CONTEXT__ + +layout(location = 0) in vec4 vertPosition; + +uniform mat4 viewProjection; + +out vec3 vPosition; +out vec4 worldPosition; + +#include "PowerScaling/powerScaling_vs.hglsl" + +void main() { + vPosition = vertPosition.xyz; + worldPosition = vertPosition; + + vec4 position = pscTransform(worldPosition, mat4(1.0)); + + // project the position to view space + gl_Position = viewProjection * position; + + gl_Position.z = 1.0; +} diff --git a/modules/kameleonvolume/shaders/helper.glsl b/modules/kameleonvolume/shaders/helper.glsl new file mode 100644 index 0000000000..a144abecdb --- /dev/null +++ b/modules/kameleonvolume/shaders/helper.glsl @@ -0,0 +1,19 @@ +#define KAMELEON_PI 3.14159265358979323846 /* pi */ +#define KAMELEON_SQRT1_3 0.57735026919 /* 1/sqrt(3) */ + +vec3 kameleon_cartesianToSpherical(vec3 _cartesian) { + // Put cartesian in [-1..1] range first + vec3 cartesian = vec3(-1.0,-1.0,-1.0) + _cartesian * 2.0f; + + 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 ); + } + r *= KAMELEON_SQRT1_3; + return vec3(r, 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..7de501504b --- /dev/null +++ b/modules/kameleonvolume/shaders/raycast.glsl @@ -0,0 +1,62 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +uniform float maxStepSize#{id} = 0.02; +uniform sampler3D volumeTexture_#{id}; +uniform sampler1D transferFunction_#{id}; +uniform int gridType_#{id} = 0; + + +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 val = texture(volumeTexture_#{id}, transformedPos).r; + vec4 color = texture(transferFunction_#{id}, val); + vec3 backColor = color.rgb; + vec3 backAlpha = color.aaa; + + backColor *= stepSize; + backAlpha *= stepSize; + + 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..3ce8d2c249 --- /dev/null +++ b/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp @@ -0,0 +1,162 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +namespace { + const std::string KeyInput = "Input"; + const std::string KeyOutput = "Output"; + const std::string MainTemplateFilename = "${OPENSPACE_DATA}/web/kameleondocumentation/main.hbs"; + const std::string HandlebarsFilename = "${OPENSPACE_DATA}/web/common/handlebars-v4.0.5.js"; + const std::string JsFilename = "${OPENSPACE_DATA}/web/kameleondocumentation/script.js"; + const std::string BootstrapFilename = "${OPENSPACE_DATA}/web/common/bootstrap.min.css"; + const std::string 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; + dictionary.setValue("kameleon", kameleonDictionary); + dictionary.setValue("version", std::to_string(OPENSPACE_VERSION_MAJOR) + "." + + std::to_string(OPENSPACE_VERSION_MINOR) + "." + + std::to_string(OPENSPACE_VERSION_PATCH)); + dictionary.setValue("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 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..d86e7ed5d5 --- /dev/null +++ b/modules/kameleonvolume/tasks/kameleondocumentationtask.h @@ -0,0 +1,46 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __KAMELEONDOCUMENTAIONTASK_H__ +#define __KAMELEONDOCUMENTAIONTASK_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(); +private: + std::string _inputPath; + std::string _outputPath; +}; + +} + + +#endif __KAMELEONDOCUMENTAIONTASK_H__ \ No newline at end of file diff --git a/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp new file mode 100644 index 0000000000..df1e748c2a --- /dev/null +++ b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp @@ -0,0 +1,94 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +namespace { + const std::string KeyInput = "Input"; + const std::string 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 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..3a1a732034 --- /dev/null +++ b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.h @@ -0,0 +1,46 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2016 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __KAMELEONMETADATATOJSONTASK_H__ +#define __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(); +private: + std::string _inputPath; + std::string _outputPath; +}; + +} + + +#endif __KAMELEONMETADATATOJSONTASK_H__ \ No newline at end of file diff --git a/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp b/modules/multiresvolume/rendering/multiresvolumeraycaster.cpp index 5d9c2ed3ba..5406ce7b85 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 + _textureUnit = nullptr; + _tfUnit = nullptr; } std::string MultiresVolumeRaycaster::getBoundsVsPath() const { diff --git a/modules/volume/CMakeLists.txt b/modules/volume/CMakeLists.txt index 09c6d8efde..8373907875 100644 --- a/modules/volume/CMakeLists.txt +++ b/modules/volume/CMakeLists.txt @@ -26,7 +26,10 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rawvolume.h +<<<<<<< HEAD ${CMAKE_CURRENT_SOURCE_DIR}/rawvolume.inl +======= +>>>>>>> 4bf7b71... Add support for converting and rendering volumetric data in the cdf format. Replace DataConverter by a more general purpose TaskRunner. ${CMAKE_CURRENT_SOURCE_DIR}/rawvolumereader.h ${CMAKE_CURRENT_SOURCE_DIR}/rawvolumereader.inl ${CMAKE_CURRENT_SOURCE_DIR}/rawvolumewriter.h 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/volumegridtype.h b/modules/volume/volumegridtype.h new file mode 100644 index 0000000000..6ff5027861 --- /dev/null +++ b/modules/volume/volumegridtype.h @@ -0,0 +1,33 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* Permission is hereby granted, free of charge, to any person obtaining a copy of this * +* software and associated documentation files (the "Software"), to deal in the Software * +* without restriction, including without limitation the rights to use, copy, modify, * +* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * +* permit persons to whom the Software is furnished to do so, subject to the following * +* conditions: * +* * +* The above copyright notice and this permission notice shall be included in all copies * +* or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +****************************************************************************************/ + +#ifndef __VOLUMEGRIDTYPE_H__ +#define __VOLUMEGRIDTYPE_H__ + +enum class VolumeGridType : int { + Cartesian = 0, + Spherical = 1 +}; + +#endif \ No newline at end of file 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/src/CMakeLists.txt b/src/CMakeLists.txt index 9727ee0ca3..5e962ddabf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -152,6 +152,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 @@ -293,6 +295,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..54a1c0c73d 100644 --- a/src/engine/configurationmanager.cpp +++ b/src/engine/configurationmanager.cpp @@ -57,6 +57,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 68f699ccfc..57589f5d02 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 66e6f2caf2..efff2e5f31 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -165,6 +166,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/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..40eaf06866 --- /dev/null +++ b/src/util/task.cpp @@ -0,0 +1,70 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* Permission is hereby granted, free of charge, to any person obtaining a copy of this * +* software and associated documentation files (the "Software"), to deal in the Software * +* without restriction, including without limitation the rights to use, copy, modify, * +* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * +* permit persons to whom the Software is furnished to do so, subject to the following * +* conditions: * +* * +* The above copyright notice and this permission notice shall be included in all copies * +* or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +****************************************************************************************/ + +#include +#include +#include +#include +#include + +namespace { + const std::string _loggerCat = "Task"; +} + +namespace openspace { + +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(), dictionary, "Task"); + std::string taskType = dictionary.value("Type"); + auto factory = FactoryManager::ref().factory(); + Task *task = factory->create(taskType, dictionary); + + if (task == nullptr) { + LERROR("Failed to create a Task object of type '" << taskType << "'"); + return nullptr; + } + + return std::unique_ptr(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..c4a800cb7b --- /dev/null +++ b/src/util/taskloader.cpp @@ -0,0 +1,89 @@ +/***************************************************************************************** +* * +* OpenSpace * +* * +* Copyright (c) 2014-2016 * +* * +* Permission is hereby granted, free of charge, to any person obtaining a copy of this * +* software and associated documentation files (the "Software"), to deal in the Software * +* without restriction, including without limitation the rights to use, copy, modify, * +* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * +* permit persons to whom the Software is furnished to do so, subject to the following * +* conditions: * +* * +* The above copyright notice and this permission notice shall be included in all copies * +* or substantial portions of the Software. * +* * +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * +* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * +* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * +* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * +* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * +* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +****************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace { + const std::string _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); +} + + +} \ No newline at end of file