From 3ab97231bb92d2169be05c174bb1b5572a1083b8 Mon Sep 17 00:00:00 2001 From: Malin E Date: Tue, 2 Aug 2022 09:38:30 +0200 Subject: [PATCH 01/23] Add selection property to RenderableDUMeshes --- .../rendering/renderabledumeshes.cpp | 100 +++++++++++++++++- .../rendering/renderabledumeshes.h | 15 ++- 2 files changed, 110 insertions(+), 5 deletions(-) diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index 1ac9ebdf62..0d40fa6720 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -121,6 +121,12 @@ namespace { "Debug option for rendering of billboards and texts" }; + constexpr openspace::properties::Property::PropertyInfo MeshSelectionInfo = { + "MeshSelection", + "Mesh Selection", + "Property to select one or more of the meshes to be rendered." + }; + struct [[codegen::Dictionary(RenderableDUMeshes)]] Parameters { // The path to the SPECK file that contains information about the astronomical // object being rendered @@ -160,6 +166,9 @@ namespace { // [[codegen::verbatim(MeshColorInfo.description)]] std::optional> meshColor; + + // [[codegen::verbatim(MeshSelectionInfo.description)]] + std::optional> selectedMeshes; }; #include "renderabledumeshes_codegen.cpp" } // namespace @@ -185,6 +194,7 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) ) , _lineWidth(LineWidthInfo, 2.f, 1.f, 16.f) , _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown) + , _selectedMeshes(MeshSelectionInfo) { const Parameters p = codegen::bake(dictionary); @@ -248,6 +258,66 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) _meshColorMap.insert({ static_cast(i) + 1, ops[i] }); } } + + _selectedMeshes.onChange([this]() { selectionPropertyHasChanged(); }); + addProperty(_selectedMeshes); + + if (p.selectedMeshes.has_value()) { + const std::vector options = _selectedMeshes.options(); + std::set selectedNames; + + for (const std::string& s : *p.selectedMeshes) { + const auto it = std::find(options.begin(), options.end(), s); + if (it == options.end()) { + // The user has specified a mesh name that doesn't exist + LWARNING(fmt::format("Option '{}' not found in list of meshes", s)); + } + else { + selectedNames.insert(s); + } + } + _selectedMeshes = selectedNames; + } +} + +void RenderableDUMeshes::fillSelectionProperty() { + for (const std::pair& pair : _renderingMeshesMap) { + if (pair.second.name.empty()) { + continue; + } + + auto it = std::find( + _selectedMeshes.options().begin(), + _selectedMeshes.options().end(), + pair.second.name + ); + if (it != _selectedMeshes.options().end()) { + continue; + } + _selectedMeshes.addOption(pair.second.name); + } + + if (_selectedMeshes.options().empty()) { + _selectedMeshes.setVisibility(properties::Property::Visibility::Developer); + } + else { + _selectedMeshes.setVisibility(properties::Property::Visibility::NoviceUser); + } +} + +void RenderableDUMeshes::selectionPropertyHasChanged() { + // If no values are selected (the default), we want to show all constellations + if (!_selectedMeshes.hasSelected()) { + for (std::pair& pair : _renderingMeshesMap) { + pair.second.isEnabled = true; + } + } + else { + // Enable all constellations that are selected + for (std::pair& pair : _renderingMeshesMap) { + pair.second.isEnabled = _selectedMeshes.isSelected(pair.second.name); + } + } } bool RenderableDUMeshes::isReady() const { @@ -322,6 +392,10 @@ void RenderableDUMeshes::renderMeshes(const RenderData&, _program->setUniform(_uniformCache.alphaValue, opacity()); for (const std::pair& pair : _renderingMeshesMap) { + if (!pair.second.isEnabled) { + continue; + } + _program->setUniform(_uniformCache.color, _meshColorMap[pair.second.colorIndex]); for (size_t i = 0; i < pair.second.vaoArray.size(); ++i) { glBindVertexArray(pair.second.vaoArray[i]); @@ -535,9 +609,26 @@ bool RenderableDUMeshes::readSpeckFile() { } while (dummy != "{"); std::getline(file, line); - std::stringstream dim(line); - dim >> mesh.numU; // numU - dim >> mesh.numV; // numV + std::stringstream dimOrName(line); + std::string dummyU, dummyV; + + // Try to read name of mesh if it exist + dimOrName >> dummyU; // numU or "name" + dimOrName >> dummyV; // numV or the name of the mesh + + if (dummyU == "name") { + mesh.name = dummyV; + + // Dimensions are specified in the next line as usual + std::getline(file, line); + std::stringstream dim(line); + dim >> mesh.numU; // numU + dim >> mesh.numV; // numV + } + else { + mesh.numU = stoi(dummyU); + mesh.numV = stoi(dummyV); + } // We can now read the vertices data: for (int l = 0; l < mesh.numU * mesh.numV; ++l) { @@ -603,6 +694,7 @@ bool RenderableDUMeshes::readSpeckFile() { } } + fillSelectionProperty(); setBoundingSphere(maxRadius); return true; @@ -636,7 +728,7 @@ void RenderableDUMeshes::createMeshes() { // in_position glEnableVertexAttribArray(0); // (2022-03-23, emmbr) This code was actually never used. We only read three - // values per line and di not handle any texture cooridnates, even if there + // values per line and did not handle any texture cooridnates, even if there // would have been some in the file //// U and V may not be given by the user //if (p.second.vertices.size() / (p.second.numU * p.second.numV) > 3) { diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.h b/modules/digitaluniverse/rendering/renderabledumeshes.h index 5c6222abeb..3d6f991711 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.h +++ b/modules/digitaluniverse/rendering/renderabledumeshes.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -84,13 +85,15 @@ private: // "If you wish to draw a line between points, then numU will be 1 while // numV will equal the number of points to connect. // If you want a square, 4000×4000 grid with lines every 200 units, - // then numU numU will both equal 21 + // then numU numV will both equal 21 int numU; int numV; MeshType style; std::vector vaoArray; std::vector vboArray; std::vector vertices; + bool isEnabled = true; + std::string name; }; void createMeshes(); @@ -102,6 +105,15 @@ private: bool loadData(); bool readSpeckFile(); + /// Fills the _selectedMeshes property with all available meshes + void fillSelectionProperty(); + + /** + * Callback method that gets triggered when _selectedMeshes + * changes. + */ + void selectionPropertyHasChanged(); + bool _hasSpeckFile = false; bool _dataIsDirty = true; bool _textColorIsDirty = true; @@ -114,6 +126,7 @@ private: properties::BoolProperty _drawLabels; properties::IVec2Property _textMinMaxSize; properties::FloatProperty _lineWidth; + properties::SelectionProperty _selectedMeshes; // DEBUG: properties::OptionProperty _renderOption; From 4df76934807237ed27125ae15806002ef5c98555 Mon Sep 17 00:00:00 2001 From: Malin E Date: Tue, 2 Aug 2022 10:59:26 +0200 Subject: [PATCH 02/23] Make DUMeshes selection property visible even if list is empty --- modules/digitaluniverse/rendering/renderabledumeshes.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index 0d40fa6720..25ac5be0c2 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -296,13 +296,6 @@ void RenderableDUMeshes::fillSelectionProperty() { } _selectedMeshes.addOption(pair.second.name); } - - if (_selectedMeshes.options().empty()) { - _selectedMeshes.setVisibility(properties::Property::Visibility::Developer); - } - else { - _selectedMeshes.setVisibility(properties::Property::Visibility::NoviceUser); - } } void RenderableDUMeshes::selectionPropertyHasChanged() { From 9470faddbb21f1fcb5ae35567e0cce6dc40ca149 Mon Sep 17 00:00:00 2001 From: Malin E Date: Tue, 2 Aug 2022 11:44:48 +0200 Subject: [PATCH 03/23] Change GUI name for the selection property --- modules/digitaluniverse/rendering/renderabledumeshes.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index 25ac5be0c2..2227ea5b6d 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -123,8 +123,8 @@ namespace { constexpr openspace::properties::Property::PropertyInfo MeshSelectionInfo = { "MeshSelection", - "Mesh Selection", - "Property to select one or more of the meshes to be rendered." + "Selection", + "Selected objects" }; struct [[codegen::Dictionary(RenderableDUMeshes)]] Parameters { From 39b8914917399cb67cc0db5a8422d848329b287f Mon Sep 17 00:00:00 2001 From: Malin E Date: Tue, 2 Aug 2022 13:34:31 +0200 Subject: [PATCH 04/23] Fix bug when constellations have several words in its name --- modules/digitaluniverse/rendering/renderabledumeshes.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index 2227ea5b6d..b2763d8045 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -606,11 +606,15 @@ bool RenderableDUMeshes::readSpeckFile() { std::string dummyU, dummyV; // Try to read name of mesh if it exist - dimOrName >> dummyU; // numU or "name" - dimOrName >> dummyV; // numV or the name of the mesh + dimOrName >> dummyU; // numU or "name" + std::getline(dimOrName, dummyV); // numV or the name of the mesh if (dummyU == "name") { mesh.name = dummyV; + // Trim leading whitespace + if (!mesh.name.empty() && mesh.name[0] == ' ') { + mesh.name = mesh.name.substr(1); + } // Dimensions are specified in the next line as usual std::getline(file, line); From 9c39874efcc8bb48f0a8ceed0cc85bc1cef171d2 Mon Sep 17 00:00:00 2001 From: Malin E Date: Tue, 2 Aug 2022 14:05:39 +0200 Subject: [PATCH 05/23] Load spaeck file in initialize instead of initialiseGL --- .../rendering/renderabledumeshes.cpp | 48 ++++++++++--------- .../rendering/renderabledumeshes.h | 2 + 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index b2763d8045..6ef7bd79d8 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -262,22 +262,7 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) _selectedMeshes.onChange([this]() { selectionPropertyHasChanged(); }); addProperty(_selectedMeshes); - if (p.selectedMeshes.has_value()) { - const std::vector options = _selectedMeshes.options(); - std::set selectedNames; - - for (const std::string& s : *p.selectedMeshes) { - const auto it = std::find(options.begin(), options.end(), s); - if (it == options.end()) { - // The user has specified a mesh name that doesn't exist - LWARNING(fmt::format("Option '{}' not found in list of meshes", s)); - } - else { - selectedNames.insert(s); - } - } - _selectedMeshes = selectedNames; - } + _assetSelectedMeshes = p.selectedMeshes.value_or(_assetSelectedMeshes); } void RenderableDUMeshes::fillSelectionProperty() { @@ -318,6 +303,30 @@ bool RenderableDUMeshes::isReady() const { (!_renderingMeshesMap.empty() || (!_labelset.entries.empty())); } +void RenderableDUMeshes::initialize() { + bool success = loadData(); + if (!success) { + throw ghoul::RuntimeError("Error loading data"); + } + + fillSelectionProperty(); + + const std::vector options = _selectedMeshes.options(); + std::set selectedNames; + + for (const std::string& s : _assetSelectedMeshes) { + const auto it = std::find(options.begin(), options.end(), s); + if (it == options.end()) { + // The user has specified a mesh name that doesn't exist + LWARNING(fmt::format("Option '{}' not found in list of meshes", s)); + } + else { + selectedNames.insert(s); + } + } + _selectedMeshes = selectedNames; +} + void RenderableDUMeshes::initializeGL() { _program = DigitalUniverseModule::ProgramObjectManager.request( "RenderableDUMeshes", @@ -332,11 +341,6 @@ void RenderableDUMeshes::initializeGL() { ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames); - bool success = loadData(); - if (!success) { - throw ghoul::RuntimeError("Error loading data"); - } - createMeshes(); if (_hasLabel) { @@ -690,8 +694,6 @@ bool RenderableDUMeshes::readSpeckFile() { } } } - - fillSelectionProperty(); setBoundingSphere(maxRadius); return true; diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.h b/modules/digitaluniverse/rendering/renderabledumeshes.h index 3d6f991711..4e331daab5 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.h +++ b/modules/digitaluniverse/rendering/renderabledumeshes.h @@ -56,6 +56,7 @@ public: explicit RenderableDUMeshes(const ghoul::Dictionary& dictionary); ~RenderableDUMeshes() override = default; + void initialize() override; void initializeGL() override; void deinitializeGL() override; @@ -118,6 +119,7 @@ private: bool _dataIsDirty = true; bool _textColorIsDirty = true; bool _hasLabel = false; + std::vector _assetSelectedMeshes; properties::Vec3Property _textColor; properties::FloatProperty _textOpacity; From e98e9fe4a3af50a6db241420012dd2caa556855a Mon Sep 17 00:00:00 2001 From: Malin E Date: Fri, 5 Aug 2022 11:05:57 +0200 Subject: [PATCH 06/23] WIP initiali version of new constellation classes --- .../digitaluniverse/constellationbounds.asset | 2 +- .../digitaluniverse/constellations.asset | 3 +- .../rendering/renderabledumeshes.cpp | 6 +- modules/space/CMakeLists.txt | 6 + .../rendering/renderableconstellation.cpp | 379 ++++++++++++ .../space/rendering/renderableconstellation.h | 121 ++++ .../renderableconstellationbounds.cpp | 140 +---- .../rendering/renderableconstellationbounds.h | 30 +- .../renderableconstellationlines.cpp | 581 ++++++++++++++++++ .../rendering/renderableconstellationlines.h | 137 +++++ .../space/shaders/constellationlines_fs.glsl | 49 ++ .../space/shaders/constellationlines_vs.glsl | 47 ++ modules/space/spacemodule.cpp | 5 + modules/space/speckloader.cpp | 18 +- modules/space/speckloader.h | 1 + 15 files changed, 1373 insertions(+), 152 deletions(-) create mode 100644 modules/space/rendering/renderableconstellation.cpp create mode 100644 modules/space/rendering/renderableconstellation.h create mode 100644 modules/space/rendering/renderableconstellationlines.cpp create mode 100644 modules/space/rendering/renderableconstellationlines.h create mode 100644 modules/space/shaders/constellationlines_fs.glsl create mode 100644 modules/space/shaders/constellationlines_vs.glsl diff --git a/data/assets/scene/digitaluniverse/constellationbounds.asset b/data/assets/scene/digitaluniverse/constellationbounds.asset index c53f0bead2..273fad59da 100644 --- a/data/assets/scene/digitaluniverse/constellationbounds.asset +++ b/data/assets/scene/digitaluniverse/constellationbounds.asset @@ -16,7 +16,7 @@ local object = { Type = "RenderableConstellationBounds", Enabled = false, File = data .. "bound_20.dat", - ConstellationFile = data .. "constellations.dat" + ConstellationNamesFile = data .. "constellations.dat" -- ConstellationSelection = zodiacs }, Transform = { diff --git a/data/assets/scene/digitaluniverse/constellations.asset b/data/assets/scene/digitaluniverse/constellations.asset index 9bd8d72f18..3c0bcafa09 100644 --- a/data/assets/scene/digitaluniverse/constellations.asset +++ b/data/assets/scene/digitaluniverse/constellations.asset @@ -29,11 +29,12 @@ local constellationsExtragalactic = { local constellations = { Identifier = "Constellations", Renderable = { - Type = "RenderableDUMeshes", + Type = "RenderableConstellationLines", Enabled = false, Opacity = 0.3, File = speck .. "constellations.speck", LabelFile = speck .. "constellations.label", + ConstellationNamesFile = "C:/Users/malej60/Documents/Sync/http/digitaluniverse_constellationbounds_data/1/constellations.dat", TextColor = { 0.8, 0.8, 0.8 }, TextOpacity = 0.3, TextSize = 14.5, diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index 6ef7bd79d8..01dc22f4ca 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -311,6 +311,10 @@ void RenderableDUMeshes::initialize() { fillSelectionProperty(); + if (_assetSelectedMeshes.empty()) { + return; + } + const std::vector options = _selectedMeshes.options(); std::set selectedNames; @@ -613,7 +617,7 @@ bool RenderableDUMeshes::readSpeckFile() { dimOrName >> dummyU; // numU or "name" std::getline(dimOrName, dummyV); // numV or the name of the mesh - if (dummyU == "name") { + if (dummyU == "id") { mesh.name = dummyV; // Trim leading whitespace if (!mesh.name.empty() && mesh.name[0] == ' ') { diff --git a/modules/space/CMakeLists.txt b/modules/space/CMakeLists.txt index dc8f0ddfd2..cc294fce94 100644 --- a/modules/space/CMakeLists.txt +++ b/modules/space/CMakeLists.txt @@ -27,7 +27,9 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES horizonsfile.h speckloader.h + rendering/renderableconstellation.h rendering/renderableconstellationbounds.h + rendering/renderableconstellationlines.h rendering/renderablefluxnodes.h rendering/renderablehabitablezone.h rendering/renderablerings.h @@ -48,7 +50,9 @@ set(SOURCE_FILES horizonsfile.cpp spacemodule_lua.inl speckloader.cpp + rendering/renderableconstellation.cpp rendering/renderableconstellationbounds.cpp + rendering/renderableconstellationlines.cpp rendering/renderablefluxnodes.cpp rendering/renderablehabitablezone.cpp rendering/renderablerings.cpp @@ -68,6 +72,8 @@ source_group("Source Files" FILES ${SOURCE_FILES}) set(SHADER_FILES shaders/constellationbounds_fs.glsl shaders/constellationbounds_vs.glsl + shaders/constellationlines_fs.glsl + shaders/constellationlines_vs.glsl shaders/debrisViz_fs.glsl shaders/debrisViz_vs.glsl shaders/fluxnodes_fs.glsl diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp new file mode 100644 index 0000000000..08f8d2d184 --- /dev/null +++ b/modules/space/rendering/renderableconstellation.cpp @@ -0,0 +1,379 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SpiceUsr.h" + +namespace { + constexpr int RenderOptionViewDirection = 0; + constexpr int RenderOptionPositionNormal = 1; + + constexpr openspace::properties::Property::PropertyInfo TextColorInfo = { + "TextColor", + "Text Color", + "The text color for the astronomical object" + }; + + constexpr openspace::properties::Property::PropertyInfo TextOpacityInfo = { + "TextOpacity", + "Text Opacity", + "Determines the transparency of the text label, where 1 is completely opaque " + "and 0 fully transparent" + }; + + constexpr openspace::properties::Property::PropertyInfo TextSizeInfo = { + "TextSize", + "Text Size", + "The text size for the astronomical object labels" + }; + + constexpr openspace::properties::Property::PropertyInfo LabelFileInfo = { + "LabelFile", + "Label File", + "The path to the label file that contains information about the astronomical " + "objects being rendered" + }; + + constexpr openspace::properties::Property::PropertyInfo LabelMinMaxSizeInfo = { + "TextMinMaxSize", + "Text Min/Max Size", + "The minimum and maximum size (in pixels) of the text for the labels for the " + "astronomical objects being rendered" + }; + + constexpr openspace::properties::Property::PropertyInfo ConstellationInfo = { + "ConstellationFile", + "Constellation File Path", + "Specifies the file that contains the mapping between constellation " + "abbreviations and full name of the constellation. If this value is empty, the " + "abbreviations are used as the full names" + }; + + constexpr openspace::properties::Property::PropertyInfo LineWidthInfo = { + "LineWidth", + "Line Width", + "The line width of the constellation " + }; + + constexpr openspace::properties::Property::PropertyInfo DrawLabelInfo = { + "DrawLabels", + "Draw Labels", + "Determines whether labels should be drawn or hidden" + }; + + constexpr openspace::properties::Property::PropertyInfo RenderOptionInfo = { + "RenderOption", + "Render Option", + "Debug option for rendering of billboards and texts" + }; + + constexpr openspace::properties::Property::PropertyInfo SelectionInfo = { + "ConstellationSelection", + "Constellation Selection", + "The constellations that are selected are displayed on the celestial sphere" + }; + + struct [[codegen::Dictionary(RenderableConstellation)]] Parameters { + // [[codegen::verbatim(DrawLabelInfo.description)]] + std::optional drawLabels; + + // [[codegen::verbatim(ConstellationInfo.description)]] + std::string constellationNamesFile; + + // [[codegen::verbatim(TextColorInfo.description)]] + std::optional textColor [[codegen::color()]]; + + // [[codegen::verbatim(TextOpacityInfo.description)]] + std::optional textOpacity; + + // [[codegen::verbatim(TextSizeInfo.description)]] + std::optional textSize; + + // [[codegen::verbatim(LabelFileInfo.description)]] + std::optional labelFile; + + // [[codegen::verbatim(LabelMinMaxSizeInfo.description)]] + std::optional textMinMaxSize; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(SelectionInfo.description)]] + std::optional> constellationSelection; + }; +#include "renderableconstellation_codegen.cpp" +} // namespace + +namespace openspace { + +documentation::Documentation RenderableConstellation::Documentation() { + return codegen::doc("space_renderable_constellation"); +} + +RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _textColor(TextColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f)) + , _textOpacity(TextOpacityInfo, 1.f, 0.f, 1.f) + , _textSize(TextSizeInfo, 8.f, 0.5f, 24.f) + , _drawLabels(DrawLabelInfo, false) + , _textMinMaxSize( + LabelMinMaxSizeInfo, + glm::ivec2(8, 500), + glm::ivec2(0), + glm::ivec2(1000) + ) + , _lineWidth(LineWidthInfo, 2.f, 1.f, 16.f) + , _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown) + , _constellationNamesFilename(ConstellationInfo) + , _constellationSelection(SelectionInfo) +{ + const Parameters p = codegen::bake(dictionary); + + addProperty(_opacity); + registerUpdateRenderBinFromOpacity(); + + _renderOption.addOption(RenderOptionViewDirection, "Camera View Direction"); + _renderOption.addOption(RenderOptionPositionNormal, "Camera Position Normal"); + // @TODO (abock. 2021-01-31) In the other DU classes, this is done with an enum, and + // doing it based on the fisheye rendering seems a bit brittle? + if (global::windowDelegate->isFisheyeRendering()) { + _renderOption = RenderOptionPositionNormal; + } + else { + _renderOption = RenderOptionViewDirection; + } + addProperty(_renderOption); + + // Avoid reading the translation file here, instead do it in the initialize() + _constellationNamesFilename = p.constellationNamesFile; + _constellationNamesFilename.onChange([&](){ loadConstellationFile(); }); + addProperty(_constellationNamesFilename); + + _lineWidth = p.lineWidth.value_or(_lineWidth); + addProperty(_lineWidth); + + if (p.labelFile.has_value()) { + _labelFile = absPath(*p.labelFile).string(); + _hasLabel = true; + + _drawLabels = p.drawLabels.value_or(_drawLabels); + addProperty(_drawLabels); + + _textColor = p.textColor.value_or(_textColor); + _hasLabel = p.textColor.has_value(); + _textColor.setViewOption(properties::Property::ViewOptions::Color); + addProperty(_textColor); + _textColor.onChange([&]() { _textColorIsDirty = true; }); + + _textOpacity = p.textOpacity.value_or(_textOpacity); + addProperty(_textOpacity); + + _textSize = p.textSize.value_or(_textSize); + addProperty(_textSize); + + _textMinMaxSize = p.textMinMaxSize.value_or(_textMinMaxSize); + _textMinMaxSize.setViewOption(properties::Property::ViewOptions::MinMaxRange); + addProperty(_textMinMaxSize); + } + + fillSelectionProperty(); + _constellationSelection.onChange([this]() { selectionPropertyHasChanged(); }); + addProperty(_constellationSelection); + + if (p.constellationSelection.has_value()) { + const std::vector options = _constellationSelection.options(); + + std::set selectedNames; + for (const std::string& s : *p.constellationSelection) { + const auto it = std::find(options.begin(), options.end(), s); + if (it == options.end()) { + // The user has specified a constellation name that doesn't exist + LWARNINGC( + "RenderableConstellation", + fmt::format("Option '{}' not found in list of constellations", s) + ); + } + else { + selectedNames.insert(s); + } + } + _constellationSelection = selectedNames; + } +} + +bool RenderableConstellation::loadConstellationFile() { + if (_constellationNamesFilename.value().empty()) { + return true; + } + + std::ifstream file; + file.exceptions(std::ifstream::goodbit); + file.open(absPath(_constellationNamesFilename)); + + std::string line; + int index = 0; + while (file.good()) { + std::getline(file, line); + if (line.empty()) { + continue; + } + + std::string abbreviation; + std::stringstream s(line); + s >> abbreviation; + + std::string fullName; + std::getline(s, fullName); + ghoul::trimWhitespace(fullName); + _constellationNamesTranslation.insert({ abbreviation, fullName }); + + ++index; + } + + return true; +} + +void RenderableConstellation::fillSelectionProperty() { + for (const std::pair& pair : _constellationNamesTranslation) { + _constellationSelection.addOption(pair.second); + } +} + +void RenderableConstellation::initialize() { + loadConstellationFile(); + + if (!_hasLabel) { + return; + } + + if (!_font) { + constexpr int FontSize = 50; + _font = global::fontManager->font( + "Mono", + static_cast(FontSize), + ghoul::fontrendering::FontManager::Outline::Yes, + ghoul::fontrendering::FontManager::LoadGlyphs::No + ); + } + + std::string labelFile = _labelFile; + if (!labelFile.empty()) { + _labelset = speck::label::loadFileWithCache(_labelFile); + } + + for (speck::Labelset::Entry& entry : _labelset.entries) { + if (!entry.identifier.empty()) { + entry.text = _constellationNamesTranslation[entry.identifier]; + } + } +} + +void RenderableConstellation::render(const RenderData& data, RendererTasks&) { + const glm::dmat4 modelMatrix = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation + glm::dmat4(data.modelTransform.rotation) * // Spice rotation + glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); + + const glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix; + const glm::dmat4 projectionMatrix = data.camera.projectionMatrix(); + const glm::dmat4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix; + + const glm::vec3 lookup = data.camera.lookUpVectorWorldSpace(); + const glm::vec3 viewDirection = data.camera.viewDirectionWorldSpace(); + glm::vec3 right = glm::cross(viewDirection, lookup); + const glm::vec3 up = glm::cross(right, viewDirection); + + const glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix); + glm::vec3 orthoRight = glm::normalize( + glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)) + ); + + if (orthoRight == glm::vec3(0.0)) { + glm::vec3 otherVector(lookup.y, lookup.x, lookup.z); + right = glm::cross(viewDirection, otherVector); + orthoRight = glm::normalize( + glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)) + ); + } + + if (_drawLabels && _hasLabel) { + const glm::vec3 orthoUp = glm::normalize( + glm::vec3(worldToModelTransform * glm::dvec4(up, 0.0)) + ); + renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp); + } +} + +void RenderableConstellation::renderLabels(const RenderData& data, + const glm::dmat4& modelViewProjectionMatrix, + const glm::vec3& orthoRight, + const glm::vec3& orthoUp) +{ + float scale = static_cast(toMeter(_labelUnit)); + + ghoul::fontrendering::FontRenderer::ProjectedLabelsInformation labelInfo; + labelInfo.orthoRight = orthoRight; + labelInfo.orthoUp = orthoUp; + labelInfo.minSize = _textMinMaxSize.value().x; + labelInfo.maxSize = _textMinMaxSize.value().y; + labelInfo.cameraPos = data.camera.positionVec3(); + labelInfo.cameraLookUp = data.camera.lookUpVectorWorldSpace(); + labelInfo.renderType = _renderOption; + labelInfo.mvpMatrix = modelViewProjectionMatrix; + labelInfo.scale = pow(10.f, _textSize); + labelInfo.enableDepth = true; + labelInfo.enableFalseDepth = false; + + glm::vec4 textColor = glm::vec4(glm::vec3(_textColor), _textOpacity); + + for (const speck::Labelset::Entry& e : _labelset.entries) { + glm::vec3 scaledPos(e.position); + scaledPos *= scale; + ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render( + *_font, + scaledPos, + e.text, + textColor, + labelInfo + ); + } +} + +} // namespace openspace diff --git a/modules/space/rendering/renderableconstellation.h b/modules/space/rendering/renderableconstellation.h new file mode 100644 index 0000000000..fd1acd37eb --- /dev/null +++ b/modules/space/rendering/renderableconstellation.h @@ -0,0 +1,121 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * 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_SPACE___RENDERABLECONSTELLATION___H__ +#define __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATION___H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ghoul::fontrendering { class Font; } +namespace ghoul::opengl { class ProgramObject; } + +namespace openspace { + +namespace documentation { struct Documentation; } + +class RenderableConstellation : public Renderable { +public: + virtual ~RenderableConstellation() override = default; + + virtual void initialize() override; + virtual void initializeGL() override = 0; + virtual void deinitialize() override = 0; + virtual void deinitializeGL() override = 0; + + virtual bool isReady() const override = 0; + + virtual void render(const RenderData& data, RendererTasks& rendererTask) override; + void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix, + const glm::vec3& orthoRight, const glm::vec3& orthoUp); + virtual void update(const UpdateData& data) override = 0; + + static documentation::Documentation Documentation(); + +protected: + explicit RenderableConstellation(const ghoul::Dictionary& dictionary); + + /** + * Callback method that gets triggered when _constellationSelection + * changes. + */ + virtual void selectionPropertyHasChanged() = 0; + + // Map over the constellations names and theis abbreviations + // key = abbreviations, value = full name + std::map _constellationNamesTranslation; + + // Linewidth for the constellation bounds + properties::FloatProperty _lineWidth; + + /// The property that stores all indices of constellations that should be drawn + properties::SelectionProperty _constellationSelection; + + bool _hasLabel = false; + properties::BoolProperty _drawLabels; + speck::Labelset _labelset; + +private: + /** + * Loads the file specified in _constellationNamesFilename that contains the mapping + * between abbreviations and full names of constellations. + * + * \return true if the loading succeeded, false otherwise + */ + bool loadConstellationFile(); + + /// Fills the _constellationSelection property with all constellations + void fillSelectionProperty(); + + /// The file containing constellation names and abbreviations + properties::StringProperty _constellationNamesFilename; + + //Label text settings + std::string _labelFile; + properties::Vec3Property _textColor; + bool _textColorIsDirty = true; + properties::FloatProperty _textOpacity; + properties::FloatProperty _textSize; + properties::IVec2Property _textMinMaxSize; + std::shared_ptr _font = nullptr; + DistanceUnit _labelUnit = DistanceUnit::Parsec; + + properties::OptionProperty _renderOption; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATION___H__ diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index 6a1c798c5c..998e82e127 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -50,14 +50,6 @@ namespace { "constellations" }; - constexpr openspace::properties::Property::PropertyInfo ConstellationInfo = { - "ConstellationFile", - "Constellation File Path", - "Specifies the file that contains the mapping between constellation " - "abbreviations and full name of the constellation. If this value is empty, the " - "abbreviations are used as the full names" - }; - constexpr openspace::properties::Property::PropertyInfo ColorInfo = { "Color", "Color of constellation lines", @@ -65,33 +57,12 @@ namespace { "full opacity" }; - constexpr openspace::properties::Property::PropertyInfo LineWidthInfo = { - "LineWidth", - "Line Width", - "The line width of the constellation bounds" - }; - - constexpr openspace::properties::Property::PropertyInfo SelectionInfo = { - "ConstellationSelection", - "Constellation Selection", - "The constellations that are selected are displayed on the celestial sphere" - }; - struct [[codegen::Dictionary(RenderableConstellationBounds)]] Parameters { // [[codegen::verbatim(VertexInfo.description)]] std::string file; - // [[codegen::verbatim(ConstellationInfo.description)]] - std::optional constellationFile; - // [[codegen::verbatim(ColorInfo.description)]] std::optional color [[codegen::color()]]; - - // [[codegen::verbatim(LineWidthInfo.description)]] - std::optional lineWidth; - - // [[codegen::verbatim(SelectionInfo.description)]] - std::optional> constellationSelection; }; #include "renderableconstellationbounds_codegen.cpp" } // namespace @@ -103,54 +74,27 @@ documentation::Documentation RenderableConstellationBounds::Documentation() { } RenderableConstellationBounds::RenderableConstellationBounds( - const ghoul::Dictionary& dictionary) - : Renderable(dictionary) + const ghoul::Dictionary& dictionary) + : RenderableConstellation(dictionary) , _vertexFilename(VertexInfo) - , _constellationFilename(ConstellationInfo) , _color(ColorInfo, glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f), glm::vec3(1.f)) - , _lineWidth(LineWidthInfo, 2.f, 1.f, 32.f) - , _constellationSelection(SelectionInfo) { const Parameters p = codegen::bake(dictionary); + // Avoid loading the vertex file here, do it in multithreded initialize() instead + _vertexFilename = p.file; _vertexFilename.onChange([&](){ loadVertexFile(); }); addProperty(_vertexFilename); - _vertexFilename = p.file; - - _constellationFilename.onChange([&](){ loadConstellationFile(); }); - _constellationFilename = p.constellationFile.value_or(_constellationFilename); - addProperty(_constellationFilename); _color.setViewOption(properties::Property::ViewOptions::Color); _color = p.color.value_or(_color); addProperty(_color); +} - _lineWidth = p.lineWidth.value_or(_lineWidth); - addProperty(_lineWidth); +void RenderableConstellationBounds::initialize() { + RenderableConstellation::initialize(); - fillSelectionProperty(); - _constellationSelection.onChange([this]() { selectionPropertyHasChanged(); }); - addProperty(_constellationSelection); - - if (p.constellationSelection.has_value()) { - const std::vector options = _constellationSelection.options(); - - std::set selectedNames; - for (const std::string& s : *p.constellationSelection) { - const auto it = std::find(options.begin(), options.end(), s); - if (it == options.end()) { - // The user has specified a constellation name that doesn't exist - LWARNINGC( - "RenderableConstellationBounds", - fmt::format("Option '{}' not found in list of constellations", s) - ); - } - else { - selectedNames.insert(s); - } - } - _constellationSelection = selectedNames; - } + loadVertexFile(); } void RenderableConstellationBounds::initializeGL() { @@ -179,6 +123,9 @@ void RenderableConstellationBounds::initializeGL() { glBindVertexArray(0); } +void RenderableConstellationBounds::deinitialize() { +} + void RenderableConstellationBounds::deinitializeGL() { glDeleteBuffers(1, &_vbo); _vbo = 0; @@ -192,10 +139,10 @@ void RenderableConstellationBounds::deinitializeGL() { } bool RenderableConstellationBounds::isReady() const { - return (_vao != 0) && (_vbo != 0) && _program; + return _program && _vao != 0 && _vbo != 0 && !_labelset.entries.empty(); } -void RenderableConstellationBounds::render(const RenderData& data, RendererTasks&) { +void RenderableConstellationBounds::render(const RenderData& data, RendererTasks& tasks) { _program->activate(); _program->setUniform("campos", glm::vec4(data.camera.positionVec3(), 1.f)); @@ -223,6 +170,12 @@ void RenderableConstellationBounds::render(const RenderData& data, RendererTasks } glBindVertexArray(0); _program->deactivate(); + + RenderableConstellation::render(data, tasks); +} + +void RenderableConstellationBounds::update(const UpdateData& data) { + } bool RenderableConstellationBounds::loadVertexFile() { @@ -326,61 +279,6 @@ bool RenderableConstellationBounds::loadVertexFile() { return true; } -bool RenderableConstellationBounds::loadConstellationFile() { - if (_constellationFilename.value().empty()) { - return true; - } - - std::ifstream file; - file.exceptions(std::ifstream::goodbit); - file.open(absPath(_constellationFilename)); - - std::string line; - int index = 0; - while (file.good()) { - std::getline(file, line); - if (line.empty()) { - continue; - } - - std::string abbreviation; - std::stringstream s(line); - s >> abbreviation; - - const auto it = std::find_if( - _constellationBounds.begin(), - _constellationBounds.end(), - [abbreviation](const ConstellationBound& bound) { - return bound.constellationAbbreviation == abbreviation; - } - ); - if (it == _constellationBounds.end()) { - LERRORC( - "RenderableConstellationBounds", - fmt::format("Could not find constellation '{}' in list", abbreviation) - ); - return false; - } - - // Update the constellations full name - std::string fullName; - std::getline(s, fullName); - ghoul::trimWhitespace(fullName); - it->constellationFullName = std::move(fullName); - - ++index; - } - - return true; -} - -void RenderableConstellationBounds::fillSelectionProperty() { - for (int i = 0 ; i < static_cast(_constellationBounds.size()); ++i) { - const ConstellationBound& bound = _constellationBounds[i]; - _constellationSelection.addOption(bound.constellationFullName); - } -} - void RenderableConstellationBounds::selectionPropertyHasChanged() { // If no values are selected (the default), we want to show all constellations if (!_constellationSelection.hasSelected()) { diff --git a/modules/space/rendering/renderableconstellationbounds.h b/modules/space/rendering/renderableconstellationbounds.h index bf52622de4..877187a4c4 100644 --- a/modules/space/rendering/renderableconstellationbounds.h +++ b/modules/space/rendering/renderableconstellationbounds.h @@ -25,9 +25,8 @@ #ifndef __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONBOUNDS___H__ #define __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONBOUNDS___H__ -#include +#include -#include #include #include #include @@ -48,16 +47,19 @@ namespace documentation { struct Documentation; } * _distance property. Currently, all constellation bounds are lines, which * leads to artifacts if the radius is very small. */ -class RenderableConstellationBounds : public Renderable { +class RenderableConstellationBounds : public RenderableConstellation { public: RenderableConstellationBounds(const ghoul::Dictionary& dictionary); + void initialize() override; void initializeGL() override; + void deinitialize() override; void deinitializeGL() override; bool isReady() const override; void render(const RenderData& data, RendererTasks& rendererTask) override; + void update(const UpdateData& data) override; static documentation::Documentation Documentation(); @@ -80,35 +82,18 @@ private: */ bool loadVertexFile(); - /** - * Loads the file specified in _constellationFilename that contains the mapping - * between abbreviations and full names of constellations. - * - * \return true if the loading succeeded, false otherwise - */ - bool loadConstellationFile(); - - /// Fills the _constellationSelection property with all constellations - void fillSelectionProperty(); - /** * Callback method that gets triggered when _constellationSelection * changes. */ - void selectionPropertyHasChanged(); + void selectionPropertyHasChanged() override; /// The filename containing the constellation bounds properties::StringProperty _vertexFilename; - /// The file containing constellation names - properties::StringProperty _constellationFilename; - /// Determines the color of the constellation lines properties::Vec3Property _color; - // Linewidth for the constellation bounds - properties::FloatProperty _lineWidth; - std::unique_ptr _program; /// The list of all loaded constellation bounds @@ -121,9 +106,6 @@ private: }; std::vector _vertexValues; ///< A list of all vertices of all bounds - /// The property that stores all indices of constellations that should be drawn - properties::SelectionProperty _constellationSelection; - GLuint _vao = 0; GLuint _vbo = 0; }; diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp new file mode 100644 index 0000000000..06452e2621 --- /dev/null +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -0,0 +1,581 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + constexpr std::string_view _loggerCat = "RenderableConstellationLines"; + + constexpr std::array UniformNames = { + "modelViewTransform", "projectionTransform", "alphaValue", "color" + }; + + constexpr int RenderOptionViewDirection = 0; + constexpr int RenderOptionPositionNormal = 1; + + constexpr openspace::properties::Property::PropertyInfo DrawElementsInfo = { + "DrawElements", + "Draw Elements", + "Enables/Disables the drawing of the astronomical objects" + }; + + constexpr openspace::properties::Property::PropertyInfo MeshColorInfo = { + "MeshColor", + "Meshes colors", + "The defined colors for the meshes to be rendered" + }; + + struct [[codegen::Dictionary(RenderableConstellationLines)]] Parameters { + // The path to the SPECK file that contains information about the astronomical + // object being rendered + std::string file; + + enum class [[codegen::map(openspace::DistanceUnit)]] Unit { + Meter [[codegen::key("m")]], + Kilometer [[codegen::key("Km")]], + Parsec [[codegen::key("pc")]], + Kiloparsec [[codegen::key("Kpc")]], + Megaparsec [[codegen::key("Mpc")]], + Gigaparsec [[codegen::key("Gpc")]], + Gigalightyear [[codegen::key("Gly")]] + }; + std::optional unit; + + // [[codegen::verbatim(MeshColorInfo.description)]] + std::optional> meshColor; + }; +#include "renderableconstellationlines_codegen.cpp" +} // namespace + +namespace openspace { + +documentation::Documentation RenderableConstellationLines::Documentation() { + return codegen::doc("space_renderable_constellationlines"); +} + +RenderableConstellationLines::RenderableConstellationLines( + const ghoul::Dictionary& dictionary) + : RenderableConstellation(dictionary) + , _drawElements(DrawElementsInfo, true) +{ + const Parameters p = codegen::bake(dictionary); + + _speckFile = absPath(p.file).string(); + _hasSpeckFile = true; + _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); + addProperty(_drawElements); + + if (p.unit.has_value()) { + _unit = codegen::map(*p.unit); + } + else { + _unit = DistanceUnit::Meter; + } + + if (p.meshColor.has_value()) { + std::vector ops = *p.meshColor; + for (size_t i = 0; i < ops.size(); ++i) { + _meshColorMap.insert({ static_cast(i) + 1, ops[i] }); + } + } +} + +void RenderableConstellationLines::selectionPropertyHasChanged() { + // If no values are selected (the default), we want to show all constellations + if (!_constellationSelection.hasSelected()) { + for (std::pair& pair : _renderingMeshesMap) { + pair.second.isEnabled = true; + } + } + else { + // Enable all constellations that are selected + for (std::pair& pair : _renderingMeshesMap) { + pair.second.isEnabled = + _constellationSelection.isSelected(pair.second.identifier); + } + } +} + +bool RenderableConstellationLines::isReady() const { + return (_program != nullptr) && !_renderingMeshesMap.empty() && + !_labelset.entries.empty(); +} + +void RenderableConstellationLines::initialize() { + RenderableConstellation::initialize(); + + bool success = loadData(); + if (!success) { + throw ghoul::RuntimeError("Error loading data"); + } +} + +void RenderableConstellationLines::initializeGL() { + _program = DigitalUniverseModule::ProgramObjectManager.request( + "RenderableConstellationLines", + []() { + return global::renderEngine->buildRenderProgram( + "RenderableConstellationLines", + absPath("${MODULE_SPACE}/shaders/constellationlines_vs.glsl"), + absPath("${MODULE_SPACE}/shaders/constellationlines_fs.glsl") + ); + } + ); + + ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames); + + createMeshes(); +} + +void RenderableConstellationLines::deinitialize() { +} + +void RenderableConstellationLines::deinitializeGL() { + for (const std::pair& pair : _renderingMeshesMap) { + for (int i = 0; i < pair.second.numU; ++i) { + glDeleteVertexArrays(1, &pair.second.vaoArray[i]); + glDeleteBuffers(1, &pair.second.vboArray[i]); + } + } + + DigitalUniverseModule::ProgramObjectManager.release( + "RenderableConstellationLines", + [](ghoul::opengl::ProgramObject* p) { + global::renderEngine->removeRenderProgram(p); + } + ); +} + +void RenderableConstellationLines::renderMeshes(const RenderData&, + const glm::dmat4& modelViewMatrix, + const glm::dmat4& projectionMatrix) +{ + glEnablei(GL_BLEND, 0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(false); + glEnable(GL_DEPTH_TEST); + + _program->activate(); + + _program->setUniform(_uniformCache.modelViewTransform, modelViewMatrix); + _program->setUniform(_uniformCache.projectionTransform, projectionMatrix); + _program->setUniform(_uniformCache.alphaValue, opacity()); + + for (const std::pair& pair : _renderingMeshesMap) { + if (!pair.second.isEnabled) { + continue; + } + + _program->setUniform(_uniformCache.color, _meshColorMap[pair.second.colorIndex]); + for (size_t i = 0; i < pair.second.vaoArray.size(); ++i) { + glBindVertexArray(pair.second.vaoArray[i]); + switch (pair.second.style) { + case Solid: + break; + case Wire: + glLineWidth(_lineWidth); + glDrawArrays(GL_LINE_STRIP, 0, pair.second.numV); + global::renderEngine->openglStateCache().resetLineState(); + break; + case Point: + glDrawArrays(GL_POINTS, 0, pair.second.numV); + break; + default: + break; + } + } + } + + glBindVertexArray(0); + _program->deactivate(); + + // Restores GL State + global::renderEngine->openglStateCache().resetDepthState(); + global::renderEngine->openglStateCache().resetBlendState(); +} + +void RenderableConstellationLines::render(const RenderData& data, RendererTasks& tasks) { + const glm::dmat4 modelMatrix = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation + glm::dmat4(data.modelTransform.rotation) * // Spice rotation + glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); + + const glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix; + const glm::dmat4 projectionMatrix = data.camera.projectionMatrix(); + + if (_hasSpeckFile) { + renderMeshes(data, modelViewMatrix, projectionMatrix); + } + + RenderableConstellation::render(data, tasks); +} + +void RenderableConstellationLines::update(const UpdateData&) { + if (_program->isDirty()) { + _program->rebuildFromFile(); + ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames); + } +} + +bool RenderableConstellationLines::loadData() { + bool success = false; + if (_hasSpeckFile) { + LINFO(fmt::format("Loading Speck file {}", std::filesystem::path(_speckFile))); + success = readSpeckFile(); + if (!success) { + return false; + } + } + + return success; +} + +bool RenderableConstellationLines::readSpeckFile() { + std::ifstream file(_speckFile); + if (!file.good()) { + LERROR(fmt::format( + "Failed to open Speck file {}", std::filesystem::path(_speckFile) + )); + return false; + } + + const float scale = static_cast(toMeter(_unit)); + double maxRadius = 0.0; + + int meshIndex = 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::getline(file, line); + + if (file.eof()) { + break; + } + + // Guard against wrong line endings (copying files from Windows to Mac) causes + // lines to have a final \r + if (!line.empty() && line.back() == '\r') { + line = line.substr(0, line.length() - 1); + } + + if (line.empty() || line[0] == '#') { + continue; + } + + std::size_t found = line.find("mesh"); + if (found == std::string::npos) { + continue; + } + else { + // mesh lines are structured as follows: + // mesh -t texnum -c colorindex -s style { + // where textnum is the index of the texture; + // colorindex is the index of the color for the mesh + // and style is solid, wire or point (for now we support only wire) + std::stringstream str(line); + + RenderingMesh mesh; + mesh.meshIndex = meshIndex; + + std::string dummy; + str >> dummy; // mesh command + dummy.clear(); + str >> dummy; // texture index command? + do { + if (dummy == "-t") { + dummy.clear(); + str >> mesh.textureIndex; // texture index + } + else if (dummy == "-c") { + dummy.clear(); + str >> mesh.colorIndex; // color index command + } + else if (dummy == "-s") { + dummy.clear(); + str >> dummy; // style value command + if (dummy == "solid") { + mesh.style = Solid; + } + else if (dummy == "wire") { + mesh.style = Wire; + } + else if (dummy == "point") { + mesh.style = Point; + } + else { + mesh.style = INVALID; + break; + } + } + dummy.clear(); + str >> dummy; + } while (dummy != "{"); + + std::getline(file, line); + std::stringstream dimOrName(line); + std::string dummyU, dummyV; + + // Try to read name of mesh if it exist + dimOrName >> dummyU; // numU or "id" + std::getline(dimOrName, dummyV); // numV or the identifier of the mesh + + if (dummyU == "id") { + ghoul::trimWhitespace(dummyV); + mesh.identifier = _constellationNamesTranslation[dummyV]; + + // Dimensions are specified in the next line as usual + std::getline(file, line); + std::stringstream dim(line); + dim >> mesh.numU; // numU + dim >> mesh.numV; // numV + } + else { + mesh.numU = stoi(dummyU); + mesh.numV = stoi(dummyV); + } + + // We can now read the vertices data: + for (int l = 0; l < mesh.numU * mesh.numV; ++l) { + std::getline(file, line); + if (line.substr(0, 1) == "}") { + break; + } + + std::stringstream lineData(line); + + // Try to read three values for the position + glm::vec3 pos; + bool success = true; + for (int i = 0; i < 3; ++i) { + GLfloat value; + lineData >> value; + bool errorReading = lineData.rdstate() & std::ifstream::failbit; + if (errorReading) { + success = false; + break; + } + + GLfloat scaledValue = value * scale; + pos[i] = scaledValue; + mesh.vertices.push_back(scaledValue); + } + + if (!success) { + LERROR(fmt::format( + "Failed reading position on line {} of mesh {} in file: '{}'. " + "Stopped reading mesh data", l, meshIndex, _speckFile + )); + break; + } + + // Check if new max radius + const double r = glm::length(glm::dvec3(pos)); + maxRadius = std::max(maxRadius, r); + + // OLD CODE: + // (2022-03-23, emmbr) None of our files included texture coordinates, + // and if they would they would still not be used by the shader + //for (int i = 0; i < 7; ++i) { + // GLfloat value; + // lineData >> value; + // bool errorReading = lineData.rdstate() & std::ifstream::failbit; + // if (!errorReading) { + // mesh.vertices.push_back(value); + // } + // else { + // break; + // } + //} + } + + std::getline(file, line); + if (line.substr(0, 1) == "}") { + _renderingMeshesMap.insert({ meshIndex++, mesh }); + } + else { + return false; + } + } + } + setBoundingSphere(maxRadius); + + return true; +} + +void RenderableConstellationLines::createMeshes() { + if (!(_dataIsDirty && _hasSpeckFile)) { + return; + } + LDEBUG("Creating planes"); + + for (std::pair& p : _renderingMeshesMap) { + for (int i = 0; i < p.second.numU; ++i) { + GLuint vao; + glGenVertexArrays(1, &vao); + p.second.vaoArray.push_back(vao); + + GLuint vbo; + glGenBuffers(1, &vbo); + p.second.vboArray.push_back(vbo); + + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + //glBufferData(GL_ARRAY_BUFFER, it->second.numV * sizeof(GLfloat), + glBufferData( + GL_ARRAY_BUFFER, + p.second.vertices.size() * sizeof(GLfloat), + &p.second.vertices[0], + GL_STATIC_DRAW + ); + // in_position + glEnableVertexAttribArray(0); + // (2022-03-23, emmbr) This code was actually never used. We only read three + // values per line and did not handle any texture cooridnates, even if there + // would have been some in the file + //// U and V may not be given by the user + //if (p.second.vertices.size() / (p.second.numU * p.second.numV) > 3) { + // glVertexAttribPointer( + // 0, + // 3, + // GL_FLOAT, + // GL_FALSE, + // sizeof(GLfloat) * 5, + // reinterpret_cast(sizeof(GLfloat) * i * p.second.numV) + // ); + + // // texture coords + // glEnableVertexAttribArray(1); + // glVertexAttribPointer( + // 1, + // 2, + // GL_FLOAT, + // GL_FALSE, + // sizeof(GLfloat) * 7, + // reinterpret_cast(sizeof(GLfloat) * 3 * i * p.second.numV) + // ); + //} + //else { // no U and V: + glVertexAttribPointer( + 0, + 3, + GL_FLOAT, + GL_FALSE, + 0, + reinterpret_cast(sizeof(GLfloat) * 3 * i * p.second.numV) + ); + //} + } + + // Grid: we need columns + if (p.second.numU > 1) { + for (int i = 0; i < p.second.numV; ++i) { + GLuint cvao; + glGenVertexArrays(1, &cvao); + p.second.vaoArray.push_back(cvao); + + GLuint cvbo; + glGenBuffers(1, &cvbo); + p.second.vboArray.push_back(cvbo); + + glBindVertexArray(cvao); + glBindBuffer(GL_ARRAY_BUFFER, cvbo); + glBufferData( + GL_ARRAY_BUFFER, + p.second.vertices.size() * sizeof(GLfloat), + &p.second.vertices[0], + GL_STATIC_DRAW + ); + // in_position + glEnableVertexAttribArray(0); + // U and V may not be given by the user + if (p.second.vertices.size() / (p.second.numU * p.second.numV) > 3) { + glVertexAttribPointer( + 0, + 3, + GL_FLOAT, + GL_FALSE, + p.second.numV * sizeof(GLfloat) * 5, + reinterpret_cast(sizeof(GLfloat) * i) + ); + + // texture coords + glEnableVertexAttribArray(1); + glVertexAttribPointer( + 1, + 2, + GL_FLOAT, + GL_FALSE, + p.second.numV * sizeof(GLfloat) * 7, + reinterpret_cast(sizeof(GLfloat) * 3 * i) + ); + } + else { // no U and V: + glVertexAttribPointer( + 0, + 3, + GL_FLOAT, + GL_FALSE, + p.second.numV * sizeof(GLfloat) * 3, + reinterpret_cast(sizeof(GLfloat) * 3 * i) + ); + } + } + } + } + + glBindVertexArray(0); + + _dataIsDirty = false; +} + +} // namespace openspace diff --git a/modules/space/rendering/renderableconstellationlines.h b/modules/space/rendering/renderableconstellationlines.h new file mode 100644 index 0000000000..985ebaaac3 --- /dev/null +++ b/modules/space/rendering/renderableconstellationlines.h @@ -0,0 +1,137 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * 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_DIGITALUNIVERSE___RENDERABLECONSTELLATIONLINES___H__ +#define __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLECONSTELLATIONLINES___H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ghoul::filesystem { class File; } +namespace ghoul::fontrendering { class Font; } +namespace ghoul::opengl { + class ProgramObject; + class Texture; +} // namespace ghoul::opengl + +namespace openspace { + +namespace documentation { struct Documentation; } + +class RenderableConstellationLines : public RenderableConstellation { +public: + explicit RenderableConstellationLines(const ghoul::Dictionary& dictionary); + ~RenderableConstellationLines() override = default; + + void initialize() override; + void initializeGL() override; + void deinitialize() override; + void deinitializeGL() override; + + bool isReady() const override; + + void render(const RenderData& data, RendererTasks& rendererTask) override; + void update(const UpdateData& data) override; + + static documentation::Documentation Documentation(); + +private: + enum MeshType { + Solid = 0, + Wire = 1, + Point = 2, + INVALID = 9 + }; + + struct RenderingMesh { + int meshIndex; + int colorIndex; + int textureIndex; + // From: Partiview User's Guide + // Brian Abbott + // Hayden Planetarium American Museum of Natural History New York, USA + // "Specifies the dimensions of the mesh" + // "If you wish to draw a line between points, then numU will be 1 while + // numV will equal the number of points to connect. + // If you want a square, 4000×4000 grid with lines every 200 units, + // then numU numV will both equal 21 + int numU; + int numV; + MeshType style; + std::vector vaoArray; + std::vector vboArray; + std::vector vertices; + bool isEnabled = true; + std::string identifier; + }; + + void createMeshes(); + void renderMeshes(const RenderData& data, const glm::dmat4& modelViewMatrix, + const glm::dmat4& projectionMatrix); + + bool loadData(); + bool readSpeckFile(); + + /** + * Callback method that gets triggered when _selectedMeshes + * changes. + */ + void selectionPropertyHasChanged(); + + bool _hasSpeckFile = false; + bool _dataIsDirty = true; + bool _textColorIsDirty = true; + std::vector _assetSelectedMeshes; + + properties::BoolProperty _drawElements; + + ghoul::opengl::ProgramObject* _program = nullptr; + UniformCache(modelViewTransform, projectionTransform, alphaValue, + color) _uniformCache; + std::shared_ptr _font = nullptr; + + std::string _speckFile; + + DistanceUnit _unit = DistanceUnit::Parsec; + + std::vector _fullData; + + std::unordered_map _meshColorMap; + std::unordered_map _renderingMeshesMap; +}; +} // namespace openspace + +#endif // __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLECONSTELLATIONLINES___H__ diff --git a/modules/space/shaders/constellationlines_fs.glsl b/modules/space/shaders/constellationlines_fs.glsl new file mode 100644 index 0000000000..243d5c66a5 --- /dev/null +++ b/modules/space/shaders/constellationlines_fs.glsl @@ -0,0 +1,49 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * 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 "fragment.glsl" + +in float vs_screenSpaceDepth; +in vec4 vs_positionViewSpace; + +uniform vec3 color; +uniform float alphaValue; + + +Fragment getFragment() { + Fragment frag; + + if (alphaValue == 0.0) { + discard; + } + + frag.color = vec4(color, alphaValue); + frag.depth = vs_screenSpaceDepth; + + // JCC: Need to change the position to camera space + frag.gPosition = vs_positionViewSpace; + frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0); + + return frag; +} diff --git a/modules/space/shaders/constellationlines_vs.glsl b/modules/space/shaders/constellationlines_vs.glsl new file mode 100644 index 0000000000..e8611e67d3 --- /dev/null +++ b/modules/space/shaders/constellationlines_vs.glsl @@ -0,0 +1,47 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * 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__ + +#include "PowerScaling/powerScaling_vs.hglsl" + +in vec3 in_position; + +out float vs_screenSpaceDepth; +out vec4 vs_positionViewSpace; + +uniform dmat4 modelViewTransform; +uniform dmat4 projectionTransform; + + +void main() { + dvec4 positionViewSpace = modelViewTransform * dvec4(in_position, 1.0); + vec4 positionClipSpace = vec4(projectionTransform * positionViewSpace); + vec4 positionScreenSpace = vec4(z_normalization(positionClipSpace)); + + vs_screenSpaceDepth = positionScreenSpace.w; + vs_positionViewSpace = vec4(positionViewSpace); + + gl_Position = positionScreenSpace; +} diff --git a/modules/space/spacemodule.cpp b/modules/space/spacemodule.cpp index 6bf6ec7c20..588d373799 100644 --- a/modules/space/spacemodule.cpp +++ b/modules/space/spacemodule.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -80,6 +81,9 @@ void SpaceModule::internalInitialize(const ghoul::Dictionary& dictionary) { fRenderable->registerClass( "RenderableConstellationBounds" ); + fRenderable->registerClass( + "RenderableConstellationLines" + ); fRenderable->registerClass("RenderableFluxNodes"); fRenderable->registerClass("RenderableHabitableZone"); fRenderable->registerClass("RenderableRings"); @@ -117,6 +121,7 @@ std::vector SpaceModule::documentations() const { HorizonsTranslation::Documentation(), KeplerTranslation::Documentation(), RenderableConstellationBounds::Documentation(), + RenderableConstellationLines::Documentation(), RenderableFluxNodes::Documentation(), RenderableHabitableZone::Documentation(), RenderableRings::Documentation(), diff --git a/modules/space/speckloader.cpp b/modules/space/speckloader.cpp index 05fa8fb817..a0811b3fce 100644 --- a/modules/space/speckloader.cpp +++ b/modules/space/speckloader.cpp @@ -321,7 +321,7 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) if (!str.good()) { // Need to subtract one of the line number here as we increase the current - // line count in the beginning of the while loop we are currently in + // line count in the beginning of the while loop we are currently in throw ghoul::RuntimeError(fmt::format( "Error loading position information out of data line {} in file {}. " "Value was not a number", @@ -346,7 +346,7 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) if (valueStream.fail()) { // Need to subtract one of the line number here as we increase the // current line count in the beginning of the while loop we are - // currently in + // currently in throw ghoul::RuntimeError(fmt::format( "Error loading data value {} out of data line {} in file {}. " "Value was not a number", @@ -674,10 +674,20 @@ Labelset loadFile(std::filesystem::path path, SkipAllZeroLines) { std::getline(str, rest); strip(rest); + if (startsWith(rest, "id")) { + // optional arument with identifier + // Remove the 'id' text + rest = rest.substr(std::string_view("id ").size()); + size_t index = rest.find("text"); + entry.identifier = rest.substr(0, index); + + // update the rest, remove the identifier + rest = rest.substr(index); + } if (!startsWith(rest, "text")) { throw ghoul::RuntimeError(fmt::format( - "Error loading label file {}: File contains some value between " - "positions and text label, which is unsupported", path + "Error loading label file {}: File contains an unsupported value " + "between positions and text label", path )); } diff --git a/modules/space/speckloader.h b/modules/space/speckloader.h index 0cc13c686e..8e48dbd764 100644 --- a/modules/space/speckloader.h +++ b/modules/space/speckloader.h @@ -68,6 +68,7 @@ struct Labelset { struct Entry { glm::vec3 position = glm::vec3(0.f); + std::string identifier; std::string text; }; std::vector entries; From 94a85ec719a742562349579ef9158f4ec696000d Mon Sep 17 00:00:00 2001 From: Malin E Date: Fri, 5 Aug 2022 13:05:36 +0200 Subject: [PATCH 07/23] Fix constellation label rendering --- .../rendering/renderableconstellation.cpp | 29 +++++++++++-------- modules/space/speckloader.cpp | 2 +- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index 08f8d2d184..47d8828970 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -181,9 +181,8 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio } addProperty(_renderOption); - // Avoid reading the translation file here, instead do it in the initialize() + _constellationNamesFilename.onChange([&]() { loadConstellationFile(); }); _constellationNamesFilename = p.constellationNamesFile; - _constellationNamesFilename.onChange([&](){ loadConstellationFile(); }); addProperty(_constellationNamesFilename); _lineWidth = p.lineWidth.value_or(_lineWidth); @@ -262,7 +261,7 @@ bool RenderableConstellation::loadConstellationFile() { std::string fullName; std::getline(s, fullName); ghoul::trimWhitespace(fullName); - _constellationNamesTranslation.insert({ abbreviation, fullName }); + _constellationNamesTranslation[abbreviation] = fullName; ++index; } @@ -277,8 +276,6 @@ void RenderableConstellation::fillSelectionProperty() { } void RenderableConstellation::initialize() { - loadConstellationFile(); - if (!_hasLabel) { return; } @@ -300,12 +297,16 @@ void RenderableConstellation::initialize() { for (speck::Labelset::Entry& entry : _labelset.entries) { if (!entry.identifier.empty()) { - entry.text = _constellationNamesTranslation[entry.identifier]; + entry.text = _constellationNamesTranslation.at(entry.identifier); } } } void RenderableConstellation::render(const RenderData& data, RendererTasks&) { + if (!_hasLabel || !_drawLabels) { + return; + } + const glm::dmat4 modelMatrix = glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * // Translation glm::dmat4(data.modelTransform.rotation) * // Spice rotation @@ -333,12 +334,10 @@ void RenderableConstellation::render(const RenderData& data, RendererTasks&) { ); } - if (_drawLabels && _hasLabel) { - const glm::vec3 orthoUp = glm::normalize( - glm::vec3(worldToModelTransform * glm::dvec4(up, 0.0)) - ); - renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp); - } + const glm::vec3 orthoUp = glm::normalize( + glm::vec3(worldToModelTransform * glm::dvec4(up, 0.0)) + ); + renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp); } void RenderableConstellation::renderLabels(const RenderData& data, @@ -364,6 +363,12 @@ void RenderableConstellation::renderLabels(const RenderData& data, glm::vec4 textColor = glm::vec4(glm::vec3(_textColor), _textOpacity); for (const speck::Labelset::Entry& e : _labelset.entries) { + if (_constellationSelection.hasSelected() && + !_constellationSelection.isSelected(e.text)) + { + continue; + } + glm::vec3 scaledPos(e.position); scaledPos *= scale; ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render( diff --git a/modules/space/speckloader.cpp b/modules/space/speckloader.cpp index a0811b3fce..4462c8f688 100644 --- a/modules/space/speckloader.cpp +++ b/modules/space/speckloader.cpp @@ -679,7 +679,7 @@ Labelset loadFile(std::filesystem::path path, SkipAllZeroLines) { // Remove the 'id' text rest = rest.substr(std::string_view("id ").size()); size_t index = rest.find("text"); - entry.identifier = rest.substr(0, index); + entry.identifier = rest.substr(0, index - 1); // update the rest, remove the identifier rest = rest.substr(index); From 62aaa45ff54c809ffd1c78eb6cb747cdd929d493 Mon Sep 17 00:00:00 2001 From: Malin E Date: Fri, 5 Aug 2022 14:08:36 +0200 Subject: [PATCH 08/23] Move file reading to initialize instead of constructor --- .../rendering/renderableconstellation.cpp | 56 +++++++++++-------- .../space/rendering/renderableconstellation.h | 4 +- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index 47d8828970..6e0c2936dd 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -181,8 +181,9 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio } addProperty(_renderOption); - _constellationNamesFilename.onChange([&]() { loadConstellationFile(); }); + // Read all files in the initialize() instead, multithreaded _constellationNamesFilename = p.constellationNamesFile; + _constellationNamesFilename.onChange([&]() { loadConstellationFile(); }); addProperty(_constellationNamesFilename); _lineWidth = p.lineWidth.value_or(_lineWidth); @@ -212,36 +213,21 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio addProperty(_textMinMaxSize); } - fillSelectionProperty(); _constellationSelection.onChange([this]() { selectionPropertyHasChanged(); }); addProperty(_constellationSelection); - if (p.constellationSelection.has_value()) { - const std::vector options = _constellationSelection.options(); - - std::set selectedNames; - for (const std::string& s : *p.constellationSelection) { - const auto it = std::find(options.begin(), options.end(), s); - if (it == options.end()) { - // The user has specified a constellation name that doesn't exist - LWARNINGC( - "RenderableConstellation", - fmt::format("Option '{}' not found in list of constellations", s) - ); - } - else { - selectedNames.insert(s); - } - } - _constellationSelection = selectedNames; - } + _assetSelectedMeshes = p.constellationSelection.value_or(_assetSelectedMeshes); } -bool RenderableConstellation::loadConstellationFile() { +void RenderableConstellation::loadConstellationFile() { if (_constellationNamesFilename.value().empty()) { - return true; + return; } + // Reset + _constellationSelection.clearOptions(); + _constellationNamesTranslation.clear(); + std::ifstream file; file.exceptions(std::ifstream::goodbit); file.open(absPath(_constellationNamesFilename)); @@ -266,7 +252,7 @@ bool RenderableConstellation::loadConstellationFile() { ++index; } - return true; + fillSelectionProperty(); } void RenderableConstellation::fillSelectionProperty() { @@ -276,6 +262,28 @@ void RenderableConstellation::fillSelectionProperty() { } void RenderableConstellation::initialize() { + loadConstellationFile(); + + if (!_assetSelectedMeshes.empty()) { + const std::vector options = _constellationSelection.options(); + std::set selectedConstellations; + + for (const std::string& s : _assetSelectedMeshes) { + const auto it = std::find(options.begin(), options.end(), s); + if (it == options.end()) { + // The user has specified a mesh name that doesn't exist + LWARNINGC( + "RenderableConstellation", + fmt::format("Option '{}' not found in list of meshes", s) + ); + } + else { + selectedConstellations.insert(s); + } + } + _constellationSelection = selectedConstellations; + } + if (!_hasLabel) { return; } diff --git a/modules/space/rendering/renderableconstellation.h b/modules/space/rendering/renderableconstellation.h index fd1acd37eb..06021d4f72 100644 --- a/modules/space/rendering/renderableconstellation.h +++ b/modules/space/rendering/renderableconstellation.h @@ -89,13 +89,15 @@ protected: speck::Labelset _labelset; private: + std::vector _assetSelectedMeshes; + /** * Loads the file specified in _constellationNamesFilename that contains the mapping * between abbreviations and full names of constellations. * * \return true if the loading succeeded, false otherwise */ - bool loadConstellationFile(); + void loadConstellationFile(); /// Fills the _constellationSelection property with all constellations void fillSelectionProperty(); From a2938c83841dd9529f0f453c8f346f8802dbc483 Mon Sep 17 00:00:00 2001 From: Malin E Date: Fri, 5 Aug 2022 15:12:43 +0200 Subject: [PATCH 09/23] Update label file cache format --- .../space/rendering/renderableconstellation.cpp | 11 ++++++++++- modules/space/speckloader.cpp | 16 +++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index 6e0c2936dd..14d6903b3a 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -305,7 +305,16 @@ void RenderableConstellation::initialize() { for (speck::Labelset::Entry& entry : _labelset.entries) { if (!entry.identifier.empty()) { - entry.text = _constellationNamesTranslation.at(entry.identifier); + try { + entry.text = _constellationNamesTranslation.at(entry.identifier); + } + catch (const std::out_of_range&) { + std::string message = fmt::format( + "Identifier '{}' could not be found in list of constellations", + entry.identifier + ); + throw ghoul::RuntimeError(message, "RenderableConstellation"); + } } } } diff --git a/modules/space/speckloader.cpp b/modules/space/speckloader.cpp index 4462c8f688..889be4b38e 100644 --- a/modules/space/speckloader.cpp +++ b/modules/space/speckloader.cpp @@ -37,7 +37,7 @@ namespace { constexpr int8_t DataCacheFileVersion = 10; - constexpr int8_t LabelCacheFileVersion = 10; + constexpr int8_t LabelCacheFileVersion = 11; constexpr int8_t ColorCacheFileVersion = 10; bool startsWith(std::string lhs, std::string_view rhs) noexcept { @@ -741,6 +741,13 @@ std::optional loadCachedFile(std::filesystem::path path) { file.read(reinterpret_cast(&e.position.y), sizeof(float)); file.read(reinterpret_cast(&e.position.z), sizeof(float)); + // Identifier + uint8_t idLen; + file.read(reinterpret_cast(&idLen), sizeof(uint8_t)); + e.identifier.resize(idLen); + file.read(e.identifier.data(), idLen); + + // Text uint16_t len; file.read(reinterpret_cast(&len), sizeof(uint16_t)); e.text.resize(len); @@ -773,6 +780,13 @@ void saveCachedFile(const Labelset& labelset, std::filesystem::path path) { file.write(reinterpret_cast(&e.position.y), sizeof(float)); file.write(reinterpret_cast(&e.position.z), sizeof(float)); + // Identifier + checkSize(e.identifier.size(), "Identifier too long"); + uint8_t idLen = static_cast(e.identifier.size()); + file.write(reinterpret_cast(&idLen), sizeof(uint8_t)); + file.write(e.identifier.data(), idLen); + + // Text checkSize(e.text.size(), "Text too long"); uint16_t len = static_cast(e.text.size()); file.write(reinterpret_cast(&len), sizeof(uint16_t)); From 6efb99e5510378edfa04aebf14390f19d4b2773a Mon Sep 17 00:00:00 2001 From: Malin E Date: Fri, 5 Aug 2022 16:59:04 +0200 Subject: [PATCH 10/23] Fix constellation bounds render issue --- .../rendering/renderableconstellation.cpp | 25 +++++++++++-------- .../space/rendering/renderableconstellation.h | 8 +++--- .../renderableconstellationbounds.cpp | 13 ++++++---- .../renderableconstellationlines.cpp | 2 +- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index 14d6903b3a..c7093c8009 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -219,6 +219,20 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio _assetSelectedMeshes = p.constellationSelection.value_or(_assetSelectedMeshes); } +std::string RenderableConstellation::constellationFullName( + const std::string& identifier) const +{ + try { + return _constellationNamesTranslation.at(identifier); + } + catch (const std::out_of_range&) { + std::string message = fmt::format( + "Identifier '{}' could not be found in list of constellations", identifier + ); + throw ghoul::RuntimeError(message, "RenderableConstellation"); + } +} + void RenderableConstellation::loadConstellationFile() { if (_constellationNamesFilename.value().empty()) { return; @@ -305,16 +319,7 @@ void RenderableConstellation::initialize() { for (speck::Labelset::Entry& entry : _labelset.entries) { if (!entry.identifier.empty()) { - try { - entry.text = _constellationNamesTranslation.at(entry.identifier); - } - catch (const std::out_of_range&) { - std::string message = fmt::format( - "Identifier '{}' could not be found in list of constellations", - entry.identifier - ); - throw ghoul::RuntimeError(message, "RenderableConstellation"); - } + entry.text = constellationFullName(entry.identifier); } } } diff --git a/modules/space/rendering/renderableconstellation.h b/modules/space/rendering/renderableconstellation.h index 06021d4f72..b8d4b1a548 100644 --- a/modules/space/rendering/renderableconstellation.h +++ b/modules/space/rendering/renderableconstellation.h @@ -74,9 +74,7 @@ protected: */ virtual void selectionPropertyHasChanged() = 0; - // Map over the constellations names and theis abbreviations - // key = abbreviations, value = full name - std::map _constellationNamesTranslation; + std::string constellationFullName(const std::string& identifier) const; // Linewidth for the constellation bounds properties::FloatProperty _lineWidth; @@ -89,6 +87,10 @@ protected: speck::Labelset _labelset; private: + // Map over the constellations names and theis abbreviations + // key = abbreviations, value = full name + std::map _constellationNamesTranslation; + std::vector _assetSelectedMeshes; /** diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index 998e82e127..f58f038579 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -139,6 +139,9 @@ void RenderableConstellationBounds::deinitializeGL() { } bool RenderableConstellationBounds::isReady() const { + if (!_hasLabel) { + return _program && _vao != 0 && _vbo != 0; + } return _program && _vao != 0 && _vbo != 0 && !_labelset.entries.empty(); } @@ -214,8 +217,8 @@ bool RenderableConstellationBounds::loadVertexFile() { float dec; s >> dec; - std::string constellationName; - s >> constellationName; + std::string abbreviation; + s >> abbreviation; if (!s.good()) { // If this evaluates to true, the stream was not completely filled, which @@ -230,7 +233,7 @@ bool RenderableConstellationBounds::loadVertexFile() { } // Did we arrive at a new constellation? - if (constellationName != currentBound.constellationAbbreviation) { + if (abbreviation != currentBound.constellationAbbreviation) { // Store how many vertices we read during the active time of the constellation currentBound.nVertices = static_cast( _vertexValues.size() - currentBound.startIndex @@ -239,8 +242,8 @@ bool RenderableConstellationBounds::loadVertexFile() { _constellationBounds.push_back(currentBound); currentBound = ConstellationBound(); currentBound.isEnabled = true; - currentBound.constellationAbbreviation = constellationName; - currentBound.constellationFullName = constellationName; + currentBound.constellationAbbreviation = abbreviation; + currentBound.constellationFullName = constellationFullName(abbreviation); currentBound.startIndex = static_cast(_vertexValues.size()); } diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index 06452e2621..9a3b8984bf 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -371,7 +371,7 @@ bool RenderableConstellationLines::readSpeckFile() { if (dummyU == "id") { ghoul::trimWhitespace(dummyV); - mesh.identifier = _constellationNamesTranslation[dummyV]; + mesh.identifier = constellationFullName(dummyV); // Dimensions are specified in the next line as usual std::getline(file, line); From 8c01d536b65f3fc9eef4a197758b1f5c4df1ea33 Mon Sep 17 00:00:00 2001 From: Malin E Date: Fri, 5 Aug 2022 17:01:12 +0200 Subject: [PATCH 11/23] Restore RenderableDUMeshes class --- .../rendering/renderabledumeshes.cpp | 99 +------------------ .../rendering/renderabledumeshes.h | 14 --- 2 files changed, 2 insertions(+), 111 deletions(-) diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index 01dc22f4ca..367d2ac91b 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -121,12 +121,6 @@ namespace { "Debug option for rendering of billboards and texts" }; - constexpr openspace::properties::Property::PropertyInfo MeshSelectionInfo = { - "MeshSelection", - "Selection", - "Selected objects" - }; - struct [[codegen::Dictionary(RenderableDUMeshes)]] Parameters { // The path to the SPECK file that contains information about the astronomical // object being rendered @@ -166,9 +160,6 @@ namespace { // [[codegen::verbatim(MeshColorInfo.description)]] std::optional> meshColor; - - // [[codegen::verbatim(MeshSelectionInfo.description)]] - std::optional> selectedMeshes; }; #include "renderabledumeshes_codegen.cpp" } // namespace @@ -194,7 +185,6 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) ) , _lineWidth(LineWidthInfo, 2.f, 1.f, 16.f) , _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown) - , _selectedMeshes(MeshSelectionInfo) { const Parameters p = codegen::bake(dictionary); @@ -258,44 +248,6 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) _meshColorMap.insert({ static_cast(i) + 1, ops[i] }); } } - - _selectedMeshes.onChange([this]() { selectionPropertyHasChanged(); }); - addProperty(_selectedMeshes); - - _assetSelectedMeshes = p.selectedMeshes.value_or(_assetSelectedMeshes); -} - -void RenderableDUMeshes::fillSelectionProperty() { - for (const std::pair& pair : _renderingMeshesMap) { - if (pair.second.name.empty()) { - continue; - } - - auto it = std::find( - _selectedMeshes.options().begin(), - _selectedMeshes.options().end(), - pair.second.name - ); - if (it != _selectedMeshes.options().end()) { - continue; - } - _selectedMeshes.addOption(pair.second.name); - } -} - -void RenderableDUMeshes::selectionPropertyHasChanged() { - // If no values are selected (the default), we want to show all constellations - if (!_selectedMeshes.hasSelected()) { - for (std::pair& pair : _renderingMeshesMap) { - pair.second.isEnabled = true; - } - } - else { - // Enable all constellations that are selected - for (std::pair& pair : _renderingMeshesMap) { - pair.second.isEnabled = _selectedMeshes.isSelected(pair.second.name); - } - } } bool RenderableDUMeshes::isReady() const { @@ -308,27 +260,6 @@ void RenderableDUMeshes::initialize() { if (!success) { throw ghoul::RuntimeError("Error loading data"); } - - fillSelectionProperty(); - - if (_assetSelectedMeshes.empty()) { - return; - } - - const std::vector options = _selectedMeshes.options(); - std::set selectedNames; - - for (const std::string& s : _assetSelectedMeshes) { - const auto it = std::find(options.begin(), options.end(), s); - if (it == options.end()) { - // The user has specified a mesh name that doesn't exist - LWARNING(fmt::format("Option '{}' not found in list of meshes", s)); - } - else { - selectedNames.insert(s); - } - } - _selectedMeshes = selectedNames; } void RenderableDUMeshes::initializeGL() { @@ -393,10 +324,6 @@ void RenderableDUMeshes::renderMeshes(const RenderData&, _program->setUniform(_uniformCache.alphaValue, opacity()); for (const std::pair& pair : _renderingMeshesMap) { - if (!pair.second.isEnabled) { - continue; - } - _program->setUniform(_uniformCache.color, _meshColorMap[pair.second.colorIndex]); for (size_t i = 0; i < pair.second.vaoArray.size(); ++i) { glBindVertexArray(pair.second.vaoArray[i]); @@ -610,30 +537,8 @@ bool RenderableDUMeshes::readSpeckFile() { } while (dummy != "{"); std::getline(file, line); - std::stringstream dimOrName(line); - std::string dummyU, dummyV; - - // Try to read name of mesh if it exist - dimOrName >> dummyU; // numU or "name" - std::getline(dimOrName, dummyV); // numV or the name of the mesh - - if (dummyU == "id") { - mesh.name = dummyV; - // Trim leading whitespace - if (!mesh.name.empty() && mesh.name[0] == ' ') { - mesh.name = mesh.name.substr(1); - } - - // Dimensions are specified in the next line as usual - std::getline(file, line); - std::stringstream dim(line); - dim >> mesh.numU; // numU - dim >> mesh.numV; // numV - } - else { - mesh.numU = stoi(dummyU); - mesh.numV = stoi(dummyV); - } + std::stringstream dim(line); + dim >> mesh.numU >> mesh.numV; // We can now read the vertices data: for (int l = 0; l < mesh.numU * mesh.numV; ++l) { diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.h b/modules/digitaluniverse/rendering/renderabledumeshes.h index 4e331daab5..afdf483479 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.h +++ b/modules/digitaluniverse/rendering/renderabledumeshes.h @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -93,8 +92,6 @@ private: std::vector vaoArray; std::vector vboArray; std::vector vertices; - bool isEnabled = true; - std::string name; }; void createMeshes(); @@ -106,20 +103,10 @@ private: bool loadData(); bool readSpeckFile(); - /// Fills the _selectedMeshes property with all available meshes - void fillSelectionProperty(); - - /** - * Callback method that gets triggered when _selectedMeshes - * changes. - */ - void selectionPropertyHasChanged(); - bool _hasSpeckFile = false; bool _dataIsDirty = true; bool _textColorIsDirty = true; bool _hasLabel = false; - std::vector _assetSelectedMeshes; properties::Vec3Property _textColor; properties::FloatProperty _textOpacity; @@ -128,7 +115,6 @@ private: properties::BoolProperty _drawLabels; properties::IVec2Property _textMinMaxSize; properties::FloatProperty _lineWidth; - properties::SelectionProperty _selectedMeshes; // DEBUG: properties::OptionProperty _renderOption; From 54dcdcf0f1cdf1cc674473681d2360e1439e3138 Mon Sep 17 00:00:00 2001 From: Malin E Date: Tue, 9 Aug 2022 08:54:41 +0200 Subject: [PATCH 12/23] Some clean up --- .../digitaluniverse/constellations.asset | 5 +- .../rendering/renderableconstellation.cpp | 33 +++- .../space/rendering/renderableconstellation.h | 37 ++-- .../renderableconstellationbounds.cpp | 2 +- .../rendering/renderableconstellationbounds.h | 9 +- .../renderableconstellationlines.cpp | 164 ++++++++---------- .../rendering/renderableconstellationlines.h | 47 ++--- .../space/shaders/constellationbounds_fs.glsl | 11 +- 8 files changed, 145 insertions(+), 163 deletions(-) diff --git a/data/assets/scene/digitaluniverse/constellations.asset b/data/assets/scene/digitaluniverse/constellations.asset index 3c0bcafa09..62f4d4f1e8 100644 --- a/data/assets/scene/digitaluniverse/constellations.asset +++ b/data/assets/scene/digitaluniverse/constellations.asset @@ -39,8 +39,9 @@ local constellations = { TextOpacity = 0.3, TextSize = 14.5, TextMinMaxSize = { 8, 170 }, - MeshColor = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, - Unit = "pc" + LabelUnit = "pc", + ConstellationColor = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, + ConstellationUnit = "pc" }, GUI = { Name = "Constellations", diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index c7093c8009..4d7c96b101 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -104,6 +104,12 @@ namespace { "Debug option for rendering of billboards and texts" }; + constexpr openspace::properties::Property::PropertyInfo LabelUnitInfo = { + "LabelUnit", + "Label Unit", + "The unit used for the label data" + }; + constexpr openspace::properties::Property::PropertyInfo SelectionInfo = { "ConstellationSelection", "Constellation Selection", @@ -135,6 +141,18 @@ namespace { // [[codegen::verbatim(LineWidthInfo.description)]] std::optional lineWidth; + enum class [[codegen::map(openspace::DistanceUnit)]] Unit { + Meter [[codegen::key("m")]], + Kilometer [[codegen::key("Km")]], + Parsec [[codegen::key("pc")]], + Kiloparsec [[codegen::key("Kpc")]], + Megaparsec [[codegen::key("Mpc")]], + Gigaparsec [[codegen::key("Gpc")]], + Gigalightyear [[codegen::key("Gly")]] + }; + // [[codegen::verbatim(LabelUnitInfo.description)]] + std::optional labelUnit; + // [[codegen::verbatim(SelectionInfo.description)]] std::optional> constellationSelection; }; @@ -200,7 +218,6 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio _hasLabel = p.textColor.has_value(); _textColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_textColor); - _textColor.onChange([&]() { _textColorIsDirty = true; }); _textOpacity = p.textOpacity.value_or(_textOpacity); addProperty(_textOpacity); @@ -211,12 +228,20 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio _textMinMaxSize = p.textMinMaxSize.value_or(_textMinMaxSize); _textMinMaxSize.setViewOption(properties::Property::ViewOptions::MinMaxRange); addProperty(_textMinMaxSize); + + if (p.labelUnit.has_value()) { + _labelUnit = codegen::map(*p.labelUnit); + } + else { + _labelUnit = DistanceUnit::Meter; + } } _constellationSelection.onChange([this]() { selectionPropertyHasChanged(); }); addProperty(_constellationSelection); - _assetSelectedMeshes = p.constellationSelection.value_or(_assetSelectedMeshes); + _assetSelectedConstellations = + p.constellationSelection.value_or(_assetSelectedConstellations); } std::string RenderableConstellation::constellationFullName( @@ -278,11 +303,11 @@ void RenderableConstellation::fillSelectionProperty() { void RenderableConstellation::initialize() { loadConstellationFile(); - if (!_assetSelectedMeshes.empty()) { + if (!_assetSelectedConstellations.empty()) { const std::vector options = _constellationSelection.options(); std::set selectedConstellations; - for (const std::string& s : _assetSelectedMeshes) { + for (const std::string& s : _assetSelectedConstellations) { const auto it = std::find(options.begin(), options.end(), s); if (it == options.end()) { // The user has specified a mesh name that doesn't exist diff --git a/modules/space/rendering/renderableconstellation.h b/modules/space/rendering/renderableconstellation.h index b8d4b1a548..514cffe511 100644 --- a/modules/space/rendering/renderableconstellation.h +++ b/modules/space/rendering/renderableconstellation.h @@ -29,10 +29,7 @@ #include #include -#include -#include #include -#include #include #include #include @@ -70,52 +67,54 @@ protected: /** * Callback method that gets triggered when _constellationSelection - * changes. + * changes */ virtual void selectionPropertyHasChanged() = 0; + /// Takes the given constellation identifier and returns the coresponding + /// full name std::string constellationFullName(const std::string& identifier) const; - // Linewidth for the constellation bounds + // Width for the rendered lines properties::FloatProperty _lineWidth; - /// The property that stores all indices of constellations that should be drawn + // Property that stores all constellations chosen by the user to be drawn properties::SelectionProperty _constellationSelection; + // Label text settings bool _hasLabel = false; - properties::BoolProperty _drawLabels; speck::Labelset _labelset; + properties::BoolProperty _drawLabels; private: - // Map over the constellations names and theis abbreviations - // key = abbreviations, value = full name + // Map over the constellations names and their abbreviations + // key = abbreviation, value = full name std::map _constellationNamesTranslation; - std::vector _assetSelectedMeshes; + // Temporary storage of which constellations should be rendered as stated in the + // asset file + std::vector _assetSelectedConstellations; /** - * Loads the file specified in _constellationNamesFilename that contains the mapping - * between abbreviations and full names of constellations. - * - * \return true if the loading succeeded, false otherwise + * Loads the file specified in _constellationNamesFilename that contains + * the mapping between abbreviations and full names of constellations */ void loadConstellationFile(); /// Fills the _constellationSelection property with all constellations void fillSelectionProperty(); - /// The file containing constellation names and abbreviations + // The file containing constellation names and abbreviations properties::StringProperty _constellationNamesFilename; - //Label text settings + // Label text settings std::string _labelFile; + std::shared_ptr _font = nullptr; + DistanceUnit _labelUnit = DistanceUnit::Parsec; properties::Vec3Property _textColor; - bool _textColorIsDirty = true; properties::FloatProperty _textOpacity; properties::FloatProperty _textSize; properties::IVec2Property _textMinMaxSize; - std::shared_ptr _font = nullptr; - DistanceUnit _labelUnit = DistanceUnit::Parsec; properties::OptionProperty _renderOption; }; diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index f58f038579..a0ac82f046 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -162,6 +162,7 @@ void RenderableConstellationBounds::render(const RenderData& data, RendererTasks _program->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); _program->setUniform("ModelTransform", glm::mat4(modelTransform)); _program->setUniform("color", _color); + _program->setUniform("alphaValue", opacity()); glLineWidth(_lineWidth); @@ -178,7 +179,6 @@ void RenderableConstellationBounds::render(const RenderData& data, RendererTasks } void RenderableConstellationBounds::update(const UpdateData& data) { - } bool RenderableConstellationBounds::loadVertexFile() { diff --git a/modules/space/rendering/renderableconstellationbounds.h b/modules/space/rendering/renderableconstellationbounds.h index 877187a4c4..eacb03aca9 100644 --- a/modules/space/rendering/renderableconstellationbounds.h +++ b/modules/space/rendering/renderableconstellationbounds.h @@ -27,11 +27,6 @@ #include -#include -#include -#include -#include - namespace ghoul::opengl { class ProgramObject; } namespace openspace { @@ -94,11 +89,11 @@ private: /// Determines the color of the constellation lines properties::Vec3Property _color; - std::unique_ptr _program; - /// The list of all loaded constellation bounds std::vector _constellationBounds; + std::unique_ptr _program; + struct Vertex { float x; float y; diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index 9a3b8984bf..6f46b952c8 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -24,7 +24,6 @@ #include -#include #include #include #include @@ -56,24 +55,26 @@ namespace { "modelViewTransform", "projectionTransform", "alphaValue", "color" }; - constexpr int RenderOptionViewDirection = 0; - constexpr int RenderOptionPositionNormal = 1; - constexpr openspace::properties::Property::PropertyInfo DrawElementsInfo = { "DrawElements", "Draw Elements", - "Enables/Disables the drawing of the astronomical objects" + "Enables/Disables the drawing of the constellations" }; - constexpr openspace::properties::Property::PropertyInfo MeshColorInfo = { - "MeshColor", - "Meshes colors", - "The defined colors for the meshes to be rendered" + constexpr openspace::properties::Property::PropertyInfo ConstellationUnitInfo = { + "ConstellationUnit", + "Constellation Unit", + "The unit used for the constellation data" + }; + + constexpr openspace::properties::Property::PropertyInfo ConstellationColorInfo = { + "ConstellationColor", + "Constellation colors", + "The defined colors for the constellations to be rendered" }; struct [[codegen::Dictionary(RenderableConstellationLines)]] Parameters { - // The path to the SPECK file that contains information about the astronomical - // object being rendered + // The path to the SPECK file that contains constellation lines data std::string file; enum class [[codegen::map(openspace::DistanceUnit)]] Unit { @@ -85,10 +86,11 @@ namespace { Gigaparsec [[codegen::key("Gpc")]], Gigalightyear [[codegen::key("Gly")]] }; - std::optional unit; + // [[codegen::verbatim(ConstellationUnitInfo.description)]] + std::optional constellationUnit; - // [[codegen::verbatim(MeshColorInfo.description)]] - std::optional> meshColor; + // [[codegen::verbatim(ConstellationColorInfo.description)]] + std::optional> constellationColor; }; #include "renderableconstellationlines_codegen.cpp" } // namespace @@ -111,17 +113,17 @@ RenderableConstellationLines::RenderableConstellationLines( _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); addProperty(_drawElements); - if (p.unit.has_value()) { - _unit = codegen::map(*p.unit); + if (p.constellationUnit.has_value()) { + _constellationUnit = codegen::map(*p.constellationUnit); } else { - _unit = DistanceUnit::Meter; + _constellationUnit = DistanceUnit::Meter; } - if (p.meshColor.has_value()) { - std::vector ops = *p.meshColor; + if (p.constellationColor.has_value()) { + std::vector ops = *p.constellationColor; for (size_t i = 0; i < ops.size(); ++i) { - _meshColorMap.insert({ static_cast(i) + 1, ops[i] }); + _constellationColorMap.insert({ static_cast(i) + 1, ops[i] }); } } } @@ -129,13 +131,17 @@ RenderableConstellationLines::RenderableConstellationLines( void RenderableConstellationLines::selectionPropertyHasChanged() { // If no values are selected (the default), we want to show all constellations if (!_constellationSelection.hasSelected()) { - for (std::pair& pair : _renderingMeshesMap) { + for (std::pair& pair : + _renderingConstellationsMap) + { pair.second.isEnabled = true; } } else { // Enable all constellations that are selected - for (std::pair& pair : _renderingMeshesMap) { + for (std::pair& pair : + _renderingConstellationsMap) + { pair.second.isEnabled = _constellationSelection.isSelected(pair.second.identifier); } @@ -143,7 +149,7 @@ void RenderableConstellationLines::selectionPropertyHasChanged() { } bool RenderableConstellationLines::isReady() const { - return (_program != nullptr) && !_renderingMeshesMap.empty() && + return (_program != nullptr) && !_renderingConstellationsMap.empty() && !_labelset.entries.empty(); } @@ -157,44 +163,37 @@ void RenderableConstellationLines::initialize() { } void RenderableConstellationLines::initializeGL() { - _program = DigitalUniverseModule::ProgramObjectManager.request( + _program = global::renderEngine->buildRenderProgram( "RenderableConstellationLines", - []() { - return global::renderEngine->buildRenderProgram( - "RenderableConstellationLines", - absPath("${MODULE_SPACE}/shaders/constellationlines_vs.glsl"), - absPath("${MODULE_SPACE}/shaders/constellationlines_fs.glsl") - ); - } + absPath("${MODULE_SPACE}/shaders/constellationlines_vs.glsl"), + absPath("${MODULE_SPACE}/shaders/constellationlines_fs.glsl") ); ghoul::opengl::updateUniformLocations(*_program, _uniformCache, UniformNames); - createMeshes(); + createConstellations(); } void RenderableConstellationLines::deinitialize() { } void RenderableConstellationLines::deinitializeGL() { - for (const std::pair& pair : _renderingMeshesMap) { + for (const std::pair& pair : _renderingConstellationsMap) { for (int i = 0; i < pair.second.numU; ++i) { glDeleteVertexArrays(1, &pair.second.vaoArray[i]); glDeleteBuffers(1, &pair.second.vboArray[i]); } } - DigitalUniverseModule::ProgramObjectManager.release( - "RenderableConstellationLines", - [](ghoul::opengl::ProgramObject* p) { - global::renderEngine->removeRenderProgram(p); - } - ); + if (_program) { + global::renderEngine->removeRenderProgram(_program.get()); + _program = nullptr; + } } -void RenderableConstellationLines::renderMeshes(const RenderData&, - const glm::dmat4& modelViewMatrix, - const glm::dmat4& projectionMatrix) +void RenderableConstellationLines::renderConstellations(const RenderData&, + const glm::dmat4& modelViewMatrix, + const glm::dmat4& projectionMatrix) { glEnablei(GL_BLEND, 0); glBlendFunc(GL_SRC_ALPHA, GL_ONE); @@ -208,28 +207,24 @@ void RenderableConstellationLines::renderMeshes(const RenderData&, _program->setUniform(_uniformCache.projectionTransform, projectionMatrix); _program->setUniform(_uniformCache.alphaValue, opacity()); - for (const std::pair& pair : _renderingMeshesMap) { + for (const std::pair& pair : + _renderingConstellationsMap) + { if (!pair.second.isEnabled) { continue; } - _program->setUniform(_uniformCache.color, _meshColorMap[pair.second.colorIndex]); + _program->setUniform( + _uniformCache.color, + _constellationColorMap[pair.second.colorIndex] + ); for (size_t i = 0; i < pair.second.vaoArray.size(); ++i) { glBindVertexArray(pair.second.vaoArray[i]); - switch (pair.second.style) { - case Solid: - break; - case Wire: - glLineWidth(_lineWidth); - glDrawArrays(GL_LINE_STRIP, 0, pair.second.numV); - global::renderEngine->openglStateCache().resetLineState(); - break; - case Point: - glDrawArrays(GL_POINTS, 0, pair.second.numV); - break; - default: - break; - } + + // Always render as lines + glLineWidth(_lineWidth); + glDrawArrays(GL_LINE_STRIP, 0, pair.second.numV); + global::renderEngine->openglStateCache().resetLineState(); } } @@ -251,7 +246,7 @@ void RenderableConstellationLines::render(const RenderData& data, RendererTasks& const glm::dmat4 projectionMatrix = data.camera.projectionMatrix(); if (_hasSpeckFile) { - renderMeshes(data, modelViewMatrix, projectionMatrix); + renderConstellations(data, modelViewMatrix, projectionMatrix); } RenderableConstellation::render(data, tasks); @@ -286,10 +281,10 @@ bool RenderableConstellationLines::readSpeckFile() { return false; } - const float scale = static_cast(toMeter(_unit)); + const float scale = static_cast(toMeter(_constellationUnit)); double maxRadius = 0.0; - int meshIndex = 0; + int lineIndex = 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 @@ -324,8 +319,8 @@ bool RenderableConstellationLines::readSpeckFile() { // and style is solid, wire or point (for now we support only wire) std::stringstream str(line); - RenderingMesh mesh; - mesh.meshIndex = meshIndex; + ConstellationLine constellationLine; + constellationLine.lineIndex = lineIndex; std::string dummy; str >> dummy; // mesh command @@ -334,28 +329,11 @@ bool RenderableConstellationLines::readSpeckFile() { do { if (dummy == "-t") { dummy.clear(); - str >> mesh.textureIndex; // texture index + str >> constellationLine.textureIndex; // texture index } else if (dummy == "-c") { dummy.clear(); - str >> mesh.colorIndex; // color index command - } - else if (dummy == "-s") { - dummy.clear(); - str >> dummy; // style value command - if (dummy == "solid") { - mesh.style = Solid; - } - else if (dummy == "wire") { - mesh.style = Wire; - } - else if (dummy == "point") { - mesh.style = Point; - } - else { - mesh.style = INVALID; - break; - } + str >> constellationLine.colorIndex; // color index command } dummy.clear(); str >> dummy; @@ -371,21 +349,21 @@ bool RenderableConstellationLines::readSpeckFile() { if (dummyU == "id") { ghoul::trimWhitespace(dummyV); - mesh.identifier = constellationFullName(dummyV); + constellationLine.identifier = constellationFullName(dummyV); // Dimensions are specified in the next line as usual std::getline(file, line); std::stringstream dim(line); - dim >> mesh.numU; // numU - dim >> mesh.numV; // numV + dim >> constellationLine.numU; // numU + dim >> constellationLine.numV; // numV } else { - mesh.numU = stoi(dummyU); - mesh.numV = stoi(dummyV); + constellationLine.numU = stoi(dummyU); + constellationLine.numV = stoi(dummyV); } // We can now read the vertices data: - for (int l = 0; l < mesh.numU * mesh.numV; ++l) { + for (int l = 0; l < constellationLine.numU * constellationLine.numV; ++l) { std::getline(file, line); if (line.substr(0, 1) == "}") { break; @@ -407,13 +385,13 @@ bool RenderableConstellationLines::readSpeckFile() { GLfloat scaledValue = value * scale; pos[i] = scaledValue; - mesh.vertices.push_back(scaledValue); + constellationLine.vertices.push_back(scaledValue); } if (!success) { LERROR(fmt::format( "Failed reading position on line {} of mesh {} in file: '{}'. " - "Stopped reading mesh data", l, meshIndex, _speckFile + "Stopped reading mesh data", l, lineIndex, _speckFile )); break; } @@ -440,7 +418,7 @@ bool RenderableConstellationLines::readSpeckFile() { std::getline(file, line); if (line.substr(0, 1) == "}") { - _renderingMeshesMap.insert({ meshIndex++, mesh }); + _renderingConstellationsMap.insert({ lineIndex++, constellationLine }); } else { return false; @@ -452,13 +430,13 @@ bool RenderableConstellationLines::readSpeckFile() { return true; } -void RenderableConstellationLines::createMeshes() { +void RenderableConstellationLines::createConstellations() { if (!(_dataIsDirty && _hasSpeckFile)) { return; } LDEBUG("Creating planes"); - for (std::pair& p : _renderingMeshesMap) { + for (std::pair& p : _renderingConstellationsMap) { for (int i = 0; i < p.second.numU; ++i) { GLuint vao; glGenVertexArrays(1, &vao); diff --git a/modules/space/rendering/renderableconstellationlines.h b/modules/space/rendering/renderableconstellationlines.h index 985ebaaac3..0742ce50c3 100644 --- a/modules/space/rendering/renderableconstellationlines.h +++ b/modules/space/rendering/renderableconstellationlines.h @@ -27,16 +27,6 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include @@ -69,15 +59,10 @@ public: static documentation::Documentation Documentation(); private: - enum MeshType { - Solid = 0, - Wire = 1, - Point = 2, - INVALID = 9 - }; - - struct RenderingMesh { - int meshIndex; + struct ConstellationLine { + bool isEnabled = true; + std::string identifier; + int lineIndex; int colorIndex; int textureIndex; // From: Partiview User's Guide @@ -90,47 +75,41 @@ private: // then numU numV will both equal 21 int numU; int numV; - MeshType style; std::vector vaoArray; std::vector vboArray; std::vector vertices; - bool isEnabled = true; - std::string identifier; }; - void createMeshes(); - void renderMeshes(const RenderData& data, const glm::dmat4& modelViewMatrix, + void createConstellations(); + void renderConstellations(const RenderData& data, const glm::dmat4& modelViewMatrix, const glm::dmat4& projectionMatrix); bool loadData(); bool readSpeckFile(); /** - * Callback method that gets triggered when _selectedMeshes - * changes. + * Callback method that gets triggered when _constellationSelection + * changes */ - void selectionPropertyHasChanged(); + void selectionPropertyHasChanged() override; bool _hasSpeckFile = false; bool _dataIsDirty = true; - bool _textColorIsDirty = true; - std::vector _assetSelectedMeshes; properties::BoolProperty _drawElements; - ghoul::opengl::ProgramObject* _program = nullptr; + std::unique_ptr _program = nullptr; UniformCache(modelViewTransform, projectionTransform, alphaValue, color) _uniformCache; - std::shared_ptr _font = nullptr; std::string _speckFile; - DistanceUnit _unit = DistanceUnit::Parsec; + DistanceUnit _constellationUnit = DistanceUnit::Parsec; std::vector _fullData; - std::unordered_map _meshColorMap; - std::unordered_map _renderingMeshesMap; + std::unordered_map _constellationColorMap; + std::unordered_map _renderingConstellationsMap; }; } // namespace openspace diff --git a/modules/space/shaders/constellationbounds_fs.glsl b/modules/space/shaders/constellationbounds_fs.glsl index 52237023b8..0d138b106d 100644 --- a/modules/space/shaders/constellationbounds_fs.glsl +++ b/modules/space/shaders/constellationbounds_fs.glsl @@ -28,13 +28,18 @@ in vec4 vs_position; uniform vec3 color; +uniform float alphaValue; Fragment getFragment() { - vec4 position = vs_position; - Fragment frag; - frag.color = vec4(color, 1.0); + if (alphaValue == 0.0) { + discard; + } + + vec4 position = vs_position; + + frag.color = vec4(color, alphaValue); frag.depth = pscDepth(position); return frag; From ceaf85f606f656acf9c0894428d1a70a6346b36d Mon Sep 17 00:00:00 2001 From: Malin E Date: Tue, 9 Aug 2022 14:28:16 +0200 Subject: [PATCH 13/23] Some more cleanup --- .../rendering/renderableconstellation.cpp | 3 - .../renderableconstellationbounds.cpp | 2 - .../renderableconstellationlines.cpp | 209 ++++-------------- .../rendering/renderableconstellationlines.h | 6 +- 4 files changed, 40 insertions(+), 180 deletions(-) diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index 4d7c96b101..cd60d9cc17 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -34,12 +33,10 @@ #include #include #include -#include #include #include #include #include -#include "SpiceUsr.h" namespace { constexpr int RenderOptionViewDirection = 0; diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index a0ac82f046..4d1756fa05 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -25,13 +25,11 @@ #include #include -#include #include #include #include #include #include -#include #include #include #include diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index 6f46b952c8..2e6e0456d5 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -25,25 +25,16 @@ #include #include -#include #include #include -#include #include #include #include -#include -#include #include -#include -#include #include #include #include -#include -#include #include -#include #include #include #include @@ -179,10 +170,8 @@ void RenderableConstellationLines::deinitialize() { void RenderableConstellationLines::deinitializeGL() { for (const std::pair& pair : _renderingConstellationsMap) { - for (int i = 0; i < pair.second.numU; ++i) { - glDeleteVertexArrays(1, &pair.second.vaoArray[i]); - glDeleteBuffers(1, &pair.second.vboArray[i]); - } + glDeleteVertexArrays(1, &pair.second.vaoArray); + glDeleteBuffers(1, &pair.second.vboArray); } if (_program) { @@ -197,7 +186,6 @@ void RenderableConstellationLines::renderConstellations(const RenderData&, { glEnablei(GL_BLEND, 0); glBlendFunc(GL_SRC_ALPHA, GL_ONE); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(false); glEnable(GL_DEPTH_TEST); @@ -218,14 +206,12 @@ void RenderableConstellationLines::renderConstellations(const RenderData&, _uniformCache.color, _constellationColorMap[pair.second.colorIndex] ); - for (size_t i = 0; i < pair.second.vaoArray.size(); ++i) { - glBindVertexArray(pair.second.vaoArray[i]); - // Always render as lines - glLineWidth(_lineWidth); - glDrawArrays(GL_LINE_STRIP, 0, pair.second.numV); - global::renderEngine->openglStateCache().resetLineState(); - } + glBindVertexArray(pair.second.vaoArray); + + glLineWidth(_lineWidth); + glDrawArrays(GL_LINE_STRIP, 0, pair.second.numV); + global::renderEngine->openglStateCache().resetLineState(); } glBindVertexArray(0); @@ -327,11 +313,7 @@ bool RenderableConstellationLines::readSpeckFile() { dummy.clear(); str >> dummy; // texture index command? do { - if (dummy == "-t") { - dummy.clear(); - str >> constellationLine.textureIndex; // texture index - } - else if (dummy == "-c") { + if (dummy == "-c") { dummy.clear(); str >> constellationLine.colorIndex; // color index command } @@ -340,30 +322,23 @@ bool RenderableConstellationLines::readSpeckFile() { } while (dummy != "{"); std::getline(file, line); - std::stringstream dimOrName(line); - std::string dummyU, dummyV; - // Try to read name of mesh if it exist - dimOrName >> dummyU; // numU or "id" - std::getline(dimOrName, dummyV); // numV or the identifier of the mesh + // Read the identifier + std::stringstream name(line); + std::string identifier; - if (dummyU == "id") { - ghoul::trimWhitespace(dummyV); - constellationLine.identifier = constellationFullName(dummyV); + name >> dummy; + std::getline(name, identifier); + ghoul::trimWhitespace(identifier); + constellationLine.identifier = constellationFullName(identifier); - // Dimensions are specified in the next line as usual - std::getline(file, line); - std::stringstream dim(line); - dim >> constellationLine.numU; // numU - dim >> constellationLine.numV; // numV - } - else { - constellationLine.numU = stoi(dummyU); - constellationLine.numV = stoi(dummyV); - } + // Read the number of vertices + std::getline(file, line); + std::stringstream dim(line); + dim >> constellationLine.numV; // We can now read the vertices data: - for (int l = 0; l < constellationLine.numU * constellationLine.numV; ++l) { + for (int l = 0; l < constellationLine.numV; ++l) { std::getline(file, line); if (line.substr(0, 1) == "}") { break; @@ -399,21 +374,6 @@ bool RenderableConstellationLines::readSpeckFile() { // Check if new max radius const double r = glm::length(glm::dvec3(pos)); maxRadius = std::max(maxRadius, r); - - // OLD CODE: - // (2022-03-23, emmbr) None of our files included texture coordinates, - // and if they would they would still not be used by the shader - //for (int i = 0; i < 7; ++i) { - // GLfloat value; - // lineData >> value; - // bool errorReading = lineData.rdstate() & std::ifstream::failbit; - // if (!errorReading) { - // mesh.vertices.push_back(value); - // } - // else { - // break; - // } - //} } std::getline(file, line); @@ -434,121 +394,28 @@ void RenderableConstellationLines::createConstellations() { if (!(_dataIsDirty && _hasSpeckFile)) { return; } - LDEBUG("Creating planes"); + LDEBUG("Creating constellations"); for (std::pair& p : _renderingConstellationsMap) { - for (int i = 0; i < p.second.numU; ++i) { - GLuint vao; - glGenVertexArrays(1, &vao); - p.second.vaoArray.push_back(vao); + GLuint vao; + glGenVertexArrays(1, &vao); + p.second.vaoArray = vao; - GLuint vbo; - glGenBuffers(1, &vbo); - p.second.vboArray.push_back(vbo); + GLuint vbo; + glGenBuffers(1, &vbo); + p.second.vboArray = vbo; - glBindVertexArray(vao); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - //glBufferData(GL_ARRAY_BUFFER, it->second.numV * sizeof(GLfloat), - glBufferData( - GL_ARRAY_BUFFER, - p.second.vertices.size() * sizeof(GLfloat), - &p.second.vertices[0], - GL_STATIC_DRAW - ); - // in_position - glEnableVertexAttribArray(0); - // (2022-03-23, emmbr) This code was actually never used. We only read three - // values per line and did not handle any texture cooridnates, even if there - // would have been some in the file - //// U and V may not be given by the user - //if (p.second.vertices.size() / (p.second.numU * p.second.numV) > 3) { - // glVertexAttribPointer( - // 0, - // 3, - // GL_FLOAT, - // GL_FALSE, - // sizeof(GLfloat) * 5, - // reinterpret_cast(sizeof(GLfloat) * i * p.second.numV) - // ); - - // // texture coords - // glEnableVertexAttribArray(1); - // glVertexAttribPointer( - // 1, - // 2, - // GL_FLOAT, - // GL_FALSE, - // sizeof(GLfloat) * 7, - // reinterpret_cast(sizeof(GLfloat) * 3 * i * p.second.numV) - // ); - //} - //else { // no U and V: - glVertexAttribPointer( - 0, - 3, - GL_FLOAT, - GL_FALSE, - 0, - reinterpret_cast(sizeof(GLfloat) * 3 * i * p.second.numV) - ); - //} - } - - // Grid: we need columns - if (p.second.numU > 1) { - for (int i = 0; i < p.second.numV; ++i) { - GLuint cvao; - glGenVertexArrays(1, &cvao); - p.second.vaoArray.push_back(cvao); - - GLuint cvbo; - glGenBuffers(1, &cvbo); - p.second.vboArray.push_back(cvbo); - - glBindVertexArray(cvao); - glBindBuffer(GL_ARRAY_BUFFER, cvbo); - glBufferData( - GL_ARRAY_BUFFER, - p.second.vertices.size() * sizeof(GLfloat), - &p.second.vertices[0], - GL_STATIC_DRAW - ); - // in_position - glEnableVertexAttribArray(0); - // U and V may not be given by the user - if (p.second.vertices.size() / (p.second.numU * p.second.numV) > 3) { - glVertexAttribPointer( - 0, - 3, - GL_FLOAT, - GL_FALSE, - p.second.numV * sizeof(GLfloat) * 5, - reinterpret_cast(sizeof(GLfloat) * i) - ); - - // texture coords - glEnableVertexAttribArray(1); - glVertexAttribPointer( - 1, - 2, - GL_FLOAT, - GL_FALSE, - p.second.numV * sizeof(GLfloat) * 7, - reinterpret_cast(sizeof(GLfloat) * 3 * i) - ); - } - else { // no U and V: - glVertexAttribPointer( - 0, - 3, - GL_FLOAT, - GL_FALSE, - p.second.numV * sizeof(GLfloat) * 3, - reinterpret_cast(sizeof(GLfloat) * 3 * i) - ); - } - } - } + glBindVertexArray(vao); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData( + GL_ARRAY_BUFFER, + p.second.vertices.size() * sizeof(GLfloat), + p.second.vertices.data(), + GL_STATIC_DRAW + ); + // in_position + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); } glBindVertexArray(0); diff --git a/modules/space/rendering/renderableconstellationlines.h b/modules/space/rendering/renderableconstellationlines.h index 0742ce50c3..f99a286729 100644 --- a/modules/space/rendering/renderableconstellationlines.h +++ b/modules/space/rendering/renderableconstellationlines.h @@ -64,7 +64,6 @@ private: std::string identifier; int lineIndex; int colorIndex; - int textureIndex; // From: Partiview User's Guide // Brian Abbott // Hayden Planetarium American Museum of Natural History New York, USA @@ -73,10 +72,9 @@ private: // numV will equal the number of points to connect. // If you want a square, 4000×4000 grid with lines every 200 units, // then numU numV will both equal 21 - int numU; int numV; - std::vector vaoArray; - std::vector vboArray; + GLuint vaoArray; + GLuint vboArray; std::vector vertices; }; From 87a45e7376f1f05dd70ac21df4f5cf735d48a42a Mon Sep 17 00:00:00 2001 From: Malin E Date: Tue, 9 Aug 2022 17:01:41 +0200 Subject: [PATCH 14/23] Fix asset selection of constellations --- .../digitaluniverse/constellationbounds.asset | 4 +-- .../digitaluniverse/constellations.asset | 8 +++--- .../rendering/renderableconstellation.cpp | 20 -------------- .../space/rendering/renderableconstellation.h | 9 ++++--- .../renderableconstellationbounds.cpp | 23 +++++++++++++--- .../rendering/renderableconstellationbounds.h | 1 - .../renderableconstellationlines.cpp | 27 ++++++++++++++++--- .../rendering/renderableconstellationlines.h | 1 - .../space/shaders/constellationlines_fs.glsl | 3 +-- 9 files changed, 55 insertions(+), 41 deletions(-) diff --git a/data/assets/scene/digitaluniverse/constellationbounds.asset b/data/assets/scene/digitaluniverse/constellationbounds.asset index 273fad59da..f3ce0deb86 100644 --- a/data/assets/scene/digitaluniverse/constellationbounds.asset +++ b/data/assets/scene/digitaluniverse/constellationbounds.asset @@ -1,7 +1,7 @@ local data = asset.syncedResource({ - Name = "Constellation Bounds Data", + Name = "Constellation Files", Type = "HttpSynchronization", - Identifier = "digitaluniverse_constellationbounds_data", + Identifier = "digitaluniverse_constellations_data", Version = 1 }) diff --git a/data/assets/scene/digitaluniverse/constellations.asset b/data/assets/scene/digitaluniverse/constellations.asset index 62f4d4f1e8..9515e8fb29 100644 --- a/data/assets/scene/digitaluniverse/constellations.asset +++ b/data/assets/scene/digitaluniverse/constellations.asset @@ -1,8 +1,8 @@ local speck = asset.syncedResource({ - Name = "Constellation Speck Files", + Name = "Constellation Files", Type = "HttpSynchronization", - Identifier = "digitaluniverse_constellations_speck", - Version = 2 + Identifier = "digitaluniverse_constellations_data", + Version = 1 }) local constellationsExtragalactic = { @@ -34,7 +34,7 @@ local constellations = { Opacity = 0.3, File = speck .. "constellations.speck", LabelFile = speck .. "constellations.label", - ConstellationNamesFile = "C:/Users/malej60/Documents/Sync/http/digitaluniverse_constellationbounds_data/1/constellations.dat", + ConstellationNamesFile = speck .. "constellations.dat", TextColor = { 0.8, 0.8, 0.8 }, TextOpacity = 0.3, TextSize = 14.5, diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index cd60d9cc17..eaf49d7bf3 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -300,26 +300,6 @@ void RenderableConstellation::fillSelectionProperty() { void RenderableConstellation::initialize() { loadConstellationFile(); - if (!_assetSelectedConstellations.empty()) { - const std::vector options = _constellationSelection.options(); - std::set selectedConstellations; - - for (const std::string& s : _assetSelectedConstellations) { - const auto it = std::find(options.begin(), options.end(), s); - if (it == options.end()) { - // The user has specified a mesh name that doesn't exist - LWARNINGC( - "RenderableConstellation", - fmt::format("Option '{}' not found in list of meshes", s) - ); - } - else { - selectedConstellations.insert(s); - } - } - _constellationSelection = selectedConstellations; - } - if (!_hasLabel) { return; } diff --git a/modules/space/rendering/renderableconstellation.h b/modules/space/rendering/renderableconstellation.h index 514cffe511..2fed346b4e 100644 --- a/modules/space/rendering/renderableconstellation.h +++ b/modules/space/rendering/renderableconstellation.h @@ -50,7 +50,6 @@ public: virtual void initialize() override; virtual void initializeGL() override = 0; - virtual void deinitialize() override = 0; virtual void deinitializeGL() override = 0; virtual bool isReady() const override = 0; @@ -81,6 +80,10 @@ protected: // Property that stores all constellations chosen by the user to be drawn properties::SelectionProperty _constellationSelection; + // Temporary storage of which constellations should be rendered as stated in the + // asset file + std::vector _assetSelectedConstellations; + // Label text settings bool _hasLabel = false; speck::Labelset _labelset; @@ -91,9 +94,7 @@ private: // key = abbreviation, value = full name std::map _constellationNamesTranslation; - // Temporary storage of which constellations should be rendered as stated in the - // asset file - std::vector _assetSelectedConstellations; + /** * Loads the file specified in _constellationNamesFilename that contains diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index 4d1756fa05..df3aab3106 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -93,6 +93,26 @@ void RenderableConstellationBounds::initialize() { RenderableConstellation::initialize(); loadVertexFile(); + + if (!_assetSelectedConstellations.empty()) { + const std::vector options = _constellationSelection.options(); + std::set selectedConstellations; + + for (const std::string& s : _assetSelectedConstellations) { + const auto it = std::find(options.begin(), options.end(), s); + if (it == options.end()) { + // The user has specified a mesh name that doesn't exist + LWARNINGC( + "RenderableConstellation", + fmt::format("Option '{}' not found in list of meshes", s) + ); + } + else { + selectedConstellations.insert(s); + } + } + _constellationSelection = selectedConstellations; + } } void RenderableConstellationBounds::initializeGL() { @@ -121,9 +141,6 @@ void RenderableConstellationBounds::initializeGL() { glBindVertexArray(0); } -void RenderableConstellationBounds::deinitialize() { -} - void RenderableConstellationBounds::deinitializeGL() { glDeleteBuffers(1, &_vbo); _vbo = 0; diff --git a/modules/space/rendering/renderableconstellationbounds.h b/modules/space/rendering/renderableconstellationbounds.h index eacb03aca9..3925e37c6e 100644 --- a/modules/space/rendering/renderableconstellationbounds.h +++ b/modules/space/rendering/renderableconstellationbounds.h @@ -48,7 +48,6 @@ public: void initialize() override; void initializeGL() override; - void deinitialize() override; void deinitializeGL() override; bool isReady() const override; diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index 2e6e0456d5..8aea735267 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -151,6 +151,26 @@ void RenderableConstellationLines::initialize() { if (!success) { throw ghoul::RuntimeError("Error loading data"); } + + if (!_assetSelectedConstellations.empty()) { + const std::vector options = _constellationSelection.options(); + std::set selectedConstellations; + + for (const std::string& s : _assetSelectedConstellations) { + const auto it = std::find(options.begin(), options.end(), s); + if (it == options.end()) { + // The user has specified a mesh name that doesn't exist + LWARNINGC( + "RenderableConstellation", + fmt::format("Option '{}' not found in list of meshes", s) + ); + } + else { + selectedConstellations.insert(s); + } + } + _constellationSelection = selectedConstellations; + } } void RenderableConstellationLines::initializeGL() { @@ -165,11 +185,10 @@ void RenderableConstellationLines::initializeGL() { createConstellations(); } -void RenderableConstellationLines::deinitialize() { -} - void RenderableConstellationLines::deinitializeGL() { - for (const std::pair& pair : _renderingConstellationsMap) { + for (const std::pair& pair : + _renderingConstellationsMap) + { glDeleteVertexArrays(1, &pair.second.vaoArray); glDeleteBuffers(1, &pair.second.vboArray); } diff --git a/modules/space/rendering/renderableconstellationlines.h b/modules/space/rendering/renderableconstellationlines.h index f99a286729..f10c359974 100644 --- a/modules/space/rendering/renderableconstellationlines.h +++ b/modules/space/rendering/renderableconstellationlines.h @@ -48,7 +48,6 @@ public: void initialize() override; void initializeGL() override; - void deinitialize() override; void deinitializeGL() override; bool isReady() const override; diff --git a/modules/space/shaders/constellationlines_fs.glsl b/modules/space/shaders/constellationlines_fs.glsl index 243d5c66a5..f8cfcda68d 100644 --- a/modules/space/shaders/constellationlines_fs.glsl +++ b/modules/space/shaders/constellationlines_fs.glsl @@ -33,7 +33,6 @@ uniform float alphaValue; Fragment getFragment() { Fragment frag; - if (alphaValue == 0.0) { discard; } @@ -44,6 +43,6 @@ Fragment getFragment() { // JCC: Need to change the position to camera space frag.gPosition = vs_positionViewSpace; frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0); - + return frag; } From 5bdd3d0f8c4b17c6f904ce55a1a33ad65596145a Mon Sep 17 00:00:00 2001 From: Malin E Date: Wed, 10 Aug 2022 13:57:47 +0200 Subject: [PATCH 15/23] Make the Constellations name file optional --- .../digitaluniverse/constellationbounds.asset | 4 +-- .../digitaluniverse/constellations.asset | 18 ++++++++---- .../rendering/renderableconstellation.cpp | 29 ++++++++++++------- .../space/rendering/renderableconstellation.h | 2 -- .../renderableconstellationbounds.cpp | 7 +++-- .../renderableconstellationlines.cpp | 23 ++++++++------- .../rendering/renderableconstellationlines.h | 10 +------ 7 files changed, 50 insertions(+), 43 deletions(-) diff --git a/data/assets/scene/digitaluniverse/constellationbounds.asset b/data/assets/scene/digitaluniverse/constellationbounds.asset index f3ce0deb86..4003e15b39 100644 --- a/data/assets/scene/digitaluniverse/constellationbounds.asset +++ b/data/assets/scene/digitaluniverse/constellationbounds.asset @@ -16,7 +16,7 @@ local object = { Type = "RenderableConstellationBounds", Enabled = false, File = data .. "bound_20.dat", - ConstellationNamesFile = data .. "constellations.dat" + ConstellationNamesFile = data .. "constellations.dat", -- ConstellationSelection = zodiacs }, Transform = { @@ -52,7 +52,7 @@ asset.export(object) asset.meta = { Name = "Constellation Bounds", - Version = "1.1", + Version = "1.2", Description = [[DU asset providing a Spherical mesh dividing the sky into regions that fit the constellations]], Author = "Brian Abbott (AMNH)", diff --git a/data/assets/scene/digitaluniverse/constellations.asset b/data/assets/scene/digitaluniverse/constellations.asset index 9515e8fb29..401f9ae594 100644 --- a/data/assets/scene/digitaluniverse/constellations.asset +++ b/data/assets/scene/digitaluniverse/constellations.asset @@ -5,6 +5,11 @@ local speck = asset.syncedResource({ Version = 1 }) +local zodiacs = { + "Cancer", "Taurus", "Pisces", "Aries", "Libra", "Aquarius", "Capricornus", "Scorpius", + "Virgo", "Sagittarius", "Gemini", "Leo" +} + local constellationsExtragalactic = { Identifier = "ConstellationsExtragalactic", Renderable = { @@ -39,12 +44,13 @@ local constellations = { TextOpacity = 0.3, TextSize = 14.5, TextMinMaxSize = { 8, 170 }, - LabelUnit = "pc", ConstellationColor = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, - ConstellationUnit = "pc" + LabelUnit = "pc", + ConstellationUnit = "pc", + -- ConstellationSelection = zodiacs }, GUI = { - Name = "Constellations", + Name = "Constellations", Path = "/Milky Way/Constellations", Description = [[Census 88 constellations and labels. DU Version 2.3.
These modern constellations are largely based on those of the Babylonians and @@ -62,12 +68,12 @@ asset.onInitialize(function() openspace.addSceneGraphNode(constellationsExtragalactic) openspace.addSceneGraphNode(constellations) end) - + asset.onDeinitialize(function() openspace.removeSceneGraphNode(constellations) openspace.removeSceneGraphNode(constellationsExtragalactic) end) - + asset.export(constellationsExtragalactic) asset.export(constellations) @@ -75,7 +81,7 @@ asset.export(constellations) asset.meta = { Name = "Constellations", - Version = "1.1", + Version = "1.2", Description = "Digital Universe asset for constellation lines", Author = "Brian Abbott (AMNH)", URL = "https://www.amnh.org/research/hayden-planetarium/digital-universe", diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index eaf49d7bf3..bd483546f7 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -45,7 +45,7 @@ namespace { constexpr openspace::properties::Property::PropertyInfo TextColorInfo = { "TextColor", "Text Color", - "The text color for the astronomical object" + "The text color of the labels for the constellations" }; constexpr openspace::properties::Property::PropertyInfo TextOpacityInfo = { @@ -58,28 +58,27 @@ namespace { constexpr openspace::properties::Property::PropertyInfo TextSizeInfo = { "TextSize", "Text Size", - "The text size for the astronomical object labels" + "The text size of the labels for the constellations" }; constexpr openspace::properties::Property::PropertyInfo LabelFileInfo = { "LabelFile", "Label File", - "The path to the label file that contains information about the astronomical " - "objects being rendered" + "The path to the label file that contains information about the constellations" }; constexpr openspace::properties::Property::PropertyInfo LabelMinMaxSizeInfo = { "TextMinMaxSize", "Text Min/Max Size", - "The minimum and maximum size (in pixels) of the text for the labels for the " - "astronomical objects being rendered" + "The minimum and maximum size (in pixels) for the text of the labels for the " + "constellations" }; constexpr openspace::properties::Property::PropertyInfo ConstellationInfo = { "ConstellationFile", "Constellation File Path", "Specifies the file that contains the mapping between constellation " - "abbreviations and full name of the constellation. If this value is empty, the " + "abbreviations and full names of the constellations. If this value is empty, the " "abbreviations are used as the full names" }; @@ -118,7 +117,7 @@ namespace { std::optional drawLabels; // [[codegen::verbatim(ConstellationInfo.description)]] - std::string constellationNamesFile; + std::optional constellationNamesFile; // [[codegen::verbatim(TextColorInfo.description)]] std::optional textColor [[codegen::color()]]; @@ -197,7 +196,8 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio addProperty(_renderOption); // Read all files in the initialize() instead, multithreaded - _constellationNamesFilename = p.constellationNamesFile; + _constellationNamesFilename = + p.constellationNamesFile.value_or(_constellationNamesFilename); _constellationNamesFilename.onChange([&]() { loadConstellationFile(); }); addProperty(_constellationNamesFilename); @@ -244,6 +244,12 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio std::string RenderableConstellation::constellationFullName( const std::string& identifier) const { + if (_constellationNamesTranslation.empty() || identifier.empty()) { + std::string message = "List of constellations or the given identifier was empty"; + LWARNINGC("RenderableConstellation", message); + return ""; + } + try { return _constellationNamesTranslation.at(identifier); } @@ -321,7 +327,10 @@ void RenderableConstellation::initialize() { for (speck::Labelset::Entry& entry : _labelset.entries) { if (!entry.identifier.empty()) { - entry.text = constellationFullName(entry.identifier); + std::string fullName = constellationFullName(entry.identifier); + if (!fullName.empty()) { + entry.text = fullName; + } } } } diff --git a/modules/space/rendering/renderableconstellation.h b/modules/space/rendering/renderableconstellation.h index 2fed346b4e..7d2a88f14c 100644 --- a/modules/space/rendering/renderableconstellation.h +++ b/modules/space/rendering/renderableconstellation.h @@ -94,8 +94,6 @@ private: // key = abbreviation, value = full name std::map _constellationNamesTranslation; - - /** * Loads the file specified in _constellationNamesFilename that contains * the mapping between abbreviations and full names of constellations diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index df3aab3106..24bf422786 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -101,10 +101,10 @@ void RenderableConstellationBounds::initialize() { for (const std::string& s : _assetSelectedConstellations) { const auto it = std::find(options.begin(), options.end(), s); if (it == options.end()) { - // The user has specified a mesh name that doesn't exist + // The user has specified a constellation name that doesn't exist LWARNINGC( "RenderableConstellation", - fmt::format("Option '{}' not found in list of meshes", s) + fmt::format("Option '{}' not found in list of constellations", s) ); } else { @@ -258,7 +258,8 @@ bool RenderableConstellationBounds::loadVertexFile() { currentBound = ConstellationBound(); currentBound.isEnabled = true; currentBound.constellationAbbreviation = abbreviation; - currentBound.constellationFullName = constellationFullName(abbreviation); + std::string name = constellationFullName(abbreviation); + currentBound.constellationFullName = name.empty() ? abbreviation : name; currentBound.startIndex = static_cast(_vertexValues.size()); } diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index 8aea735267..c2ac4b2dc1 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -134,7 +134,7 @@ void RenderableConstellationLines::selectionPropertyHasChanged() { _renderingConstellationsMap) { pair.second.isEnabled = - _constellationSelection.isSelected(pair.second.identifier); + _constellationSelection.isSelected(pair.second.name); } } } @@ -159,10 +159,10 @@ void RenderableConstellationLines::initialize() { for (const std::string& s : _assetSelectedConstellations) { const auto it = std::find(options.begin(), options.end(), s); if (it == options.end()) { - // The user has specified a mesh name that doesn't exist + // The user has specified a constellation name that doesn't exist LWARNINGC( "RenderableConstellation", - fmt::format("Option '{}' not found in list of meshes", s) + fmt::format("Option '{}' not found in list of constellations", s) ); } else { @@ -318,10 +318,8 @@ bool RenderableConstellationLines::readSpeckFile() { } else { // mesh lines are structured as follows: - // mesh -t texnum -c colorindex -s style { - // where textnum is the index of the texture; + // mesh -c colorindex { // colorindex is the index of the color for the mesh - // and style is solid, wire or point (for now we support only wire) std::stringstream str(line); ConstellationLine constellationLine; @@ -343,13 +341,16 @@ bool RenderableConstellationLines::readSpeckFile() { std::getline(file, line); // Read the identifier - std::stringstream name(line); + std::stringstream id(line); std::string identifier; - name >> dummy; - std::getline(name, identifier); + id >> dummy; + std::getline(id, identifier); ghoul::trimWhitespace(identifier); - constellationLine.identifier = constellationFullName(identifier); + std::string name = constellationFullName(identifier); + if (!name.empty()) { + constellationLine.name = name; + } // Read the number of vertices std::getline(file, line); @@ -385,7 +386,7 @@ bool RenderableConstellationLines::readSpeckFile() { if (!success) { LERROR(fmt::format( "Failed reading position on line {} of mesh {} in file: '{}'. " - "Stopped reading mesh data", l, lineIndex, _speckFile + "Stopped reading constellation data", l, lineIndex, _speckFile )); break; } diff --git a/modules/space/rendering/renderableconstellationlines.h b/modules/space/rendering/renderableconstellationlines.h index f10c359974..e9fb792a6e 100644 --- a/modules/space/rendering/renderableconstellationlines.h +++ b/modules/space/rendering/renderableconstellationlines.h @@ -60,17 +60,9 @@ public: private: struct ConstellationLine { bool isEnabled = true; - std::string identifier; + std::string name; int lineIndex; int colorIndex; - // From: Partiview User's Guide - // Brian Abbott - // Hayden Planetarium American Museum of Natural History New York, USA - // "Specifies the dimensions of the mesh" - // "If you wish to draw a line between points, then numU will be 1 while - // numV will equal the number of points to connect. - // If you want a square, 4000×4000 grid with lines every 200 units, - // then numU numV will both equal 21 int numV; GLuint vaoArray; GLuint vboArray; From a63a9c1ca93401b4982e00079f5009cee466a880 Mon Sep 17 00:00:00 2001 From: Malin E Date: Wed, 24 Aug 2022 16:56:54 +0200 Subject: [PATCH 16/23] Convert the extragalactic constellations to use new class --- data/assets/scene/digitaluniverse/constellations.asset | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/data/assets/scene/digitaluniverse/constellations.asset b/data/assets/scene/digitaluniverse/constellations.asset index 401f9ae594..1dafb17052 100644 --- a/data/assets/scene/digitaluniverse/constellations.asset +++ b/data/assets/scene/digitaluniverse/constellations.asset @@ -13,17 +13,20 @@ local zodiacs = { local constellationsExtragalactic = { Identifier = "ConstellationsExtragalactic", Renderable = { - Type = "RenderableDUMeshes", + Type = "RenderableConstellationLines", Enabled = false, Opacity = 0.4, File = speck .. "constellationsEXGAL.speck", LabelFile = speck .. "constellationsEXGAL.label", + ConstellationNamesFile = speck .. "constellations.dat", TextColor = { 0.8, 0.8, 0.8 }, TextOpacity = 0.4, TextSize = 20.0, TextMinMaxSize = { 20, 30 }, - MeshColor = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, - Unit = "Mpc" + ConstellationColor = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, + LabelUnit = "Mpc", + ConstellationUnit = "Mpc", + -- ConstellationSelection = zodiacs }, GUI = { Name = "Constellations (Extragalactic)", From b8f365e6dec5d1e82be2ee51464d3fedb779b830 Mon Sep 17 00:00:00 2001 From: Malin E Date: Thu, 25 Aug 2022 08:57:35 +0200 Subject: [PATCH 17/23] Name all constellations from the same source --- .../constellations/constellation_art.asset | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/data/assets/scene/milkyway/constellations/constellation_art.asset b/data/assets/scene/milkyway/constellations/constellation_art.asset index d96754f498..94fa56bb4f 100644 --- a/data/assets/scene/milkyway/constellations/constellation_art.asset +++ b/data/assets/scene/milkyway/constellations/constellation_art.asset @@ -2,12 +2,48 @@ local constellationsCSV = asset.localResource("constellation_data.csv") local transforms = asset.require("scene/solarsystem/sun/transforms") local images = asset.syncedResource({ - Name = "Constellation Images", - Type = "HttpSynchronization", - Identifier = "constellation_images", - Version = 4 + Name = "Constellation Images", + Type = "HttpSynchronization", + Identifier = "constellation_images", + Version = 4 }) +local data = asset.syncedResource({ + Name = "Constellation Files", + Type = "HttpSynchronization", + Identifier = "digitaluniverse_constellations_data", + Version = 1 +}) + + +-- Function that returns the full name of a constellation given its abbreviation +-- The function uses the constellations.dat file to find the name +-- If the file does not exist or if a match could not be found, it returns nil +local findFullName = function(abbreviation) + local namesFile = data .. "constellations.dat" + + local file = io.open(namesFile, "r") + if file ~= nil then + io.close(file) + for line in io.lines(namesFile) do + local index, length = string.find(line, abbreviation) + + if index ~= nil and index < 4 then + return string.sub(line, length + 1) + end + + local fullLine = line + local lowerLine = string.lower(line) + index, length = string.find(lowerLine, string.lower(abbreviation)) + if index ~= nil and index < 4 then + return string.sub(fullLine, length + 1) + end + end + end + return nil +end + + --function that reads the file local createConstellations = function (baseIdentifier, guiPath, constellationfile) local genConstellations = {}; @@ -30,6 +66,13 @@ local createConstellations = function (baseIdentifier, guiPath, constellationfil local normy = y/magVec local normz = z/magVec + -- Use the full name in the data constellations.dat if possible + -- Otherwise, use the given name in the constellation_data.csv file + local foundName = findFullName(abbreviation) + if foundName ~= nil then + name = foundName + end + group = (group == "" and globe or group) local aconstellation = { From 40267804bdba7f315b87d4f0390107d736899230 Mon Sep 17 00:00:00 2001 From: Malin E Date: Thu, 25 Aug 2022 13:48:48 +0200 Subject: [PATCH 18/23] Some clean up --- .../constellations/constellation_art.asset | 2 +- .../space/rendering/renderableconstellation.cpp | 17 ++++++++--------- .../rendering/renderableconstellationbounds.cpp | 6 +++--- .../rendering/renderableconstellationlines.cpp | 17 ++++++++++------- modules/space/spacemodule.cpp | 2 +- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/data/assets/scene/milkyway/constellations/constellation_art.asset b/data/assets/scene/milkyway/constellations/constellation_art.asset index 94fa56bb4f..0bf65abd00 100644 --- a/data/assets/scene/milkyway/constellations/constellation_art.asset +++ b/data/assets/scene/milkyway/constellations/constellation_art.asset @@ -215,7 +215,7 @@ end asset.meta = { Name = "Constellation Images", - Version = "1.1", + Version = "1.2", Description = "Artistic images depicting the constellations", Author = "James Hedberg", URL = "http://jameshedberg.com", diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellation.cpp index bd483546f7..01215c0a68 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellation.cpp @@ -85,7 +85,7 @@ namespace { constexpr openspace::properties::Property::PropertyInfo LineWidthInfo = { "LineWidth", "Line Width", - "The line width of the constellation " + "The line width of the constellation" }; constexpr openspace::properties::Property::PropertyInfo DrawLabelInfo = { @@ -117,7 +117,7 @@ namespace { std::optional drawLabels; // [[codegen::verbatim(ConstellationInfo.description)]] - std::optional constellationNamesFile; + std::optional constellationNamesFile; // [[codegen::verbatim(TextColorInfo.description)]] std::optional textColor [[codegen::color()]]; @@ -185,7 +185,7 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio _renderOption.addOption(RenderOptionViewDirection, "Camera View Direction"); _renderOption.addOption(RenderOptionPositionNormal, "Camera Position Normal"); - // @TODO (abock. 2021-01-31) In the other DU classes, this is done with an enum, and + // @TODO (abock. 2021-01-31) In the other classes, this is done with an enum, and // doing it based on the fisheye rendering seems a bit brittle? if (global::windowDelegate->isFisheyeRendering()) { _renderOption = RenderOptionPositionNormal; @@ -195,9 +195,11 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio } addProperty(_renderOption); - // Read all files in the initialize() instead, multithreaded - _constellationNamesFilename = - p.constellationNamesFile.value_or(_constellationNamesFilename); + // Avoid reading files here, instead do it in multithreaded initialize() + if (p.constellationNamesFile.has_value()) { + _constellationNamesFilename = + absPath(p.constellationNamesFile.value().string()).string(); + } _constellationNamesFilename.onChange([&]() { loadConstellationFile(); }); addProperty(_constellationNamesFilename); @@ -275,7 +277,6 @@ void RenderableConstellation::loadConstellationFile() { file.open(absPath(_constellationNamesFilename)); std::string line; - int index = 0; while (file.good()) { std::getline(file, line); if (line.empty()) { @@ -290,8 +291,6 @@ void RenderableConstellation::loadConstellationFile() { std::getline(s, fullName); ghoul::trimWhitespace(fullName); _constellationNamesTranslation[abbreviation] = fullName; - - ++index; } fillSelectionProperty(); diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index 24bf422786..a1cafc053c 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -57,7 +57,7 @@ namespace { struct [[codegen::Dictionary(RenderableConstellationBounds)]] Parameters { // [[codegen::verbatim(VertexInfo.description)]] - std::string file; + std::filesystem::path file; // [[codegen::verbatim(ColorInfo.description)]] std::optional color [[codegen::color()]]; @@ -79,8 +79,8 @@ RenderableConstellationBounds::RenderableConstellationBounds( { const Parameters p = codegen::bake(dictionary); - // Avoid loading the vertex file here, do it in multithreded initialize() instead - _vertexFilename = p.file; + // Avoid reading files here, instead do it in multithreaded initialize() + _vertexFilename = absPath(p.file.string()).string(); _vertexFilename.onChange([&](){ loadVertexFile(); }); addProperty(_vertexFilename); diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index c2ac4b2dc1..659f346809 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -66,7 +66,7 @@ namespace { struct [[codegen::Dictionary(RenderableConstellationLines)]] Parameters { // The path to the SPECK file that contains constellation lines data - std::string file; + std::filesystem::path file; enum class [[codegen::map(openspace::DistanceUnit)]] Unit { Meter [[codegen::key("m")]], @@ -99,7 +99,7 @@ RenderableConstellationLines::RenderableConstellationLines( { const Parameters p = codegen::bake(dictionary); - _speckFile = absPath(p.file).string(); + _speckFile = absPath(p.file.string()).string(); _hasSpeckFile = true; _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); addProperty(_drawElements); @@ -140,7 +140,10 @@ void RenderableConstellationLines::selectionPropertyHasChanged() { } bool RenderableConstellationLines::isReady() const { - return (_program != nullptr) && !_renderingConstellationsMap.empty() && + if (!_hasLabel) { + return _program && !_renderingConstellationsMap.empty(); + } + return _program && !_renderingConstellationsMap.empty() && !_labelset.entries.empty(); } @@ -328,10 +331,9 @@ bool RenderableConstellationLines::readSpeckFile() { std::string dummy; str >> dummy; // mesh command dummy.clear(); - str >> dummy; // texture index command? + str >> dummy; // color index command? do { if (dummy == "-c") { - dummy.clear(); str >> constellationLine.colorIndex; // color index command } dummy.clear(); @@ -344,8 +346,9 @@ bool RenderableConstellationLines::readSpeckFile() { std::stringstream id(line); std::string identifier; - id >> dummy; - std::getline(id, identifier); + id >> dummy; // id command + dummy.clear(); + std::getline(id, identifier); // identifier ghoul::trimWhitespace(identifier); std::string name = constellationFullName(identifier); if (!name.empty()) { diff --git a/modules/space/spacemodule.cpp b/modules/space/spacemodule.cpp index 7084f12639..bb06bed639 100644 --- a/modules/space/spacemodule.cpp +++ b/modules/space/spacemodule.cpp @@ -82,7 +82,7 @@ void SpaceModule::internalInitialize(const ghoul::Dictionary& dictionary) { ); fRenderable->registerClass( "RenderableConstellationLines" - ); + ); fRenderable->registerClass("RenderableFluxNodes"); fRenderable->registerClass("RenderableHabitableZone"); fRenderable->registerClass("RenderableRings"); From 41d52f7f0455bc5fc1357327089cfaf9e9480bb8 Mon Sep 17 00:00:00 2001 From: Malin E Date: Fri, 26 Aug 2022 16:58:48 +0200 Subject: [PATCH 19/23] Start addressing PR comments --- .../digitaluniverse/constellationbounds.asset | 4 +- .../digitaluniverse/constellations.asset | 16 ++-- modules/space/CMakeLists.txt | 4 +- .../renderableconstellationbounds.cpp | 34 ++++---- .../rendering/renderableconstellationbounds.h | 4 +- .../renderableconstellationlines.cpp | 83 ++++++++++--------- .../rendering/renderableconstellationlines.h | 6 +- ...n.cpp => renderableconstellationsbase.cpp} | 82 +++++++++--------- ...ation.h => renderableconstellationsbase.h} | 23 ++--- .../space/shaders/constellationbounds_fs.glsl | 6 +- .../space/shaders/constellationlines_fs.glsl | 7 +- .../space/shaders/constellationlines_vs.glsl | 6 +- 12 files changed, 141 insertions(+), 134 deletions(-) rename modules/space/rendering/{renderableconstellation.cpp => renderableconstellationsbase.cpp} (84%) rename modules/space/rendering/{renderableconstellation.h => renderableconstellationsbase.h} (87%) diff --git a/data/assets/scene/digitaluniverse/constellationbounds.asset b/data/assets/scene/digitaluniverse/constellationbounds.asset index 4003e15b39..4c0494e4f3 100644 --- a/data/assets/scene/digitaluniverse/constellationbounds.asset +++ b/data/assets/scene/digitaluniverse/constellationbounds.asset @@ -16,8 +16,8 @@ local object = { Type = "RenderableConstellationBounds", Enabled = false, File = data .. "bound_20.dat", - ConstellationNamesFile = data .. "constellations.dat", - -- ConstellationSelection = zodiacs + NamesFile = data .. "constellations.dat", + -- Selection = zodiacs }, Transform = { Rotation = { diff --git a/data/assets/scene/digitaluniverse/constellations.asset b/data/assets/scene/digitaluniverse/constellations.asset index 1dafb17052..a5530f6eb1 100644 --- a/data/assets/scene/digitaluniverse/constellations.asset +++ b/data/assets/scene/digitaluniverse/constellations.asset @@ -18,15 +18,15 @@ local constellationsExtragalactic = { Opacity = 0.4, File = speck .. "constellationsEXGAL.speck", LabelFile = speck .. "constellationsEXGAL.label", - ConstellationNamesFile = speck .. "constellations.dat", + NamesFile = speck .. "constellations.dat", TextColor = { 0.8, 0.8, 0.8 }, TextOpacity = 0.4, TextSize = 20.0, TextMinMaxSize = { 20, 30 }, - ConstellationColor = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, + Colors = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, LabelUnit = "Mpc", - ConstellationUnit = "Mpc", - -- ConstellationSelection = zodiacs + LineUnit = "Mpc", + -- Selection = zodiacs }, GUI = { Name = "Constellations (Extragalactic)", @@ -42,15 +42,15 @@ local constellations = { Opacity = 0.3, File = speck .. "constellations.speck", LabelFile = speck .. "constellations.label", - ConstellationNamesFile = speck .. "constellations.dat", + NamesFile = speck .. "constellations.dat", TextColor = { 0.8, 0.8, 0.8 }, TextOpacity = 0.3, TextSize = 14.5, TextMinMaxSize = { 8, 170 }, - ConstellationColor = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, + Colors = { { 0.6, 0.4, 0.4 }, { 0.8, 0.0, 0.0 }, { 0.0, 0.3, 0.8 } }, LabelUnit = "pc", - ConstellationUnit = "pc", - -- ConstellationSelection = zodiacs + LineUnit = "pc", + -- Selection = zodiacs }, GUI = { Name = "Constellations", diff --git a/modules/space/CMakeLists.txt b/modules/space/CMakeLists.txt index c6e3ced6d8..3a28b950e4 100644 --- a/modules/space/CMakeLists.txt +++ b/modules/space/CMakeLists.txt @@ -28,7 +28,7 @@ set(HEADER_FILES horizonsfile.h kepler.h speckloader.h - rendering/renderableconstellation.h + rendering/renderableconstellationsbase.h rendering/renderableconstellationbounds.h rendering/renderableconstellationlines.h rendering/renderablefluxnodes.h @@ -50,7 +50,7 @@ set(SOURCE_FILES kepler.cpp spacemodule_lua.inl speckloader.cpp - rendering/renderableconstellation.cpp + rendering/renderableconstellationsbase.cpp rendering/renderableconstellationbounds.cpp rendering/renderableconstellationlines.cpp rendering/renderablefluxnodes.cpp diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index a1cafc053c..7972203696 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -73,7 +73,7 @@ documentation::Documentation RenderableConstellationBounds::Documentation() { RenderableConstellationBounds::RenderableConstellationBounds( const ghoul::Dictionary& dictionary) - : RenderableConstellation(dictionary) + : RenderableConstellationsBase(dictionary) , _vertexFilename(VertexInfo) , _color(ColorInfo, glm::vec3(1.f, 0.f, 0.f), glm::vec3(0.f), glm::vec3(1.f)) { @@ -90,20 +90,20 @@ RenderableConstellationBounds::RenderableConstellationBounds( } void RenderableConstellationBounds::initialize() { - RenderableConstellation::initialize(); + RenderableConstellationsBase::initialize(); loadVertexFile(); - if (!_assetSelectedConstellations.empty()) { - const std::vector options = _constellationSelection.options(); + if (!_assetSelection.empty()) { + const std::vector options = _selection.options(); std::set selectedConstellations; - for (const std::string& s : _assetSelectedConstellations) { + for (const std::string& s : _assetSelection) { const auto it = std::find(options.begin(), options.end(), s); if (it == options.end()) { // The user has specified a constellation name that doesn't exist LWARNINGC( - "RenderableConstellation", + "RenderableConstellationsBase", fmt::format("Option '{}' not found in list of constellations", s) ); } @@ -111,7 +111,7 @@ void RenderableConstellationBounds::initialize() { selectedConstellations.insert(s); } } - _constellationSelection = selectedConstellations; + _selection = selectedConstellations; } } @@ -154,10 +154,13 @@ void RenderableConstellationBounds::deinitializeGL() { } bool RenderableConstellationBounds::isReady() const { - if (!_hasLabel) { - return _program && _vao != 0 && _vbo != 0; + bool isReady = _program && _vao != 0 && _vbo != 0; + + // If we have labels, they also need to be loaded + if (_hasLabel) { + return isReady && !_labelset.entries.empty(); } - return _program && _vao != 0 && _vbo != 0 && !_labelset.entries.empty(); + return isReady; } void RenderableConstellationBounds::render(const RenderData& data, RendererTasks& tasks) { @@ -177,7 +180,7 @@ void RenderableConstellationBounds::render(const RenderData& data, RendererTasks _program->setUniform("ViewProjection", data.camera.viewProjectionMatrix()); _program->setUniform("ModelTransform", glm::mat4(modelTransform)); _program->setUniform("color", _color); - _program->setUniform("alphaValue", opacity()); + _program->setUniform("opacity", opacity()); glLineWidth(_lineWidth); @@ -190,11 +193,10 @@ void RenderableConstellationBounds::render(const RenderData& data, RendererTasks glBindVertexArray(0); _program->deactivate(); - RenderableConstellation::render(data, tasks); + RenderableConstellationsBase::render(data, tasks); } -void RenderableConstellationBounds::update(const UpdateData& data) { -} +void RenderableConstellationBounds::update(const UpdateData& data) { } bool RenderableConstellationBounds::loadVertexFile() { if (_vertexFilename.value().empty()) { @@ -300,7 +302,7 @@ bool RenderableConstellationBounds::loadVertexFile() { void RenderableConstellationBounds::selectionPropertyHasChanged() { // If no values are selected (the default), we want to show all constellations - if (!_constellationSelection.hasSelected()) { + if (!_selection.hasSelected()) { for (ConstellationBound& b : _constellationBounds) { b.isEnabled = true; } @@ -308,7 +310,7 @@ void RenderableConstellationBounds::selectionPropertyHasChanged() { else { // Enable all constellations that are selected for (ConstellationBound& b : _constellationBounds) { - b.isEnabled = _constellationSelection.isSelected(b.constellationFullName); + b.isEnabled = _selection.isSelected(b.constellationFullName); } } } diff --git a/modules/space/rendering/renderableconstellationbounds.h b/modules/space/rendering/renderableconstellationbounds.h index 3925e37c6e..b5fcefe299 100644 --- a/modules/space/rendering/renderableconstellationbounds.h +++ b/modules/space/rendering/renderableconstellationbounds.h @@ -25,7 +25,7 @@ #ifndef __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONBOUNDS___H__ #define __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONBOUNDS___H__ -#include +#include namespace ghoul::opengl { class ProgramObject; } @@ -42,7 +42,7 @@ namespace documentation { struct Documentation; } * _distance property. Currently, all constellation bounds are lines, which * leads to artifacts if the radius is very small. */ -class RenderableConstellationBounds : public RenderableConstellation { +class RenderableConstellationBounds : public RenderableConstellationsBase { public: RenderableConstellationBounds(const ghoul::Dictionary& dictionary); diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index 659f346809..852e17d3ef 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -25,13 +25,13 @@ #include #include -#include #include #include -#include +#include #include -#include +#include #include +#include #include #include #include @@ -43,7 +43,7 @@ namespace { constexpr std::string_view _loggerCat = "RenderableConstellationLines"; constexpr std::array UniformNames = { - "modelViewTransform", "projectionTransform", "alphaValue", "color" + "modelViewTransform", "projectionTransform", "opacity", "color" }; constexpr openspace::properties::Property::PropertyInfo DrawElementsInfo = { @@ -52,16 +52,17 @@ namespace { "Enables/Disables the drawing of the constellations" }; - constexpr openspace::properties::Property::PropertyInfo ConstellationUnitInfo = { - "ConstellationUnit", - "Constellation Unit", - "The unit used for the constellation data" + constexpr openspace::properties::Property::PropertyInfo LineUnitInfo = { + "LineUnit", + "Line Unit", + "The distance unit used for the constellation lines data" }; - constexpr openspace::properties::Property::PropertyInfo ConstellationColorInfo = { - "ConstellationColor", - "Constellation colors", - "The defined colors for the constellations to be rendered" + constexpr openspace::properties::Property::PropertyInfo ColorsInfo = { + "Colors", + "Constellation Colors", + "The defined colors for the constellations to be rendered. " + "There can be several groups of constellaitons that can have distinct colors." }; struct [[codegen::Dictionary(RenderableConstellationLines)]] Parameters { @@ -77,11 +78,11 @@ namespace { Gigaparsec [[codegen::key("Gpc")]], Gigalightyear [[codegen::key("Gly")]] }; - // [[codegen::verbatim(ConstellationUnitInfo.description)]] - std::optional constellationUnit; + // [[codegen::verbatim(LineUnitInfo.description)]] + std::optional lineUnit; - // [[codegen::verbatim(ConstellationColorInfo.description)]] - std::optional> constellationColor; + // [[codegen::verbatim(ColorsInfo.description)]] + std::optional> colors; }; #include "renderableconstellationlines_codegen.cpp" } // namespace @@ -94,7 +95,7 @@ documentation::Documentation RenderableConstellationLines::Documentation() { RenderableConstellationLines::RenderableConstellationLines( const ghoul::Dictionary& dictionary) - : RenderableConstellation(dictionary) + : RenderableConstellationsBase(dictionary) , _drawElements(DrawElementsInfo, true) { const Parameters p = codegen::bake(dictionary); @@ -104,15 +105,15 @@ RenderableConstellationLines::RenderableConstellationLines( _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); addProperty(_drawElements); - if (p.constellationUnit.has_value()) { - _constellationUnit = codegen::map(*p.constellationUnit); + if (p.lineUnit.has_value()) { + _constellationUnit = codegen::map(*p.lineUnit); } else { _constellationUnit = DistanceUnit::Meter; } - if (p.constellationColor.has_value()) { - std::vector ops = *p.constellationColor; + if (p.colors.has_value()) { + std::vector ops = *p.colors; for (size_t i = 0; i < ops.size(); ++i) { _constellationColorMap.insert({ static_cast(i) + 1, ops[i] }); } @@ -121,7 +122,7 @@ RenderableConstellationLines::RenderableConstellationLines( void RenderableConstellationLines::selectionPropertyHasChanged() { // If no values are selected (the default), we want to show all constellations - if (!_constellationSelection.hasSelected()) { + if (!_selection.hasSelected()) { for (std::pair& pair : _renderingConstellationsMap) { @@ -133,38 +134,39 @@ void RenderableConstellationLines::selectionPropertyHasChanged() { for (std::pair& pair : _renderingConstellationsMap) { - pair.second.isEnabled = - _constellationSelection.isSelected(pair.second.name); + pair.second.isEnabled = _selection.isSelected(pair.second.name); } } } bool RenderableConstellationLines::isReady() const { - if (!_hasLabel) { - return _program && !_renderingConstellationsMap.empty(); + bool isReady = _program && !_renderingConstellationsMap.empty(); + + // If we have labels, they also need to be loaded + if (_hasLabel) { + return isReady && !_labelset.entries.empty(); } - return _program && !_renderingConstellationsMap.empty() && - !_labelset.entries.empty(); + return isReady; } void RenderableConstellationLines::initialize() { - RenderableConstellation::initialize(); + RenderableConstellationsBase::initialize(); bool success = loadData(); if (!success) { throw ghoul::RuntimeError("Error loading data"); } - if (!_assetSelectedConstellations.empty()) { - const std::vector options = _constellationSelection.options(); + if (!_assetSelection.empty()) { + const std::vector options = _selection.options(); std::set selectedConstellations; - for (const std::string& s : _assetSelectedConstellations) { + for (const std::string& s : _assetSelection) { const auto it = std::find(options.begin(), options.end(), s); if (it == options.end()) { // The user has specified a constellation name that doesn't exist LWARNINGC( - "RenderableConstellation", + "RenderableConstellationsBase", fmt::format("Option '{}' not found in list of constellations", s) ); } @@ -172,7 +174,7 @@ void RenderableConstellationLines::initialize() { selectedConstellations.insert(s); } } - _constellationSelection = selectedConstellations; + _selection = selectedConstellations; } } @@ -215,7 +217,7 @@ void RenderableConstellationLines::renderConstellations(const RenderData&, _program->setUniform(_uniformCache.modelViewTransform, modelViewMatrix); _program->setUniform(_uniformCache.projectionTransform, projectionMatrix); - _program->setUniform(_uniformCache.alphaValue, opacity()); + _program->setUniform(_uniformCache.opacity, opacity()); for (const std::pair& pair : _renderingConstellationsMap) @@ -257,7 +259,7 @@ void RenderableConstellationLines::render(const RenderData& data, RendererTasks& renderConstellations(data, modelViewMatrix, projectionMatrix); } - RenderableConstellation::render(data, tasks); + RenderableConstellationsBase::render(data, tasks); } void RenderableConstellationLines::update(const UpdateData&) { @@ -331,10 +333,15 @@ bool RenderableConstellationLines::readSpeckFile() { std::string dummy; str >> dummy; // mesh command dummy.clear(); - str >> dummy; // color index command? + str >> dummy; // color index command do { if (dummy == "-c") { - str >> constellationLine.colorIndex; // color index command + str >> constellationLine.colorIndex; // color index + } + else { + std::string message = fmt::format("Unknown command '{}' found in " + "constellation file '{}'", dummy, _speckFile); + LWARNING(message); } dummy.clear(); str >> dummy; diff --git a/modules/space/rendering/renderableconstellationlines.h b/modules/space/rendering/renderableconstellationlines.h index e9fb792a6e..51dfe2044c 100644 --- a/modules/space/rendering/renderableconstellationlines.h +++ b/modules/space/rendering/renderableconstellationlines.h @@ -25,7 +25,7 @@ #ifndef __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLECONSTELLATIONLINES___H__ #define __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLECONSTELLATIONLINES___H__ -#include +#include #include #include @@ -41,7 +41,7 @@ namespace openspace { namespace documentation { struct Documentation; } -class RenderableConstellationLines : public RenderableConstellation { +class RenderableConstellationLines : public RenderableConstellationsBase { public: explicit RenderableConstellationLines(const ghoul::Dictionary& dictionary); ~RenderableConstellationLines() override = default; @@ -88,7 +88,7 @@ private: properties::BoolProperty _drawElements; std::unique_ptr _program = nullptr; - UniformCache(modelViewTransform, projectionTransform, alphaValue, + UniformCache(modelViewTransform, projectionTransform, opacity, color) _uniformCache; std::string _speckFile; diff --git a/modules/space/rendering/renderableconstellation.cpp b/modules/space/rendering/renderableconstellationsbase.cpp similarity index 84% rename from modules/space/rendering/renderableconstellation.cpp rename to modules/space/rendering/renderableconstellationsbase.cpp index 01215c0a68..5925fd5da3 100644 --- a/modules/space/rendering/renderableconstellation.cpp +++ b/modules/space/rendering/renderableconstellationsbase.cpp @@ -22,7 +22,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include #include #include @@ -74,9 +74,9 @@ namespace { "constellations" }; - constexpr openspace::properties::Property::PropertyInfo ConstellationInfo = { - "ConstellationFile", - "Constellation File Path", + constexpr openspace::properties::Property::PropertyInfo NamesFileInfo = { + "NamesFile", + "Constellation Names File Path", "Specifies the file that contains the mapping between constellation " "abbreviations and full names of the constellations. If this value is empty, the " "abbreviations are used as the full names" @@ -112,12 +112,12 @@ namespace { "The constellations that are selected are displayed on the celestial sphere" }; - struct [[codegen::Dictionary(RenderableConstellation)]] Parameters { + struct [[codegen::Dictionary(RenderableConstellationsBase)]] Parameters { // [[codegen::verbatim(DrawLabelInfo.description)]] std::optional drawLabels; - // [[codegen::verbatim(ConstellationInfo.description)]] - std::optional constellationNamesFile; + // [[codegen::verbatim(NamesFileInfo.description)]] + std::optional namesFile; // [[codegen::verbatim(TextColorInfo.description)]] std::optional textColor [[codegen::color()]]; @@ -150,18 +150,18 @@ namespace { std::optional labelUnit; // [[codegen::verbatim(SelectionInfo.description)]] - std::optional> constellationSelection; + std::optional> selection; }; -#include "renderableconstellation_codegen.cpp" +#include "renderableconstellationsbase_codegen.cpp" } // namespace namespace openspace { -documentation::Documentation RenderableConstellation::Documentation() { - return codegen::doc("space_renderable_constellation"); +documentation::Documentation RenderableConstellationsBase::Documentation() { + return codegen::doc("space_renderable_constellationsbase"); } -RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictionary) +RenderableConstellationsBase::RenderableConstellationsBase(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _textColor(TextColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f)) , _textOpacity(TextOpacityInfo, 1.f, 0.f, 1.f) @@ -175,8 +175,8 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio ) , _lineWidth(LineWidthInfo, 2.f, 1.f, 16.f) , _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown) - , _constellationNamesFilename(ConstellationInfo) - , _constellationSelection(SelectionInfo) + , _namesFilename(NamesFileInfo) + , _selection(SelectionInfo) { const Parameters p = codegen::bake(dictionary); @@ -196,12 +196,11 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio addProperty(_renderOption); // Avoid reading files here, instead do it in multithreaded initialize() - if (p.constellationNamesFile.has_value()) { - _constellationNamesFilename = - absPath(p.constellationNamesFile.value().string()).string(); + if (p.namesFile.has_value()) { + _namesFilename = absPath(p.namesFile.value().string()).string(); } - _constellationNamesFilename.onChange([&]() { loadConstellationFile(); }); - addProperty(_constellationNamesFilename); + _namesFilename.onChange([&]() { loadConstellationFile(); }); + addProperty(_namesFilename); _lineWidth = p.lineWidth.value_or(_lineWidth); addProperty(_lineWidth); @@ -236,45 +235,44 @@ RenderableConstellation::RenderableConstellation(const ghoul::Dictionary& dictio } } - _constellationSelection.onChange([this]() { selectionPropertyHasChanged(); }); - addProperty(_constellationSelection); + _selection.onChange([this]() { selectionPropertyHasChanged(); }); + addProperty(_selection); - _assetSelectedConstellations = - p.constellationSelection.value_or(_assetSelectedConstellations); + _assetSelection = p.selection.value_or(_assetSelection); } -std::string RenderableConstellation::constellationFullName( +std::string RenderableConstellationsBase::constellationFullName( const std::string& identifier) const { - if (_constellationNamesTranslation.empty() || identifier.empty()) { + if (_namesTranslation.empty() || identifier.empty()) { std::string message = "List of constellations or the given identifier was empty"; - LWARNINGC("RenderableConstellation", message); + LWARNINGC("RenderableConstellationsBase", message); return ""; } try { - return _constellationNamesTranslation.at(identifier); + return _namesTranslation.at(identifier); } catch (const std::out_of_range&) { std::string message = fmt::format( "Identifier '{}' could not be found in list of constellations", identifier ); - throw ghoul::RuntimeError(message, "RenderableConstellation"); + throw ghoul::RuntimeError(message, "RenderableConstellationsBase"); } } -void RenderableConstellation::loadConstellationFile() { - if (_constellationNamesFilename.value().empty()) { +void RenderableConstellationsBase::loadConstellationFile() { + if (_namesFilename.value().empty()) { return; } // Reset - _constellationSelection.clearOptions(); - _constellationNamesTranslation.clear(); + _selection.clearOptions(); + _namesTranslation.clear(); std::ifstream file; file.exceptions(std::ifstream::goodbit); - file.open(absPath(_constellationNamesFilename)); + file.open(absPath(_namesFilename)); std::string line; while (file.good()) { @@ -290,19 +288,19 @@ void RenderableConstellation::loadConstellationFile() { std::string fullName; std::getline(s, fullName); ghoul::trimWhitespace(fullName); - _constellationNamesTranslation[abbreviation] = fullName; + _namesTranslation[abbreviation] = fullName; } fillSelectionProperty(); } -void RenderableConstellation::fillSelectionProperty() { - for (const std::pair& pair : _constellationNamesTranslation) { - _constellationSelection.addOption(pair.second); +void RenderableConstellationsBase::fillSelectionProperty() { + for (const std::pair& pair : _namesTranslation) { + _selection.addOption(pair.second); } } -void RenderableConstellation::initialize() { +void RenderableConstellationsBase::initialize() { loadConstellationFile(); if (!_hasLabel) { @@ -334,7 +332,7 @@ void RenderableConstellation::initialize() { } } -void RenderableConstellation::render(const RenderData& data, RendererTasks&) { +void RenderableConstellationsBase::render(const RenderData& data, RendererTasks&) { if (!_hasLabel || !_drawLabels) { return; } @@ -372,7 +370,7 @@ void RenderableConstellation::render(const RenderData& data, RendererTasks&) { renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp); } -void RenderableConstellation::renderLabels(const RenderData& data, +void RenderableConstellationsBase::renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix, const glm::vec3& orthoRight, const glm::vec3& orthoUp) @@ -395,9 +393,7 @@ void RenderableConstellation::renderLabels(const RenderData& data, glm::vec4 textColor = glm::vec4(glm::vec3(_textColor), _textOpacity); for (const speck::Labelset::Entry& e : _labelset.entries) { - if (_constellationSelection.hasSelected() && - !_constellationSelection.isSelected(e.text)) - { + if (_selection.hasSelected() && !_selection.isSelected(e.text)) { continue; } diff --git a/modules/space/rendering/renderableconstellation.h b/modules/space/rendering/renderableconstellationsbase.h similarity index 87% rename from modules/space/rendering/renderableconstellation.h rename to modules/space/rendering/renderableconstellationsbase.h index 7d2a88f14c..8da74feedc 100644 --- a/modules/space/rendering/renderableconstellation.h +++ b/modules/space/rendering/renderableconstellationsbase.h @@ -22,8 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATION___H__ -#define __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATION___H__ +#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONSBASE___H__ +#define __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONSBASE___H__ #include @@ -44,9 +44,12 @@ namespace openspace { namespace documentation { struct Documentation; } -class RenderableConstellation : public Renderable { +/** + * This is a base class for constellation lines and bounds + */ +class RenderableConstellationsBase : public Renderable { public: - virtual ~RenderableConstellation() override = default; + virtual ~RenderableConstellationsBase() override = default; virtual void initialize() override; virtual void initializeGL() override = 0; @@ -62,7 +65,7 @@ public: static documentation::Documentation Documentation(); protected: - explicit RenderableConstellation(const ghoul::Dictionary& dictionary); + explicit RenderableConstellationsBase(const ghoul::Dictionary& dictionary); /** * Callback method that gets triggered when _constellationSelection @@ -78,11 +81,11 @@ protected: properties::FloatProperty _lineWidth; // Property that stores all constellations chosen by the user to be drawn - properties::SelectionProperty _constellationSelection; + properties::SelectionProperty _selection; // Temporary storage of which constellations should be rendered as stated in the // asset file - std::vector _assetSelectedConstellations; + std::vector _assetSelection; // Label text settings bool _hasLabel = false; @@ -92,7 +95,7 @@ protected: private: // Map over the constellations names and their abbreviations // key = abbreviation, value = full name - std::map _constellationNamesTranslation; + std::map _namesTranslation; /** * Loads the file specified in _constellationNamesFilename that contains @@ -104,7 +107,7 @@ private: void fillSelectionProperty(); // The file containing constellation names and abbreviations - properties::StringProperty _constellationNamesFilename; + properties::StringProperty _namesFilename; // Label text settings std::string _labelFile; @@ -120,4 +123,4 @@ private: } // namespace openspace -#endif // __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATION___H__ +#endif // __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONSBASE___H__ diff --git a/modules/space/shaders/constellationbounds_fs.glsl b/modules/space/shaders/constellationbounds_fs.glsl index 0d138b106d..ce1a490d4e 100644 --- a/modules/space/shaders/constellationbounds_fs.glsl +++ b/modules/space/shaders/constellationbounds_fs.glsl @@ -28,18 +28,18 @@ in vec4 vs_position; uniform vec3 color; -uniform float alphaValue; +uniform float opacity; Fragment getFragment() { Fragment frag; - if (alphaValue == 0.0) { + if (opacity == 0.0) { discard; } vec4 position = vs_position; - frag.color = vec4(color, alphaValue); + frag.color = vec4(color, opacity); frag.depth = pscDepth(position); return frag; diff --git a/modules/space/shaders/constellationlines_fs.glsl b/modules/space/shaders/constellationlines_fs.glsl index f8cfcda68d..06311674c6 100644 --- a/modules/space/shaders/constellationlines_fs.glsl +++ b/modules/space/shaders/constellationlines_fs.glsl @@ -28,19 +28,18 @@ in float vs_screenSpaceDepth; in vec4 vs_positionViewSpace; uniform vec3 color; -uniform float alphaValue; +uniform float opacity; Fragment getFragment() { Fragment frag; - if (alphaValue == 0.0) { + if (opacity == 0.0) { discard; } - frag.color = vec4(color, alphaValue); + frag.color = vec4(color, opacity); frag.depth = vs_screenSpaceDepth; - // JCC: Need to change the position to camera space frag.gPosition = vs_positionViewSpace; frag.gNormal = vec4(0.0, 0.0, 0.0, 1.0); diff --git a/modules/space/shaders/constellationlines_vs.glsl b/modules/space/shaders/constellationlines_vs.glsl index e8611e67d3..1fa6aa80fe 100644 --- a/modules/space/shaders/constellationlines_vs.glsl +++ b/modules/space/shaders/constellationlines_vs.glsl @@ -36,11 +36,11 @@ uniform dmat4 projectionTransform; void main() { - dvec4 positionViewSpace = modelViewTransform * dvec4(in_position, 1.0); - vec4 positionClipSpace = vec4(projectionTransform * positionViewSpace); + dvec4 positionViewSpace = modelViewTransform * dvec4(in_position, 1.0); + vec4 positionClipSpace = vec4(projectionTransform * positionViewSpace); vec4 positionScreenSpace = vec4(z_normalization(positionClipSpace)); - vs_screenSpaceDepth = positionScreenSpace.w; + vs_screenSpaceDepth = positionScreenSpace.w; vs_positionViewSpace = vec4(positionViewSpace); gl_Position = positionScreenSpace; From 53b2d0e76c44172d69a8a270f57f9d4caadeb0f5 Mon Sep 17 00:00:00 2001 From: Malin E Date: Mon, 29 Aug 2022 11:44:21 +0200 Subject: [PATCH 20/23] Address some more PR comments --- .../digitaluniverse/constellationbounds.asset | 4 +-- .../renderableconstellationlines.cpp | 27 ++++--------------- .../rendering/renderableconstellationlines.h | 11 +++----- .../renderableconstellationsbase.cpp | 22 +++++++-------- 4 files changed, 22 insertions(+), 42 deletions(-) diff --git a/data/assets/scene/digitaluniverse/constellationbounds.asset b/data/assets/scene/digitaluniverse/constellationbounds.asset index 4c0494e4f3..346e516c7e 100644 --- a/data/assets/scene/digitaluniverse/constellationbounds.asset +++ b/data/assets/scene/digitaluniverse/constellationbounds.asset @@ -41,11 +41,11 @@ local object = { asset.onInitialize(function() openspace.addSceneGraphNode(object) end) - + asset.onDeinitialize(function() openspace.removeSceneGraphNode(object) end) - + asset.export(object) diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index 852e17d3ef..4b5c2d100c 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -100,9 +100,7 @@ RenderableConstellationLines::RenderableConstellationLines( { const Parameters p = codegen::bake(dictionary); - _speckFile = absPath(p.file.string()).string(); - _hasSpeckFile = true; - _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); + _speckFile = absPath(p.file); addProperty(_drawElements); if (p.lineUnit.has_value()) { @@ -255,7 +253,7 @@ void RenderableConstellationLines::render(const RenderData& data, RendererTasks& const glm::dmat4 modelViewMatrix = data.camera.combinedViewMatrix() * modelMatrix; const glm::dmat4 projectionMatrix = data.camera.projectionMatrix(); - if (_hasSpeckFile) { + if (_drawElements) { renderConstellations(data, modelViewMatrix, projectionMatrix); } @@ -270,24 +268,14 @@ void RenderableConstellationLines::update(const UpdateData&) { } bool RenderableConstellationLines::loadData() { - bool success = false; - if (_hasSpeckFile) { - LINFO(fmt::format("Loading Speck file {}", std::filesystem::path(_speckFile))); - success = readSpeckFile(); - if (!success) { - return false; - } - } - - return success; + return readSpeckFile(); } bool RenderableConstellationLines::readSpeckFile() { + LINFO(fmt::format("Loading Speck file {}", _speckFile)); std::ifstream file(_speckFile); if (!file.good()) { - LERROR(fmt::format( - "Failed to open Speck file {}", std::filesystem::path(_speckFile) - )); + LERROR(fmt::format("Failed to open Speck file {}", _speckFile)); return false; } @@ -421,9 +409,6 @@ bool RenderableConstellationLines::readSpeckFile() { } void RenderableConstellationLines::createConstellations() { - if (!(_dataIsDirty && _hasSpeckFile)) { - return; - } LDEBUG("Creating constellations"); for (std::pair& p : _renderingConstellationsMap) { @@ -449,8 +434,6 @@ void RenderableConstellationLines::createConstellations() { } glBindVertexArray(0); - - _dataIsDirty = false; } } // namespace openspace diff --git a/modules/space/rendering/renderableconstellationlines.h b/modules/space/rendering/renderableconstellationlines.h index 51dfe2044c..4bfcda7b61 100644 --- a/modules/space/rendering/renderableconstellationlines.h +++ b/modules/space/rendering/renderableconstellationlines.h @@ -22,8 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLECONSTELLATIONLINES___H__ -#define __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLECONSTELLATIONLINES___H__ +#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONLINES___H__ +#define __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONLINES___H__ #include @@ -82,16 +82,13 @@ private: */ void selectionPropertyHasChanged() override; - bool _hasSpeckFile = false; - bool _dataIsDirty = true; - properties::BoolProperty _drawElements; std::unique_ptr _program = nullptr; UniformCache(modelViewTransform, projectionTransform, opacity, color) _uniformCache; - std::string _speckFile; + std::filesystem::path _speckFile; DistanceUnit _constellationUnit = DistanceUnit::Parsec; @@ -102,4 +99,4 @@ private: }; } // namespace openspace -#endif // __OPENSPACE_MODULE_DIGITALUNIVERSE___RENDERABLECONSTELLATIONLINES___H__ +#endif // __OPENSPACE_MODULE_SPACE___RENDERABLECONSTELLATIONLINES___H__ diff --git a/modules/space/rendering/renderableconstellationsbase.cpp b/modules/space/rendering/renderableconstellationsbase.cpp index 5925fd5da3..6d6ca5d06b 100644 --- a/modules/space/rendering/renderableconstellationsbase.cpp +++ b/modules/space/rendering/renderableconstellationsbase.cpp @@ -250,15 +250,15 @@ std::string RenderableConstellationsBase::constellationFullName( return ""; } - try { + if (_namesTranslation.contains(identifier)) { return _namesTranslation.at(identifier); } - catch (const std::out_of_range&) { - std::string message = fmt::format( - "Identifier '{}' could not be found in list of constellations", identifier - ); - throw ghoul::RuntimeError(message, "RenderableConstellationsBase"); - } + + std::string message = fmt::format( + "Identifier '{}' could not be found in list of constellations", identifier + ); + LERRORC("RenderableConstellationsBase", message); + return ""; } void RenderableConstellationsBase::loadConstellationFile() { @@ -353,19 +353,19 @@ void RenderableConstellationsBase::render(const RenderData& data, RendererTasks& const glm::dmat4 worldToModelTransform = glm::inverse(modelMatrix); glm::vec3 orthoRight = glm::normalize( - glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)) + glm::vec3(worldToModelTransform * glm::vec4(right, 0.f)) ); - if (orthoRight == glm::vec3(0.0)) { + if (orthoRight == glm::vec3(0.f)) { glm::vec3 otherVector(lookup.y, lookup.x, lookup.z); right = glm::cross(viewDirection, otherVector); orthoRight = glm::normalize( - glm::vec3(worldToModelTransform * glm::vec4(right, 0.0)) + glm::vec3(worldToModelTransform * glm::vec4(right, 0.f)) ); } const glm::vec3 orthoUp = glm::normalize( - glm::vec3(worldToModelTransform * glm::dvec4(up, 0.0)) + glm::vec3(worldToModelTransform * glm::dvec4(up, 0.f)) ); renderLabels(data, modelViewProjectionMatrix, orthoRight, orthoUp); } From dc55105000dfbb4ab91b920b031636c8fbae72ac Mon Sep 17 00:00:00 2001 From: Malin E Date: Mon, 29 Aug 2022 13:13:47 +0200 Subject: [PATCH 21/23] Move loading of data error handling --- .../rendering/renderableconstellationbounds.cpp | 12 ++++++++++-- .../space/rendering/renderableconstellationbounds.h | 1 + .../space/rendering/renderableconstellationlines.cpp | 12 +++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index 7972203696..2dc8eea9c0 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -81,7 +81,7 @@ RenderableConstellationBounds::RenderableConstellationBounds( // Avoid reading files here, instead do it in multithreaded initialize() _vertexFilename = absPath(p.file.string()).string(); - _vertexFilename.onChange([&](){ loadVertexFile(); }); + _vertexFilename.onChange([&](){ loadData(); }); addProperty(_vertexFilename); _color.setViewOption(properties::Property::ViewOptions::Color); @@ -92,7 +92,7 @@ RenderableConstellationBounds::RenderableConstellationBounds( void RenderableConstellationBounds::initialize() { RenderableConstellationsBase::initialize(); - loadVertexFile(); + loadData(); if (!_assetSelection.empty()) { const std::vector options = _selection.options(); @@ -198,6 +198,14 @@ void RenderableConstellationBounds::render(const RenderData& data, RendererTasks void RenderableConstellationBounds::update(const UpdateData& data) { } +bool RenderableConstellationBounds::loadData() { + bool success = loadVertexFile(); + if (!success) { + throw ghoul::RuntimeError("Error loading data"); + } + return success; +} + bool RenderableConstellationBounds::loadVertexFile() { if (_vertexFilename.value().empty()) { return false; diff --git a/modules/space/rendering/renderableconstellationbounds.h b/modules/space/rendering/renderableconstellationbounds.h index b5fcefe299..e5fda8c9d6 100644 --- a/modules/space/rendering/renderableconstellationbounds.h +++ b/modules/space/rendering/renderableconstellationbounds.h @@ -75,6 +75,7 @@ private: * \return \c true if the loading succeeded, \c false otherwise */ bool loadVertexFile(); + bool loadData(); /** * Callback method that gets triggered when _constellationSelection diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index 4b5c2d100c..baf6343591 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -101,6 +101,7 @@ RenderableConstellationLines::RenderableConstellationLines( const Parameters p = codegen::bake(dictionary); _speckFile = absPath(p.file); + addProperty(_drawElements); if (p.lineUnit.has_value()) { @@ -150,10 +151,7 @@ bool RenderableConstellationLines::isReady() const { void RenderableConstellationLines::initialize() { RenderableConstellationsBase::initialize(); - bool success = loadData(); - if (!success) { - throw ghoul::RuntimeError("Error loading data"); - } + loadData(); if (!_assetSelection.empty()) { const std::vector options = _selection.options(); @@ -268,7 +266,11 @@ void RenderableConstellationLines::update(const UpdateData&) { } bool RenderableConstellationLines::loadData() { - return readSpeckFile(); + bool success = readSpeckFile(); + if (!success) { + throw ghoul::RuntimeError("Error loading data"); + } + return success; } bool RenderableConstellationLines::readSpeckFile() { From 719786452d8bc93e98b875f6610e11db5b05cb54 Mon Sep 17 00:00:00 2001 From: Malin E Date: Wed, 31 Aug 2022 10:58:34 +0200 Subject: [PATCH 22/23] Address some more PR commnets --- .../renderableconstellationlines.cpp | 42 ++++++++----------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index baf6343591..d27c73d4ae 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -120,18 +121,18 @@ RenderableConstellationLines::RenderableConstellationLines( } void RenderableConstellationLines::selectionPropertyHasChanged() { + using ConstellationKeyValuePair = std::pair; + // If no values are selected (the default), we want to show all constellations if (!_selection.hasSelected()) { - for (std::pair& pair : - _renderingConstellationsMap) + for (ConstellationKeyValuePair& pair : _renderingConstellationsMap) { pair.second.isEnabled = true; } } else { // Enable all constellations that are selected - for (std::pair& pair : - _renderingConstellationsMap) + for (ConstellationKeyValuePair& pair : _renderingConstellationsMap) { pair.second.isEnabled = _selection.isSelected(pair.second.name); } @@ -187,8 +188,8 @@ void RenderableConstellationLines::initializeGL() { } void RenderableConstellationLines::deinitializeGL() { - for (const std::pair& pair : - _renderingConstellationsMap) + using ConstellationKeyValuePair = std::pair; + for (const ConstellationKeyValuePair& pair : _renderingConstellationsMap) { glDeleteVertexArrays(1, &pair.second.vaoArray); glDeleteBuffers(1, &pair.second.vboArray); @@ -215,8 +216,8 @@ void RenderableConstellationLines::renderConstellations(const RenderData&, _program->setUniform(_uniformCache.projectionTransform, projectionMatrix); _program->setUniform(_uniformCache.opacity, opacity()); - for (const std::pair& pair : - _renderingConstellationsMap) + using ConstellationKeyValuePair = std::pair; + for (const ConstellationKeyValuePair& pair : _renderingConstellationsMap) { if (!pair.second.isEnabled) { continue; @@ -364,31 +365,22 @@ bool RenderableConstellationLines::readSpeckFile() { break; } - std::stringstream lineData(line); - // Try to read three values for the position glm::vec3 pos; bool success = true; - for (int i = 0; i < 3; ++i) { - GLfloat value; - lineData >> value; - bool errorReading = lineData.rdstate() & std::ifstream::failbit; - if (errorReading) { - success = false; - break; - } - - GLfloat scaledValue = value * scale; - pos[i] = scaledValue; - constellationLine.vertices.push_back(scaledValue); + auto reading = scn::scan(line, "{} {} {}", pos.x, pos.y, pos.z); + if (reading) { + pos *= scale; + constellationLine.vertices.push_back(pos.x); + constellationLine.vertices.push_back(pos.y); + constellationLine.vertices.push_back(pos.z); } - - if (!success) { + else { + success = false; LERROR(fmt::format( "Failed reading position on line {} of mesh {} in file: '{}'. " "Stopped reading constellation data", l, lineIndex, _speckFile )); - break; } // Check if new max radius From 7b4b0ab20273db8509495aae96a8e663435b6f25 Mon Sep 17 00:00:00 2001 From: Malin E Date: Wed, 31 Aug 2022 13:44:31 +0200 Subject: [PATCH 23/23] Make the constellation lines data file a property --- .../renderableconstellationbounds.cpp | 2 -- .../rendering/renderableconstellationbounds.h | 1 - .../renderableconstellationlines.cpp | 27 ++++++++++++++----- .../rendering/renderableconstellationlines.h | 2 +- .../rendering/renderableconstellationsbase.h | 1 - 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index 2dc8eea9c0..db292afaab 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -196,8 +196,6 @@ void RenderableConstellationBounds::render(const RenderData& data, RendererTasks RenderableConstellationsBase::render(data, tasks); } -void RenderableConstellationBounds::update(const UpdateData& data) { } - bool RenderableConstellationBounds::loadData() { bool success = loadVertexFile(); if (!success) { diff --git a/modules/space/rendering/renderableconstellationbounds.h b/modules/space/rendering/renderableconstellationbounds.h index e5fda8c9d6..f6486a50de 100644 --- a/modules/space/rendering/renderableconstellationbounds.h +++ b/modules/space/rendering/renderableconstellationbounds.h @@ -53,7 +53,6 @@ public: bool isReady() const override; void render(const RenderData& data, RendererTasks& rendererTask) override; - void update(const UpdateData& data) override; static documentation::Documentation Documentation(); diff --git a/modules/space/rendering/renderableconstellationlines.cpp b/modules/space/rendering/renderableconstellationlines.cpp index d27c73d4ae..a0c6a1a23d 100644 --- a/modules/space/rendering/renderableconstellationlines.cpp +++ b/modules/space/rendering/renderableconstellationlines.cpp @@ -47,6 +47,12 @@ namespace { "modelViewTransform", "projectionTransform", "opacity", "color" }; + constexpr openspace::properties::Property::PropertyInfo SpeckInfo = { + "File", + "Constellation Data File Path", + "The file that contains the data for the constellation lines" + }; + constexpr openspace::properties::Property::PropertyInfo DrawElementsInfo = { "DrawElements", "Draw Elements", @@ -97,11 +103,15 @@ documentation::Documentation RenderableConstellationLines::Documentation() { RenderableConstellationLines::RenderableConstellationLines( const ghoul::Dictionary& dictionary) : RenderableConstellationsBase(dictionary) + , _speckFile(SpeckInfo) , _drawElements(DrawElementsInfo, true) { const Parameters p = codegen::bake(dictionary); - _speckFile = absPath(p.file); + // Avoid reading files here, instead do it in multithreaded initialize() + _speckFile = absPath(p.file.string()).string(); + _speckFile.onChange([&]() { loadData(); }); + addProperty(_speckFile); addProperty(_drawElements); @@ -275,10 +285,15 @@ bool RenderableConstellationLines::loadData() { } bool RenderableConstellationLines::readSpeckFile() { - LINFO(fmt::format("Loading Speck file {}", _speckFile)); - std::ifstream file(_speckFile); + if (_speckFile.value().empty()) { + return false; + } + std::filesystem::path fileName = absPath(_speckFile); + + LINFO(fmt::format("Loading Speck file {}", fileName)); + std::ifstream file(fileName); if (!file.good()) { - LERROR(fmt::format("Failed to open Speck file {}", _speckFile)); + LERROR(fmt::format("Failed to open Speck file {}", fileName)); return false; } @@ -331,7 +346,7 @@ bool RenderableConstellationLines::readSpeckFile() { } else { std::string message = fmt::format("Unknown command '{}' found in " - "constellation file '{}'", dummy, _speckFile); + "constellation file '{}'", dummy, fileName); LWARNING(message); } dummy.clear(); @@ -379,7 +394,7 @@ bool RenderableConstellationLines::readSpeckFile() { success = false; LERROR(fmt::format( "Failed reading position on line {} of mesh {} in file: '{}'. " - "Stopped reading constellation data", l, lineIndex, _speckFile + "Stopped reading constellation data", l, lineIndex, fileName )); } diff --git a/modules/space/rendering/renderableconstellationlines.h b/modules/space/rendering/renderableconstellationlines.h index 4bfcda7b61..8453fc5dc5 100644 --- a/modules/space/rendering/renderableconstellationlines.h +++ b/modules/space/rendering/renderableconstellationlines.h @@ -88,7 +88,7 @@ private: UniformCache(modelViewTransform, projectionTransform, opacity, color) _uniformCache; - std::filesystem::path _speckFile; + properties::StringProperty _speckFile; DistanceUnit _constellationUnit = DistanceUnit::Parsec; diff --git a/modules/space/rendering/renderableconstellationsbase.h b/modules/space/rendering/renderableconstellationsbase.h index 8da74feedc..3752201577 100644 --- a/modules/space/rendering/renderableconstellationsbase.h +++ b/modules/space/rendering/renderableconstellationsbase.h @@ -60,7 +60,6 @@ public: virtual void render(const RenderData& data, RendererTasks& rendererTask) override; void renderLabels(const RenderData& data, const glm::dmat4& modelViewProjectionMatrix, const glm::vec3& orthoRight, const glm::vec3& orthoUp); - virtual void update(const UpdateData& data) override = 0; static documentation::Documentation Documentation();