From 44d046e770aad7194fba672444dfd4a29fe2b5d3 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 18 Sep 2017 03:15:19 +0200 Subject: [PATCH 01/47] Setup main files for fieldlinesSequence module --- modules/fieldlinessequence/CMakeLists.txt | 45 +++++++++++++++ .../fieldlinessequencemodule.cpp | 47 ++++++++++++++++ .../fieldlinessequencemodule.h | 42 ++++++++++++++ modules/fieldlinessequence/include.cmake | 3 + .../renderablefieldlinessequence.cpp | 56 +++++++++++++++++++ .../rendering/renderablefieldlinessequence.h | 50 +++++++++++++++++ 6 files changed, 243 insertions(+) create mode 100644 modules/fieldlinessequence/CMakeLists.txt create mode 100644 modules/fieldlinessequence/fieldlinessequencemodule.cpp create mode 100644 modules/fieldlinessequence/fieldlinessequencemodule.h create mode 100644 modules/fieldlinessequence/include.cmake create mode 100644 modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp create mode 100644 modules/fieldlinessequence/rendering/renderablefieldlinessequence.h diff --git a/modules/fieldlinessequence/CMakeLists.txt b/modules/fieldlinessequence/CMakeLists.txt new file mode 100644 index 0000000000..e8c46e4b8c --- /dev/null +++ b/modules/fieldlinessequence/CMakeLists.txt @@ -0,0 +1,45 @@ +########################################################################################## +# # +# OpenSpace # +# # +# Copyright (c) 2014-2017 # +# # +# Permission is hereby granted, free of charge, to any person obtaining a copy of this # +# software and associated documentation files (the "Software"), to deal in the Software # +# without restriction, including without limitation the rights to use, copy, modify, # +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the following # +# conditions: # +# # +# The above copyright notice and this permission notice shall be included in all copies # +# or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, # +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A # +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF # +# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE # +# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +########################################################################################## + +include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequence.h +) +source_group("Header Files" FILES ${HEADER_FILES}) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequence.cpp +) +source_group("Source Files" FILES ${SOURCE_FILES}) + +set(SHADER_FILES +) +source_group("Shader Files" FILES ${SHADER_FILES}) + +create_new_module( + "FieldlinesSequence" + fieldlinessequence_module + ${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES} +) diff --git a/modules/fieldlinessequence/fieldlinessequencemodule.cpp b/modules/fieldlinessequence/fieldlinessequencemodule.cpp new file mode 100644 index 0000000000..040625f1f9 --- /dev/null +++ b/modules/fieldlinessequence/fieldlinessequencemodule.cpp @@ -0,0 +1,47 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include + +#include + +#include + +namespace openspace { + +FieldlinesSequenceModule::FieldlinesSequenceModule() + : OpenSpaceModule("FieldlinesSequence") {} + +void FieldlinesSequenceModule::internalInitialize() { + auto fRenderable = FactoryManager::ref().factory(); + ghoul_assert(fRenderable, "No renderable factory existed"); + + fRenderable->registerClass("RenderableFieldlinesSequence"); +} + +} // namespace openspace diff --git a/modules/fieldlinessequence/fieldlinessequencemodule.h b/modules/fieldlinessequence/fieldlinessequencemodule.h new file mode 100644 index 0000000000..e8290795e2 --- /dev/null +++ b/modules/fieldlinessequence/fieldlinessequencemodule.h @@ -0,0 +1,42 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSEQUENCEMODULE___H__ +#define __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSEQUENCEMODULE___H__ + +#include + +namespace openspace { + +class FieldlinesSequenceModule : public OpenSpaceModule { +public: + FieldlinesSequenceModule(); + +protected: + void internalInitialize() override; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSEQUENCEMODULE___H__ diff --git a/modules/fieldlinessequence/include.cmake b/modules/fieldlinessequence/include.cmake new file mode 100644 index 0000000000..67a0fe8d77 --- /dev/null +++ b/modules/fieldlinessequence/include.cmake @@ -0,0 +1,3 @@ +set (OPENSPACE_DEPENDENCIES + space +) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp new file mode 100644 index 0000000000..62301fe154 --- /dev/null +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -0,0 +1,56 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +namespace openspace { + +RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) { + + std::string name; + dictionary.getValue(SceneGraphNode::KeyName, name); + + _loggerCat += " [" + name + "]"; +} + +void RenderableFieldlinesSequence::initialize() { +} + +void RenderableFieldlinesSequence::deinitialize() { +} + +bool RenderableFieldlinesSequence::isReady() const { + return true; +} + +void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&) { +} + +void RenderableFieldlinesSequence::update(const UpdateData& data) { +} + +} // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h new file mode 100644 index 0000000000..adc4f49b2e --- /dev/null +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -0,0 +1,50 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_FIELDLINESSEQUENCE___RENDERABLEFIELDLINESSEQUENCE___H__ +#define __OPENSPACE_MODULE_FIELDLINESSEQUENCE___RENDERABLEFIELDLINESSEQUENCE___H__ + +#include + +namespace openspace { + +class RenderableFieldlinesSequence : public Renderable { +public: + RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary); + // ~RenderableFieldlinesSequence(); + + void initialize() override; + void deinitialize() override; + + bool isReady() const override; + + void render(const RenderData& data, RendererTasks& rendererTask) override; + void update(const UpdateData& data) override; +private: + std::string _loggerCat = "RenderableFieldlinesSequence"; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_FIELDLINESSEQUENCE___RENDERABLEFIELDLINESSEQUENCE___H__ From d6eaab8c268830be789c148169e011781f25eec6 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 18 Sep 2017 03:41:26 +0200 Subject: [PATCH 02/47] Add FieldlinesState class files --- modules/fieldlinessequence/CMakeLists.txt | 2 + .../rendering/renderablefieldlinessequence.h | 4 ++ .../util/fieldlinesstate.cpp | 31 +++++++++++++++ .../fieldlinessequence/util/fieldlinesstate.h | 38 +++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 modules/fieldlinessequence/util/fieldlinesstate.cpp create mode 100644 modules/fieldlinessequence/util/fieldlinesstate.h diff --git a/modules/fieldlinessequence/CMakeLists.txt b/modules/fieldlinessequence/CMakeLists.txt index e8c46e4b8c..32a65b9163 100644 --- a/modules/fieldlinessequence/CMakeLists.txt +++ b/modules/fieldlinessequence/CMakeLists.txt @@ -26,11 +26,13 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequence.h + ${CMAKE_CURRENT_SOURCE_DIR}/util/fieldlinesstate.h ) source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequence.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/util/fieldlinesstate.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index adc4f49b2e..0b111f6c37 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -27,6 +27,8 @@ #include +#include + namespace openspace { class RenderableFieldlinesSequence : public Renderable { @@ -43,6 +45,8 @@ public: void update(const UpdateData& data) override; private: std::string _loggerCat = "RenderableFieldlinesSequence"; + + std::vector _states; }; } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp new file mode 100644 index 0000000000..ca33976f63 --- /dev/null +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -0,0 +1,31 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +namespace openspace { + +FieldlinesState::FieldlinesState() {} + +} // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h new file mode 100644 index 0000000000..584c06608d --- /dev/null +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -0,0 +1,38 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSTATE___H__ +#define __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSTATE___H__ + +namespace openspace { + +class FieldlinesState { +public: + FieldlinesState(); +private: +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSTATE___H__ From 1519fa794fef6461c346d6a5a3d9bddd3f311781 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 18 Sep 2017 21:11:46 +0200 Subject: [PATCH 03/47] Add functionality for reading inputFileType from modfile dictionary --- .../renderablefieldlinessequence.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 62301fe154..3ae677fb4e 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -26,6 +26,17 @@ #include +namespace { + // ----- KEYS POSSIBLE IN MODFILE. EXPECTED DATA TYPE OF VALUE IN [BRACKETS] ----- // + // ---------------------------- MANDATORY MODFILE KEYS ---------------------------- // + const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] + + // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // + const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf"; + const char* VALUE_INPUT_FILE_TYPE_JSON = "json"; + const char* VALUE_INPUT_FILE_TYPE_OSFLS = "osfls"; +} // namespace + namespace openspace { RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) @@ -35,6 +46,14 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona dictionary.getValue(SceneGraphNode::KeyName, name); _loggerCat += " [" + name + "]"; + + // ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- // + std::string inputFileType; + if(!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileType)) { + LERRORC("FieldlinesSequence", + "The field " + std::string(KEY_INPUT_FILE_TYPE) + " is missing!"); + return; + } } void RenderableFieldlinesSequence::initialize() { From 499156d22187f4f7c8bf4b601e07edb989bce4b0 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 18 Sep 2017 22:42:52 +0200 Subject: [PATCH 04/47] Add functionality which read sourceFolder from Modfile and extracts all valid files from that directory --- .../renderablefieldlinessequence.cpp | 38 +++++++++++++++++-- .../rendering/renderablefieldlinessequence.h | 2 + 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 3ae677fb4e..512326a7c3 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -26,10 +26,15 @@ #include +#include + +using std::string; + namespace { // ----- KEYS POSSIBLE IN MODFILE. EXPECTED DATA TYPE OF VALUE IN [BRACKETS] ----- // // ---------------------------- MANDATORY MODFILE KEYS ---------------------------- // const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] + const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf"; @@ -42,16 +47,43 @@ namespace openspace { RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) : Renderable(dictionary) { - std::string name; + string name; dictionary.getValue(SceneGraphNode::KeyName, name); _loggerCat += " [" + name + "]"; // ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- // - std::string inputFileType; + string inputFileType; if(!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileType)) { LERRORC("FieldlinesSequence", - "The field " + std::string(KEY_INPUT_FILE_TYPE) + " is missing!"); + "The field " + string(KEY_INPUT_FILE_TYPE) + " is missing!"); + return; + } + + string sourceFolderPath; + if(!dictionary.getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) { + LERRORC("FieldlinesSequence", + "The field " + string(KEY_SOURCE_FOLDER) + " is missing!"); + return; + } + + // Ensure that the source folder exists and then extract + // the files with the same extension as + ghoul::filesystem::Directory sourceFolder(sourceFolderPath); + if (FileSys.directoryExists(sourceFolder)) { + // Extract all file paths from the provided folder (Non-recursively! Sorted!) + _sourceFiles = sourceFolder.readFiles(ghoul::Boolean::No, ghoul::Boolean::Yes); + + // Remove all files that don't have as extension + _sourceFiles.erase(std::remove_if(_sourceFiles.begin(), _sourceFiles.end(), + [inputFileType] (string str) { + const size_t EXT_LENGTH = inputFileType.length(); + string sub = str.substr(str.length() - EXT_LENGTH, EXT_LENGTH); + std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower); + return sub != inputFileType; + }), _sourceFiles.end()); + } else { + LERRORC("FieldlinesSequence", sourceFolderPath + " is not a valid directory!"); return; } } diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 0b111f6c37..1a4a6f8875 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -47,6 +47,8 @@ private: std::string _loggerCat = "RenderableFieldlinesSequence"; std::vector _states; + std::vector _sourceFiles; + }; } // namespace openspace From 2e4108093b70c62b54f6017982e6c4830865f57d Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Tue, 19 Sep 2017 03:46:25 +0200 Subject: [PATCH 05/47] Add member variables and function to read osfls files to FieldlinesState --- .../util/fieldlinesstate.cpp | 80 +++++++++++++++++++ .../fieldlinessequence/util/fieldlinesstate.h | 33 ++++++++ 2 files changed, 113 insertions(+) diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index ca33976f63..6336736d58 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -24,8 +24,88 @@ #include +#include + +#include + namespace openspace { FieldlinesState::FieldlinesState() {} +FieldlinesState::FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& loadSucessful) { + loadSucessful = loadStateFromOsfls(PATH_TO_OSFLS_FILE); +} + +bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) { + std::ifstream ifs(PATH_TO_OSFLS_FILE, std::ifstream::binary); + if (!ifs.is_open()) { + LERRORC("FieldlinesState", "Couldn't open file: " + PATH_TO_OSFLS_FILE); + return false; + } + + int binFileVersion; + ifs.read( reinterpret_cast(&binFileVersion), sizeof(int)); + + switch (binFileVersion) { + case 0 : { + // No need to put everything in this scope now, as only version 0 exists! + } + break; + default : + LERRORC("FieldlinesState","VERSION OF BINARY FILE WAS NOT RECOGNISED!"); + return false; + } + + // Define tmp variables to store meta data in + size_t numLines; + size_t numPoints; + size_t numExtras; + size_t byteSizeAllNames; + + // Read single value variables + ifs.read( reinterpret_cast(&_triggerTime), sizeof(double)); + ifs.read( reinterpret_cast(&_model), sizeof(int)); + ifs.read( reinterpret_cast(&_isMorphable), sizeof(bool)); + ifs.read( reinterpret_cast(&numLines), sizeof(size_t)); + ifs.read( reinterpret_cast(&numPoints), sizeof(size_t)); + ifs.read( reinterpret_cast(&numExtras), sizeof(size_t)); + ifs.read( reinterpret_cast(&byteSizeAllNames), sizeof(size_t)); + + // RESERVE/RESIZE vectors + // TODO: Do this without initializing values? Resize is slower than just using reserve, due to initialization of all values + _lineStart.resize(numLines); + _lineCount.resize(numLines); + _vertexPositions.resize(numPoints); + _extraVariables.resize(numExtras); + _extraVariableNames.reserve(numExtras); + + // Read vertex position data + ifs.read( reinterpret_cast(_lineStart.data()), sizeof(GLint)*numLines); + ifs.read( reinterpret_cast(_lineCount.data()), sizeof(GLsizei)*numLines); + ifs.read( reinterpret_cast(_vertexPositions.data()), sizeof(glm::vec3)*numPoints); + + // Read all extra variables + for (std::vector& vec : _extraVariables) { + vec.resize(numPoints); + ifs.read( reinterpret_cast(vec.data()), sizeof(float) * numPoints); + } + + // Read all extra variables' names. Stored as multiple c-strings + std::string allNamesInOne; + char* s = new char[byteSizeAllNames]; + ifs.read(s, byteSizeAllNames); + allNamesInOne.assign(s, byteSizeAllNames); + delete[] s; + + size_t offset = 0; + for (size_t i = 0; i < numExtras; ++i) { + auto endOfVarName = allNamesInOne.find('\0', offset); + endOfVarName -= offset; + std::string varName = allNamesInOne.substr(offset, endOfVarName); + offset += varName.size() + 1; + _extraVariableNames.push_back(varName); + } + + return true; +} } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index 584c06608d..e2145df1cf 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -25,12 +25,45 @@ #ifndef __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSTATE___H__ #define __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSTATE___H__ +#include +#include + +#include +#include + namespace openspace { class FieldlinesState { public: + enum Model : int { + batsrus = 0, + enlil = 1, + pfss = 2 + }; + FieldlinesState(); + FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& loadSucessful); + + bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE); + + // Getters + double triggerTime() { return _triggerTime; } + Model model() { return _model; } + const std::vector& vertexPositions() { return _vertexPositions; } + const std::vector& lineStart() { return _lineStart; } + const std::vector& lineCount() { return _lineCount; } + private: + bool _isMorphable = false; + double _triggerTime = -1.0; + Model _model; + + std::vector _vertexPositions; + std::vector _lineStart; + std::vector _lineCount; + std::vector> _extraVariables; + std::vector _extraVariableNames; + // TODO: Maybe introduce a vector containing seed point indices }; } // namespace openspace From 4f51dafae3b6aeca2f8b492f36b26a8bc9514976 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 20 Sep 2017 06:58:57 +0200 Subject: [PATCH 06/47] Place _loggercat in empty namespace of .cpp instead of storing it as a member variable --- .../renderablefieldlinessequence.cpp | 28 +++++++++---------- .../rendering/renderablefieldlinessequence.h | 1 - 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 512326a7c3..172bdc8033 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -31,6 +31,8 @@ using std::string; namespace { + std::string _loggerCat = "RenderableFieldlinesSequence"; + // ----- KEYS POSSIBLE IN MODFILE. EXPECTED DATA TYPE OF VALUE IN [BRACKETS] ----- // // ---------------------------- MANDATORY MODFILE KEYS ---------------------------- // const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] @@ -49,41 +51,39 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona string name; dictionary.getValue(SceneGraphNode::KeyName, name); - - _loggerCat += " [" + name + "]"; + name += ": "; // ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- // - string inputFileType; - if(!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileType)) { - LERRORC("FieldlinesSequence", - "The field " + string(KEY_INPUT_FILE_TYPE) + " is missing!"); + string inputFileTypeValue; + if(!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileTypeValue)) { + LERROR(name << "The field " << string(KEY_INPUT_FILE_TYPE) << " is missing!"); return; } string sourceFolderPath; if(!dictionary.getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) { - LERRORC("FieldlinesSequence", - "The field " + string(KEY_SOURCE_FOLDER) + " is missing!"); + LERROR(name << "The field " << string(KEY_SOURCE_FOLDER) << " is missing!"); return; } // Ensure that the source folder exists and then extract - // the files with the same extension as + // the files with the same extension as ghoul::filesystem::Directory sourceFolder(sourceFolderPath); if (FileSys.directoryExists(sourceFolder)) { // Extract all file paths from the provided folder (Non-recursively! Sorted!) _sourceFiles = sourceFolder.readFiles(ghoul::Boolean::No, ghoul::Boolean::Yes); - // Remove all files that don't have as extension + // Remove all files that don't have as extension _sourceFiles.erase(std::remove_if(_sourceFiles.begin(), _sourceFiles.end(), - [inputFileType] (string str) { - const size_t EXT_LENGTH = inputFileType.length(); + [inputFileTypeValue] (string str) { + const size_t EXT_LENGTH = inputFileTypeValue.length(); string sub = str.substr(str.length() - EXT_LENGTH, EXT_LENGTH); std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower); - return sub != inputFileType; + return sub != inputFileTypeValue; }), _sourceFiles.end()); } else { - LERRORC("FieldlinesSequence", sourceFolderPath + " is not a valid directory!"); + LERROR(name << "FieldlinesSequence" << sourceFolderPath + << " is not a valid directory!"); return; } } diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 1a4a6f8875..413320cda4 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -44,7 +44,6 @@ public: void render(const RenderData& data, RendererTasks& rendererTask) override; void update(const UpdateData& data) override; private: - std::string _loggerCat = "RenderableFieldlinesSequence"; std::vector _states; std::vector _sourceFiles; From 94d0cc3ddd3b65cf692f10e015cd7ee105eea78b Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 20 Sep 2017 17:52:10 +0200 Subject: [PATCH 07/47] Handle inputs from modfile Dictionary in separate function --- .../renderablefieldlinessequence.cpp | 105 ++++++++++++++---- .../rendering/renderablefieldlinessequence.h | 12 +- 2 files changed, 97 insertions(+), 20 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 172bdc8033..9dc65fecab 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -38,6 +38,9 @@ namespace { const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] + // ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- // + const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM + // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf"; const char* VALUE_INPUT_FILE_TYPE_JSON = "json"; @@ -49,6 +52,44 @@ namespace openspace { RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) : Renderable(dictionary) { + if(!extractInfoFromDictionary(dictionary)) { + _sourceFileType = INVALID; + } + +} + +void RenderableFieldlinesSequence::initialize() { + switch (_sourceFileType) { + case CDF: + LERROR("CDF NOT YET IMPLEMENTED!"); + break; + case JSON: + LERROR("JSON NOT YET IMPLEMENTED!"); + break; + case OSFLS: + LERROR("OSFLS NOT YET IMPLEMENTED!"); + break; + default: + break; + } +} + +void RenderableFieldlinesSequence::deinitialize() { +} + +bool RenderableFieldlinesSequence::isReady() const { + return true; +} + +void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&) { +} + +void RenderableFieldlinesSequence::update(const UpdateData& data) { +} + +bool RenderableFieldlinesSequence::extractInfoFromDictionary( + const ghoul::Dictionary& dictionary) { + string name; dictionary.getValue(SceneGraphNode::KeyName, name); name += ": "; @@ -57,13 +98,29 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona string inputFileTypeValue; if(!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileTypeValue)) { LERROR(name << "The field " << string(KEY_INPUT_FILE_TYPE) << " is missing!"); - return; + return false; + } else { + std::transform(inputFileTypeValue.begin(), inputFileTypeValue.end(), + inputFileTypeValue.begin(), ::tolower); + // Verify that the input type is correct + if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_CDF) { + _sourceFileType = CDF; + } else if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_JSON) { + _sourceFileType = JSON; + } else if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_OSFLS) { + _sourceFileType = OSFLS; + } else { + LERROR(name << inputFileTypeValue << " is not a recognised " + << KEY_INPUT_FILE_TYPE); + _sourceFileType = INVALID; + return false; + } } string sourceFolderPath; if(!dictionary.getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) { LERROR(name << "The field " << string(KEY_SOURCE_FOLDER) << " is missing!"); - return; + return false; } // Ensure that the source folder exists and then extract @@ -81,27 +138,37 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower); return sub != inputFileTypeValue; }), _sourceFiles.end()); + // Ensure that there are available and valid source files left + if (_sourceFiles.empty()) { + LERROR(name << sourceFolderPath << " contains no ." << inputFileTypeValue + << " files!"); + return false; + } } else { LERROR(name << "FieldlinesSequence" << sourceFolderPath << " is not a valid directory!"); - return; + return false; + } + + switch (_sourceFileType) { + case CDF: + LERROR(name << "CDF NOT YET IMPLEMENTED!"); + break; + case JSON: + LERROR(name << "JSON NOT YET IMPLEMENTED!"); + break; + case OSFLS: { + bool shouldLoadInRealtime = false; + if (dictionary.getValue(KEY_OSLFS_LOAD_AT_RUNTIME, shouldLoadInRealtime)) { + _isLoadingStatesAtRuntime = shouldLoadInRealtime; + } else { + LWARNING(name << KEY_OSLFS_LOAD_AT_RUNTIME << + " isn't specified! Fieldline states will be stored in RAM"); + } + } break; + default: + break; } } -void RenderableFieldlinesSequence::initialize() { -} - -void RenderableFieldlinesSequence::deinitialize() { -} - -bool RenderableFieldlinesSequence::isReady() const { - return true; -} - -void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&) { -} - -void RenderableFieldlinesSequence::update(const UpdateData& data) { -} - } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 413320cda4..8cc0328d00 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -44,10 +44,20 @@ public: void render(const RenderData& data, RendererTasks& rendererTask) override; void update(const UpdateData& data) override; private: + enum SourceFileType : int { + CDF = 0, + JSON, + OSFLS, + INVALID + }; + + bool _isLoadingStatesAtRuntime = false; // False => loading osfls at runtime + SourceFileType _sourceFileType; std::vector _states; - std::vector _sourceFiles; + std::vector _sourceFiles; // Stored in RAM if files are loaded at runtime, else emptied after initialization + bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); }; } // namespace openspace From 8ff9cb403eea09389a2e411be6bbca74926ed559 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 20 Sep 2017 18:02:01 +0200 Subject: [PATCH 08/47] Load OSFLS states into RAM and keep track of trigger times --- .../renderablefieldlinessequence.cpp | 29 ++++++++++++++++++- .../rendering/renderablefieldlinessequence.h | 4 +++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 9dc65fecab..0c250825ad 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -67,11 +67,25 @@ void RenderableFieldlinesSequence::initialize() { LERROR("JSON NOT YET IMPLEMENTED!"); break; case OSFLS: - LERROR("OSFLS NOT YET IMPLEMENTED!"); + if (_isLoadingStatesAtRuntime) { + LERROR("OSFLS LOAD AT RUNTIME NOT YET IMPLEMENTED!"); + } else { + for (string filePath : _sourceFiles) { + FieldlinesState newState; + bool loadedSuccessfully = newState.loadStateFromOsfls(filePath); + if (loadedSuccessfully) { + _states.push_back(newState); + _startTimes.push_back(newState.triggerTime()); + _nStates++; + } + } + } break; default: break; } + + computeSequenceEndTime(); } void RenderableFieldlinesSequence::deinitialize() { @@ -171,4 +185,17 @@ bool RenderableFieldlinesSequence::extractInfoFromDictionary( } } +// Calculate expected end time. +void RenderableFieldlinesSequence::computeSequenceEndTime() { + if (_nStates > 1) { + const double LAST_TRIGGER_TIME = _startTimes[_nStates - 1]; + const double SEQUENCE_DURATION = LAST_TRIGGER_TIME - _startTimes[0]; + const double AVERAGE_STATE_DURATION = SEQUENCE_DURATION / (static_cast(_nStates) - 1.0); + _sequenceEndTime = LAST_TRIGGER_TIME + AVERAGE_STATE_DURATION; + } else { + // If there's just one state it should never disappear! + _sequenceEndTime = DBL_MAX; + } +} + } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 8cc0328d00..8e3ebdddaf 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -52,11 +52,15 @@ private: }; bool _isLoadingStatesAtRuntime = false; // False => loading osfls at runtime + size_t _nStates = 0; + double _sequenceEndTime; SourceFileType _sourceFileType; + std::vector _startTimes; std::vector _states; std::vector _sourceFiles; // Stored in RAM if files are loaded at runtime, else emptied after initialization + void computeSequenceEndTime(); bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); }; From 5882c16bcc3e80f7348c21feae4ead693dc4f769 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 20 Sep 2017 18:08:21 +0200 Subject: [PATCH 09/47] Add functionality for checking which state should be shown, depending on time --- .../renderablefieldlinessequence.cpp | 45 +++++++++++++++++++ .../rendering/renderablefieldlinessequence.h | 4 ++ 2 files changed, 49 insertions(+) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 0c250825ad..7abe27eff5 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -99,6 +99,51 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& } void RenderableFieldlinesSequence::update(const UpdateData& data) { + // This node shouldn't do anything if its been disabled from the gui! + if (_enabled) { + const double CURRENT_TIME = data.time.j2000Seconds(); + // Check if current time in OpenSpace is within sequence interval + if (isWithinSequenceInterval(CURRENT_TIME)) { + const int NEXT_IDX = _activeStateIndex + 1; + if (_activeStateIndex < 0 // true => Previous frame was not within the sequence interval + || CURRENT_TIME < _startTimes[_activeStateIndex] // true => OpenSpace has stepped back to a time represented by another state + || (NEXT_IDX < _nStates && CURRENT_TIME >= _startTimes[NEXT_IDX])) { // true => OpenSpace has stepped forward to a time represented by another state + + updateActiveStateIndex(CURRENT_TIME); + _needsUpdate = true; + } // else {we're still in same state as previous frame (no changes needed)} + } else { + // Not in interval => set everything to false + _activeStateIndex = -1; + _needsUpdate = false; + } + + if (_needsUpdate) { + // Update States + // ... + // ... + // Everything is set and ready for rendering! + _needsUpdate = false; + } + } +} + +inline bool RenderableFieldlinesSequence::isWithinSequenceInterval(const double CURRENT_TIME) { + return (CURRENT_TIME >= _startTimes[0]) && (CURRENT_TIME < _sequenceEndTime); +} + +// Assumes we already know that CURRENT_TIME is within the sequence interval +void RenderableFieldlinesSequence::updateActiveStateIndex(const double CURRENT_TIME) { + auto iter = std::upper_bound(_startTimes.begin(), _startTimes.end(), CURRENT_TIME); + if (iter != _startTimes.end()) { + if ( iter != _startTimes.begin()) { + _activeStateIndex = std::distance(_startTimes.begin(), iter) - 1; + } else { + _activeStateIndex = 0; + } + } else { + _activeStateIndex = _nStates - 1; + } } bool RenderableFieldlinesSequence::extractInfoFromDictionary( diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 8e3ebdddaf..56b39b4d5b 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -51,6 +51,8 @@ private: INVALID }; + int _activeStateIndex = -1; + bool _needsUpdate = false; // If still in same state as previous frame == false bool _isLoadingStatesAtRuntime = false; // False => loading osfls at runtime size_t _nStates = 0; double _sequenceEndTime; @@ -62,6 +64,8 @@ private: void computeSequenceEndTime(); bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); + inline bool isWithinSequenceInterval(const double CURRENT_TIME); + inline void updateActiveStateIndex(const double CURRENT_TIME); }; } // namespace openspace From 42d49ecc5561c821ed7c238d21b568489243fa9e Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 20 Sep 2017 18:44:21 +0200 Subject: [PATCH 10/47] Setup OpenGL variables and shaders and draw field lines --- modules/fieldlinessequence/CMakeLists.txt | 2 + .../renderablefieldlinessequence.cpp | 80 ++++++++++++++++++- .../rendering/renderablefieldlinessequence.h | 9 +++ .../shaders/fieldlinessequence_fs.glsl | 43 ++++++++++ .../shaders/fieldlinessequence_vs.glsl | 42 ++++++++++ 5 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl create mode 100644 modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl diff --git a/modules/fieldlinessequence/CMakeLists.txt b/modules/fieldlinessequence/CMakeLists.txt index 32a65b9163..33a0b287ec 100644 --- a/modules/fieldlinessequence/CMakeLists.txt +++ b/modules/fieldlinessequence/CMakeLists.txt @@ -37,6 +37,8 @@ set(SOURCE_FILES source_group("Source Files" FILES ${SOURCE_FILES}) set(SHADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/fieldlinessequence_vs.glsl + ${CMAKE_CURRENT_SOURCE_DIR}/shaders/fieldlinessequence_fs.glsl ) source_group("Shader Files" FILES ${SHADER_FILES}) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 7abe27eff5..eb5831e681 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -24,9 +24,14 @@ #include +#include +#include #include +#include + #include +#include using std::string; @@ -86,9 +91,36 @@ void RenderableFieldlinesSequence::initialize() { } computeSequenceEndTime(); + + // Setup shader program + _shaderProgram = OsEng.renderEngine().buildRenderProgram( + "FieldlinesSequence", + "${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_vs.glsl", + "${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_fs.glsl" + ); + + if (!_shaderProgram) { + LERROR("Shader program failed initialization!"); + _sourceFileType = INVALID; + } + + //------------------ Initialize OpenGL VBOs and VAOs-------------------------------// + glGenVertexArrays(1, &_vertexArrayObject); + glGenBuffers(1, &_vertexPositionBuffer); } void RenderableFieldlinesSequence::deinitialize() { + glDeleteVertexArrays(1, &_vertexArrayObject); + _vertexArrayObject = 0; + + glDeleteBuffers(1, &_vertexPositionBuffer); + _vertexPositionBuffer = 0; + + RenderEngine& renderEngine = OsEng.renderEngine(); + if (_shaderProgram) { + renderEngine.removeRenderProgram(_shaderProgram); + _shaderProgram = nullptr; + } } bool RenderableFieldlinesSequence::isReady() const { @@ -96,9 +128,38 @@ bool RenderableFieldlinesSequence::isReady() const { } void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&) { + if (_activeStateIndex != -1) { + _shaderProgram->activate(); + + const glm::dmat4 ROTATION_TRANSFORM = glm::dmat4(data.modelTransform.rotation); + // const glm::mat4 SCALE_TRANSFORM = glm::mat4(1.0); // TODO remove if no use + const glm::dmat4 MODEL_TRANSFORM = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + ROTATION_TRANSFORM * + glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale))); + const glm::dmat4 MODEL_VIEW_TRANSFORM = data.camera.combinedViewMatrix() * MODEL_TRANSFORM; + + _shaderProgram->setUniform("modelViewProjection", + data.camera.sgctInternal.projectionMatrix() * glm::mat4(MODEL_VIEW_TRANSFORM)); + + glBindVertexArray(_vertexArrayObject); + glMultiDrawArrays( + GL_LINE_STRIP, //_drawingOutputType, + _states[_activeStateIndex].lineStart().data(), + _states[_activeStateIndex].lineCount().data(), + static_cast(_states[_activeStateIndex].lineStart().size()) + ); + + glBindVertexArray(0); + _shaderProgram->deactivate(); + } } void RenderableFieldlinesSequence::update(const UpdateData& data) { + if (_shaderProgram->isDirty()) { + _shaderProgram->rebuildFromFile(); + } + // This node shouldn't do anything if its been disabled from the gui! if (_enabled) { const double CURRENT_TIME = data.time.j2000Seconds(); @@ -119,9 +180,22 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { } if (_needsUpdate) { - // Update States - // ... - // ... + glBindVertexArray(_vertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + + const std::vector& VERTEX_POS_VEC = + _states[_activeStateIndex].vertexPositions(); + + glBufferData(GL_ARRAY_BUFFER, VERTEX_POS_VEC.size() * sizeof(glm::vec3), + &VERTEX_POS_VEC.front(), GL_STATIC_DRAW); + + glEnableVertexAttribArray(_vertAttrVertexPos); + glVertexAttribPointer(_vertAttrVertexPos, 3, GL_FLOAT, GL_FALSE, 0, 0); + + // UNBIND + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + // Everything is set and ready for rendering! _needsUpdate = false; } diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 56b39b4d5b..9f5c44d45a 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -58,10 +58,19 @@ private: double _sequenceEndTime; SourceFileType _sourceFileType; + std::unique_ptr _shaderProgram; + std::vector _startTimes; std::vector _states; std::vector _sourceFiles; // Stored in RAM if files are loaded at runtime, else emptied after initialization + GLuint _vertexArrayObject = 0; + GLuint _vertexPositionBuffer = 0; + + // THESE MUST CORRESPOND TO THE SHADER PROGRAM + // TODO: THIS CAN BE DETERMINED BY ASKING THE SHADER PROGRAM TOO + GLuint _vertAttrVertexPos = 0; + void computeSequenceEndTime(); bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); inline bool isWithinSequenceInterval(const double CURRENT_TIME); diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl new file mode 100644 index 0000000000..8e8f3ec6d3 --- /dev/null +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl @@ -0,0 +1,43 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +in vec4 vs_color; +in float vs_depth; + +#include "fragment.glsl" +#include "PowerScaling/powerScaling_fs.hglsl" + +Fragment getFragment() { + if (vs_color.a == 0) { + discard; + } + + vec4 fragColor = vs_color; + + Fragment frag; + frag.depth = vs_depth; + frag.color = fragColor; + + return frag; +} diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl new file mode 100644 index 0000000000..cc6f48bc93 --- /dev/null +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl @@ -0,0 +1,42 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#version __CONTEXT__ + +uniform mat4 modelViewProjection; + +layout(location = 0) in vec3 in_position; // in meters + +out vec4 vs_color; +out float vs_depth; + +#include "PowerScaling/powerScaling_vs.hglsl" + +void main() { + vs_color = vec4(0.75, 0.5, 0.0, 0.75); + vec4 position_in_meters = vec4(in_position, 1); + vec4 positionClipSpace = modelViewProjection * position_in_meters; + gl_Position = z_normalization(positionClipSpace); + vs_depth = gl_Position.w; +} From eea7c7306a818c712fe98ba0a146b0a0c46ce67c Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Thu, 21 Sep 2017 01:21:05 +0200 Subject: [PATCH 11/47] Add functionality to illustrate magnetic flow --- .../renderablefieldlinessequence.cpp | 69 ++++++++++++++++--- .../rendering/renderablefieldlinessequence.h | 15 ++++ .../shaders/fieldlinessequence_vs.glsl | 28 +++++++- 3 files changed, 101 insertions(+), 11 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index eb5831e681..fa6dfe77ef 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -50,12 +50,44 @@ namespace { const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf"; const char* VALUE_INPUT_FILE_TYPE_JSON = "json"; const char* VALUE_INPUT_FILE_TYPE_OSFLS = "osfls"; + + static const openspace::properties::Property::PropertyInfo LineColorInfo = { + "lineColor", "Line Color", "Color of lines." + }; + static const openspace::properties::Property::PropertyInfo EnableFlowInfo = { + "Enable", "ON/OFF", + "Toggles the rendering of moving particles along the lines. Can e.g. illustrate magnetic flow." + }; + static const openspace::properties::Property::PropertyInfo ReverseFlowInfo = { + "reversed", "Reversed Flow", "Toggle to make the flow move in the opposite direction." + }; + static const openspace::properties::Property::PropertyInfo ParticleSizeInfo = { + "particleSize", "Particle Size", "Size of the particles." + }; + static const openspace::properties::Property::PropertyInfo ParticleSpacingInfo = { + "particleSpacing", "Particle Spacing", "Spacing inbetween particles." + }; + static const openspace::properties::Property::PropertyInfo FlowSpeedInfo = { + "speed", "Speed", "Speed of the flow." + }; + static const openspace::properties::Property::PropertyInfo FlowColorInfo = { + "color", "Color", "Color of particles." + }; } // namespace namespace openspace { RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) - : Renderable(dictionary) { + : Renderable(dictionary), + _lineColor(LineColorInfo, glm::vec4(0.75f, 0.5f, 0.0f, 0.5f), glm::vec4(0.f), glm::vec4(1.f)), + _flowGroup({ "Flow" }), + _flowEnabled(EnableFlowInfo, true), + _flowReversed(ReverseFlowInfo, false), + _flowParticleSize(ParticleSizeInfo, 5, 0, 500), + _flowParticleSpacing(ParticleSpacingInfo, 60, 0, 500), + _flowSpeed(FlowSpeedInfo, 20, 0, 1000), + _flowColor(FlowColorInfo, glm::vec4(0.8f, 0.7f, 0.0f, 0.6f), + glm::vec4(0.f), glm::vec4(1.f)) { if(!extractInfoFromDictionary(dictionary)) { _sourceFileType = INVALID; @@ -92,6 +124,16 @@ void RenderableFieldlinesSequence::initialize() { computeSequenceEndTime(); + // HANDLE PROPERTIES + addProperty(_lineColor); + addPropertySubOwner(_flowGroup); + _flowGroup.addProperty(_flowEnabled); + _flowGroup.addProperty(_flowReversed); + _flowGroup.addProperty(_flowColor); + _flowGroup.addProperty(_flowParticleSize); + _flowGroup.addProperty(_flowParticleSpacing); + _flowGroup.addProperty(_flowSpeed); + // Setup shader program _shaderProgram = OsEng.renderEngine().buildRenderProgram( "FieldlinesSequence", @@ -124,23 +166,32 @@ void RenderableFieldlinesSequence::deinitialize() { } bool RenderableFieldlinesSequence::isReady() const { - return true; + return _sourceFileType != INVALID; } void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&) { if (_activeStateIndex != -1) { _shaderProgram->activate(); - const glm::dmat4 ROTATION_TRANSFORM = glm::dmat4(data.modelTransform.rotation); + const glm::dmat4 ROT_MAT = glm::dmat4(data.modelTransform.rotation); // const glm::mat4 SCALE_TRANSFORM = glm::mat4(1.0); // TODO remove if no use - const glm::dmat4 MODEL_TRANSFORM = + const glm::dmat4 MODEL_MAT = glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * - ROTATION_TRANSFORM * - glm::dmat4(glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale))); - const glm::dmat4 MODEL_VIEW_TRANSFORM = data.camera.combinedViewMatrix() * MODEL_TRANSFORM; + ROT_MAT * + glm::dmat4(glm::scale(glm::dmat4(1), glm::dvec3(data.modelTransform.scale))); + const glm::dmat4 MODEL_VIEW_MAT = data.camera.combinedViewMatrix() * MODEL_MAT; _shaderProgram->setUniform("modelViewProjection", - data.camera.sgctInternal.projectionMatrix() * glm::mat4(MODEL_VIEW_TRANSFORM)); + data.camera.sgctInternal.projectionMatrix() * glm::mat4(MODEL_VIEW_MAT)); + + _shaderProgram->setUniform("lineColor", _lineColor); + // Flow/Particles + _shaderProgram->setUniform("usingParticles", _flowEnabled); + _shaderProgram->setUniform("flowColor", _flowColor); + _shaderProgram->setUniform("particleSize", _flowParticleSize); + _shaderProgram->setUniform("particleSpeed", _flowSpeed); + _shaderProgram->setUniform("particleSpacing", _flowParticleSpacing); + _shaderProgram->setUniform("time", OsEng.runTime() * (_flowReversed ? -1 : 1)); glBindVertexArray(_vertexArrayObject); glMultiDrawArrays( @@ -216,7 +267,7 @@ void RenderableFieldlinesSequence::updateActiveStateIndex(const double CURRENT_T _activeStateIndex = 0; } } else { - _activeStateIndex = _nStates - 1; + _activeStateIndex = static_cast(_nStates) - 1; } } diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 9f5c44d45a..aeb54134e7 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -27,6 +27,9 @@ #include +#include +#include + #include namespace openspace { @@ -71,6 +74,18 @@ private: // TODO: THIS CAN BE DETERMINED BY ASKING THE SHADER PROGRAM TOO GLuint _vertAttrVertexPos = 0; + // ----------------------------- Properties ----------------------------- + properties::Vec4Property _lineColor; // Uniform Field Line Color + + properties::PropertyOwner _flowGroup; + properties::BoolProperty _flowEnabled; // Toggle flow [ON/OFF] + properties::BoolProperty _flowReversed; // Toggle flow direction [FORWARDS/BACKWARDS] + properties::IntProperty _flowParticleSize; // Size of simulated flow particles + properties::IntProperty _flowParticleSpacing; // Size of simulated flow particles + properties::IntProperty _flowSpeed; // Speed of simulated flow + properties::Vec4Property _flowColor; // Simulated particles' color + + void computeSequenceEndTime(); bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); inline bool isWithinSequenceInterval(const double CURRENT_TIME); diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl index cc6f48bc93..906953c7b7 100644 --- a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl @@ -24,7 +24,14 @@ #version __CONTEXT__ -uniform mat4 modelViewProjection; +uniform mat4 modelViewProjection; +uniform bool usingParticles; +uniform double time; +uniform int particleSize; +uniform int particleSpeed; +uniform int particleSpacing; +uniform vec4 flowColor; +uniform vec4 lineColor; layout(location = 0) in vec3 in_position; // in meters @@ -33,8 +40,25 @@ out float vs_depth; #include "PowerScaling/powerScaling_vs.hglsl" +bool isPartOfParticle(const double TIME, const int VERTEX_ID, const int PARTICLE_SIZE, + const int PARTICLE_SPEED, const int PARTICLE_SPACING) { + const int MODULUS_RESULT = int(double(PARTICLE_SPEED) * TIME + VERTEX_ID) % PARTICLE_SPACING; + return MODULUS_RESULT > 0 && MODULUS_RESULT <= PARTICLE_SIZE; +} + void main() { - vs_color = vec4(0.75, 0.5, 0.0, 0.75); + + const bool IS_PARTICLE = usingParticles && isPartOfParticle(time, gl_VertexID, + particleSize, + particleSpeed, + particleSpacing); + + if (IS_PARTICLE) { + vs_color = flowColor; + } else { + vs_color = lineColor; + } + vec4 position_in_meters = vec4(in_position, 1); vec4 positionClipSpace = modelViewProjection * position_in_meters; gl_Position = z_normalization(positionClipSpace); From ec8c3c5ea70f771cbb9b4ca47433992d588ae3ae Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Thu, 21 Sep 2017 03:36:05 +0200 Subject: [PATCH 12/47] Add functionality for reading and displaying OSFLS files during runtime --- .../renderablefieldlinessequence.cpp | 108 +++++++++++++++--- .../rendering/renderablefieldlinessequence.h | 26 +++-- 2 files changed, 112 insertions(+), 22 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index fa6dfe77ef..bbf6fec31f 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -105,8 +105,19 @@ void RenderableFieldlinesSequence::initialize() { break; case OSFLS: if (_isLoadingStatesAtRuntime) { - LERROR("OSFLS LOAD AT RUNTIME NOT YET IMPLEMENTED!"); + extractTriggerTimesFromFileNames(); + FieldlinesState newState; + bool loadedSuccessfully = newState.loadStateFromOsfls(_sourceFiles[0]); + if (loadedSuccessfully) { + _states.push_back(newState); + _nStates = _startTimes.size(); + _activeStateIndex = 0; + } else { + LERROR("The provided .osfls files seem to be corrupt!"); + _sourceFileType = INVALID; + } } else { + // Load states into RAM! for (string filePath : _sourceFiles) { FieldlinesState newState; bool loadedSuccessfully = newState.loadStateFromOsfls(filePath); @@ -122,6 +133,11 @@ void RenderableFieldlinesSequence::initialize() { break; } + // No need to store source paths in memory if their states are already in RAM! + if (!_isLoadingStatesAtRuntime) { + _sourceFiles.clear(); + } + computeSequenceEndTime(); // HANDLE PROPERTIES @@ -163,6 +179,11 @@ void RenderableFieldlinesSequence::deinitialize() { renderEngine.removeRenderProgram(_shaderProgram); _shaderProgram = nullptr; } + + // Stall main thread until thread that's loading states is done! + while (/*!_newStateIsReady &&*/ _isLoadingStateFromDisk) { + LWARNING("TRYING TO DESTROY CLASS WHEN A THREAD USING IT IS STILL ACTIVE"); + } } bool RenderableFieldlinesSequence::isReady() const { @@ -170,7 +191,7 @@ bool RenderableFieldlinesSequence::isReady() const { } void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&) { - if (_activeStateIndex != -1) { + if (_activeTriggerTimeIndex != -1) { _shaderProgram->activate(); const glm::dmat4 ROT_MAT = glm::dmat4(data.modelTransform.rotation); @@ -216,21 +237,44 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { const double CURRENT_TIME = data.time.j2000Seconds(); // Check if current time in OpenSpace is within sequence interval if (isWithinSequenceInterval(CURRENT_TIME)) { - const int NEXT_IDX = _activeStateIndex + 1; - if (_activeStateIndex < 0 // true => Previous frame was not within the sequence interval - || CURRENT_TIME < _startTimes[_activeStateIndex] // true => OpenSpace has stepped back to a time represented by another state + const int NEXT_IDX = _activeTriggerTimeIndex + 1; + if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval + || CURRENT_TIME < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state || (NEXT_IDX < _nStates && CURRENT_TIME >= _startTimes[NEXT_IDX])) { // true => OpenSpace has stepped forward to a time represented by another state - updateActiveStateIndex(CURRENT_TIME); - _needsUpdate = true; + updateActiveTriggerTimeIndex(CURRENT_TIME); + + if (_isLoadingStatesAtRuntime) { + _mustLoadNewStateFromDisk = true; + } else { + _needsUpdate = true; + _activeStateIndex = _activeTriggerTimeIndex; + } } // else {we're still in same state as previous frame (no changes needed)} } else { // Not in interval => set everything to false - _activeStateIndex = -1; - _needsUpdate = false; + _activeTriggerTimeIndex = -1; + _mustLoadNewStateFromDisk = false; + _needsUpdate = false; } - if (_needsUpdate) { + if (_mustLoadNewStateFromDisk) { + if (!_isLoadingStateFromDisk && !_newStateIsReady) { + _isLoadingStateFromDisk = true; + _mustLoadNewStateFromDisk = false; + const std::string FILEPATH = _sourceFiles[_activeTriggerTimeIndex]; + std::thread readBinaryThread([this, FILEPATH] { + this->readNewState(FILEPATH); + }); + readBinaryThread.detach(); + } + } + + if (_needsUpdate || _newStateIsReady) { + if (_isLoadingStatesAtRuntime) { + _states[0] = std::move(_newState); + } + glBindVertexArray(_vertexArrayObject); glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); @@ -249,6 +293,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { // Everything is set and ready for rendering! _needsUpdate = false; + _newStateIsReady = false; } } } @@ -258,19 +303,30 @@ inline bool RenderableFieldlinesSequence::isWithinSequenceInterval(const double } // Assumes we already know that CURRENT_TIME is within the sequence interval -void RenderableFieldlinesSequence::updateActiveStateIndex(const double CURRENT_TIME) { +void RenderableFieldlinesSequence::updateActiveTriggerTimeIndex(const double CURRENT_TIME) { auto iter = std::upper_bound(_startTimes.begin(), _startTimes.end(), CURRENT_TIME); if (iter != _startTimes.end()) { if ( iter != _startTimes.begin()) { - _activeStateIndex = std::distance(_startTimes.begin(), iter) - 1; + _activeTriggerTimeIndex = std::distance(_startTimes.begin(), iter) - 1; } else { - _activeStateIndex = 0; + _activeTriggerTimeIndex = 0; } } else { - _activeStateIndex = static_cast(_nStates) - 1; + _activeTriggerTimeIndex = static_cast(_nStates) - 1; } } +// Reading state from disk. Thread safe! +void RenderableFieldlinesSequence::readNewState(const std::string& FILEPATH) { + FieldlinesState newState; + + bool isSuccessful = newState.loadStateFromOsfls(FILEPATH); + _newState = std::move(newState); + + _newStateIsReady = true; + _isLoadingStateFromDisk = false; +} + bool RenderableFieldlinesSequence::extractInfoFromDictionary( const ghoul::Dictionary& dictionary) { @@ -347,7 +403,7 @@ bool RenderableFieldlinesSequence::extractInfoFromDictionary( _isLoadingStatesAtRuntime = shouldLoadInRealtime; } else { LWARNING(name << KEY_OSLFS_LOAD_AT_RUNTIME << - " isn't specified! Fieldline states will be stored in RAM"); + " isn't specified! OSFLS files will be loaded during runtime!"); } } break; default: @@ -368,4 +424,26 @@ void RenderableFieldlinesSequence::computeSequenceEndTime() { } } +// Extract J2000 time from file names +// Requires files to be named as such: 'YYYY-MM-DDTHH-MM-SS-XXX.osfls' +void RenderableFieldlinesSequence::extractTriggerTimesFromFileNames() { + const size_t FILENAME_SIZE = 23; // number of characters in filename (excluding '.osfls') + const size_t EXT_SIZE = 6; // size(".osfls") + + for (const std::string& FILEPATH : _sourceFiles) { + const size_t STR_LENGTH = FILEPATH.size(); + // Extract the filename from the path (without extension) + std::string timeString = FILEPATH.substr(STR_LENGTH - FILENAME_SIZE - EXT_SIZE, + FILENAME_SIZE - 1); + // Ensure the separators are correct + timeString.replace( 4, 1, "-"); + timeString.replace( 7, 1, "-"); + timeString.replace(13, 1, ":"); + timeString.replace(16, 1, ":"); + timeString.replace(19, 1, "."); + const double TRIGGER_TIME = Time::convertTime(timeString); + _startTimes.push_back(TRIGGER_TIME); + } +} + } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index aeb54134e7..455c4f1f9a 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -32,6 +32,8 @@ #include +#include + namespace openspace { class RenderableFieldlinesSequence : public Renderable { @@ -54,12 +56,19 @@ private: INVALID }; - int _activeStateIndex = -1; - bool _needsUpdate = false; // If still in same state as previous frame == false - bool _isLoadingStatesAtRuntime = false; // False => loading osfls at runtime - size_t _nStates = 0; - double _sequenceEndTime; - SourceFileType _sourceFileType; + int _activeStateIndex = -1; + int _activeTriggerTimeIndex = -1; + bool _isLoadingStatesAtRuntime = true; // False => loading osfls at runtime + bool _mustLoadNewStateFromDisk = false; // If still in same state as previous frame == false + bool _needsUpdate = false; // If still in same state as previous frame == false + FieldlinesState _newState; + size_t _nStates = 0; + double _sequenceEndTime; + SourceFileType _sourceFileType; + + std::atomic _isLoadingStateFromDisk{false}; + std::atomic _newStateIsReady{false}; + std::unique_ptr _shaderProgram; @@ -88,8 +97,11 @@ private: void computeSequenceEndTime(); bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); + void extractTriggerTimesFromFileNames(); + void readNewState(const std::string& FILEPATH); + inline bool isWithinSequenceInterval(const double CURRENT_TIME); - inline void updateActiveStateIndex(const double CURRENT_TIME); + inline void updateActiveTriggerTimeIndex(const double CURRENT_TIME); }; } // namespace openspace From f442dd4f7c5f24fcf19b1d9793b999f9fee4de09 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Fri, 22 Sep 2017 04:30:44 +0200 Subject: [PATCH 13/47] Add functionality for coloring lines by different quantities --- .../renderablefieldlinessequence.cpp | 233 +++++++++++++++--- .../rendering/renderablefieldlinessequence.h | 55 +++-- .../shaders/fieldlinessequence_vs.glsl | 46 +++- .../util/fieldlinesstate.cpp | 13 + .../fieldlinessequence/util/fieldlinesstate.h | 30 ++- 5 files changed, 303 insertions(+), 74 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index bbf6fec31f..8a79820554 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -29,9 +29,9 @@ #include #include - #include #include +#include using std::string; @@ -44,6 +44,8 @@ namespace { const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] // ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- // + const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files + const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be paths to .txt files const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // @@ -51,8 +53,26 @@ namespace { const char* VALUE_INPUT_FILE_TYPE_JSON = "json"; const char* VALUE_INPUT_FILE_TYPE_OSFLS = "osfls"; - static const openspace::properties::Property::PropertyInfo LineColorInfo = { - "lineColor", "Line Color", "Color of lines." + static const openspace::properties::Property::PropertyInfo ColorMethodInfo = { + "colorMethod", "Color Method", "Color lines uniformly or using color tables based on extra variables like e.g. temperature or particle density." + }; + static const openspace::properties::Property::PropertyInfo ColorQuantityInfo = { + "colorQuantity", "Quantity to Color By", "Quantity/variable used to color lines if the \"By Quantity\" color method is selected." + }; + static const openspace::properties::Property::PropertyInfo ColorQuantityMinInfo = { + "colorQuantityMin", "ColorTable Min Value", "Value to map to the lowest end of the color table." + }; + static const openspace::properties::Property::PropertyInfo ColorQuantityMaxInfo = { + "colorQuantityMax", "ColorTable Max Value", "Value to map to the highest end of the color table." + }; + static const openspace::properties::Property::PropertyInfo ColorTablePathInfo = { + "colorTablePath", "Path to Color Table", "Color Table/Transfer Function to use for \"By Quantity\" coloring." + }; + static const openspace::properties::Property::PropertyInfo ColorUniformInfo = { + "uniform", "Uniform Line Color", "The uniform color of lines shown when \"Color Method\" is set to \"Uniform\"." + }; + static const openspace::properties::Property::PropertyInfo FlowColorInfo = { + "color", "Color", "Color of particles." }; static const openspace::properties::Property::PropertyInfo EnableFlowInfo = { "Enable", "ON/OFF", @@ -70,29 +90,37 @@ namespace { static const openspace::properties::Property::PropertyInfo FlowSpeedInfo = { "speed", "Speed", "Speed of the flow." }; - static const openspace::properties::Property::PropertyInfo FlowColorInfo = { - "color", "Color", "Color of particles." - }; + + enum ColorMethod { UNIFORM = 0, BY_QUANTITY }; } // namespace namespace openspace { RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) : Renderable(dictionary), - _lineColor(LineColorInfo, glm::vec4(0.75f, 0.5f, 0.0f, 0.5f), glm::vec4(0.f), glm::vec4(1.f)), - _flowGroup({ "Flow" }), + _colorGroup({ "Color" }), + _colorMethod(ColorMethodInfo, properties::OptionProperty::DisplayType::Radio), + _colorQuantity(ColorQuantityInfo, properties::OptionProperty::DisplayType::Dropdown), + _colorQuantityMin(ColorQuantityMinInfo), + _colorQuantityMax(ColorQuantityMaxInfo), + _colorTablePath(ColorTablePathInfo), + _colorUniform(ColorUniformInfo, glm::vec4(0.75f, 0.5f, 0.0f, 0.5f), + glm::vec4(0.f), glm::vec4(1.f)), + _flowColor(FlowColorInfo, glm::vec4(0.8f, 0.7f, 0.0f, 0.6f), + glm::vec4(0.f), glm::vec4(1.f)), _flowEnabled(EnableFlowInfo, true), - _flowReversed(ReverseFlowInfo, false), + _flowGroup({ "Flow" }), _flowParticleSize(ParticleSizeInfo, 5, 0, 500), _flowParticleSpacing(ParticleSpacingInfo, 60, 0, 500), - _flowSpeed(FlowSpeedInfo, 20, 0, 1000), - _flowColor(FlowColorInfo, glm::vec4(0.8f, 0.7f, 0.0f, 0.6f), - glm::vec4(0.f), glm::vec4(1.f)) { + _flowReversed(ReverseFlowInfo, false), + _flowSpeed(FlowSpeedInfo, 20, 0, 1000) { + + // Set the default color table, just in case user defined paths are corrupt! + _transferFunction = std::make_shared(absPath(_colorTablePaths[0])); if(!extractInfoFromDictionary(dictionary)) { _sourceFileType = INVALID; } - } void RenderableFieldlinesSequence::initialize() { @@ -133,16 +161,27 @@ void RenderableFieldlinesSequence::initialize() { break; } - // No need to store source paths in memory if their states are already in RAM! + // At this point there's at least one state loaded into memory! + // No need to store source paths in memory if they are already in RAM! if (!_isLoadingStatesAtRuntime) { _sourceFiles.clear(); } computeSequenceEndTime(); - // HANDLE PROPERTIES - addProperty(_lineColor); + // --------------------- HANDLE PROPERTIES --------------------- // + // Add Property Groups + addPropertySubOwner(_colorGroup); addPropertySubOwner(_flowGroup); + + // Add Properties to the groups + _colorGroup.addProperty(_colorMethod); + _colorGroup.addProperty(_colorQuantity); + _colorGroup.addProperty(_colorQuantityMin); + _colorGroup.addProperty(_colorQuantityMax); + _colorGroup.addProperty(_colorTablePath); + _colorGroup.addProperty(_colorUniform); + _flowGroup.addProperty(_flowEnabled); _flowGroup.addProperty(_flowReversed); _flowGroup.addProperty(_flowColor); @@ -150,6 +189,52 @@ void RenderableFieldlinesSequence::initialize() { _flowGroup.addProperty(_flowParticleSpacing); _flowGroup.addProperty(_flowSpeed); + // Add Options to OptionProperties + _colorMethod.addOption(ColorMethod::UNIFORM, "Uniform"); + _colorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity"); + + // Add option for each extra quantity. We assume that there are just as many names to + // extra variables as there are extra variables. We also assume that all states in the + // given sequence have the same extra variables! + const size_t N_EXTRA_QUANTITIES = _states[0].nExtraVariables(); + auto EXTRA_VARIABLE_NAMES_VEC = _states[0].extraVariableNames(); + for (size_t i = 0; i < N_EXTRA_QUANTITIES; ++i) { + _colorQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]); + } + // Each quantity should have its own color table and color table range, no more, no less + _colorTablePaths.resize(N_EXTRA_QUANTITIES, _colorTablePaths.back()); + _colorTableRanges.resize(N_EXTRA_QUANTITIES, _colorTableRanges.back()); + + // Add Property Callback Functions + _colorQuantity.onChange([this] { + LDEBUG("CHANGED COLORING QUANTITY"); + _shouldUpdateColorBuffer = true; + _colorQuantityMin = std::to_string(_colorTableRanges[_colorQuantity].x); + _colorQuantityMax = std::to_string(_colorTableRanges[_colorQuantity].y); + _activeColorTable = &_colorTablePaths[_colorQuantity]; + _colorTablePath = *_activeColorTable; + }); + + _colorTablePath.onChange([this] { + // TOGGLE ACTIVE SHADER PROGRAM + _transferFunction->setPath(_colorTablePath); + *_activeColorTable = _colorTablePath; + }); + + _colorQuantityMin.onChange([this] { + LDEBUG("CHANGED MIN VALUE"); + // TODO CHECK IF VALID NUMBER! + // _updateTransferFunctionMin = true; + _colorTableRanges[_colorQuantity].x = std::stof(_colorQuantityMin); + }); + + _colorQuantityMax.onChange([this] { + LDEBUG("CHANGED MAX VALUE"); + // TODO CHECK IF VALID NUMBER! + // _updateTransferFunctionMin = true; + _colorTableRanges[_colorQuantity].y = std::stof(_colorQuantityMax); + }); + // Setup shader program _shaderProgram = OsEng.renderEngine().buildRenderProgram( "FieldlinesSequence", @@ -165,6 +250,7 @@ void RenderableFieldlinesSequence::initialize() { //------------------ Initialize OpenGL VBOs and VAOs-------------------------------// glGenVertexArrays(1, &_vertexArrayObject); glGenBuffers(1, &_vertexPositionBuffer); + glGenBuffers(1, &_vertexColorBuffer); } void RenderableFieldlinesSequence::deinitialize() { @@ -194,6 +280,7 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& if (_activeTriggerTimeIndex != -1) { _shaderProgram->activate(); + // Calculate Model View MatrixProjection const glm::dmat4 ROT_MAT = glm::dmat4(data.modelTransform.rotation); // const glm::mat4 SCALE_TRANSFORM = glm::mat4(1.0); // TODO remove if no use const glm::dmat4 MODEL_MAT = @@ -205,7 +292,19 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& _shaderProgram->setUniform("modelViewProjection", data.camera.sgctInternal.projectionMatrix() * glm::mat4(MODEL_VIEW_MAT)); - _shaderProgram->setUniform("lineColor", _lineColor); + + _shaderProgram->setUniform("colorMethod", _colorMethod); + _shaderProgram->setUniform("lineColor", _colorUniform); + + if (_colorMethod == ColorMethod::BY_QUANTITY) { + ghoul::opengl::TextureUnit textureUnit; + textureUnit.activate(); + _transferFunction->bind(); // Calls update internally + _shaderProgram->setUniform("colorTable", textureUnit); + _shaderProgram->setUniform("colorTableRange", + _colorTableRanges[_colorQuantity]); + } + // Flow/Particles _shaderProgram->setUniform("usingParticles", _flowEnabled); _shaderProgram->setUniform("flowColor", _flowColor); @@ -238,8 +337,8 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { // Check if current time in OpenSpace is within sequence interval if (isWithinSequenceInterval(CURRENT_TIME)) { const int NEXT_IDX = _activeTriggerTimeIndex + 1; - if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval - || CURRENT_TIME < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state + if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval + || CURRENT_TIME < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state || (NEXT_IDX < _nStates && CURRENT_TIME >= _startTimes[NEXT_IDX])) { // true => OpenSpace has stepped forward to a time represented by another state updateActiveTriggerTimeIndex(CURRENT_TIME); @@ -275,30 +374,27 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { _states[0] = std::move(_newState); } - glBindVertexArray(_vertexArrayObject); - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + updateVertexPositionBuffer(); - const std::vector& VERTEX_POS_VEC = - _states[_activeStateIndex].vertexPositions(); - - glBufferData(GL_ARRAY_BUFFER, VERTEX_POS_VEC.size() * sizeof(glm::vec3), - &VERTEX_POS_VEC.front(), GL_STATIC_DRAW); - - glEnableVertexAttribArray(_vertAttrVertexPos); - glVertexAttribPointer(_vertAttrVertexPos, 3, GL_FLOAT, GL_FALSE, 0, 0); - - // UNBIND - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); + if (_states[_activeStateIndex].nExtraVariables() > 0) { + _shouldUpdateColorBuffer = true; + } else { + _colorMethod = ColorMethod::UNIFORM; + } // Everything is set and ready for rendering! - _needsUpdate = false; + _needsUpdate = false; _newStateIsReady = false; } + + if (_shouldUpdateColorBuffer) { + updateVertexColorBuffer(); + _shouldUpdateColorBuffer = false; + } } } -inline bool RenderableFieldlinesSequence::isWithinSequenceInterval(const double CURRENT_TIME) { +inline bool RenderableFieldlinesSequence::isWithinSequenceInterval(const double CURRENT_TIME) const { return (CURRENT_TIME >= _startTimes[0]) && (CURRENT_TIME < _sequenceEndTime); } @@ -327,6 +423,47 @@ void RenderableFieldlinesSequence::readNewState(const std::string& FILEPATH) { _isLoadingStateFromDisk = false; } +// Unbind buffers and arrays +inline void unbindGL() { + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); +} + +void RenderableFieldlinesSequence::updateVertexPositionBuffer() { + glBindVertexArray(_vertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + + const std::vector& VERTEX_POS_VEC = + _states[_activeStateIndex].vertexPositions(); + + glBufferData(GL_ARRAY_BUFFER, VERTEX_POS_VEC.size() * sizeof(glm::vec3), + &VERTEX_POS_VEC.front(), GL_STATIC_DRAW); + + glEnableVertexAttribArray(_VA_POSITION); + glVertexAttribPointer(_VA_POSITION, 3, GL_FLOAT, GL_FALSE, 0, 0); + + unbindGL(); +} + +void RenderableFieldlinesSequence::updateVertexColorBuffer() { + glBindVertexArray(_vertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER, _vertexColorBuffer); + + bool isSuccessful; + const std::vector& QUANTITY_VEC = + _states[_activeStateIndex].extraVariable(_colorQuantity, isSuccessful); + + if (isSuccessful) { + glBufferData(GL_ARRAY_BUFFER, QUANTITY_VEC.size() * sizeof(float), + &QUANTITY_VEC.front(), GL_STATIC_DRAW); + + glEnableVertexAttribArray(_VA_COLOR); + glVertexAttribPointer(_VA_COLOR, 1, GL_FLOAT, GL_FALSE, 0, 0); + + unbindGL(); + } +} + bool RenderableFieldlinesSequence::extractInfoFromDictionary( const ghoul::Dictionary& dictionary) { @@ -390,6 +527,32 @@ bool RenderableFieldlinesSequence::extractInfoFromDictionary( return false; } + // Extract optional info from modfile + ghoul::Dictionary colorTablesPathsDictionary; + if (dictionary.getValue(KEY_COLOR_TABLE_PATHS, colorTablesPathsDictionary)) { + const size_t N_PROVIDED_PATHS = colorTablesPathsDictionary.size(); + if (N_PROVIDED_PATHS > 0) { + // Clear the default! It is already specified in the transferFunction + _colorTablePaths.clear(); + for (size_t i = 1; i <= N_PROVIDED_PATHS; ++i) { + _colorTablePaths.push_back( + colorTablesPathsDictionary.value( std::to_string(i) ) ); + } + } + } + + ghoul::Dictionary colorTablesRangesDictionary; + if (dictionary.getValue(KEY_COLOR_TABLE_RANGES, colorTablesRangesDictionary)) { + const size_t N_PROVIDED_RANGES = colorTablesRangesDictionary.size(); + for (size_t i = 1; i <= N_PROVIDED_RANGES; ++i) { + _colorTableRanges.push_back( + colorTablesRangesDictionary.value( std::to_string(i) ) ); + } + } else { + _colorTableRanges.push_back(glm::vec2(0, 1)); + } + + // Extract info specific to each inputType switch (_sourceFileType) { case CDF: LERROR(name << "CDF NOT YET IMPLEMENTED!"); diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 455c4f1f9a..06aff5c4e2 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -27,8 +27,12 @@ #include +#include #include +#include #include +#include + #include @@ -59,8 +63,9 @@ private: int _activeStateIndex = -1; int _activeTriggerTimeIndex = -1; bool _isLoadingStatesAtRuntime = true; // False => loading osfls at runtime - bool _mustLoadNewStateFromDisk = false; // If still in same state as previous frame == false + bool _mustLoadNewStateFromDisk = false; bool _needsUpdate = false; // If still in same state as previous frame == false + bool _shouldUpdateColorBuffer = false; FieldlinesState _newState; size_t _nStates = 0; double _sequenceEndTime; @@ -69,39 +74,53 @@ private: std::atomic _isLoadingStateFromDisk{false}; std::atomic _newStateIsReady{false}; - + std::shared_ptr _transferFunction; // Transfer funtion (tf) std::unique_ptr _shaderProgram; + std::string* _activeColorTable; + std::vector _colorTablePaths {"${OPENSPACE_DATA}/colortables/kroyw.txt"}; // Default in case user doesn't specify otherwise + std::vector _sourceFiles; // Stored in RAM if files are loaded at runtime, else emptied after initialization std::vector _startTimes; std::vector _states; - std::vector _sourceFiles; // Stored in RAM if files are loaded at runtime, else emptied after initialization + std::vector _colorTableRanges; // Values represents min & max values represented in the color table GLuint _vertexArrayObject = 0; GLuint _vertexPositionBuffer = 0; + GLuint _vertexColorBuffer = 0; // THESE MUST CORRESPOND TO THE SHADER PROGRAM // TODO: THIS CAN BE DETERMINED BY ASKING THE SHADER PROGRAM TOO - GLuint _vertAttrVertexPos = 0; + const GLuint _VA_POSITION = 0; + const GLuint _VA_COLOR = 1; // ----------------------------- Properties ----------------------------- - properties::Vec4Property _lineColor; // Uniform Field Line Color + properties::PropertyOwner _colorGroup; // Group to hold the color properties + properties::OptionProperty _colorMethod; // Uniform/transfer function/topology? + properties::OptionProperty _colorQuantity; // Index of the extra variable to color lines by + properties::StringProperty _colorQuantityMin; // Color table/transfer function min + properties::StringProperty _colorQuantityMax; // Color table/transfer function max + properties::StringProperty _colorTablePath; // Color table/transfer function for "By Quantity" coloring + properties::Vec4Property _colorUniform; // Uniform Field Line Color - properties::PropertyOwner _flowGroup; - properties::BoolProperty _flowEnabled; // Toggle flow [ON/OFF] - properties::BoolProperty _flowReversed; // Toggle flow direction [FORWARDS/BACKWARDS] - properties::IntProperty _flowParticleSize; // Size of simulated flow particles - properties::IntProperty _flowParticleSpacing; // Size of simulated flow particles - properties::IntProperty _flowSpeed; // Speed of simulated flow - properties::Vec4Property _flowColor; // Simulated particles' color + properties::Vec4Property _flowColor; // Simulated particles' color + properties::BoolProperty _flowEnabled; // Toggle flow [ON/OFF] + properties::PropertyOwner _flowGroup; // Gropu to hold the flow/particle properties + properties::IntProperty _flowParticleSize; // Size of simulated flow particles + properties::IntProperty _flowParticleSpacing; // Size of simulated flow particles + properties::BoolProperty _flowReversed; // Toggle flow direction [FORWARDS/BACKWARDS] + properties::IntProperty _flowSpeed; // Speed of simulated flow - void computeSequenceEndTime(); - bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); - void extractTriggerTimesFromFileNames(); - void readNewState(const std::string& FILEPATH); + void computeSequenceEndTime(); + bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); + void extractTriggerTimesFromFileNames(); + void readNewState(const std::string& FILEPATH); - inline bool isWithinSequenceInterval(const double CURRENT_TIME); - inline void updateActiveTriggerTimeIndex(const double CURRENT_TIME); + inline bool isWithinSequenceInterval(const double CURRENT_TIME) const; + + void updateActiveTriggerTimeIndex(const double CURRENT_TIME); + void updateVertexPositionBuffer(); + void updateVertexColorBuffer(); }; } // namespace openspace diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl index 906953c7b7..de0bd246a6 100644 --- a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl @@ -24,21 +24,42 @@ #version __CONTEXT__ -uniform mat4 modelViewProjection; -uniform bool usingParticles; -uniform double time; -uniform int particleSize; -uniform int particleSpeed; -uniform int particleSpacing; -uniform vec4 flowColor; -uniform vec4 lineColor; +#include "PowerScaling/powerScaling_vs.hglsl" -layout(location = 0) in vec3 in_position; // in meters +// General Uniforms that's always needed +uniform vec4 lineColor; +uniform mat4 modelViewProjection; + +// Uniforms needed to color by quantity +uniform int colorMethod; +uniform sampler1D colorTable; +uniform vec2 colorTableRange; + +// Uniforms needed for Particle Flow +uniform vec4 flowColor; +uniform int particleSize; +uniform int particleSpeed; +uniform int particleSpacing; +uniform double time; +uniform bool usingParticles; + +layout(location = 0) in vec3 in_position; // Should be provided in meters +layout(location = 1) in float in_color_scalar; // The extra value used to color lines. Location must correspond to _VA_COLOR in renderablefieldlinessequence.h + +// These should correspond to the enum 'ColorMethod' in renderablefieldlinesequence.cpp +const int UNIFORM_COLOR = 0; +const int COLOR_BY_QUANTITY = 1; out vec4 vs_color; out float vs_depth; -#include "PowerScaling/powerScaling_vs.hglsl" + +vec4 getTransferFunctionColor() { + // Remap the color scalar to a [0,1] range + const float LOOK_UP_VAL = (in_color_scalar - colorTableRange.x) / + (colorTableRange.y - colorTableRange.x); + return texture(colorTable, LOOK_UP_VAL); +} bool isPartOfParticle(const double TIME, const int VERTEX_ID, const int PARTICLE_SIZE, const int PARTICLE_SPEED, const int PARTICLE_SPACING) { @@ -59,6 +80,11 @@ void main() { vs_color = lineColor; } + if (colorMethod == COLOR_BY_QUANTITY) { + const vec4 QUANTITY_COLOR = getTransferFunctionColor(); + vs_color = vec4(QUANTITY_COLOR.xyz, vs_color.a * QUANTITY_COLOR.a); + } + vec4 position_in_meters = vec4(in_position, 1); vec4 positionClipSpace = modelViewProjection * position_in_meters; gl_Position = z_normalization(positionClipSpace); diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index 6336736d58..89aa58ba06 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -108,4 +108,17 @@ bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) return true; } +// Returns one of the extra variable vectors, _extraVariables[INDEX]. +// If INDEX is out of scope an empty vector is returned and the referenced bool will be false. +const vector& FieldlinesState::extraVariable(const size_t INDEX, + bool& isSuccessful) const { + if (INDEX < _extraVariables.size()) { + isSuccessful = true; + return _extraVariables[INDEX]; + } + isSuccessful = false; + // return empty vector which goes out of scope hence unusable! + return std::vector(); +} + } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index e2145df1cf..b4088ccefd 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -31,6 +31,8 @@ #include #include +using std::vector; + namespace openspace { class FieldlinesState { @@ -46,23 +48,29 @@ public: bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE); - // Getters - double triggerTime() { return _triggerTime; } - Model model() { return _model; } - const std::vector& vertexPositions() { return _vertexPositions; } - const std::vector& lineStart() { return _lineStart; } - const std::vector& lineCount() { return _lineCount; } + // ------------------------------GETTERS-----------------------------------------// + const vector>& extraVariables() const { return _extraVariables; } + const vector& extraVariableNames() const { return _extraVariableNames; } + const vector& lineCount() const { return _lineCount; } + const vector& lineStart() const { return _lineStart; } + size_t nExtraVariables() const { return _extraVariables.size(); } + Model model() const { return _model; } + double triggerTime() const { return _triggerTime; } + const vector& vertexPositions() const { return _vertexPositions; } + + // Special getter. Returns extraVariables[INDEX]. + const vector& extraVariable(const size_t INDEX, bool& isSuccesful) const; private: bool _isMorphable = false; double _triggerTime = -1.0; Model _model; - std::vector _vertexPositions; - std::vector _lineStart; - std::vector _lineCount; - std::vector> _extraVariables; - std::vector _extraVariableNames; + vector _vertexPositions; + vector _lineStart; + vector _lineCount; + vector> _extraVariables; + vector _extraVariableNames; // TODO: Maybe introduce a vector containing seed point indices }; From f521939370666d9e14f1d2d67b42321c50bd81fd Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Fri, 22 Sep 2017 04:53:24 +0200 Subject: [PATCH 14/47] Always refer to the extra quantities used for coloring lines as quantities, never variables. --- .../renderablefieldlinessequence.cpp | 20 +++++++++---------- .../rendering/renderablefieldlinessequence.h | 2 +- .../util/fieldlinesstate.cpp | 20 +++++++++---------- .../fieldlinessequence/util/fieldlinesstate.h | 14 ++++++------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 8a79820554..a7e5135302 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -54,10 +54,10 @@ namespace { const char* VALUE_INPUT_FILE_TYPE_OSFLS = "osfls"; static const openspace::properties::Property::PropertyInfo ColorMethodInfo = { - "colorMethod", "Color Method", "Color lines uniformly or using color tables based on extra variables like e.g. temperature or particle density." + "colorMethod", "Color Method", "Color lines uniformly or using color tables based on extra quantities like e.g. temperature or particle density." }; static const openspace::properties::Property::PropertyInfo ColorQuantityInfo = { - "colorQuantity", "Quantity to Color By", "Quantity/variable used to color lines if the \"By Quantity\" color method is selected." + "colorQuantity", "Quantity to Color By", "Quantity used to color lines if the \"By Quantity\" color method is selected." }; static const openspace::properties::Property::PropertyInfo ColorQuantityMinInfo = { "colorQuantityMin", "ColorTable Min Value", "Value to map to the lowest end of the color table." @@ -194,10 +194,10 @@ void RenderableFieldlinesSequence::initialize() { _colorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity"); // Add option for each extra quantity. We assume that there are just as many names to - // extra variables as there are extra variables. We also assume that all states in the - // given sequence have the same extra variables! - const size_t N_EXTRA_QUANTITIES = _states[0].nExtraVariables(); - auto EXTRA_VARIABLE_NAMES_VEC = _states[0].extraVariableNames(); + // extra quantities as there are extra quantities. We also assume that all states in + // the given sequence have the same extra quantities! + const size_t N_EXTRA_QUANTITIES = _states[0].nExtraQuantities(); + auto EXTRA_VARIABLE_NAMES_VEC = _states[0].extraQuantityNames(); for (size_t i = 0; i < N_EXTRA_QUANTITIES; ++i) { _colorQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]); } @@ -337,8 +337,8 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { // Check if current time in OpenSpace is within sequence interval if (isWithinSequenceInterval(CURRENT_TIME)) { const int NEXT_IDX = _activeTriggerTimeIndex + 1; - if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval - || CURRENT_TIME < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state + if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval + || CURRENT_TIME < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state || (NEXT_IDX < _nStates && CURRENT_TIME >= _startTimes[NEXT_IDX])) { // true => OpenSpace has stepped forward to a time represented by another state updateActiveTriggerTimeIndex(CURRENT_TIME); @@ -376,7 +376,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { updateVertexPositionBuffer(); - if (_states[_activeStateIndex].nExtraVariables() > 0) { + if (_states[_activeStateIndex].nExtraQuantities() > 0) { _shouldUpdateColorBuffer = true; } else { _colorMethod = ColorMethod::UNIFORM; @@ -451,7 +451,7 @@ void RenderableFieldlinesSequence::updateVertexColorBuffer() { bool isSuccessful; const std::vector& QUANTITY_VEC = - _states[_activeStateIndex].extraVariable(_colorQuantity, isSuccessful); + _states[_activeStateIndex].extraQuantity(_colorQuantity, isSuccessful); if (isSuccessful) { glBufferData(GL_ARRAY_BUFFER, QUANTITY_VEC.size() * sizeof(float), diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 06aff5c4e2..a18a207bba 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -96,7 +96,7 @@ private: // ----------------------------- Properties ----------------------------- properties::PropertyOwner _colorGroup; // Group to hold the color properties properties::OptionProperty _colorMethod; // Uniform/transfer function/topology? - properties::OptionProperty _colorQuantity; // Index of the extra variable to color lines by + properties::OptionProperty _colorQuantity; // Index of the extra quantity to color lines by properties::StringProperty _colorQuantityMin; // Color table/transfer function min properties::StringProperty _colorQuantityMax; // Color table/transfer function max properties::StringProperty _colorTablePath; // Color table/transfer function for "By Quantity" coloring diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index 89aa58ba06..73ee392d5b 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -75,21 +75,21 @@ bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) _lineStart.resize(numLines); _lineCount.resize(numLines); _vertexPositions.resize(numPoints); - _extraVariables.resize(numExtras); - _extraVariableNames.reserve(numExtras); + _extraQuantities.resize(numExtras); + _extraQuantityNames.reserve(numExtras); // Read vertex position data ifs.read( reinterpret_cast(_lineStart.data()), sizeof(GLint)*numLines); ifs.read( reinterpret_cast(_lineCount.data()), sizeof(GLsizei)*numLines); ifs.read( reinterpret_cast(_vertexPositions.data()), sizeof(glm::vec3)*numPoints); - // Read all extra variables - for (std::vector& vec : _extraVariables) { + // Read all extra quantities + for (std::vector& vec : _extraQuantities) { vec.resize(numPoints); ifs.read( reinterpret_cast(vec.data()), sizeof(float) * numPoints); } - // Read all extra variables' names. Stored as multiple c-strings + // Read all extra quantities' names. Stored as multiple c-strings std::string allNamesInOne; char* s = new char[byteSizeAllNames]; ifs.read(s, byteSizeAllNames); @@ -102,19 +102,19 @@ bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) endOfVarName -= offset; std::string varName = allNamesInOne.substr(offset, endOfVarName); offset += varName.size() + 1; - _extraVariableNames.push_back(varName); + _extraQuantityNames.push_back(varName); } return true; } -// Returns one of the extra variable vectors, _extraVariables[INDEX]. +// Returns one of the extra quantity vectors, _extraQuantities[INDEX]. // If INDEX is out of scope an empty vector is returned and the referenced bool will be false. -const vector& FieldlinesState::extraVariable(const size_t INDEX, +const vector& FieldlinesState::extraQuantity(const size_t INDEX, bool& isSuccessful) const { - if (INDEX < _extraVariables.size()) { + if (INDEX < _extraQuantities.size()) { isSuccessful = true; - return _extraVariables[INDEX]; + return _extraQuantities[INDEX]; } isSuccessful = false; // return empty vector which goes out of scope hence unusable! diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index b4088ccefd..4819897d0f 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -49,17 +49,17 @@ public: bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE); // ------------------------------GETTERS-----------------------------------------// - const vector>& extraVariables() const { return _extraVariables; } - const vector& extraVariableNames() const { return _extraVariableNames; } + const vector>& extraQuantities() const { return _extraQuantities; } + const vector& extraQuantityNames() const { return _extraQuantityNames; } const vector& lineCount() const { return _lineCount; } const vector& lineStart() const { return _lineStart; } - size_t nExtraVariables() const { return _extraVariables.size(); } + size_t nExtraQuantities() const { return _extraQuantities.size(); } Model model() const { return _model; } double triggerTime() const { return _triggerTime; } const vector& vertexPositions() const { return _vertexPositions; } - // Special getter. Returns extraVariables[INDEX]. - const vector& extraVariable(const size_t INDEX, bool& isSuccesful) const; + // Special getter. Returns extraQuantities[INDEX]. + const vector& extraQuantity(const size_t INDEX, bool& isSuccesful) const; private: bool _isMorphable = false; @@ -69,8 +69,8 @@ private: vector _vertexPositions; vector _lineStart; vector _lineCount; - vector> _extraVariables; - vector _extraVariableNames; + vector> _extraQuantities; + vector _extraQuantityNames; // TODO: Maybe introduce a vector containing seed point indices }; From 3c9d48315c02e2c59da09e85fcadb6ab0dba7c65 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Fri, 22 Sep 2017 06:27:44 +0200 Subject: [PATCH 15/47] Add trigger properties. One for focus the camera on parent and one for time jump to start of sequence! --- .../renderablefieldlinessequence.cpp | 37 ++++++++++++++++++- .../rendering/renderablefieldlinessequence.h | 33 ++++++++++------- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index a7e5135302..25c98b57cb 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -25,8 +25,11 @@ #include #include +#include #include +#include #include +#include #include #include @@ -90,6 +93,12 @@ namespace { static const openspace::properties::Property::PropertyInfo FlowSpeedInfo = { "speed", "Speed", "Speed of the flow." }; + static const openspace::properties::Property::PropertyInfo OriginButtonInfo = { + "focusCameraOnParent", "Focus Camera", "Focus camera on parent." + }; + static const openspace::properties::Property::PropertyInfo TimeJumpButtonInfo = { + "timeJumpToStart", "Jump to Start Time", "Performs a time jump to the start of the sequence." + }; enum ColorMethod { UNIFORM = 0, BY_QUANTITY }; } // namespace @@ -113,7 +122,9 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona _flowParticleSize(ParticleSizeInfo, 5, 0, 500), _flowParticleSpacing(ParticleSpacingInfo, 60, 0, 500), _flowReversed(ReverseFlowInfo, false), - _flowSpeed(FlowSpeedInfo, 20, 0, 1000) { + _flowSpeed(FlowSpeedInfo, 20, 0, 1000), + _focusOnOriginBtn(OriginButtonInfo), + _jumpToStartBtn(TimeJumpButtonInfo) { // Set the default color table, just in case user defined paths are corrupt! _transferFunction = std::make_shared(absPath(_colorTablePaths[0])); @@ -174,6 +185,10 @@ void RenderableFieldlinesSequence::initialize() { addPropertySubOwner(_colorGroup); addPropertySubOwner(_flowGroup); + // Add non-grouped properties + addProperty(_focusOnOriginBtn); + addProperty(_jumpToStartBtn); + // Add Properties to the groups _colorGroup.addProperty(_colorMethod); _colorGroup.addProperty(_colorQuantity); @@ -235,6 +250,25 @@ void RenderableFieldlinesSequence::initialize() { _colorTableRanges[_colorQuantity].y = std::stof(_colorQuantityMax); }); + _focusOnOriginBtn.onChange([this] { + LDEBUG("SET FOCUS NODE TO PARENT"); + // TODO CHECK IF VALID NUMBER! + // _updateTransferFunctionMin = true; + //OsEng.navigationHandler().setFocusNode(); + SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(_name); + if (!node) { + LWARNING("Could not find a node in scenegraph called '" << _name << "'"); + return; + } + OsEng.navigationHandler().setFocusNode(node->parent()); + OsEng.navigationHandler().resetCameraDirection(); + }); + + _jumpToStartBtn.onChange([this] { + LDEBUG("Jump in time to start of sequence!"); + OsEng.timeManager().time().setTime(_startTimes[0]); + }); + // Setup shader program _shaderProgram = OsEng.renderEngine().buildRenderProgram( "FieldlinesSequence", @@ -469,6 +503,7 @@ bool RenderableFieldlinesSequence::extractInfoFromDictionary( string name; dictionary.getValue(SceneGraphNode::KeyName, name); + _name = name; name += ": "; // ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- // diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index a18a207bba..773022754c 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,8 @@ private: INVALID }; + std::string _name; + int _activeStateIndex = -1; int _activeTriggerTimeIndex = -1; bool _isLoadingStatesAtRuntime = true; // False => loading osfls at runtime @@ -94,22 +97,24 @@ private: const GLuint _VA_COLOR = 1; // ----------------------------- Properties ----------------------------- - properties::PropertyOwner _colorGroup; // Group to hold the color properties - properties::OptionProperty _colorMethod; // Uniform/transfer function/topology? - properties::OptionProperty _colorQuantity; // Index of the extra quantity to color lines by - properties::StringProperty _colorQuantityMin; // Color table/transfer function min - properties::StringProperty _colorQuantityMax; // Color table/transfer function max - properties::StringProperty _colorTablePath; // Color table/transfer function for "By Quantity" coloring - properties::Vec4Property _colorUniform; // Uniform Field Line Color + properties::PropertyOwner _colorGroup; // Group to hold the color properties + properties::OptionProperty _colorMethod; // Uniform/transfer function/topology? + properties::OptionProperty _colorQuantity; // Index of the extra quantity to color lines by + properties::StringProperty _colorQuantityMin; // Color table/transfer function min + properties::StringProperty _colorQuantityMax; // Color table/transfer function max + properties::StringProperty _colorTablePath; // Color table/transfer function for "By Quantity" coloring + properties::Vec4Property _colorUniform; // Uniform Field Line Color - properties::Vec4Property _flowColor; // Simulated particles' color - properties::BoolProperty _flowEnabled; // Toggle flow [ON/OFF] - properties::PropertyOwner _flowGroup; // Gropu to hold the flow/particle properties - properties::IntProperty _flowParticleSize; // Size of simulated flow particles - properties::IntProperty _flowParticleSpacing; // Size of simulated flow particles - properties::BoolProperty _flowReversed; // Toggle flow direction [FORWARDS/BACKWARDS] - properties::IntProperty _flowSpeed; // Speed of simulated flow + properties::Vec4Property _flowColor; // Simulated particles' color + properties::BoolProperty _flowEnabled; // Toggle flow [ON/OFF] + properties::PropertyOwner _flowGroup; // Gropu to hold the flow/particle properties + properties::IntProperty _flowParticleSize; // Size of simulated flow particles + properties::IntProperty _flowParticleSpacing; // Size of simulated flow particles + properties::BoolProperty _flowReversed; // Toggle flow direction [FORWARDS/BACKWARDS] + properties::IntProperty _flowSpeed; // Speed of simulated flow + properties::TriggerProperty _focusOnOriginBtn; // Button which sets camera focus to parent node of the renderable + properties::TriggerProperty _jumpToStartBtn; // Button which executes a time jump to start of sequence void computeSequenceEndTime(); bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); From dc597f59c4730396782cb4b1c1358670bfc6050c Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 4 Oct 2017 03:34:23 +0200 Subject: [PATCH 16/47] REFACTOR: split renderablefieldlinessequence.cpp into two files and give propertiy variables a 'p' as prefix --- modules/fieldlinessequence/CMakeLists.txt | 2 + .../renderablefieldlinessequence.cpp | 427 +--------------- .../rendering/renderablefieldlinessequence.h | 58 ++- .../renderablefieldlinessequencesetup.cpp | 460 ++++++++++++++++++ modules/fieldlinessequence/util/commons.h | 49 ++ .../util/fieldlinesstate.cpp | 39 +- .../fieldlinessequence/util/fieldlinesstate.h | 26 +- 7 files changed, 597 insertions(+), 464 deletions(-) create mode 100644 modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp create mode 100644 modules/fieldlinessequence/util/commons.h diff --git a/modules/fieldlinessequence/CMakeLists.txt b/modules/fieldlinessequence/CMakeLists.txt index 33a0b287ec..1fb4a1da1e 100644 --- a/modules/fieldlinessequence/CMakeLists.txt +++ b/modules/fieldlinessequence/CMakeLists.txt @@ -27,11 +27,13 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequence.h ${CMAKE_CURRENT_SOURCE_DIR}/util/fieldlinesstate.h + ${CMAKE_CURRENT_SOURCE_DIR}/util/commons.h ) source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequence.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequencesetup.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/fieldlinesstate.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 25c98b57cb..0e23cb81ed 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -25,268 +25,19 @@ #include #include -#include #include -#include -#include -#include #include -#include #include #include -using std::string; namespace { std::string _loggerCat = "RenderableFieldlinesSequence"; - - // ----- KEYS POSSIBLE IN MODFILE. EXPECTED DATA TYPE OF VALUE IN [BRACKETS] ----- // - // ---------------------------- MANDATORY MODFILE KEYS ---------------------------- // - const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] - const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] - - // ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- // - const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files - const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be paths to .txt files - const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM - - // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // - const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf"; - const char* VALUE_INPUT_FILE_TYPE_JSON = "json"; - const char* VALUE_INPUT_FILE_TYPE_OSFLS = "osfls"; - - static const openspace::properties::Property::PropertyInfo ColorMethodInfo = { - "colorMethod", "Color Method", "Color lines uniformly or using color tables based on extra quantities like e.g. temperature or particle density." - }; - static const openspace::properties::Property::PropertyInfo ColorQuantityInfo = { - "colorQuantity", "Quantity to Color By", "Quantity used to color lines if the \"By Quantity\" color method is selected." - }; - static const openspace::properties::Property::PropertyInfo ColorQuantityMinInfo = { - "colorQuantityMin", "ColorTable Min Value", "Value to map to the lowest end of the color table." - }; - static const openspace::properties::Property::PropertyInfo ColorQuantityMaxInfo = { - "colorQuantityMax", "ColorTable Max Value", "Value to map to the highest end of the color table." - }; - static const openspace::properties::Property::PropertyInfo ColorTablePathInfo = { - "colorTablePath", "Path to Color Table", "Color Table/Transfer Function to use for \"By Quantity\" coloring." - }; - static const openspace::properties::Property::PropertyInfo ColorUniformInfo = { - "uniform", "Uniform Line Color", "The uniform color of lines shown when \"Color Method\" is set to \"Uniform\"." - }; - static const openspace::properties::Property::PropertyInfo FlowColorInfo = { - "color", "Color", "Color of particles." - }; - static const openspace::properties::Property::PropertyInfo EnableFlowInfo = { - "Enable", "ON/OFF", - "Toggles the rendering of moving particles along the lines. Can e.g. illustrate magnetic flow." - }; - static const openspace::properties::Property::PropertyInfo ReverseFlowInfo = { - "reversed", "Reversed Flow", "Toggle to make the flow move in the opposite direction." - }; - static const openspace::properties::Property::PropertyInfo ParticleSizeInfo = { - "particleSize", "Particle Size", "Size of the particles." - }; - static const openspace::properties::Property::PropertyInfo ParticleSpacingInfo = { - "particleSpacing", "Particle Spacing", "Spacing inbetween particles." - }; - static const openspace::properties::Property::PropertyInfo FlowSpeedInfo = { - "speed", "Speed", "Speed of the flow." - }; - static const openspace::properties::Property::PropertyInfo OriginButtonInfo = { - "focusCameraOnParent", "Focus Camera", "Focus camera on parent." - }; - static const openspace::properties::Property::PropertyInfo TimeJumpButtonInfo = { - "timeJumpToStart", "Jump to Start Time", "Performs a time jump to the start of the sequence." - }; - - enum ColorMethod { UNIFORM = 0, BY_QUANTITY }; } // namespace namespace openspace { -RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) - : Renderable(dictionary), - _colorGroup({ "Color" }), - _colorMethod(ColorMethodInfo, properties::OptionProperty::DisplayType::Radio), - _colorQuantity(ColorQuantityInfo, properties::OptionProperty::DisplayType::Dropdown), - _colorQuantityMin(ColorQuantityMinInfo), - _colorQuantityMax(ColorQuantityMaxInfo), - _colorTablePath(ColorTablePathInfo), - _colorUniform(ColorUniformInfo, glm::vec4(0.75f, 0.5f, 0.0f, 0.5f), - glm::vec4(0.f), glm::vec4(1.f)), - _flowColor(FlowColorInfo, glm::vec4(0.8f, 0.7f, 0.0f, 0.6f), - glm::vec4(0.f), glm::vec4(1.f)), - _flowEnabled(EnableFlowInfo, true), - _flowGroup({ "Flow" }), - _flowParticleSize(ParticleSizeInfo, 5, 0, 500), - _flowParticleSpacing(ParticleSpacingInfo, 60, 0, 500), - _flowReversed(ReverseFlowInfo, false), - _flowSpeed(FlowSpeedInfo, 20, 0, 1000), - _focusOnOriginBtn(OriginButtonInfo), - _jumpToStartBtn(TimeJumpButtonInfo) { - - // Set the default color table, just in case user defined paths are corrupt! - _transferFunction = std::make_shared(absPath(_colorTablePaths[0])); - - if(!extractInfoFromDictionary(dictionary)) { - _sourceFileType = INVALID; - } -} - -void RenderableFieldlinesSequence::initialize() { - switch (_sourceFileType) { - case CDF: - LERROR("CDF NOT YET IMPLEMENTED!"); - break; - case JSON: - LERROR("JSON NOT YET IMPLEMENTED!"); - break; - case OSFLS: - if (_isLoadingStatesAtRuntime) { - extractTriggerTimesFromFileNames(); - FieldlinesState newState; - bool loadedSuccessfully = newState.loadStateFromOsfls(_sourceFiles[0]); - if (loadedSuccessfully) { - _states.push_back(newState); - _nStates = _startTimes.size(); - _activeStateIndex = 0; - } else { - LERROR("The provided .osfls files seem to be corrupt!"); - _sourceFileType = INVALID; - } - } else { - // Load states into RAM! - for (string filePath : _sourceFiles) { - FieldlinesState newState; - bool loadedSuccessfully = newState.loadStateFromOsfls(filePath); - if (loadedSuccessfully) { - _states.push_back(newState); - _startTimes.push_back(newState.triggerTime()); - _nStates++; - } - } - } - break; - default: - break; - } - - // At this point there's at least one state loaded into memory! - // No need to store source paths in memory if they are already in RAM! - if (!_isLoadingStatesAtRuntime) { - _sourceFiles.clear(); - } - - computeSequenceEndTime(); - - // --------------------- HANDLE PROPERTIES --------------------- // - // Add Property Groups - addPropertySubOwner(_colorGroup); - addPropertySubOwner(_flowGroup); - - // Add non-grouped properties - addProperty(_focusOnOriginBtn); - addProperty(_jumpToStartBtn); - - // Add Properties to the groups - _colorGroup.addProperty(_colorMethod); - _colorGroup.addProperty(_colorQuantity); - _colorGroup.addProperty(_colorQuantityMin); - _colorGroup.addProperty(_colorQuantityMax); - _colorGroup.addProperty(_colorTablePath); - _colorGroup.addProperty(_colorUniform); - - _flowGroup.addProperty(_flowEnabled); - _flowGroup.addProperty(_flowReversed); - _flowGroup.addProperty(_flowColor); - _flowGroup.addProperty(_flowParticleSize); - _flowGroup.addProperty(_flowParticleSpacing); - _flowGroup.addProperty(_flowSpeed); - - // Add Options to OptionProperties - _colorMethod.addOption(ColorMethod::UNIFORM, "Uniform"); - _colorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity"); - - // Add option for each extra quantity. We assume that there are just as many names to - // extra quantities as there are extra quantities. We also assume that all states in - // the given sequence have the same extra quantities! - const size_t N_EXTRA_QUANTITIES = _states[0].nExtraQuantities(); - auto EXTRA_VARIABLE_NAMES_VEC = _states[0].extraQuantityNames(); - for (size_t i = 0; i < N_EXTRA_QUANTITIES; ++i) { - _colorQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]); - } - // Each quantity should have its own color table and color table range, no more, no less - _colorTablePaths.resize(N_EXTRA_QUANTITIES, _colorTablePaths.back()); - _colorTableRanges.resize(N_EXTRA_QUANTITIES, _colorTableRanges.back()); - - // Add Property Callback Functions - _colorQuantity.onChange([this] { - LDEBUG("CHANGED COLORING QUANTITY"); - _shouldUpdateColorBuffer = true; - _colorQuantityMin = std::to_string(_colorTableRanges[_colorQuantity].x); - _colorQuantityMax = std::to_string(_colorTableRanges[_colorQuantity].y); - _activeColorTable = &_colorTablePaths[_colorQuantity]; - _colorTablePath = *_activeColorTable; - }); - - _colorTablePath.onChange([this] { - // TOGGLE ACTIVE SHADER PROGRAM - _transferFunction->setPath(_colorTablePath); - *_activeColorTable = _colorTablePath; - }); - - _colorQuantityMin.onChange([this] { - LDEBUG("CHANGED MIN VALUE"); - // TODO CHECK IF VALID NUMBER! - // _updateTransferFunctionMin = true; - _colorTableRanges[_colorQuantity].x = std::stof(_colorQuantityMin); - }); - - _colorQuantityMax.onChange([this] { - LDEBUG("CHANGED MAX VALUE"); - // TODO CHECK IF VALID NUMBER! - // _updateTransferFunctionMin = true; - _colorTableRanges[_colorQuantity].y = std::stof(_colorQuantityMax); - }); - - _focusOnOriginBtn.onChange([this] { - LDEBUG("SET FOCUS NODE TO PARENT"); - // TODO CHECK IF VALID NUMBER! - // _updateTransferFunctionMin = true; - //OsEng.navigationHandler().setFocusNode(); - SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(_name); - if (!node) { - LWARNING("Could not find a node in scenegraph called '" << _name << "'"); - return; - } - OsEng.navigationHandler().setFocusNode(node->parent()); - OsEng.navigationHandler().resetCameraDirection(); - }); - - _jumpToStartBtn.onChange([this] { - LDEBUG("Jump in time to start of sequence!"); - OsEng.timeManager().time().setTime(_startTimes[0]); - }); - - // Setup shader program - _shaderProgram = OsEng.renderEngine().buildRenderProgram( - "FieldlinesSequence", - "${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_vs.glsl", - "${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_fs.glsl" - ); - - if (!_shaderProgram) { - LERROR("Shader program failed initialization!"); - _sourceFileType = INVALID; - } - - //------------------ Initialize OpenGL VBOs and VAOs-------------------------------// - glGenVertexArrays(1, &_vertexArrayObject); - glGenBuffers(1, &_vertexPositionBuffer); - glGenBuffers(1, &_vertexColorBuffer); -} - void RenderableFieldlinesSequence::deinitialize() { glDeleteVertexArrays(1, &_vertexArrayObject); _vertexArrayObject = 0; @@ -294,6 +45,9 @@ void RenderableFieldlinesSequence::deinitialize() { glDeleteBuffers(1, &_vertexPositionBuffer); _vertexPositionBuffer = 0; + glDeleteBuffers(1, &_vertexColorBuffer); + _vertexColorBuffer = 0; + RenderEngine& renderEngine = OsEng.renderEngine(); if (_shaderProgram) { renderEngine.removeRenderProgram(_shaderProgram); @@ -326,26 +80,25 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& _shaderProgram->setUniform("modelViewProjection", data.camera.sgctInternal.projectionMatrix() * glm::mat4(MODEL_VIEW_MAT)); + _shaderProgram->setUniform("colorMethod", _pColorMethod); + _shaderProgram->setUniform("lineColor", _pColorUniform); - _shaderProgram->setUniform("colorMethod", _colorMethod); - _shaderProgram->setUniform("lineColor", _colorUniform); - - if (_colorMethod == ColorMethod::BY_QUANTITY) { + if (_pColorMethod == ColorMethod::BY_QUANTITY) { ghoul::opengl::TextureUnit textureUnit; textureUnit.activate(); _transferFunction->bind(); // Calls update internally _shaderProgram->setUniform("colorTable", textureUnit); _shaderProgram->setUniform("colorTableRange", - _colorTableRanges[_colorQuantity]); + _colorTableRanges[_pColorQuantity]); } // Flow/Particles - _shaderProgram->setUniform("usingParticles", _flowEnabled); - _shaderProgram->setUniform("flowColor", _flowColor); - _shaderProgram->setUniform("particleSize", _flowParticleSize); - _shaderProgram->setUniform("particleSpeed", _flowSpeed); - _shaderProgram->setUniform("particleSpacing", _flowParticleSpacing); - _shaderProgram->setUniform("time", OsEng.runTime() * (_flowReversed ? -1 : 1)); + _shaderProgram->setUniform("flowColor", _pFlowColor); + _shaderProgram->setUniform("usingParticles", _pFlowEnabled); + _shaderProgram->setUniform("particleSize", _pFlowParticleSize); + _shaderProgram->setUniform("particleSpacing", _pFlowParticleSpacing); + _shaderProgram->setUniform("particleSpeed", _pFlowSpeed); + _shaderProgram->setUniform("time", OsEng.runTime() * (_pFlowReversed ? -1 : 1)); glBindVertexArray(_vertexArrayObject); glMultiDrawArrays( @@ -377,7 +130,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { updateActiveTriggerTimeIndex(CURRENT_TIME); - if (_isLoadingStatesAtRuntime) { + if (_loadingStatesDynamically) { _mustLoadNewStateFromDisk = true; } else { _needsUpdate = true; @@ -404,7 +157,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { } if (_needsUpdate || _newStateIsReady) { - if (_isLoadingStatesAtRuntime) { + if (_loadingStatesDynamically) { _states[0] = std::move(_newState); } @@ -413,7 +166,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { if (_states[_activeStateIndex].nExtraQuantities() > 0) { _shouldUpdateColorBuffer = true; } else { - _colorMethod = ColorMethod::UNIFORM; + _pColorMethod = ColorMethod::UNIFORM; } // Everything is set and ready for rendering! @@ -437,7 +190,8 @@ void RenderableFieldlinesSequence::updateActiveTriggerTimeIndex(const double CUR auto iter = std::upper_bound(_startTimes.begin(), _startTimes.end(), CURRENT_TIME); if (iter != _startTimes.end()) { if ( iter != _startTimes.begin()) { - _activeTriggerTimeIndex = std::distance(_startTimes.begin(), iter) - 1; + _activeTriggerTimeIndex = + static_cast(std::distance(_startTimes.begin(), iter)) - 1; } else { _activeTriggerTimeIndex = 0; } @@ -485,7 +239,7 @@ void RenderableFieldlinesSequence::updateVertexColorBuffer() { bool isSuccessful; const std::vector& QUANTITY_VEC = - _states[_activeStateIndex].extraQuantity(_colorQuantity, isSuccessful); + _states[_activeStateIndex].extraQuantity(_pColorQuantity, isSuccessful); if (isSuccessful) { glBufferData(GL_ARRAY_BUFFER, QUANTITY_VEC.size() * sizeof(float), @@ -498,150 +252,7 @@ void RenderableFieldlinesSequence::updateVertexColorBuffer() { } } -bool RenderableFieldlinesSequence::extractInfoFromDictionary( - const ghoul::Dictionary& dictionary) { - string name; - dictionary.getValue(SceneGraphNode::KeyName, name); - _name = name; - name += ": "; - // ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- // - string inputFileTypeValue; - if(!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileTypeValue)) { - LERROR(name << "The field " << string(KEY_INPUT_FILE_TYPE) << " is missing!"); - return false; - } else { - std::transform(inputFileTypeValue.begin(), inputFileTypeValue.end(), - inputFileTypeValue.begin(), ::tolower); - // Verify that the input type is correct - if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_CDF) { - _sourceFileType = CDF; - } else if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_JSON) { - _sourceFileType = JSON; - } else if (inputFileTypeValue == VALUE_INPUT_FILE_TYPE_OSFLS) { - _sourceFileType = OSFLS; - } else { - LERROR(name << inputFileTypeValue << " is not a recognised " - << KEY_INPUT_FILE_TYPE); - _sourceFileType = INVALID; - return false; - } - } - - string sourceFolderPath; - if(!dictionary.getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) { - LERROR(name << "The field " << string(KEY_SOURCE_FOLDER) << " is missing!"); - return false; - } - - // Ensure that the source folder exists and then extract - // the files with the same extension as - ghoul::filesystem::Directory sourceFolder(sourceFolderPath); - if (FileSys.directoryExists(sourceFolder)) { - // Extract all file paths from the provided folder (Non-recursively! Sorted!) - _sourceFiles = sourceFolder.readFiles(ghoul::Boolean::No, ghoul::Boolean::Yes); - - // Remove all files that don't have as extension - _sourceFiles.erase(std::remove_if(_sourceFiles.begin(), _sourceFiles.end(), - [inputFileTypeValue] (string str) { - const size_t EXT_LENGTH = inputFileTypeValue.length(); - string sub = str.substr(str.length() - EXT_LENGTH, EXT_LENGTH); - std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower); - return sub != inputFileTypeValue; - }), _sourceFiles.end()); - // Ensure that there are available and valid source files left - if (_sourceFiles.empty()) { - LERROR(name << sourceFolderPath << " contains no ." << inputFileTypeValue - << " files!"); - return false; - } - } else { - LERROR(name << "FieldlinesSequence" << sourceFolderPath - << " is not a valid directory!"); - return false; - } - - // Extract optional info from modfile - ghoul::Dictionary colorTablesPathsDictionary; - if (dictionary.getValue(KEY_COLOR_TABLE_PATHS, colorTablesPathsDictionary)) { - const size_t N_PROVIDED_PATHS = colorTablesPathsDictionary.size(); - if (N_PROVIDED_PATHS > 0) { - // Clear the default! It is already specified in the transferFunction - _colorTablePaths.clear(); - for (size_t i = 1; i <= N_PROVIDED_PATHS; ++i) { - _colorTablePaths.push_back( - colorTablesPathsDictionary.value( std::to_string(i) ) ); - } - } - } - - ghoul::Dictionary colorTablesRangesDictionary; - if (dictionary.getValue(KEY_COLOR_TABLE_RANGES, colorTablesRangesDictionary)) { - const size_t N_PROVIDED_RANGES = colorTablesRangesDictionary.size(); - for (size_t i = 1; i <= N_PROVIDED_RANGES; ++i) { - _colorTableRanges.push_back( - colorTablesRangesDictionary.value( std::to_string(i) ) ); - } - } else { - _colorTableRanges.push_back(glm::vec2(0, 1)); - } - - // Extract info specific to each inputType - switch (_sourceFileType) { - case CDF: - LERROR(name << "CDF NOT YET IMPLEMENTED!"); - break; - case JSON: - LERROR(name << "JSON NOT YET IMPLEMENTED!"); - break; - case OSFLS: { - bool shouldLoadInRealtime = false; - if (dictionary.getValue(KEY_OSLFS_LOAD_AT_RUNTIME, shouldLoadInRealtime)) { - _isLoadingStatesAtRuntime = shouldLoadInRealtime; - } else { - LWARNING(name << KEY_OSLFS_LOAD_AT_RUNTIME << - " isn't specified! OSFLS files will be loaded during runtime!"); - } - } break; - default: - break; - } -} - -// Calculate expected end time. -void RenderableFieldlinesSequence::computeSequenceEndTime() { - if (_nStates > 1) { - const double LAST_TRIGGER_TIME = _startTimes[_nStates - 1]; - const double SEQUENCE_DURATION = LAST_TRIGGER_TIME - _startTimes[0]; - const double AVERAGE_STATE_DURATION = SEQUENCE_DURATION / (static_cast(_nStates) - 1.0); - _sequenceEndTime = LAST_TRIGGER_TIME + AVERAGE_STATE_DURATION; - } else { - // If there's just one state it should never disappear! - _sequenceEndTime = DBL_MAX; - } -} - -// Extract J2000 time from file names -// Requires files to be named as such: 'YYYY-MM-DDTHH-MM-SS-XXX.osfls' -void RenderableFieldlinesSequence::extractTriggerTimesFromFileNames() { - const size_t FILENAME_SIZE = 23; // number of characters in filename (excluding '.osfls') - const size_t EXT_SIZE = 6; // size(".osfls") - - for (const std::string& FILEPATH : _sourceFiles) { - const size_t STR_LENGTH = FILEPATH.size(); - // Extract the filename from the path (without extension) - std::string timeString = FILEPATH.substr(STR_LENGTH - FILENAME_SIZE - EXT_SIZE, - FILENAME_SIZE - 1); - // Ensure the separators are correct - timeString.replace( 4, 1, "-"); - timeString.replace( 7, 1, "-"); - timeString.replace(13, 1, ":"); - timeString.replace(16, 1, ":"); - timeString.replace(19, 1, "."); - const double TRIGGER_TIME = Time::convertTime(timeString); - _startTimes.push_back(TRIGGER_TIME); - } -} } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 773022754c..e138591c90 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -34,13 +34,14 @@ #include #include - #include #include namespace openspace { +class ghoul::Dictionary; + class RenderableFieldlinesSequence : public Renderable { public: RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary); @@ -54,6 +55,11 @@ public: void render(const RenderData& data, RendererTasks& rendererTask) override; void update(const UpdateData& data) override; private: + enum ColorMethod : int { + UNIFORM = 0, + BY_QUANTITY + }; + enum SourceFileType : int { CDF = 0, JSON, @@ -63,12 +69,12 @@ private: std::string _name; - int _activeStateIndex = -1; - int _activeTriggerTimeIndex = -1; - bool _isLoadingStatesAtRuntime = true; // False => loading osfls at runtime - bool _mustLoadNewStateFromDisk = false; - bool _needsUpdate = false; // If still in same state as previous frame == false - bool _shouldUpdateColorBuffer = false; + int _activeStateIndex = -1; + int _activeTriggerTimeIndex = -1; + bool _loadingStatesDynamically = false; // False => loading osfls files into RAM in initializing step + bool _mustLoadNewStateFromDisk = false; + bool _needsUpdate = false; // If still in same state as previous frame == false + bool _shouldUpdateColorBuffer = false; FieldlinesState _newState; size_t _nStates = 0; double _sequenceEndTime; @@ -77,10 +83,10 @@ private: std::atomic _isLoadingStateFromDisk{false}; std::atomic _newStateIsReady{false}; + std::unique_ptr _dictionary; std::shared_ptr _transferFunction; // Transfer funtion (tf) std::unique_ptr _shaderProgram; - std::string* _activeColorTable; std::vector _colorTablePaths {"${OPENSPACE_DATA}/colortables/kroyw.txt"}; // Default in case user doesn't specify otherwise std::vector _sourceFiles; // Stored in RAM if files are loaded at runtime, else emptied after initialization std::vector _startTimes; @@ -97,24 +103,24 @@ private: const GLuint _VA_COLOR = 1; // ----------------------------- Properties ----------------------------- - properties::PropertyOwner _colorGroup; // Group to hold the color properties - properties::OptionProperty _colorMethod; // Uniform/transfer function/topology? - properties::OptionProperty _colorQuantity; // Index of the extra quantity to color lines by - properties::StringProperty _colorQuantityMin; // Color table/transfer function min - properties::StringProperty _colorQuantityMax; // Color table/transfer function max - properties::StringProperty _colorTablePath; // Color table/transfer function for "By Quantity" coloring - properties::Vec4Property _colorUniform; // Uniform Field Line Color + properties::PropertyOwner _pColorGroup; // Group to hold the color properties + properties::OptionProperty _pColorMethod; // Uniform/transfer function/topology? + properties::OptionProperty _pColorQuantity; // Index of the extra quantity to color lines by + properties::StringProperty _pColorQuantityMin; // Color table/transfer function min + properties::StringProperty _pColorQuantityMax; // Color table/transfer function max + properties::StringProperty _pColorTablePath; // Color table/transfer function for "By Quantity" coloring + properties::Vec4Property _pColorUniform; // Uniform Field Line Color - properties::Vec4Property _flowColor; // Simulated particles' color - properties::BoolProperty _flowEnabled; // Toggle flow [ON/OFF] - properties::PropertyOwner _flowGroup; // Gropu to hold the flow/particle properties - properties::IntProperty _flowParticleSize; // Size of simulated flow particles - properties::IntProperty _flowParticleSpacing; // Size of simulated flow particles - properties::BoolProperty _flowReversed; // Toggle flow direction [FORWARDS/BACKWARDS] - properties::IntProperty _flowSpeed; // Speed of simulated flow + properties::Vec4Property _pFlowColor; // Simulated particles' color + properties::BoolProperty _pFlowEnabled; // Toggle flow [ON/OFF] + properties::PropertyOwner _pFlowGroup; // Group to hold the flow/particle properties + properties::IntProperty _pFlowParticleSize; // Size of simulated flow particles + properties::IntProperty _pFlowParticleSpacing; // Size of simulated flow particles + properties::BoolProperty _pFlowReversed; // Toggle flow direction [FORWARDS/BACKWARDS] + properties::IntProperty _pFlowSpeed; // Speed of simulated flow - properties::TriggerProperty _focusOnOriginBtn; // Button which sets camera focus to parent node of the renderable - properties::TriggerProperty _jumpToStartBtn; // Button which executes a time jump to start of sequence + properties::TriggerProperty _pFocusOnOriginBtn; // Button which sets camera focus to parent node of the renderable + properties::TriggerProperty _pJumpToStartBtn; // Button which executes a time jump to start of sequence void computeSequenceEndTime(); bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); @@ -126,6 +132,10 @@ private: void updateActiveTriggerTimeIndex(const double CURRENT_TIME); void updateVertexPositionBuffer(); void updateVertexColorBuffer(); + void updateVertexMaskingBuffer(); + + void definePropertyCallbackFunctions(); + void setupProperties(); }; } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp new file mode 100644 index 0000000000..d2811e5ef4 --- /dev/null +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -0,0 +1,460 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace { + std::string _loggerCat = "RenderableFieldlinesSequence"; + + // ----- KEYS POSSIBLE IN MODFILE. EXPECTED DATA TYPE OF VALUE IN [BRACKETS] ----- // + // ---------------------------- MANDATORY MODFILE KEYS ---------------------------- // + const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] + const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] + + // ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- // + const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files + const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers + const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM + + // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // + const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf"; + const char* VALUE_INPUT_FILE_TYPE_JSON = "json"; + const char* VALUE_INPUT_FILE_TYPE_OSFLS = "osfls"; + + // --------------------------------- Property Info -------------------------------- // + static const openspace::properties::Property::PropertyInfo ColorMethodInfo = { + "colorMethod", "Color Method", "Color lines uniformly or using color tables based on extra quantities like e.g. temperature or particle density." + }; + static const openspace::properties::Property::PropertyInfo ColorQuantityInfo = { + "colorQuantity", "Quantity to Color By", "Quantity used to color lines if the \"By Quantity\" color method is selected." + }; + static const openspace::properties::Property::PropertyInfo ColorQuantityMinInfo = { + "colorQuantityMin", "ColorTable Min Value", "Value to map to the lowest end of the color table." + }; + static const openspace::properties::Property::PropertyInfo ColorQuantityMaxInfo = { + "colorQuantityMax", "ColorTable Max Value", "Value to map to the highest end of the color table." + }; + static const openspace::properties::Property::PropertyInfo ColorTablePathInfo = { + "colorTablePath", "Path to Color Table", "Color Table/Transfer Function to use for \"By Quantity\" coloring." + }; + static const openspace::properties::Property::PropertyInfo ColorUniformInfo = { + "uniform", "Uniform Line Color", "The uniform color of lines shown when \"Color Method\" is set to \"Uniform\"." + }; + static const openspace::properties::Property::PropertyInfo FlowColorInfo = { + "color", "Color", "Color of particles." + }; + static const openspace::properties::Property::PropertyInfo FlowEnabledInfo = { + "flowEnabled", "Flow Direction", + "Toggles the rendering of moving particles along the lines. Can e.g. illustrate magnetic flow." + }; + static const openspace::properties::Property::PropertyInfo FlowReversedInfo = { + "reversed", "Reversed Flow", "Toggle to make the flow move in the opposite direction." + }; + static const openspace::properties::Property::PropertyInfo FlowParticleSizeInfo = { + "particleSize", "Particle Size", "Size of the particles." + }; + static const openspace::properties::Property::PropertyInfo FlowParticleSpacingInfo = { + "particleSpacing", "Particle Spacing", "Spacing inbetween particles." + }; + static const openspace::properties::Property::PropertyInfo FlowSpeedInfo = { + "speed", "Speed", "Speed of the flow." + }; + static const openspace::properties::Property::PropertyInfo OriginButtonInfo = { + "focusCameraOnParent", "Focus Camera", "Focus camera on parent." + }; + static const openspace::properties::Property::PropertyInfo TimeJumpButtonInfo = { + "timeJumpToStart", "Jump to Start Of Sequence", "Performs a time jump to the start of the sequence." + }; + + float stringToFloat(const std::string INPUT, const float BACKUP_VALUE = 0.f) { + float tmp; + try { + tmp = std::stof(INPUT); + } catch (const std::invalid_argument& ia) { + LWARNING("Invalid argument: " << ia.what() << ". '" << INPUT << + "' is NOT a valid number!"); + return BACKUP_VALUE; + } + return tmp; + } +} // namespace + +namespace openspace { + +RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) + : Renderable(dictionary), + _pColorGroup({ "Color" }), + _pColorMethod(ColorMethodInfo, properties::OptionProperty::DisplayType::Radio), + _pColorQuantity(ColorQuantityInfo, properties::OptionProperty::DisplayType::Dropdown), + _pColorQuantityMin(ColorQuantityMinInfo), + _pColorQuantityMax(ColorQuantityMaxInfo), + _pColorTablePath(ColorTablePathInfo), + _pColorUniform(ColorUniformInfo, glm::vec4(0.75f, 0.5f, 0.0f, 0.5f), + glm::vec4(0.f), glm::vec4(1.f)), + _pFlowColor(FlowColorInfo, glm::vec4(0.8f, 0.7f, 0.0f, 0.6f), + glm::vec4(0.f), glm::vec4(1.f)), + _pFlowEnabled(FlowEnabledInfo, true), + _pFlowGroup({ "Flow" }), + _pFlowParticleSize(FlowParticleSizeInfo, 5, 0, 500), + _pFlowParticleSpacing(FlowParticleSpacingInfo, 60, 0, 500), + _pFlowReversed(FlowReversedInfo, false), + _pFlowSpeed(FlowSpeedInfo, 20, 0, 1000), + _pFocusOnOriginBtn(OriginButtonInfo), + _pJumpToStartBtn(TimeJumpButtonInfo) { + + _dictionary = std::make_unique(dictionary); + // Set the default color table, just in case user defined paths are corrupt! + _transferFunction = std::make_shared(absPath(_colorTablePaths[0])); +} + +void RenderableFieldlinesSequence::initialize() { + LINFO("RenderableFieldlinesSequence::initialize()"); + + if (!extractInfoFromDictionary(*_dictionary)) { + _sourceFileType = SourceFileType::INVALID; + } + + // dictionary is no longer necessary as everything is extracted + _dictionary.reset(); + + switch (_sourceFileType) { + case CDF: + LERROR("CDF NOT YET IMPLEMENTED!"); return; + break; + case JSON: + LERROR("JSON NOT YET IMPLEMENTED!"); return; + break; + case OSFLS: + if (_loadingStatesDynamically) { + extractTriggerTimesFromFileNames(); + FieldlinesState newState; + bool loadedSuccessfully = newState.loadStateFromOsfls(_sourceFiles[0]); + if (loadedSuccessfully) { + _states.push_back(newState); + _nStates = _startTimes.size(); + _activeStateIndex = 0; + } else { + LERROR("The provided .osfls files seem to be corrupt!"); + _sourceFileType = SourceFileType::INVALID; + } + } else { + // Load states into RAM! + for (std::string filePath : _sourceFiles) { + FieldlinesState newState; + bool loadedSuccessfully = newState.loadStateFromOsfls(filePath); + if (loadedSuccessfully) { + _states.push_back(newState); + _startTimes.push_back(newState.triggerTime()); + _nStates++; + } + } + } + break; + default: + return; + } + + // At this point there's at least one state loaded into memory! + // No need to store source paths in memory if they are already in RAM! + if (!_loadingStatesDynamically) { + _sourceFiles.clear(); + } + + computeSequenceEndTime(); + + setupProperties(); + + // Setup shader program + _shaderProgram = OsEng.renderEngine().buildRenderProgram( + "FieldlinesSequence", + "${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_vs.glsl", + "${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_fs.glsl" + ); + + if (!_shaderProgram) { + LERROR("Shader program failed initialization!"); + _sourceFileType = SourceFileType::INVALID; + } + + //------------------ Initialize OpenGL VBOs and VAOs-------------------------------// + glGenVertexArrays(1, &_vertexArrayObject); + glGenBuffers(1, &_vertexPositionBuffer); + glGenBuffers(1, &_vertexColorBuffer); +} + +bool RenderableFieldlinesSequence::extractInfoFromDictionary( + const ghoul::Dictionary& dictionary) { + + std::string name; + dictionary.getValue(SceneGraphNode::KeyName, name); + _name = name; + name += ": "; + + // ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- // + std::string inputFileTypeString; + if (!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileTypeString)) { + LERROR(name << "The field " << std::string(KEY_INPUT_FILE_TYPE) << " is missing!"); + return false; + } else { + std::transform(inputFileTypeString.begin(), inputFileTypeString.end(), + inputFileTypeString.begin(), ::tolower); + // Verify that the input type is correct + if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_CDF) { + _sourceFileType = CDF; + } else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_JSON) { + _sourceFileType = JSON; + } else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_OSFLS) { + _sourceFileType = OSFLS; + } else { + LERROR(name << inputFileTypeString << " is not a recognised " + << KEY_INPUT_FILE_TYPE); + _sourceFileType = INVALID; + return false; + } + } + + std::string sourceFolderPath; + if (!dictionary.getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) { + LERROR(name << "The field " << std::string(KEY_SOURCE_FOLDER) << " is missing!"); + return false; + } + + // Ensure that the source folder exists and then extract + // the files with the same extension as + ghoul::filesystem::Directory sourceFolder(sourceFolderPath); + if (FileSys.directoryExists(sourceFolder)) { + // Extract all file paths from the provided folder (Non-recursively! Sorted!) + _sourceFiles = sourceFolder.readFiles(ghoul::Boolean::No, ghoul::Boolean::Yes); + + // Remove all files that don't have as extension + _sourceFiles.erase(std::remove_if(_sourceFiles.begin(), _sourceFiles.end(), + [inputFileTypeString](std::string str) { + const size_t EXT_LENGTH = inputFileTypeString.length(); + std::string sub = str.substr(str.length() - EXT_LENGTH, EXT_LENGTH); + std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower); + return sub != inputFileTypeString; + }), _sourceFiles.end()); + // Ensure that there are available and valid source files left + if (_sourceFiles.empty()) { + LERROR(name << sourceFolderPath << " contains no ." << inputFileTypeString + << " files!"); + return false; + } + } else { + LERROR(name << "FieldlinesSequence" << sourceFolderPath + << " is not a valid directory!"); + return false; + } + + // ------------------- EXTRACT OPTIONAL VALUES FROM DICTIONARY ------------------- // + ghoul::Dictionary colorTablesPathsDictionary; + if (dictionary.getValue(KEY_COLOR_TABLE_PATHS, colorTablesPathsDictionary)) { + const size_t N_PROVIDED_PATHS = colorTablesPathsDictionary.size(); + if (N_PROVIDED_PATHS > 0) { + // Clear the default! It is already specified in the transferFunction + _colorTablePaths.clear(); + for (size_t i = 1; i <= N_PROVIDED_PATHS; ++i) { + _colorTablePaths.push_back( + colorTablesPathsDictionary.value(std::to_string(i))); + } + } + } + + ghoul::Dictionary colorTablesRangesDictionary; + if (dictionary.getValue(KEY_COLOR_TABLE_RANGES, colorTablesRangesDictionary)) { + const size_t N_PROVIDED_RANGES = colorTablesRangesDictionary.size(); + for (size_t i = 1; i <= N_PROVIDED_RANGES; ++i) { + _colorTableRanges.push_back( + colorTablesRangesDictionary.value(std::to_string(i))); + } + } else { + _colorTableRanges.push_back(glm::vec2(0, 1)); + } + + // Extract info specific to each inputType + switch (_sourceFileType) { + case CDF: + LERROR(name << "CDF NOT YET IMPLEMENTED!"); + break; + case JSON: + LERROR(name << "JSON NOT YET IMPLEMENTED!"); + break; + case OSFLS: { + bool shouldLoadInRealtime = false; + if (dictionary.getValue(KEY_OSLFS_LOAD_AT_RUNTIME, shouldLoadInRealtime)) { + _loadingStatesDynamically = shouldLoadInRealtime; + } else { + LWARNING(name << KEY_OSLFS_LOAD_AT_RUNTIME << + " isn't specified! States from OSFLS files will be stored in RAM!"); + } + } break; + default: + break; + } + + return true; +} + +void RenderableFieldlinesSequence::setupProperties() { + // -------------- Add non-grouped properties (enablers and buttons) -------------- // + addProperty(_pFlowEnabled); + addProperty(_pFocusOnOriginBtn); + addProperty(_pJumpToStartBtn); + + // ----------------------------- Add Property Groups ----------------------------- // + addPropertySubOwner(_pColorGroup); + addPropertySubOwner(_pFlowGroup); + + // ------------------------- Add Properties to the groups ------------------------- // + _pColorGroup.addProperty(_pColorMethod); + _pColorGroup.addProperty(_pColorQuantity); + _pColorGroup.addProperty(_pColorQuantityMin); + _pColorGroup.addProperty(_pColorQuantityMax); + _pColorGroup.addProperty(_pColorTablePath); + _pColorGroup.addProperty(_pColorUniform); + + _pFlowGroup.addProperty(_pFlowReversed); + _pFlowGroup.addProperty(_pFlowColor); + _pFlowGroup.addProperty(_pFlowParticleSize); + _pFlowGroup.addProperty(_pFlowParticleSpacing); + _pFlowGroup.addProperty(_pFlowSpeed); + + // ----------------------- Add Options to OptionProperties ----------------------- // + _pColorMethod.addOption(ColorMethod::UNIFORM, "Uniform"); + _pColorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity"); + + /* Add option for each extra quantity. We assume that there are just as many names to + extra quantities as there are extra quantities. We also assume that all states in + the given sequence have the same extra quantities! */ + const size_t N_EXTRA_QUANTITIES = _states[0].nExtraQuantities(); + auto EXTRA_VARIABLE_NAMES_VEC = _states[0].extraQuantityNames(); + for (int i = 0; i < N_EXTRA_QUANTITIES; ++i) { + _pColorQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]); + } + // Each quantity should have its own color table and color table range, no more, no less + _colorTablePaths.resize(N_EXTRA_QUANTITIES, _colorTablePaths.back()); + _colorTableRanges.resize(N_EXTRA_QUANTITIES, _colorTableRanges.back()); + + definePropertyCallbackFunctions(); + + // Set defaults + _pColorQuantity = 0; + _pColorQuantityMin = std::to_string(_colorTableRanges[_pColorQuantity].x); + _pColorQuantityMax = std::to_string(_colorTableRanges[_pColorQuantity].y); + _pColorTablePath = _colorTablePaths[_pColorQuantity]; + +} + +void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { + // Add Property Callback Functions + _pColorQuantity.onChange([this] { + LDEBUG("CHANGED COLORING QUANTITY"); + _shouldUpdateColorBuffer = true; + _pColorQuantityMin = std::to_string(_colorTableRanges[_pColorQuantity].x); + _pColorQuantityMax = std::to_string(_colorTableRanges[_pColorQuantity].y); + _pColorTablePath = _colorTablePaths[_pColorQuantity]; + }); + + _pColorTablePath.onChange([this] { + _transferFunction->setPath(_pColorTablePath); + _colorTablePaths[_pColorQuantity] = _pColorTablePath; + }); + + _pColorQuantityMin.onChange([this] { + LDEBUG("CHANGED MIN VALUE"); + float f = stringToFloat(_pColorQuantityMin, _colorTableRanges[_pColorQuantity].x); + _pColorQuantityMin = std::to_string(f); + _colorTableRanges[_pColorQuantity].x = f; + }); + + _pColorQuantityMax.onChange([this] { + LDEBUG("CHANGED MAX VALUE"); + float f = stringToFloat(_pColorQuantityMax, _colorTableRanges[_pColorQuantity].y); + _pColorQuantityMax = std::to_string(f); + _colorTableRanges[_pColorQuantity].y = f; + }); + + _pFocusOnOriginBtn.onChange([this] { + LDEBUG("SET FOCUS NODE TO PARENT"); + SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(_name); + if (!node) { + LWARNING("Could not find a node in scenegraph called '" << _name << "'"); + return; + } + OsEng.navigationHandler().setFocusNode(node->parent()); + OsEng.navigationHandler().resetCameraDirection(); + }); + + _pJumpToStartBtn.onChange([this] { + LDEBUG("Jump in time to start of sequence!"); + OsEng.timeManager().time().setTime(_startTimes[0]); + }); +} + +// Calculate expected end time. +void RenderableFieldlinesSequence::computeSequenceEndTime() { + if (_nStates > 1) { + const double LAST_TRIGGER_TIME = _startTimes[_nStates - 1]; + const double SEQUENCE_DURATION = LAST_TRIGGER_TIME - _startTimes[0]; + const double AVERAGE_STATE_DURATION = SEQUENCE_DURATION / + (static_cast(_nStates) - 1.0); + _sequenceEndTime = LAST_TRIGGER_TIME + AVERAGE_STATE_DURATION; + } else { + // If there's just one state it should never disappear! + _sequenceEndTime = DBL_MAX; + } +} + +// Extract J2000 time from file names +// Requires files to be named as such: 'YYYY-MM-DDTHH-MM-SS-XXX.osfls' +void RenderableFieldlinesSequence::extractTriggerTimesFromFileNames() { + const size_t FILENAME_SIZE = 23; // number of characters in filename (excluding '.osfls') + const size_t EXT_SIZE = 6; // size(".osfls") + + for (const std::string& FILEPATH : _sourceFiles) { + const size_t STR_LENGTH = FILEPATH.size(); + // Extract the filename from the path (without extension) + std::string timeString = FILEPATH.substr(STR_LENGTH - FILENAME_SIZE - EXT_SIZE, + FILENAME_SIZE - 1); + // Ensure the separators are correct + timeString.replace(4, 1, "-"); + timeString.replace(7, 1, "-"); + timeString.replace(13, 1, ":"); + timeString.replace(16, 1, ":"); + timeString.replace(19, 1, "."); + const double TRIGGER_TIME = Time::convertTime(timeString); + _startTimes.push_back(TRIGGER_TIME); + } +} + +} // namespace openspace diff --git a/modules/fieldlinessequence/util/commons.h b/modules/fieldlinessequence/util/commons.h new file mode 100644 index 0000000000..f019070095 --- /dev/null +++ b/modules/fieldlinessequence/util/commons.h @@ -0,0 +1,49 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_FIELDLINESSEQUENCE___COMMONS___H__ +#define __OPENSPACE_MODULE_FIELDLINESSEQUENCE___COMMONS___H__ + +#include + +namespace openspace { +namespace fls { // (F)ield(L)ines(S)equence + +enum Model : int { + BATSRUS = 0, + ENLIL, + PFSS, + INVALID +}; + + + +const float A_U_TO_METER = 149597870700.f; // Astronomical Units +const float R_E_TO_METER = 6371000.f; // Earth radius +const float R_S_TO_METER = 695700000.f; // Sun radius + +} // namespace fls +} // namespace openspace + +#endif // __OPENSPACE_MODULE_FIELDLINESSEQUENCE___COMMONS___H__ diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index 73ee392d5b..bde5dc452b 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -28,6 +28,11 @@ #include +namespace { + std::string _loggerCat = "FieldlinesState"; + const int CURRENT_VERSION = 0; +} + namespace openspace { FieldlinesState::FieldlinesState() {} @@ -56,37 +61,37 @@ bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) } // Define tmp variables to store meta data in - size_t numLines; - size_t numPoints; - size_t numExtras; + size_t nLines; + size_t nPoints; + size_t nExtras; size_t byteSizeAllNames; // Read single value variables ifs.read( reinterpret_cast(&_triggerTime), sizeof(double)); ifs.read( reinterpret_cast(&_model), sizeof(int)); ifs.read( reinterpret_cast(&_isMorphable), sizeof(bool)); - ifs.read( reinterpret_cast(&numLines), sizeof(size_t)); - ifs.read( reinterpret_cast(&numPoints), sizeof(size_t)); - ifs.read( reinterpret_cast(&numExtras), sizeof(size_t)); + ifs.read( reinterpret_cast(&nLines), sizeof(size_t)); + ifs.read( reinterpret_cast(&nPoints), sizeof(size_t)); + ifs.read( reinterpret_cast(&nExtras), sizeof(size_t)); ifs.read( reinterpret_cast(&byteSizeAllNames), sizeof(size_t)); // RESERVE/RESIZE vectors // TODO: Do this without initializing values? Resize is slower than just using reserve, due to initialization of all values - _lineStart.resize(numLines); - _lineCount.resize(numLines); - _vertexPositions.resize(numPoints); - _extraQuantities.resize(numExtras); - _extraQuantityNames.reserve(numExtras); + _lineStart.resize(nLines); + _lineCount.resize(nLines); + _vertexPositions.resize(nPoints); + _extraQuantities.resize(nExtras); + _extraQuantityNames.reserve(nExtras); // Read vertex position data - ifs.read( reinterpret_cast(_lineStart.data()), sizeof(GLint)*numLines); - ifs.read( reinterpret_cast(_lineCount.data()), sizeof(GLsizei)*numLines); - ifs.read( reinterpret_cast(_vertexPositions.data()), sizeof(glm::vec3)*numPoints); + ifs.read( reinterpret_cast(_lineStart.data()), sizeof(GLint)*nLines); + ifs.read( reinterpret_cast(_lineCount.data()), sizeof(GLsizei)*nLines); + ifs.read( reinterpret_cast(_vertexPositions.data()), sizeof(glm::vec3)*nPoints); // Read all extra quantities for (std::vector& vec : _extraQuantities) { - vec.resize(numPoints); - ifs.read( reinterpret_cast(vec.data()), sizeof(float) * numPoints); + vec.resize(nPoints); + ifs.read( reinterpret_cast(vec.data()), sizeof(float) * nPoints); } // Read all extra quantities' names. Stored as multiple c-strings @@ -97,7 +102,7 @@ bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) delete[] s; size_t offset = 0; - for (size_t i = 0; i < numExtras; ++i) { + for (size_t i = 0; i < nExtras; ++i) { auto endOfVarName = allNamesInOne.find('\0', offset); endOfVarName -= offset; std::string varName = allNamesInOne.substr(offset, endOfVarName); diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index 4819897d0f..2e6a4a29df 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -25,6 +25,8 @@ #ifndef __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSTATE___H__ #define __OPENSPACE_MODULE_FIELDLINESSEQUENCE___FIELDLINESSTATE___H__ +#include + #include #include @@ -37,12 +39,6 @@ namespace openspace { class FieldlinesState { public: - enum Model : int { - batsrus = 0, - enlil = 1, - pfss = 2 - }; - FieldlinesState(); FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& loadSucessful); @@ -54,7 +50,7 @@ public: const vector& lineCount() const { return _lineCount; } const vector& lineStart() const { return _lineStart; } size_t nExtraQuantities() const { return _extraQuantities.size(); } - Model model() const { return _model; } + fls::Model model() const { return _model; } double triggerTime() const { return _triggerTime; } const vector& vertexPositions() const { return _vertexPositions; } @@ -62,15 +58,15 @@ public: const vector& extraQuantity(const size_t INDEX, bool& isSuccesful) const; private: - bool _isMorphable = false; - double _triggerTime = -1.0; - Model _model; + bool _isMorphable = false; + double _triggerTime = -1.0; + fls::Model _model; - vector _vertexPositions; - vector _lineStart; - vector _lineCount; - vector> _extraQuantities; - vector _extraQuantityNames; + vector _vertexPositions; + vector _lineStart; + vector _lineCount; + vector> _extraQuantities; + vector _extraQuantityNames; // TODO: Maybe introduce a vector containing seed point indices }; From adcd62deddf86549cdeeb3bfffc0e00c3c740788 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 4 Oct 2017 03:43:32 +0200 Subject: [PATCH 17/47] Add DomainLimiting, Masking and AdditiveBlending options --- .../renderablefieldlinessequence.cpp | 67 +++++++++- .../rendering/renderablefieldlinessequence.h | 24 +++- .../renderablefieldlinessequencesetup.cpp | 122 ++++++++++++++++++ .../shaders/fieldlinessequence_fs.glsl | 6 + .../shaders/fieldlinessequence_vs.glsl | 62 +++++++-- 5 files changed, 266 insertions(+), 15 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 0e23cb81ed..2c8fc0b729 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -48,6 +48,9 @@ void RenderableFieldlinesSequence::deinitialize() { glDeleteBuffers(1, &_vertexColorBuffer); _vertexColorBuffer = 0; + glDeleteBuffers(1, &_vertexMaskingBuffer); + _vertexMaskingBuffer = 0; + RenderEngine& renderEngine = OsEng.renderEngine(); if (_shaderProgram) { renderEngine.removeRenderProgram(_shaderProgram); @@ -82,6 +85,8 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& _shaderProgram->setUniform("colorMethod", _pColorMethod); _shaderProgram->setUniform("lineColor", _pColorUniform); + _shaderProgram->setUniform("usingDomain", _pDomainEnabled); + _shaderProgram->setUniform("usingMasking", _pMaskingEnabled); if (_pColorMethod == ColorMethod::BY_QUANTITY) { ghoul::opengl::TextureUnit textureUnit; @@ -92,6 +97,15 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& _colorTableRanges[_pColorQuantity]); } + if (_pMaskingEnabled) { + _shaderProgram->setUniform("maskingRange", _maskingRanges[_pMaskingQuantity]); + } + + _shaderProgram->setUniform("domainLimR", _pDomainR.value() * _scalingFactor); + _shaderProgram->setUniform("domainLimX", _pDomainX.value() * _scalingFactor); + _shaderProgram->setUniform("domainLimY", _pDomainY.value() * _scalingFactor); + _shaderProgram->setUniform("domainLimZ", _pDomainZ.value() * _scalingFactor); + // Flow/Particles _shaderProgram->setUniform("flowColor", _pFlowColor); _shaderProgram->setUniform("usingParticles", _pFlowEnabled); @@ -100,6 +114,26 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& _shaderProgram->setUniform("particleSpeed", _pFlowSpeed); _shaderProgram->setUniform("time", OsEng.runTime() * (_pFlowReversed ? -1 : 1)); + bool additiveBlending = false; + if (_pColorABlendEnabled) { + const auto RENDERER = OsEng.renderEngine().rendererImplementation(); + bool usingFBufferRenderer = RENDERER == + RenderEngine::RendererImplementation::Framebuffer; + + bool usingABufferRenderer = RENDERER == + RenderEngine::RendererImplementation::ABuffer; + + if (usingABufferRenderer) { + _shaderProgram->setUniform("usingAdditiveBlending", _pColorABlendEnabled); + } + + additiveBlending = usingFBufferRenderer; + if (additiveBlending) { + glDepthMask(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + } + } + glBindVertexArray(_vertexArrayObject); glMultiDrawArrays( GL_LINE_STRIP, //_drawingOutputType, @@ -110,6 +144,11 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& glBindVertexArray(0); _shaderProgram->deactivate(); + + if (additiveBlending) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(true); + } } } @@ -164,7 +203,8 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { updateVertexPositionBuffer(); if (_states[_activeStateIndex].nExtraQuantities() > 0) { - _shouldUpdateColorBuffer = true; + _shouldUpdateColorBuffer = true; + _shouldUpdateMaskingBuffer = true; } else { _pColorMethod = ColorMethod::UNIFORM; } @@ -178,6 +218,11 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { updateVertexColorBuffer(); _shouldUpdateColorBuffer = false; } + + if (_shouldUpdateMaskingBuffer) { + updateVertexMaskingBuffer(); + _shouldUpdateMaskingBuffer = false; + } } } @@ -252,6 +297,26 @@ void RenderableFieldlinesSequence::updateVertexColorBuffer() { } } +void RenderableFieldlinesSequence::updateVertexMaskingBuffer() { + glBindVertexArray(_vertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER, _vertexMaskingBuffer); + + bool isSuccessful; + const std::vector& QUANTITY_VEC = + _states[_activeStateIndex].extraQuantity(_pMaskingQuantity, isSuccessful); + + if (isSuccessful) { + glBufferData(GL_ARRAY_BUFFER, QUANTITY_VEC.size() * sizeof(float), + &QUANTITY_VEC.front(), GL_STATIC_DRAW); + + glEnableVertexAttribArray(_VA_MASKING); + glVertexAttribPointer(_VA_MASKING, 1, GL_FLOAT, GL_FALSE, 0, 0); + + unbindGL(); + } +} + + diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index e138591c90..6302b43abf 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -75,8 +76,10 @@ private: bool _mustLoadNewStateFromDisk = false; bool _needsUpdate = false; // If still in same state as previous frame == false bool _shouldUpdateColorBuffer = false; + bool _shouldUpdateMaskingBuffer = false; FieldlinesState _newState; - size_t _nStates = 0; + size_t _nStates = 0; + float _scalingFactor = 1.f; double _sequenceEndTime; SourceFileType _sourceFileType; @@ -92,15 +95,18 @@ private: std::vector _startTimes; std::vector _states; std::vector _colorTableRanges; // Values represents min & max values represented in the color table + std::vector _maskingRanges; // Values represents min & max values for valid masking range GLuint _vertexArrayObject = 0; GLuint _vertexPositionBuffer = 0; GLuint _vertexColorBuffer = 0; + GLuint _vertexMaskingBuffer = 0; // THESE MUST CORRESPOND TO THE SHADER PROGRAM // TODO: THIS CAN BE DETERMINED BY ASKING THE SHADER PROGRAM TOO const GLuint _VA_POSITION = 0; const GLuint _VA_COLOR = 1; + const GLuint _VA_MASKING = 2; // ----------------------------- Properties ----------------------------- properties::PropertyOwner _pColorGroup; // Group to hold the color properties @@ -110,6 +116,14 @@ private: properties::StringProperty _pColorQuantityMax; // Color table/transfer function max properties::StringProperty _pColorTablePath; // Color table/transfer function for "By Quantity" coloring properties::Vec4Property _pColorUniform; // Uniform Field Line Color + properties::BoolProperty _pColorABlendEnabled; // Whether or not to use additive blending + + properties::BoolProperty _pDomainEnabled; // Whether or not to use Domain + properties::PropertyOwner _pDomainGroup; // Group to hold the Domain properties + properties::Vec2Property _pDomainX; // Domain Limits along x-axis + properties::Vec2Property _pDomainY; // Domain Limits along y-axis + properties::Vec2Property _pDomainZ; // Domain Limits along z-axis + properties::Vec2Property _pDomainR; // Domain Limits radially properties::Vec4Property _pFlowColor; // Simulated particles' color properties::BoolProperty _pFlowEnabled; // Toggle flow [ON/OFF] @@ -119,6 +133,12 @@ private: properties::BoolProperty _pFlowReversed; // Toggle flow direction [FORWARDS/BACKWARDS] properties::IntProperty _pFlowSpeed; // Speed of simulated flow + properties::BoolProperty _pMaskingEnabled; // Whether or not to use masking + properties::PropertyOwner _pMaskingGroup; // Group to hold the masking properties + properties::StringProperty _pMaskingMin; // Lower limit for allowed values + properties::StringProperty _pMaskingMax; // Upper limit for allowed values + properties::OptionProperty _pMaskingQuantity; // Index of the extra quantity to use for masking + properties::TriggerProperty _pFocusOnOriginBtn; // Button which sets camera focus to parent node of the renderable properties::TriggerProperty _pJumpToStartBtn; // Button which executes a time jump to start of sequence @@ -136,6 +156,8 @@ private: void definePropertyCallbackFunctions(); void setupProperties(); + + void setModelDependentConstants(); }; } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index d2811e5ef4..ff1c7f14ad 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -44,6 +44,7 @@ namespace { // ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- // const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers + const char* KEY_MASKING_RANGES = "MaskingRanges"; // [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // @@ -70,6 +71,24 @@ namespace { static const openspace::properties::Property::PropertyInfo ColorUniformInfo = { "uniform", "Uniform Line Color", "The uniform color of lines shown when \"Color Method\" is set to \"Uniform\"." }; + static const openspace::properties::Property::PropertyInfo ColorUseABlendingInfo = { + "aBlendingEnabled", "Additive Blending", "Activate/deactivate additive blending." + }; + static const openspace::properties::Property::PropertyInfo DomainEnabledInfo = { + "domainEnabled", "Domain Limits", "Enable/Disable domain limits" + }; + static const openspace::properties::Property::PropertyInfo DomainXInfo = { + "limitsX", "X-limits", "Valid range along the X-axis. [Min, Max]" + }; + static const openspace::properties::Property::PropertyInfo DomainYInfo = { + "limitsY", "Y-limits", "Valid range along the Y-axis. [Min, Max]" + }; + static const openspace::properties::Property::PropertyInfo DomainZInfo = { + "limitsZ", "Z-limits", "Valid range along the Z-axis. [Min, Max]" + }; + static const openspace::properties::Property::PropertyInfo DomainRInfo = { + "limitsR", "Radial limits", "Valid radial range. [Min, Max]" + }; static const openspace::properties::Property::PropertyInfo FlowColorInfo = { "color", "Color", "Color of particles." }; @@ -89,6 +108,19 @@ namespace { static const openspace::properties::Property::PropertyInfo FlowSpeedInfo = { "speed", "Speed", "Speed of the flow." }; + static const openspace::properties::Property::PropertyInfo MaskingEnabledInfo = { + "maskingEnabled", "Masking", + "Enable/disable masking. Use masking to show lines where a given quantity is within a given range, e.g. if you only want to see where the temperature is between 10 and 20 degrees. Also used for masking out line topologies like solar wind & closed lines." + }; + static const openspace::properties::Property::PropertyInfo MaskingMinInfo = { + "maskingMinLimit", "Lower Limit", "Lower limit of the valid masking range" + }; + static const openspace::properties::Property::PropertyInfo MaskingMaxInfo = { + "maskingMaxLimit", "Upper Limit", "Upper limit of the valid masking range" + }; + static const openspace::properties::Property::PropertyInfo MaskingQuantityInfo = { + "maskingQuantity", "Quantity used for Masking", "Quantity used for masking." + }; static const openspace::properties::Property::PropertyInfo OriginButtonInfo = { "focusCameraOnParent", "Focus Camera", "Focus camera on parent." }; @@ -121,6 +153,13 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona _pColorTablePath(ColorTablePathInfo), _pColorUniform(ColorUniformInfo, glm::vec4(0.75f, 0.5f, 0.0f, 0.5f), glm::vec4(0.f), glm::vec4(1.f)), + _pColorABlendEnabled(ColorUseABlendingInfo, true), + _pDomainEnabled(DomainEnabledInfo, true), + _pDomainGroup({ "Domain" }), + _pDomainX(DomainXInfo), + _pDomainY(DomainYInfo), + _pDomainZ(DomainZInfo), + _pDomainR(DomainRInfo), _pFlowColor(FlowColorInfo, glm::vec4(0.8f, 0.7f, 0.0f, 0.6f), glm::vec4(0.f), glm::vec4(1.f)), _pFlowEnabled(FlowEnabledInfo, true), @@ -129,6 +168,11 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona _pFlowParticleSpacing(FlowParticleSpacingInfo, 60, 0, 500), _pFlowReversed(FlowReversedInfo, false), _pFlowSpeed(FlowSpeedInfo, 20, 0, 1000), + _pMaskingEnabled(MaskingEnabledInfo, false), + _pMaskingGroup({ "Masking" }), + _pMaskingMin(MaskingMinInfo), + _pMaskingMax(MaskingMaxInfo), + _pMaskingQuantity(MaskingQuantityInfo, properties::OptionProperty::DisplayType::Dropdown), _pFocusOnOriginBtn(OriginButtonInfo), _pJumpToStartBtn(TimeJumpButtonInfo) { @@ -191,6 +235,7 @@ void RenderableFieldlinesSequence::initialize() { } computeSequenceEndTime(); + setModelDependentConstants(); setupProperties(); @@ -210,6 +255,10 @@ void RenderableFieldlinesSequence::initialize() { glGenVertexArrays(1, &_vertexArrayObject); glGenBuffers(1, &_vertexPositionBuffer); glGenBuffers(1, &_vertexColorBuffer); + glGenBuffers(1, &_vertexMaskingBuffer); + + // Needed for additive blending + setRenderBin(Renderable::RenderBin::Overlay); } bool RenderableFieldlinesSequence::extractInfoFromDictionary( @@ -327,13 +376,18 @@ bool RenderableFieldlinesSequence::extractInfoFromDictionary( void RenderableFieldlinesSequence::setupProperties() { // -------------- Add non-grouped properties (enablers and buttons) -------------- // + addProperty(_pColorABlendEnabled); + addProperty(_pDomainEnabled); addProperty(_pFlowEnabled); + addProperty(_pMaskingEnabled); addProperty(_pFocusOnOriginBtn); addProperty(_pJumpToStartBtn); // ----------------------------- Add Property Groups ----------------------------- // addPropertySubOwner(_pColorGroup); + addPropertySubOwner(_pDomainGroup); addPropertySubOwner(_pFlowGroup); + addPropertySubOwner(_pMaskingGroup); // ------------------------- Add Properties to the groups ------------------------- // _pColorGroup.addProperty(_pColorMethod); @@ -343,12 +397,21 @@ void RenderableFieldlinesSequence::setupProperties() { _pColorGroup.addProperty(_pColorTablePath); _pColorGroup.addProperty(_pColorUniform); + _pDomainGroup.addProperty(_pDomainX); + _pDomainGroup.addProperty(_pDomainY); + _pDomainGroup.addProperty(_pDomainZ); + _pDomainGroup.addProperty(_pDomainR); + _pFlowGroup.addProperty(_pFlowReversed); _pFlowGroup.addProperty(_pFlowColor); _pFlowGroup.addProperty(_pFlowParticleSize); _pFlowGroup.addProperty(_pFlowParticleSpacing); _pFlowGroup.addProperty(_pFlowSpeed); + _pMaskingGroup.addProperty(_pMaskingMin); + _pMaskingGroup.addProperty(_pMaskingMax); + _pMaskingGroup.addProperty(_pMaskingQuantity); + // ----------------------- Add Options to OptionProperties ----------------------- // _pColorMethod.addOption(ColorMethod::UNIFORM, "Uniform"); _pColorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity"); @@ -360,10 +423,12 @@ void RenderableFieldlinesSequence::setupProperties() { auto EXTRA_VARIABLE_NAMES_VEC = _states[0].extraQuantityNames(); for (int i = 0; i < N_EXTRA_QUANTITIES; ++i) { _pColorQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]); + _pMaskingQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]); } // Each quantity should have its own color table and color table range, no more, no less _colorTablePaths.resize(N_EXTRA_QUANTITIES, _colorTablePaths.back()); _colorTableRanges.resize(N_EXTRA_QUANTITIES, _colorTableRanges.back()); + _maskingRanges.resize(N_EXTRA_QUANTITIES, _maskingRanges.back()); definePropertyCallbackFunctions(); @@ -373,6 +438,10 @@ void RenderableFieldlinesSequence::setupProperties() { _pColorQuantityMax = std::to_string(_colorTableRanges[_pColorQuantity].y); _pColorTablePath = _colorTablePaths[_pColorQuantity]; + _pMaskingQuantity = 0; + _pMaskingMin = std::to_string(_maskingRanges[_pMaskingQuantity].x); + _pMaskingMax = std::to_string(_maskingRanges[_pMaskingQuantity].y); + } void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { @@ -404,6 +473,27 @@ void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { _colorTableRanges[_pColorQuantity].y = f; }); + _pMaskingQuantity.onChange([this] { + LDEBUG("CHANGED MASKING QUANTITY"); + _shouldUpdateMaskingBuffer = true; + _pMaskingMin = std::to_string(_maskingRanges[_pMaskingQuantity].x); + _pMaskingMax = std::to_string(_maskingRanges[_pMaskingQuantity].y); + }); + + _pMaskingMin.onChange([this] { + LDEBUG("CHANGED LOWER MASKING LIMIT"); + float f = stringToFloat(_pMaskingMin, _maskingRanges[_pMaskingQuantity].x); + _pMaskingMin = std::to_string(f); + _maskingRanges[_pMaskingQuantity].x = f; + }); + + _pMaskingMax.onChange([this] { + LDEBUG("CHANGED UPPER MASKING LIMIT"); + float f = stringToFloat(_pMaskingMax, _maskingRanges[_pMaskingQuantity].y); + _pMaskingMax = std::to_string(f); + _maskingRanges[_pMaskingQuantity].y = f; + }); + _pFocusOnOriginBtn.onChange([this] { LDEBUG("SET FOCUS NODE TO PARENT"); SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(_name); @@ -435,6 +525,38 @@ void RenderableFieldlinesSequence::computeSequenceEndTime() { } } +void RenderableFieldlinesSequence::setModelDependentConstants() { + const fls::Model simulationModel = _states[0].model(); + float limit = 100.f; // Just used as a default value. + switch (simulationModel) { + case fls::Model::BATSRUS: + _scalingFactor = fls::R_E_TO_METER; + limit = 300; // Should include a long magnetotail + break; + case fls::Model::ENLIL: + _pFlowReversed = true; + _scalingFactor = fls::A_U_TO_METER; + limit = 50; // Should include Plutos furthest distance from the Sun + break; + case fls::Model::PFSS: + _scalingFactor = fls::R_S_TO_METER; + limit = 100; // Just a default value far away from the solar surface + break; + default: + break; + } + _pDomainX.setMinValue(glm::vec2(-limit)); _pDomainX.setMaxValue(glm::vec2(limit)); + _pDomainY.setMinValue(glm::vec2(-limit)); _pDomainY.setMaxValue(glm::vec2(limit)); + _pDomainZ.setMinValue(glm::vec2(-limit)); _pDomainZ.setMaxValue(glm::vec2(limit)); + // Radial should range from 0 out to a corner of the cartesian box: sqrt(3) = 1.732..., 1.75 is a nice and round number + _pDomainR.setMinValue(glm::vec2(0)); _pDomainR.setMaxValue(glm::vec2(limit*1.75f)); + + _pDomainX = glm::vec2(-limit, limit); + _pDomainY = glm::vec2(-limit, limit); + _pDomainZ = glm::vec2(-limit, limit); + _pDomainR = glm::vec2(0, limit*1.5f); +} + // Extract J2000 time from file names // Requires files to be named as such: 'YYYY-MM-DDTHH-MM-SS-XXX.osfls' void RenderableFieldlinesSequence::extractTriggerTimesFromFileNames() { diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl index 8e8f3ec6d3..47f3c6ac2d 100644 --- a/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl @@ -25,6 +25,8 @@ in vec4 vs_color; in float vs_depth; +uniform bool usingAdditiveBlending; + #include "fragment.glsl" #include "PowerScaling/powerScaling_fs.hglsl" @@ -39,5 +41,9 @@ Fragment getFragment() { frag.depth = vs_depth; frag.color = fragColor; + if (usingAdditiveBlending) { + frag.blend = BLEND_MODE_ADDITIVE; + } + return frag; } diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl index de0bd246a6..8491716b29 100644 --- a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl @@ -43,8 +43,21 @@ uniform int particleSpacing; uniform double time; uniform bool usingParticles; -layout(location = 0) in vec3 in_position; // Should be provided in meters -layout(location = 1) in float in_color_scalar; // The extra value used to color lines. Location must correspond to _VA_COLOR in renderablefieldlinessequence.h +// Masking Uniforms +uniform bool usingMasking; +uniform vec2 maskingRange; + +// Domain Uniforms +uniform bool usingDomain; +uniform vec2 domainLimX; +uniform vec2 domainLimY; +uniform vec2 domainLimZ; +uniform vec2 domainLimR; + +// Inputs +layout(location = 0) in vec3 in_position; // Should be provided in meters +layout(location = 1) in float in_color_scalar; // The extra value used to color lines. Location must correspond to _VA_COLOR in renderablefieldlinessequence.h +layout(location = 2) in float in_masking_scalar; // The extra value used to mask out parts of lines. Location must correspond to _VA_MASKING in renderablefieldlinessequence.h // These should correspond to the enum 'ColorMethod' in renderablefieldlinesequence.cpp const int UNIFORM_COLOR = 0; @@ -69,20 +82,43 @@ bool isPartOfParticle(const double TIME, const int VERTEX_ID, const int PARTICLE void main() { - const bool IS_PARTICLE = usingParticles && isPartOfParticle(time, gl_VertexID, - particleSize, - particleSpeed, - particleSpacing); + bool hasColor = true; - if (IS_PARTICLE) { - vs_color = flowColor; - } else { - vs_color = lineColor; + if (usingMasking && (in_masking_scalar < maskingRange.x || + in_masking_scalar > maskingRange.y )) { + hasColor = false; } - if (colorMethod == COLOR_BY_QUANTITY) { - const vec4 QUANTITY_COLOR = getTransferFunctionColor(); - vs_color = vec4(QUANTITY_COLOR.xyz, vs_color.a * QUANTITY_COLOR.a); + if (usingDomain && hasColor) { + const float RADIUS = length(in_position); + + if (in_position.x < domainLimX.x || in_position.x > domainLimX.y || + in_position.y < domainLimY.x || in_position.y > domainLimY.y || + in_position.z < domainLimZ.x || in_position.z > domainLimZ.y || + RADIUS < domainLimR.x || RADIUS > domainLimR.y) { + + hasColor = false; + } + } + + if (hasColor) { + const bool IS_PARTICLE = usingParticles && isPartOfParticle(time, gl_VertexID, + particleSize, + particleSpeed, + particleSpacing); + + if (IS_PARTICLE) { + vs_color = flowColor; + } else { + vs_color = lineColor; + } + + if (colorMethod == COLOR_BY_QUANTITY) { + const vec4 QUANTITY_COLOR = getTransferFunctionColor(); + vs_color = vec4(QUANTITY_COLOR.xyz, vs_color.a * QUANTITY_COLOR.a); + } + } else { + vs_color = vec4(0); } vec4 position_in_meters = vec4(in_position, 1); From bfe0cfd770f2cb5cb59a70438a996ca11853e2c2 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 4 Oct 2017 14:19:51 +0200 Subject: [PATCH 18/47] Implement functionality for saving field line states to a JSON format --- .../util/fieldlinesstate.cpp | 77 +++++++++++++++++++ .../fieldlinessequence/util/fieldlinesstate.h | 2 + 2 files changed, 79 insertions(+) diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index bde5dc452b..519167a6e6 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -24,6 +24,9 @@ #include +#include +#include + #include #include @@ -31,6 +34,8 @@ namespace { std::string _loggerCat = "FieldlinesState"; const int CURRENT_VERSION = 0; + + using json = nlohmann::json; } namespace openspace { @@ -113,6 +118,78 @@ bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) return true; } +// TODO: This should probably be rewritten, but this is the way the files were structured by CCMC +// Structure of File! NO TRAILING COMMAS ALLOWED! +// Additional info can be stored within each line as the code only extracts the keys it needs (time, trace & data) +// The key/name of each line ("0" & "1" in the example below) is arbitrary +// { +// "0":{ +// "time": "YYYY-MM-DDTHH:MM:SS.XXX", +// "trace": { +// "columns": ["x","y","z","s","temperature","rho","j_para"], +// "data": [[8.694,127.853,115.304,0.0,0.047,9.249,-5e-10],...,[8.698,127.253,114.768,0.800,0.0,9.244,-5e-10]] +// }, +// }, +// "1":{ +// "time": "YYYY-MM-DDTHH:MM:SS.XXX +// "trace": { +// "columns": ["x","y","z","s","temperature","rho","j_para"], +// "data": [[8.694,127.853,115.304,0.0,0.047,9.249,-5e-10],...,[8.698,127.253,114.768,0.800,0.0,9.244,-5e-10]] +// }, +// } +// } +void FieldlinesState::saveStateToJson(const std::string& ABS_FILEPATH) { + // Create the file + const std::string EXT = ".json"; + std::ofstream ofs(ABS_FILEPATH + EXT, std::ofstream::trunc); + if (!ofs.is_open()) { + LERROR("Failed to save state to json file at location: " << ABS_FILEPATH << EXT); + return; + } + LINFO("Saving fieldline state to: " << ABS_FILEPATH << EXT ); + + json jColumns = {"x", "y", "z"}; + for (std::string s : _extraQuantityNames) { + jColumns.push_back(s); + } + + json jFile; + + const std::string TIME_STRING = Time(_triggerTime).ISO8601(); + + const size_t N_LINES = _lineStart.size(); + const size_t N_POINTS = _vertexPositions.size(); + const size_t N_EXTRAS = _extraQuantities.size(); + + size_t pointIndex = 0; + for (size_t lineIndex = 0; lineIndex < N_LINES; lineIndex++) { + json jData = json::array(); + for (size_t i = 0; i < _lineCount[lineIndex]; i++, pointIndex++) { + const glm::vec3 POS = _vertexPositions[pointIndex]; + json jDataElement = {POS.x, POS.y, POS.z}; + + for (size_t extraIndex = 0; extraIndex < N_EXTRAS; extraIndex++) { + jDataElement.push_back(_extraQuantities[extraIndex][pointIndex]); + } + jData.push_back(jDataElement); + } + + jFile[std::to_string(lineIndex)] = { + {"time", TIME_STRING}, + {"trace", { + {"columns", jColumns}, + {"data", jData} + }} + }; + } + + //------------------------------ WRITE EVERYTHING TO FILE ------------------------------ + const int INDENTATION_SPACES = 2; + ofs << std::setw(INDENTATION_SPACES) << jFile << std::endl; + + LINFO("Saved fieldline state to: " << ABS_FILEPATH << EXT ); +} + // Returns one of the extra quantity vectors, _extraQuantities[INDEX]. // If INDEX is out of scope an empty vector is returned and the referenced bool will be false. const vector& FieldlinesState::extraQuantity(const size_t INDEX, diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index 2e6a4a29df..aa14fd71cb 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -44,6 +44,8 @@ public: bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE); + void saveStateToJson(const std::string& PATH_TO_JSON_FILE); + // ------------------------------GETTERS-----------------------------------------// const vector>& extraQuantities() const { return _extraQuantities; } const vector& extraQuantityNames() const { return _extraQuantityNames; } From 84a511a1fc9cd7f27a92c6ce947b9a12db124865 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 4 Oct 2017 14:35:02 +0200 Subject: [PATCH 19/47] Add functionality for reading field line states from JSON files --- .../util/fieldlinesstate.cpp | 75 +++++++++++++++++++ .../fieldlinessequence/util/fieldlinesstate.h | 2 + 2 files changed, 77 insertions(+) diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index 519167a6e6..d5801bfb84 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -118,6 +118,81 @@ bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) return true; } +bool FieldlinesState::loadStateFromJson(const std::string& PATH_TO_JSON_FILE, + const fls::Model MODEL, + const float COORD_TO_METERS = 1.f) { + + // --------------------- ENSURE FILE IS VALID, THEN PARSE IT --------------------- // + std::ifstream ifs(PATH_TO_JSON_FILE); + + if (!ifs.is_open()) { + LERROR("FAILED TO OPEN FILE: " << PATH_TO_JSON_FILE); + return false; + } + + json jFile; + ifs >> jFile; + // -------------------------------------------------------------------------------- // + + _model = MODEL; + + const std::string S_DATA = "data"; + const std::string S_TRACE = "trace"; + + // ----- EXTRACT THE EXTRA QUANTITY NAMES & TRIGGER TIME (same for all lines) ----- // + { + const json J_TMP = *jFile.begin(); // First field line in the file + _triggerTime = Time::convertTime(J_TMP["time"]); + + const std::string S_COLUMNS = "columns"; + auto variableNameVec = J_TMP[S_TRACE][S_COLUMNS]; + const size_t N_VARIABLES = variableNameVec.size(); + const size_t N_POS_COMPONENTS = 3; // x,y,z + + if (N_VARIABLES < N_POS_COMPONENTS) { + LERROR(PATH_TO_JSON_FILE + ": Each field '" + S_COLUMNS + + "' must contain the variables: 'x', 'y' and 'z' (order is important)."); + return false; + } + + for (size_t i = N_POS_COMPONENTS ; i < N_VARIABLES ; i++) { + _extraQuantityNames.push_back(variableNameVec[i]); + } + } + + const size_t N_EXTRAS = _extraQuantityNames.size(); + _extraQuantities.resize(N_EXTRAS); + + size_t lineStartIdx = 0; + // Loop through all fieldlines + for (json::iterator fieldlineIt = jFile.begin(); fieldlineIt != jFile.end(); ++fieldlineIt) { + // The 'data' field in the 'trace' variable contains all vertex positions and the + // extra quantities. Each element is an array related to one vertex point. + const std::vector> J_DATA = (*fieldlineIt)[S_TRACE][S_DATA]; + const size_t N_POINTS = J_DATA.size(); + + for (size_t j = 0; j < N_POINTS; ++j) { + const std::vector& VARIABLES = J_DATA[j]; + + // Expects the x, y and z variables to be stored first! + const size_t X_IDX = 0, Y_IDX = 1, Z_IDX = 2; + _vertexPositions.push_back(COORD_TO_METERS * glm::vec3(VARIABLES[X_IDX], + VARIABLES[Y_IDX], + VARIABLES[Z_IDX])); + + // Add the extra quantites. Stored in the same array as the x,y,z variables. + // Hence index of the first extra quantity = 3 + for (size_t xtraIdx = 3, k = 0 ; k < N_EXTRAS; ++k, ++xtraIdx) { + _extraQuantities[k].push_back(VARIABLES[xtraIdx]); + } + } + _lineCount.push_back(static_cast(N_POINTS)); + _lineStart.push_back(static_cast(lineStartIdx)); + lineStartIdx += N_POINTS; + } + return true; +} + // TODO: This should probably be rewritten, but this is the way the files were structured by CCMC // Structure of File! NO TRAILING COMMAS ALLOWED! // Additional info can be stored within each line as the code only extracts the keys it needs (time, trace & data) diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index aa14fd71cb..2417907a71 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -44,6 +44,8 @@ public: bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE); + bool loadStateFromJson(const std::string& PATH_TO_JSON_FILE, + const fls::Model MODEL, const float COORD_TO_METERS); void saveStateToJson(const std::string& PATH_TO_JSON_FILE); // ------------------------------GETTERS-----------------------------------------// From d9268593cec0366c9be487cee87eddea3f93f4c1 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 4 Oct 2017 14:56:47 +0200 Subject: [PATCH 20/47] Add functionality for saving states to the OSFLS format --- .../util/fieldlinesstate.cpp | 62 +++++++++++++++++++ .../fieldlinessequence/util/fieldlinesstate.h | 1 + 2 files changed, 63 insertions(+) diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index d5801bfb84..264513ce0c 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -193,6 +193,68 @@ bool FieldlinesState::loadStateFromJson(const std::string& PATH_TO_JSON_FILE, return true; } +/** + * @param ABS_FILEPATH must be the path to the file (incl. filename but excl. extension!) + * Directory must exist! File is created (or overwritten if already existing). + * File is structured like this: (for version 0) + * 0. int - version number of binary state file! (in case something needs to be altered in the future, then increase CURRENT_VERSION) + * 1. double - _triggerTime + * 2. int - _model + * 3. bool - _isMorphable + * 4. size_t - Number of lines in the state == _lineStart.size() == _lineCount.size() + * 5. size_t - Total number of vertex points == _vertexPositions.size() == _extraQuantities[i].size() + * 6. size_t - Number of extra quantites == _extraQuantities.size() == _extraQuantityNames.size() + * 7. site_t - Number of total bytes that ALL _extraQuantityNames consists of (Each such name is stored as a c_str which means it ends with the null char '\0' ) + * 7. std::vector - _lineStart + * 8. std::vector - _lineCount + * 9. std::vector - _vertexPositions + * 10. std::vector - _extraQuantities + * 11. array of c_str - Strings naming the extra quantities (elements of _extraQuantityNames). Each string ends with null char '\0' + */ +void FieldlinesState::saveStateToOsfls(const std::string& ABS_FILEPATH) { + // Create the file + const std::string EXT = ".osfls"; + std::ofstream ofs(ABS_FILEPATH + EXT, std::ofstream::binary | std::ofstream::trunc); + if (!ofs.is_open()) { + LERROR("Failed to save state to binary file: " << ABS_FILEPATH << EXT); + return; + } + + std::string allExtraQuantityNamesInOne = ""; + for (std::string str : _extraQuantityNames) { + allExtraQuantityNamesInOne += str + '\0'; // Add the null char '\0' for easier reading + } + + const size_t N_LINES = _lineStart.size(); + const size_t N_POINTS = _vertexPositions.size(); + const size_t N_EXTRAS = _extraQuantities.size(); + const size_t N_STRING_BYTES = allExtraQuantityNamesInOne.size(); + + //------------------------------ WRITE EVERYTHING TO FILE ------------------------------ + // WHICH VERSION OF BINARY FIELDLINES STATE FILE - IN CASE STRUCTURE CHANGES IN THE FUTURE + ofs.write( (char*)(&CURRENT_VERSION), sizeof( int ) ); + + //-------------------- WRITE META DATA FOR STATE -------------------------------- + ofs.write( reinterpret_cast(&_triggerTime), sizeof( _triggerTime ) ); + ofs.write( reinterpret_cast(&_model), sizeof( int ) ); + ofs.write( reinterpret_cast(&_isMorphable), sizeof( bool ) ); + + ofs.write( reinterpret_cast(&N_LINES), sizeof( size_t ) ); + ofs.write( reinterpret_cast(&N_POINTS), sizeof( size_t ) ); + ofs.write( reinterpret_cast(&N_EXTRAS), sizeof( size_t ) ); + ofs.write( reinterpret_cast(&N_STRING_BYTES), sizeof( size_t ) ); + + //---------------------- WRITE ALL ARRAYS OF DATA -------------------------------- + ofs.write( reinterpret_cast(_lineStart.data()), sizeof(GLint) * N_LINES); + ofs.write( reinterpret_cast(_lineCount.data()), sizeof(GLsizei) * N_LINES); + ofs.write( reinterpret_cast(_vertexPositions.data()), sizeof(glm::vec3) * N_POINTS); + // Write the data for each vector in _extraQuantities + for (std::vector& vec : _extraQuantities) { + ofs.write( reinterpret_cast(vec.data()), sizeof(float) * N_POINTS); + } + ofs.write( allExtraQuantityNamesInOne.c_str(), N_STRING_BYTES); +} + // TODO: This should probably be rewritten, but this is the way the files were structured by CCMC // Structure of File! NO TRAILING COMMAS ALLOWED! // Additional info can be stored within each line as the code only extracts the keys it needs (time, trace & data) diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index 2417907a71..a4f2a9b50e 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -43,6 +43,7 @@ public: FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& loadSucessful); bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE); + void saveStateToOsfls(const std::string& PATH_TO_OSFLS_FILE); bool loadStateFromJson(const std::string& PATH_TO_JSON_FILE, const fls::Model MODEL, const float COORD_TO_METERS); From b1d1a7cf026ed3c53e86bc1353d2accc4eeb76b2 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Thu, 5 Oct 2017 01:35:14 +0200 Subject: [PATCH 21/47] Refactor: restructure & clean up --- .../renderablefieldlinessequence.cpp | 22 +-- .../rendering/renderablefieldlinessequence.h | 103 +++++++------ .../renderablefieldlinessequencesetup.cpp | 138 +++++++++++------- 3 files changed, 145 insertions(+), 118 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 2c8fc0b729..2fb669f39f 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -34,6 +34,10 @@ namespace { std::string _loggerCat = "RenderableFieldlinesSequence"; + + const GLuint _VA_POSITION = 0; // MUST CORRESPOND TO THE SHADER PROGRAM + const GLuint _VA_COLOR = 1; // MUST CORRESPOND TO THE SHADER PROGRAM + const GLuint _VA_MASKING = 2; // MUST CORRESPOND TO THE SHADER PROGRAM } // namespace namespace openspace { @@ -58,13 +62,13 @@ void RenderableFieldlinesSequence::deinitialize() { } // Stall main thread until thread that's loading states is done! - while (/*!_newStateIsReady &&*/ _isLoadingStateFromDisk) { + while (_isLoadingStateFromDisk) { LWARNING("TRYING TO DESTROY CLASS WHEN A THREAD USING IT IS STILL ACTIVE"); } } bool RenderableFieldlinesSequence::isReady() const { - return _sourceFileType != INVALID; + return _isReady; } void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks&) { @@ -197,7 +201,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { if (_needsUpdate || _newStateIsReady) { if (_loadingStatesDynamically) { - _states[0] = std::move(_newState); + _states[0] = std::move(*_newState); } updateVertexPositionBuffer(); @@ -245,14 +249,12 @@ void RenderableFieldlinesSequence::updateActiveTriggerTimeIndex(const double CUR } } -// Reading state from disk. Thread safe! +// Reading state from disk. Must be thread safe! void RenderableFieldlinesSequence::readNewState(const std::string& FILEPATH) { - FieldlinesState newState; - - bool isSuccessful = newState.loadStateFromOsfls(FILEPATH); - _newState = std::move(newState); - - _newStateIsReady = true; + _newState = std::make_unique(); + if (_newState->loadStateFromOsfls(FILEPATH)) { + _newStateIsReady = true; + } _isLoadingStateFromDisk = false; } diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 6302b43abf..dcf7363c90 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -39,14 +39,15 @@ #include -namespace openspace { +namespace { + enum class SourceFileType; +} -class ghoul::Dictionary; +namespace openspace { class RenderableFieldlinesSequence : public Renderable { public: RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary); - // ~RenderableFieldlinesSequence(); void initialize() override; void deinitialize() override; @@ -56,59 +57,51 @@ public: void render(const RenderData& data, RendererTasks& rendererTask) override; void update(const UpdateData& data) override; private: - enum ColorMethod : int { + // ------------------------------------- ENUMS -------------------------------------// + enum ColorMethod : int { // Used to determine if lines should be colored UNIFORMLY or by an extraQuantity UNIFORM = 0, BY_QUANTITY }; - enum SourceFileType : int { - CDF = 0, - JSON, - OSFLS, - INVALID - }; + // ------------------------------------ STRINGS ------------------------------------// + std::string _name; // Name of the Node! - std::string _name; + // ------------------------------------- FLAGS -------------------------------------// + std::atomic _isLoadingStateFromDisk { false}; // Used for 'runtime-states'. True when loading a new state from disk on another thread. + bool _isReady = false; // If initialization proved successful + bool _loadingStatesDynamically = false; // False => states are stored in RAM (using 'in-RAM-states'), True => states are loaded from disk during runtime (using 'runtime-states') + bool _mustLoadNewStateFromDisk = false; // Used for 'runtime-states': True if new 'runtime-state' must be loaded from disk. False => the previous frame's state should still be shown + bool _needsUpdate = false; // Used for 'in-RAM-states' : True if new 'in-RAM-state' must be loaded. False => the previous frame's state should still be shown + std::atomic _newStateIsReady { false}; // Used for 'runtime-states'. True when finished loading a new state from disk on another thread. + bool _shouldUpdateColorBuffer = false; // True when new state is loaded or user change which quantity to color the lines by + bool _shouldUpdateMaskingBuffer = false; // True when new state is loaded or user change which quantity used for masking out line segments - int _activeStateIndex = -1; - int _activeTriggerTimeIndex = -1; - bool _loadingStatesDynamically = false; // False => loading osfls files into RAM in initializing step - bool _mustLoadNewStateFromDisk = false; - bool _needsUpdate = false; // If still in same state as previous frame == false - bool _shouldUpdateColorBuffer = false; - bool _shouldUpdateMaskingBuffer = false; - FieldlinesState _newState; - size_t _nStates = 0; - float _scalingFactor = 1.f; - double _sequenceEndTime; - SourceFileType _sourceFileType; + // --------------------------------- NUMERICALS ----------------------------------- // + int _activeStateIndex = -1; // Active index of _states. If(==-1)=>no state available for current time. Always the same as _activeTriggerTimeIndex if(_loadingStatesDynamically==true), else always = 0 + int _activeTriggerTimeIndex = -1; // Active index of _startTimes + size_t _nStates = 0; // Number of states in the sequence + float _scalingFactor = 1.f; // In setup it is used to scale JSON coordinates. During runtime it is used to scale domain limits. + double _sequenceEndTime; // Estimated end of sequence. + GLuint _vertexArrayObject = 0; // OpenGL Vertex Array Object + GLuint _vertexColorBuffer = 0; // OpenGL Vertex Buffer Object containing the extraQuantity values used for coloring the lines + GLuint _vertexMaskingBuffer = 0; // OpenGL Vertex Buffer Object containing the extraQuantity values used for masking out segments of the lines + GLuint _vertexPositionBuffer = 0; // OpenGL Vertex Buffer Object containing the vertex positions - std::atomic _isLoadingStateFromDisk{false}; - std::atomic _newStateIsReady{false}; - - std::unique_ptr _dictionary; - std::shared_ptr _transferFunction; // Transfer funtion (tf) + // ----------------------------------- POINTERS ------------------------------------// + std::unique_ptr _dictionary; // The Lua-Modfile-Dictionary used during initialization + std::unique_ptr _newState; // Used for 'runtime-states' when switching out current state to a new state std::unique_ptr _shaderProgram; + std::shared_ptr _transferFunction; // Transfer function used to color lines when _pColorMethod is set to BY_QUANTITY - std::vector _colorTablePaths {"${OPENSPACE_DATA}/colortables/kroyw.txt"}; // Default in case user doesn't specify otherwise - std::vector _sourceFiles; // Stored in RAM if files are loaded at runtime, else emptied after initialization - std::vector _startTimes; - std::vector _states; - std::vector _colorTableRanges; // Values represents min & max values represented in the color table - std::vector _maskingRanges; // Values represents min & max values for valid masking range + // ------------------------------------ VECTORS ----------------------------------- // + std::vector _colorTablePaths; // Paths to color tables. One for each 'extraQuantity' + std::vector _colorTableRanges; // Values represents min & max values represented in the color table + std::vector _maskingRanges; // Values represents min & max limits for valid masking range + std::vector _sourceFiles; // Stores the provided source file paths if using 'runtime-states', else emptied after initialization + std::vector _startTimes; // Contains the _triggerTimes for all FieldlineStates in the sequence + std::vector _states; // Stores the FieldlineStates - GLuint _vertexArrayObject = 0; - GLuint _vertexPositionBuffer = 0; - GLuint _vertexColorBuffer = 0; - GLuint _vertexMaskingBuffer = 0; - - // THESE MUST CORRESPOND TO THE SHADER PROGRAM - // TODO: THIS CAN BE DETERMINED BY ASKING THE SHADER PROGRAM TOO - const GLuint _VA_POSITION = 0; - const GLuint _VA_COLOR = 1; - const GLuint _VA_MASKING = 2; - - // ----------------------------- Properties ----------------------------- + // ---------------------------------- Properties ---------------------------------- // properties::PropertyOwner _pColorGroup; // Group to hold the color properties properties::OptionProperty _pColorMethod; // Uniform/transfer function/topology? properties::OptionProperty _pColorQuantity; // Index of the extra quantity to color lines by @@ -142,22 +135,24 @@ private: properties::TriggerProperty _pFocusOnOriginBtn; // Button which sets camera focus to parent node of the renderable properties::TriggerProperty _pJumpToStartBtn; // Button which executes a time jump to start of sequence + // --------------------- FUNCTIONS USED DURING INITIALIZATION --------------------- // void computeSequenceEndTime(); - bool extractInfoFromDictionary(const ghoul::Dictionary& dictionary); + void definePropertyCallbackFunctions(); + bool extractJsonInfoFromDictionary(fls::Model& model); + bool extractMandatoryInfoFromDictionary(SourceFileType& sourceFileType); + void extractOptionalInfoFromDictionary(std::string& outputFolderPath); + void extractOsflsInfoFromDictionary(); void extractTriggerTimesFromFileNames(); - void readNewState(const std::string& FILEPATH); + void setModelDependentConstants(); + void setupProperties(); + // ------------------------- FUNCTIONS USED DURING RUNTIME ------------------------ // inline bool isWithinSequenceInterval(const double CURRENT_TIME) const; - + void readNewState(const std::string& FILEPATH); void updateActiveTriggerTimeIndex(const double CURRENT_TIME); void updateVertexPositionBuffer(); void updateVertexColorBuffer(); void updateVertexMaskingBuffer(); - - void definePropertyCallbackFunctions(); - void setupProperties(); - - void setModelDependentConstants(); }; } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index ff1c7f14ad..5f960324b0 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -128,6 +128,13 @@ namespace { "timeJumpToStart", "Jump to Start Of Sequence", "Performs a time jump to the start of the sequence." }; + enum class SourceFileType : int { + CDF = 0, + JSON, + OSFLS, + INVALID + }; + float stringToFloat(const std::string INPUT, const float BACKUP_VALUE = 0.f) { float tmp; try { @@ -143,8 +150,8 @@ namespace { namespace openspace { -RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) - : Renderable(dictionary), +RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& DICTIONARY) + : Renderable(DICTIONARY), _pColorGroup({ "Color" }), _pColorMethod(ColorMethodInfo, properties::OptionProperty::DisplayType::Radio), _pColorQuantity(ColorQuantityInfo, properties::OptionProperty::DisplayType::Dropdown), @@ -176,29 +183,37 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona _pFocusOnOriginBtn(OriginButtonInfo), _pJumpToStartBtn(TimeJumpButtonInfo) { - _dictionary = std::make_unique(dictionary); - // Set the default color table, just in case user defined paths are corrupt! - _transferFunction = std::make_shared(absPath(_colorTablePaths[0])); + _dictionary = std::make_unique(DICTIONARY); } void RenderableFieldlinesSequence::initialize() { LINFO("RenderableFieldlinesSequence::initialize()"); - if (!extractInfoFromDictionary(*_dictionary)) { - _sourceFileType = SourceFileType::INVALID; + // EXTRACT MANDATORY INFORMATION FROM DICTIONARY + SourceFileType sourceFileType = SourceFileType::INVALID; + if (!extractMandatoryInfoFromDictionary(sourceFileType)) { + return; } - // dictionary is no longer necessary as everything is extracted - _dictionary.reset(); + // Set the default color table, just in case the (optional) user defined paths are corrupt! + _colorTablePaths.push_back("${OPENSPACE_DATA}/colortables/kroyw.txt"); + _transferFunction = std::make_shared(absPath(_colorTablePaths[0])); - switch (_sourceFileType) { - case CDF: + // EXTRACT OPTIONAL INFORMATION FROM DICTIONARY + std::string outputFolderPath; + extractOptionalInfoFromDictionary(outputFolderPath); + const bool SHOULD_SAVE_STATES = !outputFolderPath.empty(); + + // EXTRACT SOURCE FILE TYPE SPECIFIC INFOMRATION FROM DICTIONARY & GET STATES FROM SOURCE + switch (sourceFileType) { + case SourceFileType::CDF: LERROR("CDF NOT YET IMPLEMENTED!"); return; break; - case JSON: + case SourceFileType::JSON: LERROR("JSON NOT YET IMPLEMENTED!"); return; break; - case OSFLS: + case SourceFileType::OSFLS: + extractOsflsInfoFromDictionary(); if (_loadingStatesDynamically) { extractTriggerTimesFromFileNames(); FieldlinesState newState; @@ -209,7 +224,7 @@ void RenderableFieldlinesSequence::initialize() { _activeStateIndex = 0; } else { LERROR("The provided .osfls files seem to be corrupt!"); - _sourceFileType = SourceFileType::INVALID; + sourceFileType = SourceFileType::INVALID; } } else { // Load states into RAM! @@ -228,6 +243,9 @@ void RenderableFieldlinesSequence::initialize() { return; } + // dictionary is no longer needed as everything is extracted + _dictionary.reset(); + // At this point there's at least one state loaded into memory! // No need to store source paths in memory if they are already in RAM! if (!_loadingStatesDynamically) { @@ -248,7 +266,7 @@ void RenderableFieldlinesSequence::initialize() { if (!_shaderProgram) { LERROR("Shader program failed initialization!"); - _sourceFileType = SourceFileType::INVALID; + sourceFileType = SourceFileType::INVALID; } //------------------ Initialize OpenGL VBOs and VAOs-------------------------------// @@ -259,42 +277,44 @@ void RenderableFieldlinesSequence::initialize() { // Needed for additive blending setRenderBin(Renderable::RenderBin::Overlay); + + _isReady = true; } -bool RenderableFieldlinesSequence::extractInfoFromDictionary( - const ghoul::Dictionary& dictionary) { +/* + * Returns false if it fails to extract mandatory information! + */ +bool RenderableFieldlinesSequence::extractMandatoryInfoFromDictionary( + SourceFileType& sourceFileType) { - std::string name; - dictionary.getValue(SceneGraphNode::KeyName, name); - _name = name; - name += ": "; + _dictionary->getValue(SceneGraphNode::KeyName, _name); // ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- // std::string inputFileTypeString; - if (!dictionary.getValue(KEY_INPUT_FILE_TYPE, inputFileTypeString)) { - LERROR(name << "The field " << std::string(KEY_INPUT_FILE_TYPE) << " is missing!"); + if (!_dictionary->getValue(KEY_INPUT_FILE_TYPE, inputFileTypeString)) { + LERROR(_name << ": The field " << std::string(KEY_INPUT_FILE_TYPE) << " is missing!"); return false; } else { std::transform(inputFileTypeString.begin(), inputFileTypeString.end(), inputFileTypeString.begin(), ::tolower); // Verify that the input type is correct if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_CDF) { - _sourceFileType = CDF; + sourceFileType = SourceFileType::CDF; } else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_JSON) { - _sourceFileType = JSON; + sourceFileType = SourceFileType::JSON; } else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_OSFLS) { - _sourceFileType = OSFLS; + sourceFileType = SourceFileType::OSFLS; } else { - LERROR(name << inputFileTypeString << " is not a recognised " + LERROR(_name << ": " << inputFileTypeString << " is not a recognised " << KEY_INPUT_FILE_TYPE); - _sourceFileType = INVALID; + sourceFileType = SourceFileType::INVALID; return false; } } std::string sourceFolderPath; - if (!dictionary.getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) { - LERROR(name << "The field " << std::string(KEY_SOURCE_FOLDER) << " is missing!"); + if (!_dictionary->getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) { + LERROR(_name << ": The field " << std::string(KEY_SOURCE_FOLDER) << " is missing!"); return false; } @@ -315,19 +335,25 @@ bool RenderableFieldlinesSequence::extractInfoFromDictionary( }), _sourceFiles.end()); // Ensure that there are available and valid source files left if (_sourceFiles.empty()) { - LERROR(name << sourceFolderPath << " contains no ." << inputFileTypeString + LERROR(_name << ": " << sourceFolderPath << " contains no ." << inputFileTypeString << " files!"); return false; } } else { - LERROR(name << "FieldlinesSequence" << sourceFolderPath + LERROR(_name << ": FieldlinesSequence" << sourceFolderPath << " is not a valid directory!"); return false; } + return true; +} + +void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( + std::string& outputFolderPath) { + // ------------------- EXTRACT OPTIONAL VALUES FROM DICTIONARY ------------------- // ghoul::Dictionary colorTablesPathsDictionary; - if (dictionary.getValue(KEY_COLOR_TABLE_PATHS, colorTablesPathsDictionary)) { + if (_dictionary->getValue(KEY_COLOR_TABLE_PATHS, colorTablesPathsDictionary)) { const size_t N_PROVIDED_PATHS = colorTablesPathsDictionary.size(); if (N_PROVIDED_PATHS > 0) { // Clear the default! It is already specified in the transferFunction @@ -340,7 +366,7 @@ bool RenderableFieldlinesSequence::extractInfoFromDictionary( } ghoul::Dictionary colorTablesRangesDictionary; - if (dictionary.getValue(KEY_COLOR_TABLE_RANGES, colorTablesRangesDictionary)) { + if (_dictionary->getValue(KEY_COLOR_TABLE_RANGES, colorTablesRangesDictionary)) { const size_t N_PROVIDED_RANGES = colorTablesRangesDictionary.size(); for (size_t i = 1; i <= N_PROVIDED_RANGES; ++i) { _colorTableRanges.push_back( @@ -350,30 +376,35 @@ bool RenderableFieldlinesSequence::extractInfoFromDictionary( _colorTableRanges.push_back(glm::vec2(0, 1)); } - // Extract info specific to each inputType - switch (_sourceFileType) { - case CDF: - LERROR(name << "CDF NOT YET IMPLEMENTED!"); - break; - case JSON: - LERROR(name << "JSON NOT YET IMPLEMENTED!"); - break; - case OSFLS: { - bool shouldLoadInRealtime = false; - if (dictionary.getValue(KEY_OSLFS_LOAD_AT_RUNTIME, shouldLoadInRealtime)) { - _loadingStatesDynamically = shouldLoadInRealtime; - } else { - LWARNING(name << KEY_OSLFS_LOAD_AT_RUNTIME << - " isn't specified! States from OSFLS files will be stored in RAM!"); - } - } break; - default: - break; + ghoul::Dictionary maskingRangesDictionary; + if (_dictionary->getValue(KEY_MASKING_RANGES, maskingRangesDictionary)) { + const size_t N_PROVIDED_RANGES = maskingRangesDictionary.size(); + for (size_t i = 1; i <= N_PROVIDED_RANGES; ++i) { + _maskingRanges.push_back( + maskingRangesDictionary.value(std::to_string(i))); + } + } else { + _maskingRanges.push_back(glm::vec2(-100000, 100000)); // Just some default values! } +} +/* + * Returns false if it fails to extract mandatory information! + */ +bool RenderableFieldlinesSequence::extractJsonInfoFromDictionary(fls::Model& model) { return true; } +void RenderableFieldlinesSequence::extractOsflsInfoFromDictionary() { + bool shouldLoadInRealtime = false; + if (_dictionary->getValue(KEY_OSLFS_LOAD_AT_RUNTIME, shouldLoadInRealtime)) { + _loadingStatesDynamically = shouldLoadInRealtime; + } else { + LWARNING(_name << ": " << KEY_OSLFS_LOAD_AT_RUNTIME << + " isn't specified! States will be stored in RAM!"); + } +} + void RenderableFieldlinesSequence::setupProperties() { // -------------- Add non-grouped properties (enablers and buttons) -------------- // addProperty(_pColorABlendEnabled); @@ -441,7 +472,6 @@ void RenderableFieldlinesSequence::setupProperties() { _pMaskingQuantity = 0; _pMaskingMin = std::to_string(_maskingRanges[_pMaskingQuantity].x); _pMaskingMax = std::to_string(_maskingRanges[_pMaskingQuantity].y); - } void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { From 0bb118b4cc6847fe4e8a6031363873936613969d Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Thu, 5 Oct 2017 01:40:02 +0200 Subject: [PATCH 22/47] Save state to JSON when input is .osfls and an output folder is specified in the lua-modfile --- .../renderablefieldlinessequencesetup.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index 5f960324b0..31ace78104 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -45,6 +45,7 @@ namespace { const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers const char* KEY_MASKING_RANGES = "MaskingRanges"; // [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers + const char* KEY_OUTPUT_FOLDER = "OutputFolder"; // [STRING] Value should be path to folder where states are saved (JSON/CDF input => osfls output & oslfs input => JSON output) const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // @@ -235,6 +236,11 @@ void RenderableFieldlinesSequence::initialize() { _states.push_back(newState); _startTimes.push_back(newState.triggerTime()); _nStates++; + + if (SHOULD_SAVE_STATES) { + ghoul::filesystem::File tmpFile(filePath); + newState.saveStateToJson(outputFolderPath + tmpFile.baseName()); + } } } } @@ -352,6 +358,16 @@ void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( std::string& outputFolderPath) { // ------------------- EXTRACT OPTIONAL VALUES FROM DICTIONARY ------------------- // + if (_dictionary->getValue(KEY_OUTPUT_FOLDER, outputFolderPath)) { + ghoul::filesystem::Directory outputFolder(outputFolderPath); + if (FileSys.directoryExists(outputFolder)) { + outputFolderPath = absPath(outputFolderPath); + } else { + LERROR(_name << ": The specified output path: '" << outputFolderPath << "', does not exist!"); + outputFolderPath = ""; + } + } + ghoul::Dictionary colorTablesPathsDictionary; if (_dictionary->getValue(KEY_COLOR_TABLE_PATHS, colorTablesPathsDictionary)) { const size_t N_PROVIDED_PATHS = colorTablesPathsDictionary.size(); From c4c576eaa2526d8b99fdbb71f4de5f3573874d31 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Thu, 5 Oct 2017 01:43:42 +0200 Subject: [PATCH 23/47] Load states from JSON into RAM and save to osfls if output folder is specified --- .../renderablefieldlinessequencesetup.cpp | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index 31ace78104..641dc90cb2 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -46,6 +46,8 @@ namespace { const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers const char* KEY_MASKING_RANGES = "MaskingRanges"; // [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers const char* KEY_OUTPUT_FOLDER = "OutputFolder"; // [STRING] Value should be path to folder where states are saved (JSON/CDF input => osfls output & oslfs input => JSON output) + const char* KEY_JSON_SIMULATION_MODEL = "SimulationModel"; // [STRING] + const char* KEY_JSON_SCALING_FACTOR = "ScaleToMeters"; // [STRING] const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // @@ -147,6 +149,17 @@ namespace { } return tmp; } + + openspace::fls::Model stringToModel(const std::string S) { + if (S == "batsrus") { + return openspace::fls::Model::BATSRUS; + } else if (S == "enlil") { + return openspace::fls::Model::ENLIL; + } else if (S == "pfss") { + return openspace::fls::Model::PFSS; + } + return openspace::fls::Model::INVALID; + } } // namespace namespace openspace { @@ -211,7 +224,28 @@ void RenderableFieldlinesSequence::initialize() { LERROR("CDF NOT YET IMPLEMENTED!"); return; break; case SourceFileType::JSON: - LERROR("JSON NOT YET IMPLEMENTED!"); return; + fls::Model model; + if (!extractJsonInfoFromDictionary(model)) { + return; + } + // Load states into RAM! + for (std::string filePath : _sourceFiles) { + FieldlinesState newState; + bool loadedSuccessfully = newState.loadStateFromJson(filePath, model, + _scalingFactor); + if (loadedSuccessfully) { + _states.push_back(newState); + _startTimes.push_back(newState.triggerTime()); + _nStates++; + if (SHOULD_SAVE_STATES) { + std::string pathSafeTimeString = Time(_startTimes.back()).ISO8601(); + pathSafeTimeString.replace(13, 1, "-"); + pathSafeTimeString.replace(16, 1, "-"); + pathSafeTimeString.replace(19, 1, "-"); + newState.saveStateToOsfls(outputFolderPath + pathSafeTimeString); + } + } + } break; case SourceFileType::OSFLS: extractOsflsInfoFromDictionary(); @@ -408,6 +442,22 @@ void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( * Returns false if it fails to extract mandatory information! */ bool RenderableFieldlinesSequence::extractJsonInfoFromDictionary(fls::Model& model) { + std::string modelStr; + if (_dictionary->getValue(KEY_JSON_SIMULATION_MODEL, modelStr)) { + std::transform(modelStr.begin(), modelStr.end(), modelStr.begin(), ::tolower); + model = stringToModel(modelStr); + } else { + LERROR(_name << ": Must specify '" << KEY_JSON_SIMULATION_MODEL << "'"); + return false; + } + + float scaleFactor; + if (_dictionary->getValue(KEY_JSON_SCALING_FACTOR, scaleFactor)) { + _scalingFactor = scaleFactor; + } else { + LWARNING(_name << ": Does not provide scalingFactor! " << + "Assumes coordinates are already expressed in meters!"); + } return true; } From caa98a4a629d23f51a4187cfd43c43e7f963ebb0 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 9 Oct 2017 19:45:04 +0200 Subject: [PATCH 24/47] Move stringToModel function to utils/commons.cpp --- modules/fieldlinessequence/CMakeLists.txt | 1 + .../renderablefieldlinessequencesetup.cpp | 13 +----- modules/fieldlinessequence/util/commons.cpp | 42 +++++++++++++++++++ modules/fieldlinessequence/util/commons.h | 2 +- 4 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 modules/fieldlinessequence/util/commons.cpp diff --git a/modules/fieldlinessequence/CMakeLists.txt b/modules/fieldlinessequence/CMakeLists.txt index 1fb4a1da1e..195e9d93d7 100644 --- a/modules/fieldlinessequence/CMakeLists.txt +++ b/modules/fieldlinessequence/CMakeLists.txt @@ -35,6 +35,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequence.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequencesetup.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/fieldlinesstate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/util/commons.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index 641dc90cb2..b126c689fa 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -149,17 +149,6 @@ namespace { } return tmp; } - - openspace::fls::Model stringToModel(const std::string S) { - if (S == "batsrus") { - return openspace::fls::Model::BATSRUS; - } else if (S == "enlil") { - return openspace::fls::Model::ENLIL; - } else if (S == "pfss") { - return openspace::fls::Model::PFSS; - } - return openspace::fls::Model::INVALID; - } } // namespace namespace openspace { @@ -445,7 +434,7 @@ bool RenderableFieldlinesSequence::extractJsonInfoFromDictionary(fls::Model& mod std::string modelStr; if (_dictionary->getValue(KEY_JSON_SIMULATION_MODEL, modelStr)) { std::transform(modelStr.begin(), modelStr.end(), modelStr.begin(), ::tolower); - model = stringToModel(modelStr); + model = fls::stringToModel(modelStr); } else { LERROR(_name << ": Must specify '" << KEY_JSON_SIMULATION_MODEL << "'"); return false; diff --git a/modules/fieldlinessequence/util/commons.cpp b/modules/fieldlinessequence/util/commons.cpp new file mode 100644 index 0000000000..76bedb6dc9 --- /dev/null +++ b/modules/fieldlinessequence/util/commons.cpp @@ -0,0 +1,42 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +namespace openspace { +namespace fls { + +Model stringToModel(const std::string S) { + if (S == "batsrus") { + return Model::BATSRUS; + } else if (S == "enlil") { + return Model::ENLIL; + } else if (S == "pfss") { + return Model::PFSS; + } + return Model::INVALID; +} + +} // namespace fls +} // namespace openspace \ No newline at end of file diff --git a/modules/fieldlinessequence/util/commons.h b/modules/fieldlinessequence/util/commons.h index f019070095..488f358451 100644 --- a/modules/fieldlinessequence/util/commons.h +++ b/modules/fieldlinessequence/util/commons.h @@ -37,7 +37,7 @@ enum Model : int { INVALID }; - +Model stringToModel(const std::string S); const float A_U_TO_METER = 149597870700.f; // Astronomical Units const float R_E_TO_METER = 6371000.f; // Earth radius From fad306d510e7d1a950b204f395f7395e573467a6 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 9 Oct 2017 20:26:02 +0200 Subject: [PATCH 25/47] Cleanup! Neater structure in initialize. --- .../rendering/renderablefieldlinessequence.h | 4 + .../renderablefieldlinessequencesetup.cpp | 113 ++++++++++-------- .../util/fieldlinesstate.cpp | 14 ++- 3 files changed, 80 insertions(+), 51 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index dcf7363c90..7fef4cb1cc 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -136,6 +136,7 @@ private: properties::TriggerProperty _pJumpToStartBtn; // Button which executes a time jump to start of sequence // --------------------- FUNCTIONS USED DURING INITIALIZATION --------------------- // + void addStateToSequence(FieldlinesState& STATE); void computeSequenceEndTime(); void definePropertyCallbackFunctions(); bool extractJsonInfoFromDictionary(fls::Model& model); @@ -143,8 +144,11 @@ private: void extractOptionalInfoFromDictionary(std::string& outputFolderPath); void extractOsflsInfoFromDictionary(); void extractTriggerTimesFromFileNames(); + bool loadJsonStatesIntoRAM(const std::string& OUTPUT_FOLDER); + void loadOsflsStatesIntoRAM(const std::string& OUTPUT_FOLDER); void setModelDependentConstants(); void setupProperties(); + bool prepareForOsflsStreaming(); // ------------------------- FUNCTIONS USED DURING RUNTIME ------------------------ // inline bool isWithinSequenceInterval(const double CURRENT_TIME) const; diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index b126c689fa..8343f6cddd 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -205,7 +205,6 @@ void RenderableFieldlinesSequence::initialize() { // EXTRACT OPTIONAL INFORMATION FROM DICTIONARY std::string outputFolderPath; extractOptionalInfoFromDictionary(outputFolderPath); - const bool SHOULD_SAVE_STATES = !outputFolderPath.empty(); // EXTRACT SOURCE FILE TYPE SPECIFIC INFOMRATION FROM DICTIONARY & GET STATES FROM SOURCE switch (sourceFileType) { @@ -213,59 +212,18 @@ void RenderableFieldlinesSequence::initialize() { LERROR("CDF NOT YET IMPLEMENTED!"); return; break; case SourceFileType::JSON: - fls::Model model; - if (!extractJsonInfoFromDictionary(model)) { + if (!loadJsonStatesIntoRAM(outputFolderPath)) { return; } - // Load states into RAM! - for (std::string filePath : _sourceFiles) { - FieldlinesState newState; - bool loadedSuccessfully = newState.loadStateFromJson(filePath, model, - _scalingFactor); - if (loadedSuccessfully) { - _states.push_back(newState); - _startTimes.push_back(newState.triggerTime()); - _nStates++; - if (SHOULD_SAVE_STATES) { - std::string pathSafeTimeString = Time(_startTimes.back()).ISO8601(); - pathSafeTimeString.replace(13, 1, "-"); - pathSafeTimeString.replace(16, 1, "-"); - pathSafeTimeString.replace(19, 1, "-"); - newState.saveStateToOsfls(outputFolderPath + pathSafeTimeString); - } - } - } break; case SourceFileType::OSFLS: extractOsflsInfoFromDictionary(); if (_loadingStatesDynamically) { - extractTriggerTimesFromFileNames(); - FieldlinesState newState; - bool loadedSuccessfully = newState.loadStateFromOsfls(_sourceFiles[0]); - if (loadedSuccessfully) { - _states.push_back(newState); - _nStates = _startTimes.size(); - _activeStateIndex = 0; - } else { - LERROR("The provided .osfls files seem to be corrupt!"); - sourceFileType = SourceFileType::INVALID; + if (!prepareForOsflsStreaming()) { + return; } } else { - // Load states into RAM! - for (std::string filePath : _sourceFiles) { - FieldlinesState newState; - bool loadedSuccessfully = newState.loadStateFromOsfls(filePath); - if (loadedSuccessfully) { - _states.push_back(newState); - _startTimes.push_back(newState.triggerTime()); - _nStates++; - - if (SHOULD_SAVE_STATES) { - ghoul::filesystem::File tmpFile(filePath); - newState.saveStateToJson(outputFolderPath + tmpFile.baseName()); - } - } - } + loadOsflsStatesIntoRAM(outputFolderPath); } break; default: @@ -275,12 +233,17 @@ void RenderableFieldlinesSequence::initialize() { // dictionary is no longer needed as everything is extracted _dictionary.reset(); - // At this point there's at least one state loaded into memory! // No need to store source paths in memory if they are already in RAM! if (!_loadingStatesDynamically) { _sourceFiles.clear(); } + // At this point there should be at least one state loaded into memory! + if (_states.size() == 0) { + LERROR("Wasn't able to extract any valid states from provided source files!"); + return; + } + computeSequenceEndTime(); setModelDependentConstants(); @@ -450,6 +413,56 @@ bool RenderableFieldlinesSequence::extractJsonInfoFromDictionary(fls::Model& mod return true; } +bool RenderableFieldlinesSequence::loadJsonStatesIntoRAM(const std::string& OUTPUT_FOLDER) { + fls::Model model; + if (!extractJsonInfoFromDictionary(model)) { + return false; + } + // Load states into RAM! + for (std::string filePath : _sourceFiles) { + FieldlinesState newState; + bool loadedSuccessfully = newState.loadStateFromJson(filePath, model, + _scalingFactor); + if (loadedSuccessfully) { + addStateToSequence(newState); + if (!OUTPUT_FOLDER.empty()) { + newState.saveStateToOsfls(OUTPUT_FOLDER); + } + } + } + return true; +} + +bool RenderableFieldlinesSequence::prepareForOsflsStreaming() { + extractTriggerTimesFromFileNames(); + FieldlinesState newState; + if (!newState.loadStateFromOsfls(_sourceFiles[0])) { + LERROR("The provided .osfls files seem to be corrupt!"); + return false; + } + _states.push_back(newState); + _nStates = _startTimes.size(); + _activeStateIndex = 0; + return true; + +} + +void RenderableFieldlinesSequence::loadOsflsStatesIntoRAM(const std::string& OUTPUT_FOLDER) { + // Load states from .osfls files into RAM! + for (const std::string FILEPATH : _sourceFiles) { + FieldlinesState newState; + if (newState.loadStateFromOsfls(FILEPATH)) { + addStateToSequence(newState); + if (!OUTPUT_FOLDER.empty()) { + ghoul::filesystem::File tmpFile(FILEPATH); + newState.saveStateToJson(OUTPUT_FOLDER + tmpFile.baseName()); + } + } else { + LWARNING("Failed to load state from: " << FILEPATH); + } + } +} + void RenderableFieldlinesSequence::extractOsflsInfoFromDictionary() { bool shouldLoadInRealtime = false; if (_dictionary->getValue(KEY_OSLFS_LOAD_AT_RUNTIME, shouldLoadInRealtime)) { @@ -664,4 +677,10 @@ void RenderableFieldlinesSequence::extractTriggerTimesFromFileNames() { } } +void RenderableFieldlinesSequence::addStateToSequence(FieldlinesState& state) { + _states.push_back(state); + _startTimes.push_back(state.triggerTime()); + _nStates++; +} + } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index 264513ce0c..ed7928d763 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -212,14 +212,20 @@ bool FieldlinesState::loadStateFromJson(const std::string& PATH_TO_JSON_FILE, * 11. array of c_str - Strings naming the extra quantities (elements of _extraQuantityNames). Each string ends with null char '\0' */ void FieldlinesState::saveStateToOsfls(const std::string& ABS_FILEPATH) { - // Create the file - const std::string EXT = ".osfls"; - std::ofstream ofs(ABS_FILEPATH + EXT, std::ofstream::binary | std::ofstream::trunc); + // ------------------------------- Create the file ------------------------------- // + std::string pathSafeTimeString = Time(_triggerTime).ISO8601(); + pathSafeTimeString.replace(13, 1, "-"); + pathSafeTimeString.replace(16, 1, "-"); + pathSafeTimeString.replace(19, 1, "-"); + const std::string FILENAME = pathSafeTimeString + ".osfls"; + + std::ofstream ofs(ABS_FILEPATH + FILENAME, std::ofstream::binary | std::ofstream::trunc); if (!ofs.is_open()) { - LERROR("Failed to save state to binary file: " << ABS_FILEPATH << EXT); + LERROR("Failed to save state to binary file: " << ABS_FILEPATH << FILENAME); return; } + // --------- Add each string of _extraQuantityNames into one long string --------- // std::string allExtraQuantityNamesInOne = ""; for (std::string str : _extraQuantityNames) { allExtraQuantityNamesInOne += str + '\0'; // Add the null char '\0' for easier reading From 3f756016e746c6089d5e0cd49da735078307f051 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 9 Oct 2017 21:20:26 +0200 Subject: [PATCH 26/47] Ensure no extraQuantity-dependent properties are added when there are no extraQuantities --- .../renderablefieldlinessequence.cpp | 2 - .../renderablefieldlinessequencesetup.cpp | 161 +++++++++--------- 2 files changed, 83 insertions(+), 80 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 2fb669f39f..c4a1cb89cf 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -209,8 +209,6 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { if (_states[_activeStateIndex].nExtraQuantities() > 0) { _shouldUpdateColorBuffer = true; _shouldUpdateMaskingBuffer = true; - } else { - _pColorMethod = ColorMethod::UNIFORM; } // Everything is set and ready for rendering! diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index 8343f6cddd..53e92a433b 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -474,11 +474,13 @@ void RenderableFieldlinesSequence::extractOsflsInfoFromDictionary() { } void RenderableFieldlinesSequence::setupProperties() { + bool hasExtras = _states[0].nExtraQuantities() > 0; + // -------------- Add non-grouped properties (enablers and buttons) -------------- // addProperty(_pColorABlendEnabled); addProperty(_pDomainEnabled); addProperty(_pFlowEnabled); - addProperty(_pMaskingEnabled); + if (hasExtras) { addProperty(_pMaskingEnabled); } addProperty(_pFocusOnOriginBtn); addProperty(_pJumpToStartBtn); @@ -486,111 +488,114 @@ void RenderableFieldlinesSequence::setupProperties() { addPropertySubOwner(_pColorGroup); addPropertySubOwner(_pDomainGroup); addPropertySubOwner(_pFlowGroup); - addPropertySubOwner(_pMaskingGroup); + if (hasExtras) { addPropertySubOwner(_pMaskingGroup); } // ------------------------- Add Properties to the groups ------------------------- // - _pColorGroup.addProperty(_pColorMethod); - _pColorGroup.addProperty(_pColorQuantity); - _pColorGroup.addProperty(_pColorQuantityMin); - _pColorGroup.addProperty(_pColorQuantityMax); - _pColorGroup.addProperty(_pColorTablePath); _pColorGroup.addProperty(_pColorUniform); - _pDomainGroup.addProperty(_pDomainX); _pDomainGroup.addProperty(_pDomainY); _pDomainGroup.addProperty(_pDomainZ); _pDomainGroup.addProperty(_pDomainR); - _pFlowGroup.addProperty(_pFlowReversed); _pFlowGroup.addProperty(_pFlowColor); _pFlowGroup.addProperty(_pFlowParticleSize); _pFlowGroup.addProperty(_pFlowParticleSpacing); _pFlowGroup.addProperty(_pFlowSpeed); + if (hasExtras) { + _pColorGroup.addProperty(_pColorMethod); + _pColorGroup.addProperty(_pColorQuantity); + _pColorGroup.addProperty(_pColorQuantityMin); + _pColorGroup.addProperty(_pColorQuantityMax); + _pColorGroup.addProperty(_pColorTablePath); + _pMaskingGroup.addProperty(_pMaskingMin); + _pMaskingGroup.addProperty(_pMaskingMax); + _pMaskingGroup.addProperty(_pMaskingQuantity); - _pMaskingGroup.addProperty(_pMaskingMin); - _pMaskingGroup.addProperty(_pMaskingMax); - _pMaskingGroup.addProperty(_pMaskingQuantity); - - // ----------------------- Add Options to OptionProperties ----------------------- // - _pColorMethod.addOption(ColorMethod::UNIFORM, "Uniform"); - _pColorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity"); - - /* Add option for each extra quantity. We assume that there are just as many names to - extra quantities as there are extra quantities. We also assume that all states in - the given sequence have the same extra quantities! */ - const size_t N_EXTRA_QUANTITIES = _states[0].nExtraQuantities(); - auto EXTRA_VARIABLE_NAMES_VEC = _states[0].extraQuantityNames(); - for (int i = 0; i < N_EXTRA_QUANTITIES; ++i) { - _pColorQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]); - _pMaskingQuantity.addOption(i, EXTRA_VARIABLE_NAMES_VEC[i]); + // --------------------- Add Options to OptionProperties --------------------- // + _pColorMethod.addOption(ColorMethod::UNIFORM, "Uniform"); + _pColorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity"); + // Add option for each extra quantity. Assumes there are just as many names to + // extra quantities as there are extra quantities. Also assume that all states in + // the given sequence have the same extra quantities! */ + const size_t N_EXTRA_QUANTITIES = _states[0].nExtraQuantities(); + const std::vector& XTRA_NAMES_VEC = _states[0].extraQuantityNames(); + for (int i = 0; i < N_EXTRA_QUANTITIES; ++i) { + _pColorQuantity.addOption(i, XTRA_NAMES_VEC[i]); + _pMaskingQuantity.addOption(i, XTRA_NAMES_VEC[i]); + } + // Each quantity should have its own color table and color table range, no more, no less + _colorTablePaths.resize(N_EXTRA_QUANTITIES, _colorTablePaths.back()); + _colorTableRanges.resize(N_EXTRA_QUANTITIES, _colorTableRanges.back()); + _maskingRanges.resize(N_EXTRA_QUANTITIES, _maskingRanges.back()); } - // Each quantity should have its own color table and color table range, no more, no less - _colorTablePaths.resize(N_EXTRA_QUANTITIES, _colorTablePaths.back()); - _colorTableRanges.resize(N_EXTRA_QUANTITIES, _colorTableRanges.back()); - _maskingRanges.resize(N_EXTRA_QUANTITIES, _maskingRanges.back()); definePropertyCallbackFunctions(); - // Set defaults - _pColorQuantity = 0; - _pColorQuantityMin = std::to_string(_colorTableRanges[_pColorQuantity].x); - _pColorQuantityMax = std::to_string(_colorTableRanges[_pColorQuantity].y); - _pColorTablePath = _colorTablePaths[_pColorQuantity]; + if (hasExtras) { + // Set defaults + _pColorQuantity = 0; + _pColorQuantityMin = std::to_string(_colorTableRanges[0].x); + _pColorQuantityMax = std::to_string(_colorTableRanges[0].y); + _pColorTablePath = _colorTablePaths[0]; - _pMaskingQuantity = 0; - _pMaskingMin = std::to_string(_maskingRanges[_pMaskingQuantity].x); - _pMaskingMax = std::to_string(_maskingRanges[_pMaskingQuantity].y); + _pMaskingQuantity = 0; + _pMaskingMin = std::to_string(_maskingRanges[0].x); + _pMaskingMax = std::to_string(_maskingRanges[0].y); + } } void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { // Add Property Callback Functions - _pColorQuantity.onChange([this] { - LDEBUG("CHANGED COLORING QUANTITY"); - _shouldUpdateColorBuffer = true; - _pColorQuantityMin = std::to_string(_colorTableRanges[_pColorQuantity].x); - _pColorQuantityMax = std::to_string(_colorTableRanges[_pColorQuantity].y); - _pColorTablePath = _colorTablePaths[_pColorQuantity]; - }); + bool hasExtras = _states[0].nExtraQuantities() > 0; + if (hasExtras) { + _pColorQuantity.onChange([this] { + LDEBUG("CHANGED COLORING QUANTITY"); + _shouldUpdateColorBuffer = true; + _pColorQuantityMin = std::to_string(_colorTableRanges[_pColorQuantity].x); + _pColorQuantityMax = std::to_string(_colorTableRanges[_pColorQuantity].y); + _pColorTablePath = _colorTablePaths[_pColorQuantity]; + }); - _pColorTablePath.onChange([this] { - _transferFunction->setPath(_pColorTablePath); - _colorTablePaths[_pColorQuantity] = _pColorTablePath; - }); + _pColorTablePath.onChange([this] { + _transferFunction->setPath(_pColorTablePath); + _colorTablePaths[_pColorQuantity] = _pColorTablePath; + }); - _pColorQuantityMin.onChange([this] { - LDEBUG("CHANGED MIN VALUE"); - float f = stringToFloat(_pColorQuantityMin, _colorTableRanges[_pColorQuantity].x); - _pColorQuantityMin = std::to_string(f); - _colorTableRanges[_pColorQuantity].x = f; - }); + _pColorQuantityMin.onChange([this] { + LDEBUG("CHANGED MIN VALUE"); + float f = stringToFloat(_pColorQuantityMin, _colorTableRanges[_pColorQuantity].x); + _pColorQuantityMin = std::to_string(f); + _colorTableRanges[_pColorQuantity].x = f; + }); - _pColorQuantityMax.onChange([this] { - LDEBUG("CHANGED MAX VALUE"); - float f = stringToFloat(_pColorQuantityMax, _colorTableRanges[_pColorQuantity].y); - _pColorQuantityMax = std::to_string(f); - _colorTableRanges[_pColorQuantity].y = f; - }); + _pColorQuantityMax.onChange([this] { + LDEBUG("CHANGED MAX VALUE"); + float f = stringToFloat(_pColorQuantityMax, _colorTableRanges[_pColorQuantity].y); + _pColorQuantityMax = std::to_string(f); + _colorTableRanges[_pColorQuantity].y = f; + }); - _pMaskingQuantity.onChange([this] { - LDEBUG("CHANGED MASKING QUANTITY"); - _shouldUpdateMaskingBuffer = true; - _pMaskingMin = std::to_string(_maskingRanges[_pMaskingQuantity].x); - _pMaskingMax = std::to_string(_maskingRanges[_pMaskingQuantity].y); - }); + _pMaskingQuantity.onChange([this] { + LDEBUG("CHANGED MASKING QUANTITY"); + _shouldUpdateMaskingBuffer = true; + _pMaskingMin = std::to_string(_maskingRanges[_pMaskingQuantity].x); + _pMaskingMax = std::to_string(_maskingRanges[_pMaskingQuantity].y); + }); - _pMaskingMin.onChange([this] { - LDEBUG("CHANGED LOWER MASKING LIMIT"); - float f = stringToFloat(_pMaskingMin, _maskingRanges[_pMaskingQuantity].x); - _pMaskingMin = std::to_string(f); - _maskingRanges[_pMaskingQuantity].x = f; - }); + _pMaskingMin.onChange([this] { + LDEBUG("CHANGED LOWER MASKING LIMIT"); + float f = stringToFloat(_pMaskingMin, _maskingRanges[_pMaskingQuantity].x); + _pMaskingMin = std::to_string(f); + _maskingRanges[_pMaskingQuantity].x = f; + }); - _pMaskingMax.onChange([this] { - LDEBUG("CHANGED UPPER MASKING LIMIT"); - float f = stringToFloat(_pMaskingMax, _maskingRanges[_pMaskingQuantity].y); - _pMaskingMax = std::to_string(f); - _maskingRanges[_pMaskingQuantity].y = f; - }); + _pMaskingMax.onChange([this] { + LDEBUG("CHANGED UPPER MASKING LIMIT"); + float f = stringToFloat(_pMaskingMax, _maskingRanges[_pMaskingQuantity].y); + _pMaskingMax = std::to_string(f); + _maskingRanges[_pMaskingQuantity].y = f; + }); + } _pFocusOnOriginBtn.onChange([this] { LDEBUG("SET FOCUS NODE TO PARENT"); From bf830731206cafa36d37b70ba49ac75cd520935b Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 9 Oct 2017 21:30:57 +0200 Subject: [PATCH 27/47] Add general helper functions for Kameleon --- modules/kameleon/CMakeLists.txt | 2 + modules/kameleon/include/kameleonhelper.h | 42 ++++++ modules/kameleon/src/kameleonhelper.cpp | 152 ++++++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 modules/kameleon/include/kameleonhelper.h create mode 100644 modules/kameleon/src/kameleonhelper.cpp diff --git a/modules/kameleon/CMakeLists.txt b/modules/kameleon/CMakeLists.txt index be287a3f30..cbd27c5872 100644 --- a/modules/kameleon/CMakeLists.txt +++ b/modules/kameleon/CMakeLists.txt @@ -26,11 +26,13 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/kameleonwrapper.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/kameleonhelper.h ) source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/kameleonwrapper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/kameleonhelper.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/kameleon/include/kameleonhelper.h b/modules/kameleon/include/kameleonhelper.h new file mode 100644 index 0000000000..6d89c87c2f --- /dev/null +++ b/modules/kameleon/include/kameleonhelper.h @@ -0,0 +1,42 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_KAMELEON___KAMELEONHELPER___H__ +#define __OPENSPACE_MODULE_KAMELEON___KAMELEONHELPER___H__ + +#include +#include + +namespace ccmc { + class Kameleon; +} // namespace ccmc + +namespace openspace::kameleonHelper { + + std::unique_ptr createKameleonObject(const std::string& CDF_FILE_PATH); + double getTime(ccmc::Kameleon* kameleon); + +} //namespace openspace::kameleonHelper + +#endif // __OPENSPACE_MODULE_KAMELEON___KAMELEONHELPER___H__ diff --git a/modules/kameleon/src/kameleonhelper.cpp b/modules/kameleon/src/kameleonhelper.cpp new file mode 100644 index 0000000000..8ee44abd60 --- /dev/null +++ b/modules/kameleon/src/kameleonhelper.cpp @@ -0,0 +1,152 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +#include +#include + + +namespace { + std::string _loggerCat = "KameleonHelper"; +} + +namespace openspace::kameleonHelper { + +/** + * Opens a ccmc::Kameleon object from the provided path to a .cdf file. + * Path should be absolute. + * + * Returns 'nullptr' if the file fails to open! + */ +std::unique_ptr createKameleonObject(const std::string& CDF_FILE_PATH) { + + // ---------------------------- CREATE KAMELEON OBJECT ---------------------------- // + std::unique_ptr kameleon = std::make_unique(); + LDEBUG("\tOpening the cdf file: " << CDF_FILE_PATH); + long kamStatus = kameleon->open(CDF_FILE_PATH); + + if (kamStatus != ccmc::FileReader::OK) { + LERROR("Failed to create a Kameleon Object from file: " << CDF_FILE_PATH); + return nullptr; + } + LDEBUG("\tSuccessfully opened : " << CDF_FILE_PATH); + return kameleon; +} + +/** + * Extract the time for the simulation. Time is returned as a J2000 double. + * + * *NOTE!* The function has only been tested for some BATSRUS and ENLIL and may need to + * be updated to work with other models! + */ +double getTime(ccmc::Kameleon* kameleon) { + // Inspiration from 'void KameleonInterpolator::setEphemTime()' which doesn't seem to + // exist in the version of Kameleon that is included in OpenSpace. Alterations + // done to fit here. + // As a new version of Kameleon is included in OpenSpace this function may prove to be + // redundant! + + std::string seqStartStr; + double seqStartDbl; + if (kameleon->doesAttributeExist("start_time")){ + seqStartStr = + kameleon->getGlobalAttribute("start_time").getAttributeString(); + } else if (kameleon->doesAttributeExist("tim_rundate_cal")) { + seqStartStr = + kameleon->getGlobalAttribute("tim_rundate_cal").getAttributeString(); + const size_t N_CHARS = seqStartStr.length(); + if (N_CHARS < 19) { + // Fall through to add the required characters + switch (N_CHARS) { + case 10 : // YYYY-MM-DD => YYYY-MM-DDTHH + seqStartStr += "T00"; + case 13 : // YYYY-MM-DDTHH => YYYY-MM-DDTHH: + seqStartStr += ":"; + case 14 : // YYYY-MM-DDTHH: => YYYY-MM-DDTHH:MM + seqStartStr += "00"; + case 16 : // YYYY-MM-DDTHH:MM => YYYY-MM-DDTHH:MM: + seqStartStr += ":"; + case 17 : // YYYY-MM-DDTHH:MM: => YYYY-MM-DDTHH:MM:SS + seqStartStr += "00"; + // case 19 : // YYYY-MM-DDTHH:MM:SS => YYYY-MM-DDTHH:MM:SS.000 + // seqStartStr += ".000"; + // case 23 : // YYYY-MM-DDTHH:MM:SS. => YYYY-MM-DDTHH:MM:SS.000Z + // seqStartStr += "Z"; + default : + break; + } + } + // else if (seqStartStr.length() < 19 && kameleon->doesAttributeExist("tim_crstart_cal")) { + // seqStartStr = + // kameleon->getGlobalAttribute("tim_crstart_cal").getAttributeString(); + // } + } else if (kameleon->doesAttributeExist("tim_obsdate_cal")) { + seqStartStr = + kameleon->getGlobalAttribute("tim_obsdate_cal").getAttributeString(); + } else if (kameleon->doesAttributeExist("tim_crstart_cal")) { + seqStartStr = + kameleon->getGlobalAttribute("tim_crstart_cal").getAttributeString(); + } else { + LWARNING("No starting time attribute could be found in the .cdf file.\n\t" << + "Starting time is set to 01.JAN.2000 12:00."); + seqStartDbl = 0.0; + } + + if (seqStartStr.length() == 19){ + seqStartStr += ".000Z"; + } + + if (seqStartStr.length() == 24){ + seqStartDbl = + Time::convertTime( + seqStartStr.substr(0, seqStartStr.length() - 2)); + } else { + LWARNING("No starting time attribute could be found in the .cdf file.\n\t" << + "Starting time is set to 01.JAN.2000 12:00."); + seqStartDbl = 0.0; + } + + double stateStartOffset; + + if (kameleon->doesAttributeExist("elapsed_time_in_seconds")) { + stateStartOffset = static_cast( + kameleon->getGlobalAttribute( + "elapsed_time_in_seconds").getAttributeFloat()); + } else if (kameleon->doesAttributeExist("time_physical_time")) { + stateStartOffset = static_cast( + kameleon->getGlobalAttribute( + "time_physical_time").getAttributeFloat()); + } else { + stateStartOffset = 0.0; + LWARNING("No time offset attribute could be found in the .cdf file.\n\t" << + "The current state starts the same time as the sequence!"); + } + + return seqStartDbl + stateStartOffset; +} + +} // namespace openspace::kameleonHelper { From 4fc88c595f3b68cfbc70bb58e232197050576cb6 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 9 Oct 2017 21:56:47 +0200 Subject: [PATCH 28/47] Load CDFs and trace field lines using kameleon and store the info in FieldlinesState. --- .../rendering/renderablefieldlinessequence.h | 9 ++ .../renderablefieldlinessequencesetup.cpp | 150 +++++++++++++++++- .../util/fieldlinesstate.cpp | 104 ++++++++++++ .../fieldlinessequence/util/fieldlinesstate.h | 16 ++ 4 files changed, 275 insertions(+), 4 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 7fef4cb1cc..b61b5667f7 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -149,6 +149,15 @@ private: void setModelDependentConstants(); void setupProperties(); bool prepareForOsflsStreaming(); +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + // --- Initialization functions which require the kameleon module to be loaded! --- // + bool extractCdfInfoFromDictionary(std::string& seedFilePath, + std::string& tracingVar, + std::vector& extraVars); + bool extractSeedPointsFromFile(const std::string& path, + std::vector& outVec); + bool getStatesFromCdfFiles(const std::string& OUTPUT_FOLDER); +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED // ------------------------- FUNCTIONS USED DURING RUNTIME ------------------------ // inline bool isWithinSequenceInterval(const double CURRENT_TIME) const; diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index 53e92a433b..c4e1d78b8c 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -24,6 +24,11 @@ #include +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + #include + #include +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + #include #include #include @@ -33,6 +38,9 @@ #include #include +#include +#include + namespace { std::string _loggerCat = "RenderableFieldlinesSequence"; @@ -41,14 +49,21 @@ namespace { const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] + // ---------------------- MANDATORY INPUT TYPE SPECIFIC KEYS ---------------------- // + const char* KEY_CDF_SEED_POINT_FILE = "SeedPointFile"; // [STRING] Path to a .txt file containing seed points + const char* KEY_JSON_SIMULATION_MODEL = "SimulationModel"; // [STRING] Currently supports: "batsrus", "enlil" & "pfss" + + // ----------------------- OPTIONAL INPUT TYPE SPECIFIC KEYS ---------------------- // + const char* KEY_CDF_EXTRA_VARIABLES = "ExtraVariables"; // [STRING ARRAY] + const char* KEY_CDF_TRACING_VARIABLE = "TracingVariable"; // [STRING] + const char* KEY_JSON_SCALING_FACTOR = "ScaleToMeters"; // [STRING] + const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM + // ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- // const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers const char* KEY_MASKING_RANGES = "MaskingRanges"; // [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers const char* KEY_OUTPUT_FOLDER = "OutputFolder"; // [STRING] Value should be path to folder where states are saved (JSON/CDF input => osfls output & oslfs input => JSON output) - const char* KEY_JSON_SIMULATION_MODEL = "SimulationModel"; // [STRING] - const char* KEY_JSON_SCALING_FACTOR = "ScaleToMeters"; // [STRING] - const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf"; @@ -209,7 +224,11 @@ void RenderableFieldlinesSequence::initialize() { // EXTRACT SOURCE FILE TYPE SPECIFIC INFOMRATION FROM DICTIONARY & GET STATES FROM SOURCE switch (sourceFileType) { case SourceFileType::CDF: - LERROR("CDF NOT YET IMPLEMENTED!"); return; +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + if (!getStatesFromCdfFiles(outputFolderPath)) { + return; + } +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED break; case SourceFileType::JSON: if (!loadJsonStatesIntoRAM(outputFolderPath)) { @@ -292,6 +311,10 @@ bool RenderableFieldlinesSequence::extractMandatoryInfoFromDictionary( // Verify that the input type is correct if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_CDF) { sourceFileType = SourceFileType::CDF; +#ifndef OPENSPACE_MODULE_KAMELEON_ENABLED + LERROR(_name << ": CDF file inputs requires the 'Kameleon' module to be enabled!"); + return false; +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED } else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_JSON) { sourceFileType = SourceFileType::JSON; } else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_OSFLS) { @@ -688,4 +711,123 @@ void RenderableFieldlinesSequence::addStateToSequence(FieldlinesState& state) { _nStates++; } +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& OUTPUT_FOLDER) { + + std::string seedFilePath; + std::string tracingVar; + std::vector extraVars; + if (!extractCdfInfoFromDictionary(seedFilePath, tracingVar, extraVars)) { + return false; + } + + std::vector seedPoints; + if (!extractSeedPointsFromFile(seedFilePath, seedPoints)) { + return false; + } + + // Load states into RAM! + for (std::string filePath : _sourceFiles) { + // Create Kameleon object and open CDF file! + std::unique_ptr kameleon = + kameleonHelper::createKameleonObject(filePath); + + FieldlinesState newState; + newState.setTriggerTime(kameleonHelper::getTime(kameleon.get())); + + if (newState.addLinesFromKameleon(kameleon.get(), seedPoints, tracingVar)) { + switch (newState.model()) { + case fls::BATSRUS: + newState.scalePositions(fls::R_E_TO_METER); + break; + case fls::ENLIL : + newState.convertLatLonToCartesian(fls::A_U_TO_METER); + break; + default: + break; + } + + addStateToSequence(newState); + if (!OUTPUT_FOLDER.empty()) { + newState.saveStateToOsfls(OUTPUT_FOLDER); + } + } + } + return true; +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +/* + * Returns false if it fails to extract mandatory information! + */ +bool RenderableFieldlinesSequence::extractCdfInfoFromDictionary( + std::string& seedFilePath, + std::string& tracingVar, + std::vector& extraVars) { + + if (_dictionary->getValue(KEY_CDF_SEED_POINT_FILE, seedFilePath)) { + ghoul::filesystem::File seedPointFile(seedFilePath); + if (FileSys.fileExists(seedPointFile)) { + seedFilePath = absPath(seedFilePath); + } else { + LERROR(_name << ": The specified seed point file: '" << seedFilePath + << "', does not exist!"); + return false; + } + } else { + LERROR(_name << ": Must specify '" << KEY_CDF_SEED_POINT_FILE << "'"); + return false; + } + + if (!_dictionary->getValue(KEY_CDF_TRACING_VARIABLE, tracingVar)) { + tracingVar = "b"; // Magnetic field variable as default + LWARNING(_name << ": No '" << KEY_CDF_TRACING_VARIABLE << "', using default: " + << tracingVar); + } + + ghoul::Dictionary extraQuantityNamesDictionary; + if (_dictionary->getValue(KEY_CDF_EXTRA_VARIABLES, extraQuantityNamesDictionary)) { + const size_t N_PROVIDED_EXTRAS = extraQuantityNamesDictionary.size(); + for (size_t i = 1; i <= N_PROVIDED_EXTRAS; ++i) { + extraVars.push_back( + extraQuantityNamesDictionary.value(std::to_string(i))); + } + } + + return true; +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +bool RenderableFieldlinesSequence::extractSeedPointsFromFile( + const std::string& path, + std::vector& outVec) { + + std::ifstream seedFile(FileSys.relativePath(path)); + if (!seedFile.good()) { + LERROR("Could not open seed points file '" << path << "'"); + return false; + } + + LDEBUG("Reading seed points from file '" << path << "'"); + std::string line; + while (std::getline(seedFile, line)) { + glm::vec3 point; + std::stringstream ss(line); + ss >> point.x; + ss >> point.y; + ss >> point.z; + outVec.push_back(std::move(point)); + } + + if (outVec.size() == 0) { + LERROR("Found no seed points in: " << path); + return false; + } + + return true; +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index ed7928d763..6dd298b0e7 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -25,16 +25,27 @@ #include #include + #include #include #include +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + #include + #include + #include +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + namespace { std::string _loggerCat = "FieldlinesState"; const int CURRENT_VERSION = 0; + const std::string T_AS_P_OVER_RHO = "T = p/rho"; + const std::string J_PARALLEL_B = "Current: mag(J||B)"; + const float TO_KELVIN = 72429735.6984f; // <-- [nPa]/[amu/cm^3] * TO_KELVIN => Temperature in Kelvin + using json = nlohmann::json; } @@ -45,6 +56,99 @@ FieldlinesState::FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& lo loadSucessful = loadStateFromOsfls(PATH_TO_OSFLS_FILE); } +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +/** + * Traces and adds line vertices to state. (Also sets the simulation model variable: _model!) + * Vertices may need to be scaled to meters & converted from spherical into cartesian coordinates. + * Note that extraQuantities will NOT be set! + */ +bool FieldlinesState::addLinesFromKameleon(ccmc::Kameleon* kameleon, + const std::vector& SEED_POINTS, + const std::string TRACING_VAR) { + + _model = fls::stringToModel(kameleon->getModelName()); + + float innerBoundaryLimit; + + switch (_model) { + case fls::Model::BATSRUS : + innerBoundaryLimit = 2.5f; // TODO specify in Lua? + break; + case fls::Model::ENLIL : + innerBoundaryLimit = 0.11f; // TODO specify in Lua? + break; + default: + LERROR("OpenSpace's fieldlines sequence currently only supports CDFs from" << + "the BATSRUS and ENLIL models!" ); + return false; + } + + // --------------------------- LOAD TRACING VARIABLE ---------------------------- // + if (!kameleon->loadVariable(TRACING_VAR)) { + LERROR("FAILED TO LOAD TRACING VARIABLE: " << TRACING_VAR); + return false; + } + + LINFO("TRACING FIELD LINES!"); + // - LOOP THROUGH THE SEED POINTS, TRACE LINES AND CONVERT TO THE DESIRED FORMAT - // + size_t lineStart = 0; + for (glm::vec3 seed : SEED_POINTS) { + //--------------------------------------------------------------------------// + // We have to create a new tracer (or actually a new interpolator) for each // + // new line, otherwise some issues occur // + //--------------------------------------------------------------------------// + std::unique_ptr interpolator = + std::make_unique(kameleon->model); + ccmc::Tracer tracer(kameleon, interpolator.get()); + tracer.setInnerBoundary(innerBoundaryLimit); // TODO specify in Lua? + ccmc::Fieldline ccmcFieldline = tracer.bidirectionalTrace(TRACING_VAR, + seed.x, + seed.y, + seed.z); + const std::vector& POSITIONS = ccmcFieldline.getPositions(); + + _lineStart.push_back(lineStart); + const size_t N_LINE_POINTS = POSITIONS.size(); + _lineCount.push_back(static_cast(N_LINE_POINTS)); + lineStart += static_cast(N_LINE_POINTS); + + for (const ccmc::Point3f& p : POSITIONS) { + _vertexPositions.emplace_back( + glm::vec3(p.component1, p.component2, p.component3)); + } + } + + return _vertexPositions.size() > 0; +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +/** +* Converts all glm::vec3 in _vertexPositions from spherical (radius, latitude, longitude) +* coordinates into cartesian coordinates. The longitude and latitude coordinates are +* expected to be in degrees. SCALE is an optional scaling factor. +*/ +void FieldlinesState::convertLatLonToCartesian(const float SCALE /* = 1.f */) { + for (glm::vec3& p : _vertexPositions) { + + const float R = p.x * SCALE; + const float LAT = glm::radians(p.y); + const float LON = glm::radians(p.z); + const float R_COS_LAT = R * cos(LAT); + + p = glm::vec3(R_COS_LAT * cos(LON), R_COS_LAT* sin(LON), R * sin(LAT)); + } +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +void FieldlinesState::scalePositions(const float SCALE) { + for (glm::vec3& p : _vertexPositions) { + p *= SCALE; + } +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) { std::ifstream ifs(PATH_TO_OSFLS_FILE, std::ifstream::binary); if (!ifs.is_open()) { diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index a4f2a9b50e..076a025462 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -35,6 +35,12 @@ using std::vector; +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +namespace ccmc { + class Kameleon; +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + namespace openspace { class FieldlinesState { @@ -42,6 +48,14 @@ public: FieldlinesState(); FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& loadSucessful); +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + bool addLinesFromKameleon(ccmc::Kameleon* kameleon, + const vector& SEED_POINTS, + const std::string TRACING_VAR); + void convertLatLonToCartesian(const float SCALE = 1.f); + void scalePositions(const float SCALE); +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE); void saveStateToOsfls(const std::string& PATH_TO_OSFLS_FILE); @@ -62,6 +76,8 @@ public: // Special getter. Returns extraQuantities[INDEX]. const vector& extraQuantity(const size_t INDEX, bool& isSuccesful) const; + void setTriggerTime(const double T) { _triggerTime = T; } + private: bool _isMorphable = false; double _triggerTime = -1.0; From 173a32b0203e0125f2d5e727212994782a9a4bcc Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 9 Oct 2017 22:16:57 +0200 Subject: [PATCH 29/47] Add extraQuanities to FieldlinesState from cdf source --- .../rendering/renderablefieldlinessequence.h | 2 + .../renderablefieldlinessequencesetup.cpp | 39 +++++ .../util/fieldlinesstate.cpp | 149 ++++++++++++++++++ .../fieldlinessequence/util/fieldlinesstate.h | 8 + 4 files changed, 198 insertions(+) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index b61b5667f7..a9f3b8d233 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -156,6 +156,8 @@ private: std::vector& extraVars); bool extractSeedPointsFromFile(const std::string& path, std::vector& outVec); + void extractMagnitudeVarsFromStrings(std::vector& extraVars, + std::vector& extraMagVars); bool getStatesFromCdfFiles(const std::string& OUTPUT_FOLDER); #endif // OPENSPACE_MODULE_KAMELEON_ENABLED diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index c4e1d78b8c..0abd7901db 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -726,6 +726,9 @@ bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& OUTP return false; } + std::vector extraMagVars; + extractMagnitudeVarsFromStrings(extraVars, extraMagVars); + // Load states into RAM! for (std::string filePath : _sourceFiles) { // Create Kameleon object and open CDF file! @@ -736,6 +739,10 @@ bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& OUTP newState.setTriggerTime(kameleonHelper::getTime(kameleon.get())); if (newState.addLinesFromKameleon(kameleon.get(), seedPoints, tracingVar)) { + // The line points are in their RAW format (unscaled & maybe spherical) + // Before we scale to meters (and maybe cartesian) we must extract + // the extraQuantites, as the iterpolator needs the unaltered positions + newState.addExtraQuantities(kameleon.get(), extraVars, extraMagVars); switch (newState.model()) { case fls::BATSRUS: newState.scalePositions(fls::R_E_TO_METER); @@ -830,4 +837,36 @@ bool RenderableFieldlinesSequence::extractSeedPointsFromFile( } #endif // OPENSPACE_MODULE_KAMELEON_ENABLED +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +void RenderableFieldlinesSequence::extractMagnitudeVarsFromStrings( + std::vector& extraVars, + std::vector& extraMagVars) { + + + for (int i = 0; i < extraVars.size(); i++) { + const std::string STR = extraVars[i]; + // Check if string is in the format specified for magnitude variables + if (STR.substr(0, 2) == "|(" && STR.substr(STR.size() - 2, 2) == ")|") { + std::istringstream ss(STR.substr(2, STR.size() - 4)); + std::string magVar; + size_t counter = 0; + while(std::getline(ss, magVar, ',')) { + magVar.erase(std::remove_if(magVar.begin(), magVar.end(), ::isspace), + magVar.end()); + extraMagVars.push_back(magVar); + counter++; + if (counter == 3) { + break; + } + } + if (counter != 3 && counter > 0) { + extraMagVars.erase(extraMagVars.end() - counter, extraMagVars.end()); + } + extraVars.erase(extraVars.begin() + i); + i--; + } + } +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index 6dd298b0e7..9ffa156c3b 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -122,6 +122,155 @@ bool FieldlinesState::addLinesFromKameleon(ccmc::Kameleon* kameleon, } #endif // OPENSPACE_MODULE_KAMELEON_ENABLED +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +void FieldlinesState::loadExtrasIntoKameleon(ccmc::Kameleon* kameleon, + std::vector& xtraScalarVars, + std::vector& xtraMagVars) { + // Load the existing SCALAR variables into kameleon. + // Remove non-existing variables from vector + for (int i = 0; i < xtraScalarVars.size(); i++) { + std::string& str = xtraScalarVars[i]; + bool isSuccesful = kameleon->doesVariableExist(str) && kameleon->loadVariable(str); + if (!isSuccesful && + (_model == fls::Model::BATSRUS && (str == T_AS_P_OVER_RHO || str == "T" ))) { + LDEBUG("BATSRUS doesn't contain variable T for temperature. Trying to " + << "calculate it using the ideal gas law: T = pressure/density"); + const std::string P = "p", R = "rho"; + isSuccesful = kameleon->doesVariableExist(P) && kameleon->loadVariable(P) + && kameleon->doesVariableExist(R) && kameleon->loadVariable(R); + str = T_AS_P_OVER_RHO; + } + if (!isSuccesful) { + LWARNING("FAILED TO LOAD EXTRA VARIABLE: '" << str << "'. Ignoring it!"); + xtraScalarVars.erase(xtraScalarVars.begin() + i); + --i; + } else { + _extraQuantityNames.push_back(str); + } + } + + // Load the existing magnitude variables (should be provided in multiple of 3) + // into kameleon. Remove non-existing variables from vector + if (xtraMagVars.size() % 3 == 0) { + for (int i = 0; i < static_cast(xtraMagVars.size()); i += 3) { + std::string s1 = xtraMagVars[i]; + std::string s2 = xtraMagVars[i+1]; + std::string s3 = xtraMagVars[i+2]; + bool isSuccesful = kameleon->doesVariableExist(s1) && + kameleon->doesVariableExist(s2) && + kameleon->doesVariableExist(s3) && + kameleon->loadVariable(s1) && + kameleon->loadVariable(s2) && + kameleon->loadVariable(s3); + std::string name = "Magnitude of (" + s1 + ", "+ s2 + ", "+ s3 + ")"; + if (isSuccesful && _model == fls::Model::BATSRUS && s1 == "jx" && s2 == "jy" + && s3 == "jz") { + // CCMC isn't really interested in the magnitude of current, but by the + // magnitude of the part of the current's vector that is parallel to the + // magnetic field => ensure that the magnetic variables are loaded + isSuccesful = kameleon->doesVariableExist("bx") && + kameleon->doesVariableExist("by") && + kameleon->doesVariableExist("bz") && + kameleon->loadVariable("bx") && + kameleon->loadVariable("by") && + kameleon->loadVariable("bz"); + name = J_PARALLEL_B; + } + if (!isSuccesful) { + LWARNING("FAILED TO LOAD AT LEAST ONE OF THE MAGNITUDE VARIABLES: " + << s1 << ", " << s2 << " & " << s3 + << ". Removing ability to store corresponding magnitude!"); + xtraMagVars.erase(xtraMagVars.begin() + i, xtraMagVars.begin() + i + 3); + i -= 3; + } else { + _extraQuantityNames.push_back(name); + } + } + } else { + // WRONG NUMBER OF MAGNITUDE VARIABLES.. REMOVE ALL! + xtraMagVars.clear(); + LWARNING("Wrong number of variables provided for storing magnitudes. " + << "Expects multiple of 3 but " << xtraMagVars.size() + << " are provided"); + } +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +/** + * Loops through _vertexPositions and extracts corresponding 'extraQuantities' att each + * position from the kameleon object using a ccmc::interpolator. + * Note that the positions MUST be unaltered (NOT scaled NOR converted to different + * coordinate system)! + * + * @param kameleon raw pointer to an already opened Kameleon object + * @param xtraScalarVars vector of strings. Strings should be names of a scalar quantities + * to load into _extraQuantites; such as: "T" for temperature or "rho" for density. + * @param xtraMagVars vector of strings. Size must be multiple of 3. Strings should be + * names of the components needed to calculate magnitude. E.g. {"ux", "uy", "uz"} will + * calculate: sqrt(ux*ux + uy*uy + uz*uz). Magnitude will be stored in _extraQuantities + */ +void FieldlinesState::addExtraQuantities(ccmc::Kameleon* kameleon, + std::vector& xtraScalarVars, + std::vector& xtraMagVars) { + + loadExtrasIntoKameleon(kameleon, xtraScalarVars, xtraMagVars); + + const size_t N_XTRA_SCALARS = xtraScalarVars.size(); + const size_t N_XTRA_MAGNITUDES = xtraMagVars.size() / 3; + + _extraQuantities.resize(N_XTRA_SCALARS + N_XTRA_MAGNITUDES); + + std::unique_ptr interpolator = + std::make_unique(kameleon->model); + + // ------ Extract all the extraQuantities from kameleon and store in state! ------ // + for (const glm::vec3& P : _vertexPositions) { + // Load the scalars! + for (size_t i = 0; i < N_XTRA_SCALARS; i++) { + float val; + if (xtraScalarVars[i] == T_AS_P_OVER_RHO) { + val = interpolator->interpolate("p", P.x, P.y, P.z); + val *= TO_KELVIN; + val /= interpolator->interpolate("rho", P.x, P.y, P.z); + } else { + val = interpolator->interpolate(xtraScalarVars[i], P.x, P.y, P.z); + + // When measuring density in ENLIL CCMC multiply by the radius^2 + if (xtraScalarVars[i] == "rho" && _model == fls::Model::ENLIL) { + val *= std::pow(P.x * fls::A_U_TO_METER, 2.0f); + } + } + _extraQuantities[i].push_back(val); + } + // Calculate and store the magnitudes! + for (size_t i = 0; i < N_XTRA_MAGNITUDES; ++i) { + const size_t IDX = i*3; + + const float X = interpolator->interpolate(xtraMagVars[IDX] , P.x, P.y, P.z); + const float Y = interpolator->interpolate(xtraMagVars[IDX+1], P.x, P.y, P.z); + const float Z = interpolator->interpolate(xtraMagVars[IDX+2], P.x, P.y, P.z); + float val; + // When looking at the current's magnitude in Batsrus, CCMC staff are + // only interested in the magnitude parallel to the magnetic field + if (_extraQuantityNames[N_XTRA_SCALARS + i] == J_PARALLEL_B) { + const glm::vec3 NORM_MAGNETIC = glm::normalize(glm::vec3( + interpolator->interpolate("bx", P.x, P.y, P.z), + interpolator->interpolate("by", P.x, P.y, P.z), + interpolator->interpolate("bz", P.x, P.y, P.z))); + // Magnitude of the part of the current vector that's parallel to + // the magnetic field vector! + val = glm::dot(glm::vec3(X,Y,Z), NORM_MAGNETIC); + + } else { + val = std::sqrt(X*X + Y*Y + Z*Z); + } + _extraQuantities[i + N_XTRA_SCALARS].push_back(val); + } + } +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED /** * Converts all glm::vec3 in _vertexPositions from spherical (radius, latitude, longitude) diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index 076a025462..55bdde6f7e 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -52,6 +52,8 @@ public: bool addLinesFromKameleon(ccmc::Kameleon* kameleon, const vector& SEED_POINTS, const std::string TRACING_VAR); + void addExtraQuantities(ccmc::Kameleon* kameleon, vector& xtraScalarVars, + vector& xtraMagVars); void convertLatLonToCartesian(const float SCALE = 1.f); void scalePositions(const float SCALE); #endif // OPENSPACE_MODULE_KAMELEON_ENABLED @@ -88,6 +90,12 @@ private: vector _lineCount; vector> _extraQuantities; vector _extraQuantityNames; + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + void loadExtrasIntoKameleon(ccmc::Kameleon* kameleon, + vector& xtraScalarVars, + vector& xtraMagVars); +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED // TODO: Maybe introduce a vector containing seed point indices }; From bb43dace322e3440b91d2479db7a4d21c1ae9ff1 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 9 Oct 2017 22:44:33 +0200 Subject: [PATCH 30/47] Cleanup minor things --- .../renderablefieldlinessequencesetup.cpp | 12 +++-- .../shaders/fieldlinessequence_fs.glsl | 5 +- .../shaders/fieldlinessequence_vs.glsl | 4 +- .../util/fieldlinesstate.cpp | 9 +--- .../fieldlinessequence/util/fieldlinesstate.h | 50 +++++++++---------- 5 files changed, 35 insertions(+), 45 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index 0abd7901db..f87df3726a 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -46,8 +46,8 @@ namespace { // ----- KEYS POSSIBLE IN MODFILE. EXPECTED DATA TYPE OF VALUE IN [BRACKETS] ----- // // ---------------------------- MANDATORY MODFILE KEYS ---------------------------- // - const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] - const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] + const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] "cdf", "json" or "osfls" + const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] should be path to folder containing the input files // ---------------------- MANDATORY INPUT TYPE SPECIFIC KEYS ---------------------- // const char* KEY_CDF_SEED_POINT_FILE = "SeedPointFile"; // [STRING] Path to a .txt file containing seed points @@ -213,7 +213,7 @@ void RenderableFieldlinesSequence::initialize() { return; } - // Set the default color table, just in case the (optional) user defined paths are corrupt! + // Set a default color table, just in case the (optional) user defined paths are corrupt/not provided! _colorTablePaths.push_back("${OPENSPACE_DATA}/colortables/kroyw.txt"); _transferFunction = std::make_shared(absPath(_colorTablePaths[0])); @@ -292,7 +292,9 @@ void RenderableFieldlinesSequence::initialize() { _isReady = true; } -/* +/** + * Extracts the general information (from the lua modfile) that is mandatory for the class + * to function; such as the file type and the location of the source files. * Returns false if it fails to extract mandatory information! */ bool RenderableFieldlinesSequence::extractMandatoryInfoFromDictionary( @@ -413,7 +415,7 @@ void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( } } -/* +/** * Returns false if it fails to extract mandatory information! */ bool RenderableFieldlinesSequence::extractJsonInfoFromDictionary(fls::Model& model) { diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl index 47f3c6ac2d..cfdef530df 100644 --- a/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_fs.glsl @@ -22,14 +22,13 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#include "fragment.glsl" + in vec4 vs_color; in float vs_depth; uniform bool usingAdditiveBlending; -#include "fragment.glsl" -#include "PowerScaling/powerScaling_fs.hglsl" - Fragment getFragment() { if (vs_color.a == 0) { discard; diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl index 8491716b29..a1313ae00d 100644 --- a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl @@ -24,8 +24,6 @@ #version __CONTEXT__ -#include "PowerScaling/powerScaling_vs.hglsl" - // General Uniforms that's always needed uniform vec4 lineColor; uniform mat4 modelViewProjection; @@ -123,6 +121,6 @@ void main() { vec4 position_in_meters = vec4(in_position, 1); vec4 positionClipSpace = modelViewProjection * position_in_meters; - gl_Position = z_normalization(positionClipSpace); + gl_Position = vec4(positionClipSpace.xy, 0, positionClipSpace.w); vs_depth = gl_Position.w; } diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index 9ffa156c3b..3bbeb7eabf 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -51,11 +51,6 @@ namespace { namespace openspace { -FieldlinesState::FieldlinesState() {} -FieldlinesState::FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& loadSucessful) { - loadSucessful = loadStateFromOsfls(PATH_TO_OSFLS_FILE); -} - #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED /** * Traces and adds line vertices to state. (Also sets the simulation model variable: _model!) @@ -588,8 +583,8 @@ void FieldlinesState::saveStateToJson(const std::string& ABS_FILEPATH) { // Returns one of the extra quantity vectors, _extraQuantities[INDEX]. // If INDEX is out of scope an empty vector is returned and the referenced bool will be false. -const vector& FieldlinesState::extraQuantity(const size_t INDEX, - bool& isSuccessful) const { +const std::vector& FieldlinesState::extraQuantity(const size_t INDEX, + bool& isSuccessful) const { if (INDEX < _extraQuantities.size()) { isSuccessful = true; return _extraQuantities[INDEX]; diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index 55bdde6f7e..67172d1880 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -33,8 +33,6 @@ #include #include -using std::vector; - #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED namespace ccmc { class Kameleon; @@ -45,15 +43,14 @@ namespace openspace { class FieldlinesState { public: - FieldlinesState(); - FieldlinesState(const std::string& PATH_TO_OSFLS_FILE, bool& loadSucessful); #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED bool addLinesFromKameleon(ccmc::Kameleon* kameleon, - const vector& SEED_POINTS, + const std::vector& SEED_POINTS, const std::string TRACING_VAR); - void addExtraQuantities(ccmc::Kameleon* kameleon, vector& xtraScalarVars, - vector& xtraMagVars); + void addExtraQuantities(ccmc::Kameleon* kameleon, + std::vector& xtraScalarVars, + std::vector& xtraMagVars); void convertLatLonToCartesian(const float SCALE = 1.f); void scalePositions(const float SCALE); #endif // OPENSPACE_MODULE_KAMELEON_ENABLED @@ -66,37 +63,36 @@ public: void saveStateToJson(const std::string& PATH_TO_JSON_FILE); // ------------------------------GETTERS-----------------------------------------// - const vector>& extraQuantities() const { return _extraQuantities; } - const vector& extraQuantityNames() const { return _extraQuantityNames; } - const vector& lineCount() const { return _lineCount; } - const vector& lineStart() const { return _lineStart; } - size_t nExtraQuantities() const { return _extraQuantities.size(); } - fls::Model model() const { return _model; } - double triggerTime() const { return _triggerTime; } - const vector& vertexPositions() const { return _vertexPositions; } + const std::vector>& extraQuantities() const { return _extraQuantities; } + const std::vector& extraQuantityNames() const { return _extraQuantityNames; } + const std::vector& lineCount() const { return _lineCount; } + const std::vector& lineStart() const { return _lineStart; } + size_t nExtraQuantities() const { return _extraQuantities.size(); } + fls::Model model() const { return _model; } + double triggerTime() const { return _triggerTime; } + const std::vector& vertexPositions() const { return _vertexPositions; } // Special getter. Returns extraQuantities[INDEX]. - const vector& extraQuantity(const size_t INDEX, bool& isSuccesful) const; + const std::vector& extraQuantity(const size_t INDEX, bool& isSuccesful) const; void setTriggerTime(const double T) { _triggerTime = T; } private: - bool _isMorphable = false; - double _triggerTime = -1.0; - fls::Model _model; + bool _isMorphable = false; + double _triggerTime = -1.0; + fls::Model _model; - vector _vertexPositions; - vector _lineStart; - vector _lineCount; - vector> _extraQuantities; - vector _extraQuantityNames; + std::vector> _extraQuantities; + std::vector _extraQuantityNames; + std::vector _lineCount; + std::vector _lineStart; + std::vector _vertexPositions; #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED void loadExtrasIntoKameleon(ccmc::Kameleon* kameleon, - vector& xtraScalarVars, - vector& xtraMagVars); + std::vector& xtraScalarVars, + std::vector& xtraMagVars); #endif // OPENSPACE_MODULE_KAMELEON_ENABLED - // TODO: Maybe introduce a vector containing seed point indices }; } // namespace openspace From 1a00d8a34f55fedfbc06e2d801d13f57d2349e57 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Mon, 9 Oct 2017 23:58:32 +0200 Subject: [PATCH 31/47] Add default colortable to data folder --- data/scene/fieldlinessequence/colortables/kroyw.txt | 9 +++++++++ .../rendering/renderablefieldlinessequencesetup.cpp | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 data/scene/fieldlinessequence/colortables/kroyw.txt diff --git a/data/scene/fieldlinessequence/colortables/kroyw.txt b/data/scene/fieldlinessequence/colortables/kroyw.txt new file mode 100644 index 0000000000..0852f05fc6 --- /dev/null +++ b/data/scene/fieldlinessequence/colortables/kroyw.txt @@ -0,0 +1,9 @@ +width 5 +lower 0.0 +upper 1.0 +mappingkey 0.0 0 0 0 255 +mappingkey 0.25 255 0 0 255 +mappingkey 0.5 255 140 0 255 +mappingkey 0.75 255 255 0 255 +mappingkey 1.0 255 255 255 255 + diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index f87df3726a..2fdea78a0d 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -214,7 +214,7 @@ void RenderableFieldlinesSequence::initialize() { } // Set a default color table, just in case the (optional) user defined paths are corrupt/not provided! - _colorTablePaths.push_back("${OPENSPACE_DATA}/colortables/kroyw.txt"); + _colorTablePaths.push_back("${OPENSPACE_DATA}/scene/fieldlinessequence/colortables/kroyw.txt"); _transferFunction = std::make_shared(absPath(_colorTablePaths[0])); // EXTRACT OPTIONAL INFORMATION FROM DICTIONARY From ecc760ac12707deca05c1baf662287832b7a1ad6 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 18 Oct 2017 23:29:09 +0200 Subject: [PATCH 32/47] Change ALL_CAPS constants to camelCase --- .../renderablefieldlinessequence.cpp | 94 +++--- .../rendering/renderablefieldlinessequence.h | 16 +- .../renderablefieldlinessequencesetup.cpp | 236 +++++++-------- .../shaders/fieldlinessequence_vs.glsl | 32 +- modules/fieldlinessequence/util/commons.cpp | 16 +- modules/fieldlinessequence/util/commons.h | 16 +- .../util/fieldlinesstate.cpp | 277 +++++++++--------- .../fieldlinessequence/util/fieldlinesstate.h | 20 +- modules/kameleon/include/kameleonhelper.h | 2 +- modules/kameleon/src/kameleonhelper.cpp | 10 +- 10 files changed, 356 insertions(+), 363 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index c4a1cb89cf..ad467f4110 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -31,13 +31,12 @@ #include #include - namespace { std::string _loggerCat = "RenderableFieldlinesSequence"; - const GLuint _VA_POSITION = 0; // MUST CORRESPOND TO THE SHADER PROGRAM - const GLuint _VA_COLOR = 1; // MUST CORRESPOND TO THE SHADER PROGRAM - const GLuint _VA_MASKING = 2; // MUST CORRESPOND TO THE SHADER PROGRAM + const GLuint VaPosition = 0; // MUST CORRESPOND TO THE SHADER PROGRAM + const GLuint VaColor = 1; // MUST CORRESPOND TO THE SHADER PROGRAM + const GLuint VaMasking = 2; // MUST CORRESPOND TO THE SHADER PROGRAM } // namespace namespace openspace { @@ -76,23 +75,22 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& _shaderProgram->activate(); // Calculate Model View MatrixProjection - const glm::dmat4 ROT_MAT = glm::dmat4(data.modelTransform.rotation); - // const glm::mat4 SCALE_TRANSFORM = glm::mat4(1.0); // TODO remove if no use - const glm::dmat4 MODEL_MAT = + const glm::dmat4 rotMat = glm::dmat4(data.modelTransform.rotation); + const glm::dmat4 modelMat = glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * - ROT_MAT * + rotMat * glm::dmat4(glm::scale(glm::dmat4(1), glm::dvec3(data.modelTransform.scale))); - const glm::dmat4 MODEL_VIEW_MAT = data.camera.combinedViewMatrix() * MODEL_MAT; + const glm::dmat4 modelViewMat = data.camera.combinedViewMatrix() * modelMat; _shaderProgram->setUniform("modelViewProjection", - data.camera.sgctInternal.projectionMatrix() * glm::mat4(MODEL_VIEW_MAT)); + data.camera.sgctInternal.projectionMatrix() * glm::mat4(modelViewMat)); _shaderProgram->setUniform("colorMethod", _pColorMethod); _shaderProgram->setUniform("lineColor", _pColorUniform); _shaderProgram->setUniform("usingDomain", _pDomainEnabled); _shaderProgram->setUniform("usingMasking", _pMaskingEnabled); - if (_pColorMethod == ColorMethod::BY_QUANTITY) { + if (_pColorMethod == ColorMethod::ByQuantity) { ghoul::opengl::TextureUnit textureUnit; textureUnit.activate(); _transferFunction->bind(); // Calls update internally @@ -120,11 +118,11 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& bool additiveBlending = false; if (_pColorABlendEnabled) { - const auto RENDERER = OsEng.renderEngine().rendererImplementation(); - bool usingFBufferRenderer = RENDERER == + const auto renderer = OsEng.renderEngine().rendererImplementation(); + bool usingFBufferRenderer = renderer == RenderEngine::RendererImplementation::Framebuffer; - bool usingABufferRenderer = RENDERER == + bool usingABufferRenderer = renderer == RenderEngine::RendererImplementation::ABuffer; if (usingABufferRenderer) { @@ -163,15 +161,15 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { // This node shouldn't do anything if its been disabled from the gui! if (_enabled) { - const double CURRENT_TIME = data.time.j2000Seconds(); + const double currentTime = data.time.j2000Seconds(); // Check if current time in OpenSpace is within sequence interval - if (isWithinSequenceInterval(CURRENT_TIME)) { - const int NEXT_IDX = _activeTriggerTimeIndex + 1; - if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval - || CURRENT_TIME < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state - || (NEXT_IDX < _nStates && CURRENT_TIME >= _startTimes[NEXT_IDX])) { // true => OpenSpace has stepped forward to a time represented by another state + if (isWithinSequenceInterval(currentTime)) { + const int nextIdx = _activeTriggerTimeIndex + 1; + if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval + || currentTime < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state + || (nextIdx < _nStates && currentTime >= _startTimes[nextIdx])) { // true => OpenSpace has stepped forward to a time represented by another state - updateActiveTriggerTimeIndex(CURRENT_TIME); + updateActiveTriggerTimeIndex(currentTime); if (_loadingStatesDynamically) { _mustLoadNewStateFromDisk = true; @@ -191,9 +189,9 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { if (!_isLoadingStateFromDisk && !_newStateIsReady) { _isLoadingStateFromDisk = true; _mustLoadNewStateFromDisk = false; - const std::string FILEPATH = _sourceFiles[_activeTriggerTimeIndex]; - std::thread readBinaryThread([this, FILEPATH] { - this->readNewState(FILEPATH); + const std::string filePath = _sourceFiles[_activeTriggerTimeIndex]; + std::thread readBinaryThread([this, filePath] { + this->readNewState(filePath); }); readBinaryThread.detach(); } @@ -228,13 +226,13 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { } } -inline bool RenderableFieldlinesSequence::isWithinSequenceInterval(const double CURRENT_TIME) const { - return (CURRENT_TIME >= _startTimes[0]) && (CURRENT_TIME < _sequenceEndTime); +inline bool RenderableFieldlinesSequence::isWithinSequenceInterval(const double currentTime) const { + return (currentTime >= _startTimes[0]) && (currentTime < _sequenceEndTime); } -// Assumes we already know that CURRENT_TIME is within the sequence interval -void RenderableFieldlinesSequence::updateActiveTriggerTimeIndex(const double CURRENT_TIME) { - auto iter = std::upper_bound(_startTimes.begin(), _startTimes.end(), CURRENT_TIME); +// Assumes we already know that currentTime is within the sequence interval +void RenderableFieldlinesSequence::updateActiveTriggerTimeIndex(const double currentTime) { + auto iter = std::upper_bound(_startTimes.begin(), _startTimes.end(), currentTime); if (iter != _startTimes.end()) { if ( iter != _startTimes.begin()) { _activeTriggerTimeIndex = @@ -248,9 +246,9 @@ void RenderableFieldlinesSequence::updateActiveTriggerTimeIndex(const double CUR } // Reading state from disk. Must be thread safe! -void RenderableFieldlinesSequence::readNewState(const std::string& FILEPATH) { +void RenderableFieldlinesSequence::readNewState(const std::string& filePath) { _newState = std::make_unique(); - if (_newState->loadStateFromOsfls(FILEPATH)) { + if (_newState->loadStateFromOsfls(filePath)) { _newStateIsReady = true; } _isLoadingStateFromDisk = false; @@ -266,14 +264,14 @@ void RenderableFieldlinesSequence::updateVertexPositionBuffer() { glBindVertexArray(_vertexArrayObject); glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); - const std::vector& VERTEX_POS_VEC = + const std::vector& vertexPosVec = _states[_activeStateIndex].vertexPositions(); - glBufferData(GL_ARRAY_BUFFER, VERTEX_POS_VEC.size() * sizeof(glm::vec3), - &VERTEX_POS_VEC.front(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vertexPosVec.size() * sizeof(glm::vec3), + &vertexPosVec.front(), GL_STATIC_DRAW); - glEnableVertexAttribArray(_VA_POSITION); - glVertexAttribPointer(_VA_POSITION, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(VaPosition); + glVertexAttribPointer(VaPosition, 3, GL_FLOAT, GL_FALSE, 0, 0); unbindGL(); } @@ -283,15 +281,15 @@ void RenderableFieldlinesSequence::updateVertexColorBuffer() { glBindBuffer(GL_ARRAY_BUFFER, _vertexColorBuffer); bool isSuccessful; - const std::vector& QUANTITY_VEC = + const std::vector& quantityVec = _states[_activeStateIndex].extraQuantity(_pColorQuantity, isSuccessful); if (isSuccessful) { - glBufferData(GL_ARRAY_BUFFER, QUANTITY_VEC.size() * sizeof(float), - &QUANTITY_VEC.front(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, quantityVec.size() * sizeof(float), + &quantityVec.front(), GL_STATIC_DRAW); - glEnableVertexAttribArray(_VA_COLOR); - glVertexAttribPointer(_VA_COLOR, 1, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(VaColor); + glVertexAttribPointer(VaColor, 1, GL_FLOAT, GL_FALSE, 0, 0); unbindGL(); } @@ -302,22 +300,18 @@ void RenderableFieldlinesSequence::updateVertexMaskingBuffer() { glBindBuffer(GL_ARRAY_BUFFER, _vertexMaskingBuffer); bool isSuccessful; - const std::vector& QUANTITY_VEC = + const std::vector& quantityVec = _states[_activeStateIndex].extraQuantity(_pMaskingQuantity, isSuccessful); if (isSuccessful) { - glBufferData(GL_ARRAY_BUFFER, QUANTITY_VEC.size() * sizeof(float), - &QUANTITY_VEC.front(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, quantityVec.size() * sizeof(float), + &quantityVec.front(), GL_STATIC_DRAW); - glEnableVertexAttribArray(_VA_MASKING); - glVertexAttribPointer(_VA_MASKING, 1, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(VaMasking); + glVertexAttribPointer(VaMasking, 1, GL_FLOAT, GL_FALSE, 0, 0); unbindGL(); } } - - - - } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index a9f3b8d233..ef4b4870bf 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -59,8 +59,8 @@ public: private: // ------------------------------------- ENUMS -------------------------------------// enum ColorMethod : int { // Used to determine if lines should be colored UNIFORMLY or by an extraQuantity - UNIFORM = 0, - BY_QUANTITY + Uniform = 0, + ByQuantity }; // ------------------------------------ STRINGS ------------------------------------// @@ -144,8 +144,8 @@ private: void extractOptionalInfoFromDictionary(std::string& outputFolderPath); void extractOsflsInfoFromDictionary(); void extractTriggerTimesFromFileNames(); - bool loadJsonStatesIntoRAM(const std::string& OUTPUT_FOLDER); - void loadOsflsStatesIntoRAM(const std::string& OUTPUT_FOLDER); + bool loadJsonStatesIntoRAM(const std::string& outputFolder); + void loadOsflsStatesIntoRAM(const std::string& outputFolder); void setModelDependentConstants(); void setupProperties(); bool prepareForOsflsStreaming(); @@ -158,13 +158,13 @@ private: std::vector& outVec); void extractMagnitudeVarsFromStrings(std::vector& extraVars, std::vector& extraMagVars); - bool getStatesFromCdfFiles(const std::string& OUTPUT_FOLDER); + bool getStatesFromCdfFiles(const std::string& outputFolder); #endif // OPENSPACE_MODULE_KAMELEON_ENABLED // ------------------------- FUNCTIONS USED DURING RUNTIME ------------------------ // - inline bool isWithinSequenceInterval(const double CURRENT_TIME) const; - void readNewState(const std::string& FILEPATH); - void updateActiveTriggerTimeIndex(const double CURRENT_TIME); + inline bool isWithinSequenceInterval(const double currentTime) const; + void readNewState(const std::string& filePath); + void updateActiveTriggerTimeIndex(const double currentTime); void updateVertexPositionBuffer(); void updateVertexColorBuffer(); void updateVertexMaskingBuffer(); diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index 2fdea78a0d..112d4090e0 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -46,29 +46,29 @@ namespace { // ----- KEYS POSSIBLE IN MODFILE. EXPECTED DATA TYPE OF VALUE IN [BRACKETS] ----- // // ---------------------------- MANDATORY MODFILE KEYS ---------------------------- // - const char* KEY_INPUT_FILE_TYPE = "InputFileType"; // [STRING] "cdf", "json" or "osfls" - const char* KEY_SOURCE_FOLDER = "SourceFolder"; // [STRING] should be path to folder containing the input files + const char* KeyInputFileType = "InputFileType"; // [STRING] "cdf", "json" or "osfls" + const char* KeySourceFolder = "SourceFolder"; // [STRING] should be path to folder containing the input files // ---------------------- MANDATORY INPUT TYPE SPECIFIC KEYS ---------------------- // - const char* KEY_CDF_SEED_POINT_FILE = "SeedPointFile"; // [STRING] Path to a .txt file containing seed points - const char* KEY_JSON_SIMULATION_MODEL = "SimulationModel"; // [STRING] Currently supports: "batsrus", "enlil" & "pfss" + const char* KeyCdfSeedPointFile = "SeedPointFile"; // [STRING] Path to a .txt file containing seed points + const char* KeyJsonSimulationModel = "SimulationModel"; // [STRING] Currently supports: "batsrus", "enlil" & "pfss" // ----------------------- OPTIONAL INPUT TYPE SPECIFIC KEYS ---------------------- // - const char* KEY_CDF_EXTRA_VARIABLES = "ExtraVariables"; // [STRING ARRAY] - const char* KEY_CDF_TRACING_VARIABLE = "TracingVariable"; // [STRING] - const char* KEY_JSON_SCALING_FACTOR = "ScaleToMeters"; // [STRING] - const char* KEY_OSLFS_LOAD_AT_RUNTIME = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM + const char* KeyCdfExtraVariables = "ExtraVariables"; // [STRING ARRAY] + const char* KeyCdfTracingVariable = "TracingVariable"; // [STRING] + const char* KeyJsonScalingFactor = "ScaleToMeters"; // [STRING] + const char* KeyOslfsLoadAtRuntime = "LoadAtRuntime"; // [BOOLEAN] If value False => Load in initializing step and store in RAM // ---------------------------- OPTIONAL MODFILE KEYS ---------------------------- // - const char* KEY_COLOR_TABLE_PATHS = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files - const char* KEY_COLOR_TABLE_RANGES = "ColorTableRanges";// [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers - const char* KEY_MASKING_RANGES = "MaskingRanges"; // [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers - const char* KEY_OUTPUT_FOLDER = "OutputFolder"; // [STRING] Value should be path to folder where states are saved (JSON/CDF input => osfls output & oslfs input => JSON output) + const char* KeyColorTablePaths = "ColorTablePaths"; // [STRING ARRAY] Values should be paths to .txt files + const char* KeyColorTableRanges = "ColorTableRanges";// [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers + const char* KeyMaskingRanges = "MaskingRanges"; // [VEC2 ARRAY] Values should be entered as {X, Y}, where X & Y are numbers + const char* KeyOutputFolder = "OutputFolder"; // [STRING] Value should be path to folder where states are saved (JSON/CDF input => osfls output & oslfs input => JSON output) // ------------- POSSIBLE STRING VALUES FOR CORRESPONDING MODFILE KEY ------------- // - const char* VALUE_INPUT_FILE_TYPE_CDF = "cdf"; - const char* VALUE_INPUT_FILE_TYPE_JSON = "json"; - const char* VALUE_INPUT_FILE_TYPE_OSFLS = "osfls"; + const char* ValueInputFileTypeCdf = "cdf"; + const char* ValueInputFileTypeJson = "json"; + const char* ValueInputFileTypeOsfls = "osfls"; // --------------------------------- Property Info -------------------------------- // static const openspace::properties::Property::PropertyInfo ColorMethodInfo = { @@ -147,20 +147,20 @@ namespace { }; enum class SourceFileType : int { - CDF = 0, - JSON, - OSFLS, - INVALID + Cdf = 0, + Json, + Osfls, + Invalid }; - float stringToFloat(const std::string INPUT, const float BACKUP_VALUE = 0.f) { + float stringToFloat(const std::string input, const float backupValue = 0.f) { float tmp; try { - tmp = std::stof(INPUT); + tmp = std::stof(input); } catch (const std::invalid_argument& ia) { - LWARNING("Invalid argument: " << ia.what() << ". '" << INPUT << + LWARNING("Invalid argument: " << ia.what() << ". '" << input << "' is NOT a valid number!"); - return BACKUP_VALUE; + return backupValue; } return tmp; } @@ -168,8 +168,8 @@ namespace { namespace openspace { -RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& DICTIONARY) - : Renderable(DICTIONARY), +RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictionary& dictionary) + : Renderable(dictionary), _pColorGroup({ "Color" }), _pColorMethod(ColorMethodInfo, properties::OptionProperty::DisplayType::Radio), _pColorQuantity(ColorQuantityInfo, properties::OptionProperty::DisplayType::Dropdown), @@ -201,14 +201,14 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(const ghoul::Dictiona _pFocusOnOriginBtn(OriginButtonInfo), _pJumpToStartBtn(TimeJumpButtonInfo) { - _dictionary = std::make_unique(DICTIONARY); + _dictionary = std::make_unique(dictionary); } void RenderableFieldlinesSequence::initialize() { LINFO("RenderableFieldlinesSequence::initialize()"); // EXTRACT MANDATORY INFORMATION FROM DICTIONARY - SourceFileType sourceFileType = SourceFileType::INVALID; + SourceFileType sourceFileType = SourceFileType::Invalid; if (!extractMandatoryInfoFromDictionary(sourceFileType)) { return; } @@ -223,19 +223,19 @@ void RenderableFieldlinesSequence::initialize() { // EXTRACT SOURCE FILE TYPE SPECIFIC INFOMRATION FROM DICTIONARY & GET STATES FROM SOURCE switch (sourceFileType) { - case SourceFileType::CDF: + case SourceFileType::Cdf: #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED if (!getStatesFromCdfFiles(outputFolderPath)) { return; } #endif // OPENSPACE_MODULE_KAMELEON_ENABLED break; - case SourceFileType::JSON: + case SourceFileType::Json: if (!loadJsonStatesIntoRAM(outputFolderPath)) { return; } break; - case SourceFileType::OSFLS: + case SourceFileType::Osfls: extractOsflsInfoFromDictionary(); if (_loadingStatesDynamically) { if (!prepareForOsflsStreaming()) { @@ -277,7 +277,7 @@ void RenderableFieldlinesSequence::initialize() { if (!_shaderProgram) { LERROR("Shader program failed initialization!"); - sourceFileType = SourceFileType::INVALID; + sourceFileType = SourceFileType::Invalid; } //------------------ Initialize OpenGL VBOs and VAOs-------------------------------// @@ -304,34 +304,34 @@ bool RenderableFieldlinesSequence::extractMandatoryInfoFromDictionary( // ------------------- EXTRACT MANDATORY VALUES FROM DICTIONARY ------------------- // std::string inputFileTypeString; - if (!_dictionary->getValue(KEY_INPUT_FILE_TYPE, inputFileTypeString)) { - LERROR(_name << ": The field " << std::string(KEY_INPUT_FILE_TYPE) << " is missing!"); + if (!_dictionary->getValue(KeyInputFileType, inputFileTypeString)) { + LERROR(_name << ": The field " << std::string(KeyInputFileType) << " is missing!"); return false; } else { std::transform(inputFileTypeString.begin(), inputFileTypeString.end(), inputFileTypeString.begin(), ::tolower); // Verify that the input type is correct - if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_CDF) { - sourceFileType = SourceFileType::CDF; + if (inputFileTypeString == ValueInputFileTypeCdf) { + sourceFileType = SourceFileType::Cdf; #ifndef OPENSPACE_MODULE_KAMELEON_ENABLED LERROR(_name << ": CDF file inputs requires the 'Kameleon' module to be enabled!"); return false; #endif // OPENSPACE_MODULE_KAMELEON_ENABLED - } else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_JSON) { - sourceFileType = SourceFileType::JSON; - } else if (inputFileTypeString == VALUE_INPUT_FILE_TYPE_OSFLS) { - sourceFileType = SourceFileType::OSFLS; + } else if (inputFileTypeString == ValueInputFileTypeJson) { + sourceFileType = SourceFileType::Json; + } else if (inputFileTypeString == ValueInputFileTypeOsfls) { + sourceFileType = SourceFileType::Osfls; } else { LERROR(_name << ": " << inputFileTypeString << " is not a recognised " - << KEY_INPUT_FILE_TYPE); - sourceFileType = SourceFileType::INVALID; + << KeyInputFileType); + sourceFileType = SourceFileType::Invalid; return false; } } std::string sourceFolderPath; - if (!_dictionary->getValue(KEY_SOURCE_FOLDER, sourceFolderPath)) { - LERROR(_name << ": The field " << std::string(KEY_SOURCE_FOLDER) << " is missing!"); + if (!_dictionary->getValue(KeySourceFolder, sourceFolderPath)) { + LERROR(_name << ": The field " << std::string(KeySourceFolder) << " is missing!"); return false; } @@ -345,8 +345,8 @@ bool RenderableFieldlinesSequence::extractMandatoryInfoFromDictionary( // Remove all files that don't have as extension _sourceFiles.erase(std::remove_if(_sourceFiles.begin(), _sourceFiles.end(), [inputFileTypeString](std::string str) { - const size_t EXT_LENGTH = inputFileTypeString.length(); - std::string sub = str.substr(str.length() - EXT_LENGTH, EXT_LENGTH); + const size_t extLength = inputFileTypeString.length(); + std::string sub = str.substr(str.length() - extLength, extLength); std::transform(sub.begin(), sub.end(), sub.begin(), ::tolower); return sub != inputFileTypeString; }), _sourceFiles.end()); @@ -369,7 +369,7 @@ void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( std::string& outputFolderPath) { // ------------------- EXTRACT OPTIONAL VALUES FROM DICTIONARY ------------------- // - if (_dictionary->getValue(KEY_OUTPUT_FOLDER, outputFolderPath)) { + if (_dictionary->getValue(KeyOutputFolder, outputFolderPath)) { ghoul::filesystem::Directory outputFolder(outputFolderPath); if (FileSys.directoryExists(outputFolder)) { outputFolderPath = absPath(outputFolderPath); @@ -380,12 +380,12 @@ void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( } ghoul::Dictionary colorTablesPathsDictionary; - if (_dictionary->getValue(KEY_COLOR_TABLE_PATHS, colorTablesPathsDictionary)) { - const size_t N_PROVIDED_PATHS = colorTablesPathsDictionary.size(); - if (N_PROVIDED_PATHS > 0) { + if (_dictionary->getValue(KeyColorTablePaths, colorTablesPathsDictionary)) { + const size_t nProvidedPaths = colorTablesPathsDictionary.size(); + if (nProvidedPaths > 0) { // Clear the default! It is already specified in the transferFunction _colorTablePaths.clear(); - for (size_t i = 1; i <= N_PROVIDED_PATHS; ++i) { + for (size_t i = 1; i <= nProvidedPaths; ++i) { _colorTablePaths.push_back( colorTablesPathsDictionary.value(std::to_string(i))); } @@ -393,9 +393,9 @@ void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( } ghoul::Dictionary colorTablesRangesDictionary; - if (_dictionary->getValue(KEY_COLOR_TABLE_RANGES, colorTablesRangesDictionary)) { - const size_t N_PROVIDED_RANGES = colorTablesRangesDictionary.size(); - for (size_t i = 1; i <= N_PROVIDED_RANGES; ++i) { + if (_dictionary->getValue(KeyColorTableRanges, colorTablesRangesDictionary)) { + const size_t nProvidedRanges = colorTablesRangesDictionary.size(); + for (size_t i = 1; i <= nProvidedRanges; ++i) { _colorTableRanges.push_back( colorTablesRangesDictionary.value(std::to_string(i))); } @@ -404,9 +404,9 @@ void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( } ghoul::Dictionary maskingRangesDictionary; - if (_dictionary->getValue(KEY_MASKING_RANGES, maskingRangesDictionary)) { - const size_t N_PROVIDED_RANGES = maskingRangesDictionary.size(); - for (size_t i = 1; i <= N_PROVIDED_RANGES; ++i) { + if (_dictionary->getValue(KeyMaskingRanges, maskingRangesDictionary)) { + const size_t nProvidedRanges = maskingRangesDictionary.size(); + for (size_t i = 1; i <= nProvidedRanges; ++i) { _maskingRanges.push_back( maskingRangesDictionary.value(std::to_string(i))); } @@ -420,16 +420,16 @@ void RenderableFieldlinesSequence::extractOptionalInfoFromDictionary( */ bool RenderableFieldlinesSequence::extractJsonInfoFromDictionary(fls::Model& model) { std::string modelStr; - if (_dictionary->getValue(KEY_JSON_SIMULATION_MODEL, modelStr)) { + if (_dictionary->getValue(KeyJsonSimulationModel, modelStr)) { std::transform(modelStr.begin(), modelStr.end(), modelStr.begin(), ::tolower); model = fls::stringToModel(modelStr); } else { - LERROR(_name << ": Must specify '" << KEY_JSON_SIMULATION_MODEL << "'"); + LERROR(_name << ": Must specify '" << KeyJsonSimulationModel << "'"); return false; } float scaleFactor; - if (_dictionary->getValue(KEY_JSON_SCALING_FACTOR, scaleFactor)) { + if (_dictionary->getValue(KeyJsonScalingFactor, scaleFactor)) { _scalingFactor = scaleFactor; } else { LWARNING(_name << ": Does not provide scalingFactor! " << @@ -438,7 +438,7 @@ bool RenderableFieldlinesSequence::extractJsonInfoFromDictionary(fls::Model& mod return true; } -bool RenderableFieldlinesSequence::loadJsonStatesIntoRAM(const std::string& OUTPUT_FOLDER) { +bool RenderableFieldlinesSequence::loadJsonStatesIntoRAM(const std::string& outputFolder) { fls::Model model; if (!extractJsonInfoFromDictionary(model)) { return false; @@ -450,8 +450,8 @@ bool RenderableFieldlinesSequence::loadJsonStatesIntoRAM(const std::string& OUTP _scalingFactor); if (loadedSuccessfully) { addStateToSequence(newState); - if (!OUTPUT_FOLDER.empty()) { - newState.saveStateToOsfls(OUTPUT_FOLDER); + if (!outputFolder.empty()) { + newState.saveStateToOsfls(outputFolder); } } } @@ -472,28 +472,28 @@ bool RenderableFieldlinesSequence::prepareForOsflsStreaming() { } -void RenderableFieldlinesSequence::loadOsflsStatesIntoRAM(const std::string& OUTPUT_FOLDER) { +void RenderableFieldlinesSequence::loadOsflsStatesIntoRAM(const std::string& outputFolder) { // Load states from .osfls files into RAM! - for (const std::string FILEPATH : _sourceFiles) { + for (const std::string filePath : _sourceFiles) { FieldlinesState newState; - if (newState.loadStateFromOsfls(FILEPATH)) { + if (newState.loadStateFromOsfls(filePath)) { addStateToSequence(newState); - if (!OUTPUT_FOLDER.empty()) { - ghoul::filesystem::File tmpFile(FILEPATH); - newState.saveStateToJson(OUTPUT_FOLDER + tmpFile.baseName()); + if (!outputFolder.empty()) { + ghoul::filesystem::File tmpFile(filePath); + newState.saveStateToJson(outputFolder + tmpFile.baseName()); } } else { - LWARNING("Failed to load state from: " << FILEPATH); + LWARNING("Failed to load state from: " << filePath); } } } void RenderableFieldlinesSequence::extractOsflsInfoFromDictionary() { bool shouldLoadInRealtime = false; - if (_dictionary->getValue(KEY_OSLFS_LOAD_AT_RUNTIME, shouldLoadInRealtime)) { + if (_dictionary->getValue(KeyOslfsLoadAtRuntime, shouldLoadInRealtime)) { _loadingStatesDynamically = shouldLoadInRealtime; } else { - LWARNING(_name << ": " << KEY_OSLFS_LOAD_AT_RUNTIME << + LWARNING(_name << ": " << KeyOslfsLoadAtRuntime << " isn't specified! States will be stored in RAM!"); } } @@ -537,21 +537,21 @@ void RenderableFieldlinesSequence::setupProperties() { _pMaskingGroup.addProperty(_pMaskingQuantity); // --------------------- Add Options to OptionProperties --------------------- // - _pColorMethod.addOption(ColorMethod::UNIFORM, "Uniform"); - _pColorMethod.addOption(ColorMethod::BY_QUANTITY, "By Quantity"); + _pColorMethod.addOption(ColorMethod::Uniform, "Uniform"); + _pColorMethod.addOption(ColorMethod::ByQuantity, "By Quantity"); // Add option for each extra quantity. Assumes there are just as many names to // extra quantities as there are extra quantities. Also assume that all states in // the given sequence have the same extra quantities! */ - const size_t N_EXTRA_QUANTITIES = _states[0].nExtraQuantities(); - const std::vector& XTRA_NAMES_VEC = _states[0].extraQuantityNames(); - for (int i = 0; i < N_EXTRA_QUANTITIES; ++i) { - _pColorQuantity.addOption(i, XTRA_NAMES_VEC[i]); - _pMaskingQuantity.addOption(i, XTRA_NAMES_VEC[i]); + const size_t nExtraQuantities = _states[0].nExtraQuantities(); + const std::vector& extraNamesVec = _states[0].extraQuantityNames(); + for (int i = 0; i < nExtraQuantities; ++i) { + _pColorQuantity.addOption(i, extraNamesVec[i]); + _pMaskingQuantity.addOption(i, extraNamesVec[i]); } // Each quantity should have its own color table and color table range, no more, no less - _colorTablePaths.resize(N_EXTRA_QUANTITIES, _colorTablePaths.back()); - _colorTableRanges.resize(N_EXTRA_QUANTITIES, _colorTableRanges.back()); - _maskingRanges.resize(N_EXTRA_QUANTITIES, _maskingRanges.back()); + _colorTablePaths.resize(nExtraQuantities, _colorTablePaths.back()); + _colorTableRanges.resize(nExtraQuantities, _colorTableRanges.back()); + _maskingRanges.resize(nExtraQuantities, _maskingRanges.back()); } definePropertyCallbackFunctions(); @@ -642,11 +642,11 @@ void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { // Calculate expected end time. void RenderableFieldlinesSequence::computeSequenceEndTime() { if (_nStates > 1) { - const double LAST_TRIGGER_TIME = _startTimes[_nStates - 1]; - const double SEQUENCE_DURATION = LAST_TRIGGER_TIME - _startTimes[0]; - const double AVERAGE_STATE_DURATION = SEQUENCE_DURATION / - (static_cast(_nStates) - 1.0); - _sequenceEndTime = LAST_TRIGGER_TIME + AVERAGE_STATE_DURATION; + const double lastTriggerTime = _startTimes[_nStates - 1]; + const double sequenceDuration = lastTriggerTime - _startTimes[0]; + const double averageStateDuration = sequenceDuration / + (static_cast(_nStates) - 1.0); + _sequenceEndTime = lastTriggerTime + averageStateDuration; } else { // If there's just one state it should never disappear! _sequenceEndTime = DBL_MAX; @@ -657,17 +657,17 @@ void RenderableFieldlinesSequence::setModelDependentConstants() { const fls::Model simulationModel = _states[0].model(); float limit = 100.f; // Just used as a default value. switch (simulationModel) { - case fls::Model::BATSRUS: - _scalingFactor = fls::R_E_TO_METER; + case fls::Model::Batsrus: + _scalingFactor = fls::ReToMeter; limit = 300; // Should include a long magnetotail break; - case fls::Model::ENLIL: + case fls::Model::Enlil: _pFlowReversed = true; - _scalingFactor = fls::A_U_TO_METER; + _scalingFactor = fls::AuToMeter; limit = 50; // Should include Plutos furthest distance from the Sun break; - case fls::Model::PFSS: - _scalingFactor = fls::R_S_TO_METER; + case fls::Model::Pfss: + _scalingFactor = fls::RsToMeter; limit = 100; // Just a default value far away from the solar surface break; default: @@ -682,28 +682,28 @@ void RenderableFieldlinesSequence::setModelDependentConstants() { _pDomainX = glm::vec2(-limit, limit); _pDomainY = glm::vec2(-limit, limit); _pDomainZ = glm::vec2(-limit, limit); - _pDomainR = glm::vec2(0, limit*1.5f); + _pDomainR = glm::vec2(0, limit * 1.5f); } // Extract J2000 time from file names // Requires files to be named as such: 'YYYY-MM-DDTHH-MM-SS-XXX.osfls' void RenderableFieldlinesSequence::extractTriggerTimesFromFileNames() { - const size_t FILENAME_SIZE = 23; // number of characters in filename (excluding '.osfls') - const size_t EXT_SIZE = 6; // size(".osfls") + const size_t filenameSize = 23; // number of characters in filename (excluding '.osfls') + const size_t extSize = 6; // size(".osfls") - for (const std::string& FILEPATH : _sourceFiles) { - const size_t STR_LENGTH = FILEPATH.size(); + for (const std::string& filePath : _sourceFiles) { + const size_t strLength = filePath.size(); // Extract the filename from the path (without extension) - std::string timeString = FILEPATH.substr(STR_LENGTH - FILENAME_SIZE - EXT_SIZE, - FILENAME_SIZE - 1); + std::string timeString = filePath.substr(strLength - filenameSize - extSize, + filenameSize - 1); // Ensure the separators are correct timeString.replace(4, 1, "-"); timeString.replace(7, 1, "-"); timeString.replace(13, 1, ":"); timeString.replace(16, 1, ":"); timeString.replace(19, 1, "."); - const double TRIGGER_TIME = Time::convertTime(timeString); - _startTimes.push_back(TRIGGER_TIME); + const double triggerTime = Time::convertTime(timeString); + _startTimes.push_back(triggerTime); } } @@ -714,7 +714,7 @@ void RenderableFieldlinesSequence::addStateToSequence(FieldlinesState& state) { } #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED -bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& OUTPUT_FOLDER) { +bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& outputFolder) { std::string seedFilePath; std::string tracingVar; @@ -746,19 +746,19 @@ bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& OUTP // the extraQuantites, as the iterpolator needs the unaltered positions newState.addExtraQuantities(kameleon.get(), extraVars, extraMagVars); switch (newState.model()) { - case fls::BATSRUS: - newState.scalePositions(fls::R_E_TO_METER); + case fls::Batsrus: + newState.scalePositions(fls::ReToMeter); break; - case fls::ENLIL : - newState.convertLatLonToCartesian(fls::A_U_TO_METER); + case fls::Enlil : + newState.convertLatLonToCartesian(fls::AuToMeter); break; default: break; } addStateToSequence(newState); - if (!OUTPUT_FOLDER.empty()) { - newState.saveStateToOsfls(OUTPUT_FOLDER); + if (!outputFolder.empty()) { + newState.saveStateToOsfls(outputFolder); } } } @@ -775,7 +775,7 @@ bool RenderableFieldlinesSequence::extractCdfInfoFromDictionary( std::string& tracingVar, std::vector& extraVars) { - if (_dictionary->getValue(KEY_CDF_SEED_POINT_FILE, seedFilePath)) { + if (_dictionary->getValue(KeyCdfSeedPointFile, seedFilePath)) { ghoul::filesystem::File seedPointFile(seedFilePath); if (FileSys.fileExists(seedPointFile)) { seedFilePath = absPath(seedFilePath); @@ -785,20 +785,20 @@ bool RenderableFieldlinesSequence::extractCdfInfoFromDictionary( return false; } } else { - LERROR(_name << ": Must specify '" << KEY_CDF_SEED_POINT_FILE << "'"); + LERROR(_name << ": Must specify '" << KeyCdfSeedPointFile << "'"); return false; } - if (!_dictionary->getValue(KEY_CDF_TRACING_VARIABLE, tracingVar)) { + if (!_dictionary->getValue(KeyCdfTracingVariable, tracingVar)) { tracingVar = "b"; // Magnetic field variable as default - LWARNING(_name << ": No '" << KEY_CDF_TRACING_VARIABLE << "', using default: " + LWARNING(_name << ": No '" << KeyCdfTracingVariable << "', using default: " << tracingVar); } ghoul::Dictionary extraQuantityNamesDictionary; - if (_dictionary->getValue(KEY_CDF_EXTRA_VARIABLES, extraQuantityNamesDictionary)) { - const size_t N_PROVIDED_EXTRAS = extraQuantityNamesDictionary.size(); - for (size_t i = 1; i <= N_PROVIDED_EXTRAS; ++i) { + if (_dictionary->getValue(KeyCdfExtraVariables, extraQuantityNamesDictionary)) { + const size_t nProvidedExtras = extraQuantityNamesDictionary.size(); + for (size_t i = 1; i <= nProvidedExtras; ++i) { extraVars.push_back( extraQuantityNamesDictionary.value(std::to_string(i))); } @@ -846,10 +846,10 @@ void RenderableFieldlinesSequence::extractMagnitudeVarsFromStrings( for (int i = 0; i < extraVars.size(); i++) { - const std::string STR = extraVars[i]; + const std::string str = extraVars[i]; // Check if string is in the format specified for magnitude variables - if (STR.substr(0, 2) == "|(" && STR.substr(STR.size() - 2, 2) == ")|") { - std::istringstream ss(STR.substr(2, STR.size() - 4)); + if (str.substr(0, 2) == "|(" && str.substr(str.size() - 2, 2) == ")|") { + std::istringstream ss(str.substr(2, str.size() - 4)); std::string magVar; size_t counter = 0; while(std::getline(ss, magVar, ',')) { diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl index a1313ae00d..1dca94c11e 100644 --- a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl @@ -58,8 +58,8 @@ layout(location = 1) in float in_color_scalar; // The extra value used to colo layout(location = 2) in float in_masking_scalar; // The extra value used to mask out parts of lines. Location must correspond to _VA_MASKING in renderablefieldlinessequence.h // These should correspond to the enum 'ColorMethod' in renderablefieldlinesequence.cpp -const int UNIFORM_COLOR = 0; -const int COLOR_BY_QUANTITY = 1; +const int uniformColor = 0; +const int colorByQuantity = 1; out vec4 vs_color; out float vs_depth; @@ -67,15 +67,15 @@ out float vs_depth; vec4 getTransferFunctionColor() { // Remap the color scalar to a [0,1] range - const float LOOK_UP_VAL = (in_color_scalar - colorTableRange.x) / - (colorTableRange.y - colorTableRange.x); - return texture(colorTable, LOOK_UP_VAL); + const float lookUpVal = (in_color_scalar - colorTableRange.x) / + (colorTableRange.y - colorTableRange.x); + return texture(colorTable, lookUpVal); } -bool isPartOfParticle(const double TIME, const int VERTEX_ID, const int PARTICLE_SIZE, - const int PARTICLE_SPEED, const int PARTICLE_SPACING) { - const int MODULUS_RESULT = int(double(PARTICLE_SPEED) * TIME + VERTEX_ID) % PARTICLE_SPACING; - return MODULUS_RESULT > 0 && MODULUS_RESULT <= PARTICLE_SIZE; +bool isPartOfParticle(const double time, const int vertexId, const int particleSize, + const int particleSpeed, const int particleSpacing) { + const int modulusResult = int(double(particleSpeed) * time + vertexId) % particleSpacing; + return modulusResult > 0 && modulusResult <= particleSize; } void main() { @@ -88,32 +88,32 @@ void main() { } if (usingDomain && hasColor) { - const float RADIUS = length(in_position); + const float radius = length(in_position); if (in_position.x < domainLimX.x || in_position.x > domainLimX.y || in_position.y < domainLimY.x || in_position.y > domainLimY.y || in_position.z < domainLimZ.x || in_position.z > domainLimZ.y || - RADIUS < domainLimR.x || RADIUS > domainLimR.y) { + radius < domainLimR.x || radius > domainLimR.y) { hasColor = false; } } if (hasColor) { - const bool IS_PARTICLE = usingParticles && isPartOfParticle(time, gl_VertexID, + const bool isParticle = usingParticles && isPartOfParticle(time, gl_VertexID, particleSize, particleSpeed, particleSpacing); - if (IS_PARTICLE) { + if (isParticle) { vs_color = flowColor; } else { vs_color = lineColor; } - if (colorMethod == COLOR_BY_QUANTITY) { - const vec4 QUANTITY_COLOR = getTransferFunctionColor(); - vs_color = vec4(QUANTITY_COLOR.xyz, vs_color.a * QUANTITY_COLOR.a); + if (colorMethod == colorByQuantity) { + const vec4 quantityColor = getTransferFunctionColor(); + vs_color = vec4(quantityColor.xyz, vs_color.a * quantityColor.a); } } else { vs_color = vec4(0); diff --git a/modules/fieldlinessequence/util/commons.cpp b/modules/fieldlinessequence/util/commons.cpp index 76bedb6dc9..df3f76978f 100644 --- a/modules/fieldlinessequence/util/commons.cpp +++ b/modules/fieldlinessequence/util/commons.cpp @@ -27,15 +27,15 @@ namespace openspace { namespace fls { -Model stringToModel(const std::string S) { - if (S == "batsrus") { - return Model::BATSRUS; - } else if (S == "enlil") { - return Model::ENLIL; - } else if (S == "pfss") { - return Model::PFSS; +Model stringToModel(const std::string s) { + if (s == "batsrus") { + return Model::Batsrus; + } else if (s == "enlil") { + return Model::Enlil; + } else if (s == "pfss") { + return Model::Pfss; } - return Model::INVALID; + return Model::Invalid; } } // namespace fls diff --git a/modules/fieldlinessequence/util/commons.h b/modules/fieldlinessequence/util/commons.h index 488f358451..d730f8082c 100644 --- a/modules/fieldlinessequence/util/commons.h +++ b/modules/fieldlinessequence/util/commons.h @@ -31,17 +31,17 @@ namespace openspace { namespace fls { // (F)ield(L)ines(S)equence enum Model : int { - BATSRUS = 0, - ENLIL, - PFSS, - INVALID + Batsrus = 0, + Enlil, + Pfss, + Invalid }; -Model stringToModel(const std::string S); +Model stringToModel(const std::string s); -const float A_U_TO_METER = 149597870700.f; // Astronomical Units -const float R_E_TO_METER = 6371000.f; // Earth radius -const float R_S_TO_METER = 695700000.f; // Sun radius +const float AuToMeter = 149597870700.f; // Astronomical Units +const float ReToMeter = 6371000.f; // Earth radius +const float RsToMeter = 695700000.f; // Sun radius } // namespace fls } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index 3bbeb7eabf..f40f28a7bf 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -40,11 +40,11 @@ namespace { std::string _loggerCat = "FieldlinesState"; - const int CURRENT_VERSION = 0; + const int CurrentVersion = 0; - const std::string T_AS_P_OVER_RHO = "T = p/rho"; - const std::string J_PARALLEL_B = "Current: mag(J||B)"; - const float TO_KELVIN = 72429735.6984f; // <-- [nPa]/[amu/cm^3] * TO_KELVIN => Temperature in Kelvin + const std::string TAsPOverRho = "T = p/rho"; + const std::string JParallelB = "Current: mag(J||B)"; + const float ToKelvin = 72429735.6984f; // <-- [nPa]/[amu/cm^3] * ToKelvin => Temperature in Kelvin using json = nlohmann::json; } @@ -58,18 +58,18 @@ namespace openspace { * Note that extraQuantities will NOT be set! */ bool FieldlinesState::addLinesFromKameleon(ccmc::Kameleon* kameleon, - const std::vector& SEED_POINTS, - const std::string TRACING_VAR) { + const std::vector& seedPoints, + const std::string tracingVar) { _model = fls::stringToModel(kameleon->getModelName()); float innerBoundaryLimit; switch (_model) { - case fls::Model::BATSRUS : + case fls::Model::Batsrus : innerBoundaryLimit = 2.5f; // TODO specify in Lua? break; - case fls::Model::ENLIL : + case fls::Model::Enlil : innerBoundaryLimit = 0.11f; // TODO specify in Lua? break; default: @@ -79,15 +79,15 @@ bool FieldlinesState::addLinesFromKameleon(ccmc::Kameleon* kameleon, } // --------------------------- LOAD TRACING VARIABLE ---------------------------- // - if (!kameleon->loadVariable(TRACING_VAR)) { - LERROR("FAILED TO LOAD TRACING VARIABLE: " << TRACING_VAR); + if (!kameleon->loadVariable(tracingVar)) { + LERROR("FAILED TO LOAD TRACING VARIABLE: " << tracingVar); return false; } LINFO("TRACING FIELD LINES!"); // - LOOP THROUGH THE SEED POINTS, TRACE LINES AND CONVERT TO THE DESIRED FORMAT - // size_t lineStart = 0; - for (glm::vec3 seed : SEED_POINTS) { + for (glm::vec3 seed : seedPoints) { //--------------------------------------------------------------------------// // We have to create a new tracer (or actually a new interpolator) for each // // new line, otherwise some issues occur // @@ -96,18 +96,18 @@ bool FieldlinesState::addLinesFromKameleon(ccmc::Kameleon* kameleon, std::make_unique(kameleon->model); ccmc::Tracer tracer(kameleon, interpolator.get()); tracer.setInnerBoundary(innerBoundaryLimit); // TODO specify in Lua? - ccmc::Fieldline ccmcFieldline = tracer.bidirectionalTrace(TRACING_VAR, + ccmc::Fieldline ccmcFieldline = tracer.bidirectionalTrace(tracingVar, seed.x, seed.y, seed.z); - const std::vector& POSITIONS = ccmcFieldline.getPositions(); + const std::vector& positions = ccmcFieldline.getPositions(); _lineStart.push_back(lineStart); - const size_t N_LINE_POINTS = POSITIONS.size(); - _lineCount.push_back(static_cast(N_LINE_POINTS)); - lineStart += static_cast(N_LINE_POINTS); + const size_t nLinePoints = positions.size(); + _lineCount.push_back(static_cast(nLinePoints)); + lineStart += static_cast(nLinePoints); - for (const ccmc::Point3f& p : POSITIONS) { + for (const ccmc::Point3f& p : positions) { _vertexPositions.emplace_back( glm::vec3(p.component1, p.component2, p.component3)); } @@ -127,13 +127,13 @@ void FieldlinesState::loadExtrasIntoKameleon(ccmc::Kameleon* kameleon, std::string& str = xtraScalarVars[i]; bool isSuccesful = kameleon->doesVariableExist(str) && kameleon->loadVariable(str); if (!isSuccesful && - (_model == fls::Model::BATSRUS && (str == T_AS_P_OVER_RHO || str == "T" ))) { + (_model == fls::Model::Batsrus && (str == TAsPOverRho || str == "T" ))) { LDEBUG("BATSRUS doesn't contain variable T for temperature. Trying to " << "calculate it using the ideal gas law: T = pressure/density"); - const std::string P = "p", R = "rho"; - isSuccesful = kameleon->doesVariableExist(P) && kameleon->loadVariable(P) - && kameleon->doesVariableExist(R) && kameleon->loadVariable(R); - str = T_AS_P_OVER_RHO; + const std::string p = "p", r = "rho"; + isSuccesful = kameleon->doesVariableExist(p) && kameleon->loadVariable(p) + && kameleon->doesVariableExist(r) && kameleon->loadVariable(r); + str = TAsPOverRho; } if (!isSuccesful) { LWARNING("FAILED TO LOAD EXTRA VARIABLE: '" << str << "'. Ignoring it!"); @@ -158,7 +158,7 @@ void FieldlinesState::loadExtrasIntoKameleon(ccmc::Kameleon* kameleon, kameleon->loadVariable(s2) && kameleon->loadVariable(s3); std::string name = "Magnitude of (" + s1 + ", "+ s2 + ", "+ s3 + ")"; - if (isSuccesful && _model == fls::Model::BATSRUS && s1 == "jx" && s2 == "jy" + if (isSuccesful && _model == fls::Model::Batsrus && s1 == "jx" && s2 == "jy" && s3 == "jz") { // CCMC isn't really interested in the magnitude of current, but by the // magnitude of the part of the current's vector that is parallel to the @@ -169,7 +169,7 @@ void FieldlinesState::loadExtrasIntoKameleon(ccmc::Kameleon* kameleon, kameleon->loadVariable("bx") && kameleon->loadVariable("by") && kameleon->loadVariable("bz"); - name = J_PARALLEL_B; + name = JParallelB; } if (!isSuccesful) { LWARNING("FAILED TO LOAD AT LEAST ONE OF THE MAGNITUDE VARIABLES: " @@ -211,56 +211,56 @@ void FieldlinesState::addExtraQuantities(ccmc::Kameleon* kameleon, loadExtrasIntoKameleon(kameleon, xtraScalarVars, xtraMagVars); - const size_t N_XTRA_SCALARS = xtraScalarVars.size(); - const size_t N_XTRA_MAGNITUDES = xtraMagVars.size() / 3; + const size_t nXtraScalars = xtraScalarVars.size(); + const size_t nXtraMagnitudes = xtraMagVars.size() / 3; - _extraQuantities.resize(N_XTRA_SCALARS + N_XTRA_MAGNITUDES); + _extraQuantities.resize(nXtraScalars + nXtraMagnitudes); std::unique_ptr interpolator = std::make_unique(kameleon->model); // ------ Extract all the extraQuantities from kameleon and store in state! ------ // - for (const glm::vec3& P : _vertexPositions) { + for (const glm::vec3& p : _vertexPositions) { // Load the scalars! - for (size_t i = 0; i < N_XTRA_SCALARS; i++) { + for (size_t i = 0; i < nXtraScalars; i++) { float val; - if (xtraScalarVars[i] == T_AS_P_OVER_RHO) { - val = interpolator->interpolate("p", P.x, P.y, P.z); - val *= TO_KELVIN; - val /= interpolator->interpolate("rho", P.x, P.y, P.z); + if (xtraScalarVars[i] == TAsPOverRho) { + val = interpolator->interpolate("p", p.x, p.y, p.z); + val *= ToKelvin; + val /= interpolator->interpolate("rho", p.x, p.y, p.z); } else { - val = interpolator->interpolate(xtraScalarVars[i], P.x, P.y, P.z); + val = interpolator->interpolate(xtraScalarVars[i], p.x, p.y, p.z); // When measuring density in ENLIL CCMC multiply by the radius^2 - if (xtraScalarVars[i] == "rho" && _model == fls::Model::ENLIL) { - val *= std::pow(P.x * fls::A_U_TO_METER, 2.0f); + if (xtraScalarVars[i] == "rho" && _model == fls::Model::Enlil) { + val *= std::pow(p.x * fls::AuToMeter, 2.0f); } } _extraQuantities[i].push_back(val); } // Calculate and store the magnitudes! - for (size_t i = 0; i < N_XTRA_MAGNITUDES; ++i) { - const size_t IDX = i*3; + for (size_t i = 0; i < nXtraMagnitudes; ++i) { + const size_t idx = i*3; - const float X = interpolator->interpolate(xtraMagVars[IDX] , P.x, P.y, P.z); - const float Y = interpolator->interpolate(xtraMagVars[IDX+1], P.x, P.y, P.z); - const float Z = interpolator->interpolate(xtraMagVars[IDX+2], P.x, P.y, P.z); + const float x = interpolator->interpolate(xtraMagVars[idx] , p.x, p.y, p.z); + const float y = interpolator->interpolate(xtraMagVars[idx+1], p.x, p.y, p.z); + const float z = interpolator->interpolate(xtraMagVars[idx+2], p.x, p.y, p.z); float val; // When looking at the current's magnitude in Batsrus, CCMC staff are // only interested in the magnitude parallel to the magnetic field - if (_extraQuantityNames[N_XTRA_SCALARS + i] == J_PARALLEL_B) { - const glm::vec3 NORM_MAGNETIC = glm::normalize(glm::vec3( - interpolator->interpolate("bx", P.x, P.y, P.z), - interpolator->interpolate("by", P.x, P.y, P.z), - interpolator->interpolate("bz", P.x, P.y, P.z))); + if (_extraQuantityNames[nXtraScalars + i] == JParallelB) { + const glm::vec3 normMagnetic = glm::normalize(glm::vec3( + interpolator->interpolate("bx", p.x, p.y, p.z), + interpolator->interpolate("by", p.x, p.y, p.z), + interpolator->interpolate("bz", p.x, p.y, p.z))); // Magnitude of the part of the current vector that's parallel to // the magnetic field vector! - val = glm::dot(glm::vec3(X,Y,Z), NORM_MAGNETIC); + val = glm::dot(glm::vec3(x,y,z), normMagnetic); } else { - val = std::sqrt(X*X + Y*Y + Z*Z); + val = std::sqrt(x*x + y*y + z*z); } - _extraQuantities[i + N_XTRA_SCALARS].push_back(val); + _extraQuantities[i + nXtraScalars].push_back(val); } } } @@ -270,33 +270,33 @@ void FieldlinesState::addExtraQuantities(ccmc::Kameleon* kameleon, /** * Converts all glm::vec3 in _vertexPositions from spherical (radius, latitude, longitude) * coordinates into cartesian coordinates. The longitude and latitude coordinates are -* expected to be in degrees. SCALE is an optional scaling factor. +* expected to be in degrees. scale is an optional scaling factor. */ -void FieldlinesState::convertLatLonToCartesian(const float SCALE /* = 1.f */) { +void FieldlinesState::convertLatLonToCartesian(const float scale /* = 1.f */) { for (glm::vec3& p : _vertexPositions) { - const float R = p.x * SCALE; - const float LAT = glm::radians(p.y); - const float LON = glm::radians(p.z); - const float R_COS_LAT = R * cos(LAT); + const float r = p.x * scale; + const float lat = glm::radians(p.y); + const float lon = glm::radians(p.z); + const float rCosLat = r * cos(lat); - p = glm::vec3(R_COS_LAT * cos(LON), R_COS_LAT* sin(LON), R * sin(LAT)); + p = glm::vec3(rCosLat * cos(lon), rCosLat* sin(lon), r * sin(lat)); } } #endif // OPENSPACE_MODULE_KAMELEON_ENABLED #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED -void FieldlinesState::scalePositions(const float SCALE) { +void FieldlinesState::scalePositions(const float scale) { for (glm::vec3& p : _vertexPositions) { - p *= SCALE; + p *= scale; } } #endif // OPENSPACE_MODULE_KAMELEON_ENABLED -bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) { - std::ifstream ifs(PATH_TO_OSFLS_FILE, std::ifstream::binary); +bool FieldlinesState::loadStateFromOsfls(const std::string& pathToOsflsFile) { + std::ifstream ifs(pathToOsflsFile, std::ifstream::binary); if (!ifs.is_open()) { - LERRORC("FieldlinesState", "Couldn't open file: " + PATH_TO_OSFLS_FILE); + LERRORC("FieldlinesState", "Couldn't open file: " + pathToOsflsFile); return false; } @@ -366,15 +366,15 @@ bool FieldlinesState::loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE) return true; } -bool FieldlinesState::loadStateFromJson(const std::string& PATH_TO_JSON_FILE, - const fls::Model MODEL, - const float COORD_TO_METERS = 1.f) { +bool FieldlinesState::loadStateFromJson(const std::string& pathToJsonFile, + const fls::Model Model, + const float coordToMeters = 1.f) { // --------------------- ENSURE FILE IS VALID, THEN PARSE IT --------------------- // - std::ifstream ifs(PATH_TO_JSON_FILE); + std::ifstream ifs(pathToJsonFile); if (!ifs.is_open()) { - LERROR("FAILED TO OPEN FILE: " << PATH_TO_JSON_FILE); + LERROR("FAILED TO OPEN FILE: " << pathToJsonFile); return false; } @@ -382,70 +382,70 @@ bool FieldlinesState::loadStateFromJson(const std::string& PATH_TO_JSON_FILE, ifs >> jFile; // -------------------------------------------------------------------------------- // - _model = MODEL; + _model = Model; - const std::string S_DATA = "data"; - const std::string S_TRACE = "trace"; + const std::string sData = "data"; + const std::string sTrace = "trace"; // ----- EXTRACT THE EXTRA QUANTITY NAMES & TRIGGER TIME (same for all lines) ----- // { - const json J_TMP = *jFile.begin(); // First field line in the file - _triggerTime = Time::convertTime(J_TMP["time"]); + const json jTmp = *jFile.begin(); // First field line in the file + _triggerTime = Time::convertTime(jTmp["time"]); - const std::string S_COLUMNS = "columns"; - auto variableNameVec = J_TMP[S_TRACE][S_COLUMNS]; - const size_t N_VARIABLES = variableNameVec.size(); - const size_t N_POS_COMPONENTS = 3; // x,y,z + const std::string sColumns = "columns"; + auto variableNameVec = jTmp[sTrace][sColumns]; + const size_t nVariables = variableNameVec.size(); + const size_t nPosComponents = 3; // x,y,z - if (N_VARIABLES < N_POS_COMPONENTS) { - LERROR(PATH_TO_JSON_FILE + ": Each field '" + S_COLUMNS + + if (nVariables < nPosComponents) { + LERROR(pathToJsonFile + ": Each field '" + sColumns + "' must contain the variables: 'x', 'y' and 'z' (order is important)."); return false; } - for (size_t i = N_POS_COMPONENTS ; i < N_VARIABLES ; i++) { + for (size_t i = nPosComponents ; i < nVariables ; i++) { _extraQuantityNames.push_back(variableNameVec[i]); } } - const size_t N_EXTRAS = _extraQuantityNames.size(); - _extraQuantities.resize(N_EXTRAS); + const size_t nExtras = _extraQuantityNames.size(); + _extraQuantities.resize(nExtras); size_t lineStartIdx = 0; // Loop through all fieldlines - for (json::iterator fieldlineIt = jFile.begin(); fieldlineIt != jFile.end(); ++fieldlineIt) { + for (json::iterator lineIter = jFile.begin(); lineIter != jFile.end(); ++lineIter) { // The 'data' field in the 'trace' variable contains all vertex positions and the // extra quantities. Each element is an array related to one vertex point. - const std::vector> J_DATA = (*fieldlineIt)[S_TRACE][S_DATA]; - const size_t N_POINTS = J_DATA.size(); + const std::vector> jData = (*lineIter)[sTrace][sData]; + const size_t nPoints = jData.size(); - for (size_t j = 0; j < N_POINTS; ++j) { - const std::vector& VARIABLES = J_DATA[j]; + for (size_t j = 0; j < nPoints; ++j) { + const std::vector& variables = jData[j]; // Expects the x, y and z variables to be stored first! - const size_t X_IDX = 0, Y_IDX = 1, Z_IDX = 2; - _vertexPositions.push_back(COORD_TO_METERS * glm::vec3(VARIABLES[X_IDX], - VARIABLES[Y_IDX], - VARIABLES[Z_IDX])); + const size_t xIdx = 0, yIdx = 1, zIdx = 2; + _vertexPositions.push_back(coordToMeters * glm::vec3(variables[xIdx], + variables[yIdx], + variables[zIdx])); // Add the extra quantites. Stored in the same array as the x,y,z variables. // Hence index of the first extra quantity = 3 - for (size_t xtraIdx = 3, k = 0 ; k < N_EXTRAS; ++k, ++xtraIdx) { - _extraQuantities[k].push_back(VARIABLES[xtraIdx]); + for (size_t xtraIdx = 3, k = 0 ; k < nExtras; ++k, ++xtraIdx) { + _extraQuantities[k].push_back(variables[xtraIdx]); } } - _lineCount.push_back(static_cast(N_POINTS)); + _lineCount.push_back(static_cast(nPoints)); _lineStart.push_back(static_cast(lineStartIdx)); - lineStartIdx += N_POINTS; + lineStartIdx += nPoints; } return true; } /** - * @param ABS_FILEPATH must be the path to the file (incl. filename but excl. extension!) + * @param absPath must be the path to the file (incl. filename but excl. extension!) * Directory must exist! File is created (or overwritten if already existing). * File is structured like this: (for version 0) - * 0. int - version number of binary state file! (in case something needs to be altered in the future, then increase CURRENT_VERSION) + * 0. int - version number of binary state file! (in case something needs to be altered in the future, then increase CurrentVersion) * 1. double - _triggerTime * 2. int - _model * 3. bool - _isMorphable @@ -459,17 +459,17 @@ bool FieldlinesState::loadStateFromJson(const std::string& PATH_TO_JSON_FILE, * 10. std::vector - _extraQuantities * 11. array of c_str - Strings naming the extra quantities (elements of _extraQuantityNames). Each string ends with null char '\0' */ -void FieldlinesState::saveStateToOsfls(const std::string& ABS_FILEPATH) { +void FieldlinesState::saveStateToOsfls(const std::string& absPath) { // ------------------------------- Create the file ------------------------------- // std::string pathSafeTimeString = Time(_triggerTime).ISO8601(); pathSafeTimeString.replace(13, 1, "-"); pathSafeTimeString.replace(16, 1, "-"); pathSafeTimeString.replace(19, 1, "-"); - const std::string FILENAME = pathSafeTimeString + ".osfls"; + const std::string fileName = pathSafeTimeString + ".osfls"; - std::ofstream ofs(ABS_FILEPATH + FILENAME, std::ofstream::binary | std::ofstream::trunc); + std::ofstream ofs(absPath + fileName, std::ofstream::binary | std::ofstream::trunc); if (!ofs.is_open()) { - LERROR("Failed to save state to binary file: " << ABS_FILEPATH << FILENAME); + LERROR("Failed to save state to binary file: " << absPath << fileName); return; } @@ -479,34 +479,34 @@ void FieldlinesState::saveStateToOsfls(const std::string& ABS_FILEPATH) { allExtraQuantityNamesInOne += str + '\0'; // Add the null char '\0' for easier reading } - const size_t N_LINES = _lineStart.size(); - const size_t N_POINTS = _vertexPositions.size(); - const size_t N_EXTRAS = _extraQuantities.size(); - const size_t N_STRING_BYTES = allExtraQuantityNamesInOne.size(); + const size_t nLines = _lineStart.size(); + const size_t nPoints = _vertexPositions.size(); + const size_t nExtras = _extraQuantities.size(); + const size_t nStringBytes = allExtraQuantityNamesInOne.size(); //------------------------------ WRITE EVERYTHING TO FILE ------------------------------ // WHICH VERSION OF BINARY FIELDLINES STATE FILE - IN CASE STRUCTURE CHANGES IN THE FUTURE - ofs.write( (char*)(&CURRENT_VERSION), sizeof( int ) ); + ofs.write( (char*)(&CurrentVersion), sizeof( int ) ); //-------------------- WRITE META DATA FOR STATE -------------------------------- - ofs.write( reinterpret_cast(&_triggerTime), sizeof( _triggerTime ) ); - ofs.write( reinterpret_cast(&_model), sizeof( int ) ); - ofs.write( reinterpret_cast(&_isMorphable), sizeof( bool ) ); + ofs.write( reinterpret_cast(&_triggerTime), sizeof( _triggerTime ) ); + ofs.write( reinterpret_cast(&_model), sizeof( int ) ); + ofs.write( reinterpret_cast(&_isMorphable), sizeof( bool ) ); - ofs.write( reinterpret_cast(&N_LINES), sizeof( size_t ) ); - ofs.write( reinterpret_cast(&N_POINTS), sizeof( size_t ) ); - ofs.write( reinterpret_cast(&N_EXTRAS), sizeof( size_t ) ); - ofs.write( reinterpret_cast(&N_STRING_BYTES), sizeof( size_t ) ); + ofs.write( reinterpret_cast(&nLines), sizeof( size_t ) ); + ofs.write( reinterpret_cast(&nPoints), sizeof( size_t ) ); + ofs.write( reinterpret_cast(&nExtras), sizeof( size_t ) ); + ofs.write( reinterpret_cast(&nStringBytes), sizeof( size_t ) ); //---------------------- WRITE ALL ARRAYS OF DATA -------------------------------- - ofs.write( reinterpret_cast(_lineStart.data()), sizeof(GLint) * N_LINES); - ofs.write( reinterpret_cast(_lineCount.data()), sizeof(GLsizei) * N_LINES); - ofs.write( reinterpret_cast(_vertexPositions.data()), sizeof(glm::vec3) * N_POINTS); + ofs.write( reinterpret_cast(_lineStart.data()), sizeof(GLint) * nLines); + ofs.write( reinterpret_cast(_lineCount.data()), sizeof(GLsizei) * nLines); + ofs.write( reinterpret_cast(_vertexPositions.data()), sizeof(glm::vec3) * nPoints); // Write the data for each vector in _extraQuantities for (std::vector& vec : _extraQuantities) { - ofs.write( reinterpret_cast(vec.data()), sizeof(float) * N_POINTS); + ofs.write( reinterpret_cast(vec.data()), sizeof(float) * nPoints); } - ofs.write( allExtraQuantityNamesInOne.c_str(), N_STRING_BYTES); + ofs.write( allExtraQuantityNamesInOne.c_str(), nStringBytes); } // TODO: This should probably be rewritten, but this is the way the files were structured by CCMC @@ -529,15 +529,15 @@ void FieldlinesState::saveStateToOsfls(const std::string& ABS_FILEPATH) { // }, // } // } -void FieldlinesState::saveStateToJson(const std::string& ABS_FILEPATH) { +void FieldlinesState::saveStateToJson(const std::string& absPath) { // Create the file - const std::string EXT = ".json"; - std::ofstream ofs(ABS_FILEPATH + EXT, std::ofstream::trunc); + const std::string ext = ".json"; + std::ofstream ofs(absPath + ext, std::ofstream::trunc); if (!ofs.is_open()) { - LERROR("Failed to save state to json file at location: " << ABS_FILEPATH << EXT); + LERROR("Failed to save state to json file at location: " << absPath << ext); return; } - LINFO("Saving fieldline state to: " << ABS_FILEPATH << EXT ); + LINFO("Saving fieldline state to: " << absPath << ext ); json jColumns = {"x", "y", "z"}; for (std::string s : _extraQuantityNames) { @@ -546,27 +546,26 @@ void FieldlinesState::saveStateToJson(const std::string& ABS_FILEPATH) { json jFile; - const std::string TIME_STRING = Time(_triggerTime).ISO8601(); - - const size_t N_LINES = _lineStart.size(); - const size_t N_POINTS = _vertexPositions.size(); - const size_t N_EXTRAS = _extraQuantities.size(); + const std::string timeStr = Time(_triggerTime).ISO8601(); + const size_t nLines = _lineStart.size(); + const size_t nPoints = _vertexPositions.size(); + const size_t nExtras = _extraQuantities.size(); size_t pointIndex = 0; - for (size_t lineIndex = 0; lineIndex < N_LINES; lineIndex++) { + for (size_t lineIndex = 0; lineIndex < nLines; lineIndex++) { json jData = json::array(); for (size_t i = 0; i < _lineCount[lineIndex]; i++, pointIndex++) { - const glm::vec3 POS = _vertexPositions[pointIndex]; - json jDataElement = {POS.x, POS.y, POS.z}; + const glm::vec3 pos = _vertexPositions[pointIndex]; + json jDataElement = {pos.x, pos.y, pos.z}; - for (size_t extraIndex = 0; extraIndex < N_EXTRAS; extraIndex++) { + for (size_t extraIndex = 0; extraIndex < nExtras; extraIndex++) { jDataElement.push_back(_extraQuantities[extraIndex][pointIndex]); } jData.push_back(jDataElement); } jFile[std::to_string(lineIndex)] = { - {"time", TIME_STRING}, + {"time", timeStr}, {"trace", { {"columns", jColumns}, {"data", jData} @@ -575,19 +574,19 @@ void FieldlinesState::saveStateToJson(const std::string& ABS_FILEPATH) { } //------------------------------ WRITE EVERYTHING TO FILE ------------------------------ - const int INDENTATION_SPACES = 2; - ofs << std::setw(INDENTATION_SPACES) << jFile << std::endl; + const int indentationSpaces = 2; + ofs << std::setw(indentationSpaces) << jFile << std::endl; - LINFO("Saved fieldline state to: " << ABS_FILEPATH << EXT ); + LINFO("Saved fieldline state to: " << absPath << ext ); } -// Returns one of the extra quantity vectors, _extraQuantities[INDEX]. -// If INDEX is out of scope an empty vector is returned and the referenced bool will be false. -const std::vector& FieldlinesState::extraQuantity(const size_t INDEX, +// Returns one of the extra quantity vectors, _extraQuantities[index]. +// If index is out of scope an empty vector is returned and the referenced bool will be false. +const std::vector& FieldlinesState::extraQuantity(const size_t index, bool& isSuccessful) const { - if (INDEX < _extraQuantities.size()) { + if (index < _extraQuantities.size()) { isSuccessful = true; - return _extraQuantities[INDEX]; + return _extraQuantities[index]; } isSuccessful = false; // return empty vector which goes out of scope hence unusable! diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index 67172d1880..71184395c4 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -46,23 +46,23 @@ public: #ifdef OPENSPACE_MODULE_KAMELEON_ENABLED bool addLinesFromKameleon(ccmc::Kameleon* kameleon, - const std::vector& SEED_POINTS, - const std::string TRACING_VAR); + const std::vector& seedPoints, + const std::string tracingVar); void addExtraQuantities(ccmc::Kameleon* kameleon, std::vector& xtraScalarVars, std::vector& xtraMagVars); - void convertLatLonToCartesian(const float SCALE = 1.f); - void scalePositions(const float SCALE); + void convertLatLonToCartesian(const float scale = 1.f); + void scalePositions(const float scale); #endif // OPENSPACE_MODULE_KAMELEON_ENABLED - bool loadStateFromOsfls(const std::string& PATH_TO_OSFLS_FILE); - void saveStateToOsfls(const std::string& PATH_TO_OSFLS_FILE); + bool loadStateFromOsfls(const std::string& pathToOsflsFile); + void saveStateToOsfls(const std::string& pathToOsflsFile); - bool loadStateFromJson(const std::string& PATH_TO_JSON_FILE, - const fls::Model MODEL, const float COORD_TO_METERS); - void saveStateToJson(const std::string& PATH_TO_JSON_FILE); + bool loadStateFromJson(const std::string& pathToJsonFile, + const fls::Model model, const float coordToMeters); + void saveStateToJson(const std::string& pathToJsonFile); - // ------------------------------GETTERS-----------------------------------------// + // ----------------------------------- GETTERS ----------------------------------- // const std::vector>& extraQuantities() const { return _extraQuantities; } const std::vector& extraQuantityNames() const { return _extraQuantityNames; } const std::vector& lineCount() const { return _lineCount; } diff --git a/modules/kameleon/include/kameleonhelper.h b/modules/kameleon/include/kameleonhelper.h index 6d89c87c2f..180ae19e37 100644 --- a/modules/kameleon/include/kameleonhelper.h +++ b/modules/kameleon/include/kameleonhelper.h @@ -34,7 +34,7 @@ namespace ccmc { namespace openspace::kameleonHelper { - std::unique_ptr createKameleonObject(const std::string& CDF_FILE_PATH); + std::unique_ptr createKameleonObject(const std::string& cdfFilePath); double getTime(ccmc::Kameleon* kameleon); } //namespace openspace::kameleonHelper diff --git a/modules/kameleon/src/kameleonhelper.cpp b/modules/kameleon/src/kameleonhelper.cpp index 8ee44abd60..ad3c6444aa 100644 --- a/modules/kameleon/src/kameleonhelper.cpp +++ b/modules/kameleon/src/kameleonhelper.cpp @@ -42,18 +42,18 @@ namespace openspace::kameleonHelper { * * Returns 'nullptr' if the file fails to open! */ -std::unique_ptr createKameleonObject(const std::string& CDF_FILE_PATH) { +std::unique_ptr createKameleonObject(const std::string& cdfFilePath) { // ---------------------------- CREATE KAMELEON OBJECT ---------------------------- // std::unique_ptr kameleon = std::make_unique(); - LDEBUG("\tOpening the cdf file: " << CDF_FILE_PATH); - long kamStatus = kameleon->open(CDF_FILE_PATH); + LDEBUG("\tOpening the cdf file: " << cdfFilePath); + long kamStatus = kameleon->open(cdfFilePath); if (kamStatus != ccmc::FileReader::OK) { - LERROR("Failed to create a Kameleon Object from file: " << CDF_FILE_PATH); + LERROR("Failed to create a Kameleon Object from file: " << cdfFilePath); return nullptr; } - LDEBUG("\tSuccessfully opened : " << CDF_FILE_PATH); + LDEBUG("\tSuccessfully opened : " << cdfFilePath); return kameleon; } From 69fd2ed8a44f6b09362678b9aef5fc4980d0262d Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Wed, 18 Oct 2017 23:48:39 +0200 Subject: [PATCH 33/47] Remove unnecessary debug messages and return false in update() if renderable is disabled --- .../renderablefieldlinessequence.cpp | 110 +++++++++--------- .../renderablefieldlinessequencesetup.cpp | 8 -- 2 files changed, 56 insertions(+), 62 deletions(-) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index ad467f4110..ac0ec033a7 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -155,74 +155,76 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& } void RenderableFieldlinesSequence::update(const UpdateData& data) { + // This node shouldn't do anything if its been disabled from the gui! + if (!_enabled) { + return; + } + if (_shaderProgram->isDirty()) { _shaderProgram->rebuildFromFile(); } - // This node shouldn't do anything if its been disabled from the gui! - if (_enabled) { - const double currentTime = data.time.j2000Seconds(); - // Check if current time in OpenSpace is within sequence interval - if (isWithinSequenceInterval(currentTime)) { - const int nextIdx = _activeTriggerTimeIndex + 1; - if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval - || currentTime < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state - || (nextIdx < _nStates && currentTime >= _startTimes[nextIdx])) { // true => OpenSpace has stepped forward to a time represented by another state + const double currentTime = data.time.j2000Seconds(); + // Check if current time in OpenSpace is within sequence interval + if (isWithinSequenceInterval(currentTime)) { + const int nextIdx = _activeTriggerTimeIndex + 1; + if (_activeTriggerTimeIndex < 0 // true => Previous frame was not within the sequence interval + || currentTime < _startTimes[_activeTriggerTimeIndex] // true => OpenSpace has stepped back to a time represented by another state + || (nextIdx < _nStates && currentTime >= _startTimes[nextIdx])) { // true => OpenSpace has stepped forward to a time represented by another state - updateActiveTriggerTimeIndex(currentTime); + updateActiveTriggerTimeIndex(currentTime); - if (_loadingStatesDynamically) { - _mustLoadNewStateFromDisk = true; - } else { - _needsUpdate = true; - _activeStateIndex = _activeTriggerTimeIndex; - } - } // else {we're still in same state as previous frame (no changes needed)} - } else { - // Not in interval => set everything to false - _activeTriggerTimeIndex = -1; - _mustLoadNewStateFromDisk = false; - _needsUpdate = false; - } - - if (_mustLoadNewStateFromDisk) { - if (!_isLoadingStateFromDisk && !_newStateIsReady) { - _isLoadingStateFromDisk = true; - _mustLoadNewStateFromDisk = false; - const std::string filePath = _sourceFiles[_activeTriggerTimeIndex]; - std::thread readBinaryThread([this, filePath] { - this->readNewState(filePath); - }); - readBinaryThread.detach(); - } - } - - if (_needsUpdate || _newStateIsReady) { if (_loadingStatesDynamically) { - _states[0] = std::move(*_newState); + _mustLoadNewStateFromDisk = true; + } else { + _needsUpdate = true; + _activeStateIndex = _activeTriggerTimeIndex; } + } // else {we're still in same state as previous frame (no changes needed)} + } else { + // Not in interval => set everything to false + _activeTriggerTimeIndex = -1; + _mustLoadNewStateFromDisk = false; + _needsUpdate = false; + } - updateVertexPositionBuffer(); + if (_mustLoadNewStateFromDisk) { + if (!_isLoadingStateFromDisk && !_newStateIsReady) { + _isLoadingStateFromDisk = true; + _mustLoadNewStateFromDisk = false; + const std::string filePath = _sourceFiles[_activeTriggerTimeIndex]; + std::thread readBinaryThread([this, filePath] { + this->readNewState(filePath); + }); + readBinaryThread.detach(); + } + } - if (_states[_activeStateIndex].nExtraQuantities() > 0) { - _shouldUpdateColorBuffer = true; - _shouldUpdateMaskingBuffer = true; - } - - // Everything is set and ready for rendering! - _needsUpdate = false; - _newStateIsReady = false; + if (_needsUpdate || _newStateIsReady) { + if (_loadingStatesDynamically) { + _states[0] = std::move(*_newState); } - if (_shouldUpdateColorBuffer) { - updateVertexColorBuffer(); - _shouldUpdateColorBuffer = false; + updateVertexPositionBuffer(); + + if (_states[_activeStateIndex].nExtraQuantities() > 0) { + _shouldUpdateColorBuffer = true; + _shouldUpdateMaskingBuffer = true; } - if (_shouldUpdateMaskingBuffer) { - updateVertexMaskingBuffer(); - _shouldUpdateMaskingBuffer = false; - } + // Everything is set and ready for rendering! + _needsUpdate = false; + _newStateIsReady = false; + } + + if (_shouldUpdateColorBuffer) { + updateVertexColorBuffer(); + _shouldUpdateColorBuffer = false; + } + + if (_shouldUpdateMaskingBuffer) { + updateVertexMaskingBuffer(); + _shouldUpdateMaskingBuffer = false; } } diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index 112d4090e0..c529394613 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -574,7 +574,6 @@ void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { bool hasExtras = _states[0].nExtraQuantities() > 0; if (hasExtras) { _pColorQuantity.onChange([this] { - LDEBUG("CHANGED COLORING QUANTITY"); _shouldUpdateColorBuffer = true; _pColorQuantityMin = std::to_string(_colorTableRanges[_pColorQuantity].x); _pColorQuantityMax = std::to_string(_colorTableRanges[_pColorQuantity].y); @@ -587,35 +586,30 @@ void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { }); _pColorQuantityMin.onChange([this] { - LDEBUG("CHANGED MIN VALUE"); float f = stringToFloat(_pColorQuantityMin, _colorTableRanges[_pColorQuantity].x); _pColorQuantityMin = std::to_string(f); _colorTableRanges[_pColorQuantity].x = f; }); _pColorQuantityMax.onChange([this] { - LDEBUG("CHANGED MAX VALUE"); float f = stringToFloat(_pColorQuantityMax, _colorTableRanges[_pColorQuantity].y); _pColorQuantityMax = std::to_string(f); _colorTableRanges[_pColorQuantity].y = f; }); _pMaskingQuantity.onChange([this] { - LDEBUG("CHANGED MASKING QUANTITY"); _shouldUpdateMaskingBuffer = true; _pMaskingMin = std::to_string(_maskingRanges[_pMaskingQuantity].x); _pMaskingMax = std::to_string(_maskingRanges[_pMaskingQuantity].y); }); _pMaskingMin.onChange([this] { - LDEBUG("CHANGED LOWER MASKING LIMIT"); float f = stringToFloat(_pMaskingMin, _maskingRanges[_pMaskingQuantity].x); _pMaskingMin = std::to_string(f); _maskingRanges[_pMaskingQuantity].x = f; }); _pMaskingMax.onChange([this] { - LDEBUG("CHANGED UPPER MASKING LIMIT"); float f = stringToFloat(_pMaskingMax, _maskingRanges[_pMaskingQuantity].y); _pMaskingMax = std::to_string(f); _maskingRanges[_pMaskingQuantity].y = f; @@ -623,7 +617,6 @@ void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { } _pFocusOnOriginBtn.onChange([this] { - LDEBUG("SET FOCUS NODE TO PARENT"); SceneGraphNode* node = OsEng.renderEngine().scene()->sceneGraphNode(_name); if (!node) { LWARNING("Could not find a node in scenegraph called '" << _name << "'"); @@ -634,7 +627,6 @@ void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { }); _pJumpToStartBtn.onChange([this] { - LDEBUG("Jump in time to start of sequence!"); OsEng.timeManager().time().setTime(_startTimes[0]); }); } From afd91fc4af28ef9d3cba45cb55b0db0a5ee7ccf3 Mon Sep 17 00:00:00 2001 From: Oskar Carlbaum Date: Sun, 22 Oct 2017 14:55:59 +0200 Subject: [PATCH 34/47] Move all kameleon dependency to separate files named 'kameleonfieldlinehelper' --- modules/fieldlinessequence/CMakeLists.txt | 2 + .../rendering/renderablefieldlinessequence.h | 53 ++- .../renderablefieldlinessequencesetup.cpp | 45 +-- .../util/fieldlinesstate.cpp | 249 +------------ .../fieldlinessequence/util/fieldlinesstate.h | 38 +- .../util/kameleonfieldlinehelper.cpp | 342 ++++++++++++++++++ .../util/kameleonfieldlinehelper.h | 48 +++ 7 files changed, 454 insertions(+), 323 deletions(-) create mode 100644 modules/fieldlinessequence/util/kameleonfieldlinehelper.cpp create mode 100644 modules/fieldlinessequence/util/kameleonfieldlinehelper.h diff --git a/modules/fieldlinessequence/CMakeLists.txt b/modules/fieldlinessequence/CMakeLists.txt index 195e9d93d7..c9b49768f0 100644 --- a/modules/fieldlinessequence/CMakeLists.txt +++ b/modules/fieldlinessequence/CMakeLists.txt @@ -28,6 +28,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequence.h ${CMAKE_CURRENT_SOURCE_DIR}/util/fieldlinesstate.h ${CMAKE_CURRENT_SOURCE_DIR}/util/commons.h + ${CMAKE_CURRENT_SOURCE_DIR}/util/kameleonfieldlinehelper.h ) source_group("Header Files" FILES ${HEADER_FILES}) @@ -36,6 +37,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefieldlinessequencesetup.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/fieldlinesstate.cpp ${CMAKE_CURRENT_SOURCE_DIR}/util/commons.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/util/kameleonfieldlinehelper.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index ef4b4870bf..54f666b660 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -136,38 +136,33 @@ private: properties::TriggerProperty _pJumpToStartBtn; // Button which executes a time jump to start of sequence // --------------------- FUNCTIONS USED DURING INITIALIZATION --------------------- // - void addStateToSequence(FieldlinesState& STATE); - void computeSequenceEndTime(); - void definePropertyCallbackFunctions(); - bool extractJsonInfoFromDictionary(fls::Model& model); - bool extractMandatoryInfoFromDictionary(SourceFileType& sourceFileType); - void extractOptionalInfoFromDictionary(std::string& outputFolderPath); - void extractOsflsInfoFromDictionary(); - void extractTriggerTimesFromFileNames(); - bool loadJsonStatesIntoRAM(const std::string& outputFolder); - void loadOsflsStatesIntoRAM(const std::string& outputFolder); - void setModelDependentConstants(); - void setupProperties(); - bool prepareForOsflsStreaming(); -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED - // --- Initialization functions which require the kameleon module to be loaded! --- // - bool extractCdfInfoFromDictionary(std::string& seedFilePath, - std::string& tracingVar, - std::vector& extraVars); - bool extractSeedPointsFromFile(const std::string& path, - std::vector& outVec); - void extractMagnitudeVarsFromStrings(std::vector& extraVars, - std::vector& extraMagVars); - bool getStatesFromCdfFiles(const std::string& outputFolder); -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + void addStateToSequence(FieldlinesState& STATE); + void computeSequenceEndTime(); + void definePropertyCallbackFunctions(); + bool extractCdfInfoFromDictionary(std::string& seedFilePath, std::string& tracingVar, + std::vector& extraVars); + bool extractJsonInfoFromDictionary(fls::Model& model); + void extractMagnitudeVarsFromStrings(std::vector& extraVars, + std::vector& extraMagVars); + bool extractMandatoryInfoFromDictionary(SourceFileType& sourceFileType); + void extractOptionalInfoFromDictionary(std::string& outputFolderPath); + void extractOsflsInfoFromDictionary(); + bool extractSeedPointsFromFile(const std::string& path, std::vector& outVec); + void extractTriggerTimesFromFileNames(); + bool loadJsonStatesIntoRAM(const std::string& outputFolder); + void loadOsflsStatesIntoRAM(const std::string& outputFolder); + bool getStatesFromCdfFiles(const std::string& outputFolder); + void setModelDependentConstants(); + void setupProperties(); + bool prepareForOsflsStreaming(); // ------------------------- FUNCTIONS USED DURING RUNTIME ------------------------ // inline bool isWithinSequenceInterval(const double currentTime) const; - void readNewState(const std::string& filePath); - void updateActiveTriggerTimeIndex(const double currentTime); - void updateVertexPositionBuffer(); - void updateVertexColorBuffer(); - void updateVertexMaskingBuffer(); + void readNewState(const std::string& filePath); + void updateActiveTriggerTimeIndex(const double currentTime); + void updateVertexPositionBuffer(); + void updateVertexColorBuffer(); + void updateVertexMaskingBuffer(); }; } // namespace openspace diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp index c529394613..538186e5e0 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequencesetup.cpp @@ -24,10 +24,7 @@ #include -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED - #include - #include -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED +#include #include #include @@ -224,11 +221,9 @@ void RenderableFieldlinesSequence::initialize() { // EXTRACT SOURCE FILE TYPE SPECIFIC INFOMRATION FROM DICTIONARY & GET STATES FROM SOURCE switch (sourceFileType) { case SourceFileType::Cdf: -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED if (!getStatesFromCdfFiles(outputFolderPath)) { return; } -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED break; case SourceFileType::Json: if (!loadJsonStatesIntoRAM(outputFolderPath)) { @@ -313,10 +308,6 @@ bool RenderableFieldlinesSequence::extractMandatoryInfoFromDictionary( // Verify that the input type is correct if (inputFileTypeString == ValueInputFileTypeCdf) { sourceFileType = SourceFileType::Cdf; -#ifndef OPENSPACE_MODULE_KAMELEON_ENABLED - LERROR(_name << ": CDF file inputs requires the 'Kameleon' module to be enabled!"); - return false; -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED } else if (inputFileTypeString == ValueInputFileTypeJson) { sourceFileType = SourceFileType::Json; } else if (inputFileTypeString == ValueInputFileTypeOsfls) { @@ -705,7 +696,6 @@ void RenderableFieldlinesSequence::addStateToSequence(FieldlinesState& state) { _nStates++; } -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& outputFolder) { std::string seedFilePath; @@ -724,30 +714,13 @@ bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& outp extractMagnitudeVarsFromStrings(extraVars, extraMagVars); // Load states into RAM! - for (std::string filePath : _sourceFiles) { - // Create Kameleon object and open CDF file! - std::unique_ptr kameleon = - kameleonHelper::createKameleonObject(filePath); + for (std::string cdfPath : _sourceFiles) { FieldlinesState newState; - newState.setTriggerTime(kameleonHelper::getTime(kameleon.get())); - - if (newState.addLinesFromKameleon(kameleon.get(), seedPoints, tracingVar)) { - // The line points are in their RAW format (unscaled & maybe spherical) - // Before we scale to meters (and maybe cartesian) we must extract - // the extraQuantites, as the iterpolator needs the unaltered positions - newState.addExtraQuantities(kameleon.get(), extraVars, extraMagVars); - switch (newState.model()) { - case fls::Batsrus: - newState.scalePositions(fls::ReToMeter); - break; - case fls::Enlil : - newState.convertLatLonToCartesian(fls::AuToMeter); - break; - default: - break; - } + bool isSuccessful = fls::convertCdfToFieldlinesState(newState, cdfPath, + seedPoints, tracingVar, extraVars, extraMagVars); + if (isSuccessful) { addStateToSequence(newState); if (!outputFolder.empty()) { newState.saveStateToOsfls(outputFolder); @@ -756,9 +729,7 @@ bool RenderableFieldlinesSequence::getStatesFromCdfFiles(const std::string& outp } return true; } -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED /* * Returns false if it fails to extract mandatory information! */ @@ -798,9 +769,7 @@ bool RenderableFieldlinesSequence::extractCdfInfoFromDictionary( return true; } -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED bool RenderableFieldlinesSequence::extractSeedPointsFromFile( const std::string& path, std::vector& outVec) { @@ -829,14 +798,11 @@ bool RenderableFieldlinesSequence::extractSeedPointsFromFile( return true; } -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED void RenderableFieldlinesSequence::extractMagnitudeVarsFromStrings( std::vector& extraVars, std::vector& extraMagVars) { - for (int i = 0; i < extraVars.size(); i++) { const std::string str = extraVars[i]; // Check if string is in the format specified for magnitude variables @@ -861,6 +827,5 @@ void RenderableFieldlinesSequence::extractMagnitudeVarsFromStrings( } } } -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.cpp b/modules/fieldlinessequence/util/fieldlinesstate.cpp index f40f28a7bf..3d61f1c384 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.cpp +++ b/modules/fieldlinessequence/util/fieldlinesstate.cpp @@ -32,241 +32,14 @@ #include -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED - #include - #include - #include -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED - namespace { std::string _loggerCat = "FieldlinesState"; const int CurrentVersion = 0; - - const std::string TAsPOverRho = "T = p/rho"; - const std::string JParallelB = "Current: mag(J||B)"; - const float ToKelvin = 72429735.6984f; // <-- [nPa]/[amu/cm^3] * ToKelvin => Temperature in Kelvin - using json = nlohmann::json; } namespace openspace { -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED -/** - * Traces and adds line vertices to state. (Also sets the simulation model variable: _model!) - * Vertices may need to be scaled to meters & converted from spherical into cartesian coordinates. - * Note that extraQuantities will NOT be set! - */ -bool FieldlinesState::addLinesFromKameleon(ccmc::Kameleon* kameleon, - const std::vector& seedPoints, - const std::string tracingVar) { - - _model = fls::stringToModel(kameleon->getModelName()); - - float innerBoundaryLimit; - - switch (_model) { - case fls::Model::Batsrus : - innerBoundaryLimit = 2.5f; // TODO specify in Lua? - break; - case fls::Model::Enlil : - innerBoundaryLimit = 0.11f; // TODO specify in Lua? - break; - default: - LERROR("OpenSpace's fieldlines sequence currently only supports CDFs from" << - "the BATSRUS and ENLIL models!" ); - return false; - } - - // --------------------------- LOAD TRACING VARIABLE ---------------------------- // - if (!kameleon->loadVariable(tracingVar)) { - LERROR("FAILED TO LOAD TRACING VARIABLE: " << tracingVar); - return false; - } - - LINFO("TRACING FIELD LINES!"); - // - LOOP THROUGH THE SEED POINTS, TRACE LINES AND CONVERT TO THE DESIRED FORMAT - // - size_t lineStart = 0; - for (glm::vec3 seed : seedPoints) { - //--------------------------------------------------------------------------// - // We have to create a new tracer (or actually a new interpolator) for each // - // new line, otherwise some issues occur // - //--------------------------------------------------------------------------// - std::unique_ptr interpolator = - std::make_unique(kameleon->model); - ccmc::Tracer tracer(kameleon, interpolator.get()); - tracer.setInnerBoundary(innerBoundaryLimit); // TODO specify in Lua? - ccmc::Fieldline ccmcFieldline = tracer.bidirectionalTrace(tracingVar, - seed.x, - seed.y, - seed.z); - const std::vector& positions = ccmcFieldline.getPositions(); - - _lineStart.push_back(lineStart); - const size_t nLinePoints = positions.size(); - _lineCount.push_back(static_cast(nLinePoints)); - lineStart += static_cast(nLinePoints); - - for (const ccmc::Point3f& p : positions) { - _vertexPositions.emplace_back( - glm::vec3(p.component1, p.component2, p.component3)); - } - } - - return _vertexPositions.size() > 0; -} -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED - -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED -void FieldlinesState::loadExtrasIntoKameleon(ccmc::Kameleon* kameleon, - std::vector& xtraScalarVars, - std::vector& xtraMagVars) { - // Load the existing SCALAR variables into kameleon. - // Remove non-existing variables from vector - for (int i = 0; i < xtraScalarVars.size(); i++) { - std::string& str = xtraScalarVars[i]; - bool isSuccesful = kameleon->doesVariableExist(str) && kameleon->loadVariable(str); - if (!isSuccesful && - (_model == fls::Model::Batsrus && (str == TAsPOverRho || str == "T" ))) { - LDEBUG("BATSRUS doesn't contain variable T for temperature. Trying to " - << "calculate it using the ideal gas law: T = pressure/density"); - const std::string p = "p", r = "rho"; - isSuccesful = kameleon->doesVariableExist(p) && kameleon->loadVariable(p) - && kameleon->doesVariableExist(r) && kameleon->loadVariable(r); - str = TAsPOverRho; - } - if (!isSuccesful) { - LWARNING("FAILED TO LOAD EXTRA VARIABLE: '" << str << "'. Ignoring it!"); - xtraScalarVars.erase(xtraScalarVars.begin() + i); - --i; - } else { - _extraQuantityNames.push_back(str); - } - } - - // Load the existing magnitude variables (should be provided in multiple of 3) - // into kameleon. Remove non-existing variables from vector - if (xtraMagVars.size() % 3 == 0) { - for (int i = 0; i < static_cast(xtraMagVars.size()); i += 3) { - std::string s1 = xtraMagVars[i]; - std::string s2 = xtraMagVars[i+1]; - std::string s3 = xtraMagVars[i+2]; - bool isSuccesful = kameleon->doesVariableExist(s1) && - kameleon->doesVariableExist(s2) && - kameleon->doesVariableExist(s3) && - kameleon->loadVariable(s1) && - kameleon->loadVariable(s2) && - kameleon->loadVariable(s3); - std::string name = "Magnitude of (" + s1 + ", "+ s2 + ", "+ s3 + ")"; - if (isSuccesful && _model == fls::Model::Batsrus && s1 == "jx" && s2 == "jy" - && s3 == "jz") { - // CCMC isn't really interested in the magnitude of current, but by the - // magnitude of the part of the current's vector that is parallel to the - // magnetic field => ensure that the magnetic variables are loaded - isSuccesful = kameleon->doesVariableExist("bx") && - kameleon->doesVariableExist("by") && - kameleon->doesVariableExist("bz") && - kameleon->loadVariable("bx") && - kameleon->loadVariable("by") && - kameleon->loadVariable("bz"); - name = JParallelB; - } - if (!isSuccesful) { - LWARNING("FAILED TO LOAD AT LEAST ONE OF THE MAGNITUDE VARIABLES: " - << s1 << ", " << s2 << " & " << s3 - << ". Removing ability to store corresponding magnitude!"); - xtraMagVars.erase(xtraMagVars.begin() + i, xtraMagVars.begin() + i + 3); - i -= 3; - } else { - _extraQuantityNames.push_back(name); - } - } - } else { - // WRONG NUMBER OF MAGNITUDE VARIABLES.. REMOVE ALL! - xtraMagVars.clear(); - LWARNING("Wrong number of variables provided for storing magnitudes. " - << "Expects multiple of 3 but " << xtraMagVars.size() - << " are provided"); - } -} -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED - -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED -/** - * Loops through _vertexPositions and extracts corresponding 'extraQuantities' att each - * position from the kameleon object using a ccmc::interpolator. - * Note that the positions MUST be unaltered (NOT scaled NOR converted to different - * coordinate system)! - * - * @param kameleon raw pointer to an already opened Kameleon object - * @param xtraScalarVars vector of strings. Strings should be names of a scalar quantities - * to load into _extraQuantites; such as: "T" for temperature or "rho" for density. - * @param xtraMagVars vector of strings. Size must be multiple of 3. Strings should be - * names of the components needed to calculate magnitude. E.g. {"ux", "uy", "uz"} will - * calculate: sqrt(ux*ux + uy*uy + uz*uz). Magnitude will be stored in _extraQuantities - */ -void FieldlinesState::addExtraQuantities(ccmc::Kameleon* kameleon, - std::vector& xtraScalarVars, - std::vector& xtraMagVars) { - - loadExtrasIntoKameleon(kameleon, xtraScalarVars, xtraMagVars); - - const size_t nXtraScalars = xtraScalarVars.size(); - const size_t nXtraMagnitudes = xtraMagVars.size() / 3; - - _extraQuantities.resize(nXtraScalars + nXtraMagnitudes); - - std::unique_ptr interpolator = - std::make_unique(kameleon->model); - - // ------ Extract all the extraQuantities from kameleon and store in state! ------ // - for (const glm::vec3& p : _vertexPositions) { - // Load the scalars! - for (size_t i = 0; i < nXtraScalars; i++) { - float val; - if (xtraScalarVars[i] == TAsPOverRho) { - val = interpolator->interpolate("p", p.x, p.y, p.z); - val *= ToKelvin; - val /= interpolator->interpolate("rho", p.x, p.y, p.z); - } else { - val = interpolator->interpolate(xtraScalarVars[i], p.x, p.y, p.z); - - // When measuring density in ENLIL CCMC multiply by the radius^2 - if (xtraScalarVars[i] == "rho" && _model == fls::Model::Enlil) { - val *= std::pow(p.x * fls::AuToMeter, 2.0f); - } - } - _extraQuantities[i].push_back(val); - } - // Calculate and store the magnitudes! - for (size_t i = 0; i < nXtraMagnitudes; ++i) { - const size_t idx = i*3; - - const float x = interpolator->interpolate(xtraMagVars[idx] , p.x, p.y, p.z); - const float y = interpolator->interpolate(xtraMagVars[idx+1], p.x, p.y, p.z); - const float z = interpolator->interpolate(xtraMagVars[idx+2], p.x, p.y, p.z); - float val; - // When looking at the current's magnitude in Batsrus, CCMC staff are - // only interested in the magnitude parallel to the magnetic field - if (_extraQuantityNames[nXtraScalars + i] == JParallelB) { - const glm::vec3 normMagnetic = glm::normalize(glm::vec3( - interpolator->interpolate("bx", p.x, p.y, p.z), - interpolator->interpolate("by", p.x, p.y, p.z), - interpolator->interpolate("bz", p.x, p.y, p.z))); - // Magnitude of the part of the current vector that's parallel to - // the magnetic field vector! - val = glm::dot(glm::vec3(x,y,z), normMagnetic); - - } else { - val = std::sqrt(x*x + y*y + z*z); - } - _extraQuantities[i + nXtraScalars].push_back(val); - } - } -} -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED - -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED /** * Converts all glm::vec3 in _vertexPositions from spherical (radius, latitude, longitude) * coordinates into cartesian coordinates. The longitude and latitude coordinates are @@ -283,15 +56,12 @@ void FieldlinesState::convertLatLonToCartesian(const float scale /* = 1.f */) { p = glm::vec3(rCosLat * cos(lon), rCosLat* sin(lon), r * sin(lat)); } } -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED void FieldlinesState::scalePositions(const float scale) { for (glm::vec3& p : _vertexPositions) { p *= scale; } } -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED bool FieldlinesState::loadStateFromOsfls(const std::string& pathToOsflsFile) { std::ifstream ifs(pathToOsflsFile, std::ifstream::binary); @@ -588,9 +358,28 @@ const std::vector& FieldlinesState::extraQuantity(const size_t index, isSuccessful = true; return _extraQuantities[index]; } + LERROR("Provided Index was out of scope!"); isSuccessful = false; // return empty vector which goes out of scope hence unusable! return std::vector(); } +/** Moves the points in @param line over to _vertexPositions and updates _lineStart & _lineCount accordingly. + */ +void FieldlinesState::addLine(std::vector& line) { + const size_t nNewPoints = line.size(); + const size_t nOldPoints = _vertexPositions.size(); + _lineStart.push_back(static_cast(nOldPoints)); + _lineCount.push_back(static_cast(nNewPoints)); + _vertexPositions.reserve(nOldPoints + nNewPoints); + _vertexPositions.insert(_vertexPositions.end(), std::make_move_iterator(line.begin()), + std::make_move_iterator(line.end())); + line.clear(); +} + +void FieldlinesState::setExtraQuantityNames(std::vector& names) { + _extraQuantityNames = std::move(names); + names.clear(); + _extraQuantities.resize(_extraQuantityNames.size()); +} } // namespace openspace diff --git a/modules/fieldlinessequence/util/fieldlinesstate.h b/modules/fieldlinessequence/util/fieldlinesstate.h index 71184395c4..35b1fb9db3 100644 --- a/modules/fieldlinessequence/util/fieldlinesstate.h +++ b/modules/fieldlinessequence/util/fieldlinesstate.h @@ -43,39 +43,35 @@ namespace openspace { class FieldlinesState { public: + void convertLatLonToCartesian(const float scale = 1.f); + void scalePositions(const float scale); -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED - bool addLinesFromKameleon(ccmc::Kameleon* kameleon, - const std::vector& seedPoints, - const std::string tracingVar); - void addExtraQuantities(ccmc::Kameleon* kameleon, - std::vector& xtraScalarVars, - std::vector& xtraMagVars); - void convertLatLonToCartesian(const float scale = 1.f); - void scalePositions(const float scale); -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + bool loadStateFromOsfls(const std::string& pathToOsflsFile); + void saveStateToOsfls(const std::string& pathToOsflsFile); - bool loadStateFromOsfls(const std::string& pathToOsflsFile); - void saveStateToOsfls(const std::string& pathToOsflsFile); - - bool loadStateFromJson(const std::string& pathToJsonFile, - const fls::Model model, const float coordToMeters); - void saveStateToJson(const std::string& pathToJsonFile); + bool loadStateFromJson(const std::string& pathToJsonFile, + const fls::Model model, const float coordToMeters); + void saveStateToJson(const std::string& pathToJsonFile); // ----------------------------------- GETTERS ----------------------------------- // const std::vector>& extraQuantities() const { return _extraQuantities; } const std::vector& extraQuantityNames() const { return _extraQuantityNames; } const std::vector& lineCount() const { return _lineCount; } const std::vector& lineStart() const { return _lineStart; } - size_t nExtraQuantities() const { return _extraQuantities.size(); } fls::Model model() const { return _model; } + size_t nExtraQuantities() const { return _extraQuantities.size(); } double triggerTime() const { return _triggerTime; } const std::vector& vertexPositions() const { return _vertexPositions; } // Special getter. Returns extraQuantities[INDEX]. const std::vector& extraQuantity(const size_t INDEX, bool& isSuccesful) const; - void setTriggerTime(const double T) { _triggerTime = T; } + void setModel(const fls::Model m) { _model = m; } + void setTriggerTime(const double t) { _triggerTime = t; } + void setExtraQuantityNames(std::vector& names); + + void addLine(std::vector& line); + void appendToExtra(size_t idx, float val) { _extraQuantities[idx].push_back(val); } private: bool _isMorphable = false; @@ -87,12 +83,6 @@ private: std::vector _lineCount; std::vector _lineStart; std::vector _vertexPositions; - -#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED - void loadExtrasIntoKameleon(ccmc::Kameleon* kameleon, - std::vector& xtraScalarVars, - std::vector& xtraMagVars); -#endif // OPENSPACE_MODULE_KAMELEON_ENABLED }; } // namespace openspace diff --git a/modules/fieldlinessequence/util/kameleonfieldlinehelper.cpp b/modules/fieldlinessequence/util/kameleonfieldlinehelper.cpp new file mode 100644 index 0000000000..283207ec1c --- /dev/null +++ b/modules/fieldlinessequence/util/kameleonfieldlinehelper.cpp @@ -0,0 +1,342 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + #include + #include + #include +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +#include + +#include + +namespace { + std::string _loggerCat = "FieldlinesSequence[ Kameleon ]"; + + const std::string TAsPOverRho = "T = p/rho"; + const std::string JParallelB = "Current: mag(J||B)"; + const float ToKelvin = 72429735.6984f; // <-- [nPa]/[amu/cm^3] * ToKelvin => Temperature in Kelvin +} + +namespace openspace { +namespace fls { + +// -------------------- DECLARE FUNCTIONS USED (ONLY) IN THIS FILE -------------------- // +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED + bool addLinesToState(ccmc::Kameleon* kameleon, const std::vector& seeds, + const std::string tracingVar, FieldlinesState& state); + void addExtraQuantities(ccmc::Kameleon* kameleon, + std::vector& extraScalarVars, + std::vector& extraMagVars, + FieldlinesState& state); + void prepareStateAndKameleonForExtras(ccmc::Kameleon* kameleon, + std::vector& extraScalarVars, + std::vector& extraMagVars, + FieldlinesState& state); +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED +// ----------------------------------------------------------------------------------- // + +/** Traces field lines from the provided cdf file using kameleon and stores the data in the provided FieldlinesState. + * Returns `false` if it fails to create a valid state. Requires the kameleon module to be activated! + * @param state, FieldlineState which should hold the extracted data + * @param cdfPath, std::string of the absolute path to a .cdf file + * @param seedPoints, vector of seed points from which to trace field lines + * @param tracingVar, which quantity to trace lines from. Typically "b" for magnetic field lines and "u" for velocity flow lines + * @param extraVars, extra scalar quantities to be stored in the FieldlinesState; e.g. "T" for temperature, "rho" for density or "P" for pressure + * @param extraMagVars, variables which should be used for extracting magnitudes, must be a multiple of 3; e.g. "ux", "uy" & "uz" to get the magnitude of the velocity vector at each line vertex + */ +bool convertCdfToFieldlinesState(FieldlinesState& state, const std::string cdfPath, + const std::vector& seedPoints, + const std::string tracingVar, + std::vector& extraVars, + std::vector& extraMagVars) { + +#ifndef OPENSPACE_MODULE_KAMELEON_ENABLED + + LERROR("CDF inputs provided but Kameleon module is deactivated!"); + return false; + +#else // OPENSPACE_MODULE_KAMELEON_ENABLED + + // Create Kameleon object and open CDF file! + std::unique_ptr kameleon = + kameleonHelper::createKameleonObject(cdfPath); + + state.setModel(fls::stringToModel(kameleon->getModelName())); + state.setTriggerTime(kameleonHelper::getTime(kameleon.get())); + + if (addLinesToState(kameleon.get(), seedPoints, tracingVar, state)) { + // The line points are in their RAW format (unscaled & maybe spherical) + // Before we scale to meters (and maybe cartesian) we must extract + // the extraQuantites, as the iterpolator needs the unaltered positions + addExtraQuantities(kameleon.get(), extraVars, extraMagVars, state); + switch (state.model()) { + case fls::Batsrus: + state.scalePositions(fls::ReToMeter); + break; + case fls::Enlil : + state.convertLatLonToCartesian(fls::AuToMeter); + break; + default: + break; + } + + return true; + } + + return false; +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED +} + +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +/** + * Traces and adds line vertices to state. + * Vertices are not scaled to meters nor converted from spherical into cartesian coordinates. + * Note that extraQuantities will NOT be set! + */ +bool addLinesToState(ccmc::Kameleon* kameleon, const std::vector& seedPoints, + const std::string tracingVar, FieldlinesState& state) { + + float innerBoundaryLimit; + + switch (state.model()) { + case fls::Model::Batsrus : + innerBoundaryLimit = 2.5f; // TODO specify in Lua? + break; + case fls::Model::Enlil : + innerBoundaryLimit = 0.11f; // TODO specify in Lua? + break; + default: + LERROR("OpenSpace's fieldlines sequence currently only supports CDFs from the" + << " BATSRUS and ENLIL models!"); + return false; + } + + // ---------------------------- LOAD TRACING VARIABLE ---------------------------- // + if (!kameleon->loadVariable(tracingVar)) { + LERROR("FAILED TO LOAD TRACING VARIABLE: " + tracingVar); + return false; + } + + bool isSuccesful = false; + LINFO("TRACING FIELD LINES!"); + // LOOP THROUGH THE SEED POINTS, TRACE LINES, CONVERT POINTS TO glm::vec3 AND STORE // + for (glm::vec3 seed : seedPoints) { + //--------------------------------------------------------------------------// + // We have to create a new tracer (or actually a new interpolator) for each // + // new line, otherwise some issues occur // + //--------------------------------------------------------------------------// + std::unique_ptr interpolator = + std::make_unique(kameleon->model); + ccmc::Tracer tracer(kameleon, interpolator.get()); + tracer.setInnerBoundary(innerBoundaryLimit); // TODO specify in Lua? + ccmc::Fieldline ccmcFieldline = tracer.bidirectionalTrace(tracingVar, seed.x, + seed.y, + seed.z); + const std::vector& positions = ccmcFieldline.getPositions(); + + const size_t nLinePoints = positions.size(); + + std::vector vertices; + vertices.reserve(nLinePoints); + for (const ccmc::Point3f& p : positions) { + vertices.emplace_back(p.component1, p.component2, p.component3); + } + state.addLine(vertices); + isSuccesful = (nLinePoints > 0) ? true : isSuccesful; + } + + return isSuccesful; +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +/** + * Loops through state's _vertexPositions and extracts corresponding 'extraQuantities' + * from the kameleon object using a ccmc::interpolator. + * Note that the positions MUST be unaltered (NOT scaled NOR converted to different + * coordinate system)! + * + * @param kameleon raw pointer to an already opened Kameleon object + * @param extraScalarVars vector of strings. Strings should be names of a scalar quantities + * to load into _extraQuantites; such as: "T" for temperature or "rho" for density. + * @param extraMagVars vector of strings. Size must be multiple of 3. Strings should be + * names of the components needed to calculate magnitude. E.g. {"ux", "uy", "uz"} will + * calculate: sqrt(ux*ux + uy*uy + uz*uz). Magnitude will be stored in _extraQuantities + * @param state, The FieldlinesState which the extra quantities should be added to. + */ +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +void addExtraQuantities(ccmc::Kameleon* kameleon, + std::vector& extraScalarVars, + std::vector& extraMagVars, FieldlinesState& state) { + + prepareStateAndKameleonForExtras(kameleon, extraScalarVars, extraMagVars, state); + + const size_t nXtraScalars = extraScalarVars.size(); + const size_t nXtraMagnitudes = extraMagVars.size() / 3; + + std::unique_ptr interpolator = + std::make_unique(kameleon->model); + + // ------ Extract all the extraQuantities from kameleon and store in state! ------ // + for (const glm::vec3 p : state.vertexPositions()) { + // Load the scalars! + for (size_t i = 0; i < nXtraScalars; i++) { + float val; + if (extraScalarVars[i] == TAsPOverRho) { + val = interpolator->interpolate("p", p.x, p.y, p.z); + val *= ToKelvin; + val /= interpolator->interpolate("rho", p.x, p.y, p.z); + } else { + val = interpolator->interpolate(extraScalarVars[i], p.x, p.y, p.z); + + // When measuring density in ENLIL CCMC multiply by the radius^2 + if (extraScalarVars[i] == "rho" && state.model() == fls::Model::Enlil) { + val *= std::pow(p.x * fls::AuToMeter, 2.0f); + } + } + state.appendToExtra(i, val); + } + // Calculate and store the magnitudes! + for (size_t i = 0; i < nXtraMagnitudes; ++i) { + const size_t idx = i*3; + + const float x = interpolator->interpolate(extraMagVars[idx] , p.x, p.y, p.z); + const float y = interpolator->interpolate(extraMagVars[idx+1], p.x, p.y, p.z); + const float z = interpolator->interpolate(extraMagVars[idx+2], p.x, p.y, p.z); + float val; + // When looking at the current's magnitude in Batsrus, CCMC staff are + // only interested in the magnitude parallel to the magnetic field + if (state.extraQuantityNames()[nXtraScalars + i] == JParallelB) { + const glm::vec3 normMagnetic = glm::normalize(glm::vec3( + interpolator->interpolate("bx", p.x, p.y, p.z), + interpolator->interpolate("by", p.x, p.y, p.z), + interpolator->interpolate("bz", p.x, p.y, p.z))); + // Magnitude of the part of the current vector that's parallel to + // the magnetic field vector! + val = glm::dot(glm::vec3(x,y,z), normMagnetic); + + } else { + val = std::sqrt(x*x + y*y + z*z); + } + state.appendToExtra(i + nXtraScalars, val); + } + } +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +/** Validate the provided extra quantity variables -> load the data from the validated + * quantities into the kameleon object & add the quantity names into the state's + * _extraQuantityNames vector. + * + * @param kameleon, raw pointer to an already opened kameleon object + * @param extraScalarVars, names of scalar quantities to add to state; e.g "rho" for density + * @param extraMagVars, names of the variables used for calculating magnitudes. Must be multiple of 3. + */ +#ifdef OPENSPACE_MODULE_KAMELEON_ENABLED +void prepareStateAndKameleonForExtras(ccmc::Kameleon* kameleon, + std::vector& extraScalarVars, + std::vector& extraMagVars, + FieldlinesState& state) { + std::vector extraQuantityNames; + fls::Model model = fls::stringToModel(kameleon->getModelName()); + + // Load the existing SCALAR variables into kameleon. + // Remove non-existing variables from vector + for (int i = 0; i < extraScalarVars.size(); i++) { + std::string& str = extraScalarVars[i]; + bool isSuccesful = kameleon->doesVariableExist(str) && kameleon->loadVariable(str); + if (!isSuccesful && + (model == fls::Model::Batsrus && (str == TAsPOverRho || str == "T" ))) { + LDEBUG("BATSRUS doesn't contain variable T for temperature. Trying to " + << "calculate it using the ideal gas law: T = pressure/density"); + const std::string p = "p", r = "rho"; + isSuccesful = kameleon->doesVariableExist(p) && kameleon->loadVariable(p) + && kameleon->doesVariableExist(r) && kameleon->loadVariable(r); + str = TAsPOverRho; + } + if (!isSuccesful) { + LWARNING("FAILED TO LOAD EXTRA VARIABLE: '" << str << "'. Ignoring it!"); + extraScalarVars.erase(extraScalarVars.begin() + i); + --i; + } else { + extraQuantityNames.push_back(str); + } + } + + // Load the existing magnitude variables (should be provided in multiple of 3) + // into kameleon. Remove non-existing variables from vector + if (extraMagVars.size() % 3 == 0) { + for (int i = 0; i < static_cast(extraMagVars.size()); i += 3) { + std::string s1 = extraMagVars[i]; + std::string s2 = extraMagVars[i+1]; + std::string s3 = extraMagVars[i+2]; + bool isSuccesful = kameleon->doesVariableExist(s1) && + kameleon->doesVariableExist(s2) && + kameleon->doesVariableExist(s3) && + kameleon->loadVariable(s1) && + kameleon->loadVariable(s2) && + kameleon->loadVariable(s3); + std::string name = "Magnitude of (" + s1 + ", "+ s2 + ", "+ s3 + ")"; + if (isSuccesful && model == fls::Model::Batsrus && s1 == "jx" && s2 == "jy" + && s3 == "jz") { + // CCMC isn't really interested in the magnitude of current, but by the + // magnitude of the part of the current's vector that is parallel to the + // magnetic field => ensure that the magnetic variables are loaded + isSuccesful = kameleon->doesVariableExist("bx") && + kameleon->doesVariableExist("by") && + kameleon->doesVariableExist("bz") && + kameleon->loadVariable("bx") && + kameleon->loadVariable("by") && + kameleon->loadVariable("bz"); + name = JParallelB; + } + if (!isSuccesful) { + LWARNING("FAILED TO LOAD AT LEAST ONE OF THE MAGNITUDE VARIABLES: " + << s1 << ", " << s2 << " & " << s3 + << ". Removing ability to store corresponding magnitude!"); + extraMagVars.erase(extraMagVars.begin() + i, extraMagVars.begin() + i + 3); + i -= 3; + } else { + extraQuantityNames.push_back(name); + } + } + } else { + // WRONG NUMBER OF MAGNITUDE VARIABLES.. REMOVE ALL! + extraMagVars.clear(); + LWARNING("Wrong number of variables provided for storing magnitudes. " + << "Expects multiple of 3 but " << extraMagVars.size() + << " are provided"); + } + state.setExtraQuantityNames(extraQuantityNames); +} +#endif // OPENSPACE_MODULE_KAMELEON_ENABLED + +} // namespace fls +} // namespace openspace diff --git a/modules/fieldlinessequence/util/kameleonfieldlinehelper.h b/modules/fieldlinessequence/util/kameleonfieldlinehelper.h new file mode 100644 index 0000000000..f6f898a5ed --- /dev/null +++ b/modules/fieldlinessequence/util/kameleonfieldlinehelper.h @@ -0,0 +1,48 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_FIELDLINESSEQUENCE___KAMELEONFIELDLINEHELPER___H__ +#define __OPENSPACE_MODULE_FIELDLINESSEQUENCE___KAMELEONFIELDLINEHELPER___H__ + +#include + +#include +#include + +namespace openspace { + +class FieldlinesState; + +namespace fls { + +bool convertCdfToFieldlinesState(FieldlinesState& state, const std::string cdfPath, + const std::vector& seedPoints, + const std::string tracingVar, + std::vector& extraVars, + std::vector& extraMagVars); + +} // namespace fls +} // namespace openspace + +#endif // __OPENSPACE_MODULE_FIELDLINESSEQUENCE___KAMELEONFIELDLINEHELPER___H__ \ No newline at end of file From 4a449f36681ae23d3602629759dc7ecb10dde93a Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 2 Nov 2017 10:12:57 -0400 Subject: [PATCH 35/47] Update starlabels.data file --- data/scene/digitaluniverse/starlabels/starlabels.data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/scene/digitaluniverse/starlabels/starlabels.data b/data/scene/digitaluniverse/starlabels/starlabels.data index b02b3e2687..d5b2f49e80 100644 --- a/data/scene/digitaluniverse/starlabels/starlabels.data +++ b/data/scene/digitaluniverse/starlabels/starlabels.data @@ -1,5 +1,5 @@ return { FileRequest = { - { Identifier = "digitaluniverse_starlabels_speck", Destination = "speck", Version = 1 } + { Identifier = "digitaluniverse_starlabels_speck", Destination = "speck", Version = 2 } } } From ca6940836644b7f4bc12a1f429ac2c5556b7552e Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 2 Nov 2017 11:58:21 -0400 Subject: [PATCH 36/47] Enable minimum picking distance in NDC --- modules/touch/include/touchinteraction.h | 2 + modules/touch/src/touchinteraction.cpp | 86 ++++++++++++++++++++++-- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/modules/touch/include/touchinteraction.h b/modules/touch/include/touchinteraction.h index 10d466c079..8f3092c8f4 100644 --- a/modules/touch/include/touchinteraction.h +++ b/modules/touch/include/touchinteraction.h @@ -176,6 +176,7 @@ private: properties::FloatProperty _slerpTime; properties::IVec2Property _guiButton; properties::Vec4Property _friction; + properties::FloatProperty _pickingRadiusMinimum; // Class variables VelocityStates _vel; @@ -194,6 +195,7 @@ private: bool _lmSuccess; bool _guiON; std::vector _selected; + SceneGraphNode* _pickingSelected; LMstat _lmstat; glm::dquat _toSlerp; glm::dvec3 _centroid; diff --git a/modules/touch/src/touchinteraction.cpp b/modules/touch/src/touchinteraction.cpp index 339f126a6d..7f86603100 100644 --- a/modules/touch/src/touchinteraction.cpp +++ b/modules/touch/src/touchinteraction.cpp @@ -172,6 +172,12 @@ TouchInteraction::TouchInteraction() glm::vec4(0.f), glm::vec4(0.2f) ) + , _pickingRadiusMinimum( + { "Picking Radius", "Minimum radius for picking in NDC coordinates", "" }, + 0.1f, + 0.f, + 1.f + ) , _vel{ glm::dvec2(0.0), 0.0, 0.0, glm::dvec2(0.0) } , _sensitivity{ glm::dvec2(0.08, 0.045), 4.0, 2.75, glm::dvec2(0.08, 0.045) } , _centroid(glm::dvec3(0.0)) @@ -203,6 +209,7 @@ TouchInteraction::TouchInteraction() addProperty(_slerpTime); addProperty(_guiButton); addProperty(_friction); + addProperty(_pickingRadiusMinimum); _origin.onChange([this]() { SceneGraphNode* node = sceneGraphNode(_origin.value()); @@ -476,6 +483,15 @@ void TouchInteraction::findSelectedNode(const std::vector& list) { glm::dquat camToWorldSpace = _camera->rotationQuaternion(); glm::dvec3 camPos = _camera->positionVec3(); std::vector newSelected; + + struct PickingInfo { + SceneGraphNode* node; + double pickingDistanceNDC; + double pickingDistanceWorld; + }; + std::vector pickingInfo; + + for (const TuioCursor& c : list) { double xCo = 2 * (c.getX() - 0.5); double yCo = -2 * (c.getY() - 0.5); // normalized -1 to 1 coordinates on screen @@ -484,7 +500,8 @@ void TouchInteraction::findSelectedNode(const std::vector& list) { glm::dvec3 raytrace = glm::normalize(cursorInWorldSpace); int id = c.getSessionID(); - for (SceneGraphNode* node : selectableNodes) { + + for (SceneGraphNode* node : selectableNodes) { double boundingSphere = node->boundingSphere(); glm::dvec3 camToSelectable = node->worldPosition() - camPos; double dist = length(glm::cross(cursorInWorldSpace, camToSelectable)) / glm::length(cursorInWorldSpace) - boundingSphere; @@ -492,8 +509,9 @@ void TouchInteraction::findSelectedNode(const std::vector& list) { // finds intersection closest point between boundingsphere and line in world coordinates, assumes line direction is normalized double d = glm::dot(raytrace, camToSelectable); double root = boundingSphere * boundingSphere - glm::dot(camToSelectable, camToSelectable) + d * d; - if (root > 0) // two intersection points (take the closest one) + if (root > 0) { // two intersection points (take the closest one) d -= sqrt(root); + } glm::dvec3 intersectionPoint = camPos + d * raytrace; glm::dvec3 pointInModelView = glm::inverse(node->rotationMatrix()) * (intersectionPoint - node->worldPosition()); @@ -510,9 +528,65 @@ void TouchInteraction::findSelectedNode(const std::vector& list) { newSelected.push_back({ id, node, pointInModelView }); } } + + // Compute locations in view space to perform the picking + glm::dvec4 clip = glm::dmat4(_camera->projectionMatrix()) * _camera->combinedViewMatrix() * glm::vec4(node->worldPosition(), 1.0); + glm::dvec2 ndc = clip / clip.w; + + // If the object is not in the screen, we dont want to consider it at all + if (ndc.x >= -1.0 && ndc.x <= 1.0 && ndc.y >= -1.0 && ndc.y <= 1.0) { + glm::dvec2 cursor = { xCo, yCo }; + + double ndcDist = glm::length(ndc - cursor); + // We either want to select the object if it's bounding sphere as been touched + // (checked by the first part of this loop above) or if the touch point is + // within a minimum distance of the center + if (dist <= 0.0 || (ndcDist <= _pickingRadiusMinimum)) { + + // If the user touched the planet directly, this is definitely the one they are + // interested in => minimum distance + if (dist <= 0.0) { + LINFOC(node->name(), "Picking candidate based on direct touch"); + pickingInfo.push_back({ + node, + -std::numeric_limits::max(), + -std::numeric_limits::max() + }); + } + else { + // The node was considered due to minimum picking distance radius + LINFOC(node->name(), "Picking candidate based on proximity"); + pickingInfo.push_back({ + node, + ndcDist, + dist + }); + } + } + } } } - _selected = newSelected; + + + // After we are done with all of the nodes, we can sort the picking list and pick the + // one that fits best (= is closest or was touched directly) + std::sort( + pickingInfo.begin(), + pickingInfo.end(), + [](const PickingInfo& lhs, const PickingInfo& rhs) { + return lhs.pickingDistanceWorld < rhs.pickingDistanceWorld; + } + ); + + // If an item has been picked, it's in the first position of the vector now + if (!pickingInfo.empty()) { + _pickingSelected = pickingInfo.begin()->node; + LINFOC("Picking", "Picked node: " + _pickingSelected->name()); + } + + LINFOC("Picking", "============"); + + _selected = std::move(newSelected); } // Interprets the input gesture to a specific interaction @@ -634,8 +708,8 @@ void TouchInteraction::computeVelocities(const std::vector& list, co break; } case PICK: { // pick something in the scene as focus node - if (_selected.size() == 1 && _selected.at(0).node) { - setFocusNode(_selected.at(0).node); + if (_pickingSelected) { + setFocusNode(_pickingSelected); OsEng.navigationHandler().setFocusNode(_focusNode); // cant do setFocusNode() since TouchInteraction is not subclass of InteractionMode // rotate camera to look at new focus, using slerp quat @@ -771,6 +845,7 @@ void TouchInteraction::unitTest() { // clear everything _selected.clear(); + _pickingSelected = nullptr; _vel.orbit = glm::dvec2(0.0, 0.0); _vel.zoom = 0.0; _vel.roll = 0.0; @@ -838,6 +913,7 @@ void TouchInteraction::resetAfterInput() { _lastVel.roll = 0.0; _lastVel.pan = glm::dvec2(0.0, 0.0); _selected.clear(); + _pickingSelected = nullptr; } // Reset all property values to default From 7ab79ce6876e28b43f2213a5afa1b862e94579b3 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sat, 4 Nov 2017 09:45:10 -0400 Subject: [PATCH 37/47] Update Digital Universe stars --- data/scene/stars/digitaluniverse/digitaluniverse.data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/scene/stars/digitaluniverse/digitaluniverse.data b/data/scene/stars/digitaluniverse/digitaluniverse.data index e1ea7be746..f5379331c4 100644 --- a/data/scene/stars/digitaluniverse/digitaluniverse.data +++ b/data/scene/stars/digitaluniverse/digitaluniverse.data @@ -1,7 +1,7 @@ return { FileRequest = { { Identifier = "stars_textures", Destination = "textures", Version = 1 }, - { Identifier = "stars_du", Destination = "speck", Version = 1 }, + { Identifier = "stars_du", Destination = "speck", Version = 2 }, { Identifier = "stars_colormap", Destination = ".", Version = 1 }, }, } \ No newline at end of file From 81e81d04e4357c0f5b19c304e1c4e7ff6e5e9af9 Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Sun, 5 Nov 2017 20:04:01 +0100 Subject: [PATCH 38/47] Force Cmake flags for Libtorrent --- apps/Launcher/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/Launcher/CMakeLists.txt b/apps/Launcher/CMakeLists.txt index ce0a9ca48c..a103345d17 100644 --- a/apps/Launcher/CMakeLists.txt +++ b/apps/Launcher/CMakeLists.txt @@ -67,8 +67,8 @@ target_link_libraries( ##### set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_MULTITHREADED ON) -SET(LIBTORRENT_encryption OFF) -SET(LIBTORRENT_shared OFF) +SET(LIBTORRENT_encryption OFF CACHE BOOL "Use OpenSSL Encryption" FORCE) +SET(LIBTORRENT_shared OFF CACHE BOOL "Use Libtorrent as shared library" FORCE) include_external_library( Launcher From 3d9481a4fc3faf8423262960a03f5bc49c01aaba Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Mon, 6 Nov 2017 22:11:58 +0100 Subject: [PATCH 39/47] Make screen log thread safe --- include/openspace/util/screenlog.h | 8 ++++++-- src/util/screenlog.cpp | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/openspace/util/screenlog.h b/include/openspace/util/screenlog.h index f92816cf2a..8335c25f78 100644 --- a/include/openspace/util/screenlog.h +++ b/include/openspace/util/screenlog.h @@ -29,6 +29,7 @@ #include #include +#include namespace openspace { @@ -104,7 +105,7 @@ public: * Returns the list of all stored LogEntry%s. * \return The list of all stored LogEntry%s */ - const std::vector& entries() const; + std::vector entries() const; private: /// The list of all LogEntry%s stored by this ScreenLog @@ -113,9 +114,12 @@ private: /// The time-to-live for the LogEntry%s in this ScreenLog. Is used by the /// #removeExpiredEntries method to remove expired entries. std::chrono::seconds _timeToLive; - + /// The minimum LogLevel of messages LogLevel _logLevel; + + /// A mutex to ensure thread-safety + mutable std::mutex _mutex; }; } // namespace openspace diff --git a/src/util/screenlog.cpp b/src/util/screenlog.cpp index aaa24260c5..5f4a6e46a3 100644 --- a/src/util/screenlog.cpp +++ b/src/util/screenlog.cpp @@ -38,6 +38,7 @@ ScreenLog::ScreenLog(std::chrono::seconds timeToLive, LogLevel logLevel) ScreenLog::~ScreenLog() {} void ScreenLog::removeExpiredEntries() { + std::lock_guard guard(_mutex); auto t = std::chrono::steady_clock::now(); auto ttl = _timeToLive; @@ -51,6 +52,7 @@ void ScreenLog::removeExpiredEntries() { } void ScreenLog::log(LogLevel level, const string& category, const string& message) { + std::lock_guard guard(_mutex); if (level >= _logLevel) { _entries.push_back({ level, @@ -62,7 +64,8 @@ void ScreenLog::log(LogLevel level, const string& category, const string& messag } } -const std::vector& ScreenLog::entries() const { +std::vector ScreenLog::entries() const { + std::lock_guard guard(_mutex); return _entries; } From 80f5706049930603ce93d5d84bfe53499d72f5bc Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 7 Nov 2017 09:19:45 -0600 Subject: [PATCH 40/47] Remove warnings on Clang --- apps/Launcher/mainwindow.cpp | 6 +- ext/ghoul | 2 +- ext/sgct | 2 +- include/openspace/rendering/abufferrenderer.h | 2 + .../rendering/renderablebillboardscloud.cpp | 37 ++++++----- .../rendering/renderabledumeshes.cpp | 8 +-- .../rendering/renderableplanescloud.cpp | 6 +- .../rendering/renderablepoints.cpp | 23 ++++--- .../imgui/include/guiglobebrowsingcomponent.h | 7 +- .../tasks/kameleonvolumetorawtask.h | 2 +- .../rendering/renderablecrawlingline.cpp | 14 ++-- .../rendering/renderabletimevaryingvolume.h | 6 +- src/interaction/orbitalnavigator.cpp | 12 ++-- src/network/parallelconnection.cpp | 30 +++++---- src/properties/scalar/wcharproperty.cpp | 50 +++++++-------- src/rendering/renderengine.cpp | 2 + src/util/spicemanager.cpp | 64 +++++++++++++++++-- support/coding/check_style_guide.py | 6 +- tests/main.cpp | 1 + tests/test_gdalwms.inl | 4 +- tests/test_spicemanager.inl | 13 ++-- 21 files changed, 190 insertions(+), 107 deletions(-) diff --git a/apps/Launcher/mainwindow.cpp b/apps/Launcher/mainwindow.cpp index 855cc023f8..46d6ea595b 100644 --- a/apps/Launcher/mainwindow.cpp +++ b/apps/Launcher/mainwindow.cpp @@ -64,9 +64,9 @@ namespace { class QLog : public ghoul::logging::Log { public: void log( - ghoul::logging::LogLevel level, - const std::string& category, - const std::string& message + [[maybe_unused]] ghoul::logging::LogLevel level, + [[maybe_unused]] const std::string& category, + [[maybe_unused]] const std::string& message ) { //qDebug() << QString::fromStdString(category) << ": " << QString::fromStdString(message); } diff --git a/ext/ghoul b/ext/ghoul index e50afc4291..f723df0348 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit e50afc429167fcccc248192281594cd32dc79844 +Subproject commit f723df034890c0fff4b1411a8419294650486897 diff --git a/ext/sgct b/ext/sgct index ee29d15894..c487fe9d77 160000 --- a/ext/sgct +++ b/ext/sgct @@ -1 +1 @@ -Subproject commit ee29d158944eed9bafbccbccdfb9856b3a96cac0 +Subproject commit c487fe9d778a730125b72027b2da5588a664d01b diff --git a/include/openspace/rendering/abufferrenderer.h b/include/openspace/rendering/abufferrenderer.h index b83e75530e..f16397eb00 100644 --- a/include/openspace/rendering/abufferrenderer.h +++ b/include/openspace/rendering/abufferrenderer.h @@ -71,7 +71,9 @@ public: void setResolution(glm::ivec2 res) override; void setNAaSamples(int nAaSamples) override; + using Renderer::preRaycast; void preRaycast(const RaycasterTask& raycasterTask); + using Renderer::postRaycast; void postRaycast(const RaycasterTask& raycasterTask); void update() override; diff --git a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp index d9130ae819..1084709808 100644 --- a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp +++ b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include @@ -386,7 +386,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di ghoul::Dictionary colorOptionDataDic = dictionary.value( ColorOptionInfo.identifier ); - for (int i = 0; i < colorOptionDataDic.size(); ++i) { + for (int i = 0; i < static_cast(colorOptionDataDic.size()); ++i) { std::string colorMapInUseName( colorOptionDataDic.value(std::to_string(i + 1))); _colorOption.addOption(i, colorMapInUseName); @@ -405,7 +405,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di ghoul::Dictionary rangeDataDic = dictionary.value( ColorRangeInfo.identifier ); - for (int i = 0; i < rangeDataDic.size(); ++i) { + for (int i = 0; i < static_cast(rangeDataDic.size()); ++i) { _colorRangeData.push_back( rangeDataDic.value(std::to_string(i+1))); } @@ -490,7 +490,7 @@ void RenderableBillboardsCloud::initialize() { if (!_colorOptionString.empty()) { // Following DU behavior here. The last colormap variable // entry is the one selected by default. - _colorOption.setValue(_colorRangeData.size()-1); + _colorOption = static_cast(_colorRangeData.size() - 1); } if (_hasPolygon) { @@ -504,7 +504,9 @@ void RenderableBillboardsCloud::initialize() { if (_font == nullptr) { size_t _fontSize = 30; _font = OsEng.fontManager().font("Mono", static_cast(_fontSize), - ghoul::fontrendering::FontManager::Outline::Yes, ghoul::fontrendering::FontManager::LoadGlyphs::No); + ghoul::fontrendering::FontManager::Outline::Yes, + ghoul::fontrendering::FontManager::LoadGlyphs::No + ); } } } @@ -683,7 +685,7 @@ void RenderableBillboardsCloud::render(const RenderData& data, RendererTasks&) { glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix; - glm::mat4 viewMatrix = data.camera.viewMatrix(); + // glm::mat4 viewMatrix = data.camera.viewMatrix(); glm::mat4 projectionMatrix = data.camera.projectionMatrix(); glm::dmat4 modelViewProjectionMatrix = glm::dmat4(projectionMatrix) * modelViewMatrix; @@ -979,14 +981,14 @@ bool RenderableBillboardsCloud::readColorMapFile() { return false; } - std::size_t numberOfColors = 0; + int numberOfColors = 0; // The beginning of the speck file has a header that either contains comments // (signaled by a preceding '#') or information about the structure of the file // (signaled by the keywords 'datavar', 'texturevar', and 'texture') std::string line = ""; while (true) { - std::streampos position = file.tellg(); + // std::streampos position = file.tellg(); std::getline(file, line); if (line[0] == '#' || line.empty()) { @@ -997,15 +999,15 @@ bool RenderableBillboardsCloud::readColorMapFile() { std::locale loc; if (std::isdigit(line[0], loc)) { std::string::size_type sz; - numberOfColors = std::stoi(line, &sz); + numberOfColors = static_cast(std::stoi(line, &sz)); break; } else if (file.eof()) { return false; - } + } } - - for (auto i = 0; i < numberOfColors; ++i) { + + for (int i = 0; i < numberOfColors; ++i) { std::getline(file, line); std::stringstream str(line); @@ -1182,7 +1184,7 @@ bool RenderableBillboardsCloud::saveCachedFile(const std::string& file) const { for (auto pair : _variableDataPositionMap) { int32_t keySize = static_cast(pair.first.size()); fileStream.write(reinterpret_cast(&keySize), sizeof(int32_t)); - for (int c = 0; c < pair.first.size(); ++c) { + for (int c = 0; c < static_cast(pair.first.size()); ++c) { int32_t keyChar = static_cast(pair.first[c]); fileStream.write(reinterpret_cast(&keyChar), sizeof(int32_t)); } @@ -1217,7 +1219,7 @@ void RenderableBillboardsCloud::createDataSlice() { glm::vec2 currentColorRange = _colorRangeData[_colorOption.value()]; float colorMapBinSize = (currentColorRange.y - currentColorRange.x) / static_cast(_colorMapData.size()); float bin = colorMapBinSize; - for (int i = 0; i < _colorMapData.size(); ++i) { + for (int i = 0; i < static_cast(_colorMapData.size()); ++i) { colorBins.push_back(bin); bin += colorMapBinSize; } @@ -1228,7 +1230,7 @@ void RenderableBillboardsCloud::createDataSlice() { glm::vec4 position(glm::vec3(transformedPos), static_cast(_unit)); if (_hasColorMapFile) { - for (auto j = 0; j < 4; ++j) { + for (int j = 0; j < 4; ++j) { _slicedData.push_back(position[j]); } // Finds from which bin to get the color. @@ -1236,14 +1238,15 @@ void RenderableBillboardsCloud::createDataSlice() { // is the outliers color. glm::vec4 itemColor; float variableColor = _fullData[i + 3 + colorMapInUse]; - int c = colorBins.size()-1; + int c = static_cast(colorBins.size() - 1); + // Float vs int comparison? while (variableColor < colorBins[c]) { --c; if (c == 0) break; } - int colorIndex = c == colorBins.size() - 1 ? 0 : c + 1; + int colorIndex = (c == static_cast(colorBins.size())) - 1 ? 0 : c + 1; for (auto j = 0; j < 4; ++j) { _slicedData.push_back(_colorMapData[colorIndex][j]); diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index cae2c552b1..7e847b7b0c 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include @@ -359,7 +359,7 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) ghoul::Dictionary colorDic = dictionary.value( MeshColorInfo.identifier ); - for (int i = 0; i < colorDic.size(); ++i) { + for (int i = 0; i < static_cast(colorDic.size()); ++i) { _meshColorMap.insert({ i + 1, colorDic.value(std::to_string(i + 1)) }); } @@ -447,7 +447,7 @@ void RenderableDUMeshes::renderMeshes(const RenderData&, for (auto pair : _renderingMeshesMap) { _program->setUniform("color", _meshColorMap[pair.second.colorIndex]); - for (int i = 0; i < pair.second.vaoArray.size(); ++i) { + for (int i = 0; i < static_cast(pair.second.vaoArray.size()); ++i) { glBindVertexArray(pair.second.vaoArray[i]); switch (pair.second.style) { @@ -936,7 +936,7 @@ void RenderableDUMeshes::createMeshes() { break; } - for (int v = 0; v < it->second.vertices.size(); ++v) { + for (int v = 0; v < static_cast(it->second.vertices.size()); ++v) { it->second.vertices[v] *= scale; } diff --git a/modules/digitaluniverse/rendering/renderableplanescloud.cpp b/modules/digitaluniverse/rendering/renderableplanescloud.cpp index f4af818063..320e27cc22 100644 --- a/modules/digitaluniverse/rendering/renderableplanescloud.cpp +++ b/modules/digitaluniverse/rendering/renderableplanescloud.cpp @@ -40,7 +40,7 @@ #include #include -#include +#include #include #include @@ -1040,9 +1040,9 @@ void RenderablePlanesCloud::createPlanes() { LDEBUG("Creating planes"); int planeNumber = 0; - for (int p = 0; p < _fullData.size(); p += _nValuesPerAstronomicalObject) { + for (int p = 0; p < static_cast(_fullData.size()); p += _nValuesPerAstronomicalObject) { glm::vec4 transformedPos = glm::vec4(_transformationMatrix * - glm::dvec4(_fullData[p + 0], _fullData[p + 1], _fullData[p + 2], 1.0)); + glm::dvec4(_fullData[p + 0], _fullData[p + 1], _fullData[p + 2], 1.0)); // Plane vectors u and v glm::vec4 u = glm::vec4(_transformationMatrix * diff --git a/modules/digitaluniverse/rendering/renderablepoints.cpp b/modules/digitaluniverse/rendering/renderablepoints.cpp index 1acc217745..3587436f69 100644 --- a/modules/digitaluniverse/rendering/renderablepoints.cpp +++ b/modules/digitaluniverse/rendering/renderablepoints.cpp @@ -364,8 +364,8 @@ namespace openspace { if (_hasColorMapFile) { const size_t nAstronomicalObjects = _fullData.size() / _nValuesPerAstronomicalObject; - const size_t nValues = _slicedData.size() / nAstronomicalObjects; - GLsizei stride = static_cast(sizeof(double) * nValues); + // const size_t nValues = _slicedData.size() / nAstronomicalObjects; + // GLsizei stride = static_cast(sizeof(double) * nValues); glEnableVertexAttribArray(positionAttrib); glVertexAttribLPointer( @@ -540,14 +540,14 @@ namespace openspace { return false; } - std::size_t numberOfColors = 0; + int numberOfColors = 0; // The beginning of the speck file has a header that either contains comments // (signaled by a preceding '#') or information about the structure of the file // (signaled by the keywords 'datavar', 'texturevar', and 'texture') std::string line = ""; while (true) { - std::streampos position = file.tellg(); + // std::streampos position = file.tellg(); std::getline(file, line); if (line[0] == '#' || line.empty()) { @@ -558,7 +558,7 @@ namespace openspace { std::locale loc; if (std::isdigit(line[0], loc)) { std::string::size_type sz; - numberOfColors = std::stoi(line, &sz); + numberOfColors = static_cast(std::stoi(line, &sz)); break; } else if (file.eof()) { @@ -566,7 +566,7 @@ namespace openspace { } } - for (auto i = 0; i < numberOfColors; ++i) { + for (int i = 0; i < numberOfColors; ++i) { std::getline(file, line); std::stringstream str(line); @@ -674,20 +674,23 @@ namespace openspace { glm::dvec4 position(p, 1.0); if (_hasColorMapFile) { - for (auto j = 0; j < 4; ++j) { + for (int j = 0; j < 4; ++j) { _slicedData.push_back(position[j]); } - for (auto j = 0; j < 4; ++j) { + for (int j = 0; j < 4; ++j) { _slicedData.push_back(_colorMapData[colorIndex][j]); } } else { - for (auto j = 0; j < 4; ++j) { + for (int j = 0; j < 4; ++j) { _slicedData.push_back(position[j]); } } - colorIndex = (colorIndex == (_colorMapData.size() - 1)) ? 0 : colorIndex + 1; + colorIndex = + (colorIndex == (static_cast(_colorMapData.size()) - 1)) ? + 0 : + colorIndex + 1; } } diff --git a/modules/imgui/include/guiglobebrowsingcomponent.h b/modules/imgui/include/guiglobebrowsingcomponent.h index e31a81ead9..1a6b66c064 100644 --- a/modules/imgui/include/guiglobebrowsingcomponent.h +++ b/modules/imgui/include/guiglobebrowsingcomponent.h @@ -22,11 +22,11 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifdef GLOBEBROWSING_USE_GDAL - #ifndef __OPENSPACE_MODULE_IMGUI___GUIGLOBEBROWSINGCOMPONENT___H__ #define __OPENSPACE_MODULE_IMGUI___GUIGLOBEBROWSINGCOMPONENT___H__ +#ifdef GLOBEBROWSING_USE_GDAL + #include #include @@ -49,7 +49,6 @@ private: } // namespace openspace::gui +#endif // GLOBEBROWSING_USE_GDAL #endif // __OPENSPACE_MODULE_IMGUI___GUIGLOBEBROWSINGCOMPONENT___H__ - -#endif // GLOBEBROWSING_USE_GDAL diff --git a/modules/kameleonvolume/tasks/kameleonvolumetorawtask.h b/modules/kameleonvolume/tasks/kameleonvolumetorawtask.h index 2556348d2a..62655bd732 100644 --- a/modules/kameleonvolume/tasks/kameleonvolumetorawtask.h +++ b/modules/kameleonvolume/tasks/kameleonvolumetorawtask.h @@ -56,4 +56,4 @@ private: } // namespace kameleon } // namespace openspace -#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONMETADATATORAWTASK___H__ +#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___KAMELEONVOLUMETORAWTASK___H__ diff --git a/modules/spacecraftinstruments/rendering/renderablecrawlingline.cpp b/modules/spacecraftinstruments/rendering/renderablecrawlingline.cpp index 94011b540b..16811b004c 100644 --- a/modules/spacecraftinstruments/rendering/renderablecrawlingline.cpp +++ b/modules/spacecraftinstruments/rendering/renderablecrawlingline.cpp @@ -228,12 +228,12 @@ void RenderableCrawlingLine::update(const UpdateData& data) { _program->rebuildFromFile(); } - glm::dmat3 transformMatrix = SpiceManager::ref().positionTransformMatrix( - _source, - //"ECLIPJ2000", - "GALACTIC", - data.time.j2000Seconds() - ); + // glm::dmat3 transformMatrix = SpiceManager::ref().positionTransformMatrix( + // _source, + // //"ECLIPJ2000", + // "GALACTIC", + // data.time.j2000Seconds() + // ); glm::dmat3 tm = SpiceManager::ref().frameTransformationMatrix(_instrumentName, "ECLIPJ2000", data.time.j2000Seconds()); @@ -251,7 +251,7 @@ void RenderableCrawlingLine::update(const UpdateData& data) { //} glm::vec4 target(boresight[0], boresight[1], boresight[2], 12); - //target = glm::dmat4(tm) * target; + target = glm::dmat4(tm) * target; //_positions[TargetPosition] = target; //_positions[TargetPosition] = { diff --git a/modules/volume/rendering/renderabletimevaryingvolume.h b/modules/volume/rendering/renderabletimevaryingvolume.h index f3fe18137f..3157319f39 100644 --- a/modules/volume/rendering/renderabletimevaryingvolume.h +++ b/modules/volume/rendering/renderabletimevaryingvolume.h @@ -22,8 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_VOLUME___RENDERABLEKAMELEONVOLUME___H__ -#define __OPENSPACE_MODULE_VOLUME___RENDERABLEKAMELEONVOLUME___H__ +#ifndef __OPENSPACE_MODULE_VOLUME___RENDERABLETIMEVARYINGVOLUME___H__ +#define __OPENSPACE_MODULE_VOLUME___RENDERABLETIMEVARYINGVOLUME___H__ #include @@ -106,4 +106,4 @@ private: } // namespace volume } // namespace openspace -#endif // __OPENSPACE_MODULE_KAMELEONVOLUME___RENDERABLEKAMELEONVOLUME___H__ +#endif // __OPENSPACE_MODULE_VOLUME___RENDERABLETIMEVARYINGVOLUME___H__ diff --git a/src/interaction/orbitalnavigator.cpp b/src/interaction/orbitalnavigator.cpp index fb6e984037..a7f67fe980 100644 --- a/src/interaction/orbitalnavigator.cpp +++ b/src/interaction/orbitalnavigator.cpp @@ -402,8 +402,8 @@ glm::dvec3 OrbitalNavigator::translateHorizontally(double deltaTime, // Vector logic glm::dvec3 posDiff = cameraPosition - objectPosition; - glm::dvec3 centerToReferenceSurface = glm::dmat3(modelTransform) * - positionHandle.centerToReferenceSurface; + // glm::dvec3 centerToReferenceSurface = glm::dmat3(modelTransform) * + // positionHandle.centerToReferenceSurface; glm::dvec3 centerToActualSurfaceModelSpace = positionHandle.centerToReferenceSurface + positionHandle.referenceSurfaceOutDirection * positionHandle.heightToSurface; glm::dvec3 centerToActualSurface = glm::dmat3(modelTransform) * @@ -488,8 +488,8 @@ glm::dvec3 OrbitalNavigator::translateVertically( glm::dvec3 posDiff = cameraPosition - objectPosition; - glm::dvec3 centerToReferenceSurface = - glm::dmat3(modelTransform) * positionHandle.centerToReferenceSurface; + // glm::dvec3 centerToReferenceSurface = + // glm::dmat3(modelTransform) * positionHandle.centerToReferenceSurface; glm::dvec3 centerToActualSurfaceModelSpace = positionHandle.centerToReferenceSurface + positionHandle.referenceSurfaceOutDirection * positionHandle.heightToSurface; @@ -533,8 +533,8 @@ glm::dvec3 OrbitalNavigator::pushToSurface( glm::dvec3 posDiff = cameraPosition - objectPosition; glm::dvec3 referenceSurfaceOutDirection = glm::dmat3(modelTransform) * positionHandle.referenceSurfaceOutDirection; - glm::dvec3 centerToReferenceSurface = - glm::dmat3(modelTransform) * positionHandle.centerToReferenceSurface; + // glm::dvec3 centerToReferenceSurface = + // glm::dmat3(modelTransform) * positionHandle.centerToReferenceSurface; glm::dvec3 centerToActualSurfaceModelSpace = positionHandle.centerToReferenceSurface + positionHandle.referenceSurfaceOutDirection * positionHandle.heightToSurface; diff --git a/src/network/parallelconnection.cpp b/src/network/parallelconnection.cpp index 7f0236e53c..718e405324 100644 --- a/src/network/parallelconnection.cpp +++ b/src/network/parallelconnection.cpp @@ -35,17 +35,24 @@ #include #include #include + #ifndef SOCKET_ERROR #define SOCKET_ERROR (-1) #endif #ifndef INVALID_SOCKET -#define INVALID_SOCKET (_SOCKET)(~0) +#define INVALID_SOCKET static_cast<_SOCKET>(~0) #endif -#ifndef NO_ERROR -#define NO_ERROR 0L -#endif +// #ifndef NO_ERROR +// #define NO_ERROR 0L +// #endif + +#ifdef WIN32 +using SocketResultType = int; +#else +using SocketResultType = size_t; +#endif // WIN32 #ifndef _ERRNO #define _ERRNO errno @@ -697,8 +704,7 @@ void ParallelConnection::queueOutMessage(const Message& message) { _sendCondition.notify_all(); } -void ParallelConnection::sendFunc(){ - int result; +void ParallelConnection::sendFunc() { // While we're connected while (_isConnected && !_disconnect) { // Wait for signal then lock mutex and send first queued message @@ -737,7 +743,9 @@ void ParallelConnection::sendFunc(){ reinterpret_cast(&messageSizeOut) + sizeof(uint32_t) ); - result = send( + // result is most likely size_t, but send might return a different type on + // different platforms + auto result = send( _clientSocket, header.data(), static_cast(header.size()), @@ -976,8 +984,8 @@ void ParallelConnection::listenCommunication() { int ParallelConnection::receiveData(_SOCKET& socket, std::vector& buffer, int length, int flags) { - int result = 0; - int received = 0; + SocketResultType result = 0; + SocketResultType received = 0; while (result < length) { received = recv(socket, buffer.data() + result, length - result, flags); @@ -992,9 +1000,9 @@ int ParallelConnection::receiveData(_SOCKET& socket, std::vector& buffer, } } - return result; + return static_cast(result); } - + void ParallelConnection::setPort(std::string port){ _port = std::move(port); } diff --git a/src/properties/scalar/wcharproperty.cpp b/src/properties/scalar/wcharproperty.cpp index 0d011ba509..75bc573f2e 100644 --- a/src/properties/scalar/wcharproperty.cpp +++ b/src/properties/scalar/wcharproperty.cpp @@ -33,33 +33,33 @@ using std::numeric_limits; namespace openspace::properties { -#define DEFAULT_FROM_LUA_LAMBDA(TYPE, DEFAULT_VALUE) \ - [](lua_State* state, bool& success) -> TYPE { \ - success = (lua_isnumber(state, -1) == 1); \ - if (success) { \ - return static_cast(lua_tonumber(state, -1)); \ - } \ - else { \ - return DEFAULT_VALUE; \ - } \ - } +// #define DEFAULT_FROM_LUA_LAMBDA(TYPE, DEFAULT_VALUE) \ +// [](lua_State* state, bool& success) -> TYPE { \ +// success = (lua_isnumber(state, -1) == 1); \ +// if (success) { \ +// return static_cast(lua_tonumber(state, -1)); \ +// } \ +// else { \ +// return DEFAULT_VALUE; \ +// } \ +// } -#define DEFAULT_TO_LUA_LAMBDA(TYPE) \ - [](lua_State* state, TYPE value) -> bool { \ - lua_pushnumber(state, static_cast(value)); \ - return true; \ - } +// #define DEFAULT_TO_LUA_LAMBDA(TYPE) \ +// [](lua_State* state, TYPE value) -> bool { \ +// lua_pushnumber(state, static_cast(value)); \ +// return true; \ +// } -#define DEFAULT_FROM_STRING_LAMBDA(TYPE, DEFAULT_VALUE) \ - [](std::string val, bool& success) -> TYPE { \ - std::stringstream s(val); \ - TYPE v; \ - s >> v; \ - success = !s.fail(); \ - if (success) { \ - return v; \ - } \ - } +// #define DEFAULT_FROM_STRING_LAMBDA(TYPE, DEFAULT_VALUE) \ +// [](std::string val, bool& success) -> TYPE { \ +// std::stringstream s(val); \ +// TYPE v; \ +// s >> v; \ +// success = !s.fail(); \ +// if (success) { \ +// return v; \ +// } \ +// } //REGISTER_NUMERICALPROPERTY_SOURCE(WCharProperty, wchar_t, wchar_t(0), // numeric_limits::lowest(), diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index e02dc1ca89..952582602e 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -989,6 +989,8 @@ void RenderEngine::renderInformation() { 1.0 / OsEng.windowWrapper().averageDeltaTime() ); break; + case FrametimeType::None: + break; } ParallelConnection::Status status = OsEng.parallelConnection().status(); diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index e4a1f9a104..aee1e24eae 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -919,15 +919,43 @@ void SpiceManager::findCkCoverage(const std::string& path) { const unsigned int MaxObj = 64; const unsigned int WinSiz = 10000; +#if defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + SPICEINT_CELL(ids, MaxObj); SPICEDOUBLE_CELL(cover, WinSiz); - + +#if defined __clang__ +#pragma clang diagnostic pop +#elif defined __GNUC__ +#pragma GCC diagnostic pop +#endif + ckobj_c(path.c_str(), &ids); throwOnSpiceError("Error finding Ck Coverage"); for (SpiceInt i = 0; i < card_c(&ids); ++i) { +#if defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + SpiceInt frame = SPICE_CELL_ELEM_I(&ids, i); - + +#if defined __clang__ +#pragma clang diagnostic pop +#elif defined __GNUC__ +#pragma GCC diagnostic pop +#endif + scard_c(0, &cover); ckcov_c(path.c_str(), frame, SPICEFALSE, "SEGMENT", 0.0, "TDB", &cover); throwOnSpiceError("Error finding Ck Coverage"); @@ -955,15 +983,43 @@ void SpiceManager::findSpkCoverage(const std::string& path) { const unsigned int MaxObj = 64; const unsigned int WinSiz = 10000; +#if defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + SPICEINT_CELL(ids, MaxObj); SPICEDOUBLE_CELL(cover, WinSiz); - + +#if defined __clang__ +#pragma clang diagnostic pop +#elif defined __GNUC__ +#pragma GCC diagnostic pop +#endif + spkobj_c(path.c_str(), &ids); throwOnSpiceError("Error finding Spk Converage"); for (SpiceInt i = 0; i < card_c(&ids); ++i) { +#if defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + SpiceInt obj = SPICE_CELL_ELEM_I(&ids, i); - + +#if defined __clang__ +#pragma clang diagnostic pop +#elif defined __GNUC__ +#pragma GCC diagnostic pop +#endif + scard_c(0, &cover); spkcov_c(path.c_str(), obj, &cover); throwOnSpiceError("Error finding Spk Converage"); diff --git a/support/coding/check_style_guide.py b/support/coding/check_style_guide.py index fa8ebce5e2..65663d87a2 100644 --- a/support/coding/check_style_guide.py +++ b/support/coding/check_style_guide.py @@ -148,6 +148,8 @@ def check_comment(lines): endif_line = lines[index[-1]].strip() if endif_line != '#endif // ' + ifndef_symbol: + print(ifndef_symbol) + print(endif_line) return '#endif line is not correctly formatted' else: return '' @@ -207,8 +209,10 @@ def check_naming_convention_subcomponent(lines, component, file): subcomponent_part = subcomponent_part[: subcomponent_part.find('_')] path_part = file.split(os.sep)[1] + second_path_part = file.split(os.sep)[2] - if path_part.upper() != subcomponent_part: + + if (path_part.upper() != subcomponent_part) and (second_path_part.upper() != subcomponent_part): return 'Subcomponent naming convention broken: ' + ifndef_symbol else: return '' diff --git a/tests/main.cpp b/tests/main.cpp index 71acb6f178..d49b4e62fb 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -30,6 +30,7 @@ #pragma clang diagnostic ignored "-Wundef" #pragma clang diagnostic ignored "-Wmissing-noreturn" #pragma clang diagnostic ignored "-Wshift-sign-overflow" +#pragma clang diagnostic ignored "-Wsign-compare" #elif defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wundef" diff --git a/tests/test_gdalwms.inl b/tests/test_gdalwms.inl index e8efb87766..a936586e72 100644 --- a/tests/test_gdalwms.inl +++ b/tests/test_gdalwms.inl @@ -45,7 +45,7 @@ class GdalWmsTest : public testing::Test {}; TEST_F(GdalWmsTest, Simple) { - GDALDataset *poDataset; + GDALDatasetH poDataset; GDALAllRegister(); @@ -55,7 +55,7 @@ TEST_F(GdalWmsTest, Simple) { std::string testFile = absPath("${TESTDIR}/gdal/TERRA_CR_B143_2016-04-12.wms"); - poDataset = (GDALDataset *)GDALOpen(testFile.c_str(), GA_ReadOnly); + poDataset = GDALOpen(testFile.c_str(), GA_ReadOnly); // This assertion fails //ASSERT_NE(poDataset, nullptr) << "Failed to load testFile"; diff --git a/tests/test_spicemanager.inl b/tests/test_spicemanager.inl index 812484229b..430886a777 100644 --- a/tests/test_spicemanager.inl +++ b/tests/test_spicemanager.inl @@ -415,17 +415,22 @@ TEST_F(SpiceManagerTest, getPositionTransformMatrix) { } } -#if (defined(__GNUC__) && !defined(__clang__)) +#if defined __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wold-style-cast" -#endif // __GNUC__ +#endif // transform reference position into new frame mxvg_c(referenceMatrix, state, 3, 3, state_t); -#if (defined(__GNUC__) && !defined(__clang__)) +#if defined __clang__ +#pragma clang diagnostic pop +#elif defined __GNUC__ #pragma GCC diagnostic pop -#endif // __GNUC__ +#endif position = positionMatrix * position; // check transformed values match From d94408224c8ed749d19ba18ef700a489675c33c8 Mon Sep 17 00:00:00 2001 From: Emil Axelsson Date: Tue, 7 Nov 2017 18:04:35 +0100 Subject: [PATCH 41/47] Compile fix for Windows --- src/network/parallelconnection.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/network/parallelconnection.cpp b/src/network/parallelconnection.cpp index 718e405324..f62abb2041 100644 --- a/src/network/parallelconnection.cpp +++ b/src/network/parallelconnection.cpp @@ -48,17 +48,17 @@ // #define NO_ERROR 0L // #endif +#ifndef _ERRNO +#define _ERRNO errno +#endif +#endif + #ifdef WIN32 using SocketResultType = int; #else using SocketResultType = size_t; #endif // WIN32 -#ifndef _ERRNO -#define _ERRNO errno -#endif -#endif - #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN From b50b52d3516d5c1bfdd6ccd34e5cd408dfb59357 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 8 Nov 2017 10:35:39 -0600 Subject: [PATCH 42/47] Cleanup for coding style Add strict mode to check_style_guide script --- apps/Launcher/mainwindow.cpp | 27 +- apps/Launcher/mainwindow.h | 6 +- apps/Launcher/syncwidget.cpp | 16 +- apps/Launcher/syncwidget.h | 2 +- apps/OpenSpace/main.cpp | 66 +++-- apps/TimelineView/controlwidget.cpp | 1 - apps/TimelineView/mainwindow.cpp | 4 +- apps/TimelineView/mainwindow.h | 2 +- apps/TimelineView/timelinewidget.cpp | 4 +- ext/ghoul | 2 +- .../openspace/documentation/documentation.h | 2 +- .../documentation/documentationgenerator.h | 11 +- .../openspace/engine/configurationmanager.h | 2 +- include/openspace/engine/moduleengine.h | 6 +- include/openspace/engine/openspaceengine.h | 32 +-- include/openspace/engine/settingsengine.h | 4 +- include/openspace/engine/syncengine.h | 2 +- .../engine/wrapper/sgctwindowwrapper.h | 6 +- .../openspace/engine/wrapper/windowwrapper.h | 26 +- include/openspace/interaction/controller.h | 2 +- include/openspace/interaction/interpolator.h | 2 +- .../openspace/interaction/keybindingmanager.h | 4 +- include/openspace/interaction/mousestate.h | 2 +- .../openspace/interaction/navigationhandler.h | 2 +- .../openspace/interaction/orbitalnavigator.h | 6 +- include/openspace/mission/mission.h | 2 +- include/openspace/network/messagestructures.h | 40 +-- .../openspace/network/parallelconnection.h | 9 +- .../performance/performancemanager.h | 14 +- .../performance/performancemeasurement.h | 4 +- .../properties/numericalproperty.inl | 2 +- include/openspace/properties/property.h | 6 +- include/openspace/properties/propertyowner.h | 13 +- .../properties/scalar/boolproperty.h | 2 +- .../properties/scalar/charproperty.h | 2 +- .../properties/scalar/doubleproperty.h | 2 +- .../properties/scalar/floatproperty.h | 2 +- .../openspace/properties/scalar/intproperty.h | 2 +- .../properties/scalar/longdoubleproperty.h | 2 +- .../properties/scalar/longlongproperty.h | 2 +- .../properties/scalar/longproperty.h | 2 +- .../properties/scalar/shortproperty.h | 2 +- .../properties/scalar/signedcharproperty.h | 2 +- .../properties/scalar/ucharproperty.h | 2 +- .../properties/scalar/uintproperty.h | 2 +- .../properties/scalar/ulonglongproperty.h | 2 +- .../properties/scalar/ulongproperty.h | 2 +- .../properties/scalar/ushortproperty.h | 2 +- .../properties/scalar/wcharproperty.h | 2 +- .../openspace/properties/selectionproperty.h | 2 +- include/openspace/rendering/abufferrenderer.h | 11 +- .../openspace/rendering/framebufferrenderer.h | 6 +- include/openspace/rendering/renderable.h | 6 +- include/openspace/rendering/renderengine.h | 14 +- include/openspace/rendering/renderer.h | 6 +- .../rendering/screenspacerenderable.h | 8 +- include/openspace/rendering/volume.h | 4 +- include/openspace/rendering/volumeraycaster.h | 5 +- include/openspace/scene/scene.h | 2 +- include/openspace/scene/scenegraphnode.h | 4 +- include/openspace/scene/scenelicense.h | 10 +- include/openspace/scene/scenelicensewriter.h | 2 +- include/openspace/scripting/scriptengine.h | 20 +- include/openspace/scripting/scriptscheduler.h | 10 +- include/openspace/util/boxgeometry.h | 2 +- include/openspace/util/camera.h | 2 +- include/openspace/util/factorymanager.h | 8 +- include/openspace/util/factorymanager.inl | 2 +- include/openspace/util/gpudata.h | 16 +- include/openspace/util/keys.h | 8 +- include/openspace/util/mouse.h | 2 +- include/openspace/util/openspacemodule.h | 10 +- include/openspace/util/powerscaledscalar.h | 9 +- include/openspace/util/screenlog.h | 16 +- include/openspace/util/spicemanager.h | 84 +++---- include/openspace/util/task.h | 2 +- include/openspace/util/time.h | 9 +- include/openspace/util/timerange.h | 4 +- modules/base/rendering/modelgeometry.cpp | 4 +- modules/base/rendering/modelgeometry.h | 4 +- modules/base/rendering/multimodelgeometry.cpp | 2 +- modules/base/rendering/renderablemodel.cpp | 2 +- modules/base/rendering/renderableplane.cpp | 5 +- modules/base/rendering/renderablesphere.cpp | 6 +- modules/base/rendering/renderabletrail.cpp | 4 +- modules/base/rendering/renderabletrail.h | 2 +- .../base/rendering/renderabletrailorbit.cpp | 2 +- modules/base/rendering/renderabletrailorbit.h | 4 +- .../rendering/renderabletrailtrajectory.cpp | 8 +- .../rendering/renderabletrailtrajectory.h | 2 +- .../base/rendering/screenspaceframebuffer.cpp | 4 +- .../base/rendering/screenspaceframebuffer.h | 2 +- .../base/rendering/screenspaceimagelocal.h | 4 +- .../base/rendering/screenspaceimageonline.h | 4 +- modules/base/rendering/wavefrontgeometry.cpp | 1 - modules/base/rotation/luarotation.cpp | 2 +- modules/base/rotation/luarotation.h | 4 +- modules/base/rotation/staticrotation.h | 6 +- modules/base/scale/luascale.cpp | 2 +- modules/base/scale/luascale.h | 4 +- modules/base/scale/staticscale.cpp | 2 +- modules/base/scale/staticscale.h | 6 +- modules/base/translation/luatranslation.cpp | 2 +- modules/base/translation/luatranslation.h | 4 +- modules/base/translation/statictranslation.h | 4 +- modules/debugging/debuggingmodule.h | 2 +- modules/debugging/rendering/debugrenderer.cpp | 8 +- modules/debugging/rendering/debugrenderer.h | 6 +- .../rendering/renderabledebugplane.cpp | 12 +- .../rendering/renderablebillboardscloud.cpp | 87 ++++--- .../rendering/renderablebillboardscloud.h | 6 +- .../rendering/renderabledumeshes.cpp | 26 +- .../rendering/renderabledumeshes.h | 7 +- .../rendering/renderableplanescloud.cpp | 82 +++--- .../rendering/renderableplanescloud.h | 13 +- .../rendering/renderablepoints.cpp | 40 ++- .../rendering/renderablepoints.h | 4 +- modules/fieldlines/fieldlinesmodule.h | 2 +- .../rendering/renderablefieldlines.cpp | 34 ++- .../rendering/renderablefieldlines.h | 2 +- modules/galaxy/galaxymodule.cpp | 2 +- modules/galaxy/rendering/galaxyraycaster.cpp | 38 ++- modules/galaxy/rendering/renderablegalaxy.cpp | 27 +- modules/galaxy/rendering/renderablegalaxy.h | 4 +- .../galaxy/tasks/milkywayconversiontask.cpp | 12 +- .../tasks/milkywaypointsconversiontask.h | 2 +- modules/globebrowsing/cache/lrucache.h | 4 +- modules/globebrowsing/cache/lrucache.inl | 2 +- .../cache/memoryawaretilecache.cpp | 12 +- .../cache/memoryawaretilecache.h | 2 +- .../globebrowsing/cache/texturecontainer.cpp | 7 +- .../globebrowsing/cache/texturecontainer.h | 4 +- modules/globebrowsing/chunk/chunk.cpp | 10 +- modules/globebrowsing/chunk/chunk.h | 4 +- .../availabletiledataevaluator.cpp | 4 +- .../chunklevelevaluator/chunklevelevaluator.h | 2 +- .../chunklevelevaluator/distanceevaluator.cpp | 8 +- .../projectedareaevaluator.cpp | 10 +- .../projectedareaevaluator.h | 2 +- modules/globebrowsing/chunk/chunknode.cpp | 2 +- .../chunk/culling/frustumculler.cpp | 4 +- .../chunk/culling/horizonculler.cpp | 8 +- modules/globebrowsing/geometry/angle.h | 2 +- modules/globebrowsing/geometry/ellipsoid.cpp | 7 +- modules/globebrowsing/geometry/ellipsoid.h | 4 +- modules/globebrowsing/geometry/geodetic2.h | 2 +- .../globebrowsing/geometry/geodeticpatch.cpp | 7 +- modules/globebrowsing/globebrowsingmodule.cpp | 43 ++-- modules/globebrowsing/globebrowsingmodule.h | 1 - .../globebrowsing/globebrowsingmodule_lua.inl | 15 +- .../globebrowsing/globes/chunkedlodglobe.cpp | 25 +- .../globebrowsing/globes/chunkedlodglobe.h | 10 +- modules/globebrowsing/globes/pointglobe.cpp | 20 +- modules/globebrowsing/globes/pointglobe.h | 2 +- .../globebrowsing/globes/renderableglobe.cpp | 14 +- .../globebrowsing/globes/renderableglobe.h | 8 +- modules/globebrowsing/meshes/grid.h | 10 +- modules/globebrowsing/meshes/trianglesoup.h | 2 +- .../globebrowsing/other/distanceswitch.cpp | 2 +- modules/globebrowsing/other/lruthreadpool.h | 2 +- modules/globebrowsing/other/lruthreadpool.inl | 2 +- modules/globebrowsing/other/pixelbuffer.h | 4 +- .../other/pixelbuffercontainer.h | 4 +- .../other/pixelbuffercontainer.inl | 4 +- .../other/prioritizingconcurrentjobmanager.h | 2 +- modules/globebrowsing/other/statscollector.h | 2 +- .../globebrowsing/rendering/chunkrenderer.cpp | 32 ++- .../globebrowsing/rendering/gpu/gpulayer.cpp | 4 +- .../globebrowsing/rendering/gpu/gpulayer.h | 2 +- .../rendering/gpu/gpulayergroup.cpp | 2 +- .../rendering/gpu/gpulayermanager.cpp | 2 +- .../rendering/gpu/gputiledepthtransform.h | 2 +- .../globebrowsing/rendering/layer/layer.cpp | 2 +- modules/globebrowsing/rendering/layer/layer.h | 8 +- .../rendering/layer/layeradjustment.cpp | 2 +- .../rendering/layer/layeradjustment.h | 2 +- .../rendering/layer/layermanager.cpp | 4 +- .../rendering/layer/layermanager.h | 2 +- .../rendering/layer/layerrendersettings.cpp | 2 +- .../rendering/layer/layerrendersettings.h | 2 +- .../rendering/layershadermanager.cpp | 8 +- .../rendering/layershadermanager.h | 7 +- .../tile/asynctiledataprovider.cpp | 10 +- .../tile/asynctiledataprovider.h | 4 +- modules/globebrowsing/tile/pixelregion.cpp | 4 +- modules/globebrowsing/tile/pixelregion.h | 6 +- modules/globebrowsing/tile/rawtile.h | 4 +- .../gdalrawtiledatareader.cpp | 6 +- .../rawtiledatareader/gdalrawtiledatareader.h | 4 +- .../tile/rawtiledatareader/gdalwrapper.cpp | 2 +- .../tile/rawtiledatareader/gdalwrapper.h | 4 +- .../tile/rawtiledatareader/iodescription.cpp | 2 +- .../tile/rawtiledatareader/iodescription.h | 4 +- .../rawtiledatareader/rawtiledatareader.cpp | 32 +-- .../rawtiledatareader/rawtiledatareader.h | 9 +- .../simplerawtiledatareader.cpp | 2 +- modules/globebrowsing/tile/tile.h | 2 +- modules/globebrowsing/tile/tileindex.cpp | 22 +- modules/globebrowsing/tile/tileindex.h | 6 +- modules/globebrowsing/tile/tileloadjob.h | 2 +- .../tile/tileprovider/defaulttileprovider.cpp | 4 +- .../tile/tileprovider/defaulttileprovider.h | 6 +- .../presentationslideprovider.cpp | 118 --------- .../tileprovider/projectiontileprovider.h | 20 +- .../tile/tileprovider/singleimageprovider.cpp | 4 +- .../sizereferencetileprovider.cpp | 2 +- .../tileprovider/sizereferencetileprovider.h | 2 +- .../tileprovider/temporaltileprovider.cpp | 16 +- .../tile/tileprovider/temporaltileprovider.h | 12 +- .../tile/tileprovider/texttileprovider.cpp | 8 +- .../tile/tileprovider/texttileprovider.h | 6 +- .../tile/tileprovider/tileindextileprovider.h | 4 +- .../tile/tileprovider/tileprovider.cpp | 8 +- .../tile/tileprovider/tileprovider.h | 7 +- .../tile/tileprovider/tileproviderbyindex.cpp | 18 +- .../tile/tileprovider/tileproviderbylevel.cpp | 12 +- modules/globebrowsing/tile/tileselector.cpp | 2 +- modules/globebrowsing/tile/tileselector.h | 2 +- modules/imgui/imguimodule.cpp | 24 +- modules/imgui/imguimodule.h | 2 +- modules/imgui/include/guicomponent.h | 2 +- modules/imgui/src/gui.cpp | 6 +- modules/imgui/src/guiiswacomponent.cpp | 4 +- modules/imgui/src/guimissioncomponent.cpp | 4 +- modules/imgui/src/guiperformancecomponent.cpp | 24 +- modules/imgui/src/guispacetimecomponent.cpp | 3 +- modules/imgui/src/guitimecomponent.cpp | 2 +- modules/imgui/src/renderproperties.cpp | 20 +- modules/iswa/iswamodule.cpp | 2 +- modules/iswa/iswamodule.h | 2 +- modules/iswa/rendering/datacygnet.cpp | 8 +- modules/iswa/rendering/dataplane.cpp | 2 +- modules/iswa/rendering/iswabasegroup.cpp | 2 +- modules/iswa/rendering/iswacygnet.cpp | 17 +- modules/iswa/rendering/iswacygnet.h | 2 +- modules/iswa/rendering/iswadatagroup.cpp | 2 +- modules/iswa/rendering/iswakameleongroup.cpp | 2 +- modules/iswa/rendering/iswakameleongroup.h | 2 +- modules/iswa/rendering/kameleonplane.cpp | 14 +- modules/iswa/rendering/kameleonplane.h | 2 +- modules/iswa/rendering/screenspacecygnet.cpp | 4 +- modules/iswa/rendering/textureplane.cpp | 2 +- modules/iswa/rendering/textureplane.h | 2 +- modules/iswa/util/dataprocessor.cpp | 10 +- modules/iswa/util/dataprocessorjson.cpp | 2 +- modules/iswa/util/dataprocessorjson.h | 2 +- modules/iswa/util/dataprocessorkameleon.cpp | 4 +- modules/iswa/util/dataprocessortext.cpp | 9 +- modules/iswa/util/iswamanager.cpp | 18 +- modules/iswa/util/iswamanager.h | 7 +- modules/iswa/util/iswamanager_lua.inl | 38 +-- modules/kameleon/include/kameleonwrapper.h | 4 +- modules/kameleon/src/kameleonwrapper.cpp | 92 ++++--- .../kameleonvolume/kameleonvolumereader.cpp | 2 +- .../rendering/renderablekameleonvolume.cpp | 24 +- .../rendering/renderablekameleonvolume.h | 2 +- .../tasks/kameleondocumentationtask.h | 2 +- .../tasks/kameleonmetadatatojsontask.h | 2 +- .../tasks/kameleonvolumetorawtask.cpp | 6 +- .../tasks/kameleonvolumetorawtask.h | 4 +- .../multiresvolume/rendering/atlasmanager.cpp | 11 +- .../rendering/errorhistogrammanager.cpp | 2 +- .../rendering/localtfbrickselector.h | 3 +- .../rendering/multiresvolumeraycaster.cpp | 34 +-- .../rendering/renderablemultiresvolume.cpp | 5 - .../rendering/renderablemultiresvolume.h | 4 +- .../rendering/simpletfbrickselector.cpp | 2 +- .../rendering/tfbrickselector.h | 3 +- .../rendering/renderableconstellationbounds.h | 4 +- modules/space/rendering/renderableplanet.cpp | 14 +- modules/space/rendering/renderableplanet.h | 6 +- modules/space/rendering/renderablerings.cpp | 15 +- modules/space/rendering/renderablestars.cpp | 14 +- modules/space/rotation/spicerotation.cpp | 4 +- modules/space/rotation/spicerotation.h | 6 +- .../space/translation/keplertranslation.cpp | 28 +-- modules/space/translation/keplertranslation.h | 22 +- .../space/translation/spicetranslation.cpp | 6 +- modules/space/translation/spicetranslation.h | 6 +- modules/space/translation/tletranslation.cpp | 117 +++++---- modules/space/translation/tletranslation.h | 6 +- .../rendering/renderablecrawlingline.cpp | 4 +- .../rendering/renderablecrawlingline.h | 2 +- .../rendering/renderablefov.cpp | 23 +- .../rendering/renderablefov.h | 6 +- .../rendering/renderablemodelprojection.cpp | 18 +- .../rendering/renderablemodelprojection.h | 2 +- .../rendering/renderableplaneprojection.cpp | 10 +- .../rendering/renderableplaneprojection.h | 4 +- .../rendering/renderableplanetprojection.cpp | 6 +- .../rendering/renderableplanetprojection.h | 2 +- .../rendering/renderableshadowcylinder.cpp | 8 +- .../rendering/renderableshadowcylinder.h | 2 +- .../spacecraftinstrumentsmodule.h | 2 +- .../spacecraftinstruments/util/decoder.cpp | 4 +- .../util/hongkangparser.cpp | 8 +- .../util/imagesequencer.cpp | 16 +- .../util/imagesequencer.h | 2 +- .../util/instrumentdecoder.cpp | 3 +- .../util/instrumentdecoder.h | 4 +- .../util/instrumenttimesparser.cpp | 12 +- .../util/labelparser.cpp | 8 +- .../spacecraftinstruments/util/labelparser.h | 2 +- .../util/projectioncomponent.cpp | 8 +- .../util/projectioncomponent.h | 2 +- .../util/scannerdecoder.cpp | 2 +- .../util/scannerdecoder.h | 4 +- .../util/targetdecoder.h | 4 +- modules/touch/include/touchinteraction.h | 2 +- modules/touch/include/touchmarker.h | 3 +- modules/touch/include/tuioear.h | 7 +- modules/touch/src/touchinteraction.cpp | 11 +- modules/touch/src/touchmarker.cpp | 4 +- modules/touch/src/tuioear.cpp | 2 +- modules/touch/touchmodule.cpp | 2 +- .../rendering/renderabletoyvolume.cpp | 12 +- .../toyvolume/rendering/renderabletoyvolume.h | 6 +- .../rendering/toyvolumeraycaster.cpp | 30 +-- modules/volume/linearlrucache.h | 2 +- modules/volume/lrucache.h | 3 +- modules/volume/rawvolumewriter.h | 4 +- modules/volume/rawvolumewriter.inl | 4 +- .../volume/rendering/basicvolumeraycaster.cpp | 44 ++-- .../rendering/renderabletimevaryingvolume.cpp | 13 +- .../rendering/renderabletimevaryingvolume.h | 2 +- modules/volume/textureslicevolumereader.inl | 8 +- modules/volume/volumesampler.inl | 6 +- modules/volume/volumeutils.cpp | 12 +- src/documentation/core_registration.cpp | 2 +- src/documentation/documentation.cpp | 4 +- src/documentation/documentationgenerator.cpp | 18 +- src/engine/configurationmanager.cpp | 20 +- src/engine/downloadmanager.cpp | 42 ++-- src/engine/logfactory.cpp | 2 +- src/engine/moduleengine.cpp | 4 +- src/engine/moduleengine_lua.inl | 2 +- src/engine/openspaceengine.cpp | 89 ++++--- src/engine/openspaceengine_lua.inl | 2 +- src/engine/wrapper/sgctwindowwrapper.cpp | 8 +- src/engine/wrapper/windowwrapper.cpp | 9 +- src/interaction/keybindingmanager.cpp | 4 +- src/interaction/keybindingmanager_lua.inl | 2 +- src/interaction/keyframenavigator.cpp | 2 +- src/interaction/luaconsole.cpp | 9 +- src/interaction/mousestate.cpp | 2 +- src/interaction/navigationhandler.cpp | 6 +- src/mission/mission.cpp | 4 +- src/network/networkengine.cpp | 4 +- src/network/parallelconnection.cpp | 175 +++++++------ src/openspace.cpp | 2 +- src/performance/performancemanager.cpp | 51 ++-- src/properties/optionproperty.cpp | 2 +- src/properties/propertyowner.cpp | 30 +-- src/query/query.cpp | 2 +- src/rendering/abufferrenderer.cpp | 10 +- src/rendering/framebufferrenderer.cpp | 6 +- src/rendering/renderengine.cpp | 29 +-- src/rendering/renderengine_lua.inl | 8 +- src/rendering/screenspacerenderable.cpp | 14 +- src/scene/rotation.cpp | 6 +- src/scene/scene.cpp | 19 +- src/scene/scene_lua.inl | 25 +- src/scene/scenegraphnode.cpp | 8 +- src/scene/scenelicense.cpp | 4 +- src/scene/scenelicensewriter.cpp | 5 +- src/scene/sceneloader.cpp | 16 +- src/scene/translation.cpp | 2 +- src/scripting/scriptengine.cpp | 34 +-- src/scripting/scriptscheduler.cpp | 26 +- src/scripting/scriptscheduler_lua.inl | 2 +- src/scripting/systemcapabilitiesbinding.cpp | 53 ++-- src/util/blockplaneintersectiongeometry.cpp | 7 +- src/util/boxgeometry.cpp | 8 +- src/util/camera.cpp | 6 +- src/util/factorymanager.cpp | 4 +- src/util/histogram.cpp | 4 +- src/util/keys.cpp | 8 +- src/util/openspacemodule.cpp | 6 +- src/util/powerscaledsphere.cpp | 4 +- src/util/screenlog.cpp | 6 +- src/util/spicemanager.cpp | 235 ++++++++---------- src/util/task.cpp | 2 +- src/util/threadpool.cpp | 4 +- src/util/time.cpp | 2 +- src/util/timemanager.cpp | 6 +- src/util/timerange.cpp | 2 +- support/coding/check_style_guide.py | 35 ++- 387 files changed, 1907 insertions(+), 2132 deletions(-) delete mode 100644 modules/globebrowsing/tile/tileprovider/presentationslideprovider.cpp diff --git a/apps/Launcher/mainwindow.cpp b/apps/Launcher/mainwindow.cpp index 46d6ea595b..59e50a1547 100644 --- a/apps/Launcher/mainwindow.cpp +++ b/apps/Launcher/mainwindow.cpp @@ -84,10 +84,10 @@ MainWindow::MainWindow() setObjectName("MainWindow"); setFixedSize(WindowSize); //setContentsMargins(0, 0, 0, 0); - + QGridLayout* layout = new QGridLayout; layout->setContentsMargins(0, 0, 0, 0); - + QLabel* image = new QLabel; //image->setContentsMargins(0, 0, 0, 0); image->setObjectName("Image"); @@ -95,7 +95,6 @@ MainWindow::MainWindow() image->setPixmap(p); layout->addWidget(image, 0, 0, 1, 2); - _informationWidget = new QTextEdit(this); _informationWidget->setReadOnly(true); //_informationWidget->setEnabled(false); @@ -107,7 +106,7 @@ MainWindow::MainWindow() QWidget* container = new QWidget; { QGridLayout* innerLayout = new QGridLayout; - + //QLabel* shortcutLabel = new QLabel("Keyboard Shortcuts:"); //innerLayout->addWidget(shortcutLabel, 0, 0); //QPushButton* shortcutButton = new QPushButton("Open..."); @@ -122,47 +121,47 @@ MainWindow::MainWindow() innerLayout->addWidget(configurationSelectionLabel, 2, 0); _configurations = new QComboBox; innerLayout->addWidget(_configurations, 2, 1); - + QLabel* sceneSelectionLabel = new QLabel("Scenes:"); innerLayout->addWidget(sceneSelectionLabel, 3, 0); _scenes = new QComboBox; innerLayout->addWidget(_scenes, 3, 1); - + container->setLayout(innerLayout); } layout->addWidget(container, 1, 1); - + container = new QWidget; { QBoxLayout* innerLayout = new QHBoxLayout; - + QPushButton* cancelButton = new QPushButton("Exit"); QObject::connect( cancelButton, SIGNAL(clicked(bool)), QApplication::instance(), SLOT(quit()) ); innerLayout->addWidget(cancelButton); - + QPushButton* syncButton = new QPushButton("Sync"); QObject::connect( syncButton, SIGNAL(clicked(bool)), this, SLOT(syncButtonPressed()) ); innerLayout->addWidget(syncButton); - + QPushButton* startButton = new QPushButton("Start"); QObject::connect( startButton, SIGNAL(clicked(bool)), this, SLOT(startButtonPressed()) ); innerLayout->addWidget(startButton); - + container->setLayout(innerLayout); } layout->addWidget(container, 2, 1); - + setLayout(layout); - + initialize(); } @@ -244,7 +243,7 @@ void MainWindow::initialize() { // Get the news information QNetworkRequest request; request.setUrl(QUrl(NewsURL)); - + _newsReply = _networkManager.get(request); QObject::connect(_newsReply, SIGNAL(finished()), this, SLOT(newsReadyRead()) diff --git a/apps/Launcher/mainwindow.h b/apps/Launcher/mainwindow.h index 9c1e56449c..54436e09b0 100644 --- a/apps/Launcher/mainwindow.h +++ b/apps/Launcher/mainwindow.h @@ -53,7 +53,7 @@ private slots: void shortcutButtonPressed(); void syncButtonPressed(); void startButtonPressed(); - + void newsNetworkError(); void newsReadyRead(); @@ -64,7 +64,7 @@ private: void configureLogging(); QNetworkReply* _newsReply; - + QTextEdit* _informationWidget; QComboBox* _configurations; @@ -72,7 +72,7 @@ private: QComboBox* _scenes; QMap _sceneFiles; - + ShortcutWidget* _shortcutWidget; SyncWidget* _syncWidget; diff --git a/apps/Launcher/syncwidget.cpp b/apps/Launcher/syncwidget.cpp index b02351e3e8..df65188357 100644 --- a/apps/Launcher/syncwidget.cpp +++ b/apps/Launcher/syncwidget.cpp @@ -281,7 +281,7 @@ void SyncWidget::handleDirectFiles() { void SyncWidget::handleFileRequest() { LDEBUG("File Requests"); - + for (const FileRequest& f : _fileRequests) { LDEBUG(f.identifier.toStdString() << " (" << f.version << ") -> " << f.destination.toStdString()); @@ -405,18 +405,18 @@ void SyncWidget::syncButtonPressed() { for (int i = 1; i <= modules.size(); ++i) { std::string module = modules.value(std::to_string(i)); std::string shortModule = module; - + std::string::size_type pos = module.find_last_of(FileSys.PathSeparator); if (pos != std::string::npos) { shortModule = module.substr(pos+1); } - + QString m = QString::fromStdString(module); - + QString dataFile = sceneDir.absoluteFilePath( QString::fromStdString(module) + "/" + QString::fromStdString(shortModule) + ".data" ); - + if (QFileInfo(dataFile).exists()) { modulesList.append({ QString::fromStdString(module), @@ -427,13 +427,13 @@ void SyncWidget::syncButtonPressed() { else { QDir metaModuleDir = sceneDir; metaModuleDir.cd(QString::fromStdString(module)); - + QDirIterator it(metaModuleDir.absolutePath(), QStringList() << "*.data", QDir::Files, QDirIterator::Subdirectories); while (it.hasNext()) { QString v = it.next(); QDir d(v); d.cdUp(); - + modulesList.append({ d.dirName(), v, @@ -533,7 +533,7 @@ void SyncWidget::syncButtonPressed() { continue; } std::string file = d.value(FileKey); - + std::string dest; if (d.hasKeyAndValue(DestinationKey)) dest = d.value(DestinationKey); diff --git a/apps/Launcher/syncwidget.h b/apps/Launcher/syncwidget.h index 028c15e326..ec7eb88adb 100644 --- a/apps/Launcher/syncwidget.h +++ b/apps/Launcher/syncwidget.h @@ -52,7 +52,7 @@ Q_OBJECT public: SyncWidget(QWidget* parent, Qt::WindowFlags f = 0); ~SyncWidget(); - + void setSceneFiles(QMap sceneFiles); private slots: diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 3bc0f706c2..d5dc91c1b4 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -66,7 +66,7 @@ #define DEVELOPER_MODE namespace { - + const char* _loggerCat = "main"; sgct::Engine* SgctEngine; @@ -79,7 +79,6 @@ LONG WINAPI generateMiniDump(EXCEPTION_POINTERS* exceptionPointers) { SYSTEMTIME stLocalTime; GetLocalTime(&stLocalTime); - LFATAL("Printing Stack Trace that lead to the crash:"); std::vector stackTrace = ghoul::stackTrace(); for (const std::string& s : stackTrace) { @@ -139,7 +138,7 @@ LONG WINAPI generateMiniDump(EXCEPTION_POINTERS* exceptionPointers) { } #endif // WIN32 - + #ifdef OPENVR_SUPPORT sgct::SGCTWindow* FirstOpenVRWindow = nullptr; #endif @@ -172,7 +171,6 @@ std::vector SpoutWindows; #endif // OPENSPACE_HAS_SPOUT - std::pair supportedOpenGLVersion() { // Just create a window in order to retrieve the available OpenGL version before we // create the real window @@ -188,9 +186,9 @@ std::pair supportedOpenGLVersion() { glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #endif - + glfwWindowHint(GLFW_VISIBLE, GL_FALSE); - + // By creating an offscreen window, the user will not know that we created this window GLFWwindow* offscreen = glfwCreateWindow(128, 128, "", nullptr, nullptr); glfwMakeContextCurrent(offscreen); @@ -203,7 +201,7 @@ std::pair supportedOpenGLVersion() { // And get rid of the window again glfwDestroyWindow(offscreen); glfwWindowHint(GLFW_VISIBLE, GL_TRUE); - + return { major, minor }; } @@ -217,14 +215,14 @@ void mainInitFunc() { LDEBUG("Initializing OpenGL in OpenSpace Engine started"); OsEng.initializeGL(); LDEBUG("Initializing OpenGL in OpenSpace Engine finished"); - + // Find if we have at least one OpenVR window // Save reference to first OpenVR window, which is the one we will copy to the HMD. for (size_t i = 0; i < SgctEngine->getNumberOfWindows(); ++i) { if (SgctEngine->getWindowPtr(i)->checkIfTagExists(OpenVRTag)) { #ifdef OPENVR_SUPPORT FirstOpenVRWindow = SgctEngine->getWindowPtr(i); - + // If we have an OpenVRWindow, initialize OpenVR. sgct::SGCTOpenVR::initialize( SgctEngine->getNearClippingPlane(), SgctEngine->getFarClippingPlane() @@ -305,7 +303,7 @@ void mainInitFunc() { LWARNING( "Spout was requested, but OpenSpace was compiled without Spout support." ); - + #endif // OPENSPACE_HAS_SPOUT } LTRACE("main::mainInitFunc(end)"); @@ -480,7 +478,7 @@ void mainLogCallback(const char* msg) { int main_main(int argc, char** argv) { std::pair glVersion = supportedOpenGLVersion(); - + // Create the OpenSpace engine and get arguments for the SGCT engine // @CLEANUP: Replace the return valua with throwing an exception --abock std::vector sgctArguments; @@ -491,37 +489,37 @@ int main_main(int argc, char** argv) { sgctArguments, requestQuit ); - + if (requestQuit) { return EXIT_SUCCESS; } - + LINFO("Detected OpenGL version: " << glVersion.first << "." << glVersion.second); - + // Create sgct engine c arguments int newArgc = static_cast(sgctArguments.size()); - + char** newArgv = new char*[newArgc]; for (int i = 0; i < newArgc; ++i) { newArgv[i] = const_cast(sgctArguments.at(i).c_str()); } - + // Need to set this before the creation of the sgct::Engine sgct::MessageHandler::instance()->setLogToConsole(false); sgct::MessageHandler::instance()->setShowTime(false); sgct::MessageHandler::instance()->setLogToCallback(true); sgct::MessageHandler::instance()->setLogCallback(mainLogCallback); - + #ifdef __APPLE__ glfwWindowHint(GLFW_STENCIL_BITS, 8); #endif - + LDEBUG("Creating SGCT Engine"); SgctEngine = new sgct::Engine(newArgc, newArgv); - + // Deallocate sgct c arguments delete[] newArgv; - + // Bind functions SgctEngine->setInitOGLFunction(mainInitFunc); SgctEngine->setPreSyncFunction(mainPreSyncFunc); @@ -534,17 +532,17 @@ int main_main(int argc, char** argv) { SgctEngine->setMouseScrollCallbackFunction(mainMouseScrollCallback); SgctEngine->setExternalControlCallback(mainExternalControlCallback); SgctEngine->setCharCallbackFunction(mainCharCallback); - + // Disable the immediate exit of the application when the ESC key is pressed SgctEngine->setExitKey(SGCT_KEY_UNKNOWN); - + sgct::MessageHandler::instance()->setNotifyLevel(sgct::MessageHandler::NOTIFY_ALL); - + // Set encode and decode functions // NOTE: starts synchronizing before init functions sgct::SharedData::instance()->setEncodeFunction(mainEncodeFun); sgct::SharedData::instance()->setDecodeFunction(mainDecodeFun); - + // Try to open a window LDEBUG("Initialize SGCT Engine"); std::map, sgct::Engine::RunMode> versionMapping = { @@ -561,17 +559,17 @@ int main_main(int argc, char** argv) { versionMapping.find(glVersion) != versionMapping.end(), "Unknown OpenGL version. Missing statement in version mapping map" ); - + auto cleanup = [&](){ OsEng.deinitialize(); - + // Clear function bindings to avoid crash after destroying the OpenSpace Engine sgct::MessageHandler::instance()->setLogToCallback(false); sgct::MessageHandler::instance()->setLogCallback(nullptr); - + LDEBUG("Destroying OpenSpaceEngine"); openspace::OpenSpaceEngine::destroy(); - + LDEBUG("Destroying SGCT Engine"); delete SgctEngine; @@ -594,26 +592,26 @@ int main_main(int argc, char** argv) { } #endif // OPENSPACE_HAS_SPOUT }; - + bool initSuccess = SgctEngine->init(versionMapping[glVersion]); - + if (!initSuccess) { LFATAL("Initializing failed"); cleanup(); return EXIT_FAILURE; } - + // Main loop LDEBUG("Starting rendering loop"); SgctEngine->render(); LDEBUG("Ending rendering loop"); - + cleanup(); - + // Exit program exit(EXIT_SUCCESS); } - + } // namespace int main(int argc, char** argv) { diff --git a/apps/TimelineView/controlwidget.cpp b/apps/TimelineView/controlwidget.cpp index 010e00a9cd..a4f501d830 100644 --- a/apps/TimelineView/controlwidget.cpp +++ b/apps/TimelineView/controlwidget.cpp @@ -177,7 +177,6 @@ ControlWidget::ControlWidget(QWidget* parent) _setDelta->setObjectName("background"); layout->addWidget(_setDelta, 4, 0, 1, 2); - QWidget* controlContainer = new QWidget; controlContainer->setObjectName("background"); diff --git a/apps/TimelineView/mainwindow.cpp b/apps/TimelineView/mainwindow.cpp index 088f4f3a95..b227633515 100644 --- a/apps/TimelineView/mainwindow.cpp +++ b/apps/TimelineView/mainwindow.cpp @@ -228,7 +228,7 @@ void MainWindow::readTcpData() { fullyConnected(); continuousData.clear(); break; - + default: qDebug() << QString(data); } @@ -309,7 +309,7 @@ QByteArray MainWindow::handlePlaybook(QByteArray data) { image.beginningString = readFromBuffer(buffer, currentReadLocation); image.endingString = readFromBuffer(buffer, currentReadLocation); - + uint8_t targetId = readFromBuffer(buffer, currentReadLocation); uint16_t instrumentId = readFromBuffer(buffer, currentReadLocation); image.target = targetMap[targetId]; diff --git a/apps/TimelineView/mainwindow.h b/apps/TimelineView/mainwindow.h index 5bb3774885..70a0f06cc4 100644 --- a/apps/TimelineView/mainwindow.h +++ b/apps/TimelineView/mainwindow.h @@ -65,7 +65,7 @@ private: ControlWidget* _timeControlWidget; InformationWidget* _informationWidget; TimelineWidget* _timelineWidget; - + QTcpSocket* _socket; bool _isConnected = false; diff --git a/apps/TimelineView/timelinewidget.cpp b/apps/TimelineView/timelinewidget.cpp index 1003a82d24..b4014b12bf 100644 --- a/apps/TimelineView/timelinewidget.cpp +++ b/apps/TimelineView/timelinewidget.cpp @@ -35,7 +35,7 @@ namespace { static const int LegendHeight = 105; static const int TimeWidth = 200; - + static const int TextOffset = 5; QMap InstrumentColors = { @@ -127,7 +127,7 @@ void TimelineWidget::setData(std::vector images, std::map namespace openspace { - + /* * This abstract class is used for instances when another class has the ability to * generate a Handlebar generated documentation file that contains valuable information @@ -51,7 +51,7 @@ public: std::string name; ///< The name of the Handlebar template defined in \m filename std::string filename; ///< The filename referenced in the \m name }; - + /** * The constructor that is used to set the member variables later used in the * writeDocumentation method. @@ -72,7 +72,7 @@ public: /// Default constructor virtual ~DocumentationGenerator() = default; - + /** * Create the documentation into the provided filename. Any existing file will be * silently overwritten. This method will call the generateJson method that can be @@ -81,7 +81,7 @@ public: * \param filename The filename in which the documentation is written */ void writeDocumentation(const std::string& filename); - + protected: /** * This abstract method is used by concrete subclasses to provide the actual data that @@ -92,14 +92,13 @@ protected: * DocumentationGenerator constructor */ virtual std::string generateJson() const = 0; - + private: const std::string _name; const std::string _jsonName; const std::vector _handlebarTemplates; const std::string _javascriptFile; }; - /** * This function takes a \p text and escapes all necessary characters () that JSON diff --git a/include/openspace/engine/configurationmanager.h b/include/openspace/engine/configurationmanager.h index 69a83bb6a8..d13734aee8 100644 --- a/include/openspace/engine/configurationmanager.h +++ b/include/openspace/engine/configurationmanager.h @@ -168,7 +168,7 @@ public: * \throw ghoul::RuntimeError If the configuration could not be found */ static std::string findConfiguration(const std::string& filename); - + /** * Load the provided configuration file (\p filename) into this Dictionary. All paths * that are specified in the configuration file will automatically be registered in diff --git a/include/openspace/engine/moduleengine.h b/include/openspace/engine/moduleengine.h index f7c18d2b16..22b15f142f 100644 --- a/include/openspace/engine/moduleengine.h +++ b/include/openspace/engine/moduleengine.h @@ -57,7 +57,7 @@ public: * name */ void initialize(); - + /** * Deinitializes all of the contained OpenSpaceModule%s by calling the * OpenSpaceModule::deinitialize methods. @@ -73,14 +73,14 @@ public: * \pre \p module must not be nullptr */ void registerModule(std::unique_ptr module); - + /** * Returns a list of all registered OpenSpaceModule%s that have been registered with * this ModuleEngine. All returned OpenSpaceModule%s are guaranteed to be initialized. * \return A list of all registered OpenSpaceModule%s */ std::vector modules() const; - + /** * Get the module subclass with given template argument. Requires the module subclass * to have the public static member variable name which must be equal to diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 28bb568b37..8aa395f08e 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -98,10 +98,10 @@ public: void decode(); void scheduleLoadScene(std::string scenePath); - + void writeDocumentation(); void toggleShutdownMode(); - + void runPostInitializationScripts(const std::string& sceneDescription); // Guaranteed to return a valid pointer @@ -123,7 +123,7 @@ public: scripting::ScriptScheduler& scriptScheduler(); VirtualPropertyManager& virtualPropertyManager(); - + // This method is only to be called from Modules enum class CallbackOption { Initialize = 0, // Callback for the end of the initialization @@ -135,14 +135,14 @@ public: Render, // Callback for the end of the render function PostDraw // Callback for the end of the post-draw function }; - + // Registers a callback for a specific CallbackOption void registerModuleCallback(CallbackOption option, std::function function); - + // Registers a callback that is called when a new keyboard event is received void registerModuleKeyboardCallback( std::function function); - + // Registers a callback that is called when a new character event is received void registerModuleCharCallback( std::function function); @@ -150,16 +150,16 @@ public: // Registers a callback that is called when a new mouse button is received void registerModuleMouseButtonCallback( std::function function); - + // Registers a callback that is called when a new mouse movement is received void registerModuleMousePositionCallback( std::function function); - + // Registers a callback that is called when a scroll wheel change is received void registerModuleMouseScrollWheelCallback( std::function function ); - + /** * Returns the Lua library that contains all Lua functions available to affect the * application. @@ -175,7 +175,7 @@ private: void loadFonts(); void runPreInitializationScripts(const std::string& sceneDescription); void configureLogging(); - + // Components std::unique_ptr _configurationManager; std::unique_ptr _sceneManager; @@ -204,30 +204,30 @@ private: properties::StringProperty versionString; properties::StringProperty sourceControlInformation; } _versionInformation; - + bool _scheduledSceneSwitch; std::string _scenePath; struct { std::vector> initialize; std::vector> deinitialize; - + std::vector> initializeGL; std::vector> deinitializeGL; - + std::vector> preSync; std::vector> postSyncPreDraw; std::vector> render; std::vector> postDraw; - + std::vector> keyboard; std::vector> character; - + std::vector> mouseButton; std::vector> mousePosition; std::vector> mouseScrollWheel; } _moduleCallbacks; - + // Structure that is responsible for the delayed shutdown of the application struct { // Whether the application is currently in shutdown mode (i.e. counting down the diff --git a/include/openspace/engine/settingsengine.h b/include/openspace/engine/settingsengine.h index 4c90b10832..e5bd295995 100644 --- a/include/openspace/engine/settingsengine.h +++ b/include/openspace/engine/settingsengine.h @@ -34,7 +34,7 @@ #include namespace openspace { - + class OpenSpaceModule; class SettingsEngine : public properties::PropertyOwner { @@ -42,7 +42,7 @@ public: SettingsEngine(); void initialize(); - + void setModules(const std::vector& modules); private: diff --git a/include/openspace/engine/syncengine.h b/include/openspace/engine/syncengine.h index 8d2c92711e..a23dc78c22 100644 --- a/include/openspace/engine/syncengine.h +++ b/include/openspace/engine/syncengine.h @@ -71,7 +71,7 @@ public: * Invokes the postsync method of all added Syncables */ void postSynchronization(IsMaster isMaster); - + /** * Add a Syncable to be synchronized over the SGCT cluster. * \pre syncable must not be nullptr diff --git a/include/openspace/engine/wrapper/sgctwindowwrapper.h b/include/openspace/engine/wrapper/sgctwindowwrapper.h index d106ce400d..8f7d5d8107 100644 --- a/include/openspace/engine/wrapper/sgctwindowwrapper.h +++ b/include/openspace/engine/wrapper/sgctwindowwrapper.h @@ -64,14 +64,14 @@ public: bool isMaster() const override; bool isUsingSwapGroups() const override; bool isSwapGroupMaster() const override; - + glm::mat4 viewProjectionMatrix() const override; glm::mat4 modelMatrix() const override; void setNearFarClippingPlane(float near, float far) override; void setEyeSeparationDistance(float distance) override; - + glm::ivec4 viewportPixelCoordinates() const override; - + bool isExternalControlConnected() const override; void sendMessageToExternalControl(const std::vector& message) const override; diff --git a/include/openspace/engine/wrapper/windowwrapper.h b/include/openspace/engine/wrapper/windowwrapper.h index 23713c50de..2498addbfd 100644 --- a/include/openspace/engine/wrapper/windowwrapper.h +++ b/include/openspace/engine/wrapper/windowwrapper.h @@ -76,7 +76,7 @@ public: * disables it */ virtual void setSynchronization(bool enabled); - + /** * This method clears all the rendering windows with the specified \p clearColor. In * most OpenGL cases, this will end up with one or mode glClear calls. @@ -84,7 +84,7 @@ public: * \param clearColor The color with which to clear all windows */ virtual void clearAllWindows(const glm::vec4& clearColor); - + /** * Returns whether the current window has been resized recently. On default, this * method always returns false. @@ -119,7 +119,7 @@ public: * \return The location of the mouse cursor in pixel screen coordinates */ virtual glm::vec2 mousePosition() const; - + /** * Returns a bitmask of the status of all available mouse buttons. Bit i * is 1 if mouse button i is pressed down; @@ -129,28 +129,28 @@ public: * \return A bitmask showing the status of all mouse buttons (up to \p maxNumber) */ virtual uint32_t mouseButtons(int maxNumber = 8) const; - + /** * Returns the size of the currently active window in pixel coordinates. On default, * this method returns a window size of 0,0. * \return The size of the currently active window in pixel coordinates */ virtual glm::ivec2 currentWindowSize() const; - + /** * Returns the resolution of the currently active window in pixel coordinates. On * default, this method returns the same size as #currentWindowSize. * \return The resolution of the currently active window in pixel coordinates */ virtual glm::ivec2 currentWindowResolution() const; - + /** * Returns the resolution of the currently active framebuffer in pixel coordinates. * On default, this method returns the same size as #currentWindowSize. * \return The resolution of the currently active window in pixel coordinates */ virtual glm::ivec2 currentDrawBufferResolution() const; - + /** * Returns the DPI scaling factor for the current window. This is normally 1 on all * regular monitors and 2 on Retina screens. @@ -187,7 +187,7 @@ public: * \return Whether the current rendering window is GUI-only */ virtual bool isGuiWindow() const; - + /** * Returns true if this application is the master for a clustered * environment. @@ -218,7 +218,7 @@ public: * \return The currently employed model matrix */ virtual glm::mat4 modelMatrix() const; - + /** * Sets the near and far clipping planes of the rendering window. This method defaults * to a no-op. @@ -226,7 +226,7 @@ public: * \param far The far clipping plane */ virtual void setNearFarClippingPlane(float near, float far); - + /** * Sets the stereo eye separation distance for the render engine. * \param distance The distance between eyes for stereo rendering. @@ -241,7 +241,7 @@ public: * \return The location and size of the current viewport */ virtual glm::ivec4 viewportPixelCoordinates() const; - + /** * Returns true if there is an external control connected, i.e., an * application that can receive control commands. On default, this method will return @@ -249,13 +249,13 @@ public: * \return If there is an external control connected */ virtual bool isExternalControlConnected() const; - + /** * Sends a \p message to an external control. This method defaults to a no-op. * \param message The message to be sent */ virtual void sendMessageToExternalControl(const std::vector& message) const; - + /** * Returns true if the rendering is a single viewport with an single * window; false otherwise. On default, this method returns diff --git a/include/openspace/interaction/controller.h b/include/openspace/interaction/controller.h index 41076f09b1..6c837d4315 100644 --- a/include/openspace/interaction/controller.h +++ b/include/openspace/interaction/controller.h @@ -39,7 +39,7 @@ public: Controller() : _handler(nullptr) {} - + void setHandler(NavigationHandler* handler); protected: diff --git a/include/openspace/interaction/interpolator.h b/include/openspace/interaction/interpolator.h index 625b9f2b0d..810b0650ed 100644 --- a/include/openspace/interaction/interpolator.h +++ b/include/openspace/interaction/interpolator.h @@ -44,7 +44,7 @@ public: void setTransferFunction(std::function transferFunction); void setInterpolationTime(float interpolationTime); void step(); - + float deltaTimeScaled() const; T value() const; bool isInterpolating() const; diff --git a/include/openspace/interaction/keybindingmanager.h b/include/openspace/interaction/keybindingmanager.h index 8d66788195..8682fecc6a 100644 --- a/include/openspace/interaction/keybindingmanager.h +++ b/include/openspace/interaction/keybindingmanager.h @@ -42,7 +42,7 @@ class KeyBindingManager : public DocumentationGenerator { public: KeyBindingManager(); ~KeyBindingManager() = default; - + void resetKeyBindings(); void bindKeyLocal( @@ -72,7 +72,7 @@ private: Synchronized synchronization; std::string documentation; }; - + std::string generateJson() const override; std::multimap _keyLua; diff --git a/include/openspace/interaction/mousestate.h b/include/openspace/interaction/mousestate.h index 40b619f036..7db9a94d53 100644 --- a/include/openspace/interaction/mousestate.h +++ b/include/openspace/interaction/mousestate.h @@ -36,7 +36,7 @@ struct MouseState { MouseState(double scaleFactor); void setFriction(double friction); void setVelocityScaleFactor(double scaleFactor); - + glm::dvec2 previousPosition; DelayedVariable velocity; }; diff --git a/include/openspace/interaction/navigationhandler.h b/include/openspace/interaction/navigationhandler.h index 03aad77069..6e8d4fad76 100644 --- a/include/openspace/interaction/navigationhandler.h +++ b/include/openspace/interaction/navigationhandler.h @@ -58,7 +58,7 @@ public: void resetCameraDirection(); void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict); - + void updateCamera(double deltaTime); // Accessors diff --git a/include/openspace/interaction/orbitalnavigator.h b/include/openspace/interaction/orbitalnavigator.h index 7faf0b77b4..8a99f752e6 100644 --- a/include/openspace/interaction/orbitalnavigator.h +++ b/include/openspace/interaction/orbitalnavigator.h @@ -89,7 +89,7 @@ private: SceneGraphNode* _focusNode = nullptr; glm::dvec3 _previousFocusNodePosition; glm::dquat _previousFocusNodeRotation; - + Interpolator _rotateToFocusNodeInterpolator; Interpolator _followRotationInterpolator; @@ -117,14 +117,14 @@ private: */ glm::dquat rotateLocally(double deltaTime, const glm::dquat& localCameraRotation) const; - + /** * Interpolates the local rotation towards a 0 rotation. * \returns a modified local rotation interpolated towards 0. */ glm::dquat interpolateLocalRotation(double deltaTime, const glm::dquat& localCameraRotation); - + /** * Translates the horizontal direction. If far from the focus object, this will * result in an orbital rotation around the object. This function does not affect the diff --git a/include/openspace/mission/mission.h b/include/openspace/mission/mission.h index 03e19d1ff6..a7036bfb44 100644 --- a/include/openspace/mission/mission.h +++ b/include/openspace/mission/mission.h @@ -114,7 +114,7 @@ protected: * \pre maxDepth must not be negative */ void phaseTrace(double time, Trace& trace, int maxDepth) const; - + /// The name of the MissionPhase std::string _name; /// The description of the MissionPhase diff --git a/include/openspace/network/messagestructures.h b/include/openspace/network/messagestructures.h index e200630526..eb3c9eea09 100644 --- a/include/openspace/network/messagestructures.h +++ b/include/openspace/network/messagestructures.h @@ -51,14 +51,14 @@ struct CameraKeyframe { std::string _focusNode; double _timestamp; - + void serialize(std::vector &buffer){ // Add position buffer.insert(buffer.end(), reinterpret_cast(&_position), reinterpret_cast(&_position) + sizeof(_position)); - + // Add orientation buffer.insert(buffer.end(), reinterpret_cast(&_rotation), reinterpret_cast(&_rotation) + sizeof(_rotation)); - + // Follow focus node rotation? buffer.insert(buffer.end(), reinterpret_cast(&_followNodeRotation), reinterpret_cast(&_followNodeRotation) + sizeof(_followNodeRotation)); @@ -71,11 +71,11 @@ struct CameraKeyframe { // Add timestamp buffer.insert(buffer.end(), reinterpret_cast(&_timestamp), reinterpret_cast(&_timestamp) + sizeof(_timestamp)); }; - + void deserialize(const std::vector &buffer){ int offset = 0; int size = 0; - + // Position size = sizeof(_position); memcpy(&_position, buffer.data() + offset, size); @@ -99,13 +99,13 @@ struct CameraKeyframe { size = nodeNameLength; _focusNode = std::string(buffer.data() + offset, buffer.data() + offset + size); offset += size; - + // Timestamp size = sizeof(_timestamp); memcpy(&_timestamp, buffer.data() + offset, size); }; }; - + struct TimeKeyframe { TimeKeyframe() {} TimeKeyframe(const std::vector &buffer) { @@ -117,43 +117,43 @@ struct TimeKeyframe { bool _paused; bool _requiresTimeJump; double _timestamp; - + void serialize(std::vector &buffer){ // Add current time buffer.insert(buffer.end(), reinterpret_cast(&_time), reinterpret_cast(&_time) + sizeof(_time)); - + // Add delta time buffer.insert(buffer.end(), reinterpret_cast(&_dt), reinterpret_cast(&_dt) + sizeof(_dt)); - + // Add whether time is paused or not buffer.insert(buffer.end(), reinterpret_cast(&_paused), reinterpret_cast(&_paused) + sizeof(_paused)); - + // Add whether a time jump is necessary (recompute paths etc) buffer.insert(buffer.end(), reinterpret_cast(&_requiresTimeJump), reinterpret_cast(&_requiresTimeJump) + sizeof(_requiresTimeJump)); // Add timestamp buffer.insert(buffer.end(), reinterpret_cast(&_timestamp), reinterpret_cast(&_timestamp) + sizeof(_timestamp)); }; - + void deserialize(const std::vector &buffer){ int offset = 0; int size = 0; - + // Current time size = sizeof(_time); memcpy(&_time, buffer.data() + offset, size); offset += size; - + // Delta time size = sizeof(_dt); memcpy(&_dt, buffer.data() + offset, size); offset += size; - + // Is time paused? size = sizeof(_paused); memcpy(&_paused, buffer.data() + offset, size); offset += sizeof(_paused); - + // Is a time jump required? size = sizeof(_requiresTimeJump); memcpy(&_requiresTimeJump, buffer.data() + offset, size); @@ -165,7 +165,7 @@ struct TimeKeyframe { offset += size; }; }; - + struct ScriptMessage { ScriptMessage() {} ScriptMessage(const std::vector &buffer) { @@ -173,16 +173,16 @@ struct ScriptMessage { } std::string _script; - + void serialize(std::vector &buffer){ buffer.insert(buffer.end(), _script.begin(), _script.end()); }; - + void deserialize(const std::vector &buffer){ _script.assign(buffer.begin(), buffer.end()); }; }; - + } // namespace openspace::messagestructures #endif // __OPENSPACE_CORE___MESSAGESTRUCTURES___H__ diff --git a/include/openspace/network/parallelconnection.h b/include/openspace/network/parallelconnection.h index 14b58f9579..47cd5a7663 100644 --- a/include/openspace/network/parallelconnection.h +++ b/include/openspace/network/parallelconnection.h @@ -125,8 +125,7 @@ class ParallelConnection : public properties::PropertyOwner { int nConnections(); std::shared_ptr> connectionEvent(); - - + private: //@TODO change this into the ghoul hasher for client AND server uint32_t hash(const std::string &val); @@ -171,7 +170,7 @@ private: double _lastTimeKeyframeTimestamp; double _lastCameraKeyframeTimestamp; - + _SOCKET _clientSocket; std::atomic _isConnected; @@ -186,14 +185,14 @@ private: std::condition_variable _disconnectCondition; std::mutex _disconnectMutex; - + std::condition_variable _sendCondition; std::deque _sendBuffer; std::mutex _sendBufferMutex; std::deque _receiveBuffer; std::mutex _receiveBufferMutex; - + std::atomic _timeJumped; std::mutex _latencyMutex; std::deque _latencyDiffs; diff --git a/include/openspace/performance/performancemanager.h b/include/openspace/performance/performancemanager.h index 6b12dfa914..890657363c 100644 --- a/include/openspace/performance/performancemanager.h +++ b/include/openspace/performance/performancemanager.h @@ -43,19 +43,19 @@ class PerformanceManager { public: static void createGlobalSharedMemory(); static void destroyGlobalSharedMemory(); - + PerformanceManager(std::string loggingDirectory = "${BASE_PATH}", std::string prefix = "PM-"); - + ~PerformanceManager(); void resetPerformanceMeasurements(); - + bool isMeasuringPerformance() const; void storeIndividualPerformanceMeasurement(std::string identifier, long long nanoseconds); void storeScenePerformanceMeasurements(const std::vector& sceneNodes); - + void outputLogs(); void writeData(std::ofstream& out, const std::vector& data); @@ -83,13 +83,13 @@ private: std::string _prefix; std::string _suffix; std::string _ext; - + std::map individualPerformanceLocations; - + std::unique_ptr _performanceMemory; size_t _tick; - + void tick(); bool createLogDir(); }; diff --git a/include/openspace/performance/performancemeasurement.h b/include/openspace/performance/performancemeasurement.h index 58d90650e2..7815492e51 100644 --- a/include/openspace/performance/performancemeasurement.h +++ b/include/openspace/performance/performancemeasurement.h @@ -46,7 +46,7 @@ private: std::chrono::high_resolution_clock::time_point _startTime; }; - + #define __MERGE(a,b) a##b #define __LABEL(a) __MERGE(unique_name_, a) @@ -57,7 +57,7 @@ private: (name), \ OsEng.renderEngine().performanceManager() \ ) - + } // namespace openspace::performance #endif // __OPENSPACE_CORE___PERFORMANCEMEASUREMENT___H__ diff --git a/include/openspace/properties/numericalproperty.inl b/include/openspace/properties/numericalproperty.inl index 51ce94f827..39a4ea2cf9 100644 --- a/include/openspace/properties/numericalproperty.inl +++ b/include/openspace/properties/numericalproperty.inl @@ -232,7 +232,7 @@ const std::string NumericalProperty::SteppingValueKey = "SteppingValue"; // Delegating constructors are necessary; automatic template deduction cannot // deduce template argument for 'U' if 'default' methods are used as default values in // a single constructor - + template NumericalProperty::NumericalProperty(Property::PropertyInfo info) : NumericalProperty( diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index 62e0fbf15d..83301f87d1 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -148,7 +148,7 @@ public: * \return The type that is requested by this Property's Property::set method */ virtual const std::type_info& type() const; - + /** * This method encodes the encapsulated value of this Property at the top of the Lua * stack. The specific details of this serialization is up to the property developer @@ -237,7 +237,7 @@ public: * \return The unique identifier of this Property */ const std::string& identifier() const; - + /** * Returns the fully qualified name for this Property that uniquely identifies this * Property within OpenSpace. It consists of the identifier preceded by @@ -260,7 +260,7 @@ public: * \param owner The new PropertyOwner for this Property */ void setPropertyOwner(PropertyOwner* owner); - + /** * Returns the human-readable GUI name for this Property that has been set in the * constructor. This method returns the same value as accessing the metaData object diff --git a/include/openspace/properties/propertyowner.h b/include/openspace/properties/propertyowner.h index 061a77d8fe..c0f8bc8914 100644 --- a/include/openspace/properties/propertyowner.h +++ b/include/openspace/properties/propertyowner.h @@ -56,7 +56,7 @@ public: std::string name; std::string description = ""; }; - + /// The constructor initializing the PropertyOwner's name to "" PropertyOwner(PropertyOwnerInfo info); @@ -85,7 +85,6 @@ public: void setDescription(std::string description); std::string description() const; - /** * Returns a list of all Propertys directly owned by this PropertyOwner. This list not @@ -123,7 +122,7 @@ public: * false otherwise. */ bool hasProperty(const std::string& URI) const; - + void setPropertyOwner(PropertyOwner* owner) { _owner = owner; } PropertyOwner* owner() const { return _owner; } @@ -171,7 +170,7 @@ public: * groupID */ std::string propertyGroupName(const std::string& groupID) const; - + /** * Assigns the Property prop to this PropertyOwner. This method will * check if the name of the Property is unique amongst Propertys and sub-owners in @@ -180,10 +179,10 @@ public: * \param prop The Property whose ownership is changed. */ void addProperty(Property* prop); - + /// \see Property::addProperty(Property*) void addProperty(Property& prop); - + /** * Adds the provided PropertyOwner to the list of sub-owners for this PropertyOwner. * This means that the name of the owner has to be unique amonst the @@ -206,7 +205,7 @@ public: /// \see PropertyOwner::removeProperty(Property*) void removeProperty(Property& prop); - + /** * Removes the sub-owner from this PropertyOwner. * \param owner The PropertyOwner that should be removed diff --git a/include/openspace/properties/scalar/boolproperty.h b/include/openspace/properties/scalar/boolproperty.h index bb5a6bae41..ee74bbfcf8 100644 --- a/include/openspace/properties/scalar/boolproperty.h +++ b/include/openspace/properties/scalar/boolproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class BoolProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type bool. diff --git a/include/openspace/properties/scalar/charproperty.h b/include/openspace/properties/scalar/charproperty.h index 0622c0bb00..3151c53ebe 100644 --- a/include/openspace/properties/scalar/charproperty.h +++ b/include/openspace/properties/scalar/charproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class CharProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type char. diff --git a/include/openspace/properties/scalar/doubleproperty.h b/include/openspace/properties/scalar/doubleproperty.h index 594e220ccb..0ef4ed259c 100644 --- a/include/openspace/properties/scalar/doubleproperty.h +++ b/include/openspace/properties/scalar/doubleproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class DoubleProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type double. diff --git a/include/openspace/properties/scalar/floatproperty.h b/include/openspace/properties/scalar/floatproperty.h index 0d8233ddfe..bf7957d4f0 100644 --- a/include/openspace/properties/scalar/floatproperty.h +++ b/include/openspace/properties/scalar/floatproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class FloatProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type float. diff --git a/include/openspace/properties/scalar/intproperty.h b/include/openspace/properties/scalar/intproperty.h index ac5a0fc639..b0fbdd9acb 100644 --- a/include/openspace/properties/scalar/intproperty.h +++ b/include/openspace/properties/scalar/intproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class IntProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type int. diff --git a/include/openspace/properties/scalar/longdoubleproperty.h b/include/openspace/properties/scalar/longdoubleproperty.h index 01ee6e5a2e..f02ac8f44f 100644 --- a/include/openspace/properties/scalar/longdoubleproperty.h +++ b/include/openspace/properties/scalar/longdoubleproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class LongDoubleProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type long double. diff --git a/include/openspace/properties/scalar/longlongproperty.h b/include/openspace/properties/scalar/longlongproperty.h index 151a54f8d8..d8f86f3351 100644 --- a/include/openspace/properties/scalar/longlongproperty.h +++ b/include/openspace/properties/scalar/longlongproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class LongLongProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type long long. diff --git a/include/openspace/properties/scalar/longproperty.h b/include/openspace/properties/scalar/longproperty.h index 2d76d51e3d..85576f258c 100644 --- a/include/openspace/properties/scalar/longproperty.h +++ b/include/openspace/properties/scalar/longproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class LongProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type long. diff --git a/include/openspace/properties/scalar/shortproperty.h b/include/openspace/properties/scalar/shortproperty.h index 8969e4805e..90cb81af0c 100644 --- a/include/openspace/properties/scalar/shortproperty.h +++ b/include/openspace/properties/scalar/shortproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class ShortProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type short. diff --git a/include/openspace/properties/scalar/signedcharproperty.h b/include/openspace/properties/scalar/signedcharproperty.h index d32f8b5a5c..fae4a5e2ed 100644 --- a/include/openspace/properties/scalar/signedcharproperty.h +++ b/include/openspace/properties/scalar/signedcharproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class SignedCharProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type signed char. diff --git a/include/openspace/properties/scalar/ucharproperty.h b/include/openspace/properties/scalar/ucharproperty.h index 8b0affc8e2..04f799179a 100644 --- a/include/openspace/properties/scalar/ucharproperty.h +++ b/include/openspace/properties/scalar/ucharproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class UCharProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type unsigned char. diff --git a/include/openspace/properties/scalar/uintproperty.h b/include/openspace/properties/scalar/uintproperty.h index d206a179cc..bb3b346a40 100644 --- a/include/openspace/properties/scalar/uintproperty.h +++ b/include/openspace/properties/scalar/uintproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class UIntProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type unsigned int. diff --git a/include/openspace/properties/scalar/ulonglongproperty.h b/include/openspace/properties/scalar/ulonglongproperty.h index f0290bc806..b0b36b5eb3 100644 --- a/include/openspace/properties/scalar/ulonglongproperty.h +++ b/include/openspace/properties/scalar/ulonglongproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class ULongLongProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type unsigned long long. diff --git a/include/openspace/properties/scalar/ulongproperty.h b/include/openspace/properties/scalar/ulongproperty.h index 81f6c437e2..8372f62938 100644 --- a/include/openspace/properties/scalar/ulongproperty.h +++ b/include/openspace/properties/scalar/ulongproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class ULongProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type unsigned long. diff --git a/include/openspace/properties/scalar/ushortproperty.h b/include/openspace/properties/scalar/ushortproperty.h index 6892cad6f2..10fac45e29 100644 --- a/include/openspace/properties/scalar/ushortproperty.h +++ b/include/openspace/properties/scalar/ushortproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class UShortProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type unsigned short. diff --git a/include/openspace/properties/scalar/wcharproperty.h b/include/openspace/properties/scalar/wcharproperty.h index dccaaa6ed6..d9b2ca546a 100644 --- a/include/openspace/properties/scalar/wcharproperty.h +++ b/include/openspace/properties/scalar/wcharproperty.h @@ -32,7 +32,7 @@ * @{ * \addtogroup properties * @{ - + * \class WCharProperty * This class is a concrete implementation of openspace::properties::TemplateProperty with * the type wchar_t. diff --git a/include/openspace/properties/selectionproperty.h b/include/openspace/properties/selectionproperty.h index 26603c8569..f60d7b5217 100644 --- a/include/openspace/properties/selectionproperty.h +++ b/include/openspace/properties/selectionproperty.h @@ -39,7 +39,7 @@ public: }; SelectionProperty(Property::PropertyInfo info); - + void addOption(Option option); void removeOptions(); const std::vector