From 76d599d28435a6a6c4bf267fdc250e1a7b71f480 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Thu, 7 Jan 2021 13:33:28 +0100 Subject: [PATCH 01/41] Add a basic disc renderable --- data/assets/examples/discs.asset | 22 ++ modules/base/CMakeLists.txt | 5 +- modules/base/basemodule.cpp | 3 + modules/base/rendering/renderabledisc.cpp | 296 ++++++++++++++++++++++ modules/base/rendering/renderabledisc.h | 81 ++++++ modules/base/shaders/disc_fs.glsl | 60 +++++ modules/base/shaders/disc_vs.glsl | 44 ++++ 7 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 data/assets/examples/discs.asset create mode 100644 modules/base/rendering/renderabledisc.cpp create mode 100644 modules/base/rendering/renderabledisc.h create mode 100644 modules/base/shaders/disc_fs.glsl create mode 100644 modules/base/shaders/disc_vs.glsl diff --git a/data/assets/examples/discs.asset b/data/assets/examples/discs.asset new file mode 100644 index 0000000000..9b90c51c9e --- /dev/null +++ b/data/assets/examples/discs.asset @@ -0,0 +1,22 @@ +local assetHelper = asset.require('util/asset_helper') + +local singeColorTexturePath = openspace.createPixelImage("example_ring_color", {0.0, 1.0, 1.0}) + +local BasicDisc = { + Identifier = "BasicDisc", + Parent = "Root", + Renderable = { + Type = "RenderableDisc", + Texture = singeColorTexturePath, + Size = 1e10, + Width = 0.5 + }, + GUI = { + Name = "Basic Disc", + Path = "/Examples/Discs" + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { + BasicDisc +}) \ No newline at end of file diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index 55519e8c01..521cf3f950 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -45,6 +45,7 @@ set(HEADER_FILES rendering/grids/renderableradialgrid.h rendering/grids/renderablesphericalgrid.h rendering/renderablecartesianaxes.h + rendering/renderabledisc.h rendering/renderablelabels.h rendering/renderablemodel.h rendering/renderablenodeline.h @@ -73,7 +74,6 @@ set(HEADER_FILES translation/luatranslation.h translation/statictranslation.h translation/timelinetranslation.h - ) source_group("Header Files" FILES ${HEADER_FILES}) @@ -98,6 +98,7 @@ set(SOURCE_FILES rendering/grids/renderableradialgrid.cpp rendering/grids/renderablesphericalgrid.cpp rendering/renderablecartesianaxes.cpp + rendering/renderabledisc.cpp rendering/renderablelabels.cpp rendering/renderablemodel.cpp rendering/renderablenodeline.cpp @@ -132,6 +133,8 @@ source_group("Source Files" FILES ${SOURCE_FILES}) set(SHADER_FILES shaders/axes_fs.glsl shaders/axes_vs.glsl + shaders/disc_fs.glsl + shaders/disc_vs.glsl shaders/grid_vs.glsl shaders/grid_fs.glsl shaders/imageplane_fs.glsl diff --git a/modules/base/basemodule.cpp b/modules/base/basemodule.cpp index 6a9ebdce24..09ef673631 100644 --- a/modules/base/basemodule.cpp +++ b/modules/base/basemodule.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -129,6 +130,7 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) { fRenderable->registerClass("RenderableBoxGrid"); fRenderable->registerClass("RenderableCartesianAxes"); + fRenderable->registerClass("RenderableDisc"); fRenderable->registerClass("RenderableGrid"); fRenderable->registerClass("RenderableLabels"); fRenderable->registerClass("RenderableModel"); @@ -206,6 +208,7 @@ std::vector BaseModule::documentations() const { RenderableNodeLine::Documentation(), RenderablePlane::Documentation(), RenderableRadialGrid::Documentation(), + RenderableDisc::Documentation(), RenderableSphere::Documentation(), RenderableSphericalGrid::Documentation(), RenderableTrailOrbit::Documentation(), diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp new file mode 100644 index 0000000000..f5052e33fe --- /dev/null +++ b/modules/base/rendering/renderabledisc.cpp @@ -0,0 +1,296 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + constexpr const std::array UniformNames = { + "modelViewProjectionTransform", "opacity", "width", "colorTexture" + }; + + constexpr openspace::properties::Property::PropertyInfo TextureInfo = { + "Texture", + "Texture", + "This value is the path to a texture on disk that contains a one-dimensional " + "texture to be used for the color." + }; + + constexpr openspace::properties::Property::PropertyInfo SizeInfo = { + "Size", + "Size", + "This value specifies the outer radius of the disc in meter." + }; + + constexpr openspace::properties::Property::PropertyInfo WidthInfo = { + "Width", + "Width", + "This value is used to set the width of the disc. The actual width is set " + "based on the given size and this value should be set between 0 and 1. A value " + "of 1 results in a full circle and 0.5 a disc with an inner radius of 0.5*size." + }; +} // namespace + +namespace openspace { + +documentation::Documentation RenderableDisc::Documentation() { + using namespace documentation; + return { + "Renderable Disc", + "renderable_disc", + { + { + "Type", + new StringEqualVerifier("RenderableDisc"), + Optional::No + }, + { + TextureInfo.identifier, + new StringVerifier, + Optional::No, + TextureInfo.description + }, + { + SizeInfo.identifier, + new DoubleVerifier, + Optional::No, + SizeInfo.description + }, + { + WidthInfo.identifier, + new DoubleVerifier, + Optional::Yes, + WidthInfo.description + } + } + }; +} + +RenderableDisc::RenderableDisc(const ghoul::Dictionary& dictionary) + : Renderable(dictionary) + , _texturePath(TextureInfo) + , _size(SizeInfo, 1.f, 0.f, 1e13f) + , _width(WidthInfo, 0.5f, 0.f, 1.f) +{ + using ghoul::filesystem::File; + + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableDisc" + ); + + _size = static_cast(dictionary.value(SizeInfo.identifier)); + setBoundingSphere(_size); + _size.onChange([&]() { _planeIsDirty = true; }); + addProperty(_size); + + _texturePath = absPath(dictionary.value(TextureInfo.identifier)); + _textureFile = std::make_unique(_texturePath); + + if (dictionary.hasKey(WidthInfo.identifier)) { + _width = dictionary.value(WidthInfo.identifier); + } + addProperty(_width); + + _texturePath.onChange([&]() { loadTexture(); }); + addProperty(_texturePath); + + _textureFile->setCallback([&](const File&) { _textureIsDirty = true; }); + + addProperty(_opacity); +} + +bool RenderableDisc::isReady() const { + return _shader && _texture; +} + +void RenderableDisc::initializeGL() { + _shader = global::renderEngine->buildRenderProgram( + "RingProgram", + absPath("${MODULE_BASE}/shaders/disc_vs.glsl"), + absPath("${MODULE_BASE}/shaders/disc_fs.glsl") + ); + + ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); + + glGenVertexArrays(1, &_quad); + glGenBuffers(1, &_vertexPositionBuffer); + + createPlane(); + loadTexture(); +} + +void RenderableDisc::deinitializeGL() { + glDeleteVertexArrays(1, &_quad); + _quad = 0; + + glDeleteBuffers(1, &_vertexPositionBuffer); + _vertexPositionBuffer = 0; + + _textureFile = nullptr; + _texture = nullptr; + + global::renderEngine->removeRenderProgram(_shader.get()); + _shader = nullptr; +} + +void RenderableDisc::render(const RenderData& data, RendererTasks&) { + _shader->activate(); + + glm::dmat4 modelTransform = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * + glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); + + glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; + + _shader->setUniform( + _uniformCache.modelViewProjection, + data.camera.projectionMatrix() * glm::mat4(modelViewTransform) + ); + _shader->setUniform(_uniformCache.width, _width); + + _shader->setUniform(_uniformCache.opacity, _opacity); + + ghoul::opengl::TextureUnit unit; + unit.activate(); + _texture->bind(); + _shader->setUniform(_uniformCache.texture, unit); + + glEnablei(GL_BLEND, 0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glDepthMask(false); + glDisable(GL_CULL_FACE); + + glBindVertexArray(_quad); + glDrawArrays(GL_TRIANGLES, 0, 6); + + _shader->deactivate(); + + // Restores GL State + global::renderEngine->openglStateCache().resetBlendState(); + global::renderEngine->openglStateCache().resetDepthState(); + global::renderEngine->openglStateCache().resetPolygonAndClippingState(); +} + +void RenderableDisc::update(const UpdateData&) { + if (_shader->isDirty()) { + _shader->rebuildFromFile(); + ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); + } + + if (_planeIsDirty) { + createPlane(); + _planeIsDirty = false; + } + + if (_textureIsDirty) { + loadTexture(); + _textureIsDirty = false; + } +} + +void RenderableDisc::loadTexture() { + if (!_texturePath.value().empty()) { + using namespace ghoul::io; + using namespace ghoul::opengl; + std::unique_ptr texture = TextureReader::ref().loadTexture( + absPath(_texturePath) + ); + + if (texture) { + LDEBUGC( + "RenderableDisc", + fmt::format("Loaded texture from '{}'", absPath(_texturePath)) + ); + _texture = std::move(texture); + + _texture->uploadTexture(); + _texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + + _textureFile = std::make_unique(_texturePath); + _textureFile->setCallback( + [&](const ghoul::filesystem::File&) { _textureIsDirty = true; } + ); + } + } +} + +void RenderableDisc::createPlane() { + const GLfloat size = _size; + + struct VertexData { + GLfloat x; + GLfloat y; + GLfloat s; + GLfloat t; + }; + + VertexData data[] = { + { -size, -size, 0.f, 0.f }, + { size, size, 1.f, 1.f }, + { -size, size, 0.f, 1.f }, + { -size, -size, 0.f, 0.f }, + { size, -size, 1.f, 0.f }, + { size, size, 1.f, 1.f }, + }; + + glBindVertexArray(_quad); + glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer( + 0, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(VertexData), + nullptr + ); + glEnableVertexAttribArray(1); + glVertexAttribPointer( + 1, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(VertexData), + reinterpret_cast(offsetof(VertexData, s)) // NOLINT + ); +} + +} // namespace openspace diff --git a/modules/base/rendering/renderabledisc.h b/modules/base/rendering/renderabledisc.h new file mode 100644 index 0000000000..e767b2239c --- /dev/null +++ b/modules/base/rendering/renderabledisc.h @@ -0,0 +1,81 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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_BASE___RENDERABLEDISC___H__ +#define __OPENSPACE_MODULE_BASE___RENDERABLEDISC___H__ + +#include + +#include +#include + +#include +#include + +namespace ghoul::filesystem { class File; } +namespace ghoul::opengl { + class ProgramObject; + class Texture; +} // namespace ghoul::opengl + +namespace openspace { + +namespace documentation { struct Documentation; } + +class RenderableDisc : public Renderable { +public: + RenderableDisc(const ghoul::Dictionary& dictionary); + + void initializeGL() 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: + void loadTexture(); + void createPlane(); + + properties::StringProperty _texturePath; + properties::FloatProperty _size; + properties::FloatProperty _width; + + std::unique_ptr _shader; + UniformCache(modelViewProjection, opacity, width, texture) _uniformCache; + std::unique_ptr _texture; + std::unique_ptr _textureFile; + + bool _textureIsDirty = false; + GLuint _quad = 0; + GLuint _vertexPositionBuffer = 0; + bool _planeIsDirty = false; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___RENDERABLEDISC___H__ diff --git a/modules/base/shaders/disc_fs.glsl b/modules/base/shaders/disc_fs.glsl new file mode 100644 index 0000000000..7d0d15dc1d --- /dev/null +++ b/modules/base/shaders/disc_fs.glsl @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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 vec2 vs_st; +in vec4 vs_position; + +uniform sampler1D colorTexture; +uniform float width; +uniform float opacity; + +Fragment getFragment() { + // Moving the origin to the center + vec2 st = (vs_st - vec2(0.5)) * 2.0; + + // The length of the texture coordinates vector is our distance from the center + float radius = length(st); + + // We only want to consider ring-like objects so we need to discard everything else + if (radius > 1.0) + discard; + + // Remapping the texture coordinates + // Radius \in [0,1], + float inner = 1.0 - width; + float texCoord = (radius - inner) / (1.0 - inner); + if (texCoord < 0.0 || texCoord > 1.0) { + discard; + } + + vec4 diffuse = texture(colorTexture, texCoord); + diffuse.a *= opacity; + + Fragment frag; + frag.color = diffuse; + frag.depth = vs_position.w; + return frag; +} diff --git a/modules/base/shaders/disc_vs.glsl b/modules/base/shaders/disc_vs.glsl new file mode 100644 index 0000000000..a3f6cbedb6 --- /dev/null +++ b/modules/base/shaders/disc_vs.glsl @@ -0,0 +1,44 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2020 * + * * + * 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" + +layout(location = 0) in vec2 in_position; +layout(location = 1) in vec2 in_st; + +out vec2 vs_st; +out vec4 vs_position; + +uniform mat4 modelViewProjectionTransform; + +void main() { + vs_st = in_st; + + vs_position = z_normalization( + modelViewProjectionTransform * vec4(in_position.xy, 0.0, 1.0) + ); + gl_Position = vs_position; +} From c075dbcdeb961b639904da4823ef2e9b59150738 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Fri, 8 Jan 2021 14:05:15 +0100 Subject: [PATCH 02/41] Add simple plane geometry class --- include/openspace/util/planegeometry.h | 55 ++++++++ modules/base/rendering/renderabledisc.cpp | 61 +-------- modules/base/rendering/renderabledisc.h | 7 +- .../rendering/renderableorbitdisc.cpp | 64 ++------- .../rendering/renderableorbitdisc.h | 9 +- src/CMakeLists.txt | 2 + src/util/planegeometry.cpp | 123 ++++++++++++++++++ 7 files changed, 207 insertions(+), 114 deletions(-) create mode 100644 include/openspace/util/planegeometry.h create mode 100644 src/util/planegeometry.cpp diff --git a/include/openspace/util/planegeometry.h b/include/openspace/util/planegeometry.h new file mode 100644 index 0000000000..93d4b656c1 --- /dev/null +++ b/include/openspace/util/planegeometry.h @@ -0,0 +1,55 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___PLANEGEOMETRY___H__ +#define __OPENSPACE_CORE___PLANEGEOMETRY___H__ + +#include +#include + +namespace openspace { + +class PlaneGeometry { +public: + PlaneGeometry(glm::vec2 size); + PlaneGeometry(float size); + + ~PlaneGeometry(); + + bool initialize(); + void deinitialize(); + void render(); + + void updateSize(const glm::vec2 size); + void updateSize(const float size); + +private: + GLuint _vaoId = 0; + GLuint _vBufferId = 0; + glm::vec2 _size = glm::vec2(0.f); +}; + +} // namespace openspace + +#endif // __OPENSPACE_CORE___PLANEGEOMETRY___H__ diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index f5052e33fe..8d4e71e104 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -133,6 +133,8 @@ RenderableDisc::RenderableDisc(const ghoul::Dictionary& dictionary) _textureFile->setCallback([&](const File&) { _textureIsDirty = true; }); addProperty(_opacity); + + _plane = std::make_unique(2*_size); } bool RenderableDisc::isReady() const { @@ -148,19 +150,13 @@ void RenderableDisc::initializeGL() { ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); - glGenVertexArrays(1, &_quad); - glGenBuffers(1, &_vertexPositionBuffer); - - createPlane(); + _plane->initialize(); loadTexture(); } void RenderableDisc::deinitializeGL() { - glDeleteVertexArrays(1, &_quad); - _quad = 0; - - glDeleteBuffers(1, &_vertexPositionBuffer); - _vertexPositionBuffer = 0; + _plane->deinitialize(); + _plane = nullptr; _textureFile = nullptr; _texture = nullptr; @@ -197,8 +193,7 @@ void RenderableDisc::render(const RenderData& data, RendererTasks&) { glDepthMask(false); glDisable(GL_CULL_FACE); - glBindVertexArray(_quad); - glDrawArrays(GL_TRIANGLES, 0, 6); + _plane->render(); _shader->deactivate(); @@ -215,7 +210,7 @@ void RenderableDisc::update(const UpdateData&) { } if (_planeIsDirty) { - createPlane(); + _plane->updateSize(2*_size); _planeIsDirty = false; } @@ -251,46 +246,4 @@ void RenderableDisc::loadTexture() { } } -void RenderableDisc::createPlane() { - const GLfloat size = _size; - - struct VertexData { - GLfloat x; - GLfloat y; - GLfloat s; - GLfloat t; - }; - - VertexData data[] = { - { -size, -size, 0.f, 0.f }, - { size, size, 1.f, 1.f }, - { -size, size, 0.f, 1.f }, - { -size, -size, 0.f, 0.f }, - { size, -size, 1.f, 0.f }, - { size, size, 1.f, 1.f }, - }; - - glBindVertexArray(_quad); - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer( - 0, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(VertexData), - nullptr - ); - glEnableVertexAttribArray(1); - glVertexAttribPointer( - 1, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(VertexData), - reinterpret_cast(offsetof(VertexData, s)) // NOLINT - ); -} - } // namespace openspace diff --git a/modules/base/rendering/renderabledisc.h b/modules/base/rendering/renderabledisc.h index e767b2239c..6cbe6baa75 100644 --- a/modules/base/rendering/renderabledisc.h +++ b/modules/base/rendering/renderabledisc.h @@ -29,7 +29,7 @@ #include #include - +#include #include #include @@ -59,7 +59,6 @@ public: private: void loadTexture(); - void createPlane(); properties::StringProperty _texturePath; properties::FloatProperty _size; @@ -70,9 +69,9 @@ private: std::unique_ptr _texture; std::unique_ptr _textureFile; + std::unique_ptr _plane; + bool _textureIsDirty = false; - GLuint _quad = 0; - GLuint _vertexPositionBuffer = 0; bool _planeIsDirty = false; }; diff --git a/modules/exoplanets/rendering/renderableorbitdisc.cpp b/modules/exoplanets/rendering/renderableorbitdisc.cpp index 2887a6bae9..fdef0e820a 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.cpp +++ b/modules/exoplanets/rendering/renderableorbitdisc.cpp @@ -158,6 +158,8 @@ RenderableOrbitDisc::RenderableOrbitDisc(const ghoul::Dictionary& dictionary) addProperty(_eccentricity); addProperty(_opacity); + + _plane = std::make_unique(planeSize()); } bool RenderableOrbitDisc::isReady() const { @@ -173,19 +175,13 @@ void RenderableOrbitDisc::initializeGL() { ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); - glGenVertexArrays(1, &_quad); - glGenBuffers(1, &_vertexPositionBuffer); - - createPlane(); + _plane->initialize(); loadTexture(); } void RenderableOrbitDisc::deinitializeGL() { - glDeleteVertexArrays(1, &_quad); - _quad = 0; - - glDeleteBuffers(1, &_vertexPositionBuffer); - _vertexPositionBuffer = 0; + _plane->deinitialize(); + _plane = nullptr; _textureFile = nullptr; _texture = nullptr; @@ -223,8 +219,7 @@ void RenderableOrbitDisc::render(const RenderData& data, RendererTasks&) { glDepthMask(false); glDisable(GL_CULL_FACE); - glBindVertexArray(_quad); - glDrawArrays(GL_TRIANGLES, 0, 6); + _plane->render(); _shader->deactivate(); @@ -241,7 +236,7 @@ void RenderableOrbitDisc::update(const UpdateData&) { } if (_planeIsDirty) { - createPlane(); + _plane->updateSize(planeSize()); _planeIsDirty = false; } @@ -274,47 +269,10 @@ void RenderableOrbitDisc::loadTexture() { } } -void RenderableOrbitDisc::createPlane() { - const GLfloat outerDistance = (_size + _offset.value().y * _size); - const GLfloat size = outerDistance * (1.f + _eccentricity); - - struct VertexData { - GLfloat x; - GLfloat y; - GLfloat s; - GLfloat t; - }; - - VertexData data[] = { - { -size, -size, 0.f, 0.f }, - { size, size, 1.f, 1.f }, - { -size, size, 0.f, 1.f }, - { -size, -size, 0.f, 0.f }, - { size, -size, 1.f, 0.f }, - { size, size, 1.f, 1.f }, - }; - - glBindVertexArray(_quad); - glBindBuffer(GL_ARRAY_BUFFER, _vertexPositionBuffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW); - glEnableVertexAttribArray(0); - glVertexAttribPointer( - 0, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(VertexData), - nullptr - ); - glEnableVertexAttribArray(1); - glVertexAttribPointer( - 1, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(VertexData), - reinterpret_cast(offsetof(VertexData, s)) - ); +float RenderableOrbitDisc::planeSize() const { + float maxRadius = _size + _offset.value().y * _size; + maxRadius *= (1.f + _eccentricity); + return 2.f * maxRadius; } } // namespace openspace diff --git a/modules/exoplanets/rendering/renderableorbitdisc.h b/modules/exoplanets/rendering/renderableorbitdisc.h index 5a94a2bfc1..1aea4ae413 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.h +++ b/modules/exoplanets/rendering/renderableorbitdisc.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -58,7 +59,9 @@ public: private: void loadTexture(); - void createPlane(); + + // Computes the size of the plane quad using the relevant properties + float planeSize() const; properties::StringProperty _texturePath; properties::FloatProperty _size; @@ -71,10 +74,10 @@ private: std::unique_ptr _texture = nullptr; std::unique_ptr _textureFile; + std::unique_ptr _plane; + bool _textureIsDirty = false; bool _planeIsDirty = false; - GLuint _quad = 0; - GLuint _vertexPositionBuffer = 0; }; } // namespace openspace diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bdd8c0b8b2..8ad4ff0933 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -178,6 +178,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/util/httprequest.cpp ${OPENSPACE_BASE_DIR}/src/util/keys.cpp ${OPENSPACE_BASE_DIR}/src/util/openspacemodule.cpp + ${OPENSPACE_BASE_DIR}/src/util/planegeometry.cpp ${OPENSPACE_BASE_DIR}/src/util/progressbar.cpp ${OPENSPACE_BASE_DIR}/src/util/resourcesynchronization.cpp ${OPENSPACE_BASE_DIR}/src/util/screenlog.cpp @@ -373,6 +374,7 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/util/memorymanager.h ${OPENSPACE_BASE_DIR}/include/openspace/util/mouse.h ${OPENSPACE_BASE_DIR}/include/openspace/util/openspacemodule.h + ${OPENSPACE_BASE_DIR}/include/openspace/util/planegeometry.h ${OPENSPACE_BASE_DIR}/include/openspace/util/progressbar.h ${OPENSPACE_BASE_DIR}/include/openspace/util/resourcesynchronization.h ${OPENSPACE_BASE_DIR}/include/openspace/util/screenlog.h diff --git a/src/util/planegeometry.cpp b/src/util/planegeometry.cpp new file mode 100644 index 0000000000..33ee25fbc3 --- /dev/null +++ b/src/util/planegeometry.cpp @@ -0,0 +1,123 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +namespace { + constexpr const char* _loggerCat = "PlaneGeometry"; +} // namespace + +namespace openspace { + +PlaneGeometry::PlaneGeometry(glm::vec2 size) : _size(std::move(size)) {} + +PlaneGeometry::PlaneGeometry(float size) : _size(size, size) {} + +PlaneGeometry::~PlaneGeometry() { + glDeleteBuffers(1, &_vBufferId); + glDeleteVertexArrays(1, &_vaoId); +} + +bool PlaneGeometry::initialize() { + // Initialize and upload to GPU + const glm::vec2 size = _size * 0.5f; + + struct VertexData { + GLfloat x; + GLfloat y; + GLfloat s; + GLfloat t; + }; + + VertexData vertices[] = { + { -size.x, -size.y, 0.f, 0.f }, + { size.x, size.y, 1.f, 1.f }, + { -size.x, size.y, 0.f, 1.f }, + { -size.x, -size.y, 0.f, 0.f }, + { size.x, -size.y, 1.f, 0.f }, + { size.x, size.y, 1.f, 1.f }, + }; + + if (_vaoId == 0) { + glGenVertexArrays(1, &_vaoId); + } + + if (_vBufferId == 0) { + glGenBuffers(1, &_vBufferId); + + if (_vBufferId == 0) { + LERROR("Could not create vertex buffer"); + return false; + } + } + + // First VAO setup + glBindVertexArray(_vaoId); + + glBindBuffer(GL_ARRAY_BUFFER, _vBufferId); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), nullptr); + glEnableVertexAttribArray(1); + glVertexAttribPointer( + 1, + 2, + GL_FLOAT, + GL_FALSE, + sizeof(VertexData), + reinterpret_cast(offsetof(VertexData, s)) // NOLINT + ); + + glBindVertexArray(0); + return true; +} + +void PlaneGeometry::deinitialize() { + glDeleteVertexArrays(1, &_vaoId); + _vaoId = 0; + + glDeleteBuffers(1, &_vBufferId); + _vBufferId = 0; +} + +void PlaneGeometry::render() { + glBindVertexArray(_vaoId); // select first VAO + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); +} + +void PlaneGeometry::updateSize(const glm::vec2 size) { + _size = size; + initialize(); +} + +void PlaneGeometry::updateSize(const float size) { + _size = glm::vec2(size, size); + initialize(); +} + +} // namespace openspace From 72ebeb7f6fcd8fb10ba722a466fadcf37b7d3f8d Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Tue, 12 Jan 2021 15:56:14 +0100 Subject: [PATCH 03/41] Add generic texture component for renderables --- .../openspace/rendering/texturecomponent.h | 70 ++++++++++++++ modules/base/rendering/renderabledisc.cpp | 64 ++++--------- modules/base/rendering/renderabledisc.h | 16 +--- .../rendering/renderableorbitdisc.cpp | 53 +++------- .../rendering/renderableorbitdisc.h | 9 +- src/CMakeLists.txt | 8 +- src/rendering/texturecomponent.cpp | 96 +++++++++++++++++++ 7 files changed, 209 insertions(+), 107 deletions(-) create mode 100644 include/openspace/rendering/texturecomponent.h create mode 100644 src/rendering/texturecomponent.cpp diff --git a/include/openspace/rendering/texturecomponent.h b/include/openspace/rendering/texturecomponent.h new file mode 100644 index 0000000000..0046ea1cc0 --- /dev/null +++ b/include/openspace/rendering/texturecomponent.h @@ -0,0 +1,70 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___TEXTURECOMPONENT___H__ +#define __OPENSPACE_CORE___TEXTURECOMPONENT___H__ + +#include +#include +#include + +namespace ghoul::filesystem { class File; } +namespace ghoul::opengl {class Texture; } + +namespace openspace { + +class TextureComponent { + using Texture = ghoul::opengl::Texture; + +public: + TextureComponent() = default; + TextureComponent(const Texture::FilterMode filterMode, bool watchFile = true); + ~TextureComponent() = default; + + Texture* texture() const; + + void bind(); + void uploadToGpu(); + + // Loads a texture from a file on disk + void loadFromFile(const std::string& path); + + // Function to call in a renderable's update function to make sure + // the texture is kept up to date + void update(); + +private: + std::unique_ptr _textureFile = nullptr; + std::unique_ptr _texture = nullptr; + + Texture::FilterMode _filterMode = Texture::FilterMode::LinearMipMap; + bool _shouldWatchFile = true; + + bool _fileIsDirty = false; + bool _textureIsDirty = false; +}; + +} // namespace openspace + +#endif // __OPENSPACE_CORE___TEXTURECOMPONENT___H__ diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index 8d4e71e104..cb29d17b28 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -31,14 +31,14 @@ #include #include #include -#include #include #include #include -#include #include namespace { + constexpr const char* _loggerCat = "RenderableDisc"; + constexpr const std::array UniformNames = { "modelViewProjectionTransform", "opacity", "width", "colorTexture" }; @@ -106,8 +106,6 @@ RenderableDisc::RenderableDisc(const ghoul::Dictionary& dictionary) , _size(SizeInfo, 1.f, 0.f, 1e13f) , _width(WidthInfo, 0.5f, 0.f, 1.f) { - using ghoul::filesystem::File; - documentation::testSpecificationAndThrow( Documentation(), dictionary, @@ -120,25 +118,26 @@ RenderableDisc::RenderableDisc(const ghoul::Dictionary& dictionary) addProperty(_size); _texturePath = absPath(dictionary.value(TextureInfo.identifier)); - _textureFile = std::make_unique(_texturePath); + _texturePath.onChange([&]() { _texture->loadFromFile(_texturePath); }); + addProperty(_texturePath); if (dictionary.hasKey(WidthInfo.identifier)) { _width = dictionary.value(WidthInfo.identifier); } addProperty(_width); - _texturePath.onChange([&]() { loadTexture(); }); - addProperty(_texturePath); - - _textureFile->setCallback([&](const File&) { _textureIsDirty = true; }); - addProperty(_opacity); - - _plane = std::make_unique(2*_size); } bool RenderableDisc::isReady() const { - return _shader && _texture; + return _shader && _texture && _plane; +} + +void RenderableDisc::initialize() { + _texture = std::make_unique( + ghoul::opengl::Texture::FilterMode::AnisotropicMipMap + ); + _plane = std::make_unique(2 * _size); } void RenderableDisc::initializeGL() { @@ -150,15 +149,15 @@ void RenderableDisc::initializeGL() { ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); + _texture->loadFromFile(_texturePath); + _texture->uploadToGpu(); + _plane->initialize(); - loadTexture(); } void RenderableDisc::deinitializeGL() { _plane->deinitialize(); _plane = nullptr; - - _textureFile = nullptr; _texture = nullptr; global::renderEngine->removeRenderProgram(_shader.get()); @@ -210,40 +209,11 @@ void RenderableDisc::update(const UpdateData&) { } if (_planeIsDirty) { - _plane->updateSize(2*_size); + _plane->updateSize(2 * _size); _planeIsDirty = false; } - if (_textureIsDirty) { - loadTexture(); - _textureIsDirty = false; - } -} - -void RenderableDisc::loadTexture() { - if (!_texturePath.value().empty()) { - using namespace ghoul::io; - using namespace ghoul::opengl; - std::unique_ptr texture = TextureReader::ref().loadTexture( - absPath(_texturePath) - ); - - if (texture) { - LDEBUGC( - "RenderableDisc", - fmt::format("Loaded texture from '{}'", absPath(_texturePath)) - ); - _texture = std::move(texture); - - _texture->uploadTexture(); - _texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); - - _textureFile = std::make_unique(_texturePath); - _textureFile->setCallback( - [&](const ghoul::filesystem::File&) { _textureIsDirty = true; } - ); - } - } + _texture->update(); } } // namespace openspace diff --git a/modules/base/rendering/renderabledisc.h b/modules/base/rendering/renderabledisc.h index 6cbe6baa75..886e2f9b74 100644 --- a/modules/base/rendering/renderabledisc.h +++ b/modules/base/rendering/renderabledisc.h @@ -25,19 +25,16 @@ #ifndef __OPENSPACE_MODULE_BASE___RENDERABLEDISC___H__ #define __OPENSPACE_MODULE_BASE___RENDERABLEDISC___H__ -#include - #include #include +#include +#include #include #include #include namespace ghoul::filesystem { class File; } -namespace ghoul::opengl { - class ProgramObject; - class Texture; -} // namespace ghoul::opengl +namespace ghoul::opengl { class ProgramObject; } namespace openspace { @@ -47,6 +44,7 @@ class RenderableDisc : public Renderable { public: RenderableDisc(const ghoul::Dictionary& dictionary); + void initialize() override; void initializeGL() override; void deinitializeGL() override; @@ -58,20 +56,16 @@ public: static documentation::Documentation Documentation(); private: - void loadTexture(); - properties::StringProperty _texturePath; properties::FloatProperty _size; properties::FloatProperty _width; std::unique_ptr _shader; UniformCache(modelViewProjection, opacity, width, texture) _uniformCache; - std::unique_ptr _texture; - std::unique_ptr _textureFile; std::unique_ptr _plane; + std::unique_ptr _texture; - bool _textureIsDirty = false; bool _planeIsDirty = false; }; diff --git a/modules/exoplanets/rendering/renderableorbitdisc.cpp b/modules/exoplanets/rendering/renderableorbitdisc.cpp index fdef0e820a..891380ddc3 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.cpp +++ b/modules/exoplanets/rendering/renderableorbitdisc.cpp @@ -33,10 +33,8 @@ #include #include #include -#include #include #include -#include #include namespace { @@ -144,13 +142,9 @@ RenderableOrbitDisc::RenderableOrbitDisc(const ghoul::Dictionary& dictionary) setBoundingSphere(_size + _offset.value().y * _size); _texturePath = absPath(dictionary.value(TextureInfo.identifier)); - _textureFile = std::make_unique(_texturePath); - - _texturePath.onChange([&]() { _textureIsDirty = true; }); + _texturePath.onChange([&]() { _texture->loadFromFile(_texturePath); }); addProperty(_texturePath); - _textureFile->setCallback([&](const File&) { _textureIsDirty = true; }); - _eccentricity = static_cast( dictionary.value(EccentricityInfo.identifier) ); @@ -158,12 +152,17 @@ RenderableOrbitDisc::RenderableOrbitDisc(const ghoul::Dictionary& dictionary) addProperty(_eccentricity); addProperty(_opacity); - - _plane = std::make_unique(planeSize()); } bool RenderableOrbitDisc::isReady() const { - return _shader && _texture; + return _shader && _texture && _plane; +} + +void RenderableOrbitDisc::initialize() { + _texture = std::make_unique( + ghoul::opengl::Texture::FilterMode::AnisotropicMipMap + ); + _plane = std::make_unique(planeSize()); } void RenderableOrbitDisc::initializeGL() { @@ -175,15 +174,15 @@ void RenderableOrbitDisc::initializeGL() { ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); + _texture->loadFromFile(_texturePath); + _texture->uploadToGpu(); + _plane->initialize(); - loadTexture(); } void RenderableOrbitDisc::deinitializeGL() { _plane->deinitialize(); _plane = nullptr; - - _textureFile = nullptr; _texture = nullptr; global::renderEngine->removeRenderProgram(_shader.get()); @@ -240,33 +239,7 @@ void RenderableOrbitDisc::update(const UpdateData&) { _planeIsDirty = false; } - if (_textureIsDirty) { - loadTexture(); - _textureIsDirty = false; - } -} - -void RenderableOrbitDisc::loadTexture() { - if (!_texturePath.value().empty()) { - std::unique_ptr texture = - ghoul::io::TextureReader::ref().loadTexture(absPath(_texturePath)); - - if (texture) { - LDEBUGC( - "RenderableOrbitDisc", - fmt::format("Loaded texture from '{}'", absPath(_texturePath)) - ); - _texture = std::move(texture); - - _texture->uploadTexture(); - _texture->setFilter(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); - - _textureFile = std::make_unique(_texturePath); - _textureFile->setCallback( - [&](const ghoul::filesystem::File&) { _textureIsDirty = true; } - ); - } - } + _texture->update(); } float RenderableOrbitDisc::planeSize() const { diff --git a/modules/exoplanets/rendering/renderableorbitdisc.h b/modules/exoplanets/rendering/renderableorbitdisc.h index 1aea4ae413..8a3be1b5d7 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.h +++ b/modules/exoplanets/rendering/renderableorbitdisc.h @@ -29,9 +29,9 @@ #include #include #include +#include #include #include -#include #include namespace ghoul::filesystem { class File; } @@ -47,6 +47,7 @@ class RenderableOrbitDisc : public Renderable { public: RenderableOrbitDisc(const ghoul::Dictionary& dictionary); + void initialize() override; void initializeGL() override; void deinitializeGL() override; @@ -58,8 +59,6 @@ public: static documentation::Documentation Documentation(); private: - void loadTexture(); - // Computes the size of the plane quad using the relevant properties float planeSize() const; @@ -71,12 +70,10 @@ private: std::unique_ptr _shader = nullptr; UniformCache(modelViewProjection, offset, opacity, texture, eccentricity, semiMajorAxis) _uniformCache; - std::unique_ptr _texture = nullptr; - std::unique_ptr _textureFile; std::unique_ptr _plane; + std::unique_ptr _texture; - bool _textureIsDirty = false; bool _planeIsDirty = false; }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8ad4ff0933..f095c64271 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -143,6 +143,7 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/rendering/renderengine.cpp ${OPENSPACE_BASE_DIR}/src/rendering/renderengine_lua.inl ${OPENSPACE_BASE_DIR}/src/rendering/screenspacerenderable.cpp + ${OPENSPACE_BASE_DIR}/src/rendering/texturecomponent.cpp ${OPENSPACE_BASE_DIR}/src/rendering/transferfunction.cpp ${OPENSPACE_BASE_DIR}/src/rendering/volumeraycaster.cpp ${OPENSPACE_BASE_DIR}/src/scene/asset.cpp @@ -323,6 +324,7 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboard.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboarditem.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/framebufferrenderer.h + ${OPENSPACE_BASE_DIR}/include/openspace/rendering/deferredcaster.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/deferredcasterlistener.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/deferredcastermanager.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/loadingscreen.h @@ -333,11 +335,11 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderable.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderer.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/renderengine.h - ${OPENSPACE_BASE_DIR}/include/openspace/rendering/volume.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/screenspacerenderable.h - ${OPENSPACE_BASE_DIR}/include/openspace/rendering/deferredcaster.h - ${OPENSPACE_BASE_DIR}/include/openspace/rendering/volumeraycaster.h + ${OPENSPACE_BASE_DIR}/include/openspace/rendering/texturecomponent.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/transferfunction.h + ${OPENSPACE_BASE_DIR}/include/openspace/rendering/volume.h + ${OPENSPACE_BASE_DIR}/include/openspace/rendering/volumeraycaster.h ${OPENSPACE_BASE_DIR}/include/openspace/scene/asset.h ${OPENSPACE_BASE_DIR}/include/openspace/scene/assetlistener.h ${OPENSPACE_BASE_DIR}/include/openspace/scene/assetloader.h diff --git a/src/rendering/texturecomponent.cpp b/src/rendering/texturecomponent.cpp new file mode 100644 index 0000000000..62e9aabf5a --- /dev/null +++ b/src/rendering/texturecomponent.cpp @@ -0,0 +1,96 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include + +namespace { + constexpr const char* _loggerCat = "TextureComponent"; +} // namespace + +namespace openspace { + +TextureComponent::TextureComponent(const Texture::FilterMode filterMode, bool watchFile) + : _filterMode(filterMode), _shouldWatchFile(watchFile) +{} + +ghoul::opengl::Texture* TextureComponent::texture() const { + return _texture.get(); +} + +void TextureComponent::bind() { + ghoul_assert(_texture, "Texture must be loaded before binding"); + _texture->bind(); +} + +void TextureComponent::uploadToGpu() { + if (!_texture) { + LERROR("Could not upload texture to GPU. Texture not loaded"); + return; + } + _texture->uploadTexture(); + _texture->setFilter(_filterMode); +} + +void TextureComponent::loadFromFile(const std::string& path) { + if (!path.empty()) { + using namespace ghoul::io; + using namespace ghoul::opengl; + std::unique_ptr texture = TextureReader::ref().loadTexture( + absPath(path) + ); + + if (texture) { + LDEBUG(fmt::format("Loaded texture from '{}'", absPath(path))); + _texture = nullptr; + _texture = std::move(texture); + + _textureFile = std::make_unique(path); + if (_shouldWatchFile) { + _textureFile->setCallback( + [&](const ghoul::filesystem::File&) { _fileIsDirty = true; } + ); + } + + _fileIsDirty = false; + _textureIsDirty = true; + } + } +} + +void TextureComponent::update() { + if (_fileIsDirty) { + loadFromFile(_textureFile->path()); + } + + if (_textureIsDirty) { + uploadToGpu(); + _textureIsDirty = false; + } +} +} // namespace openspace From 37aa7c6ab41e6c7fb6726f167d32223ba9bff16c Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Wed, 13 Jan 2021 15:51:52 +0100 Subject: [PATCH 04/41] Tiny cleanup --- modules/base/rendering/renderabledisc.cpp | 2 +- modules/exoplanets/rendering/renderableorbitdisc.cpp | 6 ++---- modules/exoplanets/rendering/renderableorbitdisc.h | 4 +--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index cb29d17b28..817e9e0eb2 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -142,7 +142,7 @@ void RenderableDisc::initialize() { void RenderableDisc::initializeGL() { _shader = global::renderEngine->buildRenderProgram( - "RingProgram", + "DiscProgram", absPath("${MODULE_BASE}/shaders/disc_vs.glsl"), absPath("${MODULE_BASE}/shaders/disc_fs.glsl") ); diff --git a/modules/exoplanets/rendering/renderableorbitdisc.cpp b/modules/exoplanets/rendering/renderableorbitdisc.cpp index 891380ddc3..2e726f8c9b 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.cpp +++ b/modules/exoplanets/rendering/renderableorbitdisc.cpp @@ -47,7 +47,7 @@ namespace { "Texture", "Texture", "This value is the path to a texture on disk that contains a one-dimensional " - "texture which is used for these rings." + "texture which is used for the color." }; static const openspace::properties::Property::PropertyInfo SizeInfo = { @@ -121,8 +121,6 @@ RenderableOrbitDisc::RenderableOrbitDisc(const ghoul::Dictionary& dictionary) , _eccentricity(EccentricityInfo, 0.f, 0.f, 1.f) , _offset(OffsetInfo, glm::vec2(0.f), glm::vec2(0.f), glm::vec2(1.f)) { - using ghoul::filesystem::File; - documentation::testSpecificationAndThrow( Documentation(), dictionary, @@ -167,7 +165,7 @@ void RenderableOrbitDisc::initialize() { void RenderableOrbitDisc::initializeGL() { _shader = global::renderEngine->buildRenderProgram( - "OrbitdiscProgram", + "OrbitDiscProgram", absPath("${BASE}/modules/exoplanets/shaders/orbitdisc_vs.glsl"), absPath("${BASE}/modules/exoplanets/shaders/orbitdisc_fs.glsl") ); diff --git a/modules/exoplanets/rendering/renderableorbitdisc.h b/modules/exoplanets/rendering/renderableorbitdisc.h index 8a3be1b5d7..b467a9cb90 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.h +++ b/modules/exoplanets/rendering/renderableorbitdisc.h @@ -35,9 +35,7 @@ #include namespace ghoul::filesystem { class File; } -namespace ghoul::opengl { - class ProgramObject; -} // namespace ghoul::opengl +namespace ghoul::opengl { class ProgramObject; } // namespace ghoul::opengl namespace openspace { From fd835688b5edf3853fd21e764f3095914e813604 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Fri, 15 Jan 2021 10:18:42 +0100 Subject: [PATCH 05/41] Add a habitable zone renderable --- modules/base/rendering/renderabledisc.cpp | 29 +-- modules/base/rendering/renderabledisc.h | 4 +- modules/exoplanets/CMakeLists.txt | 2 + modules/exoplanets/exoplanetshelper.cpp | 44 ---- modules/exoplanets/exoplanetshelper.h | 11 - modules/exoplanets/exoplanetsmodule.cpp | 5 +- modules/exoplanets/exoplanetsmodule_lua.inl | 20 +- .../rendering/renderablehabitablezone.cpp | 195 ++++++++++++++++++ .../rendering/renderablehabitablezone.h | 60 ++++++ 9 files changed, 282 insertions(+), 88 deletions(-) create mode 100644 modules/exoplanets/rendering/renderablehabitablezone.cpp create mode 100644 modules/exoplanets/rendering/renderablehabitablezone.h diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index 817e9e0eb2..d4aa7e35f8 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -73,11 +73,6 @@ documentation::Documentation RenderableDisc::Documentation() { "Renderable Disc", "renderable_disc", { - { - "Type", - new StringEqualVerifier("RenderableDisc"), - Optional::No - }, { TextureInfo.identifier, new StringVerifier, @@ -87,7 +82,7 @@ documentation::Documentation RenderableDisc::Documentation() { { SizeInfo.identifier, new DoubleVerifier, - Optional::No, + Optional::Yes, SizeInfo.description }, { @@ -112,17 +107,19 @@ RenderableDisc::RenderableDisc(const ghoul::Dictionary& dictionary) "RenderableDisc" ); - _size = static_cast(dictionary.value(SizeInfo.identifier)); - setBoundingSphere(_size); - _size.onChange([&]() { _planeIsDirty = true; }); - addProperty(_size); - _texturePath = absPath(dictionary.value(TextureInfo.identifier)); _texturePath.onChange([&]() { _texture->loadFromFile(_texturePath); }); addProperty(_texturePath); + if (dictionary.hasKey(SizeInfo.identifier)) { + _size = static_cast(dictionary.value(SizeInfo.identifier)); + } + setBoundingSphere(_size); + _size.onChange([&]() { _planeIsDirty = true; }); + addProperty(_size); + if (dictionary.hasKey(WidthInfo.identifier)) { - _width = dictionary.value(WidthInfo.identifier); + _width = static_cast(dictionary.value(WidthInfo.identifier)); } addProperty(_width); @@ -137,7 +134,7 @@ void RenderableDisc::initialize() { _texture = std::make_unique( ghoul::opengl::Texture::FilterMode::AnisotropicMipMap ); - _plane = std::make_unique(2 * _size); + _plane = std::make_unique(planeSize()); } void RenderableDisc::initializeGL() { @@ -209,11 +206,15 @@ void RenderableDisc::update(const UpdateData&) { } if (_planeIsDirty) { - _plane->updateSize(2 * _size); + _plane->updateSize(planeSize()); _planeIsDirty = false; } _texture->update(); } +float RenderableDisc::planeSize() { + return 2 * _size; +} + } // namespace openspace diff --git a/modules/base/rendering/renderabledisc.h b/modules/base/rendering/renderabledisc.h index 886e2f9b74..acf8a3c134 100644 --- a/modules/base/rendering/renderabledisc.h +++ b/modules/base/rendering/renderabledisc.h @@ -55,7 +55,9 @@ public: static documentation::Documentation Documentation(); -private: +protected: + virtual float planeSize(); + properties::StringProperty _texturePath; properties::FloatProperty _size; properties::FloatProperty _width; diff --git a/modules/exoplanets/CMakeLists.txt b/modules/exoplanets/CMakeLists.txt index 85d59b86a9..1168030ed1 100644 --- a/modules/exoplanets/CMakeLists.txt +++ b/modules/exoplanets/CMakeLists.txt @@ -27,6 +27,7 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES exoplanetshelper.h exoplanetsmodule.h + rendering/renderablehabitablezone.h rendering/renderableorbitdisc.h tasks/exoplanetsdatapreparationtask.h ) @@ -36,6 +37,7 @@ set(SOURCE_FILES exoplanetshelper.cpp exoplanetsmodule.cpp exoplanetsmodule_lua.inl + rendering/renderablehabitablezone.cpp rendering/renderableorbitdisc.cpp tasks/exoplanetsdatapreparationtask.cpp ) diff --git a/modules/exoplanets/exoplanetshelper.cpp b/modules/exoplanets/exoplanetshelper.cpp index d0becf0cc9..17bf9b5fe8 100644 --- a/modules/exoplanets/exoplanetshelper.cpp +++ b/modules/exoplanets/exoplanetshelper.cpp @@ -136,50 +136,6 @@ glm::dmat3 computeSystemRotation(glm::dvec3 starPosition) { ); } -glm::vec2 computeHabitableZone(float teff, float luminosity) { - // Kopparapu's formula only considers stars with teff in range [2600, 7200] K. - // However, we want to use the formula for more stars, so add some flexibility to - // the teff boundaries - if (teff > 8000.f || teff < 2000.f) { - // For the other stars, use a method by Tom E. Morris: - // https://www.planetarybiology.com/calculating_habitable_zone.html - float inner = std::sqrt(luminosity / 1.1f); - float outer = std::sqrt(luminosity / 0.53f); - return glm::vec2(inner, outer); - } - - struct Coefficients { - float seffSun; - float a; - float b; - float c; - float d; - }; - - // Coefficients for planets of 1 Earth mass. Received from: - // https://depts.washington.edu/naivpl/sites/default/files/HZ_coefficients.dat - constexpr const Coefficients coefficients[] = { - // Inner boundary - Runaway greenhouse - {1.10700E+00f, 1.33200E-04f, 1.58000E-08f, -8.30800E-12f, -1.93100E-15f}, - // Outer boundary - Maximum greenhouse - {3.56000E-01f, 6.17100E-05f, 1.69800E-09f, -3.19800E-12f, -5.57500E-16f} - }; - - const float tstar = teff - 5780.f; - const float tstar2 = tstar * tstar; - - glm::vec2 distances; - for (int i = 0; i < 2; ++i) { - const Coefficients& coeffs = coefficients[i]; - float seff = coeffs.seffSun + (coeffs.a * tstar) + (coeffs.b * tstar2) + - (coeffs.c * tstar * tstar2) + (coeffs.d * tstar2 * tstar2); - - distances[i] = std::pow(luminosity / seff, 0.5f); - } - - return distances; -} - std::string createIdentifier(std::string name) { std::replace(name.begin(), name.end(), ' ', '_'); std::replace(name.begin(), name.end(), '.', '-'); diff --git a/modules/exoplanets/exoplanetshelper.h b/modules/exoplanets/exoplanetshelper.h index 43bf96e66a..527bdf4b01 100644 --- a/modules/exoplanets/exoplanetshelper.h +++ b/modules/exoplanets/exoplanetshelper.h @@ -108,17 +108,6 @@ glm::dmat4 computeOrbitPlaneRotationMatrix(float i, float bigom = 180.f, // so that x is pointing from star to the sun. glm::dmat3 computeSystemRotation(glm::dvec3 starPosition); -/** - * Compute the inner and outer boundary of the habitable zone of a star, accordring to - * formula and coefficients by Kopparapu et al. (2015) https://arxiv.org/abs/1404.5292 - * - * \param teff The effective temperature of the star, in Kelvin - * \param luminosity The luminosity of the star, in solar luminosities - * \return A vec2 with the lower and upper boundary in atronomical units, if a habitable - zone could be computed. Otherwise an std::nullopt - */ -glm::vec2 computeHabitableZone(float teff, float luminosity); - // Create an identifier without whitespaces std::string createIdentifier(std::string name); diff --git a/modules/exoplanets/exoplanetsmodule.cpp b/modules/exoplanets/exoplanetsmodule.cpp index b962f758e1..1fc47e97ec 100644 --- a/modules/exoplanets/exoplanetsmodule.cpp +++ b/modules/exoplanets/exoplanetsmodule.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -89,12 +90,14 @@ void ExoplanetsModule::internalInitialize(const ghoul::Dictionary&) { ghoul_assert(fTask, "No task factory existed"); fTask->registerClass("ExoplanetsDataPreparationTask"); fRenderable->registerClass("RenderableOrbitDisc"); + fRenderable->registerClass("RenderableHabitableZone"); } std::vector ExoplanetsModule::documentations() const { return { ExoplanetsDataPreparationTask::documentation(), - RenderableOrbitDisc::Documentation() + RenderableOrbitDisc::Documentation(), + RenderableHabitableZone::Documentation() }; } diff --git a/modules/exoplanets/exoplanetsmodule_lua.inl b/modules/exoplanets/exoplanetsmodule_lua.inl index 36ff160c40..22b53b13cd 100644 --- a/modules/exoplanets/exoplanetsmodule_lua.inl +++ b/modules/exoplanets/exoplanetsmodule_lua.inl @@ -413,11 +413,6 @@ void createExoplanetSystem(const std::string& starName) { bool hasLuminosity = !std::isnan(system.starData.luminosity); if (hasTeff && hasLuminosity) { - const glm::vec2 zone = computeHabitableZone( - system.starData.teff, - system.starData.luminosity - ); - float meanInclination = 0.f; for (const ExoplanetDataEntry& p : system.planetsData) { meanInclination += p.i; @@ -426,11 +421,6 @@ void createExoplanetSystem(const std::string& starName) { const glm::dmat4 rotation = computeOrbitPlaneRotationMatrix(meanInclination); const glm::dmat3 rotationMat3 = static_cast(rotation); - glm::vec2 limitsInMeter = zone * AU; - float half = 0.5f * (limitsInMeter[1] - limitsInMeter[0]); - float center = limitsInMeter[0] + half; - float relativeOffset = half / center; - constexpr const char* description = "The habitable zone is the region around a star in which an Earth-like " "planet can potentially have liquid water on its surface." @@ -446,16 +436,12 @@ void createExoplanetSystem(const std::string& starName) { "Parent = '" + starIdentifier + "'," "Enabled = true," "Renderable = {" - "Type = 'RenderableOrbitDisc'," + "Type = 'RenderableHabitableZone'," "Texture = openspace.absPath(" "openspace.createPixelImage('exo_habitable_zone', {0, 0.92, 0.81})" ")," - "Size = " + std::to_string(center) + "," - "Eccentricity = 0," - "Offset = { " + - std::to_string(relativeOffset) + ", " + - std::to_string(relativeOffset) + - "}," //min / max extend + "Luminosity = " + std::to_string(system.starData.luminosity) + "," + "EffectiveTemperature = " + std::to_string(system.starData.teff) + "," "Opacity = 0.05" "}," "Transform = {" diff --git a/modules/exoplanets/rendering/renderablehabitablezone.cpp b/modules/exoplanets/rendering/renderablehabitablezone.cpp new file mode 100644 index 0000000000..3d090b6975 --- /dev/null +++ b/modules/exoplanets/rendering/renderablehabitablezone.cpp @@ -0,0 +1,195 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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 + +namespace { + constexpr const char* _loggerCat = "RenderableHabitableZone"; + + constexpr openspace::properties::Property::PropertyInfo EffectiveTemperatureInfo = { + "EffectiveTemperature", + "Effective Temperature", + "The effective temperature of the corresponding star, in Kelvin." + "Used to compute the width and size of the disc." + }; + + constexpr openspace::properties::Property::PropertyInfo LuminosityInfo = { + "Luminosity", + "Luminosity", + "The luminosity of the corresponding star, in units of solar luminosities." + "Used to compute the width and size of the disc." + }; +} // namespace + +namespace openspace { + +documentation::Documentation RenderableHabitableZone::Documentation() { + using namespace documentation; + documentation::Documentation doc { + "Renderable Habitable Zone", + "exoplanets_renderable_habitable_zone", + { + { + "Type", + new StringEqualVerifier("RenderableHabitableZone"), + Optional::No + }, + { + EffectiveTemperatureInfo.identifier, + new DoubleVerifier, + Optional::No, + EffectiveTemperatureInfo.description + }, + { + LuminosityInfo.identifier, + new DoubleVerifier, + Optional::No, + LuminosityInfo.description + } + } + }; + + // @TODO cleanup + // Insert the parents documentation entries until we have a verifier that can deal + // with class hierarchy + documentation::Documentation parentDoc = RenderableDisc::Documentation(); + doc.entries.insert( + doc.entries.end(), + parentDoc.entries.begin(), + parentDoc.entries.end() + ); + + return doc; +} + +RenderableHabitableZone::RenderableHabitableZone(const ghoul::Dictionary& dictionary) + : RenderableDisc(dictionary) + , _teff(EffectiveTemperatureInfo, 5780.f, 0.f, 7.5e4f) + , _luminosity(LuminosityInfo, 1.f, 0.f, 1e8f) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "RenderableHabitableZone" + ); + + if (dictionary.hasKey(EffectiveTemperatureInfo.identifier)) { + _teff = static_cast( + dictionary.value(EffectiveTemperatureInfo.identifier) + ); + } + _teff.onChange([this]() { computeZone(); }); + addProperty(_teff); + + if (dictionary.hasKey(LuminosityInfo.identifier)) { + _luminosity = static_cast( + dictionary.value(LuminosityInfo.identifier) + ); + } + _luminosity.onChange([this]() { computeZone(); }); + addProperty(_luminosity); + + // Make parent's size related properties read only. We want to set them based on the + // given temperature and luminosity + _size.setReadOnly(true); + _width.setReadOnly(true); + + computeZone(); +} + +void RenderableHabitableZone::computeZone() { + glm::vec2 distancesInAu = computeKopparapuZoneBoundaries(_teff, _luminosity); + constexpr float AU = static_cast(distanceconstants::AstronomicalUnit); + const float inner = distancesInAu[0] * AU; + const float outer = distancesInAu[1] * AU; + + float discWidth = 0.f; + if (outer > 0.f) { + discWidth = (outer - inner) / outer; + } + + _size.set(outer); + _width.set(discWidth); +} + +glm::vec2 RenderableHabitableZone::computeKopparapuZoneBoundaries(float teff, + float luminosity) +{ + // Kopparapu's formula only considers stars with teff in range [2600, 7200] K. + // However, we want to use the formula for more stars, so add some flexibility to + // the teff boundaries + if (teff > 8000.f || teff < 2000.f) { + // For the other stars, use a method by Tom E. Morris: + // https://www.planetarybiology.com/calculating_habitable_zone.html + float inner = std::sqrt(luminosity / 1.1f); + float outer = std::sqrt(luminosity / 0.53f); + return glm::vec2(inner, outer); + } + + struct Coefficients { + float seffSun; + float a; + float b; + float c; + float d; + }; + + // Coefficients for planets of 1 Earth mass. Received from: + // https://depts.washington.edu/naivpl/sites/default/files/HZ_coefficients.dat + constexpr const Coefficients coefficients[] = { + // Inner boundary - Runaway greenhouse + {1.10700E+00f, 1.33200E-04f, 1.58000E-08f, -8.30800E-12f, -1.93100E-15f}, + // Outer boundary - Maximum greenhouse + {3.56000E-01f, 6.17100E-05f, 1.69800E-09f, -3.19800E-12f, -5.57500E-16f} + }; + + const float tstar = teff - 5780.f; + const float tstar2 = tstar * tstar; + + glm::vec2 distances; + for (int i = 0; i < 2; ++i) { + const Coefficients& coeffs = coefficients[i]; + float seff = coeffs.seffSun + (coeffs.a * tstar) + (coeffs.b * tstar2) + + (coeffs.c * tstar * tstar2) + (coeffs.d * tstar2 * tstar2); + + distances[i] = std::pow(luminosity / seff, 0.5f); + } + + return distances; +} + +} // namespace openspace diff --git a/modules/exoplanets/rendering/renderablehabitablezone.h b/modules/exoplanets/rendering/renderablehabitablezone.h new file mode 100644 index 0000000000..085d13a58e --- /dev/null +++ b/modules/exoplanets/rendering/renderablehabitablezone.h @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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_EXOPLANETS___RENDERABLEHABITABLEZONE___H__ +#define __OPENSPACE_MODULE_EXOPLANETS___RENDERABLEHABITABLEZONE___H__ + +#include +#include + +namespace openspace { + +namespace documentation { struct Documentation; } + +class RenderableHabitableZone : public RenderableDisc { +public: + RenderableHabitableZone(const ghoul::Dictionary& dictionary); + + static documentation::Documentation Documentation(); + +private: + void computeZone(); + + /** + * Compute the inner and outer boundary of the habitable zone of a star, accordring to + * formula and coefficients by Kopparapu et al. (2015) https://arxiv.org/abs/1404.5292 + * + * \param teff The effective temperature of the star, in Kelvin + * \param luminosity The luminosity of the star, in solar luminosities + * \return A vec2 with the lower and upper boundary in atronomical units + */ + glm::vec2 computeKopparapuZoneBoundaries(float teff, float luminosity); + + properties::FloatProperty _teff; + properties::FloatProperty _luminosity; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_EXOPLANETS___RENDERABLEHABITABLEZONE___H__ From c956795ac65a3086538aa8ff561920ac6b6ce02f Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Fri, 15 Jan 2021 11:02:04 +0100 Subject: [PATCH 06/41] Add habitable zone asset for our solar system --- data/assets/base.asset | 1 + .../scene/solarsystem/sun/habitablezone.asset | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 data/assets/scene/solarsystem/sun/habitablezone.asset diff --git a/data/assets/base.asset b/data/assets/base.asset index 989f888df3..c6b295ab4e 100644 --- a/data/assets/base.asset +++ b/data/assets/base.asset @@ -7,6 +7,7 @@ asset.require('./base_blank') -- Specifying which other assets should be loaded in this scene asset.require('scene/solarsystem/sun/sun') asset.require('scene/solarsystem/sun/glare') +asset.require('scene/solarsystem/sun/habitablezone') asset.require('scene/solarsystem/sun/default_layers') asset.require('scene/solarsystem/planets/planets') asset.require('scene/solarsystem/planets/default_layers') diff --git a/data/assets/scene/solarsystem/sun/habitablezone.asset b/data/assets/scene/solarsystem/sun/habitablezone.asset new file mode 100644 index 0000000000..3dbf0efe65 --- /dev/null +++ b/data/assets/scene/solarsystem/sun/habitablezone.asset @@ -0,0 +1,35 @@ +local assetHelper = asset.require("util/asset_helper") +local transforms = asset.require("./transforms") + +local color = {0, 1, 0.81}; +local texture = openspace.absPath(openspace.createPixelImage('sun_habitable_zone', color)); + +local HabitableZone = { + Identifier = "SunHabitableZone", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableHabitableZone", + Enabled = false, + Texture = texture, + EffectiveTemperature = 5780, -- Kelvin + Luminosity = 1, -- solar + Opacity = 0.06 + }, + GUI = { + Name = "Sun Habitable Zone", + Path = "/Solar System/Sun", + Description = "Habitable zone for the sun in our solar system." + } +} + +assetHelper.registerSceneGraphNodesAndExport(asset, { HabitableZone }) + +asset.meta = { + Name = "Sun Habitable Zone", + Version = "1.0", + Description = [[ The habitable zone around our sun]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"SunHabitableZone"} +} From 6380e5b307463084d9960999488c3d10f926750d Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Fri, 15 Jan 2021 15:17:43 +0100 Subject: [PATCH 07/41] Change plane size to radius rather than diameter --- modules/base/rendering/renderabledisc.cpp | 2 +- modules/exoplanets/rendering/renderableorbitdisc.cpp | 2 +- src/util/planegeometry.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index d4aa7e35f8..899a006640 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -214,7 +214,7 @@ void RenderableDisc::update(const UpdateData&) { } float RenderableDisc::planeSize() { - return 2 * _size; + return _size; } } // namespace openspace diff --git a/modules/exoplanets/rendering/renderableorbitdisc.cpp b/modules/exoplanets/rendering/renderableorbitdisc.cpp index 2e726f8c9b..5fdaaabfc2 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.cpp +++ b/modules/exoplanets/rendering/renderableorbitdisc.cpp @@ -243,7 +243,7 @@ void RenderableOrbitDisc::update(const UpdateData&) { float RenderableOrbitDisc::planeSize() const { float maxRadius = _size + _offset.value().y * _size; maxRadius *= (1.f + _eccentricity); - return 2.f * maxRadius; + return maxRadius; } } // namespace openspace diff --git a/src/util/planegeometry.cpp b/src/util/planegeometry.cpp index 33ee25fbc3..9a166574d7 100644 --- a/src/util/planegeometry.cpp +++ b/src/util/planegeometry.cpp @@ -44,7 +44,7 @@ PlaneGeometry::~PlaneGeometry() { bool PlaneGeometry::initialize() { // Initialize and upload to GPU - const glm::vec2 size = _size * 0.5f; + const glm::vec2 size = _size; struct VertexData { GLfloat x; From 2ae5a16697b39ce1b021128f918df1fc35d424e6 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 18 Jan 2021 13:34:50 +0100 Subject: [PATCH 08/41] Add option to purge texture from RAM after gpu upload --- .../openspace/rendering/texturecomponent.h | 11 ++++++++--- src/rendering/texturecomponent.cpp | 19 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/include/openspace/rendering/texturecomponent.h b/include/openspace/rendering/texturecomponent.h index 0046ea1cc0..2a7d94e681 100644 --- a/include/openspace/rendering/texturecomponent.h +++ b/include/openspace/rendering/texturecomponent.h @@ -39,11 +39,15 @@ class TextureComponent { public: TextureComponent() = default; - TextureComponent(const Texture::FilterMode filterMode, bool watchFile = true); + TextureComponent(const Texture::FilterMode filterMode, bool watchFile = true, + bool shouldPurge = true); ~TextureComponent() = default; Texture* texture() const; + void setShouldWatchFileForChanges(bool value); + void setShouldPurgeFromRAM(bool value); + void bind(); void uploadToGpu(); @@ -60,9 +64,10 @@ private: Texture::FilterMode _filterMode = Texture::FilterMode::LinearMipMap; bool _shouldWatchFile = true; + bool _shouldPurgeFromRAM = true; - bool _fileIsDirty = false; - bool _textureIsDirty = false; + bool _fileIsDirty; + bool _textureIsDirty; }; } // namespace openspace diff --git a/src/rendering/texturecomponent.cpp b/src/rendering/texturecomponent.cpp index 62e9aabf5a..c334ac851b 100644 --- a/src/rendering/texturecomponent.cpp +++ b/src/rendering/texturecomponent.cpp @@ -35,14 +35,25 @@ namespace { namespace openspace { -TextureComponent::TextureComponent(const Texture::FilterMode filterMode, bool watchFile) - : _filterMode(filterMode), _shouldWatchFile(watchFile) +TextureComponent::TextureComponent(const Texture::FilterMode filterMode, + bool watchFile, bool shouldPurge) + : _filterMode(filterMode) + , _shouldWatchFile(watchFile) + , _shouldPurgeFromRAM(shouldPurge) {} ghoul::opengl::Texture* TextureComponent::texture() const { return _texture.get(); } +void TextureComponent::setShouldWatchFileForChanges(bool value) { + _shouldWatchFile = value; +} + +void TextureComponent::setShouldPurgeFromRAM(bool value) { + _shouldPurgeFromRAM = value; +} + void TextureComponent::bind() { ghoul_assert(_texture, "Texture must be loaded before binding"); _texture->bind(); @@ -55,6 +66,9 @@ void TextureComponent::uploadToGpu() { } _texture->uploadTexture(); _texture->setFilter(_filterMode); + if (_shouldPurgeFromRAM) { + _texture->purgeFromRAM(); + } } void TextureComponent::loadFromFile(const std::string& path) { @@ -67,7 +81,6 @@ void TextureComponent::loadFromFile(const std::string& path) { if (texture) { LDEBUG(fmt::format("Loaded texture from '{}'", absPath(path))); - _texture = nullptr; _texture = std::move(texture); _textureFile = std::make_unique(path); From 968d0eea64c3c706447cdda2a55a5291bb9ca59b Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 18 Jan 2021 17:19:37 +0100 Subject: [PATCH 09/41] Move habitable zone renderable to space module --- modules/exoplanets/CMakeLists.txt | 2 -- modules/exoplanets/exoplanetsmodule.cpp | 3 --- modules/exoplanets/include.cmake | 3 +++ modules/space/CMakeLists.txt | 2 ++ modules/space/include.cmake | 3 +++ .../rendering/renderablehabitablezone.cpp | 7 +------ .../rendering/renderablehabitablezone.h | 0 modules/space/spacemodule.cpp | 5 +++-- 8 files changed, 12 insertions(+), 13 deletions(-) rename modules/{exoplanets => space}/rendering/renderablehabitablezone.cpp (97%) rename modules/{exoplanets => space}/rendering/renderablehabitablezone.h (100%) diff --git a/modules/exoplanets/CMakeLists.txt b/modules/exoplanets/CMakeLists.txt index 1168030ed1..85d59b86a9 100644 --- a/modules/exoplanets/CMakeLists.txt +++ b/modules/exoplanets/CMakeLists.txt @@ -27,7 +27,6 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES exoplanetshelper.h exoplanetsmodule.h - rendering/renderablehabitablezone.h rendering/renderableorbitdisc.h tasks/exoplanetsdatapreparationtask.h ) @@ -37,7 +36,6 @@ set(SOURCE_FILES exoplanetshelper.cpp exoplanetsmodule.cpp exoplanetsmodule_lua.inl - rendering/renderablehabitablezone.cpp rendering/renderableorbitdisc.cpp tasks/exoplanetsdatapreparationtask.cpp ) diff --git a/modules/exoplanets/exoplanetsmodule.cpp b/modules/exoplanets/exoplanetsmodule.cpp index 1fc47e97ec..d923266e51 100644 --- a/modules/exoplanets/exoplanetsmodule.cpp +++ b/modules/exoplanets/exoplanetsmodule.cpp @@ -24,7 +24,6 @@ #include -#include #include #include #include @@ -90,14 +89,12 @@ void ExoplanetsModule::internalInitialize(const ghoul::Dictionary&) { ghoul_assert(fTask, "No task factory existed"); fTask->registerClass("ExoplanetsDataPreparationTask"); fRenderable->registerClass("RenderableOrbitDisc"); - fRenderable->registerClass("RenderableHabitableZone"); } std::vector ExoplanetsModule::documentations() const { return { ExoplanetsDataPreparationTask::documentation(), RenderableOrbitDisc::Documentation(), - RenderableHabitableZone::Documentation() }; } diff --git a/modules/exoplanets/include.cmake b/modules/exoplanets/include.cmake index ffea0ac430..c186634837 100644 --- a/modules/exoplanets/include.cmake +++ b/modules/exoplanets/include.cmake @@ -1 +1,4 @@ set(DEFAULT_MODULE ON) +set (OPENSPACE_DEPENDENCIES + space +) diff --git a/modules/space/CMakeLists.txt b/modules/space/CMakeLists.txt index 2c1a4e5e48..8d7222bddc 100644 --- a/modules/space/CMakeLists.txt +++ b/modules/space/CMakeLists.txt @@ -27,6 +27,7 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES rendering/planetgeometry.h rendering/renderableconstellationbounds.h + rendering/renderablehabitablezone.h rendering/renderablerings.h rendering/renderableorbitalkepler.h rendering/renderablesatellites.h @@ -44,6 +45,7 @@ source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES rendering/planetgeometry.cpp rendering/renderableconstellationbounds.cpp + rendering/renderablehabitablezone.cpp rendering/renderablerings.cpp rendering/renderableorbitalkepler.cpp rendering/renderablesatellites.cpp diff --git a/modules/space/include.cmake b/modules/space/include.cmake index ffea0ac430..f5adeba225 100644 --- a/modules/space/include.cmake +++ b/modules/space/include.cmake @@ -1 +1,4 @@ set(DEFAULT_MODULE ON) +set (OPENSPACE_DEPENDENCIES + base +) diff --git a/modules/exoplanets/rendering/renderablehabitablezone.cpp b/modules/space/rendering/renderablehabitablezone.cpp similarity index 97% rename from modules/exoplanets/rendering/renderablehabitablezone.cpp rename to modules/space/rendering/renderablehabitablezone.cpp index 3d090b6975..927b2676a4 100644 --- a/modules/exoplanets/rendering/renderablehabitablezone.cpp +++ b/modules/space/rendering/renderablehabitablezone.cpp @@ -22,7 +22,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include #include #include @@ -63,11 +63,6 @@ documentation::Documentation RenderableHabitableZone::Documentation() { "Renderable Habitable Zone", "exoplanets_renderable_habitable_zone", { - { - "Type", - new StringEqualVerifier("RenderableHabitableZone"), - Optional::No - }, { EffectiveTemperatureInfo.identifier, new DoubleVerifier, diff --git a/modules/exoplanets/rendering/renderablehabitablezone.h b/modules/space/rendering/renderablehabitablezone.h similarity index 100% rename from modules/exoplanets/rendering/renderablehabitablezone.h rename to modules/space/rendering/renderablehabitablezone.h diff --git a/modules/space/spacemodule.cpp b/modules/space/spacemodule.cpp index cdc90d3768..95c576e14f 100644 --- a/modules/space/spacemodule.cpp +++ b/modules/space/spacemodule.cpp @@ -24,8 +24,8 @@ #include -#include #include +#include #include #include #include @@ -80,7 +80,7 @@ void SpaceModule::internalInitialize(const ghoul::Dictionary& dictionary) { fRenderable->registerClass( "RenderableConstellationBounds" ); - + fRenderable->registerClass("RenderableHabitableZone"); fRenderable->registerClass("RenderableRings"); fRenderable->registerClass("RenderableSatellites"); fRenderable->registerClass("RenderableSmallBody"); @@ -119,6 +119,7 @@ void SpaceModule::internalDeinitializeGL() { std::vector SpaceModule::documentations() const { return { RenderableConstellationBounds::Documentation(), + RenderableHabitableZone::Documentation(), RenderableRings::Documentation(), RenderableSatellites::Documentation(), RenderableSmallBody::Documentation(), From 10d615cdc8b4a220440e2b7746865254c8a01e1e Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Wed, 20 Jan 2021 13:16:36 +0100 Subject: [PATCH 10/41] Update disc rendering to not conflict with atmosphere --- modules/base/rendering/renderabledisc.cpp | 4 +++- modules/base/shaders/disc_fs.glsl | 6 +++--- modules/base/shaders/disc_vs.glsl | 15 ++++++++------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index 899a006640..90b749cbbd 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -124,6 +124,8 @@ RenderableDisc::RenderableDisc(const ghoul::Dictionary& dictionary) addProperty(_width); addProperty(_opacity); + + setRenderBin(Renderable::RenderBin::PostDeferredTransparent); } bool RenderableDisc::isReady() const { @@ -185,7 +187,7 @@ void RenderableDisc::render(const RenderData& data, RendererTasks&) { _shader->setUniform(_uniformCache.texture, unit); glEnablei(GL_BLEND, 0); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDepthMask(false); glDisable(GL_CULL_FACE); diff --git a/modules/base/shaders/disc_fs.glsl b/modules/base/shaders/disc_fs.glsl index 7d0d15dc1d..0c3f3761c4 100644 --- a/modules/base/shaders/disc_fs.glsl +++ b/modules/base/shaders/disc_fs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2020 * + * Copyright (c) 2014-2021 * * * * 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 * @@ -25,7 +25,7 @@ #include "fragment.glsl" in vec2 vs_st; -in vec4 vs_position; +in float vs_screenSpaceDepth; uniform sampler1D colorTexture; uniform float width; @@ -55,6 +55,6 @@ Fragment getFragment() { Fragment frag; frag.color = diffuse; - frag.depth = vs_position.w; + frag.depth = vs_screenSpaceDepth; return frag; } diff --git a/modules/base/shaders/disc_vs.glsl b/modules/base/shaders/disc_vs.glsl index a3f6cbedb6..05ae85dfd4 100644 --- a/modules/base/shaders/disc_vs.glsl +++ b/modules/base/shaders/disc_vs.glsl @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2020 * + * Copyright (c) 2014-2021 * * * * 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 * @@ -30,15 +30,16 @@ layout(location = 0) in vec2 in_position; layout(location = 1) in vec2 in_st; out vec2 vs_st; -out vec4 vs_position; +out float vs_screenSpaceDepth; uniform mat4 modelViewProjectionTransform; void main() { - vs_st = in_st; + vec4 position = vec4(in_position.xy, 0.0, 1.0); + vec4 positionScreenSpace = z_normalization(modelViewProjectionTransform * position); - vs_position = z_normalization( - modelViewProjectionTransform * vec4(in_position.xy, 0.0, 1.0) - ); - gl_Position = vs_position; + vs_st = in_st; + vs_screenSpaceDepth = positionScreenSpace.w; + + gl_Position = positionScreenSpace; } From d693dd0bbe78ea94891e3eecb3d9e3be0527185a Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Fri, 22 Jan 2021 14:33:01 +0100 Subject: [PATCH 11/41] Add rendering of optimistic vs conservative HZ boundaries --- modules/base/rendering/renderabledisc.cpp | 24 ++-- modules/base/rendering/renderabledisc.h | 7 +- modules/space/CMakeLists.txt | 2 + .../rendering/renderablehabitablezone.cpp | 112 ++++++++++++++++-- .../space/rendering/renderablehabitablezone.h | 15 ++- modules/space/shaders/habitablezone_fs.glsl | 90 ++++++++++++++ modules/space/shaders/habitablezone_vs.glsl | 45 +++++++ 7 files changed, 271 insertions(+), 24 deletions(-) create mode 100644 modules/space/shaders/habitablezone_fs.glsl create mode 100644 modules/space/shaders/habitablezone_vs.glsl diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index 90b749cbbd..4e47fe8cf7 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -122,7 +122,6 @@ RenderableDisc::RenderableDisc(const ghoul::Dictionary& dictionary) _width = static_cast(dictionary.value(WidthInfo.identifier)); } addProperty(_width); - addProperty(_opacity); setRenderBin(Renderable::RenderBin::PostDeferredTransparent); @@ -140,13 +139,7 @@ void RenderableDisc::initialize() { } void RenderableDisc::initializeGL() { - _shader = global::renderEngine->buildRenderProgram( - "DiscProgram", - absPath("${MODULE_BASE}/shaders/disc_vs.glsl"), - absPath("${MODULE_BASE}/shaders/disc_fs.glsl") - ); - - ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); + initializeShader(); _texture->loadFromFile(_texturePath); _texture->uploadToGpu(); @@ -204,7 +197,7 @@ void RenderableDisc::render(const RenderData& data, RendererTasks&) { void RenderableDisc::update(const UpdateData&) { if (_shader->isDirty()) { _shader->rebuildFromFile(); - ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); + updateUniformLocations(); } if (_planeIsDirty) { @@ -215,6 +208,19 @@ void RenderableDisc::update(const UpdateData&) { _texture->update(); } +void RenderableDisc::initializeShader() { + _shader = global::renderEngine->buildRenderProgram( + "DiscProgram", + absPath("${MODULE_BASE}/shaders/disc_vs.glsl"), + absPath("${MODULE_BASE}/shaders/disc_fs.glsl") + ); + updateUniformLocations(); +} + +void RenderableDisc::updateUniformLocations() { + ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); +} + float RenderableDisc::planeSize() { return _size; } diff --git a/modules/base/rendering/renderabledisc.h b/modules/base/rendering/renderabledisc.h index acf8a3c134..9c8fdd83b8 100644 --- a/modules/base/rendering/renderabledisc.h +++ b/modules/base/rendering/renderabledisc.h @@ -56,6 +56,9 @@ public: static documentation::Documentation Documentation(); protected: + virtual void initializeShader(); + virtual void updateUniformLocations(); + virtual float planeSize(); properties::StringProperty _texturePath; @@ -63,11 +66,13 @@ protected: properties::FloatProperty _width; std::unique_ptr _shader; - UniformCache(modelViewProjection, opacity, width, texture) _uniformCache; std::unique_ptr _plane; std::unique_ptr _texture; +private: + UniformCache(modelViewProjection, opacity, width, texture) _uniformCache; + bool _planeIsDirty = false; }; diff --git a/modules/space/CMakeLists.txt b/modules/space/CMakeLists.txt index 8d7222bddc..583e3e89ab 100644 --- a/modules/space/CMakeLists.txt +++ b/modules/space/CMakeLists.txt @@ -65,6 +65,8 @@ set(SHADER_FILES shaders/constellationbounds_vs.glsl shaders/debrisViz_fs.glsl shaders/debrisViz_vs.glsl + shaders/habitablezone_vs.glsl + shaders/habitablezone_fs.glsl shaders/rings_vs.glsl shaders/rings_fs.glsl shaders/star_fs.glsl diff --git a/modules/space/rendering/renderablehabitablezone.cpp b/modules/space/rendering/renderablehabitablezone.cpp index 927b2676a4..dbb3f9b268 100644 --- a/modules/space/rendering/renderablehabitablezone.cpp +++ b/modules/space/rendering/renderablehabitablezone.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,19 +41,31 @@ namespace { constexpr const char* _loggerCat = "RenderableHabitableZone"; + constexpr const std::array UniformNames = { + "modelViewProjectionTransform", "opacity", "width", "transferFunctionTexture", + "conservativeBounds", "showOptimistic" + }; + constexpr openspace::properties::Property::PropertyInfo EffectiveTemperatureInfo = { "EffectiveTemperature", "Effective Temperature", - "The effective temperature of the corresponding star, in Kelvin." + "The effective temperature of the corresponding star, in Kelvin. " "Used to compute the width and size of the disc." }; constexpr openspace::properties::Property::PropertyInfo LuminosityInfo = { "Luminosity", "Luminosity", - "The luminosity of the corresponding star, in units of solar luminosities." + "The luminosity of the corresponding star, in units of solar luminosities. " "Used to compute the width and size of the disc." }; + + constexpr openspace::properties::Property::PropertyInfo OptimisticInfo = { + "Optimistic", + "Optimistic" , + "If true, the habitable zone disc is rendered with the optimistic boundaries " + "rather than the conservative ones." + }; } // namespace namespace openspace { @@ -74,6 +87,12 @@ documentation::Documentation RenderableHabitableZone::Documentation() { new DoubleVerifier, Optional::No, LuminosityInfo.description + }, + { + OptimisticInfo.identifier, + new BoolVerifier, + Optional::Yes, + OptimisticInfo.description } } }; @@ -95,6 +114,7 @@ RenderableHabitableZone::RenderableHabitableZone(const ghoul::Dictionary& dictio : RenderableDisc(dictionary) , _teff(EffectiveTemperatureInfo, 5780.f, 0.f, 7.5e4f) , _luminosity(LuminosityInfo, 1.f, 0.f, 1e8f) + , _showOptimistic(OptimisticInfo, false) { documentation::testSpecificationAndThrow( Documentation(), @@ -118,6 +138,11 @@ RenderableHabitableZone::RenderableHabitableZone(const ghoul::Dictionary& dictio _luminosity.onChange([this]() { computeZone(); }); addProperty(_luminosity); + if (dictionary.hasKey(OptimisticInfo.identifier)) { + _showOptimistic = dictionary.value(OptimisticInfo.identifier); + } + addProperty(_showOptimistic); + // Make parent's size related properties read only. We want to set them based on the // given temperature and luminosity _size.setReadOnly(true); @@ -126,11 +151,65 @@ RenderableHabitableZone::RenderableHabitableZone(const ghoul::Dictionary& dictio computeZone(); } +void RenderableHabitableZone::render(const RenderData& data, RendererTasks&) { + _shader->activate(); + + glm::dmat4 modelTransform = + glm::translate(glm::dmat4(1.0), data.modelTransform.translation) * + glm::dmat4(data.modelTransform.rotation) * + glm::scale(glm::dmat4(1.0), glm::dvec3(data.modelTransform.scale)); + + glm::dmat4 modelViewTransform = data.camera.combinedViewMatrix() * modelTransform; + + _shader->setUniform( + _uniformCache.modelViewProjection, + data.camera.projectionMatrix() * glm::mat4(modelViewTransform) + ); + _shader->setUniform(_uniformCache.width, _width); + _shader->setUniform(_uniformCache.opacity, _opacity); + _shader->setUniform(_uniformCache.conservativeBounds, _conservativeBounds); + _shader->setUniform(_uniformCache.showOptimistic, _showOptimistic); + + ghoul::opengl::TextureUnit unit; + unit.activate(); + _texture->bind(); + _shader->setUniform(_uniformCache.texture, unit); + + glEnablei(GL_BLEND, 0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(false); + glDisable(GL_CULL_FACE); + + _plane->render(); + + _shader->deactivate(); + + // Restores GL State + global::renderEngine->openglStateCache().resetBlendState(); + global::renderEngine->openglStateCache().resetDepthState(); + global::renderEngine->openglStateCache().resetPolygonAndClippingState(); +} + +void RenderableHabitableZone::initializeShader() { + _shader = global::renderEngine->buildRenderProgram( + "HabitableZoneProgram", + absPath("${MODULE_SPACE}/shaders/habitablezone_vs.glsl"), + absPath("${MODULE_SPACE}/shaders/habitablezone_fs.glsl") + ); + ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); +} + +void RenderableHabitableZone::updateUniformLocations() { + ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); +} + void RenderableHabitableZone::computeZone() { - glm::vec2 distancesInAu = computeKopparapuZoneBoundaries(_teff, _luminosity); + glm::vec4 distancesInAu = computeKopparapuZoneBoundaries(_teff, _luminosity); constexpr float AU = static_cast(distanceconstants::AstronomicalUnit); const float inner = distancesInAu[0] * AU; - const float outer = distancesInAu[1] * AU; + const float innerConservative = distancesInAu[1] * AU; + const float outerConservative = distancesInAu[2] * AU; + const float outer = distancesInAu[3] * AU; float discWidth = 0.f; if (outer > 0.f) { @@ -139,20 +218,25 @@ void RenderableHabitableZone::computeZone() { _size.set(outer); _width.set(discWidth); + + // Compute the coservative bounds normalized by the size of the disc, i.e. in [0, 1] + _conservativeBounds = glm::vec2(innerConservative, outerConservative); + _conservativeBounds /= _size; } -glm::vec2 RenderableHabitableZone::computeKopparapuZoneBoundaries(float teff, +glm::vec4 RenderableHabitableZone::computeKopparapuZoneBoundaries(float teff, float luminosity) { // Kopparapu's formula only considers stars with teff in range [2600, 7200] K. // However, we want to use the formula for more stars, so add some flexibility to - // the teff boundaries + // the teff boundaries. + // OBS! This also prevents problems with too large values in the distance computation if (teff > 8000.f || teff < 2000.f) { // For the other stars, use a method by Tom E. Morris: // https://www.planetarybiology.com/calculating_habitable_zone.html float inner = std::sqrt(luminosity / 1.1f); float outer = std::sqrt(luminosity / 0.53f); - return glm::vec2(inner, outer); + return glm::vec4(inner, inner, outer, outer); } struct Coefficients { @@ -166,17 +250,21 @@ glm::vec2 RenderableHabitableZone::computeKopparapuZoneBoundaries(float teff, // Coefficients for planets of 1 Earth mass. Received from: // https://depts.washington.edu/naivpl/sites/default/files/HZ_coefficients.dat constexpr const Coefficients coefficients[] = { - // Inner boundary - Runaway greenhouse + // Optimistic Inner boundary - Recent Venus + {1.77600E+00f, 2.13600E-04f, 2.53300E-08f, -1.33200E-11f, -3.09700E-15f}, + // Conservative Inner boundary - Runaway greenhouse {1.10700E+00f, 1.33200E-04f, 1.58000E-08f, -8.30800E-12f, -1.93100E-15f}, - // Outer boundary - Maximum greenhouse - {3.56000E-01f, 6.17100E-05f, 1.69800E-09f, -3.19800E-12f, -5.57500E-16f} + // Conservative Outer boundary - Maximum greenhouse + {3.56000E-01f, 6.17100E-05f, 1.69800E-09f, -3.19800E-12f, -5.57500E-16f}, + // Optimistic Outer boundary - Early Mars + {3.20000E-01f, 5.54700E-05f, 1.52600E-09f, -2.87400E-12f, -5.01100E-16f} }; const float tstar = teff - 5780.f; const float tstar2 = tstar * tstar; - glm::vec2 distances; - for (int i = 0; i < 2; ++i) { + glm::vec4 distances; + for (int i = 0; i < 4; ++i) { const Coefficients& coeffs = coefficients[i]; float seff = coeffs.seffSun + (coeffs.a * tstar) + (coeffs.b * tstar2) + (coeffs.c * tstar * tstar2) + (coeffs.d * tstar2 * tstar2); diff --git a/modules/space/rendering/renderablehabitablezone.h b/modules/space/rendering/renderablehabitablezone.h index 085d13a58e..1503a57d21 100644 --- a/modules/space/rendering/renderablehabitablezone.h +++ b/modules/space/rendering/renderablehabitablezone.h @@ -36,9 +36,13 @@ class RenderableHabitableZone : public RenderableDisc { public: RenderableHabitableZone(const ghoul::Dictionary& dictionary); + void render(const RenderData& data, RendererTasks& rendererTask) override; + static documentation::Documentation Documentation(); private: + void initializeShader() override; + void updateUniformLocations() override; void computeZone(); /** @@ -47,12 +51,19 @@ private: * * \param teff The effective temperature of the star, in Kelvin * \param luminosity The luminosity of the star, in solar luminosities - * \return A vec2 with the lower and upper boundary in atronomical units + * \return A vec4 with the boundaries in atronomical units, in the order: + optimistic inner, conservative inner, conservative outer, optimistic outer */ - glm::vec2 computeKopparapuZoneBoundaries(float teff, float luminosity); + glm::vec4 computeKopparapuZoneBoundaries(float teff, float luminosity); properties::FloatProperty _teff; properties::FloatProperty _luminosity; + properties::BoolProperty _showOptimistic; + + glm::vec2 _conservativeBounds; + + UniformCache(modelViewProjection, opacity, width, texture, + conservativeBounds, showOptimistic) _uniformCache; }; } // namespace openspace diff --git a/modules/space/shaders/habitablezone_fs.glsl b/modules/space/shaders/habitablezone_fs.glsl new file mode 100644 index 0000000000..d139dc0cfd --- /dev/null +++ b/modules/space/shaders/habitablezone_fs.glsl @@ -0,0 +1,90 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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 vec2 vs_st; +in float vs_screenSpaceDepth; + +uniform sampler1D transferFunctionTexture; +uniform float width; +uniform float opacity; +uniform vec2 conservativeBounds; +uniform bool showOptimistic; + +// Remap the radius to texture coordinates in the trasfer function texture. The texture +// is treated as a linear scale where the color represent too cold to too hot. Account +// for the conservative bounds my mapping one third of the texture ouside each boundary. +// All parameters \in [0,1], where 1.0 corresponds to the max radius. +float computeTextureCoord(float radius, float innerRadius, + float conservativeInner, float conservativeOuter) +{ + const float t1 = 1.0 / 3.0; + const float t2 = 2.0 / 3.0; + + if(radius < conservativeInner) { + float t = (radius - innerRadius) / (conservativeInner - innerRadius); + return mix(0.0, t1, t); + } + else if (radius > conservativeOuter) { + float t = (radius - conservativeOuter) / (1.0 - conservativeOuter); + return mix(t2, 1.0, t); + } + else { + float t = (radius - conservativeInner) / (conservativeOuter - conservativeInner); + return mix(t1, t2, t); + } +} + +Fragment getFragment() { + // Moving the origin to the center + vec2 st = (vs_st - vec2(0.5)) * 2.0; + + // The length of the texture coordinates vector is our distance from the center + float radius = length(st); + float innerRadius = 1.0 - width; + + // We only want to consider ring-like objects so we need to discard everything else + if (radius > 1.0 || radius < innerRadius) { + discard; + } + + float consInner = conservativeBounds.x; + float consOuter = conservativeBounds.y; + bool outsideConservative = (radius < consInner) || (radius > consOuter); + + if (!showOptimistic && outsideConservative) { + discard; + } + + float texCoord = computeTextureCoord(radius, innerRadius, consInner, consOuter); + + vec4 diffuse = texture(transferFunctionTexture, texCoord); + diffuse.a *= opacity; + + Fragment frag; + frag.color = diffuse; + frag.depth = vs_screenSpaceDepth; + return frag; +} diff --git a/modules/space/shaders/habitablezone_vs.glsl b/modules/space/shaders/habitablezone_vs.glsl new file mode 100644 index 0000000000..05ae85dfd4 --- /dev/null +++ b/modules/space/shaders/habitablezone_vs.glsl @@ -0,0 +1,45 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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" + +layout(location = 0) in vec2 in_position; +layout(location = 1) in vec2 in_st; + +out vec2 vs_st; +out float vs_screenSpaceDepth; + +uniform mat4 modelViewProjectionTransform; + +void main() { + vec4 position = vec4(in_position.xy, 0.0, 1.0); + vec4 positionScreenSpace = z_normalization(modelViewProjectionTransform * position); + + vs_st = in_st; + vs_screenSpaceDepth = positionScreenSpace.w; + + gl_Position = positionScreenSpace; +} From e90b52af939d999b5c8e647e0d6a13afa3ced3e7 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 25 Jan 2021 14:01:49 +0100 Subject: [PATCH 12/41] Add wrapping mode to texture component --- include/openspace/rendering/texturecomponent.h | 9 +++++---- modules/base/rendering/renderabledisc.cpp | 8 +++++--- .../exoplanets/rendering/renderableorbitdisc.cpp | 5 ++--- src/rendering/texturecomponent.cpp | 16 +++++++++------- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/include/openspace/rendering/texturecomponent.h b/include/openspace/rendering/texturecomponent.h index 2a7d94e681..17d6197ff1 100644 --- a/include/openspace/rendering/texturecomponent.h +++ b/include/openspace/rendering/texturecomponent.h @@ -39,12 +39,12 @@ class TextureComponent { public: TextureComponent() = default; - TextureComponent(const Texture::FilterMode filterMode, bool watchFile = true, - bool shouldPurge = true); ~TextureComponent() = default; Texture* texture() const; + void setFilterMode(Texture::FilterMode filterMode); + void setWrapping(Texture::WrappingMode wrapping); void setShouldWatchFileForChanges(bool value); void setShouldPurgeFromRAM(bool value); @@ -63,11 +63,12 @@ private: std::unique_ptr _texture = nullptr; Texture::FilterMode _filterMode = Texture::FilterMode::LinearMipMap; + Texture::WrappingMode _wrappingMode = Texture::WrappingMode::Repeat; bool _shouldWatchFile = true; bool _shouldPurgeFromRAM = true; - bool _fileIsDirty; - bool _textureIsDirty; + bool _fileIsDirty = false; + bool _textureIsDirty = false; }; } // namespace openspace diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index 4e47fe8cf7..c1b77bea85 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -132,9 +132,11 @@ bool RenderableDisc::isReady() const { } void RenderableDisc::initialize() { - _texture = std::make_unique( - ghoul::opengl::Texture::FilterMode::AnisotropicMipMap - ); + _texture = std::make_unique(); + _texture->setFilterMode(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + _texture->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToEdge); + _texture->setShouldWatchFileForChanges(true); + _plane = std::make_unique(planeSize()); } diff --git a/modules/exoplanets/rendering/renderableorbitdisc.cpp b/modules/exoplanets/rendering/renderableorbitdisc.cpp index 5fdaaabfc2..47f6d8726f 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.cpp +++ b/modules/exoplanets/rendering/renderableorbitdisc.cpp @@ -157,9 +157,8 @@ bool RenderableOrbitDisc::isReady() const { } void RenderableOrbitDisc::initialize() { - _texture = std::make_unique( - ghoul::opengl::Texture::FilterMode::AnisotropicMipMap - ); + _texture = std::make_unique(); + _texture->setFilterMode(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); _plane = std::make_unique(planeSize()); } diff --git a/src/rendering/texturecomponent.cpp b/src/rendering/texturecomponent.cpp index c334ac851b..95785482a8 100644 --- a/src/rendering/texturecomponent.cpp +++ b/src/rendering/texturecomponent.cpp @@ -35,17 +35,18 @@ namespace { namespace openspace { -TextureComponent::TextureComponent(const Texture::FilterMode filterMode, - bool watchFile, bool shouldPurge) - : _filterMode(filterMode) - , _shouldWatchFile(watchFile) - , _shouldPurgeFromRAM(shouldPurge) -{} - ghoul::opengl::Texture* TextureComponent::texture() const { return _texture.get(); } +void TextureComponent::setFilterMode(Texture::FilterMode filterMode) { + _filterMode = filterMode; +} + +void TextureComponent::setWrapping(Texture::WrappingMode wrapping) { + _wrappingMode = wrapping; +} + void TextureComponent::setShouldWatchFileForChanges(bool value) { _shouldWatchFile = value; } @@ -66,6 +67,7 @@ void TextureComponent::uploadToGpu() { } _texture->uploadTexture(); _texture->setFilter(_filterMode); + _texture->setWrapping(_wrappingMode); if (_shouldPurgeFromRAM) { _texture->purgeFromRAM(); } From 3fcc02d0b5a93f9888dfe4165e5dccd1c27c0316 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Tue, 26 Jan 2021 11:31:51 +0100 Subject: [PATCH 13/41] Update habitable zone textures --- .../milkyway/exoplanets/exoplanets_textures.asset | 13 +++++++++++-- .../scene/solarsystem/sun/habitablezone.asset | 12 ++++++++---- modules/exoplanets/exoplanetsmodule_lua.inl | 8 ++++---- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset index 287b29d61e..62470b7bc9 100644 --- a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset @@ -1,7 +1,16 @@ -local TexturesPath = asset.syncedResource({ +local ExoplanetsTexturesPath = asset.syncedResource({ Name = "Exoplanet Textures", Type = "HttpSynchronization", Identifier = "exoplanets_textures", Version = 1 }) -asset.export("TexturesPath", TexturesPath) + +local HabitableZoneTexturesPath = asset.syncedResource({ + Name = "Habitable Zone Textures", + Type = "HttpSynchronization", + Identifier = "habitable_zone_textures", + Version = 1 +}) + +asset.export("ExoplanetsTexturesPath", ExoplanetsTexturesPath) +asset.export("HabitableZoneTexturesPath", HabitableZoneTexturesPath) diff --git a/data/assets/scene/solarsystem/sun/habitablezone.asset b/data/assets/scene/solarsystem/sun/habitablezone.asset index 3dbf0efe65..a6ad8a4378 100644 --- a/data/assets/scene/solarsystem/sun/habitablezone.asset +++ b/data/assets/scene/solarsystem/sun/habitablezone.asset @@ -1,8 +1,12 @@ local assetHelper = asset.require("util/asset_helper") local transforms = asset.require("./transforms") -local color = {0, 1, 0.81}; -local texture = openspace.absPath(openspace.createPixelImage('sun_habitable_zone', color)); +local TexturesPath = asset.syncedResource({ + Type = "HttpSynchronization", + Name = "Habitable Zone Textures", + Identifier = "habitable_zone_textures", + Version = 1 +}) local HabitableZone = { Identifier = "SunHabitableZone", @@ -10,10 +14,10 @@ local HabitableZone = { Renderable = { Type = "RenderableHabitableZone", Enabled = false, - Texture = texture, + Texture = TexturesPath .. "/hot_to_cold_faded.png", EffectiveTemperature = 5780, -- Kelvin Luminosity = 1, -- solar - Opacity = 0.06 + Opacity = 0.1 }, GUI = { Name = "Sun Habitable Zone", diff --git a/modules/exoplanets/exoplanetsmodule_lua.inl b/modules/exoplanets/exoplanetsmodule_lua.inl index 22b53b13cd..662eb2243c 100644 --- a/modules/exoplanets/exoplanetsmodule_lua.inl +++ b/modules/exoplanets/exoplanetsmodule_lua.inl @@ -55,6 +55,8 @@ constexpr const char* NoDataTextureFile = "${SYNC}/http/exoplanets_textures/1/grid-32.png"; constexpr const char* DiscTextureFile = "${SYNC}/http/exoplanets_textures/1/disc_texture.png"; +constexpr const char* HabitableZoneTextureFile = + "${SYNC}/http/habitable_zone_textures/1/green_faded.png"; constexpr const float AU = static_cast(distanceconstants::AstronomicalUnit); constexpr const float SolarRadius = static_cast(distanceconstants::SolarRadius); @@ -437,12 +439,10 @@ void createExoplanetSystem(const std::string& starName) { "Enabled = true," "Renderable = {" "Type = 'RenderableHabitableZone'," - "Texture = openspace.absPath(" - "openspace.createPixelImage('exo_habitable_zone', {0, 0.92, 0.81})" - ")," + "Texture = openspace.absPath('" + HabitableZoneTextureFile + "')," "Luminosity = " + std::to_string(system.starData.luminosity) + "," "EffectiveTemperature = " + std::to_string(system.starData.teff) + "," - "Opacity = 0.05" + "Opacity = 0.07" "}," "Transform = {" "Rotation = {" From f7e1d48d83c51f09cb99ae60f55c3a58e6d4cf06 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Tue, 26 Jan 2021 13:11:08 +0100 Subject: [PATCH 14/41] Solve interpolation issue at egde of texture (closes issue #1430) --- modules/exoplanets/rendering/renderableorbitdisc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/exoplanets/rendering/renderableorbitdisc.cpp b/modules/exoplanets/rendering/renderableorbitdisc.cpp index 47f6d8726f..15bd28072f 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.cpp +++ b/modules/exoplanets/rendering/renderableorbitdisc.cpp @@ -159,6 +159,7 @@ bool RenderableOrbitDisc::isReady() const { void RenderableOrbitDisc::initialize() { _texture = std::make_unique(); _texture->setFilterMode(ghoul::opengl::Texture::FilterMode::AnisotropicMipMap); + _texture->setWrapping(ghoul::opengl::Texture::WrappingMode::ClampToEdge); _plane = std::make_unique(planeSize()); } From 8aad6f98bcfb26edaf0093268b7bc00e8f2852a6 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Tue, 26 Jan 2021 15:24:23 +0100 Subject: [PATCH 15/41] Fix missing new line --- data/assets/examples/discs.asset | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/assets/examples/discs.asset b/data/assets/examples/discs.asset index 9b90c51c9e..2d103f7b80 100644 --- a/data/assets/examples/discs.asset +++ b/data/assets/examples/discs.asset @@ -19,4 +19,4 @@ local BasicDisc = { assetHelper.registerSceneGraphNodesAndExport(asset, { BasicDisc -}) \ No newline at end of file +}) From 54c5b052a582de21df40111025caa4808750b2de Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Fri, 29 Jan 2021 13:14:40 +0100 Subject: [PATCH 16/41] Update disc and habitable zone textures --- .../milkyway/exoplanets/exoplanets_textures.asset | 2 +- modules/exoplanets/exoplanetsmodule_lua.inl | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset index 62470b7bc9..1b4c40dd2a 100644 --- a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset @@ -2,7 +2,7 @@ local ExoplanetsTexturesPath = asset.syncedResource({ Name = "Exoplanet Textures", Type = "HttpSynchronization", Identifier = "exoplanets_textures", - Version = 1 + Version = 2 }) local HabitableZoneTexturesPath = asset.syncedResource({ diff --git a/modules/exoplanets/exoplanetsmodule_lua.inl b/modules/exoplanets/exoplanetsmodule_lua.inl index 662eb2243c..00bd2bb2c9 100644 --- a/modules/exoplanets/exoplanetsmodule_lua.inl +++ b/modules/exoplanets/exoplanetsmodule_lua.inl @@ -50,13 +50,13 @@ constexpr const char* LookUpTablePath = "${SYNC}/http/exoplanets_data/2/lookup.t constexpr const char* ExoplanetsDataPath = "${SYNC}/http/exoplanets_data/2/exoplanets_data.bin"; -constexpr const char* StarTextureFile = "${SYNC}/http/exoplanets_textures/1/sun.jpg"; +constexpr const char* StarTextureFile = "${SYNC}/http/exoplanets_textures/2/sun.jpg"; constexpr const char* NoDataTextureFile = - "${SYNC}/http/exoplanets_textures/1/grid-32.png"; + "${SYNC}/http/exoplanets_textures/2/grid-32.png"; constexpr const char* DiscTextureFile = - "${SYNC}/http/exoplanets_textures/1/disc_texture.png"; + "${SYNC}/http/exoplanets_textures/2/disc_bw_texture.png"; constexpr const char* HabitableZoneTextureFile = - "${SYNC}/http/habitable_zone_textures/1/green_faded.png"; + "${SYNC}/http/habitable_zone_textures/1/hot_to_cold_faded.png"; constexpr const float AU = static_cast(distanceconstants::AstronomicalUnit); constexpr const float SolarRadius = static_cast(distanceconstants::SolarRadius); @@ -389,7 +389,7 @@ void createExoplanetSystem(const std::string& starName) { std::to_string(lowerOffset) + ", " + std::to_string(upperOffset) + "}," //min / max extend - "Opacity = 0.3" + "Opacity = 0.25" "}," "Transform = {" "Rotation = {" @@ -442,6 +442,7 @@ void createExoplanetSystem(const std::string& starName) { "Texture = openspace.absPath('" + HabitableZoneTextureFile + "')," "Luminosity = " + std::to_string(system.starData.luminosity) + "," "EffectiveTemperature = " + std::to_string(system.starData.teff) + "," + "Optimistic = true," "Opacity = 0.07" "}," "Transform = {" From 06787e4f77247ddaa2e2ff9d0348080b5f9c2572 Mon Sep 17 00:00:00 2001 From: Gene Payne Date: Fri, 29 Jan 2021 10:17:13 -0700 Subject: [PATCH 17/41] Globebrowsing Fade-In/Out Fix and Assets Updates (Issue #1209) (#1476) * Fixed fade out algorithm to use correct distance from globe center * Updated planet labels in asset files to match fixed fade-out algorithm * Changed variable name and removed mistakenly-added file --- .../dwarf_planets/pluto/charon/charon.asset | 9 +++++---- .../scene/solarsystem/dwarf_planets/pluto/pluto.asset | 9 +++++---- .../assets/scene/solarsystem/planets/earth/earth.asset | 10 +++++----- .../scene/solarsystem/planets/earth/moon/moon.asset | 3 ++- .../planets/jupiter/callisto/callisto.asset | 3 ++- .../solarsystem/planets/jupiter/europa/europa.asset | 9 +++++---- .../planets/jupiter/ganymede/ganymede.asset | 7 ++++--- .../scene/solarsystem/planets/jupiter/io/io.asset | 9 +++++---- data/assets/scene/solarsystem/planets/mars/mars.asset | 9 +++++---- .../scene/solarsystem/planets/mercury/mercury.asset | 8 +++++--- .../scene/solarsystem/planets/saturn/dione/dione.asset | 7 ++++--- .../planets/saturn/enceladus/enceladus.asset | 9 +++++---- .../solarsystem/planets/saturn/iapetus/iapetus.asset | 9 +++++---- .../scene/solarsystem/planets/saturn/mimas/mimas.asset | 7 ++++--- .../scene/solarsystem/planets/saturn/rhea/rhea.asset | 7 ++++--- .../solarsystem/planets/saturn/tethys/tethys.asset | 9 +++++---- .../scene/solarsystem/planets/saturn/titan/titan.asset | 7 ++++--- .../assets/scene/solarsystem/planets/venus/venus.asset | 10 ++++++---- modules/globebrowsing/src/globelabelscomponent.cpp | 6 +++--- 19 files changed, 83 insertions(+), 64 deletions(-) diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/charon/charon.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/charon/charon.asset index 35e6fe6436..4b6aa574c2 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/charon/charon.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/charon/charon.asset @@ -31,16 +31,17 @@ local Charon = { Enable = false, FileName = labelsPath .. "/charon.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 14.0, + LabelsFontSize = 40.0, LabelsSize = 8.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 2000000.0, + FadeOutStartingDistance = 800000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 250000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset index 667c201781..5299ebc5dd 100644 --- a/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset +++ b/data/assets/scene/solarsystem/dwarf_planets/pluto/pluto.asset @@ -31,16 +31,17 @@ local Pluto = { Enable = false, FileName = labelsPath .. "/pluto.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 14.0, + LabelsFontSize = 28.0, LabelsSize = 8.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 4000000.0, + FadeOutStartingDistance = 650000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 500000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/earth/earth.asset b/data/assets/scene/solarsystem/planets/earth/earth.asset index b4f793cc69..e66cb53329 100644 --- a/data/assets/scene/solarsystem/planets/earth/earth.asset +++ b/data/assets/scene/solarsystem/planets/earth/earth.asset @@ -26,15 +26,15 @@ local Earth = { Enable = false, FileName = labelsPath .. "/Earth.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 41.0, - LabelsSize = 0.52, + LabelsFontSize = 40.0, + LabelsSize = 4.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - LabelsFadeOutEnabled = false, - FadeInStartingDistance = 50000.0, - FadeOutStartingDistance = 80000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 300000.0, + FadeOutStartingDistance = 10000.0, LabelsForceDomeRendering = true, LabelsDistanceEPS = 1500000.0, LabelsColor = { 1.0, 0.0, 0.0 } diff --git a/data/assets/scene/solarsystem/planets/earth/moon/moon.asset b/data/assets/scene/solarsystem/planets/earth/moon/moon.asset index ace7442735..160b880246 100644 --- a/data/assets/scene/solarsystem/planets/earth/moon/moon.asset +++ b/data/assets/scene/solarsystem/planets/earth/moon/moon.asset @@ -43,8 +43,9 @@ local Moon = { LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, + LabelsFadeOutEnabled = true, FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + FadeOutStartingDistance = 100000.0, LabelsForceDomeRendering = true, LabelsDistanceEPS = 1350000.0, LabelsColor = { 1.0, 1.0, 0.0 } diff --git a/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset b/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset index 09c2888303..580e6c72ca 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/callisto/callisto.asset @@ -37,8 +37,9 @@ local Callisto = { LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, + LabelsFadeOutEnabled = true, FadeInStartingDistance = 15000000.0, - FadeOutStartingDistance = 1000000.0, + FadeOutStartingDistance = 5000000.0, LabelsForceDomeRendering = true, LabelsDistanceEPS = 1350000.0, LabelsColor = { 1.0, 1.0, 0.0 } diff --git a/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset b/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset index 6be8e60814..d3e29eba08 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/europa/europa.asset @@ -32,15 +32,16 @@ local Europa = { FileName = labelsPath .. "/europa.labels", LabelAlignmentOption = "Horizontally", -- or Circularly LabelsFontSize = 40.0, - LabelsSize = 10.5, + LabelsSize = 10.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 15000000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 8000000.0, + FadeOutStartingDistance = 5000000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 700000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset b/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset index c93b359f3e..0e53d189d1 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/ganymede/ganymede.asset @@ -37,10 +37,11 @@ local Ganymede = { LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 15000000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 8000000.0, + FadeOutStartingDistance = 2250000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 1750000.0, LabelsColor = {1.0, 1.0, 0.0} } }, diff --git a/data/assets/scene/solarsystem/planets/jupiter/io/io.asset b/data/assets/scene/solarsystem/planets/jupiter/io/io.asset index e64cbfe431..20f2d5a2b6 100644 --- a/data/assets/scene/solarsystem/planets/jupiter/io/io.asset +++ b/data/assets/scene/solarsystem/planets/jupiter/io/io.asset @@ -32,15 +32,16 @@ local Io = { FileName = labelsPath .. "/io.labels", LabelAlignmentOption = "Horizontally", -- or Circularly LabelsFontSize = 40.0, - LabelsSize = 10.5, + LabelsSize = 10.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 15000000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 8500000.0, + FadeOutStartingDistance = 4000000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 1000000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/mars/mars.asset b/data/assets/scene/solarsystem/planets/mars/mars.asset index 8bdd08008d..e96320563a 100644 --- a/data/assets/scene/solarsystem/planets/mars/mars.asset +++ b/data/assets/scene/solarsystem/planets/mars/mars.asset @@ -27,15 +27,16 @@ local Mars = { FileName = labelsPath .. "/mars.labels", LabelAlignmentOption = "Horizontally", -- or Circularly LabelsFontSize = 14.0, - LabelsSize = 8.0, + LabelsSize = 9.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 2000000.0, + FadeOutStartingDistance = 750000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 2500000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/mercury/mercury.asset b/data/assets/scene/solarsystem/planets/mercury/mercury.asset index c2a9ca1584..4ce1efa083 100644 --- a/data/assets/scene/solarsystem/planets/mercury/mercury.asset +++ b/data/assets/scene/solarsystem/planets/mercury/mercury.asset @@ -27,13 +27,15 @@ local Mercury = { Enable = false, FileName = labelsPath .. "/Mercury.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 40.0, + LabelsFontSize = 22.0, LabelsSize = 10.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, - FadeInStartingDistance = 40000000.0, - FadeOutStartingDistance = 80000.0, + LabelsFadeInEnabled = true, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 5000000.0, + FadeOutStartingDistance = 1800000.0, LabelsForceDomeRendering = true, LabelsDistanceEPS = 1500000.0, LabelsColor = { 1.0, 1.0, 0.0 } diff --git a/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset b/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset index bee85a6396..34b711430c 100644 --- a/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset +++ b/data/assets/scene/solarsystem/planets/saturn/dione/dione.asset @@ -29,16 +29,17 @@ local Dione = { Enable = false, FileName = labelsPath .. "/dione.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 14.0, + LabelsFontSize = 32.0, LabelsSize = 8.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 3500000.0, FadeOutStartingDistance = 1000000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 200000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset b/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset index bb66e85ba2..4dd5e1cff5 100644 --- a/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset +++ b/data/assets/scene/solarsystem/planets/saturn/enceladus/enceladus.asset @@ -29,16 +29,17 @@ local Enceladus = { Enable = false, FileName = labelsPath .. "/enceladus.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 14.0, + LabelsFontSize = 22.0, LabelsSize = 8.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 1000000.0, + FadeOutStartingDistance = 500000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 100000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset b/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset index ec01d7b69a..fbe22a9aec 100644 --- a/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset +++ b/data/assets/scene/solarsystem/planets/saturn/iapetus/iapetus.asset @@ -29,16 +29,17 @@ local Iapetus = { Enable = false, FileName = labelsPath .. "/iapetus.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 14.0, + LabelsFontSize = 30.0, LabelsSize = 8.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 3500000.0, + FadeOutStartingDistance = 600000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 250000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset b/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset index 1ba8d19d3f..7f1b4efab1 100644 --- a/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset +++ b/data/assets/scene/solarsystem/planets/saturn/mimas/mimas.asset @@ -35,10 +35,11 @@ local Mimas = { LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 1000000.0, + FadeOutStartingDistance = 400000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 25000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset b/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset index fbbe12a40d..83792b1a33 100644 --- a/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset +++ b/data/assets/scene/solarsystem/planets/saturn/rhea/rhea.asset @@ -29,16 +29,17 @@ local Rhea = { Enable = false, FileName = labelsPath .. "/rhea.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 14.0, + LabelsFontSize = 40.0, LabelsSize = 8.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 2500000.0, FadeOutStartingDistance = 1000000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 250000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset b/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset index e4440665df..18a97e75c3 100644 --- a/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset +++ b/data/assets/scene/solarsystem/planets/saturn/tethys/tethys.asset @@ -29,16 +29,17 @@ local Tethys = { Enable = false, FileName = labelsPath .. "/tethys.labels", LabelAlignmentOption = "Horizontally", -- or Circularly - LabelsFontSize = 14.0, + LabelsFontSize = 24.0, LabelsSize = 8.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 1500000.0, + FadeOutStartingDistance = 500000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 1350000.0, + LabelsDistanceEPS = 200000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset b/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset index dd947f3214..eaa851c833 100644 --- a/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset +++ b/data/assets/scene/solarsystem/planets/saturn/titan/titan.asset @@ -30,13 +30,14 @@ local Titan = { FileName = labelsPath .. "/titan.labels", LabelAlignmentOption = "Horizontally", -- or Circularly LabelsFontSize = 14.0, - LabelsSize = 8.0, + LabelsSize = 10.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 7500000.0, + FadeOutStartingDistance = 6000000.0, LabelsForceDomeRendering = true, LabelsDistanceEPS = 1350000.0, LabelsColor = { 1.0, 1.0, 0.0 } diff --git a/data/assets/scene/solarsystem/planets/venus/venus.asset b/data/assets/scene/solarsystem/planets/venus/venus.asset index 0f4c1cbe9f..b1bb529e58 100644 --- a/data/assets/scene/solarsystem/planets/venus/venus.asset +++ b/data/assets/scene/solarsystem/planets/venus/venus.asset @@ -30,15 +30,17 @@ local Venus = { FileName = labelsPath .. "/venus.labels", LabelAlignmentOption = "Horizontally", -- or Circularly LabelsFontSize = 40.0, - LabelsSize = 12.0, + LabelsSize = 10.0, LabelsMinSize = 1.0, LabelsMaxSize = 1500.0, ProximityEnabled = false, LabelsFadeInEnabled = true, - FadeInStartingDistance = 500000.0, - FadeOutStartingDistance = 1000000.0, + LabelsFadeInEnabled = true, + LabelsFadeOutEnabled = true, + FadeInStartingDistance = 7000000.0, + FadeOutStartingDistance = 2000000.0, LabelsForceDomeRendering = true, - LabelsDistanceEPS = 3500000.0, + LabelsDistanceEPS = 4000000.0, LabelsColor = { 1.0, 1.0, 0.0 } } }, diff --git a/modules/globebrowsing/src/globelabelscomponent.cpp b/modules/globebrowsing/src/globelabelscomponent.cpp index 549f4d5a4d..944f9ff220 100644 --- a/modules/globebrowsing/src/globelabelscomponent.cpp +++ b/modules/globebrowsing/src/globelabelscomponent.cpp @@ -50,7 +50,7 @@ namespace { constexpr const char* KeyLabelsFileName = "FileName"; - constexpr const double LabelFadeRangeConst = 1500.0; + constexpr const double LabelFadeOutLimitAltitudeMeters = 25000.0; constexpr const double RangeAngularCoefConst = 0.8; constexpr const float MinOpacityValueConst = 0.009f; @@ -674,10 +674,10 @@ void GlobeLabelsComponent::draw(const RenderData& data) { if (_labelsFadeOutEnabled) { glm::dvec2 fadeRange = glm::dvec2( - averageRadius + _labelsMinHeight + LabelFadeRangeConst + averageRadius + _labelsMinHeight + LabelFadeOutLimitAltitude_meters ); fadeRange.x += _labelsFadeOutDist; - double a = RangeAngularCoefConst / (fadeRange.x - fadeRange.y); + double a = 1.0 / (fadeRange.x - fadeRange.y); double b = -(fadeRange.y / (fadeRange.x - fadeRange.y)); double funcValue = a * distanceCameraGlobeWorld + b; varyingOpacity *= static_cast(std::min(funcValue, 1.0)); From 5ef4bc610e0c877f1f598563885f93fbc8d7f75f Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 31 Jan 2021 23:59:21 +0100 Subject: [PATCH 18/41] Fix issue with the item velocity not showing up correctly and with varying lengths --- modules/base/dashboard/dashboarditemvelocity.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/base/dashboard/dashboarditemvelocity.cpp b/modules/base/dashboard/dashboarditemvelocity.cpp index 4de13a891c..fb284650ab 100644 --- a/modules/base/dashboard/dashboarditemvelocity.cpp +++ b/modules/base/dashboard/dashboarditemvelocity.cpp @@ -162,7 +162,7 @@ void DashboardItemVelocity::render(glm::vec2& penPosition) { *_font, penPosition, fmt::format( - "Camera velocity: {} {}/s", dist.first, dist.second + "Camera velocity: {:.4f} {}/s", dist.first, dist.second ) ); penPosition.y -= _font->height(); From 29fe22b912dac6fe1565a9ba2822ef332b237693 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 1 Feb 2021 00:04:28 +0100 Subject: [PATCH 19/41] Fix small spelling error in variable definition --- modules/globebrowsing/src/globelabelscomponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/globebrowsing/src/globelabelscomponent.cpp b/modules/globebrowsing/src/globelabelscomponent.cpp index 944f9ff220..7632011bbd 100644 --- a/modules/globebrowsing/src/globelabelscomponent.cpp +++ b/modules/globebrowsing/src/globelabelscomponent.cpp @@ -674,7 +674,7 @@ void GlobeLabelsComponent::draw(const RenderData& data) { if (_labelsFadeOutEnabled) { glm::dvec2 fadeRange = glm::dvec2( - averageRadius + _labelsMinHeight + LabelFadeOutLimitAltitude_meters + averageRadius + _labelsMinHeight + LabelFadeOutLimitAltitudeMeters ); fadeRange.x += _labelsFadeOutDist; double a = 1.0 / (fadeRange.x - fadeRange.y); From ef091a1044ffc4f87c8098c54fe78a698e8b8794 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Fri, 29 Jan 2021 16:59:16 +0100 Subject: [PATCH 20/41] Adress review comments --- data/assets/base.asset | 4 +- .../milkyway/exoplanets/exoplanets_data.asset | 9 +++ .../exoplanets/exoplanets_textures.asset | 23 +++--- .../habitable_zone_textures.asset | 17 ++++ .../scene/solarsystem/sun/habitablezone.asset | 10 +-- .../openspace/rendering/texturecomponent.h | 14 ++-- include/openspace/util/planegeometry.h | 6 +- modules/base/rendering/renderabledisc.cpp | 6 +- modules/base/rendering/renderabledisc.h | 2 +- modules/base/shaders/disc_fs.glsl | 8 +- modules/base/shaders/disc_vs.glsl | 4 +- modules/exoplanets/exoplanetsmodule.cpp | 2 +- modules/exoplanets/exoplanetsmodule_lua.inl | 16 ++-- .../rendering/renderablehabitablezone.cpp | 62 ++++++++------- .../space/rendering/renderablehabitablezone.h | 2 +- modules/space/shaders/habitablezone_fs.glsl | 7 +- modules/space/shaders/habitablezone_vs.glsl | 4 +- src/rendering/texturecomponent.cpp | 8 +- src/util/planegeometry.cpp | 79 ++++++++----------- 19 files changed, 148 insertions(+), 135 deletions(-) create mode 100644 data/assets/scene/milkyway/habitable_zones/habitable_zone_textures.asset diff --git a/data/assets/base.asset b/data/assets/base.asset index c6b295ab4e..d4fce76bfa 100644 --- a/data/assets/base.asset +++ b/data/assets/base.asset @@ -22,9 +22,11 @@ asset.require('scene/milkyway/constellations/constellation_keybinds') asset.require('scene/milkyway/objects/orionnebula/orionnebula') asset.require('util/launcher_images') -local assetHelper = asset.require('util/asset_helper') +-- For exoplanet system visualizations asset.require('scene/milkyway/exoplanets/exoplanets_data') asset.require('scene/milkyway/exoplanets/exoplanets_textures') + +local assetHelper = asset.require('util/asset_helper') asset.require('scene/digitaluniverse/2dF') asset.require('scene/digitaluniverse/2mass') asset.require('scene/digitaluniverse/6dF') diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset index b75b5aa1a5..518f093344 100644 --- a/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset @@ -5,3 +5,12 @@ local DataPath = asset.syncedResource({ Version = 2 }) asset.export("DataPath", DataPath) + +asset.meta = { + Name = "Exoplanet Data", + Version = "2.0", + Description = [[ The data that is used for the exoplanet systems.]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", +} diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset index 1b4c40dd2a..9efd63b65c 100644 --- a/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_textures.asset @@ -1,16 +1,19 @@ -local ExoplanetsTexturesPath = asset.syncedResource({ +asset.require('./../habitable_zones/habitable_zone_textures') + +local TexturesPath = asset.syncedResource({ Name = "Exoplanet Textures", Type = "HttpSynchronization", Identifier = "exoplanets_textures", Version = 2 }) +asset.export("TexturesPath", TexturesPath) -local HabitableZoneTexturesPath = asset.syncedResource({ - Name = "Habitable Zone Textures", - Type = "HttpSynchronization", - Identifier = "habitable_zone_textures", - Version = 1 -}) - -asset.export("ExoplanetsTexturesPath", ExoplanetsTexturesPath) -asset.export("HabitableZoneTexturesPath", HabitableZoneTexturesPath) +asset.meta = { + Name = "Exoplanet Textures", + Version = "2.0", + Description = [[ Adds all textures that are required for the exoplanet system + visualizations]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", +} diff --git a/data/assets/scene/milkyway/habitable_zones/habitable_zone_textures.asset b/data/assets/scene/milkyway/habitable_zones/habitable_zone_textures.asset new file mode 100644 index 0000000000..0687c70693 --- /dev/null +++ b/data/assets/scene/milkyway/habitable_zones/habitable_zone_textures.asset @@ -0,0 +1,17 @@ +local TexturesPath = asset.syncedResource({ + Name = "Habitable Zone Textures", + Type = "HttpSynchronization", + Identifier = "habitable_zone_textures", + Version = 1 +}) +asset.export("TexturesPath", TexturesPath) + +asset.meta = { + Name = "Habitable Zone Textures", + Version = "1.0", + Description = [[ Default textures that can be used for the habitable zone + rendering]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", +} diff --git a/data/assets/scene/solarsystem/sun/habitablezone.asset b/data/assets/scene/solarsystem/sun/habitablezone.asset index a6ad8a4378..15c65237d0 100644 --- a/data/assets/scene/solarsystem/sun/habitablezone.asset +++ b/data/assets/scene/solarsystem/sun/habitablezone.asset @@ -1,12 +1,6 @@ local assetHelper = asset.require("util/asset_helper") local transforms = asset.require("./transforms") - -local TexturesPath = asset.syncedResource({ - Type = "HttpSynchronization", - Name = "Habitable Zone Textures", - Identifier = "habitable_zone_textures", - Version = 1 -}) +local textures = asset.require('scene/milkyway/habitable_zones/habitable_zone_textures').TexturesPath local HabitableZone = { Identifier = "SunHabitableZone", @@ -14,7 +8,7 @@ local HabitableZone = { Renderable = { Type = "RenderableHabitableZone", Enabled = false, - Texture = TexturesPath .. "/hot_to_cold_faded.png", + Texture = textures .. "/hot_to_cold_faded.png", EffectiveTemperature = 5780, -- Kelvin Luminosity = 1, -- solar Opacity = 0.1 diff --git a/include/openspace/rendering/texturecomponent.h b/include/openspace/rendering/texturecomponent.h index 17d6197ff1..5c4d905a7c 100644 --- a/include/openspace/rendering/texturecomponent.h +++ b/include/openspace/rendering/texturecomponent.h @@ -25,9 +25,7 @@ #ifndef __OPENSPACE_CORE___TEXTURECOMPONENT___H__ #define __OPENSPACE_CORE___TEXTURECOMPONENT___H__ -#include #include -#include namespace ghoul::filesystem { class File; } namespace ghoul::opengl {class Texture; } @@ -35,13 +33,11 @@ namespace ghoul::opengl {class Texture; } namespace openspace { class TextureComponent { +public: using Texture = ghoul::opengl::Texture; -public: - TextureComponent() = default; - ~TextureComponent() = default; - - Texture* texture() const; + const Texture* texture() const; + Texture* texture(); void setFilterMode(Texture::FilterMode filterMode); void setWrapping(Texture::WrappingMode wrapping); @@ -59,8 +55,8 @@ public: void update(); private: - std::unique_ptr _textureFile = nullptr; - std::unique_ptr _texture = nullptr; + std::unique_ptr _textureFile; + std::unique_ptr _texture; Texture::FilterMode _filterMode = Texture::FilterMode::LinearMipMap; Texture::WrappingMode _wrappingMode = Texture::WrappingMode::Repeat; diff --git a/include/openspace/util/planegeometry.h b/include/openspace/util/planegeometry.h index 93d4b656c1..2b29302c79 100644 --- a/include/openspace/util/planegeometry.h +++ b/include/openspace/util/planegeometry.h @@ -37,14 +37,16 @@ public: ~PlaneGeometry(); - bool initialize(); + void initialize(); void deinitialize(); void render(); - void updateSize(const glm::vec2 size); + void updateSize(const glm::vec2& size); void updateSize(const float size); private: + void updateGeometry(); + GLuint _vaoId = 0; GLuint _vBufferId = 0; glm::vec2 _size = glm::vec2(0.f); diff --git a/modules/base/rendering/renderabledisc.cpp b/modules/base/rendering/renderabledisc.cpp index c1b77bea85..c3de8be2b1 100644 --- a/modules/base/rendering/renderabledisc.cpp +++ b/modules/base/rendering/renderabledisc.cpp @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2020 * + * Copyright (c) 2014-2021 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -37,7 +37,7 @@ #include namespace { - constexpr const char* _loggerCat = "RenderableDisc"; + constexpr const char _loggerCat[] = "RenderableDisc"; constexpr const std::array UniformNames = { "modelViewProjectionTransform", "opacity", "width", "colorTexture" @@ -223,7 +223,7 @@ void RenderableDisc::updateUniformLocations() { ghoul::opengl::updateUniformLocations(*_shader, _uniformCache, UniformNames); } -float RenderableDisc::planeSize() { +float RenderableDisc::planeSize() const { return _size; } diff --git a/modules/base/rendering/renderabledisc.h b/modules/base/rendering/renderabledisc.h index 9c8fdd83b8..ccd5d52288 100644 --- a/modules/base/rendering/renderabledisc.h +++ b/modules/base/rendering/renderabledisc.h @@ -59,7 +59,7 @@ protected: virtual void initializeShader(); virtual void updateUniformLocations(); - virtual float planeSize(); + virtual float planeSize() const; properties::StringProperty _texturePath; properties::FloatProperty _size; diff --git a/modules/base/shaders/disc_fs.glsl b/modules/base/shaders/disc_fs.glsl index 0c3f3761c4..839d6464f5 100644 --- a/modules/base/shaders/disc_fs.glsl +++ b/modules/base/shaders/disc_fs.glsl @@ -32,15 +32,13 @@ uniform float width; uniform float opacity; Fragment getFragment() { - // Moving the origin to the center - vec2 st = (vs_st - vec2(0.5)) * 2.0; - // The length of the texture coordinates vector is our distance from the center - float radius = length(st); + float radius = length(vs_st); // We only want to consider ring-like objects so we need to discard everything else - if (radius > 1.0) + if (radius > 1.0) { discard; + } // Remapping the texture coordinates // Radius \in [0,1], diff --git a/modules/base/shaders/disc_vs.glsl b/modules/base/shaders/disc_vs.glsl index 05ae85dfd4..d5796d62d9 100644 --- a/modules/base/shaders/disc_vs.glsl +++ b/modules/base/shaders/disc_vs.glsl @@ -38,7 +38,9 @@ void main() { vec4 position = vec4(in_position.xy, 0.0, 1.0); vec4 positionScreenSpace = z_normalization(modelViewProjectionTransform * position); - vs_st = in_st; + // Moving the origin to the center + vs_st = (in_st - vec2(0.5)) * 2.0; + vs_screenSpaceDepth = positionScreenSpace.w; gl_Position = positionScreenSpace; diff --git a/modules/exoplanets/exoplanetsmodule.cpp b/modules/exoplanets/exoplanetsmodule.cpp index d923266e51..b962f758e1 100644 --- a/modules/exoplanets/exoplanetsmodule.cpp +++ b/modules/exoplanets/exoplanetsmodule.cpp @@ -94,7 +94,7 @@ void ExoplanetsModule::internalInitialize(const ghoul::Dictionary&) { std::vector ExoplanetsModule::documentations() const { return { ExoplanetsDataPreparationTask::documentation(), - RenderableOrbitDisc::Documentation(), + RenderableOrbitDisc::Documentation() }; } diff --git a/modules/exoplanets/exoplanetsmodule_lua.inl b/modules/exoplanets/exoplanetsmodule_lua.inl index 00bd2bb2c9..659ddc8350 100644 --- a/modules/exoplanets/exoplanetsmodule_lua.inl +++ b/modules/exoplanets/exoplanetsmodule_lua.inl @@ -39,23 +39,23 @@ #include namespace { - constexpr const char* _loggerCat = "ExoplanetsModule"; + constexpr const char _loggerCat[] = "ExoplanetsModule"; } // namespace namespace openspace::exoplanets::luascriptfunctions { -constexpr const char* ExoplanetsGuiPath = "/Milky Way/Exoplanets/Exoplanet Systems/"; +constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/"; -constexpr const char* LookUpTablePath = "${SYNC}/http/exoplanets_data/2/lookup.txt"; -constexpr const char* ExoplanetsDataPath = +constexpr const char LookUpTablePath[] = "${SYNC}/http/exoplanets_data/2/lookup.txt"; +constexpr const char ExoplanetsDataPath[] = "${SYNC}/http/exoplanets_data/2/exoplanets_data.bin"; -constexpr const char* StarTextureFile = "${SYNC}/http/exoplanets_textures/2/sun.jpg"; -constexpr const char* NoDataTextureFile = +constexpr const char StarTextureFile[] = "${SYNC}/http/exoplanets_textures/2/sun.jpg"; +constexpr const char NoDataTextureFile[] = "${SYNC}/http/exoplanets_textures/2/grid-32.png"; -constexpr const char* DiscTextureFile = +constexpr const char DiscTextureFile[] = "${SYNC}/http/exoplanets_textures/2/disc_bw_texture.png"; -constexpr const char* HabitableZoneTextureFile = +constexpr const char HabitableZoneTextureFile[] = "${SYNC}/http/habitable_zone_textures/1/hot_to_cold_faded.png"; constexpr const float AU = static_cast(distanceconstants::AstronomicalUnit); diff --git a/modules/space/rendering/renderablehabitablezone.cpp b/modules/space/rendering/renderablehabitablezone.cpp index dbb3f9b268..09d5cfc7f7 100644 --- a/modules/space/rendering/renderablehabitablezone.cpp +++ b/modules/space/rendering/renderablehabitablezone.cpp @@ -39,7 +39,7 @@ #include namespace { - constexpr const char* _loggerCat = "RenderableHabitableZone"; + constexpr const char _loggerCat[] = "RenderableHabitableZone"; constexpr const std::array UniformNames = { "modelViewProjectionTransform", "opacity", "width", "transferFunctionTexture", @@ -204,28 +204,28 @@ void RenderableHabitableZone::updateUniformLocations() { } void RenderableHabitableZone::computeZone() { - glm::vec4 distancesInAu = computeKopparapuZoneBoundaries(_teff, _luminosity); - constexpr float AU = static_cast(distanceconstants::AstronomicalUnit); - const float inner = distancesInAu[0] * AU; - const float innerConservative = distancesInAu[1] * AU; - const float outerConservative = distancesInAu[2] * AU; - const float outer = distancesInAu[3] * AU; + glm::dvec4 distancesInAu = computeKopparapuZoneBoundaries(_teff, _luminosity); + constexpr const double AU = distanceconstants::AstronomicalUnit; + const double inner = distancesInAu[0] * AU; + const double innerConservative = distancesInAu[1] * AU; + const double outerConservative = distancesInAu[2] * AU; + const double outer = distancesInAu[3] * AU; - float discWidth = 0.f; - if (outer > 0.f) { + double discWidth = 0.0; + if (outer > 0.0) { discWidth = (outer - inner) / outer; } - _size.set(outer); - _width.set(discWidth); + _size = static_cast(outer); + _width = static_cast(discWidth); // Compute the coservative bounds normalized by the size of the disc, i.e. in [0, 1] _conservativeBounds = glm::vec2(innerConservative, outerConservative); _conservativeBounds /= _size; } -glm::vec4 RenderableHabitableZone::computeKopparapuZoneBoundaries(float teff, - float luminosity) +glm::dvec4 RenderableHabitableZone::computeKopparapuZoneBoundaries(float teff, + float luminosity) { // Kopparapu's formula only considers stars with teff in range [2600, 7200] K. // However, we want to use the formula for more stars, so add some flexibility to @@ -234,42 +234,44 @@ glm::vec4 RenderableHabitableZone::computeKopparapuZoneBoundaries(float teff, if (teff > 8000.f || teff < 2000.f) { // For the other stars, use a method by Tom E. Morris: // https://www.planetarybiology.com/calculating_habitable_zone.html - float inner = std::sqrt(luminosity / 1.1f); - float outer = std::sqrt(luminosity / 0.53f); - return glm::vec4(inner, inner, outer, outer); + const double L = static_cast(luminosity); + double inner = std::sqrt(L / 1.1); + double outer = std::sqrt(L / 0.53); + return glm::dvec4(inner, inner, outer, outer); } struct Coefficients { - float seffSun; - float a; - float b; - float c; - float d; + double seffSun; + double a; + double b; + double c; + double d; }; // Coefficients for planets of 1 Earth mass. Received from: // https://depts.washington.edu/naivpl/sites/default/files/HZ_coefficients.dat constexpr const Coefficients coefficients[] = { // Optimistic Inner boundary - Recent Venus - {1.77600E+00f, 2.13600E-04f, 2.53300E-08f, -1.33200E-11f, -3.09700E-15f}, + {1.77600E+00, 2.13600E-04, 2.53300E-08, -1.33200E-11, -3.09700E-15}, // Conservative Inner boundary - Runaway greenhouse - {1.10700E+00f, 1.33200E-04f, 1.58000E-08f, -8.30800E-12f, -1.93100E-15f}, + {1.10700E+00, 1.33200E-04, 1.58000E-08, -8.30800E-12, -1.93100E-15}, // Conservative Outer boundary - Maximum greenhouse - {3.56000E-01f, 6.17100E-05f, 1.69800E-09f, -3.19800E-12f, -5.57500E-16f}, + {3.56000E-01, 6.17100E-05, 1.69800E-09, -3.19800E-12, -5.57500E-16}, // Optimistic Outer boundary - Early Mars - {3.20000E-01f, 5.54700E-05f, 1.52600E-09f, -2.87400E-12f, -5.01100E-16f} + {3.20000E-01, 5.54700E-05, 1.52600E-09, -2.87400E-12, -5.01100E-16} }; - const float tstar = teff - 5780.f; - const float tstar2 = tstar * tstar; + const double tstar = static_cast(teff - 5780.f); + const double tstar2 = tstar * tstar; + const double L = static_cast(luminosity); - glm::vec4 distances; + glm::dvec4 distances; for (int i = 0; i < 4; ++i) { const Coefficients& coeffs = coefficients[i]; - float seff = coeffs.seffSun + (coeffs.a * tstar) + (coeffs.b * tstar2) + + double seff = coeffs.seffSun + (coeffs.a * tstar) + (coeffs.b * tstar2) + (coeffs.c * tstar * tstar2) + (coeffs.d * tstar2 * tstar2); - distances[i] = std::pow(luminosity / seff, 0.5f); + distances[i] = std::pow(L / seff, 0.5); } return distances; diff --git a/modules/space/rendering/renderablehabitablezone.h b/modules/space/rendering/renderablehabitablezone.h index 1503a57d21..bfed46bbae 100644 --- a/modules/space/rendering/renderablehabitablezone.h +++ b/modules/space/rendering/renderablehabitablezone.h @@ -54,7 +54,7 @@ private: * \return A vec4 with the boundaries in atronomical units, in the order: optimistic inner, conservative inner, conservative outer, optimistic outer */ - glm::vec4 computeKopparapuZoneBoundaries(float teff, float luminosity); + glm::dvec4 computeKopparapuZoneBoundaries(float teff, float luminosity); properties::FloatProperty _teff; properties::FloatProperty _luminosity; diff --git a/modules/space/shaders/habitablezone_fs.glsl b/modules/space/shaders/habitablezone_fs.glsl index d139dc0cfd..11bcca4f3b 100644 --- a/modules/space/shaders/habitablezone_fs.glsl +++ b/modules/space/shaders/habitablezone_fs.glsl @@ -43,7 +43,7 @@ float computeTextureCoord(float radius, float innerRadius, const float t1 = 1.0 / 3.0; const float t2 = 2.0 / 3.0; - if(radius < conservativeInner) { + if (radius < conservativeInner) { float t = (radius - innerRadius) / (conservativeInner - innerRadius); return mix(0.0, t1, t); } @@ -58,11 +58,8 @@ float computeTextureCoord(float radius, float innerRadius, } Fragment getFragment() { - // Moving the origin to the center - vec2 st = (vs_st - vec2(0.5)) * 2.0; - // The length of the texture coordinates vector is our distance from the center - float radius = length(st); + float radius = length(vs_st); float innerRadius = 1.0 - width; // We only want to consider ring-like objects so we need to discard everything else diff --git a/modules/space/shaders/habitablezone_vs.glsl b/modules/space/shaders/habitablezone_vs.glsl index 05ae85dfd4..d5796d62d9 100644 --- a/modules/space/shaders/habitablezone_vs.glsl +++ b/modules/space/shaders/habitablezone_vs.glsl @@ -38,7 +38,9 @@ void main() { vec4 position = vec4(in_position.xy, 0.0, 1.0); vec4 positionScreenSpace = z_normalization(modelViewProjectionTransform * position); - vs_st = in_st; + // Moving the origin to the center + vs_st = (in_st - vec2(0.5)) * 2.0; + vs_screenSpaceDepth = positionScreenSpace.w; gl_Position = positionScreenSpace; diff --git a/src/rendering/texturecomponent.cpp b/src/rendering/texturecomponent.cpp index 95785482a8..ce771887f8 100644 --- a/src/rendering/texturecomponent.cpp +++ b/src/rendering/texturecomponent.cpp @@ -30,12 +30,16 @@ #include namespace { - constexpr const char* _loggerCat = "TextureComponent"; + constexpr const char _loggerCat[] = "TextureComponent"; } // namespace namespace openspace { -ghoul::opengl::Texture* TextureComponent::texture() const { +const ghoul::opengl::Texture* TextureComponent::texture() const { + return _texture.get(); +} + +ghoul::opengl::Texture* TextureComponent::texture() { return _texture.get(); } diff --git a/src/util/planegeometry.cpp b/src/util/planegeometry.cpp index 9a166574d7..69a8c92317 100644 --- a/src/util/planegeometry.cpp +++ b/src/util/planegeometry.cpp @@ -35,17 +35,44 @@ namespace openspace { PlaneGeometry::PlaneGeometry(glm::vec2 size) : _size(std::move(size)) {} -PlaneGeometry::PlaneGeometry(float size) : _size(size, size) {} +PlaneGeometry::PlaneGeometry(float size) : PlaneGeometry(glm::vec2(size, size)) {} PlaneGeometry::~PlaneGeometry() { glDeleteBuffers(1, &_vBufferId); glDeleteVertexArrays(1, &_vaoId); } -bool PlaneGeometry::initialize() { - // Initialize and upload to GPU - const glm::vec2 size = _size; +void PlaneGeometry::initialize() { + glGenVertexArrays(1, &_vaoId); + glGenBuffers(1, &_vBufferId); + updateGeometry(); +} +void PlaneGeometry::deinitialize() { + glDeleteVertexArrays(1, &_vaoId); + _vaoId = 0; + + glDeleteBuffers(1, &_vBufferId); + _vBufferId = 0; +} + +void PlaneGeometry::render() { + glBindVertexArray(_vaoId); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArray(0); +} + +void PlaneGeometry::updateSize(const glm::vec2& size) { + _size = size; + updateGeometry(); +} + +void PlaneGeometry::updateSize(const float size) { + updateSize(glm::vec2(size)); +} + +void PlaneGeometry::updateGeometry() { + const glm::vec2 size = _size; struct VertexData { GLfloat x; GLfloat y; @@ -59,25 +86,10 @@ bool PlaneGeometry::initialize() { { -size.x, size.y, 0.f, 1.f }, { -size.x, -size.y, 0.f, 0.f }, { size.x, -size.y, 1.f, 0.f }, - { size.x, size.y, 1.f, 1.f }, + { size.x, size.y, 1.f, 1.f } }; - if (_vaoId == 0) { - glGenVertexArrays(1, &_vaoId); - } - - if (_vBufferId == 0) { - glGenBuffers(1, &_vBufferId); - - if (_vBufferId == 0) { - LERROR("Could not create vertex buffer"); - return false; - } - } - - // First VAO setup glBindVertexArray(_vaoId); - glBindBuffer(GL_ARRAY_BUFFER, _vBufferId); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); @@ -91,33 +103,6 @@ bool PlaneGeometry::initialize() { sizeof(VertexData), reinterpret_cast(offsetof(VertexData, s)) // NOLINT ); - - glBindVertexArray(0); - return true; -} - -void PlaneGeometry::deinitialize() { - glDeleteVertexArrays(1, &_vaoId); - _vaoId = 0; - - glDeleteBuffers(1, &_vBufferId); - _vBufferId = 0; -} - -void PlaneGeometry::render() { - glBindVertexArray(_vaoId); // select first VAO - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); -} - -void PlaneGeometry::updateSize(const glm::vec2 size) { - _size = size; - initialize(); -} - -void PlaneGeometry::updateSize(const float size) { - _size = glm::vec2(size, size); - initialize(); } } // namespace openspace From 85d63967c298a570210cf4378329f149f2dc6fae Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 1 Feb 2021 11:00:43 +0100 Subject: [PATCH 21/41] Show habitable zone teff interval in UI --- .../rendering/renderablehabitablezone.cpp | 28 +++++++++++++++++-- .../space/rendering/renderablehabitablezone.h | 6 +++- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/modules/space/rendering/renderablehabitablezone.cpp b/modules/space/rendering/renderablehabitablezone.cpp index 09d5cfc7f7..f2888a28c0 100644 --- a/modules/space/rendering/renderablehabitablezone.cpp +++ b/modules/space/rendering/renderablehabitablezone.cpp @@ -66,6 +66,15 @@ namespace { "If true, the habitable zone disc is rendered with the optimistic boundaries " "rather than the conservative ones." }; + + constexpr openspace::properties::Property::PropertyInfo KopparapuTeffIntervalInfo = { + "KopparapuTeffInterval", + "Effective Temperature Interval (Kopparapu's formula)" , + "The range for which Kopparapu's formula is used for the habitable zone " + "computation. For stars with effective temperatures outside the range, a " + "simpler method by Tom E. Harris is used. This method only uses the star " + "luminosity and does not include computation of the optimistic boundaries." + }; } // namespace namespace openspace { @@ -93,6 +102,12 @@ documentation::Documentation RenderableHabitableZone::Documentation() { new BoolVerifier, Optional::Yes, OptimisticInfo.description + }, + { + KopparapuTeffIntervalInfo.identifier, + new DoubleVector2Verifier, + Optional::Yes, + KopparapuTeffIntervalInfo.description } } }; @@ -115,6 +130,7 @@ RenderableHabitableZone::RenderableHabitableZone(const ghoul::Dictionary& dictio , _teff(EffectiveTemperatureInfo, 5780.f, 0.f, 7.5e4f) , _luminosity(LuminosityInfo, 1.f, 0.f, 1e8f) , _showOptimistic(OptimisticInfo, false) + , _kopparapuTeffInterval(KopparapuTeffIntervalInfo, glm::vec2(2000.f, 8000.f)) { documentation::testSpecificationAndThrow( Documentation(), @@ -143,6 +159,11 @@ RenderableHabitableZone::RenderableHabitableZone(const ghoul::Dictionary& dictio } addProperty(_showOptimistic); + // The user should not be able to change this property. It's just used to communicate + // the different rendering that happens outside of this interval + addProperty(_kopparapuTeffInterval); + _kopparapuTeffInterval.setReadOnly(true); + // Make parent's size related properties read only. We want to set them based on the // given temperature and luminosity _size.setReadOnly(true); @@ -229,9 +250,10 @@ glm::dvec4 RenderableHabitableZone::computeKopparapuZoneBoundaries(float teff, { // Kopparapu's formula only considers stars with teff in range [2600, 7200] K. // However, we want to use the formula for more stars, so add some flexibility to - // the teff boundaries. - // OBS! This also prevents problems with too large values in the distance computation - if (teff > 8000.f || teff < 2000.f) { + // the teff boundaries (see constructor). + // OBS! This also prevents problems with too large teff values in the computation + const glm::vec2 teffBounds = _kopparapuTeffInterval; + if (teff > teffBounds.y || teff < teffBounds.x) { // For the other stars, use a method by Tom E. Morris: // https://www.planetarybiology.com/calculating_habitable_zone.html const double L = static_cast(luminosity); diff --git a/modules/space/rendering/renderablehabitablezone.h b/modules/space/rendering/renderablehabitablezone.h index bfed46bbae..6aa5d7f31b 100644 --- a/modules/space/rendering/renderablehabitablezone.h +++ b/modules/space/rendering/renderablehabitablezone.h @@ -26,7 +26,9 @@ #define __OPENSPACE_MODULE_EXOPLANETS___RENDERABLEHABITABLEZONE___H__ #include +#include #include +#include namespace openspace { @@ -46,7 +48,7 @@ private: void computeZone(); /** - * Compute the inner and outer boundary of the habitable zone of a star, accordring to + * Compute the inner and outer boundary of the habitable zone of a star, according to * formula and coefficients by Kopparapu et al. (2015) https://arxiv.org/abs/1404.5292 * * \param teff The effective temperature of the star, in Kelvin @@ -60,6 +62,8 @@ private: properties::FloatProperty _luminosity; properties::BoolProperty _showOptimistic; + properties::Vec2Property _kopparapuTeffInterval; + glm::vec2 _conservativeBounds; UniformCache(modelViewProjection, opacity, width, texture, From 0663d10c7837c9389acc6acb30d4ecb1f6166b48 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 1 Feb 2021 11:12:06 +0100 Subject: [PATCH 22/41] Update asset descriptions --- data/assets/scene/milkyway/exoplanets/exoplanets_data.asset | 6 ++++-- data/assets/scene/solarsystem/sun/habitablezone.asset | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset b/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset index 518f093344..0d2ab171e8 100644 --- a/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset +++ b/data/assets/scene/milkyway/exoplanets/exoplanets_data.asset @@ -9,8 +9,10 @@ asset.export("DataPath", DataPath) asset.meta = { Name = "Exoplanet Data", Version = "2.0", - Description = [[ The data that is used for the exoplanet systems.]], + Description = [[ The data that is used for the exoplanet systems. The data has been + derived from the 'Planetary Systems Composite Data' dataset from the NASA Exoplanet + Archive]], Author = "OpenSpace Team", - URL = "http://openspaceproject.com", + URL = "https://exoplanetarchive.ipac.caltech.edu/docs/data.html", License = "MIT license", } diff --git a/data/assets/scene/solarsystem/sun/habitablezone.asset b/data/assets/scene/solarsystem/sun/habitablezone.asset index 15c65237d0..9727e641fa 100644 --- a/data/assets/scene/solarsystem/sun/habitablezone.asset +++ b/data/assets/scene/solarsystem/sun/habitablezone.asset @@ -25,7 +25,8 @@ assetHelper.registerSceneGraphNodesAndExport(asset, { HabitableZone }) asset.meta = { Name = "Sun Habitable Zone", Version = "1.0", - Description = [[ The habitable zone around our sun]], + Description = [[ The habitable zone around our sun, computed using formula and + coefficients by Kopparapu et al. (2015) https://arxiv.org/abs/1404.5292]], Author = "OpenSpace Team", URL = "http://openspaceproject.com", License = "MIT license", From c323a05021a20afcef7bdd75c729406a4c6525cd Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 1 Feb 2021 13:09:17 +0100 Subject: [PATCH 23/41] Fix a crash when reloading a browser instance twice in quick succession --- modules/server/include/topics/topic.h | 2 +- modules/server/src/topics/luascripttopic.cpp | 8 +++++--- modules/server/src/topics/topic.cpp | 4 ++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/server/include/topics/topic.h b/modules/server/include/topics/topic.h index de00c28452..f982514c43 100644 --- a/modules/server/include/topics/topic.h +++ b/modules/server/include/topics/topic.h @@ -34,7 +34,7 @@ class Connection; class Topic { public: Topic() {}; - virtual ~Topic() = default; + virtual ~Topic(); void initialize(Connection* connection, size_t topicId); nlohmann::json wrappedPayload(const nlohmann::json& payload) const; diff --git a/modules/server/src/topics/luascripttopic.cpp b/modules/server/src/topics/luascripttopic.cpp index b85b2d6f67..b36289d3de 100644 --- a/modules/server/src/topics/luascripttopic.cpp +++ b/modules/server/src/topics/luascripttopic.cpp @@ -180,9 +180,11 @@ void LuaScriptTopic::runScript(const std::string& script, bool shouldReturn) { scripting::ScriptEngine::ScriptCallback callback; if (shouldReturn) { callback = [this](ghoul::Dictionary data) { - nlohmann::json j = data; - _connection->sendJson(wrappedPayload(j)); - _waitingForReturnValue = false; + if (_connection) { + nlohmann::json j = data; + _connection->sendJson(wrappedPayload(j)); + _waitingForReturnValue = false; + } }; _waitingForReturnValue = true; } diff --git a/modules/server/src/topics/topic.cpp b/modules/server/src/topics/topic.cpp index 0415ad1d63..b69ee91939 100644 --- a/modules/server/src/topics/topic.cpp +++ b/modules/server/src/topics/topic.cpp @@ -30,6 +30,10 @@ namespace openspace { +Topic::~Topic() { + _connection = nullptr; +} + void Topic::initialize(Connection* connection, size_t topicId) { _connection = connection; _topicId = topicId; From e50ca7adedaa059fb0bd4c5b0d9281db2cfd91be Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 1 Feb 2021 13:31:28 +0100 Subject: [PATCH 24/41] Try a fix against random crashes at startup when loading configuration --- ext/ghoul | 2 +- src/engine/configuration.cpp | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ext/ghoul b/ext/ghoul index e42b3f58c4..1750e592bb 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit e42b3f58c493d57afde415cf5be8af88585c320b +Subproject commit 1750e592bb64e2fe759b75e447a9a6aae2d7c3c7 diff --git a/src/engine/configuration.cpp b/src/engine/configuration.cpp index 9b948e911c..35727a3790 100644 --- a/src/engine/configuration.cpp +++ b/src/engine/configuration.cpp @@ -147,7 +147,7 @@ namespace { for (size_t i = 1; i <= d.size(); ++i) { res.push_back(d.value(std::to_string(i))); } - value = res; + value = std::move(res); } // NOLINTNEXTLINE else if constexpr (std::is_same_v>) { @@ -160,7 +160,7 @@ namespace { std::string v = d.value(key); res[std::string(key)] = std::move(v); } - value = res; + value = std::move(res); } // NOLINTNEXTLINE else if constexpr (std::is_same_v>) { @@ -173,7 +173,7 @@ namespace { ghoul::Dictionary v = d.value(key); res[std::string(key)] = std::move(v); } - value = res; + value = std::move(res); } // NOLINTNEXTLINE else if constexpr (std::is_same_v) { @@ -256,7 +256,10 @@ namespace { filter.type = fi.value(KeyType); } - res.push_back(filter); + auto fff = filter; + const auto ffg = filter; + + res.push_back(std::move(filter)); } v.identifierFilters = res; From c8fc369fb1fad40bebfffe818c42ca0abd8038ea Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 1 Feb 2021 13:55:53 +0100 Subject: [PATCH 25/41] Fixed issue preventing the rendering of color properties --- src/properties/property.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/properties/property.cpp b/src/properties/property.cpp index 5e4189811d..157aa6d261 100644 --- a/src/properties/property.cpp +++ b/src/properties/property.cpp @@ -217,6 +217,9 @@ void Property::setViewOption(std::string option, bool value) { } bool Property::viewOption(const std::string& option, bool defaultValue) const { + if (!_metaData.hasValue(_metaDataKeyViewPrefix)) { + return defaultValue; + } ghoul::Dictionary d = _metaData.value(_metaDataKeyViewPrefix); if (d.hasKey(option)) { return d.value(option); From ff39e2630e355c11a595292b1452fb0a78b410b3 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 1 Feb 2021 14:20:55 +0100 Subject: [PATCH 26/41] Update Ghoul repository (closes #1471) --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 1750e592bb..9223fb1c6b 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 1750e592bb64e2fe759b75e447a9a6aae2d7c3c7 +Subproject commit 9223fb1c6bdc7e4edab5afa36e1d1231ab214a18 From c17e43ec111ab7544a9e71dfe031236a614e6f43 Mon Sep 17 00:00:00 2001 From: Micah Date: Mon, 1 Feb 2021 17:01:03 -0500 Subject: [PATCH 27/41] fix for HiRISE Local Set DEM from esri --- .../mars/layers/heightlayers/hirisels.asset | 2 +- .../ESRI/HiRISE/HiRISE_DEM.tif | 17 ----------------- .../ESRI/HiRISE/HiRISE_DEM.wms | 17 ----------------- 3 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.tif delete mode 100644 data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.wms diff --git a/data/assets/scene/solarsystem/planets/mars/layers/heightlayers/hirisels.asset b/data/assets/scene/solarsystem/planets/mars/layers/heightlayers/hirisels.asset index 0fa9c56943..01adfc48b6 100644 --- a/data/assets/scene/solarsystem/planets/mars/layers/heightlayers/hirisels.asset +++ b/data/assets/scene/solarsystem/planets/mars/layers/heightlayers/hirisels.asset @@ -4,7 +4,7 @@ local globeIdentifier = asset.require("./../../mars").Mars.Identifier local layer = { Identifier = "HiRISE-LS-DEM", Name = "HiRISE Local Set DEM", - FilePath = mapServiceConfigs .. "/ESRI/HiRISE/HiRISE_DEM.wms", + FilePath = mapServiceConfigs .. "/ESRI/HiRISE/HiRISE_DEM.dem", Description = [[ HiRISE (High Resolution Imaging Science Experiment) is the most powerful camera ever sent to another planet, one of six instruments onboard the Mars Reconnaissance Orbiter. We launched in 2005, arrived at Mars in 2006 and have diff --git a/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.tif b/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.tif deleted file mode 100644 index f557be2ac1..0000000000 --- a/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.tif +++ /dev/null @@ -1,17 +0,0 @@ - - - http://astro.arcgis.com/arcgis/rest/services/OnMars/HiRISE_DEM/ImageServer/tile/${z}/${y}/${x} - - - -180 90 - 180 -90 - 20971520 10485760 - 15 top - - GEOGCS["GCS_Mars_2000_Sphere",DATUM["D_Mars_2000_Sphere",SPHEROID["Mars_2000_Sphere_IAU_IAG",3396190,0]],PRIMEM["Reference_Meridian",0],UNIT["Degree",0.0174532925199433]] - 512 512 - 1 Int16 - - 5 - 404,400 - diff --git a/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.wms b/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.wms deleted file mode 100644 index bedcb068e0..0000000000 --- a/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.wms +++ /dev/null @@ -1,17 +0,0 @@ - - - http://astro.arcgis.com/arcgis/rest/services/OnMars/HiRISE_DEM/ImageServer/tile/${z}/${y}/${x} - - - -180 90 - 180 -90 - 20971520 10485760 - 15 top - - GEOGCS["GCS_Mars_2000_Sphere",DATUM["D_Mars_2000_Sphere",SPHEROID["Mars_2000_Sphere_IAU_IAG",3396190,0]],PRIMEM["Reference_Meridian",0],UNIT["Degree",0.0174532925199433]] - 512 512 - 1 Int16 - - 5 - 404,400 - From e53baeece406c8d6af65bbd5244398c9ab7afc2c Mon Sep 17 00:00:00 2001 From: Micah Date: Mon, 1 Feb 2021 17:02:28 -0500 Subject: [PATCH 28/41] adding new dem config file; whoops --- .../ESRI/HiRISE/HiRISE_DEM.dem | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.dem diff --git a/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.dem b/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.dem new file mode 100644 index 0000000000..8446fe69d3 --- /dev/null +++ b/data/assets/scene/solarsystem/planets/mars/map_service_configs/ESRI/HiRISE/HiRISE_DEM.dem @@ -0,0 +1,17 @@ + + + http://astro.arcgis.com/arcgis/rest/services/OnMars/HiRISE_DEM/raw/tile/${z}/${y}/${x} + + + -180 90 + 180 -90 + 20971520 10485760 + 15 top + + GEOGCS["GCS_Mars_2000_Sphere",DATUM["D_Mars_2000_Sphere",SPHEROID["Mars_2000_Sphere_IAU_IAG",3396190,0]],PRIMEM["Reference_Meridian",0],UNIT["Degree",0.0174532925199433]] + 512 512 + 1 Int16 + + 5 + 404,400 + From 2072edd2826d00a681f5ccdf5645019002bf1abb Mon Sep 17 00:00:00 2001 From: Micah Date: Mon, 1 Feb 2021 17:51:53 -0500 Subject: [PATCH 29/41] update mars profile to fix keybindings --- data/profiles/mars.profile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/profiles/mars.profile b/data/profiles/mars.profile index 56d2dd82a6..87493a7562 100644 --- a/data/profiles/mars.profile +++ b/data/profiles/mars.profile @@ -39,7 +39,7 @@ "is_local": false, "key": "I", "name": "Setup scene for insight EDL", - "script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', -469.300000);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.OnMarsHiRISE-LS-DEM.Settings.Offset', -470.800006);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.OnMarsHiRISE-LS-DEM.Enabled', true);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.OnMarsHiRISE-LS.Enabled', true);openspace.time.setPause(true);openspace.time.setTime('2018 NOV 26 19:39:03.68');openspace.navigation.setNavigationState({Anchor = 'Insight',Pitch = 0.567457E-4,Position = { 1.240506E1,-1.369270E1,-2.423553E0 },ReferenceFrame = 'Root',Up = { 0.441211E0,0.247019E0,0.862737E0 },Yaw = -0.446853E-4});" + "script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', -469.300000);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', -470.800006);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', true);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', true);openspace.time.setPause(true);openspace.time.setTime('2018 NOV 26 19:39:03.68');openspace.navigation.setNavigationState({Anchor = 'Insight',Pitch = 0.567457E-4,Position = { 1.240506E1,-1.369270E1,-2.423553E0 },ReferenceFrame = 'Root',Up = { 0.441211E0,0.247019E0,0.862737E0 },Yaw = -0.446853E-4});" }, { "documentation": "Disable Mars layer settings used for insight EDL", @@ -47,7 +47,7 @@ "is_local": false, "key": "SHIFT+I", "name": "Unset Insight Landing", - "script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', 0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.OnMarsHiRISE-LS-DEM.Settings.Offset', 0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.OnMarsHiRISE-LS-DEM.Enabled', false);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.OnMarsHiRISE-LS.Enabled', false);" + "script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', 0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', 0);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', false);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', false);" }, { "documentation": "Sets time and layers for Perseverance landing", @@ -55,7 +55,7 @@ "is_local": false, "key": "P", "name": "Setup and Goto Perseverance", - "script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', -1677.088867);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.OnMarsHiRISE-LS-DEM.Settings.Offset', -1677.088867);openspace.time.setPause(true);openspace.time.setTime('2021 FEB 18 20:32:16');openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.OnMarsHiRISE-LS-DEM.Enabled', true);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.OnMarsHiRISE-LS.Enabled', true);openspace.navigation.setNavigationState({Anchor = 'Perseverance',Pitch = 0.567457E-4,Position = { 1.240506E1,-1.369270E1,-2.423553E0 },ReferenceFrame = 'Root',Up = { 0.441211E0,0.247019E0,0.862737E0 },Yaw = -0.446853E-4});" + "script": "openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.Mola_Utah.Settings.Offset', -1677.088867);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Settings.Offset', -1677.088867);openspace.time.setPause(true);openspace.time.setTime('2021 FEB 18 20:32:16');openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled', true);openspace.setPropertyValueSingle('Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled', true);openspace.navigation.setNavigationState({Anchor = 'Perseverance',Pitch = 0.567457E-4,Position = { 1.240506E1,-1.369270E1,-2.423553E0 },ReferenceFrame = 'Root',Up = { 0.441211E0,0.247019E0,0.862737E0 },Yaw = -0.446853E-4});" } ], "mark_nodes": [ @@ -77,6 +77,6 @@ }, "version": { "major": 1, - "minor": 0 + "minor": 1 } } \ No newline at end of file From 3a6aa7ce435277721eda31f0885ffc1d9ca30279 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 2 Feb 2021 22:25:36 -0500 Subject: [PATCH 30/41] added USGS wms layers for Phobos and Deimos; moved them to planets.asset to be consistant with other solarsystem moons --- data/assets/base.asset | 2 -- .../solarsystem/planets/default_layers.asset | 2 ++ .../layers/colorlayers/deimos_viking.asset | 29 +++++++++++++++++++ .../layers/colorlayers/phobos_viking.asset | 26 +++++++++++++++++ .../scene/solarsystem/planets/planets.asset | 2 ++ 5 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 data/assets/scene/solarsystem/planets/mars/moons/layers/colorlayers/deimos_viking.asset create mode 100644 data/assets/scene/solarsystem/planets/mars/moons/layers/colorlayers/phobos_viking.asset diff --git a/data/assets/base.asset b/data/assets/base.asset index 989f888df3..60d4e207e7 100644 --- a/data/assets/base.asset +++ b/data/assets/base.asset @@ -10,8 +10,6 @@ asset.require('scene/solarsystem/sun/glare') asset.require('scene/solarsystem/sun/default_layers') asset.require('scene/solarsystem/planets/planets') asset.require('scene/solarsystem/planets/default_layers') -asset.require('scene/solarsystem/planets/mars/moons/phobos') -asset.require('scene/solarsystem/planets/mars/moons/deimos') asset.require('scene/solarsystem/dwarf_planets/pluto/system') asset.require('scene/solarsystem/dwarf_planets/pluto/default_layers') asset.require('scene/solarsystem/dwarf_planets/pluto/charon/default_layers') diff --git a/data/assets/scene/solarsystem/planets/default_layers.asset b/data/assets/scene/solarsystem/planets/default_layers.asset index 4fc2b0ada0..37649a9ed0 100644 --- a/data/assets/scene/solarsystem/planets/default_layers.asset +++ b/data/assets/scene/solarsystem/planets/default_layers.asset @@ -8,6 +8,8 @@ asset.require('./jupiter/ganymede/default_layers') asset.require('./jupiter/io/default_layers') asset.require('./mars/default_layers') +asset.require('./mars/moons/layers/colorlayers/deimos_viking') +asset.require('./mars/moons/layers/colorlayers/phobos_viking') asset.require('./mercury/default_layers') diff --git a/data/assets/scene/solarsystem/planets/mars/moons/layers/colorlayers/deimos_viking.asset b/data/assets/scene/solarsystem/planets/mars/moons/layers/colorlayers/deimos_viking.asset new file mode 100644 index 0000000000..a339e5b425 --- /dev/null +++ b/data/assets/scene/solarsystem/planets/mars/moons/layers/colorlayers/deimos_viking.asset @@ -0,0 +1,29 @@ +local globeIdentifier = asset.require("./../../deimos").Deimos.Identifier + +local layer = { + Identifier = "Deimos_Global_Mosaic_USGS", + Name = "Deimos Global Mosaic [USGS]", + Enabled = true, + FilePath = "WMS:https://wms.wr.usgs.gov/cgi-bin/mapserv?map=/maps/mars/deimos_simp_cyl.map&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=Deimos_Simple_Cylindrical_Rasters&SRS=EPSG:4326&BBOX=-180,-90,360,90", + Description = [[ This Viking-based cylindrical map of Deimos was created by Philip + Stooke with the assistance of Chris Jongkind and Megan Arntz. Control is based on a + shape model and mosaic by Peter Thomas and colleagues at Cornell University. Date + released 26 October 2001. (Description from URL)]] +} + +asset.onInitialize(function () + openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer) +end) + +asset.export("layer", layer) + + +asset.meta = { + Name = "Deimos Global Mosaic [USGS]", + Version = "1.0", + Author = "Philip Stooke/NASA", + URL = "https://astrowebmaps.wr.usgs.gov/webmapatlas/Layers/maps.html", + License = "NASA/PDS", + Identifiers = {'Deimos_Global_Mosaic_USGS'} + +} diff --git a/data/assets/scene/solarsystem/planets/mars/moons/layers/colorlayers/phobos_viking.asset b/data/assets/scene/solarsystem/planets/mars/moons/layers/colorlayers/phobos_viking.asset new file mode 100644 index 0000000000..6a0c5b8d9a --- /dev/null +++ b/data/assets/scene/solarsystem/planets/mars/moons/layers/colorlayers/phobos_viking.asset @@ -0,0 +1,26 @@ +local globeIdentifier = asset.require("./../../phobos").Phobos.Identifier + +local layer = { + Identifier = "Phobos_Global_Shaded_Relief_USGS", + Name = "Phobos Global Shaded Relief [USGS]", + Enabled = true, + FilePath = "WMS:https://wms.wr.usgs.gov/cgi-bin/mapserv?map=/maps/mars/phobos_simp_cyl.map&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=Phobos_Simple_Cylindrical_Rasters&SRS=EPSG:4326&BBOX=-180,-90,360,90", + Description = [[ Viking-base Phobos shaded relief created by USGS.]] +} + +asset.onInitialize(function () + openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer) +end) + +asset.export("layer", layer) + + +asset.meta = { + Name = "Phobos Global Shaded Relief [USGS]", + Version = "1.0", + Author = "USGS/NASA", + URL = "https://astrowebmaps.wr.usgs.gov/webmapatlas/Layers/maps.html", + License = "NASA/PDS", + Identifiers = {'Phobos_Global_Shaded_Relief_USGS'} + +} diff --git a/data/assets/scene/solarsystem/planets/planets.asset b/data/assets/scene/solarsystem/planets/planets.asset index d7ea310c0b..2c80f258c5 100644 --- a/data/assets/scene/solarsystem/planets/planets.asset +++ b/data/assets/scene/solarsystem/planets/planets.asset @@ -14,6 +14,8 @@ asset.require('./earth/moon/trail') asset.require('./mars/mars') asset.require('./mars/atmosphere') +asset.require('./mars/moons/phobos') +asset.require('./mars/moons/deimos') asset.require('./jupiter/jupiter') asset.require('./jupiter/major_moons') From 0b9b42e0bf6a6a1669a23551265f51c0cd8547a5 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Wed, 3 Feb 2021 08:33:55 +0100 Subject: [PATCH 31/41] Rename single color image function --- data/assets/examples/discs.asset | 7 +++++-- src/engine/openspaceengine.cpp | 4 ++-- src/engine/openspaceengine_lua.inl | 8 ++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/data/assets/examples/discs.asset b/data/assets/examples/discs.asset index 2d103f7b80..0b15b2115b 100644 --- a/data/assets/examples/discs.asset +++ b/data/assets/examples/discs.asset @@ -1,6 +1,9 @@ local assetHelper = asset.require('util/asset_helper') -local singeColorTexturePath = openspace.createPixelImage("example_ring_color", {0.0, 1.0, 1.0}) +local color = {0.0, 1.0, 1.0} + +-- @TODO (emmbr 2020-02-03) Potential threading issue later on? This will run on the main thread +local singeColorTexturePath = openspace.createSingeColorImage("example_ring_color", color) local BasicDisc = { Identifier = "BasicDisc", @@ -17,6 +20,6 @@ local BasicDisc = { } } -assetHelper.registerSceneGraphNodesAndExport(asset, { +assetHelper.registerSceneGraphNodesAndExport(asset, { BasicDisc }) diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index b9512adff6..00c135152d 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -1540,8 +1540,8 @@ scripting::LuaLibrary OpenSpaceEngine::luaLibrary() { "Removes a tag (second argument) from a scene graph node (first argument)" }, { - "createPixelImage", - &luascriptfunctions::createPixelImage, + "createSingeColorImage", + &luascriptfunctions::createSingeColorImage, {}, "string, vec3", "Creates a 1 pixel image with a certain color in the cache folder and " diff --git a/src/engine/openspaceengine_lua.inl b/src/engine/openspaceengine_lua.inl index d19a6aab6c..96cb96f3c2 100644 --- a/src/engine/openspaceengine_lua.inl +++ b/src/engine/openspaceengine_lua.inl @@ -294,11 +294,11 @@ int downloadFile(lua_State* L) { /** * \ingroup LuaScripts -* createPixelImage(): -* Creates a one pixel image with a given color and returns the p +* createSingeColorImage(): +* Creates a one pixel image with a given color and returns the path to the cached file */ -int createPixelImage(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::createPixelImage"); +int createSingeColorImage(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::createSingeColorImage"); const std::string& name = ghoul::lua::value(L, 1); const ghoul::Dictionary& d = ghoul::lua::value(L, 2); From 3f63f92128f8041c9aab6d51ca73606e765daa95 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Wed, 3 Feb 2021 16:52:20 +0100 Subject: [PATCH 32/41] Add test cases for the create single color image lua function --- include/openspace/engine/openspaceengine.h | 7 + src/engine/openspaceengine_lua.inl | 4 + tests/CMakeLists.txt | 1 + tests/test_lua_createsinglecolorimage.cpp | 156 +++++++++++++++++++++ 4 files changed, 168 insertions(+) create mode 100644 tests/test_lua_createsinglecolorimage.cpp diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index a2204ace37..53e9b1d481 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -139,4 +139,11 @@ private: } // namespace openspace +// Lua functions - exposed for testing +namespace openspace::luascriptfunctions { + +int createSingeColorImage(lua_State* L); + +} + #endif // __OPENSPACE_CORE___OPENSPACEENGINE___H__ diff --git a/src/engine/openspaceengine_lua.inl b/src/engine/openspaceengine_lua.inl index 96cb96f3c2..2b4636a66f 100644 --- a/src/engine/openspaceengine_lua.inl +++ b/src/engine/openspaceengine_lua.inl @@ -302,6 +302,7 @@ int createSingeColorImage(lua_State* L) { const std::string& name = ghoul::lua::value(L, 1); const ghoul::Dictionary& d = ghoul::lua::value(L, 2); + lua_settop(L, 0); // @TODO (emmbr 2020-12-18) Verify that the input dictionary is a vec3 // Would like to clean this up with a more direct use of the Verifier in the future @@ -311,6 +312,9 @@ int createSingeColorImage(lua_State* L) { colorDict.setValue(key, d); TestResult res = DoubleVector3Verifier()(colorDict, key); + // @TODO (emmbr 2020-02-04) A 'ColorVerifier' would be really useful here, to easily + // check that we have a vector with values in [0, 1] + if (!res.success) { return ghoul::lua::luaError( L, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f68b8d0b3b..522b4509c8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,6 +33,7 @@ add_executable( test_latlonpatch.cpp test_lrucache.cpp test_luaconversions.cpp + test_lua_createsinglecolorimage.cpp test_optionproperty.cpp test_profile.cpp test_rawvolumeio.cpp diff --git a/tests/test_lua_createsinglecolorimage.cpp b/tests/test_lua_createsinglecolorimage.cpp new file mode 100644 index 0000000000..33bc010d05 --- /dev/null +++ b/tests/test_lua_createsinglecolorimage.cpp @@ -0,0 +1,156 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2021 * + * * + * 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 "catch2/catch.hpp" + +#include +#include +#include +#include +#include +#include + +TEST_CASE("CreateSingleColorImage: Create image and check return value", + "[createsinglecolorimage]") +{ + ghoul::lua::LuaState L; + ghoul::lua::push(L, "colorFile"); + ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0 })); + + int res = openspace::luascriptfunctions::createSingeColorImage(L); + + // One return value + CHECK(res == 1); + CHECK(lua_gettop(L) == 1); +} + +TEST_CASE("CreateSingleColorImage: Faulty 1st input type", "[createsinglecolorimage]") { + ghoul::lua::LuaState L; + ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0 })); + ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0 })); + + CHECK_THROWS_WITH( + openspace::luascriptfunctions::createSingeColorImage(L), + Catch::Matchers::Contains("parameter 1 was not the expected type") + ); +} + +TEST_CASE("CreateSingleColorImage: Faulty 2nd input type", "[createsinglecolorimage]") { + ghoul::lua::LuaState L; + ghoul::lua::push(L, "notCreatedColorFile"); + ghoul::lua::push(L, "not a vector"); + + CHECK_THROWS_WITH( + openspace::luascriptfunctions::createSingeColorImage(L), + Catch::Matchers::Contains("parameter 2 was not the expected type") + ); +} + +TEST_CASE("CreateSingleColorImage: Invalid number of inputs", "[createsinglecolorimage]") +{ + ghoul::lua::LuaState L; + ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0 })); + + CHECK_THROWS_WITH( + openspace::luascriptfunctions::createSingeColorImage(L), + Catch::Matchers::Contains("Expected 2 arguments, got 1") + ); +} + +TEST_CASE("CreateSingleColorImage: Faulty color value (vec4)", + "[createsinglecolorimage]") +{ + ghoul::lua::LuaState L; + ghoul::lua::push(L, "notCreatedColorFile"); + ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0, 0.0 })); + + CHECK_THROWS_WITH( + openspace::luascriptfunctions::createSingeColorImage(L), + Catch::Matchers::Contains( + "Invalid color. Expected three double values {r, g, b} in range 0 to 1" + ) + ); +} + +TEST_CASE("CreateSingleColorImage: Faulty color value (invalid values)", + "[createsinglecolorimage]") +{ + ghoul::lua::LuaState L; + ghoul::lua::push(L, "notCreatedColorFile"); + ghoul::lua::push(L, std::vector({ 255.0, 0.0, 0.0 })); + + // @TODO (emmbr 2020-02-04) This test case should be here, but as of now this case is + // not handled. Finish it up when we have a better way of verifying that a dictionary + // is a color + + //CHECK_THROWS_WITH( + // openspace::luascriptfunctions::createSingeColorImage(L), + // Catch::Matchers::Contains( + // "Invalid color. Expected three double values {r, g, b} in range 0 to 1" + // ) + //); +} + +TEST_CASE("CreateSingleColorImage: Check if file was created", + "[createsinglecolorimage]") +{ + ghoul::lua::LuaState L; + ghoul::lua::push(L, "colorFile2"); + ghoul::lua::push(L, std::vector({ 0.0, 1.0, 0.0 })); + + int res = openspace::luascriptfunctions::createSingeColorImage(L); + + CHECK(res == 1); + std::string path = ghoul::lua::value(L, 1); + CHECK(FileSys.fileExists(path)); +} + +TEST_CASE("CreateSingleColorImage: Load created image", "[createsinglecolorimage]") { + ghoul::lua::LuaState L; + const glm::dvec3 color = { 1.0, 0.0, 0.0 }; + ghoul::lua::push(L, "colorFile"); + ghoul::lua::push(L, std::vector({ color.x, color.y, color.z })); + + // Loads the same file that was created in a previous test case + int res = openspace::luascriptfunctions::createSingeColorImage(L); + CHECK(res == 1); + CHECK(lua_gettop(L) == 1); + + std::string path = ghoul::lua::value(L, 1); + + // Read the PPM file and check the image dimensions + // (maybe too hard coded, but cannot load a texture here...) + std::ifstream ppmFile(path, std::ifstream::binary); + REQUIRE(ppmFile.is_open()); + + std::string version; + unsigned int width; + unsigned int height; + + ppmFile >> version >> width >> height; + + REQUIRE(width == 1); + REQUIRE(height == 1); +} + From 57bc3f22227e72e87f70a61fdc5fb9935a92392d Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Wed, 3 Feb 2021 16:52:30 +0100 Subject: [PATCH 33/41] Update ghoul repository --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 9223fb1c6b..bd1ab84178 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 9223fb1c6bdc7e4edab5afa36e1d1231ab214a18 +Subproject commit bd1ab841785274173e4245c0bd32c80c828e018f From b10e598cd3489e026251b09b2fb6a8ae4586bafb Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Thu, 4 Feb 2021 13:09:56 +0100 Subject: [PATCH 34/41] Cleanup and improve test --- include/openspace/engine/openspaceengine.h | 2 +- tests/test_lua_createsinglecolorimage.cpp | 24 ++++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 53e9b1d481..42612a9368 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -144,6 +144,6 @@ namespace openspace::luascriptfunctions { int createSingeColorImage(lua_State* L); -} +} // openspace::luascriptfunctions #endif // __OPENSPACE_CORE___OPENSPACEENGINE___H__ diff --git a/tests/test_lua_createsinglecolorimage.cpp b/tests/test_lua_createsinglecolorimage.cpp index 33bc010d05..e2311a5cf9 100644 --- a/tests/test_lua_createsinglecolorimage.cpp +++ b/tests/test_lua_createsinglecolorimage.cpp @@ -36,19 +36,26 @@ TEST_CASE("CreateSingleColorImage: Create image and check return value", { ghoul::lua::LuaState L; ghoul::lua::push(L, "colorFile"); - ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0 })); + ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 }); int res = openspace::luascriptfunctions::createSingeColorImage(L); // One return value CHECK(res == 1); CHECK(lua_gettop(L) == 1); + CHECK(lua_isstring(L, 1)); + + std::string path = ghoul::lua::value(L, 1); + CHECK_THAT( + path, + Catch::Matchers::Contains("OpenSpace\\cache\\colorFile.ppm") + ); } TEST_CASE("CreateSingleColorImage: Faulty 1st input type", "[createsinglecolorimage]") { ghoul::lua::LuaState L; - ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0 })); - ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0 })); + ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 }); + ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 }); CHECK_THROWS_WITH( openspace::luascriptfunctions::createSingeColorImage(L), @@ -70,7 +77,7 @@ TEST_CASE("CreateSingleColorImage: Faulty 2nd input type", "[createsinglecolorim TEST_CASE("CreateSingleColorImage: Invalid number of inputs", "[createsinglecolorimage]") { ghoul::lua::LuaState L; - ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0 })); + ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 }); CHECK_THROWS_WITH( openspace::luascriptfunctions::createSingeColorImage(L), @@ -83,7 +90,7 @@ TEST_CASE("CreateSingleColorImage: Faulty color value (vec4)", { ghoul::lua::LuaState L; ghoul::lua::push(L, "notCreatedColorFile"); - ghoul::lua::push(L, std::vector({ 1.0, 0.0, 0.0, 0.0 })); + ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0, 0.0 }); CHECK_THROWS_WITH( openspace::luascriptfunctions::createSingeColorImage(L), @@ -98,7 +105,7 @@ TEST_CASE("CreateSingleColorImage: Faulty color value (invalid values)", { ghoul::lua::LuaState L; ghoul::lua::push(L, "notCreatedColorFile"); - ghoul::lua::push(L, std::vector({ 255.0, 0.0, 0.0 })); + ghoul::lua::push(L, std::vector{ 255.0, 0.0, 0.0 }); // @TODO (emmbr 2020-02-04) This test case should be here, but as of now this case is // not handled. Finish it up when we have a better way of verifying that a dictionary @@ -117,7 +124,7 @@ TEST_CASE("CreateSingleColorImage: Check if file was created", { ghoul::lua::LuaState L; ghoul::lua::push(L, "colorFile2"); - ghoul::lua::push(L, std::vector({ 0.0, 1.0, 0.0 })); + ghoul::lua::push(L, std::vector{ 0.0, 1.0, 0.0 }); int res = openspace::luascriptfunctions::createSingeColorImage(L); @@ -128,9 +135,8 @@ TEST_CASE("CreateSingleColorImage: Check if file was created", TEST_CASE("CreateSingleColorImage: Load created image", "[createsinglecolorimage]") { ghoul::lua::LuaState L; - const glm::dvec3 color = { 1.0, 0.0, 0.0 }; ghoul::lua::push(L, "colorFile"); - ghoul::lua::push(L, std::vector({ color.x, color.y, color.z })); + ghoul::lua::push(L, std::vector{ 1.0, 0.0, 0.0 }); // Loads the same file that was created in a previous test case int res = openspace::luascriptfunctions::createSingeColorImage(L); From 43a333f48e6efcabc3e498d7f35dd7513bd70dc9 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Fri, 5 Feb 2021 10:12:51 +0100 Subject: [PATCH 35/41] Bring Tracy back to live (currently, the Launcher has to be bypassed because Qt is doing something strange --- apps/OpenSpace/main.cpp | 9 ++++----- ext/ghoul | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index 8272be8ef4..b370da39e6 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -41,11 +41,11 @@ #include #include #include -//#include -#include +#include #ifdef WIN32 #define GLFW_EXPOSE_NATIVE_WIN32 #endif +#include #include #include #include @@ -576,7 +576,7 @@ void mainPostDrawFunc() { glBindTexture(GL_TEXTURE_2D, texId); w.leftOrMain.handle->SendTexture( texId, - GL_TEXTURE_2D, + GLuint(GL_TEXTURE_2D), window.framebufferResolution().x, window.framebufferResolution().y ); @@ -587,7 +587,7 @@ void mainPostDrawFunc() { glBindTexture(GL_TEXTURE_2D, tId); w.right.handle->SendTexture( tId, - GL_TEXTURE_2D, + GLuint(GL_TEXTURE_2D), window.framebufferResolution().x, window.framebufferResolution().y ); @@ -1013,7 +1013,6 @@ std::string selectedSgctProfileFromLauncher(LauncherWindow& lw, bool hasCliSGCTC } int main(int argc, char* argv[]) { - #ifdef WIN32 SetUnhandledExceptionFilter(generateMiniDump); #endif // WIN32 diff --git a/ext/ghoul b/ext/ghoul index bd1ab84178..0b46e63ebe 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit bd1ab841785274173e4245c0bd32c80c828e018f +Subproject commit 0b46e63ebef03b4c08f3ea6f7e2c43cda73e8ea2 From c87b9b316e10fff469032ed25815b75ade9bbc71 Mon Sep 17 00:00:00 2001 From: Micah Date: Sat, 6 Feb 2021 16:43:00 -0500 Subject: [PATCH 36/41] fixed pioneer model (thanks DanTell); updated pioneer identifiers to allow spice and horizions to coexist. added meta info --- .../missions/pioneer/pioneer10.asset | 28 +++++++++++--- .../missions/pioneer/pioneer11.asset | 25 ++++++++++--- .../missions/pioneer/pioneermodel.asset | 12 +++++- .../voyager1_2__pioneer10_11.asset | 37 +++++++++++++++---- 4 files changed, 82 insertions(+), 20 deletions(-) diff --git a/data/assets/scene/solarsystem/missions/pioneer/pioneer10.asset b/data/assets/scene/solarsystem/missions/pioneer/pioneer10.asset index f76730f83c..8f7ad17c31 100644 --- a/data/assets/scene/solarsystem/missions/pioneer/pioneer10.asset +++ b/data/assets/scene/solarsystem/missions/pioneer/pioneer10.asset @@ -15,7 +15,7 @@ local kernelsList = {kernelsFolder .. '/p10-a.bsp'} local Pioneer10NAIF = "-23" local Pioneer10 = { - Identifier = "Pioneer10", + Identifier = "Pioneer_10", Parent = sunTransforms.SolarSystemBarycenter.Identifier, Transform = { Translation = { @@ -27,13 +27,15 @@ local Pioneer10 = { }, Renderable = model.PioneerModel, GUI = { - Name = "Pioneer 10", - Path = "/Solar System/Missions/Pioneer/10" + Name = "Pioneer 10 Spacecraft", + Path = "/Solar System/Missions/Pioneer", + Description = [[Pioneer 10 Spacecraft. Positioned by SPICE data.]] + } } local Pioneer10Trail = { - Identifier = "Pioneer10Trail", + Identifier = "Pioneer_10Trail", Parent = sunTransforms.SolarSystemBarycenter.Identifier, Renderable = { Type = "RenderableTrailTrajectory", @@ -51,8 +53,10 @@ local Pioneer10Trail = { -- 6545 is the number of days between the Start and End time (aka sample every 2d) }, GUI = { - Name = "Pioneer 10 Trail", - Path = "/Solar System/Missions/Pioneer/10" + Name = "Pioneer 10 Trail (SPICE)", + Path = "/Solar System/Missions/Pioneer", + Description = [[Pioneer 10 Trail, spanning March 3rd, 1972 to January 2nd, 1990. + Data from SPICE]] } } @@ -60,3 +64,15 @@ assetHelper.registerSceneGraphNodesAndExport(asset, { Pioneer10, Pioneer10Trail, }) + + +asset.meta = { + Name = "Pioneer 10", + Version = "1.0", + Description = [[ Pioneer 10 Model and Trail. Driven by SPICE data for high accuracy + from March 3rd, 1972 to January 2nd, 1990.]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"Pioneer_10", "Pioneer_10Trail"} +} diff --git a/data/assets/scene/solarsystem/missions/pioneer/pioneer11.asset b/data/assets/scene/solarsystem/missions/pioneer/pioneer11.asset index 5e69367ae1..ae51e753a8 100644 --- a/data/assets/scene/solarsystem/missions/pioneer/pioneer11.asset +++ b/data/assets/scene/solarsystem/missions/pioneer/pioneer11.asset @@ -30,13 +30,14 @@ local Pioneer11 = { }, Renderable = model.PioneerModel, GUI = { - Name = "Pioneer 11", - Path = "/Solar System/Missions/Pioneer/11" + Name = "Pioneer 11 Spacecraft", + Path = "/Solar System/Missions/Pioneer", + Description = [[Pioneer 11 Spacecraft. Positioned by SPICE data.]] } } local Pioneer11Trail = { - Identifier = "Pioneer11Trail", + Identifier = "Pioneer_11Trail", Parent = sunTransforms.SolarSystemBarycenter.Identifier, Renderable = { Type = "RenderableTrailTrajectory", @@ -54,8 +55,10 @@ local Pioneer11Trail = { --6087 is the number of days between the Start and End time (so sample every 2d) }, GUI = { - Name = "Pioneer 11 Trail", - Path = "/Solar System/Missions/Pioneer/11" + Name = "Pioneer 11 Trail (SPICE)", + Path = "/Solar System/Missions/Pioneer", + Description = [[Pioneer 11 Trail, spanning April 6th, 1973 to January 2nd, 1990. + Data from SPICE.]] } } @@ -63,3 +66,15 @@ assetHelper.registerSceneGraphNodesAndExport(asset, { Pioneer11, Pioneer11Trail, }) + + +asset.meta = { + Name = "Pioneer 11", + Version = "1.0", + Description = [[ Pioneer 11 Model and Trail. Driven by SPICE data for high accuracy + from April 6th, 1973 to January 2nd, 1990.]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"Pioneer_11", "Pioneer_11Trail"} +} diff --git a/data/assets/scene/solarsystem/missions/pioneer/pioneermodel.asset b/data/assets/scene/solarsystem/missions/pioneer/pioneermodel.asset index 1903e5bb71..a0b1b632ff 100644 --- a/data/assets/scene/solarsystem/missions/pioneer/pioneermodel.asset +++ b/data/assets/scene/solarsystem/missions/pioneer/pioneermodel.asset @@ -1,5 +1,5 @@ local assetHelper = asset.require('util/asset_helper') - +local sunTransforms = asset.require('scene/solarsystem/sun/transforms') local modelFolder = asset.syncedResource({ Name = "Pioneer 10/11 Models", @@ -21,3 +21,13 @@ local ModelRenderable = { } asset.export("PioneerModel", ModelRenderable) + +asset.meta = { + Name = "Pioneer Model", + Version = "1.0", + Description = [[ Pioneer model asset. Used by both pioneer 10 and pioneer 11 asset. + Untextured version of model from NASA 3D resources.]], + Author = "NASA", + URL = "https://nasa3d.arc.nasa.gov/detail/eoss-pioneer", + License = "NASA" +} \ No newline at end of file diff --git a/data/assets/scene/solarsystem/missions/voyagerpioneer/voyager1_2__pioneer10_11.asset b/data/assets/scene/solarsystem/missions/voyagerpioneer/voyager1_2__pioneer10_11.asset index b609658789..02be5ab03e 100644 --- a/data/assets/scene/solarsystem/missions/voyagerpioneer/voyager1_2__pioneer10_11.asset +++ b/data/assets/scene/solarsystem/missions/voyagerpioneer/voyager1_2__pioneer10_11.asset @@ -20,8 +20,10 @@ local voyager1 = { TimeStampSubsampleFactor = 1 }, GUI = { - Name = "Voyager 1", - Path = "/Solar System/Missions" + Name = "Voyager 1 Trail", + Path = "/Solar System/Missions/Voyager", + Description = [[Voyager 1 Trail, spanning September 6th, 1977 to December 31st, + 2030. Data from JPL Horizons.]] } } @@ -43,8 +45,10 @@ local voyager2 = { TimeStampSubsampleFactor = 1 }, GUI = { - Name = "Voyager 2", - Path = "/Solar System/Missions" + Name = "Voyager 2 Trail", + Path = "/Solar System/Missions/Voyager", + Description = [[Voyager 2 Trail, spanning August 21st, 1977 to December 31st, 2030. + Data from JPL Horizons.]] } } @@ -66,8 +70,10 @@ local pioneer10 = { TimeStampSubsampleFactor = 1 }, GUI = { - Name = "Pioneer 10", - Path = "/Solar System/Missions" + Name = "Pioneer 10 Trail", + Path = "/Solar System/Missions/Pioneer", + Description = [[Pioneer 10 Trail, spanning March 4th, 1972 to December 31st, 2030. + Data from JPL Horizons.]] } } @@ -89,9 +95,24 @@ local pioneer11 ={ TimeStampSubsampleFactor = 1 }, GUI = { - Name = "Pioneer 11", - Path = "/Solar System/Missions" + Name = "Pioneer 11 Trail", + Path = "/Solar System/Missions/Pioneer", + Description = [[Pioneer 11 Trail, spanning April 7th, 1973 to December 31st, 2030. + Data from JPL Horizons.]] } } assetHelper.registerSceneGraphNodesAndExport(asset, { voyager1, voyager2, pioneer10, pioneer11 }) + + +asset.meta = { + Name = "Pioneer and Voyager Trails", + Version = "1.0", + Description = [[ Pioneer 10, Pioneer 11, Voyager 1 and Voyager 2 trails. Driven by JPL + Horizons data for better performance then spice but lower resolution. Data is from + shortly after mission launches until December 31st, 2030.]], + Author = "OpenSpace Team", + URL = "http://openspaceproject.com", + License = "MIT license", + Identifiers = {"Pioneer10", "Pioneer11", "Voyager1", "Voyager2"} +} \ No newline at end of file From 26e42981f1c74043fb28f8b1752044f3f3135115 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 8 Feb 2021 11:03:57 +0100 Subject: [PATCH 37/41] Always keep double precision when sending number in Lua script over websocket (closes #1467) --- modules/server/src/topics/luascripttopic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/server/src/topics/luascripttopic.cpp b/modules/server/src/topics/luascripttopic.cpp index b36289d3de..a726d05ad5 100644 --- a/modules/server/src/topics/luascripttopic.cpp +++ b/modules/server/src/topics/luascripttopic.cpp @@ -101,7 +101,7 @@ namespace { return formatArrayAsLuaTable(it->get()); } if (it->is_number()) { - return fmt::format("{:E}", it->get()); + return fmt::format("{:.16f}", it->get()); } if (it->is_string()) { return formatLuaString(it->get()); From 51b12d31584503de89bfe2ef56b8d28fbcf293ed Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Mon, 8 Feb 2021 12:40:20 +0100 Subject: [PATCH 38/41] On second thought, use the default formatting since its precision is sufficient --- modules/server/src/topics/luascripttopic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/server/src/topics/luascripttopic.cpp b/modules/server/src/topics/luascripttopic.cpp index a726d05ad5..b718ea4838 100644 --- a/modules/server/src/topics/luascripttopic.cpp +++ b/modules/server/src/topics/luascripttopic.cpp @@ -101,7 +101,7 @@ namespace { return formatArrayAsLuaTable(it->get()); } if (it->is_number()) { - return fmt::format("{:.16f}", it->get()); + return fmt::format("{}", it->get()); } if (it->is_string()) { return formatLuaString(it->get()); From 78c0b23194268cb29b8965bd5bf18c119e71fe27 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 8 Feb 2021 17:54:02 +0100 Subject: [PATCH 39/41] Remove extra line --- include/openspace/properties/propertyowner.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/openspace/properties/propertyowner.h b/include/openspace/properties/propertyowner.h index d37c6d7b9b..d20257fe9d 100644 --- a/include/openspace/properties/propertyowner.h +++ b/include/openspace/properties/propertyowner.h @@ -294,7 +294,6 @@ public: // Generate JSON for documentation std::string generateJson() const override; - protected: /// The unique identifier of this PropertyOwner std::string _identifier; From 6d821d4f9164a2182216ec754e4f265f6cabc6c3 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 9 Feb 2021 09:12:43 +0100 Subject: [PATCH 40/41] Feature/codegen (#1480) * Add the ability to automatically generate code to extract values out of a Dictionary (see https://github.com/openspace/codegen for more information on how to use this) * Applied this technique to a large number of cases in the codebase * Don't add _codegen files to the repository Co-authored-by: Emma Broman --- .gitignore | 1 + .gitmodules | 3 + CMakeLists.txt | 29 +- Jenkinsfile | 5 + apps/OpenSpace/ext/launcher/CMakeLists.txt | 8 + .../openspace/documentation/documentation.h | 7 + include/openspace/documentation/verifier.inl | 61 +- include/openspace/rendering/renderable.h | 2 +- modules/CMakeLists.txt | 2 + .../rendering/renderableatmosphere.cpp | 533 +++++----------- modules/base/dashboard/dashboarditemangle.cpp | 165 ++--- modules/base/dashboard/dashboarditemdate.cpp | 50 +- .../base/dashboard/dashboarditemdistance.cpp | 184 +++--- .../base/dashboard/dashboarditemframerate.cpp | 113 ++-- .../base/dashboard/dashboarditemmission.cpp | 1 - .../dashboard/dashboarditempropertyvalue.cpp | 50 +- .../dashboarditemsimulationincrement.cpp | 79 +-- .../base/dashboard/dashboarditemspacing.cpp | 38 +- modules/base/dashboard/dashboarditemtext.cpp | 39 +- .../base/dashboard/dashboarditemvelocity.cpp | 55 +- .../base/lightsource/cameralightsource.cpp | 42 +- .../lightsource/scenegraphlightsource.cpp | 61 +- .../rendering/grids/renderableboxgrid.cpp | 60 +- .../base/rendering/grids/renderablegrid.cpp | 76 +-- modules/base/rendering/grids/renderablegrid.h | 6 +- .../rendering/grids/renderableradialgrid.cpp | 109 +--- .../grids/renderablesphericalgrid.cpp | 61 +- .../rendering/renderablecartesianaxes.cpp | 62 +- modules/base/rendering/renderablelabels.cpp | 490 ++++++--------- modules/base/rendering/renderablenodeline.cpp | 83 +-- modules/base/rendering/renderableplane.cpp | 65 +- .../rendering/renderableplaneimagelocal.cpp | 124 ++-- .../rendering/renderableplaneimageonline.cpp | 34 +- modules/base/rendering/renderablesphere.cpp | 189 +++--- modules/base/rendering/renderabletrail.cpp | 1 - .../base/rendering/screenspacedashboard.cpp | 46 +- .../base/rendering/screenspaceimagelocal.cpp | 55 +- .../base/rendering/screenspaceimageonline.cpp | 44 +- modules/base/rotation/constantrotation.cpp | 51 +- modules/base/rotation/fixedrotation.cpp | 229 +++---- modules/base/rotation/luarotation.cpp | 35 +- modules/base/rotation/staticrotation.cpp | 59 +- modules/base/rotation/timelinerotation.cpp | 6 - modules/base/scale/luascale.cpp | 28 +- modules/base/scale/nonuniformstaticscale.cpp | 27 +- modules/base/scale/staticscale.cpp | 27 +- modules/base/scale/timedependentscale.cpp | 55 +- modules/base/timeframe/timeframeinterval.cpp | 97 ++- modules/base/timeframe/timeframeunion.cpp | 35 +- modules/base/translation/luatranslation.cpp | 38 +- .../base/translation/statictranslation.cpp | 37 +- .../base/translation/timelinetranslation.cpp | 6 - .../rendering/renderablebillboardscloud.cpp | 586 ++++++------------ .../rendering/renderabledumeshes.cpp | 261 +++----- .../rendering/renderableplanescloud.cpp | 338 ++++------ .../rendering/renderablepoints.cpp | 175 +++--- .../rendering/renderableorbitdisc.cpp | 5 - .../tasks/exoplanetsdatapreparationtask.cpp | 6 - .../gaia/rendering/renderablegaiastars.cpp | 5 - modules/gaia/tasks/constructoctreetask.cpp | 5 - modules/gaia/tasks/readfitstask.cpp | 5 - modules/gaia/tasks/readspecktask.cpp | 5 - modules/globebrowsing/globebrowsingmodule.cpp | 57 +- .../src/dashboarditemglobelocation.cpp | 5 - .../globebrowsing/src/globetranslation.cpp | 5 - modules/globebrowsing/src/layer.cpp | 270 ++++---- modules/globebrowsing/src/renderableglobe.cpp | 8 - modules/kameleon/ext/kameleon | 2 +- .../tasks/kameleondocumentationtask.cpp | 6 - .../tasks/kameleonmetadatatojsontask.cpp | 6 - .../tasks/kameleonvolumetorawtask.cpp | 6 - modules/space/rendering/planetgeometry.cpp | 31 +- .../renderableconstellationbounds.cpp | 99 +-- modules/space/rendering/renderablerings.cpp | 90 +-- .../space/rendering/renderablesatellites.cpp | 65 +- .../space/rendering/renderablesmallbody.cpp | 69 +-- modules/space/rendering/renderablestars.cpp | 291 +++------ .../space/rendering/simplespheregeometry.cpp | 51 +- modules/space/rotation/spicerotation.cpp | 90 +-- modules/space/spacemodule.cpp | 1 - .../space/translation/horizonstranslation.cpp | 39 +- .../space/translation/keplertranslation.cpp | 113 ++-- .../space/translation/spicetranslation.cpp | 100 +-- modules/space/translation/tletranslation.cpp | 58 +- .../dashboard/dashboarditeminstruments.cpp | 69 +-- .../rendering/renderablefov.cpp | 42 ++ .../rendering/renderablemodelprojection.cpp | 5 - .../rendering/renderableplaneprojection.cpp | 39 +- .../rendering/renderableplanetprojection.cpp | 6 - .../rendering/renderableshadowcylinder.cpp | 157 ++--- .../util/instrumentdecoder.cpp | 50 +- .../util/projectioncomponent.cpp | 428 ++++++------- modules/sync/tasks/syncassettask.cpp | 6 - .../volume/tasks/generaterawvolumetask.cpp | 6 - modules/webbrowser/codegentest.exe.manifest | 20 + src/CMakeLists.txt | 2 + src/documentation/documentation.cpp | 2 +- src/documentation/verifier.cpp | 118 +++- .../tasks/convertrecfileversiontask.cpp | 6 - .../tasks/convertrecformattask.cpp | 6 - src/rendering/renderable.cpp | 112 ++-- src/scene/scenegraphnode.cpp | 13 +- .../set_openspace_compile_settings.cmake | 4 + support/coding/codegen | 1 + 104 files changed, 2939 insertions(+), 4769 deletions(-) create mode 100644 modules/webbrowser/codegentest.exe.manifest create mode 160000 support/coding/codegen diff --git a/.gitignore b/.gitignore index d80ea9cee9..e75af825e0 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ Thumbs.db customization.lua # The COMMIT info is generated everytime CMake is run COMMIT.md +*_codegen.cpp diff --git a/.gitmodules b/.gitmodules index 0bfcb7f59d..112e7a1300 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,6 @@ [submodule "ext/date"] path = ext/date url = https://github.com/HowardHinnant/date +[submodule "support/coding/codegen"] + path = support/coding/codegen + url = https://github.com/OpenSpace/codegen diff --git a/CMakeLists.txt b/CMakeLists.txt index 800fe645df..a3c2a8c767 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,12 +139,29 @@ if (UNIX AND CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++ -lc++abi") endif () -# Add external dependencies -add_subdirectory(${OPENSPACE_BASE_DIR}/ext) +add_subdirectory(ext) -# include(src/CMakeLists.txt) add_subdirectory(src) +add_subdirectory(support/coding/codegen) +# It is important that the __codegen.h do not actually exist so +# that this target is never considered as finished +add_custom_target( + run_codegen + ALL DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/__codegen.h" +) +add_dependencies(run_codegen codegen) +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/__codegen.h" + COMMAND codegen ARGS "${OPENSPACE_BASE_DIR}/modules" "${OPENSPACE_BASE_DIR}/src" + VERBATIM +) +set_folder_location(codegen-lib "support") +set_folder_location(codegen "support") +set_folder_location(run_codegen "support") + + # Qt # Unfortunately, we have to set this value manually; sigh # In the future, if the Qt version is updated, just add to this variable ---abock @@ -176,6 +193,12 @@ begin_header("Configuring Modules") add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/modules") end_header("End: Configuring Modules") + +add_subdirectory(support/coding/codegen/tests) +set_folder_location(run_test_codegen "Unit Tests/support") +set_folder_location(codegentest "Unit Tests") + + begin_header("Configuring Applications") add_subdirectory("${OPENSPACE_APPS_DIR}") end_header("End: Configuring Applications") diff --git a/Jenkinsfile b/Jenkinsfile index f4de007c31..5fc5351950 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -114,6 +114,7 @@ linux_gcc_make: { } stage('linux-gcc-make/test') { // testHelper.runUnitTests('build/OpenSpaceTest'); + // testHelper.runUnitTests('bin/codegentest') } cleanWs() } // node('linux') @@ -134,6 +135,7 @@ linux_gcc_ninja: { } stage('linux-gcc-ninja/test') { // testHelper.runUnitTests('build/OpenSpaceTest'); + // testHelper.runUnitTests('bin/codegentest') } cleanWs() } // node('linux') @@ -155,6 +157,7 @@ linux_clang_make: { } stage('linux-clang-make/test') { // testHelper.runUnitTests('build/OpenSpaceTest'); + // testHelper.runUnitTests('bin/codegentest') } cleanWs() } // node('linux') @@ -175,6 +178,7 @@ linux_clang_ninja: { } stage('linux-clang-ninja/test') { // testHelper.runUnitTests('build/OpenSpaceTest'); + // testHelper.runUnitTests('bin/codegentest') } cleanWs() } // node('linux') @@ -194,6 +198,7 @@ windows_msvc: { stage('windows-msvc/test') { // Currently, the unit tests are failing on Windows // testHelper.runUnitTests('bin\\Debug\\OpenSpaceTest') + testHelper.runUnitTests('bin\\Debug\\codegentest') } cleanWs() } // node('windows') diff --git a/apps/OpenSpace/ext/launcher/CMakeLists.txt b/apps/OpenSpace/ext/launcher/CMakeLists.txt index 2ab5cf90ac..460f486412 100644 --- a/apps/OpenSpace/ext/launcher/CMakeLists.txt +++ b/apps/OpenSpace/ext/launcher/CMakeLists.txt @@ -90,3 +90,11 @@ set_openspace_compile_settings(openspace-ui-launcher) target_include_directories(openspace-ui-launcher PUBLIC include) target_link_libraries(openspace-ui-launcher PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets openspace-core) +if (MSVC) +set(MSVC_WARNINGS + "/wd4619" # #pragma warning: there is no warning number (raised by Qt headers) + "/wd4946" # reinterpret_cast used between related classes: +) +target_compile_options(openspace-ui-launcher INTERFACE ${MSVC_WARNINGS}) + +endif () diff --git a/include/openspace/documentation/documentation.h b/include/openspace/documentation/documentation.h index d01bcd1c82..f40ebb1d06 100644 --- a/include/openspace/documentation/documentation.h +++ b/include/openspace/documentation/documentation.h @@ -323,4 +323,11 @@ std::string to_string(const openspace::documentation::TestResult::Warning::Reaso } // namespace ghoul +// The verifier header depends on the classes defined in here, but we want to make it +// easier for consumers of this header to just have access to all verifiers without +// needing to include this file separately. Particularly with the use of the codegen, it +// might lead to some unexcepted error messages about recognized identifiers in the +// generated code which look scary +#include + #endif // __OPENSPACE_CORE___DOCUMENTATION___H__ diff --git a/include/openspace/documentation/verifier.inl b/include/openspace/documentation/verifier.inl index bcab502137..d61169dd2c 100644 --- a/include/openspace/documentation/verifier.inl +++ b/include/openspace/documentation/verifier.inl @@ -29,6 +29,18 @@ namespace openspace::documentation { +template <> +TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, + const std::string& key) const; + +template <> +TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, + const std::string& key) const; + +template <> +TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, + const std::string& key) const; + template TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const @@ -122,7 +134,22 @@ TestResult OperatorVerifier::operator()(const ghoul::Dictionary& di { TestResult res = T::operator()(dict, key); if (res.success) { - if (Operator()(dict.value(key), value)) { + typename T::Type val; + if constexpr (std::is_same_v) { + const double d = dict.value(key); + double intPart; + bool isInt = modf(d, &intPart) == 0.0; + if (isInt) { + val = static_cast(d); + } + else { + return { false, { { key, TestResult::Offense::Reason::WrongType } }, {} }; + } + } + else { + val = dict.value(key); + } + if (Operator()(val, value)) { return { true, {}, {} }; } else { @@ -270,7 +297,21 @@ TestResult InRangeVerifier::operator()(const ghoul::Dictionary& dict, { TestResult res = T::operator()(dict, key); if (res.success) { - typename T::Type val = dict.value(key); + typename T::Type val; + if constexpr (std::is_same_v) { + const double d = dict.value(key); + double intPart; + bool isInt = modf(d, &intPart) == 0.0; + if (isInt) { + val = static_cast(d); + } + else { + return { false, { { key, TestResult::Offense::Reason::WrongType } }, {} }; + } + } + else { + val = dict.value(key); + } if (val >= lower && val <= upper) { return { true, {}, {} }; @@ -303,7 +344,21 @@ TestResult NotInRangeVerifier::operator()(const ghoul::Dictionary& dict, const std::string& key) const { TestResult res = T::operator()(dict, key); if (res.success) { - typename T::Type val = dict.value(key); + typename T::Type val; + if constexpr (std::is_same_v) { + const double d = dict.value(key); + double intPart; + bool isInt = modf(d, &intPart) == 0.0; + if (isInt) { + val = static_cast(d); + } + else { + return { false, { { key, TestResult::Offense::Reason::WrongType } }, {} }; + } + } + else { + val = dict.value(key); + } if (val >= lower && val <= upper) { return { false, { { key, TestResult::Offense::Reason::Verification } }, {} }; diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index 884d10bee1..3fa96880d4 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -61,7 +61,7 @@ public: }; static ghoul::mm_unique_ptr createFromDictionary( - const ghoul::Dictionary& dictionary); + ghoul::Dictionary dictionary); Renderable(const ghoul::Dictionary& dictionary); virtual ~Renderable() = default; diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index 330ad3664b..b08c0bf7e5 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -288,6 +288,8 @@ foreach (val RANGE ${enabled_module_count}) list(APPEND all_enabled_modules "${library_name}") begin_header("Module ${name} (${library_name})") add_subdirectory(${path}) + # Make sure that the code generator always runs before a module + add_dependencies(${library_name} run_codegen) end_header("End: Module ${name}") message(STATUS "") diff --git a/modules/atmosphere/rendering/renderableatmosphere.cpp b/modules/atmosphere/rendering/renderableatmosphere.cpp index cbeb0a028a..4859a00628 100644 --- a/modules/atmosphere/rendering/renderableatmosphere.cpp +++ b/modules/atmosphere/rendering/renderableatmosphere.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #ifdef WIN32 #define _USE_MATH_DEFINES @@ -54,27 +55,6 @@ #include namespace { - static const char* _loggerCat = "RenderableAtmosphere"; - - constexpr const char* KeyShadowGroup = "ShadowGroup"; - constexpr const char* KeyShadowSource = "Source"; - constexpr const char* KeyShadowCaster = "Caster"; - - constexpr const char* KeyPlanetRadius = "PlanetRadius"; - constexpr const char* KeyAverageGroundReflectance = "PlanetAverageGroundReflectance"; - constexpr const char* KeyRayleigh = "Rayleigh"; - constexpr const char* KeyRayleighHeightScale = "H_R"; - constexpr const char* KeyOzone = "Ozone"; - constexpr const char* KeyOzoneHeightScale = "H_O"; - constexpr const char* KeyMie = "Mie"; - constexpr const char* KeyMieHeightScale = "H_M"; - constexpr const char* KeyMiePhaseConstant = "G"; - constexpr const char* KeyImage = "Image"; - constexpr const char* KeyToneMappingOp = "ToneMapping"; - constexpr const char* KeyATMDebug = "Debug"; - constexpr const char* KeyTextureScale = "PreCalculatedTextureScale"; - constexpr const char* KeySaveTextures = "SaveCalculatedTextures"; - constexpr openspace::properties::Property::PropertyInfo AtmosphereHeightInfo = { "AtmosphereHeight", "Atmosphere Height (KM)", @@ -174,238 +154,97 @@ namespace { "Enable Hard Shadows for Eclipses", "Enable/Disables hard shadows through the atmosphere" }; + + + struct [[codegen::Dictionary(RenderableAtmosphere)]] Parameters { + struct ShadowGroup { + // Individual light sources + struct SourceElement { + // The scene graph node name of the source + std::string name; + // The radius of the object in meters + double radius; + }; + // A list of light sources + std::vector sources; + + // Individual shadow casters + struct CasterElement { + // The scene graph node name of the source + std::string name; + // The radius of the object in meters + double radius; + }; + + // A list of objects that cast light on this atmosphere + std::vector casters; + }; + // Declares shadow groups, meaning which nodes are considered in shadow calculations + std::optional shadowGroup; + + // [[codegen::verbatim(AtmosphereHeightInfo.description)]] + float atmosphereHeight; + + // The radius of the planet in meters + float planetRadius; + + float planetAverageGroundReflectance; + + // [[codegen::verbatim(SunIntensityInfo.description)]] + std::optional sunIntensity; + + // [[codegen::verbatim(MieScatteringExtinctionPropCoeffInfo.description)]] + std::optional mieScatteringExtinctionPropCoefficient; + + // [[codegen::verbatim(GroundRadianceEmittioninfo.description)]] + float groundRadianceEmission; + + struct Rayleigh { + struct Coefficients { + glm::dvec3 wavelengths; + glm::dvec3 scattering; + }; + Coefficients coefficients; + float heightScale [[codegen::key("H_R")]]; + }; + Rayleigh rayleigh; + + struct Ozone { + struct Coefficients { + std::optional extinction; + }; + std::optional coefficients; + std::optional heightScale [[codegen::key("H_O")]]; + }; + std::optional ozone; + + struct Mie { + struct Coefficients { + glm::dvec3 scattering; + glm::dvec3 extinction; + }; + Coefficients coefficients; + float heightScale [[codegen::key("H_M")]]; + float phaseConstant [[codegen::key("G"), codegen::inrange(-1.0, 1.0)]]; + }; + Mie mie; + + struct ATMDebug { + std::optional preCalculatedTextureScale [[codegen::inrange(0.0, 1.0)]]; + std::optional saveCalculatedTextures; + }; + std::optional debug; + }; +#include "renderableatmosphere_codegen.cpp" + } // namespace namespace openspace { documentation::Documentation RenderableAtmosphere::Documentation() { - using namespace documentation; - - TableVerifier* shadowGroupTable = new TableVerifier({ - { - "Sources", - new TableVerifier({ - { - "*", - new TableVerifier({ - { - "Name", - new StringVerifier, - Optional::No, - "The scene graph node name of the source" - }, - { - "Radius", - new DoubleVerifier, - Optional::No, - "The radius of the object in meters" - } - }), - Optional::Yes, - "Individual light sources" - } - }), - Optional::No, - "A list of light sources" - }, - { - "Casters", - new TableVerifier({ - { - "*", - new TableVerifier({ - { - "Name", - new StringVerifier, - Optional::No, - "The scene graph node name of the caster" - }, - { - "Radius", - new DoubleVerifier, - Optional::No, - "The radius of the object in meters" - } - }), - Optional::Yes, - "Individual shadow casters" - } - }), - Optional::No, - "A list of objects that cast light on this atmosphere" - } - }); - - TableVerifier* rayleighTable = new TableVerifier({ - { - "Coefficients", - new TableVerifier({ - { - "Wavelengths", - new DoubleVector3Verifier, - Optional::Yes, - "" - }, - { - "Scattering", - new DoubleVector3Verifier, - Optional::No, - "" - } - }), - Optional::No, - "" - }, - { - KeyRayleighHeightScale, - new DoubleVerifier, - Optional::No, - "" - }, - }); - - TableVerifier* ozoneTable = new TableVerifier({ - { - KeyOzoneHeightScale, - new DoubleVerifier, - Optional::Yes, - "" - }, - { - "Coefficients", - new TableVerifier({ - { - "Extinction", - new DoubleVector4Verifier, - Optional::Yes, - "" - } - }), - Optional::Yes, - "" - } - }); - - TableVerifier* mieTable = new TableVerifier({ - { - KeyMieHeightScale, - new DoubleVerifier, - Optional::No, - "" - }, - { - "Coefficients", - new TableVerifier({ - { - "Scattering", - new DoubleVector3Verifier, - Optional::No, - "" - }, - { - "Extinction", - new DoubleVector3Verifier, - Optional::No, - "" - } - }), - Optional::No, - "" - }, - { - KeyMiePhaseConstant, - new DoubleInRangeVerifier(-1.0, 1.0), - Optional::No, - "" - } - }); - - return { - "RenderableAtmosphere", - "atmosphere_renderable_atmosphere", - { - { - KeyShadowGroup, - shadowGroupTable, - Optional::Yes, - "Declares shadow groups, meaning which nodes are considered in shadow " - "calculations" - }, - { - AtmosphereHeightInfo.identifier, - new DoubleVerifier, - Optional::No, - AtmosphereHeightInfo.description - }, - { - KeyPlanetRadius, - new DoubleVerifier, - Optional::No, - "The radius of the planet in meters" - }, - { - KeyAverageGroundReflectance, - new DoubleVerifier, - Optional::No, - "" - }, - { - SunIntensityInfo.identifier, - new DoubleVerifier, - Optional::Yes, - SunIntensityInfo.description - }, - { - MieScatteringExtinctionPropCoeffInfo.identifier, - new DoubleVerifier, - Optional::Yes, - MieScatteringExtinctionPropCoeffInfo.description - }, - { - GroundRadianceEmittioninfo.identifier, - new DoubleVerifier, - Optional::No, - GroundRadianceEmittioninfo.description - }, - { - KeyRayleigh, - rayleighTable, - Optional::No, - "" - }, - { - KeyOzone, - ozoneTable, - Optional::Yes, - "" - }, - { - KeyMie, - mieTable, - Optional::No, - "" - }, - { - KeyATMDebug, - new TableVerifier({ - { - KeyTextureScale, - new DoubleInRangeVerifier(0.0, 1.0), - Optional::Yes, - "" - }, - { - KeySaveTextures, - new BoolVerifier, - Optional::Yes, - "" - } - }), - Optional::Yes, - "" - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "atmosphere_renderable_atmosphere"; + return doc; } RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary) @@ -438,139 +277,6 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary) , _sunFollowingCameraEnabled(EnableSunOnCameraPositionInfo, false) , _hardShadowsEnabled(EclipseHardShadowsInfo, false) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableAtmosphere" - ); - - //================================================================ - //======== Reads Shadow (Eclipses) Entries in asset file ========= - //================================================================ - if (dictionary.hasKey(KeyShadowGroup)) { - ghoul::Dictionary shadowDictionary = - dictionary.value(KeyShadowGroup); - - std::vector> sourceArray; - ghoul::Dictionary sources = shadowDictionary.value("Sources"); - for (std::string_view k : sources.keys()) { - ghoul::Dictionary source = sources.value(k); - - std::string name = source.value("Name"); - double radius = source.value("Radius"); - sourceArray.emplace_back(name, radius); - } - - std::vector> casterArray; - ghoul::Dictionary casters = shadowDictionary.value("Casters"); - for (std::string_view k : casters.keys()) { - ghoul::Dictionary caster = casters.value(k); - - std::string name = caster.value("Name"); - double radius = caster.value("Radius"); - casterArray.emplace_back(name, radius); - } - - _shadowEnabled = !sourceArray.empty() && !casterArray.empty(); - for (const std::pair& source : sourceArray) { - for (const std::pair& caster : casterArray) { - ShadowConfiguration sc; - sc.source = source; - sc.caster = caster; - _shadowConfArray.push_back(sc); - } - } - } - - //================================================================ - //========== Reads Atmosphere Entries from asset file ============ - //================================================================ - _atmosphereHeight = static_cast( - dictionary.value(AtmosphereHeightInfo.identifier) - ); - _planetRadius = static_cast(dictionary.value(KeyPlanetRadius)); - _groundAverageReflectance = static_cast( - dictionary.value(KeyAverageGroundReflectance) - ); - _groundRadianceEmission = static_cast( - dictionary.value(GroundRadianceEmittioninfo.identifier) - ); - - if (dictionary.hasKey(SunIntensityInfo.identifier)) { - _sunIntensity = static_cast( - dictionary.value(SunIntensityInfo.identifier) - ); - } - - if (dictionary.hasKey(MieScatteringExtinctionPropCoeffInfo.identifier)) { - _mieScattExtPropCoefProp = static_cast( - dictionary.value(MieScatteringExtinctionPropCoeffInfo.identifier) - ); - } - - { - ghoul::Dictionary rayleighDict = dictionary.value(KeyRayleigh); - - ghoul::Dictionary coeffs = rayleighDict.value("Coefficients"); - _rayleighScatteringCoeff = coeffs.value("Scattering"); - - _rayleighHeightScale = static_cast( - rayleighDict.value(KeyRayleighHeightScale) - ); - } - - if (dictionary.hasValue(KeyOzone)) { - ghoul::Dictionary ozoneDict = dictionary.value(KeyOzone); - - if (ozoneDict.hasValue(KeyOzoneHeightScale)) { - _ozoneHeightScale = static_cast( - ozoneDict.value(KeyOzoneHeightScale) - ); - _ozoneEnabled = true; - } - - if (ozoneDict.hasValue("Coefficients")) { - ghoul::Dictionary coeff = ozoneDict.value("Coefficients"); - if (coeff.hasValue("Extinction")) { - _ozoneCoeff = coeff.value("Extinction"); - } - } - } - - { - ghoul::Dictionary mieDict = dictionary.value(KeyMie); - _mieHeightScale = static_cast(mieDict.value(KeyMieHeightScale)); - - ghoul::Dictionary coeffs = mieDict.value("Coefficients"); - - _mieScatteringCoeff = coeffs.value("Scattering"); - _mieExtinctionCoeff = coeffs.value("Extinction"); - - _miePhaseConstant = static_cast( - mieDict.value(KeyMiePhaseConstant) - ); - } - - if (dictionary.hasValue(KeyATMDebug)) { - ghoul::Dictionary debugDict = dictionary.value(KeyATMDebug); - if (debugDict.hasKey(KeyTextureScale)) { - _preCalculatedTexturesScale = static_cast( - debugDict.value(KeyTextureScale) - ); - LDEBUG(fmt::format( - "Atmosphere Texture Scaled to {}", _preCalculatedTexturesScale - )); - } - - if (debugDict.hasKey(KeySaveTextures)) { - _saveCalculationsToTexture = debugDict.value(KeySaveTextures); - LDEBUG("Saving Precalculated Atmosphere Textures"); - } - } - - //======================================================== - //============== Atmosphere Properties =================== - //======================================================== auto updateWithCalculation = [this]() { _deferredCasterNeedsUpdate = true; _deferredCasterNeedsCalculation = true; @@ -579,48 +285,93 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary) _deferredCasterNeedsUpdate = true; }; + const Parameters p = codegen::bake(dictionary); + + _shadowEnabled = p.shadowGroup.has_value(); + if (_shadowEnabled) { + for (const Parameters::ShadowGroup::SourceElement& s : p.shadowGroup->sources) { + for (const Parameters::ShadowGroup::CasterElement& c : + p.shadowGroup->casters) + { + ShadowConfiguration sc; + sc.source = std::pair(s.name, s.radius); + sc.caster = std::pair(c.name, c.radius); + _shadowConfArray.push_back(sc); + } + } + } + + _atmosphereHeight = p.atmosphereHeight; _atmosphereHeight.onChange(updateWithCalculation); addProperty(_atmosphereHeight); + _planetRadius = p.planetRadius; + + _groundAverageReflectance = p.planetAverageGroundReflectance; _groundAverageReflectance.onChange(updateWithCalculation); addProperty(_groundAverageReflectance); - _groundRadianceEmission.onChange(updateWithoutCalculation); - addProperty(_groundRadianceEmission); + _sunIntensity = p.sunIntensity.value_or(_sunIntensity); + _sunIntensity.onChange(updateWithoutCalculation); + addProperty(_sunIntensity); - _rayleighHeightScale.onChange(updateWithCalculation); - addProperty(_rayleighHeightScale); + _mieScattExtPropCoefProp = + p.mieScatteringExtinctionPropCoefficient.value_or(_mieScattExtPropCoefProp); + _rayleighScatteringCoeff = p.rayleigh.coefficients.scattering; _rayleighScatteringCoeff.onChange(updateWithCalculation); addProperty(_rayleighScatteringCoeff); + _rayleighHeightScale = p.rayleigh.heightScale; + _rayleighHeightScale.onChange(updateWithCalculation); + addProperty(_rayleighHeightScale); + + if (p.ozone.has_value()) { + _ozoneHeightScale = p.ozone->heightScale.value_or(_ozoneHeightScale); + _ozoneEnabled = p.ozone->heightScale.has_value(); + + if (p.ozone->coefficients.has_value()) { + _ozoneCoeff = p.ozone->coefficients->extinction.value_or(_ozoneCoeff); + } + } _ozoneEnabled.onChange(updateWithCalculation); addProperty(_ozoneEnabled); - _ozoneHeightScale.onChange(updateWithCalculation); addProperty(_ozoneHeightScale); - _ozoneCoeff.onChange(updateWithCalculation); addProperty(_ozoneCoeff); + _mieHeightScale = p.mie.heightScale; _mieHeightScale.onChange(updateWithCalculation); addProperty(_mieHeightScale); + _mieScatteringCoeff = p.mie.coefficients.scattering; _mieScatteringCoeff.onChange(updateWithCalculation); addProperty(_mieScatteringCoeff); + _mieExtinctionCoeff = p.mie.coefficients.extinction; + _miePhaseConstant = p.mie.phaseConstant; + _miePhaseConstant.onChange(updateWithCalculation); + addProperty(_miePhaseConstant); + _mieScatteringExtinctionPropCoefficient = _mieScattExtPropCoefProp != 1.f ? _mieScattExtPropCoefProp : _mieScatteringCoeff.value().x / _mieExtinctionCoeff.x; _mieScatteringExtinctionPropCoefficient.onChange(updateWithCalculation); addProperty(_mieScatteringExtinctionPropCoefficient); + + if (p.debug.has_value()) { + _preCalculatedTexturesScale = + p.debug->preCalculatedTextureScale.value_or(_preCalculatedTexturesScale); - _miePhaseConstant.onChange(updateWithCalculation); - addProperty(_miePhaseConstant); + _saveCalculationsToTexture = + p.debug->saveCalculatedTextures.value_or(_saveCalculationsToTexture); + } - _sunIntensity.onChange(updateWithoutCalculation); - addProperty(_sunIntensity); + _groundRadianceEmission = p.groundRadianceEmission; + _groundRadianceEmission.onChange(updateWithoutCalculation); + addProperty(_groundRadianceEmission); _sunFollowingCameraEnabled.onChange(updateWithoutCalculation); addProperty(_sunFollowingCameraEnabled); diff --git a/modules/base/dashboard/dashboarditemangle.cpp b/modules/base/dashboard/dashboarditemangle.cpp index 42ae2afbf4..5034b763dc 100644 --- a/modules/base/dashboard/dashboarditemangle.cpp +++ b/modules/base/dashboard/dashboarditemangle.cpp @@ -85,66 +85,36 @@ namespace { "If a scene graph node is selected as type, this value specifies the name of the " "node that is to be used as the destination for computing the angle." }; + + struct [[codegen::Dictionary(DashboardItemAngle)]] Parameters { + enum class Type { + Node, + Focus, + Camera + }; + + // [[codegen::verbatim(SourceTypeInfo.description)]] + std::optional sourceType; + // [[codegen::verbatim(SourceNodeNameInfo.description)]] + std::optional sourceNodeName; + // [[codegen::verbatim(ReferenceTypeInfo.description)]] + Type referenceType; + // [[codegen::verbatim(ReferenceNodeNameInfo.description)]] + std::optional referenceNodeName; + // [[codegen::verbatim(DestinationTypeInfo.description)]] + std::optional destinationType; + // [[codegen::verbatim(DestinationNodeNameInfo.description)]] + std::optional destinationNodeName; + }; +#include "dashboarditemangle_codegen.cpp" } // namespace namespace openspace { documentation::Documentation DashboardItemAngle::Documentation() { - using namespace documentation; - - return { - "DashboardItem Angle", - "base_dashboarditem_angle", - { - { - "Type", - new StringEqualVerifier("DashboardItemAngle"), - Optional::No - }, - { - SourceTypeInfo.identifier, - new StringInListVerifier({ - "Node", "Focus", "Camera" - }), - Optional::Yes, - SourceTypeInfo.description - }, - { - SourceNodeNameInfo.identifier, - new StringVerifier, - Optional::Yes, - SourceNodeNameInfo.description - }, - { - ReferenceTypeInfo.identifier, - new StringInListVerifier({ - "Node", "Focus", "Camera" - }), - Optional::No, - ReferenceTypeInfo.description - }, - { - ReferenceNodeNameInfo.identifier, - new StringVerifier, - Optional::Yes, - ReferenceNodeNameInfo.description - }, - { - DestinationTypeInfo.identifier, - new StringInListVerifier({ - "Node", "Focus", "Camera" - }), - Optional::Yes, - DestinationTypeInfo.description - }, - { - DestinationNodeNameInfo.identifier, - new StringVerifier, - Optional::Yes, - DestinationNodeNameInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_angle"; + return doc; } DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) @@ -174,11 +144,7 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) nullptr } { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemAngle" - ); + const Parameters p = codegen::bake(dictionary); _source.type.addOptions({ { Type::Node, "Node" }, @@ -190,16 +156,17 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) properties::Property::Visibility(_source.type == Type::Node) ); }); - if (dictionary.hasKey(SourceTypeInfo.identifier)) { - std::string value = dictionary.value(SourceTypeInfo.identifier); - if (value == "Node") { - _source.type = Type::Node; - } - else if (value == "Focus") { - _source.type = Type::Focus; - } - else { - _source.type = Type::Camera; + if (p.sourceType.has_value()) { + switch (*p.sourceType) { + case Parameters::Type::Node: + _source.type = Type::Node; + break; + case Parameters::Type::Focus: + _source.type = Type::Focus; + break; + default: + _source.type = Type::Camera; + break; } } else { @@ -209,10 +176,8 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) _source.nodeName.onChange([this]() { _source.node = nullptr; }); if (_source.type == Type::Node) { - if (dictionary.hasKey(SourceNodeNameInfo.identifier)) { - _source.nodeName = dictionary.value( - SourceNodeNameInfo.identifier - ); + if (p.sourceNodeName.has_value()) { + _source.nodeName = *p.sourceNodeName; } else { LERRORC( @@ -234,24 +199,23 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) properties::Property::Visibility(_reference.type == Type::Node) ); }); - std::string value = dictionary.value(ReferenceTypeInfo.identifier); - if (value == "Node") { - _reference.type = Type::Node; - } - else if (value == "Focus") { - _reference.type = Type::Focus; - } - else { - _reference.type = Type::Camera; + switch (p.referenceType) { + case Parameters::Type::Node: + _reference.type = Type::Node; + break; + case Parameters::Type::Focus: + _reference.type = Type::Focus; + break; + default: + _reference.type = Type::Camera; + break; } addProperty(_reference.type); _reference.nodeName.onChange([this]() { _reference.node = nullptr; }); if (_reference.type == Type::Node) { - if (dictionary.hasKey(ReferenceNodeNameInfo.identifier)) { - _reference.nodeName = dictionary.value( - ReferenceNodeNameInfo.identifier - ); + if (p.referenceNodeName.has_value()) { + _reference.nodeName = *p.referenceNodeName; } else { LERRORC( @@ -272,16 +236,17 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) properties::Property::Visibility(_source.type == Type::Node) ); }); - if (dictionary.hasKey(DestinationTypeInfo.identifier)) { - std::string type = dictionary.value(DestinationTypeInfo.identifier); - if (type == "Node") { - _destination.type = Type::Node; - } - else if (type == "Focus") { - _destination.type = Type::Focus; - } - else { - _destination.type = Type::Camera; + if (p.destinationType.has_value()) { + switch (*p.destinationType) { + case Parameters::Type::Node: + _destination.type = Type::Node; + break; + case Parameters::Type::Focus: + _destination.type = Type::Focus; + break; + default: + _destination.type = Type::Camera; + break; } } else { @@ -290,10 +255,8 @@ DashboardItemAngle::DashboardItemAngle(const ghoul::Dictionary& dictionary) addProperty(_destination.type); _destination.nodeName.onChange([this]() { _destination.node = nullptr; }); if (_destination.type == Type::Node) { - if (dictionary.hasKey(DestinationNodeNameInfo.identifier)) { - _destination.nodeName = dictionary.value( - DestinationNodeNameInfo.identifier - ); + if (p.destinationNodeName.has_value()) { + _destination.nodeName = *p.destinationNodeName; } else { LERRORC( diff --git a/modules/base/dashboard/dashboarditemdate.cpp b/modules/base/dashboard/dashboarditemdate.cpp index f47f5b9b44..87dc11ac6c 100644 --- a/modules/base/dashboard/dashboarditemdate.cpp +++ b/modules/base/dashboard/dashboarditemdate.cpp @@ -51,35 +51,23 @@ namespace { "https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html for full " "information about how to structure this format" }; + + struct [[codegen::Dictionary(DashboardItemDate)]] Parameters { + // [[codegen::verbatim(FormatStringInfo.description)]] + std::optional formatString; + + // [[codegen::verbatim(TimeFormatInfo.description)]] + std::optional timeFormat; + }; +#include "dashboarditemdate_codegen.cpp" } // namespace namespace openspace { documentation::Documentation DashboardItemDate::Documentation() { - using namespace documentation; - return { - "DashboardItem Date", - "base_dashboarditem_date", - { - { - "Type", - new StringEqualVerifier("DashboardItemDate"), - Optional::No - }, - { - FormatStringInfo.identifier, - new StringVerifier, - Optional::Yes, - FormatStringInfo.description - }, - { - TimeFormatInfo.identifier, - new StringVerifier, - Optional::Yes, - TimeFormatInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_date"; + return doc; } DashboardItemDate::DashboardItemDate(const ghoul::Dictionary& dictionary) @@ -87,20 +75,12 @@ DashboardItemDate::DashboardItemDate(const ghoul::Dictionary& dictionary) , _formatString(FormatStringInfo, "Date: {} UTC") , _timeFormat(TimeFormatInfo, "YYYY MON DDTHR:MN:SC.### ::RND") { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemDate" - ); + const Parameters p = codegen::bake(dictionary); - if (dictionary.hasKey(FormatStringInfo.identifier)) { - _formatString = dictionary.value(FormatStringInfo.identifier); - } + _formatString = p.formatString.value_or(_formatString); addProperty(_formatString); - if (dictionary.hasKey(TimeFormatInfo.identifier)) { - _timeFormat = dictionary.value(TimeFormatInfo.identifier); - } + _timeFormat = p.timeFormat.value_or(_timeFormat); addProperty(_timeFormat); } diff --git a/modules/base/dashboard/dashboarditemdistance.cpp b/modules/base/dashboard/dashboarditemdistance.cpp index f973743453..bcca68c879 100644 --- a/modules/base/dashboard/dashboarditemdistance.cpp +++ b/modules/base/dashboard/dashboarditemdistance.cpp @@ -104,69 +104,45 @@ namespace { ); return res; } + + struct [[codegen::Dictionary(DashboardItemDistance)]] Parameters { + enum class TypeInfo { + Node, + NodeSurface [[codegen::key("Node Surface")]], + Focus, + Camera + }; + + // [[codegen::verbatim(SourceTypeInfo.description)]] + std::optional sourceType; + + // [[codegen::verbatim(SourceNodeNameInfo.description)]] + std::optional sourceNodeName; + + // [[codegen::verbatim(DestinationTypeInfo.description)]] + std::optional destinationType; + + // [[codegen::verbatim(DestinationNodeNameInfo.description)]] + std::optional destinationNodeName; + + // [[codegen::verbatim(SimplificationInfo.description)]] + std::optional simplification; + + // [[codegen::verbatim(RequestedUnitInfo.description)]] + std::optional requestedUnit [[codegen::inlist(unitList())]]; + + // [[codegen::verbatim(FormatStringInfo.description)]] + std::optional formatString; + }; +#include "dashboarditemdistance_codegen.cpp" } // namespace namespace openspace { documentation::Documentation DashboardItemDistance::Documentation() { - using namespace documentation; - return { - "DashboardItem Distance", - "base_dashboarditem_distance", - { - { - "Type", - new StringEqualVerifier("DashboardItemDistance"), - Optional::No - }, - { - SourceTypeInfo.identifier, - new StringInListVerifier({ - "Node", "Node Surface", "Focus", "Camera" - }), - Optional::Yes, - SourceTypeInfo.description - }, - { - SourceNodeNameInfo.identifier, - new StringVerifier, - Optional::Yes, - SourceNodeNameInfo.description - }, - { - DestinationTypeInfo.identifier, - new StringInListVerifier({ - "Node", "Node Surface", "Focus", "Camera" - }), - Optional::Yes, - DestinationTypeInfo.description - }, - { - DestinationNodeNameInfo.identifier, - new StringVerifier, - Optional::Yes, - DestinationNodeNameInfo.description - }, - { - SimplificationInfo.identifier, - new BoolVerifier, - Optional::Yes, - SimplificationInfo.description - }, - { - RequestedUnitInfo.identifier, - new StringInListVerifier(unitList()), - Optional::Yes, - RequestedUnitInfo.description - }, - { - FormatStringInfo.identifier, - new StringVerifier, - Optional::Yes, - FormatStringInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_distance"; + return doc; } DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary) @@ -191,11 +167,7 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary nullptr } { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemDistance" - ); + const Parameters p = codegen::bake(dictionary); _source.type.addOptions({ { Type::Node, "Node" }, @@ -210,22 +182,20 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary ) ); }); - if (dictionary.hasKey(SourceTypeInfo.identifier)) { - const std::string& value = dictionary.value( - SourceTypeInfo.identifier - ); - - if (value == "Node") { - _source.type = Type::Node; - } - else if (value == "Node Surface") { - _source.type = Type::NodeSurface; - } - else if (value == "Focus") { - _source.type = Type::Focus; - } - else { - _source.type = Type::Camera; + if (p.sourceType.has_value()) { + switch (*p.sourceType) { + case Parameters::TypeInfo::Node: + _source.type = Type::Node; + break; + case Parameters::TypeInfo::NodeSurface: + _source.type = Type::NodeSurface; + break; + case Parameters::TypeInfo::Focus: + _source.type = Type::Focus; + break; + case Parameters::TypeInfo::Camera: + _source.type = Type::Camera; + break; } } else { @@ -235,10 +205,8 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary _source.nodeName.onChange([this]() { _source.node = nullptr; }); if (_source.type == Type::Node || _source.type == Type::NodeSurface) { - if (dictionary.hasKey(SourceNodeNameInfo.identifier)) { - _source.nodeName = dictionary.value( - SourceNodeNameInfo.identifier - ); + if (p.sourceNodeName.has_value()) { + _source.nodeName = *p.sourceNodeName; } else { LERRORC( @@ -262,21 +230,20 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary ) ); }); - if (dictionary.hasKey(DestinationTypeInfo.identifier)) { - const std::string& value = dictionary.value( - DestinationTypeInfo.identifier - ); - if (value == "Node") { - _destination.type = Type::Node; - } - else if (value == "Node Surface") { - _destination.type = Type::NodeSurface; - } - else if (value == "Focus") { - _destination.type = Type::Focus; - } - else { - _destination.type = Type::Camera; + if (p.destinationType.has_value()) { + switch (*p.destinationType) { + case Parameters::TypeInfo::Node: + _destination.type = Type::Node; + break; + case Parameters::TypeInfo::NodeSurface: + _destination.type = Type::NodeSurface; + break; + case Parameters::TypeInfo::Focus: + _destination.type = Type::Focus; + break; + case Parameters::TypeInfo::Camera: + _destination.type = Type::Camera; + break; } } else { @@ -285,10 +252,8 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary addProperty(_destination.type); _destination.nodeName.onChange([this]() { _destination.node = nullptr; }); if (_destination.type == Type::Node || _destination.type == Type::NodeSurface) { - if (dictionary.hasKey(DestinationNodeNameInfo.identifier)) { - _destination.nodeName = dictionary.value( - DestinationNodeNameInfo.identifier - ); + if (p.destinationNodeName.has_value()) { + _destination.nodeName = *p.destinationNodeName; } else { LERRORC( @@ -299,9 +264,7 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary } addProperty(_destination.nodeName); - if (dictionary.hasKey(SimplificationInfo.identifier)) { - _doSimplification = dictionary.value(SimplificationInfo.identifier); - } + _doSimplification = p.simplification.value_or(_doSimplification); _doSimplification.onChange([this]() { _requestedUnit.setVisibility( _doSimplification ? @@ -315,19 +278,14 @@ DashboardItemDistance::DashboardItemDistance(const ghoul::Dictionary& dictionary _requestedUnit.addOption(static_cast(u), nameForDistanceUnit(u)); } _requestedUnit = static_cast(DistanceUnit::Meter); - if (dictionary.hasKey(RequestedUnitInfo.identifier)) { - const std::string& value = dictionary.value( - RequestedUnitInfo.identifier - ); - DistanceUnit unit = distanceUnitFromString(value.c_str()); + if (p.requestedUnit.has_value()) { + DistanceUnit unit = distanceUnitFromString(p.requestedUnit->c_str()); _requestedUnit = static_cast(unit); } _requestedUnit.setVisibility(properties::Property::Visibility::Hidden); addProperty(_requestedUnit); - if (dictionary.hasKey(FormatStringInfo.identifier)) { - _formatString = dictionary.value(FormatStringInfo.identifier); - } + _formatString = p.formatString.value_or(_formatString); addProperty(_formatString); _buffer.resize(256); diff --git a/modules/base/dashboard/dashboarditemframerate.cpp b/modules/base/dashboard/dashboarditemframerate.cpp index eab94b2e45..9405cac2c6 100644 --- a/modules/base/dashboard/dashboarditemframerate.cpp +++ b/modules/base/dashboard/dashboarditemframerate.cpp @@ -32,6 +32,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo FrametimeInfo = { @@ -47,14 +48,6 @@ namespace { "does not use any caching, this trigger does not do anything." }; - constexpr const char* ValueDtAvg = "Average Deltatime"; - constexpr const char* ValueDtExtremes = "Deltatime extremes"; - constexpr const char* ValueDtStandardDeviation = "Deltatime standard deviation"; - constexpr const char* ValueDtCov = "Deltatime coefficient of variation"; - constexpr const char* ValueFps = "Frames per second"; - constexpr const char* ValueFpsAvg = "Average frames per second"; - constexpr const char* ValueNone = "None"; - [[ nodiscard ]] char* formatDt(std::vector& buffer) { return fmt::format_to( buffer.data(), @@ -133,32 +126,30 @@ namespace { throw ghoul::MissingCaseException(); } } + + struct [[codegen::Dictionary(DashboardItemFramerate)]] Parameters { + enum class Type { + DtAvg [[codegen::key("Average Deltatime")]], + DtExtremes [[codegen::key("Deltatime extremes")]], + DtStandardDeviation [[codegen::key("Deltatime standard deviation")]], + DtCoefficientOfVariation [[codegen::key("Deltatime coefficient of variation")]], + FPS [[codegen::key("Frames per second")]], + FPSAvg [[codegen::key("Average frames per second")]] + }; + + // [[codegen::verbatim(FrametimeInfo.description)]] + std::optional frametimeType; + }; +#include "dashboarditemframerate_codegen.cpp" + } // namespace namespace openspace { documentation::Documentation DashboardItemFramerate::Documentation() { - using namespace documentation; - - return { - "DashboardItem Framerate", - "base_dashboarditem_framerate", - { - { - "Type", - new StringEqualVerifier("DashboardItemFramerate"), - Optional::No - }, - { - FrametimeInfo.identifier, - new StringInListVerifier({ ValueDtAvg, ValueDtExtremes, - ValueDtStandardDeviation, ValueDtCov, ValueFps, ValueFpsAvg, ValueNone - }), - Optional::Yes, - FrametimeInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_framerate"; + return doc; } DashboardItemFramerate::DashboardItemFramerate(const ghoul::Dictionary& dictionary) @@ -166,52 +157,44 @@ DashboardItemFramerate::DashboardItemFramerate(const ghoul::Dictionary& dictiona , _frametimeType(FrametimeInfo, properties::OptionProperty::DisplayType::Dropdown) , _clearCache(ClearCacheInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemFramerate" - ); + const Parameters p = codegen::bake(dictionary); _frametimeType.addOptions({ - { static_cast(FrametimeType::DtTimeAvg), ValueDtAvg }, - { static_cast(FrametimeType::DtTimeExtremes), ValueDtExtremes }, + { static_cast(FrametimeType::DtTimeAvg), "Average Deltatime" }, + { static_cast(FrametimeType::DtTimeExtremes), "Deltatime extremes" }, { static_cast(FrametimeType::DtStandardDeviation), - ValueDtStandardDeviation + "Deltatime standard deviation" }, { static_cast(FrametimeType::DtCoefficientOfVariation), - ValueDtCov + "Deltatime coefficient of variation" }, - { static_cast(FrametimeType::FPS), ValueFps }, - { static_cast(FrametimeType::FPSAvg), ValueFpsAvg }, - { static_cast(FrametimeType::None), ValueNone } + { static_cast(FrametimeType::FPS), "Frames per second" }, + { static_cast(FrametimeType::FPSAvg), "Average frames per second" }, + { static_cast(FrametimeType::None), "None" } }); - if (dictionary.hasKey(FrametimeInfo.identifier)) { - const std::string& v = dictionary.value(FrametimeInfo.identifier); - if (v == ValueDtAvg) { - _frametimeType = static_cast(FrametimeType::DtTimeAvg); - } - else if (v == ValueDtExtremes) { - _frametimeType = static_cast(FrametimeType::DtTimeExtremes); - } - else if (v == ValueDtStandardDeviation) { - _frametimeType = - static_cast(FrametimeType::DtStandardDeviation); - } - else if (v == ValueDtCov) { - _frametimeType = - static_cast(FrametimeType::DtCoefficientOfVariation); - } - else if (v == ValueFps) { - _frametimeType = static_cast(FrametimeType::FPS); - } - else if (v == ValueFpsAvg) { - _frametimeType = static_cast(FrametimeType::FPSAvg); - } - else { - _frametimeType = static_cast(FrametimeType::None); + if (p.frametimeType.has_value()) { + switch (*p.frametimeType) { + case Parameters::Type::DtAvg: + _frametimeType = static_cast(FrametimeType::DtTimeAvg); + break; + case Parameters::Type::DtExtremes: + _frametimeType = static_cast(FrametimeType::DtTimeExtremes); + break; + case Parameters::Type::DtStandardDeviation: + _frametimeType = static_cast(FrametimeType::DtStandardDeviation); + break; + case Parameters::Type::DtCoefficientOfVariation: + _frametimeType = static_cast(FrametimeType::DtCoefficientOfVariation); + break; + case Parameters::Type::FPS: + _frametimeType = static_cast(FrametimeType::FPS); + break; + case Parameters::Type::FPSAvg: + _frametimeType = static_cast(FrametimeType::FPSAvg); + break; } } else { diff --git a/modules/base/dashboard/dashboarditemmission.cpp b/modules/base/dashboard/dashboarditemmission.cpp index 19493f2046..97b2131d85 100644 --- a/modules/base/dashboard/dashboarditemmission.cpp +++ b/modules/base/dashboard/dashboarditemmission.cpp @@ -51,7 +51,6 @@ namespace { progress.append("|"); return progress; } - } // namespace namespace openspace { diff --git a/modules/base/dashboard/dashboarditempropertyvalue.cpp b/modules/base/dashboard/dashboarditempropertyvalue.cpp index f39bfaafbe..663ff6d68f 100644 --- a/modules/base/dashboard/dashboarditempropertyvalue.cpp +++ b/modules/base/dashboard/dashboarditempropertyvalue.cpp @@ -48,35 +48,23 @@ namespace { "the value itself will be displayed), or it must contain extact one instance of " "{}, which will be replaced with the value of the property during rendering." }; + + struct [[codegen::Dictionary(DashboardItemPropertyValue)]] Parameters { + // [[codegen::verbatim(PropertyUriInfo.description)]] + std::optional uri [[codegen::key("URI")]]; + + // [[codegen::verbatim(DisplayStringInfo.description)]] + std::optional displayString; + }; +#include "dashboarditempropertyvalue_codegen.cpp" } // namespace namespace openspace { documentation::Documentation DashboardItemPropertyValue::Documentation() { - using namespace documentation; - return { - "DashboardItem PropertyValue", - "base_dashboarditem_propertyvalue", - { - { - "Type", - new StringEqualVerifier("DashboardItemPropertyValue"), - Optional::No - }, - { - PropertyUriInfo.identifier, - new StringVerifier, - Optional::Yes, - PropertyUriInfo.description - }, - { - DisplayStringInfo.identifier, - new StringVerifier, - Optional::Yes, - DisplayStringInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_propertyvalue"; + return doc; } DashboardItemPropertyValue::DashboardItemPropertyValue( @@ -85,21 +73,13 @@ DashboardItemPropertyValue::DashboardItemPropertyValue( , _propertyUri(PropertyUriInfo) , _displayString(DisplayStringInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemPropertyValue" - ); + const Parameters p = codegen::bake(dictionary); - if (dictionary.hasKey(PropertyUriInfo.identifier)) { - _propertyUri = dictionary.value(PropertyUriInfo.identifier); - } + _propertyUri = p.uri.value_or(_propertyUri); _propertyUri.onChange([this]() { _propertyIsDirty = true; }); addProperty(_propertyUri); - if (dictionary.hasKey(DisplayStringInfo.identifier)) { - _displayString = dictionary.value(DisplayStringInfo.identifier); - } + _displayString = p.displayString.value_or(_displayString); addProperty(_displayString); } diff --git a/modules/base/dashboard/dashboarditemsimulationincrement.cpp b/modules/base/dashboard/dashboarditemsimulationincrement.cpp index 8df0a80ac8..6648503c41 100644 --- a/modules/base/dashboard/dashboarditemsimulationincrement.cpp +++ b/modules/base/dashboard/dashboarditemsimulationincrement.cpp @@ -81,47 +81,29 @@ namespace { ); return res; } + + struct [[codegen::Dictionary(DashboardItemSimulationIncrement)]] Parameters { + // [[codegen::verbatim(SimplificationInfo.description)]] + std::optional simplification; + + // [[codegen::verbatim(RequestedUnitInfo.description)]] + std::optional requestedUnit [[codegen::inlist(unitList())]]; + + // [[codegen::verbatim(TransitionFormatInfo.description)]] + std::optional transitionFormat; + + // [[codegen::verbatim(RegularFormatInfo.description)]] + std::optional regularFormat; + }; +#include "dashboarditemsimulationincrement_codegen.cpp" } // namespace namespace openspace { documentation::Documentation DashboardItemSimulationIncrement::Documentation() { - using namespace documentation; - return { - "DashboardItem Simulation Increment", - "base_dashboarditem_simulationincrement", - { - { - "Type", - new StringEqualVerifier("DashboardItemSimulationIncrement"), - Optional::No - }, - { - SimplificationInfo.identifier, - new BoolVerifier, - Optional::Yes, - SimplificationInfo.description - }, - { - RequestedUnitInfo.identifier, - new StringInListVerifier(unitList()), - Optional::Yes, - RequestedUnitInfo.description - }, - { - TransitionFormatInfo.identifier, - new StringVerifier, - Optional::Yes, - TransitionFormatInfo.description - }, - { - RegularFormatInfo.identifier, - new StringVerifier, - Optional::Yes, - RegularFormatInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_simulationincrement"; + return doc; } DashboardItemSimulationIncrement::DashboardItemSimulationIncrement( @@ -135,15 +117,9 @@ DashboardItemSimulationIncrement::DashboardItemSimulationIncrement( ) , _regularFormat(RegularFormatInfo, "Simulation increment: {:.1f} {:s} / second{:s}") { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemSimulationIncrement" - ); + const Parameters p = codegen::bake(dictionary); - if (dictionary.hasKey(SimplificationInfo.identifier)) { - _doSimplification = dictionary.value(SimplificationInfo.identifier); - } + _doSimplification = p.simplification.value_or(_doSimplification); _doSimplification.onChange([this]() { _requestedUnit.setVisibility( _doSimplification ? @@ -157,24 +133,17 @@ DashboardItemSimulationIncrement::DashboardItemSimulationIncrement( _requestedUnit.addOption(static_cast(u), nameForTimeUnit(u)); } _requestedUnit = static_cast(TimeUnit::Second); - if (dictionary.hasKey(RequestedUnitInfo.identifier)) { - std::string value = dictionary.value(RequestedUnitInfo.identifier); - TimeUnit unit = timeUnitFromString(value.c_str()); + if (p.requestedUnit.has_value()) { + TimeUnit unit = timeUnitFromString(p.requestedUnit->c_str()); _requestedUnit = static_cast(unit); } _requestedUnit.setVisibility(properties::Property::Visibility::Hidden); addProperty(_requestedUnit); - if (dictionary.hasKey(TransitionFormatInfo.identifier)) { - _transitionFormat = dictionary.value( - TransitionFormatInfo.identifier - ); - } + _transitionFormat = p.transitionFormat.value_or(_transitionFormat); addProperty(_transitionFormat); - if (dictionary.hasKey(RegularFormatInfo.identifier)) { - _regularFormat = dictionary.value(RegularFormatInfo.identifier); - } + _regularFormat = p.regularFormat.value_or(_regularFormat); addProperty(_regularFormat); } diff --git a/modules/base/dashboard/dashboarditemspacing.cpp b/modules/base/dashboard/dashboarditemspacing.cpp index b1719cf894..5b615f769b 100644 --- a/modules/base/dashboard/dashboarditemspacing.cpp +++ b/modules/base/dashboard/dashboarditemspacing.cpp @@ -26,6 +26,7 @@ #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo SpacingInfo = { @@ -34,44 +35,29 @@ namespace { "This value determines the spacing (in pixels) that this item represents. The " "default value is 15." }; + + struct [[codegen::Dictionary(DashboardItemSpacing)]] Parameters { + // [[codegen::verbatim(SpacingInfo.description)]] + std::optional spacing; + }; +#include "dashboarditemspacing_codegen.cpp" } // namespace namespace openspace { documentation::Documentation DashboardItemSpacing::Documentation() { - using namespace documentation; - return { - "DashboardItem Spacing", - "base_dashboarditem_spacing", - { - { - "Type", - new StringEqualVerifier("DashboardItemSpacing"), - Optional::No - }, - { - SpacingInfo.identifier, - new DoubleVerifier, - Optional::Yes, - SpacingInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_spacing"; + return doc; } DashboardItemSpacing::DashboardItemSpacing(const ghoul::Dictionary& dictionary) : DashboardItem(dictionary) , _spacing(SpacingInfo, 15.f, 0.f, 2048.f) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemSpacing" - ); + const Parameters p = codegen::bake(dictionary); - if (dictionary.hasKey(SpacingInfo.identifier)) { - _spacing = static_cast(dictionary.value(SpacingInfo.identifier)); - } + _spacing = p.spacing.value_or(_spacing); addProperty(_spacing); } diff --git a/modules/base/dashboard/dashboarditemtext.cpp b/modules/base/dashboard/dashboarditemtext.cpp index 9a461db605..690da61c6a 100644 --- a/modules/base/dashboard/dashboarditemtext.cpp +++ b/modules/base/dashboard/dashboarditemtext.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo TextInfo = { @@ -38,44 +39,28 @@ namespace { "Text", "The text to be displayed" }; + + struct [[codegen::Dictionary(DashboardItemText)]] Parameters { + // [[codegen::verbatim(TextInfo.description)]] + std::optional text; + }; +#include "dashboarditemtext_codegen.cpp" } // namespace namespace openspace { documentation::Documentation DashboardItemText::Documentation() { - using namespace documentation; - return { - "DashboardItem Text", - "base_dashboarditem_text", - { - { - "Type", - new StringEqualVerifier("DashboardItemText"), - Optional::No - }, - { - TextInfo.identifier, - new StringVerifier, - Optional::Yes, - TextInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_text"; + return doc; } DashboardItemText::DashboardItemText(const ghoul::Dictionary& dictionary) : DashboardTextItem(dictionary) , _text(TextInfo, "") { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemText" - ); - - if (dictionary.hasKey(TextInfo.identifier)) { - _text = dictionary.value(TextInfo.identifier); - }; + const Parameters p = codegen::bake(dictionary); + _text = p.text.value_or(_text); addProperty(_text); } diff --git a/modules/base/dashboard/dashboarditemvelocity.cpp b/modules/base/dashboard/dashboarditemvelocity.cpp index fb284650ab..d71e4c585d 100644 --- a/modules/base/dashboard/dashboarditemvelocity.cpp +++ b/modules/base/dashboard/dashboarditemvelocity.cpp @@ -68,35 +68,24 @@ namespace { ); return res; } + + struct [[codegen::Dictionary(DashboardItemVelocity)]] Parameters { + // [[codegen::verbatim(SimplificationInfo.description)]] + std::optional simplification; + + // [[codegen::verbatim(RequestedUnitInfo.description)]] + std::optional requestedUnit [[codegen::inlist(unitList())]]; + }; +#include "dashboarditemvelocity_codegen.cpp" + } // namespace namespace openspace { documentation::Documentation DashboardItemVelocity::Documentation() { - using namespace documentation; - return { - "DashboardItem Velocity", - "base_dashboarditem_velocity", - { - { - "Type", - new StringEqualVerifier("DashboardItemVelocity"), - Optional::No - }, - { - SimplificationInfo.identifier, - new BoolVerifier, - Optional::Yes, - SimplificationInfo.description - }, - { - RequestedUnitInfo.identifier, - new StringInListVerifier(unitList()), - Optional::Yes, - RequestedUnitInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_dashboarditem_velocity"; + return doc; } DashboardItemVelocity::DashboardItemVelocity(const ghoul::Dictionary& dictionary) @@ -104,15 +93,8 @@ DashboardItemVelocity::DashboardItemVelocity(const ghoul::Dictionary& dictionary , _doSimplification(SimplificationInfo, true) , _requestedUnit(RequestedUnitInfo, properties::OptionProperty::DisplayType::Dropdown) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemVelocity" - ); - - if (dictionary.hasKey(SimplificationInfo.identifier)) { - _doSimplification = dictionary.value(SimplificationInfo.identifier); - } + const Parameters p = codegen::bake(dictionary); + _doSimplification = p.simplification.value_or(_doSimplification); _doSimplification.onChange([this]() { _requestedUnit.setVisibility( _doSimplification ? @@ -126,11 +108,8 @@ DashboardItemVelocity::DashboardItemVelocity(const ghoul::Dictionary& dictionary _requestedUnit.addOption(static_cast(u), nameForDistanceUnit(u)); } _requestedUnit = static_cast(DistanceUnit::Meter); - if (dictionary.hasKey(RequestedUnitInfo.identifier)) { - const std::string& value = dictionary.value( - RequestedUnitInfo.identifier - ); - DistanceUnit unit = distanceUnitFromString(value.c_str()); + if (p.requestedUnit.has_value()) { + DistanceUnit unit = distanceUnitFromString(p.requestedUnit->c_str()); _requestedUnit = static_cast(unit); } _requestedUnit.setVisibility(properties::Property::Visibility::Hidden); diff --git a/modules/base/lightsource/cameralightsource.cpp b/modules/base/lightsource/cameralightsource.cpp index 03028c9717..d878e5cf45 100644 --- a/modules/base/lightsource/cameralightsource.cpp +++ b/modules/base/lightsource/cameralightsource.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo IntensityInfo = { @@ -34,30 +35,20 @@ namespace { "Intensity", "The intensity of this light source" }; + + struct [[codegen::Dictionary(CameraLightSource)]] Parameters { + // [[codegen::verbatim(IntensityInfo.description)]] + std::optional intensity; + }; +#include "cameralightsource_codegen.cpp" } // namespace namespace openspace { documentation::Documentation CameraLightSource::Documentation() { - using namespace openspace::documentation; - return { - "Camera Light Source", - "base_camera_light_source", - { - { - "Type", - new StringEqualVerifier("CameraLightSource"), - Optional::No, - "The type of this light source" - }, - { - IntensityInfo.identifier, - new DoubleVerifier, - Optional::Yes, - IntensityInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_camera_light_source"; + return doc; } CameraLightSource::CameraLightSource() @@ -70,18 +61,9 @@ CameraLightSource::CameraLightSource(const ghoul::Dictionary& dictionary) : LightSource(dictionary) , _intensity(IntensityInfo, 1.f, 0.f, 1.f) { + const Parameters p = codegen::bake(dictionary); + _intensity = p.intensity.value_or(_intensity); addProperty(_intensity); - - documentation::testSpecificationAndThrow(Documentation(), - dictionary, - "CameraLightSource"); - - - if (dictionary.hasValue(IntensityInfo.identifier)) { - _intensity = static_cast( - dictionary.value(IntensityInfo.identifier) - ); - } } float CameraLightSource::intensity() const { diff --git a/modules/base/lightsource/scenegraphlightsource.cpp b/modules/base/lightsource/scenegraphlightsource.cpp index 7b8a2742a6..671f7efd75 100644 --- a/modules/base/lightsource/scenegraphlightsource.cpp +++ b/modules/base/lightsource/scenegraphlightsource.cpp @@ -31,6 +31,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo IntensityInfo = { @@ -44,36 +45,23 @@ namespace { "Node", "The identifier of the scene graph node to follow" }; + + struct [[codegen::Dictionary(SceneGraphLightSource)]] Parameters { + // [[codegen::verbatim(IntensityInfo.description)]] + std::optional intensity; + + // [[codegen::verbatim(NodeInfo.description)]] + std::string node; + }; +#include "scenegraphlightsource_codegen.cpp" } // namespace namespace openspace { documentation::Documentation SceneGraphLightSource::Documentation() { - using namespace openspace::documentation; - return { - "Scene Graph Light Source", - "base_scene_graph_light_source", - { - { - "Type", - new StringEqualVerifier("SceneGraphLightSource"), - Optional::No, - "The type of this light source" - }, - { - IntensityInfo.identifier, - new DoubleVerifier, - Optional::Yes, - IntensityInfo.description - }, - { - NodeInfo.identifier, - new StringVerifier, - Optional::No, - NodeInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_scene_graph_light_source"; + return doc; } SceneGraphLightSource::SceneGraphLightSource() @@ -89,30 +77,17 @@ SceneGraphLightSource::SceneGraphLightSource(const ghoul::Dictionary& dictionary , _intensity(IntensityInfo, 1.f, 0.f, 1.f) , _sceneGraphNodeReference(NodeInfo, "") { + const Parameters p = codegen::bake(dictionary); + + _intensity = p.intensity.value_or(_intensity); addProperty(_intensity); - addProperty(_sceneGraphNodeReference); - - documentation::testSpecificationAndThrow(Documentation(), - dictionary, - "SceneGraphLightSource"); - - - if (dictionary.hasValue(IntensityInfo.identifier)) { - _intensity = static_cast( - dictionary.value(IntensityInfo.identifier) - ); - } - - if (dictionary.hasValue(NodeInfo.identifier)) { - _sceneGraphNodeReference = - dictionary.value(NodeInfo.identifier); - } + _sceneGraphNodeReference = p.node; _sceneGraphNodeReference.onChange([this]() { _sceneGraphNode = global::renderEngine->scene()->sceneGraphNode(_sceneGraphNodeReference); }); - + addProperty(_sceneGraphNodeReference); } bool SceneGraphLightSource::initialize() { diff --git a/modules/base/rendering/grids/renderableboxgrid.cpp b/modules/base/rendering/grids/renderableboxgrid.cpp index a9d5c855c4..518f87b248 100644 --- a/modules/base/rendering/grids/renderableboxgrid.cpp +++ b/modules/base/rendering/grids/renderableboxgrid.cpp @@ -55,36 +55,26 @@ namespace { "Grid Size", "This value species the size of each dimensions of the box" }; + + struct [[codegen::Dictionary(RenderableBoxGrid)]] Parameters { + // [[codegen::verbatim(ColorInfo.description)]] + std::optional color; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(SizeInfo.description)]] + std::optional size; + }; +#include "renderableboxgrid_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableBoxGrid::Documentation() { - using namespace documentation; - return { - "RenderableBoxGrid", - "base_renderable_boxgrid", - { - { - ColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - ColorInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - }, - { - SizeInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - SizeInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_boxgrid"; + return doc; } RenderableBoxGrid::RenderableBoxGrid(const ghoul::Dictionary& dictionary) @@ -93,31 +83,19 @@ RenderableBoxGrid::RenderableBoxGrid(const ghoul::Dictionary& dictionary) , _lineWidth(LineWidthInfo, 0.5f, 0.f, 20.f) , _size(SizeInfo, glm::vec3(1.f), glm::vec3(1.f), glm::vec3(100.f)) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableBoxGrid" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - if (dictionary.hasKey(ColorInfo.identifier)) { - _color = dictionary.value(ColorInfo.identifier); - } + _color = p.color.value_or(_color); _color.setViewOption(properties::Property::ViewOptions::Color); addProperty(_color); - if (dictionary.hasKey(LineWidthInfo.identifier)) { - _lineWidth = static_cast( - dictionary.value(LineWidthInfo.identifier) - ); - } + _lineWidth = p.lineWidth.value_or(_lineWidth); addProperty(_lineWidth); - if (dictionary.hasKey(SizeInfo.identifier)) { - _size = dictionary.value(SizeInfo.identifier); - } + _size = p.size.value_or(_size); _size.onChange([&]() { _gridIsDirty = true; }); addProperty(_size); } diff --git a/modules/base/rendering/grids/renderablegrid.cpp b/modules/base/rendering/grids/renderablegrid.cpp index 9f8a8114db..861b54598b 100644 --- a/modules/base/rendering/grids/renderablegrid.cpp +++ b/modules/base/rendering/grids/renderablegrid.cpp @@ -62,43 +62,29 @@ namespace { "Grid Size", "This value species the size of each dimensions of the grid" }; + + struct [[codegen::Dictionary(RenderableGrid)]] Parameters { + // [[codegen::verbatim(ColorInfo.description)]] + std::optional color; + + // [[codegen::verbatim(SegmentsInfo.description)]] + std::optional segments; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(SizeInfo.description)]] + std::optional size; + }; +#include "renderablegrid_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableGrid::Documentation() { - using namespace documentation; - return { - "RenderableGrid", - "base_renderable_grid", - { - { - ColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - ColorInfo.description - }, - { - SegmentsInfo.identifier, - // @TODO (emmbr 2020-07-07): should be Int, but specification test fails.. - new DoubleVector2Verifier, - Optional::Yes, - SegmentsInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - }, - { - SizeInfo.identifier, - new DoubleVector2Verifier, - Optional::Yes, - SizeInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_grid"; + return doc; } RenderableGrid::RenderableGrid(const ghoul::Dictionary& dictionary) @@ -108,39 +94,23 @@ RenderableGrid::RenderableGrid(const ghoul::Dictionary& dictionary) , _lineWidth(LineWidthInfo, 0.5f, 0.f, 20.f) , _size(SizeInfo, glm::vec2(1e20f), glm::vec2(1.f), glm::vec2(1e35f)) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableGrid" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - if (dictionary.hasKey(ColorInfo.identifier)) { - _color = dictionary.value(ColorInfo.identifier); - } + _color = p.color.value_or(_color); _color.setViewOption(properties::Property::ViewOptions::Color); addProperty(_color); - if (dictionary.hasKey(SegmentsInfo.identifier)) { - _segments = static_cast( - dictionary.value(SegmentsInfo.identifier) - ); - } + _segments = p.segments.value_or(_segments); _segments.onChange([&]() { _gridIsDirty = true; }); addProperty(_segments); - if (dictionary.hasKey(LineWidthInfo.identifier)) { - _lineWidth = static_cast( - dictionary.value(LineWidthInfo.identifier) - ); - } + _lineWidth = p.lineWidth.value_or(_lineWidth); addProperty(_lineWidth); - if (dictionary.hasKey(SizeInfo.identifier)) { - _size = dictionary.value(SizeInfo.identifier); - } + _size = p.size.value_or(_size); _size.onChange([&]() { _gridIsDirty = true; }); addProperty(_size); } diff --git a/modules/base/rendering/grids/renderablegrid.h b/modules/base/rendering/grids/renderablegrid.h index 6c6dbade4c..c630265517 100644 --- a/modules/base/rendering/grids/renderablegrid.h +++ b/modules/base/rendering/grids/renderablegrid.h @@ -28,8 +28,8 @@ #include #include +#include #include -#include #include #include #include @@ -61,7 +61,9 @@ protected: ghoul::opengl::ProgramObject* _gridProgram = nullptr; properties::Vec3Property _color; - properties::UVec2Property _segments; + // @TODO (abock, 2021-01-28) This was a UVec2Property before, but it wasn't supported + // be the codegen. As soon as it does, this should be changed back + properties::IVec2Property _segments; properties::FloatProperty _lineWidth; properties::Vec2Property _size; diff --git a/modules/base/rendering/grids/renderableradialgrid.cpp b/modules/base/rendering/grids/renderableradialgrid.cpp index 979622e8a2..1c90c090a1 100644 --- a/modules/base/rendering/grids/renderableradialgrid.cpp +++ b/modules/base/rendering/grids/renderableradialgrid.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace { constexpr const char* ProgramName = "GridProgram"; @@ -76,54 +77,35 @@ namespace { "The inner radius of the circular grid, that is the radius of the inmost ring. " "Must be smaller than the outer radius." }; + + struct [[codegen::Dictionary(RenderableRadialGrid)]] Parameters { + // [[codegen::verbatim(ColorInfo.description)]] + std::optional color; + + // [[codegen::verbatim(GridSegmentsInfo.description)]] + std::optional gridSegments; + + // [[codegen::verbatim(CircleSegmentsInfo.description)]] + std::optional circleSegments; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(OuterRadiusInfo.description)]] + std::optional outerRadius; + + // [[codegen::verbatim(InnerRadiusInfo.description)]] + std::optional innerRadius; + }; +#include "renderableradialgrid_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableRadialGrid::Documentation() { - using namespace documentation; - return { - "RenderableRadialGrid", - "base_renderable_radialgrid", - { - { - ColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - ColorInfo.description - }, - { - GridSegmentsInfo.identifier, - new DoubleVector2Verifier, - Optional::Yes, - GridSegmentsInfo.description - }, - { - CircleSegmentsInfo.identifier, - new IntVerifier, - Optional::Yes, - CircleSegmentsInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - }, - { - OuterRadiusInfo.identifier, - new DoubleVerifier, - Optional::Yes, - OuterRadiusInfo.description - }, - { - InnerRadiusInfo.identifier, - new DoubleVerifier, - Optional::Yes, - InnerRadiusInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_radialgrid"; + return doc; } RenderableRadialGrid::RenderableRadialGrid(const ghoul::Dictionary& dictionary) @@ -135,34 +117,20 @@ RenderableRadialGrid::RenderableRadialGrid(const ghoul::Dictionary& dictionary) , _maxRadius(OuterRadiusInfo, 1.f, 0.f, 20.f) , _minRadius(InnerRadiusInfo, 0.f, 0.f, 20.f) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableRadialGrid" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - if (dictionary.hasKey(ColorInfo.identifier)) { - _color = dictionary.value(ColorInfo.identifier); - } + _color = p.color.value_or(_color); _color.setViewOption(properties::Property::ViewOptions::Color); addProperty(_color); - if (dictionary.hasKey(GridSegmentsInfo.identifier)) { - _gridSegments = static_cast( - dictionary.value(GridSegmentsInfo.identifier) - ); - } + _gridSegments = p.gridSegments.value_or(_gridSegments); _gridSegments.onChange([&]() { _gridIsDirty = true; }); addProperty(_gridSegments); - if (dictionary.hasKey(CircleSegmentsInfo.identifier)) { - _circleSegments = static_cast( - dictionary.value(CircleSegmentsInfo.identifier) - ); - } + _circleSegments = p.circleSegments.value_or(_circleSegments); _circleSegments.onChange([&]() { if (_circleSegments.value() % 2 == 1) { _circleSegments = _circleSegments - 1; @@ -171,24 +139,11 @@ RenderableRadialGrid::RenderableRadialGrid(const ghoul::Dictionary& dictionary) }); addProperty(_circleSegments); - if (dictionary.hasKey(LineWidthInfo.identifier)) { - _lineWidth = static_cast( - dictionary.value(LineWidthInfo.identifier) - ); - } + _lineWidth = p.lineWidth.value_or(_lineWidth); addProperty(_lineWidth); - if (dictionary.hasKey(OuterRadiusInfo.identifier)) { - _maxRadius = static_cast( - dictionary.value(OuterRadiusInfo.identifier) - ); - } - - if (dictionary.hasKey(InnerRadiusInfo.identifier)) { - _minRadius = static_cast( - dictionary.value(InnerRadiusInfo.identifier) - ); - } + _minRadius = p.innerRadius.value_or(_minRadius); + _maxRadius = p.outerRadius.value_or(_maxRadius); _maxRadius.setMinValue(_minRadius); _minRadius.setMaxValue(_maxRadius); diff --git a/modules/base/rendering/grids/renderablesphericalgrid.cpp b/modules/base/rendering/grids/renderablesphericalgrid.cpp index da56a19f17..1580276c27 100644 --- a/modules/base/rendering/grids/renderablesphericalgrid.cpp +++ b/modules/base/rendering/grids/renderablesphericalgrid.cpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace { constexpr const char* ProgramName = "GridProgram"; @@ -55,36 +56,26 @@ namespace { "Line Width", "This value specifies the line width of the spherical grid." }; + + struct [[codegen::Dictionary(RenderableSphericalGrid)]] Parameters { + // [[codegen::verbatim(ColorInfo.description)]] + std::optional color; + + // [[codegen::verbatim(SegmentsInfo.description)]] + std::optional segments; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + }; +#include "renderablesphericalgrid_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableSphericalGrid::Documentation() { - using namespace documentation; - return { - "RenderableSphericalGrid", - "base_renderable_sphericalgrid", - { - { - ColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - ColorInfo.description - }, - { - SegmentsInfo.identifier, - new IntVerifier, - Optional::Yes, - SegmentsInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_sphericalgrid"; + return doc; } RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictionary) @@ -94,24 +85,16 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio , _segments(SegmentsInfo, 36, 4, 200) , _lineWidth(LineWidthInfo, 0.5f, 0.f, 20.f) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableSphericalGrid" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - if (dictionary.hasKey(ColorInfo.identifier)) { - _color = dictionary.value(ColorInfo.identifier); - } + _color = p.color.value_or(_color); _color.setViewOption(properties::Property::ViewOptions::Color); addProperty(_color); - if (dictionary.hasKey(SegmentsInfo.identifier)) { - _segments = static_cast(dictionary.value(SegmentsInfo.identifier)); - } + _segments = p.segments.value_or(_segments); _segments.onChange([&]() { if (_segments.value() % 2 == 1) { _segments = _segments - 1; @@ -120,11 +103,7 @@ RenderableSphericalGrid::RenderableSphericalGrid(const ghoul::Dictionary& dictio }); addProperty(_segments); - if (dictionary.hasKey(LineWidthInfo.identifier)) { - _lineWidth = static_cast( - dictionary.value(LineWidthInfo.identifier) - ); - } + _lineWidth = p.lineWidth.value_or(_lineWidth); addProperty(_lineWidth); } diff --git a/modules/base/rendering/renderablecartesianaxes.cpp b/modules/base/rendering/renderablecartesianaxes.cpp index 1e2e2d208a..67b4f00783 100644 --- a/modules/base/rendering/renderablecartesianaxes.cpp +++ b/modules/base/rendering/renderablecartesianaxes.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace { constexpr const char* ProgramName = "CartesianAxesProgram"; @@ -56,39 +57,29 @@ namespace { "Z Color", "This value determines the color of the z axis." }; + + struct [[codegen::Dictionary(RenderableCartesianAxes)]] Parameters { + // [[codegen::verbatim(XColorInfo.description)]] + std::optional xColor; + + // [[codegen::verbatim(YColorInfo.description)]] + std::optional yColor; + + // [[codegen::verbatim(ZColorInfo.description)]] + std::optional zColor; + + }; +#include "renderablecartesianaxes_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableCartesianAxes::Documentation() { - using namespace documentation; - return { - "CartesianAxesProgram", - "base_renderable_cartesianaxes", - { - { - XColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - XColorInfo.description - }, - { - YColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - YColorInfo.description - }, - { - ZColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - ZColorInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_cartesianaxes"; + return doc; } - RenderableCartesianAxes::RenderableCartesianAxes(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _program(nullptr) @@ -111,27 +102,16 @@ RenderableCartesianAxes::RenderableCartesianAxes(const ghoul::Dictionary& dictio glm::vec3(1.f) ) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableCartesianAxes" - ); - - if (dictionary.hasKey(XColorInfo.identifier)) { - _xColor = dictionary.value(XColorInfo.identifier); - } + const Parameters p = codegen::bake(dictionary); + _xColor = p.xColor.value_or(_xColor); _xColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_xColor); - if (dictionary.hasKey(XColorInfo.identifier)) { - _yColor = dictionary.value(YColorInfo.identifier); - } + _yColor = p.yColor.value_or(_yColor); _yColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_yColor); - if (dictionary.hasKey(ZColorInfo.identifier)) { - _zColor = dictionary.value(ZColorInfo.identifier); - } + _zColor = p.zColor.value_or(_zColor); _zColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_zColor); } diff --git a/modules/base/rendering/renderablelabels.cpp b/modules/base/rendering/renderablelabels.cpp index 85f686dc93..d5a240cc74 100644 --- a/modules/base/rendering/renderablelabels.cpp +++ b/modules/base/rendering/renderablelabels.cpp @@ -46,10 +46,9 @@ #include #include #include +#include namespace { - constexpr const char* _loggerCat = "base::RenderableLabels"; - constexpr const char* MeterUnit = "m"; constexpr const char* KilometerUnit = "Km"; constexpr const char* MegameterUnit = "Mm"; @@ -176,122 +175,91 @@ namespace { "Fade-In/-Out ending speed.", "Fade-In/-Out ending speed." }; + + struct [[codegen::Dictionary(RenderableLabels)]] Parameters { + enum class BlendMode { + Normal, + Additive + }; + + // [[codegen::verbatim(BlendModeInfo.description)]] + std::optional blendMode; + + enum class Orientation { + ViewDirection [[codegen::key("Camera View Direction")]], + PositionNormal [[codegen::key("Camera Position Normal")]] + }; + + // [[codegen::verbatim(LabelOrientationOptionInfo.description)]] + std::optional labelOrientationOption; + + // [[codegen::verbatim(LabelColorInfo.description)]] + std::optional labelColor; + + // [[codegen::verbatim(LabelTextInfo.description)]] + std::optional labelText; + + // [[codegen::verbatim(FontSizeInfo.description)]] + std::optional fontSize; + + // [[codegen::verbatim(LabelSizeInfo.description)]] + std::optional labelSize; + + // [[codegen::verbatim(LabelMinSizeInfo.description)]] + std::optional labelMinSize; + + // [[codegen::verbatim(LabelMaxSizeInfo.description)]] + std::optional labelMaxSize; + + // [[codegen::verbatim(EnableFadingEffectInfo.description)]] + std::optional enableFading; + + // [[codegen::verbatim(PixelSizeControlInfo.description)]] + std::optional enablePixelControl; + + // [[codegen::verbatim(TransformationMatrixInfo.description)]] + std::optional transformationMatrix; + + enum class Unit { + Meter [[codegen::key("m")]], + Kilometer [[codegen::key("Km")]], + Megameter [[codegen::key("Mm")]], + Gigameter [[codegen::key("Gm")]], + Terameter [[codegen::key("Tm")]], + Petameter [[codegen::key("Pm")]], + AstronomicalUnit [[codegen::key("au")]], + Parsec [[codegen::key("pc")]], + KiloParsec [[codegen::key("Kpc")]], + MegaParsec [[codgen::key("Mpc")]], + GigaParsec [[codegen::key("Gpc")]], + GigaLightyear [[codegen::key("Gly")]] + }; + + // [[codegen::verbatim(FadeStartUnitOptionInfo.description)]] + std::optional fadeStartUnit; + + // [[codegen::verbatim(FadeEndUnitOptionInfo.description)]] + std::optional fadeEndUnit; + + // [[codegen::verbatim(FadeStartDistInfo.description)]] + std::optional fadeStartDistance; + + // [[codegen::verbatim(FadeEndDistInfo.description)]] + std::optional fadeEndDistance; + + // [[codegen::verbatim(FadeStartSpeedInfo.description)]] + std::optional fadeStartSpeed; + + // [[codegen::verbatim(FadeEndSpeedInfo.description)]] + std::optional fadeEndSpeed; + }; +#include "renderablelabels_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableLabels::Documentation() { - using namespace documentation; - return { - "Renderable Labels", - "base_renderable_labels", - { - { - BlendModeInfo.identifier, - new StringInListVerifier({ "Normal", "Additive" }), - Optional::Yes, - BlendModeInfo.description, // + " The default value is 'Normal'.", - }, - { - LabelOrientationOptionInfo.identifier, - new StringInListVerifier( - { "Camera View Direction", "Camera Position Normal" } - ), - Optional::Yes, - LabelOrientationOptionInfo.description, - }, - { - LabelColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - LabelColorInfo.description, - }, - { - LabelTextInfo.identifier, - new StringVerifier, - Optional::Yes, - LabelTextInfo.description - }, - { - FontSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - FontSizeInfo.description - }, - { - LabelSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LabelSizeInfo.description - }, - { - LabelMinSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LabelMinSizeInfo.description - }, - { - LabelMaxSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LabelMaxSizeInfo.description - }, - { - EnableFadingEffectInfo.identifier, - new BoolVerifier, - Optional::Yes, - EnableFadingEffectInfo.description - }, - { - PixelSizeControlInfo.identifier, - new BoolVerifier, - Optional::Yes, - PixelSizeControlInfo.description - }, - { - FadeStartUnitOptionInfo.identifier, - new StringInListVerifier( - { "m", "Km", "Mm", "Gm", "au", "Tm", "Pm", "pc", "Kpc", "Mpc", - "Gpc", "Gly"} - ), - Optional::Yes, - FadeStartUnitOptionInfo.description, - }, - { - FadeEndUnitOptionInfo.identifier, - new StringInListVerifier( - {"m", "Km", "Mm", "Gm", "au", "Tm", "Pm", "pc", "Kpc", "Mpc", - "Gpc", "Gly"} - ), - Optional::Yes, - FadeEndUnitOptionInfo.description, - }, - { - FadeStartDistInfo.identifier, - new DoubleVerifier, - Optional::Yes, - FadeStartDistInfo.description - }, - { - FadeEndDistInfo.identifier, - new DoubleVerifier, - Optional::Yes, - FadeEndDistInfo.description - }, - { - FadeStartSpeedInfo.identifier, - new DoubleVerifier, - Optional::Yes, - FadeStartSpeedInfo.description - }, - { - FadeEndSpeedInfo.identifier, - new DoubleVerifier, - Optional::Yes, - FadeEndSpeedInfo.description - }, - } - }; + return codegen::doc(); } RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) @@ -327,11 +295,7 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) properties::OptionProperty::DisplayType::Dropdown ) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableLabels" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); @@ -353,13 +317,14 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) } }); - if (dictionary.hasKey(BlendModeInfo.identifier)) { - const std::string v = dictionary.value(BlendModeInfo.identifier); - if (v == "Normal") { - _blendMode = BlendModeNormal; - } - else if (v == "Additive") { - _blendMode = BlendModeAdditive; + if (p.blendMode.has_value()) { + switch (*p.blendMode) { + case Parameters::BlendMode::Normal: + _blendMode = BlendModeNormal; + break; + case Parameters::BlendMode::Additive: + _blendMode = BlendModeAdditive; + break; } } @@ -369,35 +334,26 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) _labelOrientationOption.addOption(NormalDirection, "Camera Position Normal"); _labelOrientationOption = NormalDirection; - if (dictionary.hasValue(LabelOrientationOptionInfo.identifier)) { - const std::string o = dictionary.value( - LabelOrientationOptionInfo.identifier - ); - - if (o == "Camera View Direction") { - _labelOrientationOption = ViewDirection; - } - else if (o == "Camera Position Normal") { - _labelOrientationOption = NormalDirection; + if (p.labelOrientationOption.has_value()) { + switch (*p.labelOrientationOption) { + case Parameters::Orientation::ViewDirection: + _labelOrientationOption = ViewDirection; + break; + case Parameters::Orientation::PositionNormal: + _labelOrientationOption = NormalDirection; + break; } } - - if (dictionary.hasKey(LabelTextInfo.identifier)) { - _labelText = dictionary.value(LabelTextInfo.identifier); - } - addProperty(_labelText); - addProperty(_labelOrientationOption); + _labelText = p.labelText.value_or(_labelText); + addProperty(_labelText); + + _labelColor = p.labelColor.value_or(_labelColor); _labelColor.setViewOption(properties::Property::ViewOptions::Color); - if (dictionary.hasKey(LabelColorInfo.identifier)) { - _labelColor = dictionary.value(LabelColorInfo.identifier); - } addProperty(_labelColor); - if (dictionary.hasKey(FontSizeInfo.identifier)) { - _fontSize = static_cast(dictionary.value(FontSizeInfo.identifier)); - } + _fontSize = p.fontSize.value_or(_fontSize); _fontSize.onChange([&]() { _font = global::fontManager->font( "Mono", @@ -408,49 +364,28 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) }); addProperty(_fontSize); - if (dictionary.hasKey(LabelSizeInfo.identifier)) { - _labelSize = static_cast( - dictionary.value(LabelSizeInfo.identifier) - ); - } + _labelSize = p.labelSize.value_or(_labelSize); addProperty(_labelSize); - if (dictionary.hasKey(LabelMinSizeInfo.identifier)) { - _labelMinSize = static_cast( - dictionary.value(LabelMinSizeInfo.identifier) - ); - } + _labelMinSize = p.labelMinSize.value_or(_labelMinSize); addProperty(_labelMinSize); - if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) { - _labelMaxSize = static_cast( - dictionary.value(LabelMaxSizeInfo.identifier) - ); - } + _labelMaxSize = p.labelMaxSize.value_or(_labelMaxSize); addProperty(_labelMaxSize); - if (dictionary.hasKey(TransformationMatrixInfo.identifier)) { - _transformationMatrix = dictionary.value( - TransformationMatrixInfo.identifier - ); - } + _transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix); - if (dictionary.hasKey(PixelSizeControlInfo.identifier)) { - _pixelSizeControl = dictionary.value(PixelSizeControlInfo.identifier); + _pixelSizeControl = p.enablePixelControl.value_or(_pixelSizeControl); + if (_pixelSizeControl) { + // @TODO (abock, 2021-01-28) I don't know why we only add the property if the + // pixel control is enabled, but I think this is an error addProperty(_pixelSizeControl); } - if (dictionary.hasKey(EnableFadingEffectInfo.identifier)) { - _enableFadingEffect = dictionary.value(EnableFadingEffectInfo.identifier); - } + _enableFadingEffect = p.enableFading.value_or(_enableFadingEffect); addProperty(_enableFadingEffect); - if (dictionary.hasKey(FadeStartDistInfo.identifier)) { - _fadeStartDistance = static_cast( - dictionary.value(FadeStartDistInfo.identifier) - ); - } - + _fadeStartDistance = p.fadeStartDistance.value_or(_fadeStartDistance); addProperty(_fadeStartDistance); _fadeStartUnitOption.addOption(Meter, MeterUnit); @@ -466,72 +401,56 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) _fadeStartUnitOption.addOption(Gigaparsec, GigaparsecUnit); _fadeStartUnitOption.addOption(GigalightYears, GigalightyearUnit); - _fadeStartUnitOption = AU; - if (dictionary.hasKey(FadeStartUnitOptionInfo.identifier)) { - std::string unit = dictionary.value( - FadeStartUnitOptionInfo.identifier - ); - if (unit == MeterUnit) { - _fadeStartUnitOption = Meter; - } - else if (unit == KilometerUnit) { - _fadeStartUnitOption = Kilometer; - } - else if (unit == MegameterUnit) { - _fadeStartUnitOption = Megameter; - } - else if (unit == GigameterUnit) { - _fadeStartUnitOption = Gigameter; - } - else if (unit == AstronomicalUnit) { - _fadeStartUnitOption = AU; - } - else if (unit == TerameterUnit) { - _fadeStartUnitOption = Terameter; - } - else if (unit == PetameterUnit) { - _fadeStartUnitOption = Petameter; - } - else if (unit == ParsecUnit) { - _fadeStartUnitOption = Parsec; - } - else if (unit == KiloparsecUnit) { - _fadeStartUnitOption = Kiloparsec; - } - else if (unit == MegaparsecUnit) { - _fadeStartUnitOption = Megaparsec; - } - else if (unit == GigaparsecUnit) { - _fadeStartUnitOption = Gigaparsec; - } - else if (unit == GigalightyearUnit) { - _fadeStartUnitOption = GigalightYears; - } - else { - LWARNING( - "No unit given for RenderableLabels. Using kilometer as units." - ); - _fadeStartUnitOption = Kilometer; + if (p.fadeStartUnit.has_value()) { + switch (*p.fadeStartUnit) { + case Parameters::Unit::Meter: + _fadeStartUnitOption = Meter; + break; + case Parameters::Unit::Kilometer: + _fadeStartUnitOption = Kilometer; + break; + case Parameters::Unit::Megameter: + _fadeStartUnitOption = Megameter; + break; + case Parameters::Unit::Gigameter: + _fadeStartUnitOption = Gigameter; + break; + case Parameters::Unit::Terameter: + _fadeStartUnitOption = Terameter; + break; + case Parameters::Unit::Petameter: + _fadeStartUnitOption = Petameter; + break; + case Parameters::Unit::AstronomicalUnit: + _fadeStartUnitOption = AU; + break; + case Parameters::Unit::Parsec: + _fadeStartUnitOption = Parsec; + break; + case Parameters::Unit::KiloParsec: + _fadeStartUnitOption = Kiloparsec; + break; + case Parameters::Unit::MegaParsec: + _fadeStartUnitOption = Megaparsec; + break; + case Parameters::Unit::GigaParsec: + _fadeStartUnitOption = Gigaparsec; + break; + case Parameters::Unit::GigaLightyear: + _fadeStartUnitOption = GigalightYears; + break; } } - + else { + _fadeStartUnitOption = AU; + } addProperty(_fadeStartUnitOption); - if (dictionary.hasKey(FadeStartSpeedInfo.identifier)) { - _fadeStartSpeed = static_cast( - dictionary.value(FadeStartSpeedInfo.identifier) - ); - } - + _fadeStartSpeed = p.fadeStartSpeed.value_or(_fadeStartSpeed); addProperty(_fadeStartSpeed); - if (dictionary.hasKey(FadeEndDistInfo.identifier)) { - _fadeEndDistance = static_cast( - dictionary.value(FadeEndDistInfo.identifier) - ); - } - + _fadeEndDistance = p.fadeEndDistance.value_or(_fadeEndDistance); addProperty(_fadeEndDistance); _fadeEndUnitOption.addOption(Meter, MeterUnit); @@ -547,64 +466,53 @@ RenderableLabels::RenderableLabels(const ghoul::Dictionary& dictionary) _fadeEndUnitOption.addOption(Gigaparsec, GigaparsecUnit); _fadeEndUnitOption.addOption(GigalightYears, GigalightyearUnit); - _fadeEndUnitOption = AU; - if (dictionary.hasKey(FadeEndUnitOptionInfo.identifier)) { - std::string unit = dictionary.value( - FadeEndUnitOptionInfo.identifier - ); - if (unit == MeterUnit) { - _fadeEndUnitOption = Meter; - } - else if (unit == KilometerUnit) { - _fadeEndUnitOption = Kilometer; - } - else if (unit == MegameterUnit) { - _fadeEndUnitOption = Megameter; - } - else if (unit == GigameterUnit) { - _fadeEndUnitOption = Gigameter; - } - else if (unit == AstronomicalUnit) { - _fadeEndUnitOption = AU; - } - else if (unit == TerameterUnit) { - _fadeEndUnitOption = Terameter; - } - else if (unit == PetameterUnit) { - _fadeEndUnitOption = Petameter; - } - else if (unit == ParsecUnit) { - _fadeEndUnitOption = Parsec; - } - else if (unit == KiloparsecUnit) { - _fadeEndUnitOption = Kiloparsec; - } - else if (unit == MegaparsecUnit) { - _fadeEndUnitOption = Megaparsec; - } - else if (unit == GigaparsecUnit) { - _fadeEndUnitOption = Gigaparsec; - } - else if (unit == GigalightyearUnit) { - _fadeEndUnitOption = GigalightYears; - } - else { - LWARNING( - "No unit given for RenderableLabels. Using kilometer as units." - ); - _fadeEndUnitOption = Kilometer; + if (p.fadeEndUnit.has_value()) { + switch (*p.fadeEndUnit) { + case Parameters::Unit::Meter: + _fadeStartUnitOption = Meter; + break; + case Parameters::Unit::Kilometer: + _fadeStartUnitOption = Kilometer; + break; + case Parameters::Unit::Megameter: + _fadeStartUnitOption = Megameter; + break; + case Parameters::Unit::Gigameter: + _fadeStartUnitOption = Gigameter; + break; + case Parameters::Unit::Terameter: + _fadeStartUnitOption = Terameter; + break; + case Parameters::Unit::Petameter: + _fadeStartUnitOption = Petameter; + break; + case Parameters::Unit::AstronomicalUnit: + _fadeStartUnitOption = AU; + break; + case Parameters::Unit::Parsec: + _fadeStartUnitOption = Parsec; + break; + case Parameters::Unit::KiloParsec: + _fadeEndUnitOption = Kiloparsec; + break; + case Parameters::Unit::MegaParsec: + _fadeEndUnitOption = Megaparsec; + break; + case Parameters::Unit::GigaParsec: + _fadeEndUnitOption = Gigaparsec; + break; + case Parameters::Unit::GigaLightyear: + _fadeEndUnitOption = GigalightYears; + break; } } - + else { + _fadeEndUnitOption = AU; + } addProperty(_fadeEndUnitOption); - - if (dictionary.hasKey(FadeEndSpeedInfo.identifier)) { - _fadeEndSpeed = static_cast( - dictionary.value(FadeEndSpeedInfo.identifier) - ); - } - + + _fadeEndSpeed = p.fadeEndSpeed.value_or(_fadeEndSpeed); addProperty(_fadeEndSpeed); } diff --git a/modules/base/rendering/renderablenodeline.cpp b/modules/base/rendering/renderablenodeline.cpp index 21218e13f4..779c28e226 100644 --- a/modules/base/rendering/renderablenodeline.cpp +++ b/modules/base/rendering/renderablenodeline.cpp @@ -84,42 +84,29 @@ namespace { glm::dvec3 diffPos = worldPos - anchorNodePos; return diffPos; } + + struct [[codegen::Dictionary(RenderableNodeLine)]] Parameters { + // [[codegen::verbatim(StartNodeInfo.description)]] + std::optional startNode; + + // [[codegen::verbatim(EndNodeInfo.description)]] + std::optional endNode; + + // [[codegen::verbatim(LineColorInfo.description)]] + std::optional color; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + }; +#include "renderablenodeline_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableNodeLine::Documentation() { - using namespace documentation; - return { - "Renderable Node Line", - "base_renderable_renderablenodeline", - { - { - StartNodeInfo.identifier, - new StringVerifier, - Optional::Yes, - StartNodeInfo.description - }, - { - EndNodeInfo.identifier, - new StringVerifier, - Optional::Yes, - EndNodeInfo.description - }, - { - LineColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - LineColorInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_renderablenodeline"; + return doc; } RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary) @@ -129,36 +116,22 @@ RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary) , _lineColor(LineColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f)) , _lineWidth(LineWidthInfo, 2.f, 1.f, 20.f) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableNodeLine" - ); - - if (dictionary.hasKey(StartNodeInfo.identifier)) { - _start = dictionary.value(StartNodeInfo.identifier); - } - - if (dictionary.hasKey(EndNodeInfo.identifier)) { - _end = dictionary.value(EndNodeInfo.identifier); - } - - if (dictionary.hasKey(LineColorInfo.identifier)) { - _lineColor = dictionary.value(LineColorInfo.identifier); - } - if (dictionary.hasKey(LineWidthInfo.identifier)) { - _lineWidth = static_cast( - dictionary.value(LineWidthInfo.identifier) - ); - } + const Parameters p = codegen::bake(dictionary); + _start = p.startNode.value_or(_start); _start.onChange([&]() { validateNodes(); }); - _end.onChange([&]() { validateNodes(); }); - addProperty(_start); + + _end = p.endNode.value_or(_end); + _end.onChange([&]() { validateNodes(); }); addProperty(_end); + + _lineColor = p.color.value_or(_lineColor); addProperty(_lineColor); + + _lineWidth = p.lineWidth.value_or(_lineWidth); addProperty(_lineWidth); + addProperty(_opacity); } diff --git a/modules/base/rendering/renderableplane.cpp b/modules/base/rendering/renderableplane.cpp index 37277bd6d0..b718506c3e 100644 --- a/modules/base/rendering/renderableplane.cpp +++ b/modules/base/rendering/renderableplane.cpp @@ -40,6 +40,7 @@ #include #include #include +#include namespace { constexpr const char* ProgramName = "Plane"; @@ -68,36 +69,30 @@ namespace { "Blending Mode", "This determines the blending mode that is applied to this plane." }; + + struct [[codegen::Dictionary(RenderablePlane)]] Parameters { + // [[codegen::verbatim(BillboardInfo.description)]] + std::optional billboard; + + // [[codegen::verbatim(SizeInfo.description)]] + float size; + + enum class BlendMode { + Normal, + Additive + }; + // [[codegen::verbatim(BlendModeInfo.description)]] + std::optional blendMode; + }; +#include "renderableplane_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderablePlane::Documentation() { - using namespace documentation; - return { - "Renderable Plane", - "base_renderable_plane", - { - { - SizeInfo.identifier, - new DoubleVerifier, - Optional::No, - SizeInfo.description - }, - { - BillboardInfo.identifier, - new BoolVerifier, - Optional::Yes, - BillboardInfo.description - }, - { - BlendModeInfo.identifier, - new StringInListVerifier({ "Normal", "Additive" }), - Optional::Yes, - BlendModeInfo.description, // + " The default value is 'Normal'.", - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_plane"; + return doc; } RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) @@ -106,20 +101,13 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) , _billboard(BillboardInfo, false) , _size(SizeInfo, 10.f, 0.f, 1e25f) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderablePlane" - ); + Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - _size = static_cast(dictionary.value(SizeInfo.identifier)); - - if (dictionary.hasKey(BillboardInfo.identifier)) { - _billboard = dictionary.value(BillboardInfo.identifier); - } + _size = p.size; + _billboard = p.billboard.value_or(_billboard); _blendMode.addOptions({ { BlendModeNormal, "Normal" }, @@ -144,12 +132,11 @@ RenderablePlane::RenderablePlane(const ghoul::Dictionary& dictionary) } }); - if (dictionary.hasKey(BlendModeInfo.identifier)) { - const std::string v = dictionary.value(BlendModeInfo.identifier); - if (v == "Normal") { + if (p.blendMode.has_value()) { + if (*p.blendMode == Parameters::BlendMode::Normal) { _blendMode = BlendModeNormal; } - else if (v == "Additive") { + else if (*p.blendMode == Parameters::BlendMode::Additive) { _blendMode = BlendModeAdditive; } } diff --git a/modules/base/rendering/renderableplaneimagelocal.cpp b/modules/base/rendering/renderableplaneimagelocal.cpp index cd37175f72..c3a7279bde 100644 --- a/modules/base/rendering/renderableplaneimagelocal.cpp +++ b/modules/base/rendering/renderableplaneimagelocal.cpp @@ -35,10 +35,9 @@ #include #include #include +#include namespace { - constexpr const char* KeyLazyLoading = "LazyLoading"; - constexpr openspace::properties::Property::PropertyInfo TextureInfo = { "Texture", "Texture", @@ -52,54 +51,47 @@ namespace { "This value specifies if the plane should be rendered in the Background," "Opaque, Transparent, or Overlay rendering step." }; + + struct [[codegen::Dictionary(RenderablePlaneImageLocal)]] Parameters { + // [[codegen::verbatim(TextureInfo.description)]] + std::string texture; + + enum class RenderType { + Background, + Opaque, + PreDeferredTransparency, + PostDeferredTransparency, + Overlay + }; + + // [[codegen::verbatim(RenderableTypeInfo.description)]] + std::optional renderType [[codegen::key("RenderableType")]]; + + // If this value is set to 'true', the image for this plane will not be loaded at + // startup but rather when image is shown for the first time. Additionally, if the + // plane is hidden, the image will automatically be unloaded + std::optional lazyLoading; + }; +#include "renderableplaneimagelocal_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderablePlaneImageLocal::Documentation() { - using namespace documentation; - return { - "Renderable Plane Image Local", - "base_renderable_plane_image_local", - { - { - TextureInfo.identifier, - new StringVerifier, - Optional::No, - TextureInfo.description - }, - { - RenderableTypeInfo.identifier, - new StringVerifier, - Optional::Yes, - RenderableTypeInfo.description - }, - { - KeyLazyLoading, - new BoolVerifier, - Optional::Yes, - "If this value is set to 'true', the image for this plane will not be " - "loaded at startup but rather when image is shown for the first time. " - "Additionally, if the plane is hidden, the image will automatically be " - "unloaded" - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_plane_image_local"; + return doc; } RenderablePlaneImageLocal::RenderablePlaneImageLocal(const ghoul::Dictionary& dictionary) : RenderablePlane(dictionary) , _texturePath(TextureInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderablePlaneImageLocal" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_blendMode); - _texturePath = absPath(dictionary.value(TextureInfo.identifier)); + _texturePath = absPath(p.texture); _textureFile = std::make_unique(_texturePath); addProperty(_texturePath); @@ -108,44 +100,40 @@ RenderablePlaneImageLocal::RenderablePlaneImageLocal(const ghoul::Dictionary& di [this](const ghoul::filesystem::File&) { _textureIsDirty = true; } ); - if (dictionary.hasKey(RenderableTypeInfo.identifier)) { - std::string renderType = dictionary.value( - RenderableTypeInfo.identifier - ); - if (renderType == "Background") { - setRenderBin(Renderable::RenderBin::Background); - } - else if (renderType == "Opaque") { - setRenderBin(Renderable::RenderBin::Opaque); - } - else if (renderType == "PreDeferredTransparent") { - setRenderBin(Renderable::RenderBin::PreDeferredTransparent); - } - else if (renderType == "PostDeferredTransparent") { - setRenderBin(Renderable::RenderBin::PostDeferredTransparent); - } - else if (renderType == "Overlay") { - setRenderBin(Renderable::RenderBin::Overlay); + if (p.renderType.has_value()) { + switch (*p.renderType) { + case Parameters::RenderType::Background: + setRenderBin(Renderable::RenderBin::Background); + break; + case Parameters::RenderType::Opaque: + setRenderBin(Renderable::RenderBin::Opaque); + break; + case Parameters::RenderType::PreDeferredTransparency: + setRenderBin(Renderable::RenderBin::PreDeferredTransparent); + break; + case Parameters::RenderType::PostDeferredTransparency: + setRenderBin(Renderable::RenderBin::PostDeferredTransparent); + break; + case Parameters::RenderType::Overlay: + setRenderBin(Renderable::RenderBin::Overlay); + break; } } else { setRenderBin(Renderable::RenderBin::Opaque); } - if (dictionary.hasKey(KeyLazyLoading)) { - _isLoadingLazily = dictionary.value(KeyLazyLoading); - - if (_isLoadingLazily) { - _enabled.onChange([this]() { - if (!_enabled) { - BaseModule::TextureManager.release(_texture); - _texture = nullptr; - } - if (_enabled) { - _textureIsDirty = true; - } - }); - } + _isLoadingLazily = p.lazyLoading.value_or(_isLoadingLazily); + if (_isLoadingLazily) { + _enabled.onChange([this]() { + if (!_enabled) { + BaseModule::TextureManager.release(_texture); + _texture = nullptr; + } + if (_enabled) { + _textureIsDirty = true; + } + }); } } diff --git a/modules/base/rendering/renderableplaneimageonline.cpp b/modules/base/rendering/renderableplaneimageonline.cpp index 50d8d7d6ec..c99eb90755 100644 --- a/modules/base/rendering/renderableplaneimageonline.cpp +++ b/modules/base/rendering/renderableplaneimageonline.cpp @@ -41,24 +41,20 @@ namespace { "this value is changed, the image at the new path will automatically be loaded " "and displayed." }; + + struct [[codegen::Dictionary(RenderablePlaneImageOnline)]] Parameters { + // [[codegen::verbatim(TextureInfo.description)]] + std::string url [[codegen::key("URL")]]; + }; +#include "renderableplaneimageonline_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderablePlaneImageOnline::Documentation() { - using namespace documentation; - return { - "Renderable Plane Image Online", - "base_renderable_plane_image_online", - { - { - TextureInfo.identifier, - new StringVerifier, - Optional::No, - TextureInfo.description, - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_plane_image_online"; + return doc; } RenderablePlaneImageOnline::RenderablePlaneImageOnline( @@ -66,20 +62,12 @@ RenderablePlaneImageOnline::RenderablePlaneImageOnline( : RenderablePlane(dictionary) , _texturePath(TextureInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderablePlaneImageOnline" - ); + const Parameters p = codegen::bake(dictionary); _texturePath.onChange([this]() { _textureIsDirty = true; }); addProperty(_texturePath); - std::string texturePath; - if (dictionary.hasKey(TextureInfo.identifier)) { - _texturePath = dictionary.value(TextureInfo.identifier); - } - + _texturePath = p.url; addProperty(_texturePath); } diff --git a/modules/base/rendering/renderablesphere.cpp b/modules/base/rendering/renderablesphere.cpp index fdde7eeea7..4f20d37fc2 100644 --- a/modules/base/rendering/renderablesphere.cpp +++ b/modules/base/rendering/renderablesphere.cpp @@ -38,6 +38,7 @@ #include #include #include +#include namespace { constexpr const char* ProgramName = "Sphere"; @@ -117,81 +118,55 @@ namespace { "Sets the current sphere rendering as a background rendering type", "Enables/Disables background rendering." }; + + struct [[codegen::Dictionary(RenderableSphere)]] Parameters { + // [[codegen::verbatim(SizeInfo.description)]] + float size; + + // [[codegen::verbatim(SegmentsInfo.description)]] + int segments; + + // [[codegen::verbatim(TextureInfo.description)]] + std::string texture; + + enum class Orientation { + Outside, + Inside, + Both + }; + + // [[codegen::verbatim(OrientationInfo.description)]] + std::optional orientation; + + // [[codegen::verbatim(UseAdditiveBlendingInfo.description)]] + std::optional useAdditiveBlending; + + // [[codegen::verbatim(MirrorTextureInfo.description)]] + std::optional mirrorTexture; + + // [[codegen::verbatim(FadeOutThresholdInfo.description)]] + std::optional fadeOutThreshold [[codegen::inrange(0.0, 1.0)]]; + + // [[codegen::verbatim(FadeInThresholdInfo.description)]] + std::optional fadeInThreshold; + + // [[codegen::verbatim(DisableFadeInOutInfo.description)]] + std::optional disableFadeInOut; + + // [[codegen::verbatim(BackgroundInfo.description)]] + std::optional background; + }; +#include "renderablesphere_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableSphere::Documentation() { - using namespace documentation; - return { - "RenderableSphere", - "base_renderable_sphere", - { - { - SizeInfo.identifier, - new DoubleVerifier, - Optional::No, - SizeInfo.description - }, - { - SegmentsInfo.identifier, - new IntVerifier, - Optional::No, - SegmentsInfo.description - }, - { - TextureInfo.identifier, - new StringVerifier, - Optional::No, - TextureInfo.description - }, - { - OrientationInfo.identifier, - new StringInListVerifier({ "Inside", "Outside", "Both" }), - Optional::Yes, - OrientationInfo.description - }, - { - UseAdditiveBlendingInfo.identifier, - new BoolVerifier, - Optional::Yes, - UseAdditiveBlendingInfo.description - }, - { - MirrorTextureInfo.identifier, - new BoolVerifier, - Optional::Yes, - MirrorTextureInfo.description - }, - { - FadeOutThresholdInfo.identifier, - new DoubleInRangeVerifier(0.0, 1.0), - Optional::Yes, - FadeOutThresholdInfo.description - }, - { - FadeInThresholdInfo.identifier, - new DoubleVerifier, - Optional::Yes, - FadeInThresholdInfo.description - }, - { - DisableFadeInOutInfo.identifier, - new BoolVerifier, - Optional::Yes, - DisableFadeInOutInfo.description - }, - { - BackgroundInfo.identifier, - new BoolVerifier, - Optional::Yes, - BackgroundInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_renderable_sphere"; + return doc; } - RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _texturePath(TextureInfo) @@ -205,18 +180,14 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary) , _fadeInThreshold(FadeInThresholdInfo, -1.f, 0.f, 1.f) , _fadeOutThreshold(FadeOutThresholdInfo, -1.f, 0.f, 1.f) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableSphere" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - _size = static_cast(dictionary.value(SizeInfo.identifier)); - _segments = static_cast(dictionary.value(SegmentsInfo.identifier)); - _texturePath = absPath(dictionary.value(TextureInfo.identifier)); + _size = p.size; + _segments = p.segments; + _texturePath = p.texture; _orientation.addOptions({ { static_cast(Orientation::Outside), "Outside" }, @@ -224,19 +195,19 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary) { static_cast(Orientation::Both), "Both" } }); - if (dictionary.hasKey(OrientationInfo.identifier)) { - const std::string& v = dictionary.value(OrientationInfo.identifier); - if (v == "Inside") { - _orientation = static_cast(Orientation::Inside); - } - else if (v == "Outside") { - _orientation = static_cast(Orientation::Outside); - } - else if (v == "Both") { - _orientation = static_cast(Orientation::Both); - } - else { - throw ghoul::MissingCaseException(); + if (p.orientation.has_value()) { + switch (*p.orientation) { + case Parameters::Orientation::Inside: + _orientation = static_cast(Orientation::Inside); + break; + case Parameters::Orientation::Outside: + _orientation = static_cast(Orientation::Outside); + break; + case Parameters::Orientation::Both: + _orientation = static_cast(Orientation::Both); + break; + default: + throw ghoul::MissingCaseException(); } } else { @@ -256,44 +227,34 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary) addProperty(_mirrorTexture); addProperty(_useAdditiveBlending); + _mirrorTexture = p.mirrorTexture.value_or(_mirrorTexture); + _useAdditiveBlending = p.useAdditiveBlending.value_or(_useAdditiveBlending); - if (dictionary.hasKey(MirrorTextureInfo.identifier)) { - _mirrorTexture = dictionary.value(MirrorTextureInfo.identifier); - } - if (dictionary.hasKey(UseAdditiveBlendingInfo.identifier)) { - _useAdditiveBlending = dictionary.value(UseAdditiveBlendingInfo.identifier); - - if (_useAdditiveBlending) { - setRenderBin(Renderable::RenderBin::PreDeferredTransparent); - } + if (_useAdditiveBlending) { + setRenderBin(Renderable::RenderBin::PreDeferredTransparent); } - if (dictionary.hasKey(FadeOutThresholdInfo.identifier)) { - _fadeOutThreshold = static_cast( - dictionary.value(FadeOutThresholdInfo.identifier) - ); + bool hasGivenFadeOut = p.fadeOutThreshold.has_value(); + if (hasGivenFadeOut) { + _fadeOutThreshold = *p.fadeOutThreshold; addProperty(_fadeOutThreshold); } - if (dictionary.hasKey(FadeInThresholdInfo.identifier)) { - _fadeInThreshold = static_cast( - dictionary.value(FadeInThresholdInfo.identifier) - ); + bool hasGivenFadeIn = p.fadeInThreshold.has_value(); + if (hasGivenFadeIn) { + _fadeInThreshold = *p.fadeInThreshold; addProperty(_fadeInThreshold); } - if (dictionary.hasKey(FadeInThresholdInfo.identifier) || - dictionary.hasKey(FadeOutThresholdInfo.identifier)) { - _disableFadeInDistance.set(false); + if (hasGivenFadeIn || hasGivenFadeOut) { + _disableFadeInDistance = false; addProperty(_disableFadeInDistance); } - if (dictionary.hasKey(BackgroundInfo.identifier)) { - _backgroundRendering = dictionary.value(BackgroundInfo.identifier); + _backgroundRendering = p.background.value_or(_backgroundRendering); - if (_backgroundRendering) { - setRenderBin(Renderable::RenderBin::Background); - } + if (_backgroundRendering) { + setRenderBin(Renderable::RenderBin::Background); } setRenderBinFromOpacity(); diff --git a/modules/base/rendering/renderabletrail.cpp b/modules/base/rendering/renderabletrail.cpp index 0a033b2afc..12fd349498 100644 --- a/modules/base/rendering/renderabletrail.cpp +++ b/modules/base/rendering/renderabletrail.cpp @@ -34,7 +34,6 @@ #include #include #include - #include namespace { diff --git a/modules/base/rendering/screenspacedashboard.cpp b/modules/base/rendering/screenspacedashboard.cpp index 437af84538..4cb9cf591b 100644 --- a/modules/base/rendering/screenspacedashboard.cpp +++ b/modules/base/rendering/screenspacedashboard.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo UseMainInfo = { @@ -42,6 +43,15 @@ namespace { "If this value is set to 'true', this ScreenSpaceDashboard will use the " "main dashboard instead of creating an independent one." }; + + struct [[codegen::Dictionary(ScreenSpaceDashboard)]] Parameters { + // Specifies the GUI name of the ScreenSpaceDashboard + std::optional name; + + // [[codegen::verbatim(UseMainInfo.description)]] + std::optional useMainDashboard; + }; +#include "screenspacedashboard_codegen.cpp" } // namespace namespace openspace { @@ -115,42 +125,22 @@ int removeDashboardItemsFromScreenSpace(lua_State* L) { dash->dashboard().clearDashboardItems(); return 0; } - } // namespace luascriptfunctions - documentation::Documentation ScreenSpaceDashboard::Documentation() { - using namespace openspace::documentation; - return { - "ScreenSpace Dashboard", - "base_screenspace_dashboard", - { - { - KeyName, - new StringVerifier, - Optional::Yes, - "Specifies the GUI name of the ScreenSpaceDashboard" - }, - { - UseMainInfo.identifier, - new BoolVerifier, - Optional::Yes, - UseMainInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_screenspace_dashboard"; + return doc; } ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary) : ScreenSpaceFramebuffer(dictionary) , _useMainDashboard(UseMainInfo, false) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "ScreenSpaceDashboard" - ); + const Parameters p = codegen::bake(dictionary); + // @TODO (abock, 2021-01-29) Should this be the name variable? The identifier wasn't + // declared in the documentation std::string identifier; if (dictionary.hasValue(KeyIdentifier)) { identifier = dictionary.value(KeyIdentifier); @@ -161,9 +151,7 @@ ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary) identifier = makeUniqueIdentifier(identifier); setIdentifier(std::move(identifier)); - if (dictionary.hasKey(UseMainInfo.identifier)) { - _useMainDashboard = dictionary.value(UseMainInfo.identifier); - } + _useMainDashboard = p.useMainDashboard.value_or(_useMainDashboard); addProperty(_useMainDashboard); _scale = 1.f; diff --git a/modules/base/rendering/screenspaceimagelocal.cpp b/modules/base/rendering/screenspaceimagelocal.cpp index 058789cf43..3c74143c2f 100644 --- a/modules/base/rendering/screenspaceimagelocal.cpp +++ b/modules/base/rendering/screenspaceimagelocal.cpp @@ -32,6 +32,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo TexturePathInfo = { @@ -42,42 +43,33 @@ namespace { "and displayed. The size of the image will also automatically set the default " "size of this plane." }; + + struct [[codegen::Dictionary(ScreenSpaceImageLocal)]] Parameters { + // Specifies the GUI name of the ScreenspaceImage + std::optional name; + + // [[codegen::verbatim(TexturePathInfo.description)]] + std::optional texturePath; + }; +#include "screenspaceimagelocal_codegen.cpp" } // namespace namespace openspace { documentation::Documentation ScreenSpaceImageLocal::Documentation() { - using namespace openspace::documentation; - return { - "ScreenSpace Local Image", - "base_screenspace_image_local", - { - { - KeyName, - new StringVerifier, - Optional::Yes, - "Specifies the GUI name of the ScreenspaceImage" - }, - { - TexturePathInfo.identifier, - new StringVerifier, - Optional::Yes, - TexturePathInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_screenspace_image_local"; + return doc; } ScreenSpaceImageLocal::ScreenSpaceImageLocal(const ghoul::Dictionary& dictionary) : ScreenSpaceRenderable(dictionary) , _texturePath(TexturePathInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "ScreenSpaceImageLocal" - ); + const Parameters p = codegen::bake(dictionary); + // @TODO (abock, 2021-02-02) Should this be the name variable? The identifier wasn't + // declared in the documentation std::string identifier; if (dictionary.hasValue(KeyIdentifier)) { identifier = dictionary.value(KeyIdentifier); @@ -101,16 +93,15 @@ ScreenSpaceImageLocal::ScreenSpaceImageLocal(const ghoul::Dictionary& dictionary }); addProperty(_texturePath); - if (dictionary.hasKey(TexturePathInfo.identifier)) { - std::string path = dictionary.value(TexturePathInfo.identifier); - if (!FileSys.fileExists(FileSys.absolutePath(path))) { - LWARNINGC( - "ScreenSpaceImageLocal", - fmt::format("Image {} did not exist for {}", path, _identifier) - ); + if (p.texturePath.has_value()) { + if (FileSys.fileExists(FileSys.absolutePath(*p.texturePath))) { + _texturePath = FileSys.absolutePath(*p.texturePath); } else { - _texturePath = path; + LWARNINGC( + "ScreenSpaceImageLocal", + fmt::format("Image {} did not exist for {}", *p.texturePath, _identifier) + ); } } } diff --git a/modules/base/rendering/screenspaceimageonline.cpp b/modules/base/rendering/screenspaceimageonline.cpp index 4a138b5fa9..ef5c527175 100644 --- a/modules/base/rendering/screenspaceimageonline.cpp +++ b/modules/base/rendering/screenspaceimageonline.cpp @@ -33,6 +33,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo TextureInfo = { @@ -43,30 +44,23 @@ namespace { "and displayed. The size of the image will also automatically set the default " "size of this plane." }; + + struct [[codegen::Dictionary(ScreenSpaceImageOnline)]] Parameters { + // Specifies the GUI name of the ScreenspaceImage + std::optional name; + + // [[codegen::verbatim(TextureInfo.description)]] + std::optional url [[codegen::key("URL")]]; + }; +#include "screenspaceimageonline_codegen.cpp" } // namespace namespace openspace { documentation::Documentation ScreenSpaceImageOnline::Documentation() { - using namespace openspace::documentation; - return { - "ScreenSpace Online Image", - "base_screenspace_image_online", - { - { - KeyName, - new StringVerifier, - Optional::Yes, - "Specifies the GUI name of the ScreenspaceImage" - }, - { - TextureInfo.identifier, - new StringVerifier, - Optional::Yes, - TextureInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_screenspace_image_online"; + return doc; } ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictionary) @@ -74,11 +68,7 @@ ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictiona , _textureIsDirty(false) , _texturePath(TextureInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "ScreenSpaceImageOnline" - ); + const Parameters p = codegen::bake(dictionary); std::string identifier; if (dictionary.hasValue(KeyIdentifier)) { @@ -92,11 +82,7 @@ ScreenSpaceImageOnline::ScreenSpaceImageOnline(const ghoul::Dictionary& dictiona _texturePath.onChange([this]() { _textureIsDirty = true; }); addProperty(_texturePath); - - std::string texturePath; - if (dictionary.hasKey(TextureInfo.identifier)) { - _texturePath = dictionary.value(TextureInfo.identifier); - } + _texturePath = p.url.value_or(_texturePath); } ScreenSpaceImageOnline::~ScreenSpaceImageOnline() {} // NOLINT diff --git a/modules/base/rotation/constantrotation.cpp b/modules/base/rotation/constantrotation.cpp index bbf4f98a9c..d72f524f40 100644 --- a/modules/base/rotation/constantrotation.cpp +++ b/modules/base/rotation/constantrotation.cpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo RotationInfo = { @@ -41,35 +42,22 @@ namespace { "Rotation Rate", "This value determines the number of revolutions per in-game second" }; + + struct [[codegen::Dictionary(ConstantRotation)]] Parameters { + // [[codegen::verbatim(RotationInfo.description)]] + std::optional rotationAxis; + // [[codegen::verbatim(RotationRateInfo.description)]] + std::optional rotationRate; + }; +#include "constantrotation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation ConstantRotation::Documentation() { - using namespace openspace::documentation; - return { - "Static Rotation", - "base_transform_rotation_constant", - { - { - "Type", - new StringEqualVerifier("ConstantRotation"), - Optional::No - }, - { - RotationInfo.identifier, - new DoubleVector3Verifier(), - Optional::Yes, - RotationInfo.description - }, - { - RotationRateInfo.identifier, - new DoubleVerifier(), - Optional::Yes, - RotationRateInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_transform_rotation_constant"; + return doc; } ConstantRotation::ConstantRotation(const ghoul::Dictionary& dictionary) @@ -81,18 +69,13 @@ ConstantRotation::ConstantRotation(const ghoul::Dictionary& dictionary) ) , _rotationRate(RotationRateInfo, 1.f, -1000.f, 1000.f) { + const Parameters p = codegen::bake(dictionary); + + _rotationAxis = p.rotationAxis.value_or(_rotationAxis); addProperty(_rotationAxis); + + _rotationRate = p.rotationRate.value_or(_rotationRate); addProperty(_rotationRate); - - if (dictionary.hasKey(RotationInfo.identifier)) { - _rotationAxis = dictionary.value(RotationInfo.identifier); - } - - if (dictionary.hasKey(RotationRateInfo.identifier)) { - _rotationRate = static_cast( - dictionary.value(RotationRateInfo.identifier) - ); - } } glm::dmat3 ConstantRotation::matrix(const UpdateData& data) const { diff --git a/modules/base/rotation/fixedrotation.cpp b/modules/base/rotation/fixedrotation.cpp index 00cbbae1e2..5d0d864ad0 100644 --- a/modules/base/rotation/fixedrotation.cpp +++ b/modules/base/rotation/fixedrotation.cpp @@ -32,16 +32,11 @@ #include #include #include +#include #include +#include namespace { - constexpr const char* KeyXAxis = "XAxis"; - constexpr const char* KeyXAxisOrthogonal = "XAxisOrthogonal"; - constexpr const char* KeyYAxis = "YAxis"; - constexpr const char* KeyYAxisOrthogonal = "YAxisOrthogonal"; - constexpr const char* KeyZAxis = "ZAxis"; - constexpr const char* KeyZAxisOrthogonal = "ZAxisOrthogonal"; - constexpr const openspace::properties::Property::PropertyInfo EnableInfo = { "Enable", "Enabled", @@ -186,98 +181,59 @@ namespace { "only needed if any of the three axis uses the Object type. In this case, the " "location of the attached node is required to compute the relative direction." }; + + struct [[codegen::Dictionary(FixedRotation)]] Parameters { + // This value specifies the direction of the new X axis. If this value is not + // specified, it will be computed by completing a right handed coordinate system + // from the Y and Z axis, which must be specified instead. If this value is a + // string, it is interpreted as the identifier of another scenegraph node. If this + // value is a 3-vector, it is interpreted as a direction vector + std::optional> xAxis; + + // [[codegen::verbatim(XAxisOrthogonalVectorInfo.description)]] + std::optional xAxisOrthogonal; + + // [[codegen::verbatim(XAxisInvertObjectInfo.description)]] + std::optional xAxisInvert [[codegen::key("xAxis - InvertObject")]]; + + // This value specifies the direction of the new Y axis. If this value is not + // specified, it will be computed by completing a right handed coordinate system + // from the X and Z axis, which must be specified instead. If this value is a + // string, it is interpreted as the identifier of another scenegraph node. If this + // value is a 3-vector, it is interpreted as a direction vector + std::optional> yAxis; + + // [[codegen::verbatim(YAxisOrthogonalVectorInfo.description)]] + std::optional yAxisOrthogonal; + + // [[codegen::verbatim(YAxisInvertObjectInfo.description)]] + std::optional yAxisInvert [[codegen::key("yAxis - InvertObject")]]; + + // This value specifies the direction of the new Z axis. If this value is not + // specified, it will be computed by completing a right handed coordinate system + // from the X and Y axis, which must be specified instead. If this value is a + // string, it is interpreted as the identifier of another scenegraph node. If this + // value is a 3-vector, it is interpreted as a direction vector + std::optional> zAxis; + + // [[codegen::verbatim(ZAxisOrthogonalVectorInfo.description)]] + std::optional zAxisOrthogonal; + + // [[codegen::verbatim(ZAxisInvertObjectInfo.description)]] + std::optional zAxisInvert [[codegen::key("zAxis - InvertObject")]]; + + // [[codegen::verbatim(AttachedInfo.description)]] + std::optional attached; + }; +#include "fixedrotation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation FixedRotation::Documentation() { - using namespace openspace::documentation; - return { - "Fixed Rotation", - "base_transform_rotation_fixed", - { - { - "Type", - new StringEqualVerifier("FixedRotation"), - Optional::No - }, - { - KeyXAxis, - new OrVerifier({ new StringVerifier, new DoubleVector3Verifier, }), - Optional::Yes, - "This value specifies the direction of the new X axis. If this value is " - "not specified, it will be computed by completing a right handed " - "coordinate system from the Y and Z axis, which must be specified " - "instead. If this value is a string, it is interpreted as the identifier " - "of another scenegraph node. If this value is a 3-vector, it is " - "interpreted as a direction vector." - }, - { - KeyXAxisOrthogonal, - new BoolVerifier, - Optional::Yes, - XAxisOrthogonalVectorInfo.description - }, - { - XAxisInvertObjectInfo.identifier, - new BoolVerifier, - Optional::Yes, - XAxisInvertObjectInfo.description - }, - { - KeyYAxis, - new OrVerifier({ new StringVerifier, new DoubleVector3Verifier, }), - Optional::Yes, - "This value specifies the direction of the new Y axis. If this value is " - "not specified, it will be computed by completing a right handed " - "coordinate system from the X and Z axis, which must be specified " - "instead. If this value is a string, it is interpreted as the identifier " - "of another scenegraph node. If this value is a 3-vector, it is " - "interpreted as a direction vector." - }, - { - KeyYAxisOrthogonal, - new BoolVerifier, - Optional::Yes, - YAxisOrthogonalVectorInfo.description - }, - { - YAxisInvertObjectInfo.identifier, - new BoolVerifier, - Optional::Yes, - YAxisInvertObjectInfo.description - }, - { - KeyZAxis, - new OrVerifier({ new StringVerifier, new DoubleVector3Verifier, }), - Optional::Yes, - "This value specifies the direction of the new Z axis. If this value is " - "not specified, it will be computed by completing a right handed " - "coordinate system from the X and Y axis, which must be specified " - "instead. If this value is a string, it is interpreted as the identifier " - "of another scenegraph node. If this value is a 3-vector, it is " - "interpreted as a direction vector." - }, - { - KeyZAxisOrthogonal, - new BoolVerifier, - Optional::Yes, - ZAxisOrthogonalVectorInfo.description - }, - { - ZAxisInvertObjectInfo.identifier, - new BoolVerifier, - Optional::Yes, - ZAxisInvertObjectInfo.description - }, - { - AttachedInfo.identifier, - new StringVerifier, - Optional::Yes, - AttachedInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_transform_rotation_fixed"; + return doc; } FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary) @@ -332,6 +288,9 @@ FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary) } , _attachedObject(AttachedInfo, "") { + // We check the Dictionary here in order to detect the errors early + codegen::bake(dictionary); + documentation::testSpecificationAndThrow( Documentation(), dictionary, @@ -447,103 +406,79 @@ FixedRotation::FixedRotation(const ghoul::Dictionary& dictionary) bool FixedRotation::initialize() { ZoneScoped + // We have already checked this before, but still + const Parameters p = codegen::bake(_constructorDictionary); + // We need to do this in the initialize and not the constructor as the scene graph // nodes referenced in the dictionary might not exist yet at construction time. At // initialization time, however, we know that they already have been created const bool res = Rotation::initialize(); - if (_constructorDictionary.hasKey(AttachedInfo.identifier)) { - _attachedObject = _constructorDictionary.value( - AttachedInfo.identifier - ); - } + _attachedObject = p.attached.value_or(_attachedObject); - const bool hasXAxis = _constructorDictionary.hasKey(KeyXAxis); - if (hasXAxis) { - if (_constructorDictionary.hasValue(KeyXAxis)) { + if (p.xAxis.has_value()) { + if (std::holds_alternative(*p.xAxis)) { _xAxis.type = Axis::Type::Object; - _xAxis.object = _constructorDictionary.value(KeyXAxis); + _xAxis.object = std::get(*p.xAxis); } else { - // We know it has to be a vector now + ghoul_assert(std::holds_alternative(*p.xAxis), ""); _xAxis.type = Axis::Type::Vector; - _xAxis.vector = _constructorDictionary.value(KeyXAxis); + _xAxis.vector = std::get(*p.xAxis); } } - - if (_constructorDictionary.hasKey(KeyXAxisOrthogonal)) { - _xAxis.isOrthogonal = _constructorDictionary.value(KeyXAxisOrthogonal); - } - if (_constructorDictionary.hasKey(XAxisInvertObjectInfo.identifier)) { - _xAxis.invertObject = _constructorDictionary.value( - XAxisInvertObjectInfo.identifier - ); - } + _xAxis.isOrthogonal = p.xAxisOrthogonal.value_or(_xAxis.isOrthogonal); if (_xAxis.isOrthogonal) { _xAxis.type = Axis::Type::OrthogonalVector; } + _xAxis.invertObject = p.xAxisInvert.value_or(_xAxis.invertObject); - const bool hasYAxis = _constructorDictionary.hasKey(KeyYAxis); - if (hasYAxis) { - if (_constructorDictionary.hasValue(KeyYAxis)) { + if (p.yAxis.has_value()) { + if (std::holds_alternative(*p.yAxis)) { _yAxis.type = Axis::Type::Object; - _yAxis.object = _constructorDictionary.value(KeyYAxis); + _yAxis.object = std::get(*p.yAxis); } else { - // We know it has to be a vector now + ghoul_assert(std::holds_alternative(*p.yAxis), ""); _yAxis.type = Axis::Type::Vector; - _yAxis.vector = _constructorDictionary.value(KeyYAxis); + _yAxis.vector = std::get(*p.yAxis); } } - - if (_constructorDictionary.hasKey(KeyYAxisOrthogonal)) { - _yAxis.isOrthogonal = _constructorDictionary.value(KeyYAxisOrthogonal); - } - if (_constructorDictionary.hasKey(YAxisInvertObjectInfo.identifier)) { - _yAxis.invertObject = _constructorDictionary.value( - YAxisInvertObjectInfo.identifier - ); - } + _yAxis.isOrthogonal = p.yAxisOrthogonal.value_or(_yAxis.isOrthogonal); if (_yAxis.isOrthogonal) { _yAxis.type = Axis::Type::OrthogonalVector; } + _yAxis.invertObject = p.yAxisInvert.value_or(_yAxis.invertObject); - const bool hasZAxis = _constructorDictionary.hasKey(KeyZAxis); - if (hasZAxis) { - if (_constructorDictionary.hasValue(KeyZAxis)) { + if (p.zAxis.has_value()) { + if (std::holds_alternative(*p.zAxis)) { _zAxis.type = Axis::Type::Object; - _zAxis.object = _constructorDictionary.value(KeyZAxis); + _zAxis.object = std::get(*p.zAxis); } else { - // We know it has to be a vector now + ghoul_assert(std::holds_alternative(*p.zAxis), ""); _zAxis.type = Axis::Type::Vector; - _zAxis.vector = _constructorDictionary.value(KeyZAxis); + _zAxis.vector = std::get(*p.zAxis); } } - - if (_constructorDictionary.hasKey(KeyZAxisOrthogonal)) { - _zAxis.isOrthogonal = _constructorDictionary.value(KeyZAxisOrthogonal); - } - if (_constructorDictionary.hasKey(ZAxisInvertObjectInfo.identifier)) { - _yAxis.invertObject = _constructorDictionary.value( - ZAxisInvertObjectInfo.identifier - ); - } + _zAxis.isOrthogonal = p.zAxisOrthogonal.value_or(_zAxis.isOrthogonal); if (_zAxis.isOrthogonal) { _zAxis.type = Axis::Type::OrthogonalVector; } + _zAxis.invertObject = p.zAxisInvert.value_or(_zAxis.invertObject); - if (!hasXAxis && hasYAxis && hasZAxis) { + + if (!p.xAxis.has_value() && p.yAxis.has_value() && p.zAxis.has_value()) { _xAxis.type = Axis::Type::CoordinateSystemCompletion; } - if (hasXAxis && !hasYAxis && hasZAxis) { + if (p.xAxis.has_value() && !p.yAxis.has_value() && p.zAxis.has_value()) { _yAxis.type = Axis::Type::CoordinateSystemCompletion; } - if (hasXAxis && hasYAxis && !hasZAxis) { + if (p.xAxis.has_value() && p.yAxis.has_value() && !p.zAxis.has_value()) { _zAxis.type = Axis::Type::CoordinateSystemCompletion; } diff --git a/modules/base/rotation/luarotation.cpp b/modules/base/rotation/luarotation.cpp index 7feb62b165..f6f0f822a5 100644 --- a/modules/base/rotation/luarotation.cpp +++ b/modules/base/rotation/luarotation.cpp @@ -45,29 +45,20 @@ namespace { "J2000 epoch as the second argument and computes the rotation returned as 9 " "values." }; + + struct [[codegen::Dictionary(LuaRotation)]] Parameters { + // [[codegen::verbatim(ScriptInfo.description)]] + std::string script; + }; +#include "luarotation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation LuaRotation::Documentation() { - using namespace openspace::documentation; - return { - "Lua Rotation", - "base_transform_rotation_lua", - { - { - "Type", - new StringEqualVerifier("LuaRotation"), - Optional::No - }, - { - ScriptInfo.identifier, - new StringVerifier, - Optional::No, - ScriptInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_transform_rotation_lua"; + return doc; } LuaRotation::LuaRotation() @@ -86,13 +77,9 @@ LuaRotation::LuaRotation() } LuaRotation::LuaRotation(const ghoul::Dictionary& dictionary) : LuaRotation() { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "LuaRotation" - ); + const Parameters p = codegen::bake(dictionary); - _luaScriptFile = absPath(dictionary.value(ScriptInfo.identifier)); + _luaScriptFile = absPath(p.script); } glm::dmat3 LuaRotation::matrix(const UpdateData& data) const { diff --git a/modules/base/rotation/staticrotation.cpp b/modules/base/rotation/staticrotation.cpp index e42acfa361..1da7e72f6f 100644 --- a/modules/base/rotation/staticrotation.cpp +++ b/modules/base/rotation/staticrotation.cpp @@ -55,34 +55,21 @@ namespace { } return res; } + + struct [[codegen::Dictionary(StaticRotation)]] Parameters { + // Stores the static rotation as a vector containing Euler angles, a quaternion + // or a rotation matrix + std::variant rotation; + }; +#include "staticrotation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation StaticRotation::Documentation() { - using namespace openspace::documentation; - return { - "Static Rotation", - "base_transform_rotation_static", - { - { - "Type", - new StringEqualVerifier("StaticRotation"), - Optional::No - }, - { - RotationInfo.identifier, - new OrVerifier({ - new DoubleVector3Verifier(), - new DoubleVector4Verifier(), - new DoubleMatrix3Verifier() - }), - Optional::No, - "Stores the static rotation as a vector containing Euler angles, " - " a quaternion or a rotation matrix." - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_transform_rotation_static"; + return doc; } StaticRotation::StaticRotation() @@ -101,31 +88,21 @@ StaticRotation::StaticRotation() } StaticRotation::StaticRotation(const ghoul::Dictionary& dictionary) : StaticRotation() { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "StaticRotation" - ); + const Parameters p = codegen::bake(dictionary); - if (dictionary.hasValue(RotationInfo.identifier)) { - _eulerRotation = static_cast( - dictionary.value(RotationInfo.identifier) - ); - _matrixIsDirty = true; + if (std::holds_alternative(p.rotation)) { + _eulerRotation = std::get(p.rotation); } - else if (dictionary.hasValue(RotationInfo.identifier)) { - glm::dvec4 data = dictionary.value(RotationInfo.identifier); + else if (std::holds_alternative(p.rotation)) { + glm::dvec4 data = std::get(p.rotation); _eulerRotation = rotationMatrixToEulerAngles( glm::mat3_cast(glm::dquat(data.w, data.x, data.y, data.z)) ); - _matrixIsDirty = true; } - else if (dictionary.hasValue(RotationInfo.identifier)) { - _eulerRotation = rotationMatrixToEulerAngles( - dictionary.value(RotationInfo.identifier) - ); - _matrixIsDirty = true; + else if (std::holds_alternative(p.rotation)) { + _eulerRotation = rotationMatrixToEulerAngles(std::get(p.rotation)); } + _matrixIsDirty = true; } glm::dmat3 StaticRotation::matrix(const UpdateData&) const { diff --git a/modules/base/rotation/timelinerotation.cpp b/modules/base/rotation/timelinerotation.cpp index 46aeb0431a..39ef1dec06 100644 --- a/modules/base/rotation/timelinerotation.cpp +++ b/modules/base/rotation/timelinerotation.cpp @@ -30,7 +30,6 @@ #include namespace { - constexpr const char* KeyType = "Type"; constexpr const char* KeyKeyframes = "Keyframes"; } // namespace @@ -42,11 +41,6 @@ documentation::Documentation TimelineRotation::Documentation() { "Timeline Rotation", "base_transform_rotation_keyframe", { - { - KeyType, - new StringEqualVerifier("TimelineRotation"), - Optional::No - }, { KeyKeyframes, new TableVerifier({ diff --git a/modules/base/scale/luascale.cpp b/modules/base/scale/luascale.cpp index 204a0205f8..8ea195e15c 100644 --- a/modules/base/scale/luascale.cpp +++ b/modules/base/scale/luascale.cpp @@ -32,7 +32,6 @@ #include #include #include - #include namespace { @@ -45,24 +44,20 @@ namespace { "as the first argument, the current wall time as milliseconds past the J2000 " "epoch the second argument and computes the three scaling factors." }; + + struct [[codegen::Dictionary(LuaScale)]] Parameters { + // [[codegen::verbatim(ScriptInfo.description)]] + std::string script; + }; +#include "luascale_codegen.cpp" } // namespace namespace openspace { documentation::Documentation LuaScale::Documentation() { - using namespace openspace::documentation; - return { - "Lua Scaling", - "base_scale_lua", - { - { - ScriptInfo.identifier, - new StringVerifier, - Optional::No, - ScriptInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_scale_lua"; + return doc; } LuaScale::LuaScale() @@ -81,9 +76,8 @@ LuaScale::LuaScale() } LuaScale::LuaScale(const ghoul::Dictionary& dictionary) : LuaScale() { - documentation::testSpecificationAndThrow(Documentation(), dictionary, "LuaScale"); - - _luaScriptFile = absPath(dictionary.value(ScriptInfo.identifier)); + const Parameters p = codegen::bake(dictionary); + _luaScriptFile = absPath(p.script); } glm::dvec3 LuaScale::scaleValue(const UpdateData& data) const { diff --git a/modules/base/scale/nonuniformstaticscale.cpp b/modules/base/scale/nonuniformstaticscale.cpp index b83a3c81b5..19bc7ca349 100644 --- a/modules/base/scale/nonuniformstaticscale.cpp +++ b/modules/base/scale/nonuniformstaticscale.cpp @@ -34,24 +34,20 @@ namespace { "These values are used as scaling factors for the scene graph node that this " "transformation is attached to relative to its parent." }; + + struct [[codegen::Dictionary(NonUniformStaticScale)]] Parameters { + // [[codegen::verbatim(ScaleInfo.description)]] + glm::dvec3 scale; + }; +#include "nonuniformstaticscale_codegen.cpp" } // namespace namespace openspace { documentation::Documentation NonUniformStaticScale::Documentation() { - using namespace openspace::documentation; - return { - "Static Scaling", - "base_scale_static", - { - { - ScaleInfo.identifier, - new DoubleVector3Verifier, - Optional::No, - ScaleInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_scale_nonuniformstatic"; + return doc; } glm::dvec3 NonUniformStaticScale::scaleValue(const UpdateData&) const { @@ -71,9 +67,8 @@ NonUniformStaticScale::NonUniformStaticScale() NonUniformStaticScale::NonUniformStaticScale(const ghoul::Dictionary& dictionary) : NonUniformStaticScale() { - documentation::testSpecificationAndThrow(Documentation(), dictionary, "StaticScale"); - - _scaleValue = dictionary.value(ScaleInfo.identifier); + const Parameters p = codegen::bake(dictionary); + _scaleValue = p.scale; } } // namespace openspace diff --git a/modules/base/scale/staticscale.cpp b/modules/base/scale/staticscale.cpp index a246ab4ad9..59b5a96c57 100644 --- a/modules/base/scale/staticscale.cpp +++ b/modules/base/scale/staticscale.cpp @@ -34,24 +34,20 @@ namespace { "This value is used as a scaling factor for the scene graph node that this " "transformation is attached to relative to its parent." }; + + struct [[codegen::Dictionary(StaticScale)]] Parameters { + // [[codegen::verbatim(ScaleInfo.description)]] + float scale; + }; +#include "staticscale_codegen.cpp" } // namespace namespace openspace { documentation::Documentation StaticScale::Documentation() { - using namespace openspace::documentation; - return { - "Static Scaling", - "base_scale_static", - { - { - ScaleInfo.identifier, - new DoubleVerifier, - Optional::No, - ScaleInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_scale_static"; + return doc; } glm::dvec3 StaticScale::scaleValue(const UpdateData&) const { @@ -67,9 +63,8 @@ StaticScale::StaticScale() : _scaleValue(ScaleInfo, 1.f, 0.1f, 100.f) { } StaticScale::StaticScale(const ghoul::Dictionary& dictionary) : StaticScale() { - documentation::testSpecificationAndThrow(Documentation(), dictionary, "StaticScale"); - - _scaleValue = static_cast(dictionary.value(ScaleInfo.identifier)); + const Parameters p = codegen::bake(dictionary); + _scaleValue = p.scale; } } // namespace openspace diff --git a/modules/base/scale/timedependentscale.cpp b/modules/base/scale/timedependentscale.cpp index 255e9a3ad0..168146ef0c 100644 --- a/modules/base/scale/timedependentscale.cpp +++ b/modules/base/scale/timedependentscale.cpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace { constexpr openspace::properties::Property::PropertyInfo ReferenceDateInfo = { @@ -53,36 +54,26 @@ namespace { "negative values. This is useful for instantaneous events that only propagate " "forwards. The default value is 'true'." }; + + struct [[codegen::Dictionary(TimeDependentScale)]] Parameters { + // [[codegen::verbatim(ReferenceDateInfo.description)]] + std::string referenceDate; + + // [[codegen::verbatim(SpeedInfo.description)]] + std::optional speed; + + // [[codegen::verbatim(ClampToPositiveInfo.description)]] + std::optional clampToPositive; + }; +#include "timedependentscale_codegen.cpp" } // namespace namespace openspace { documentation::Documentation TimeDependentScale::Documentation() { - using namespace openspace::documentation; - return { - "Timedependent Scaling", - "base_scale_timedependent", - { - { - ReferenceDateInfo.identifier, - new StringVerifier, - Optional::No, - ReferenceDateInfo.description - }, - { - SpeedInfo.identifier, - new DoubleVerifier, - Optional::Yes, - SpeedInfo.description - }, - { - ClampToPositiveInfo.identifier, - new BoolVerifier, - Optional::Yes, - ClampToPositiveInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_scale_timedependent"; + return doc; } TimeDependentScale::TimeDependentScale(const ghoul::Dictionary& dictionary) @@ -90,21 +81,17 @@ TimeDependentScale::TimeDependentScale(const ghoul::Dictionary& dictionary) , _speed(SpeedInfo, 1.0, 0.0, 1e12) , _clampToPositive(ClampToPositiveInfo, true) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "TimeDependentScale" - ); + const Parameters p = codegen::bake(dictionary); - _referenceDate = dictionary.value(ReferenceDateInfo.identifier); + _referenceDate = p.referenceDate; _referenceDate.onChange([this]() { _cachedReferenceDirty = true; }); addProperty(_referenceDate); - if (dictionary.value(SpeedInfo.identifier)) { - _speed = dictionary.value(SpeedInfo.identifier); - } + _speed = p.speed.value_or(_speed); addProperty(_speed); + // @TODO (abock, 2021-01-09) The clamp to positive value from the dictionary was never + // actually read. I think this should probably be done here? addProperty(_clampToPositive); } diff --git a/modules/base/timeframe/timeframeinterval.cpp b/modules/base/timeframe/timeframeinterval.cpp index 1d194527a8..e0a18079b2 100644 --- a/modules/base/timeframe/timeframeinterval.cpp +++ b/modules/base/timeframe/timeframeinterval.cpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace { constexpr const openspace::properties::Property::PropertyInfo HasStartInfo = { @@ -53,42 +54,23 @@ namespace { "End", "Specifies the time when this TimeFrame becomes inactive" }; + + struct [[codegen::Dictionary(TimeFrameInterval)]] Parameters { + // [[codegen::verbatim(StartInfo.description)]] + std::optional> start; + + // [[codegen::verbatim(EndInfo.description)]] + std::optional> end; + }; +#include "timeframeinterval_codegen.cpp" } // namespace namespace openspace { documentation::Documentation TimeFrameInterval::Documentation() { - using namespace openspace::documentation; - return { - "Time Frame Interval", - "base_time_frame_interval", - { - { - HasStartInfo.identifier, - new BoolVerifier, - Optional::Yes, - HasStartInfo.description - }, - { - StartInfo.identifier, - new OrVerifier({ new DoubleVerifier, new StringVerifier }), - Optional::Yes, - StartInfo.description - }, - { - HasEndInfo.identifier, - new BoolVerifier, - Optional::Yes, - HasEndInfo.description - }, - { - EndInfo.identifier, - new OrVerifier({ new DoubleVerifier, new StringVerifier }), - Optional::Yes, - EndInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_time_frame_interval"; + return doc; } bool TimeFrameInterval::isActive(const Time& time) const { @@ -119,38 +101,35 @@ TimeFrameInterval::TimeFrameInterval(const ghoul::Dictionary& dictionary) , _hasEnd(HasEndInfo, false) , _end(EndInfo, 0, 0, 1E9) { + const Parameters p = codegen::bake(dictionary); + + if (p.start.has_value()) { + if (std::holds_alternative(*p.start)) { + _start = std::get(*p.start); + } + else { + _start = SpiceManager::ref().ephemerisTimeFromDate( + std::get(*p.start) + ); + } + } + _hasStart = p.start.has_value(); addProperty(_hasStart); addProperty(_start); + + if (p.end.has_value()) { + if (std::holds_alternative(*p.end)) { + _end = std::get(*p.end); + } + else { + _end = SpiceManager::ref().ephemerisTimeFromDate( + std::get(*p.end) + ); + } + } + _hasEnd = p.end.has_value(); addProperty(_hasEnd); addProperty(_end); - - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "TimeFrameInterval" - ); - - if (dictionary.hasValue(StartInfo.identifier)) { - _start = SpiceManager::ref().ephemerisTimeFromDate( - dictionary.value(StartInfo.identifier) - ); - _hasStart = true; - } - else if (dictionary.hasValue(StartInfo.identifier)) { - _start = dictionary.value(StartInfo.identifier); - _hasStart = true; - } - - if (dictionary.hasValue(EndInfo.identifier)) { - _end = SpiceManager::ref().ephemerisTimeFromDate( - dictionary.value(EndInfo.identifier) - ); - _hasEnd = true; - } - else if (dictionary.hasValue(EndInfo.identifier)) { - _end = dictionary.value(EndInfo.identifier); - _hasEnd = true; - } } } // namespace openspace diff --git a/modules/base/timeframe/timeframeunion.cpp b/modules/base/timeframe/timeframeunion.cpp index 885888db68..05f7da7028 100644 --- a/modules/base/timeframe/timeframeunion.cpp +++ b/modules/base/timeframe/timeframeunion.cpp @@ -38,30 +38,20 @@ namespace { "The time frame is active when any of the contained time frames are, " "but not in gaps between contained time frames." }; + + struct [[codegen::Dictionary(TimeFrameUnion)]] Parameters { + // [[codegen::verbatim(TimeFramesInfo.description)]] + std::vector timeFrames [[codegen::reference("core_time_frame")]]; + }; +#include "timeframeunion_codegen.cpp" } // namespace namespace openspace { documentation::Documentation TimeFrameUnion::Documentation() { - using namespace openspace::documentation; - return { - "Time Frame Union", - "base_time_frame_union", - { - { - TimeFramesInfo.identifier, - new TableVerifier({ - { - "*", - new ReferencingVerifier("core_time_frame"), - Optional::Yes - } - }), - Optional::No, - TimeFramesInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_time_frame_union"; + return doc; } bool TimeFrameUnion::isActive(const Time& time) const { @@ -76,9 +66,10 @@ bool TimeFrameUnion::isActive(const Time& time) const { TimeFrameUnion::TimeFrameUnion(const ghoul::Dictionary& dictionary) : TimeFrame() { - documentation::testSpecificationAndThrow(Documentation(), - dictionary, - "TimeFrameUnion"); + // I don't know how we can actually help the reference attribute properly. Since the + // Parameter list only contains the monostate, there is no need to actually create + // the object here + codegen::bake(dictionary); ghoul::Dictionary frames = dictionary.value(TimeFramesInfo.identifier); diff --git a/modules/base/translation/luatranslation.cpp b/modules/base/translation/luatranslation.cpp index 8268b30928..8f850d1f28 100644 --- a/modules/base/translation/luatranslation.cpp +++ b/modules/base/translation/luatranslation.cpp @@ -33,7 +33,6 @@ #include #include #include - #include namespace { @@ -46,32 +45,22 @@ namespace { "epoch as the first argument, the current wall time as milliseconds past the " "J2000 epoch as the second argument and computes the translation." }; + + struct [[codegen::Dictionary(LuaTranslation)]] Parameters { + // [[codegen::verbatim(ScriptInfo.description)]] + std::string script; + }; +#include "luatranslation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation LuaTranslation::Documentation() { - using namespace documentation; - return { - "Lua Translation", - "base_transform_translation_lua", - { - { - "Type", - new StringEqualVerifier("LuaTranslation"), - Optional::No - }, - { - ScriptInfo.identifier, - new StringVerifier, - Optional::No, - ScriptInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_transform_translation_lua"; + return doc; } - LuaTranslation::LuaTranslation() : _luaScriptFile(ScriptInfo) , _state(ghoul::lua::LuaState::IncludeStandardLibrary::No) @@ -89,13 +78,8 @@ LuaTranslation::LuaTranslation() } LuaTranslation::LuaTranslation(const ghoul::Dictionary& dictionary) : LuaTranslation() { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "StaticTranslation" - ); - - _luaScriptFile = absPath(dictionary.value(ScriptInfo.identifier)); + const Parameters p = codegen::bake(dictionary); + _luaScriptFile = absPath(p.script); } glm::dvec3 LuaTranslation::position(const UpdateData& data) const { diff --git a/modules/base/translation/statictranslation.cpp b/modules/base/translation/statictranslation.cpp index 616185556d..7cdaa8cee6 100644 --- a/modules/base/translation/statictranslation.cpp +++ b/modules/base/translation/statictranslation.cpp @@ -34,32 +34,22 @@ namespace { "This value is used as a static offset (in meters) that is applied to the scene " "graph node that this transformation is attached to relative to its parent." }; + + struct [[codegen::Dictionary(StaticTranslation)]] Parameters { + // [[codegen::verbatim(PositionInfo.description)]] + glm::dvec3 position; + }; +#include "statictranslation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation StaticTranslation::Documentation() { - using namespace documentation; - return { - "Static Translation", - "base_transform_translation_static", - { - { - "Type", - new StringEqualVerifier("StaticTranslation"), - Optional::No - }, - { - PositionInfo.identifier, - new DoubleVector3Verifier, - Optional::No, - PositionInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_transform_translation_static"; + return doc; } - StaticTranslation::StaticTranslation() : _position( PositionInfo, @@ -79,13 +69,8 @@ StaticTranslation::StaticTranslation() StaticTranslation::StaticTranslation(const ghoul::Dictionary& dictionary) : StaticTranslation() { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "StaticTranslation" - ); - - _position = dictionary.value(PositionInfo.identifier); + const Parameters p = codegen::bake(dictionary); + _position = p.position; } glm::dvec3 StaticTranslation::position(const UpdateData&) const { diff --git a/modules/base/translation/timelinetranslation.cpp b/modules/base/translation/timelinetranslation.cpp index 1479825ec3..fb6dafb14e 100644 --- a/modules/base/translation/timelinetranslation.cpp +++ b/modules/base/translation/timelinetranslation.cpp @@ -30,7 +30,6 @@ #include namespace { - constexpr const char* KeyType = "Type"; constexpr const char* KeyKeyframes = "Keyframes"; } // namespace @@ -42,11 +41,6 @@ documentation::Documentation TimelineTranslation::Documentation() { "Timeline Translation", "base_transform_translation_keyframe", { - { - KeyType, - new StringEqualVerifier("TimelineTranslation"), - Optional::No - }, { KeyKeyframes, new TableVerifier({ diff --git a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp index c7a0d77cc5..7ee516e26b 100644 --- a/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp +++ b/modules/digitaluniverse/rendering/renderablebillboardscloud.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include namespace { @@ -65,17 +66,6 @@ namespace { "hasColorMap", "enabledRectSizeControl", "hasDvarScaling" }; - constexpr const char* KeyFile = "File"; - constexpr const char* keyColor = "Color"; - constexpr const char* keyUnit = "Unit"; - constexpr const char* MeterUnit = "m"; - constexpr const char* KilometerUnit = "Km"; - constexpr const char* ParsecUnit = "pc"; - constexpr const char* KiloparsecUnit = "Kpc"; - constexpr const char* MegaparsecUnit = "Mpc"; - constexpr const char* GigaparsecUnit = "Gpc"; - constexpr const char* GigalightyearUnit = "Gly"; - constexpr int8_t CurrentCacheVersion = 1; constexpr double PARSEC = 0.308567756E17; @@ -107,26 +97,6 @@ namespace { "The path to the color map file of the astronomical object." }; - constexpr openspace::properties::Property::PropertyInfo ExactColorMapInfo = { - "ExactColorMap", - "Exact Color Map File", - "Set a 1 to 1 relationship between the color index variable and the colormap" - " entrered value." - }; - - constexpr openspace::properties::Property::PropertyInfo ColorRangeInfo = { - "ColorRange", - "Color Range", - "This value determines the colormap ranges for the color parameters of the " - "astronomical objects." - }; - - constexpr openspace::properties::Property::PropertyInfo PolygonSidesInfo = { - "PolygonSides", - "Polygon Sides", - "The number of sides for the polygon used to represent the astronomical object." - }; - constexpr openspace::properties::Property::PropertyInfo TextColorInfo = { "TextColor", "Text Color", @@ -146,13 +116,6 @@ namespace { "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 LabelMinSizeInfo = { "TextMinSize", "Text Min Size", @@ -199,12 +162,6 @@ namespace { "of the astronomical objects." }; - constexpr openspace::properties::Property::PropertyInfo TransformationMatrixInfo = { - "TransformationMatrix", - "Transformation Matrix", - "Transformation matrix to be applied to each astronomical object." - }; - constexpr openspace::properties::Property::PropertyInfo RenderOptionInfo = { "RenderOption", "Render Option", @@ -270,180 +227,120 @@ namespace { "Set Data Range from Data", "Set the data range based on the available data" }; + + struct [[codegen::Dictionary(RenderableBillboardsCloud)]] Parameters { + // The path to the SPECK file that contains information about the astronomical + // object being rendered + std::optional file; + + // [[codegen::verbatim(ColorInfo.description)]] + glm::vec3 color; + + // [[codegen::verbatim(SpriteTextureInfo.description)]] + std::optional texture; + + // [[codegen::verbatim(DrawElementsInfo.description)]] + std::optional drawElements; + + enum class RenderOption { + ViewDirection [[codegen::key("Camera View Direction")]], + PositionNormal [[codegen::key("Camera Position Normal")]] + }; + // [[codegen::verbatim(RenderOptionInfo.description)]] + std::optional renderOption; + + enum class 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")]], + GigalightYears [[codegen::key("Gly")]] + }; + std::optional unit; + + // [[codegen::verbatim(ScaleFactorInfo.description)]] + std::optional scaleFactor; + + // [[codegen::verbatim(ColorMapInfo.description)]] + std::optional colorMap; + + // Set a 1 to 1 relationship between the color index variable and the colormap + // entrered value + std::optional exactColorMap; + + // The number of sides for the polygon used to represent the astronomical object + std::optional polygonSides; + + // [[codgen::verbatim(DrawLabelInfo.description)]] + std::optional drawLabels; + + // [[codgen::verbatim(TextColorInfo.description)]] + std::optional textColor; + + // [[codgen::verbatim(TextOpacityInfo.description)]] + std::optional textOpacity; + + // [[codgen::verbatim(TextSizeInfo.description)]] + std::optional textSize; + + // The path to the label file that contains information about the astronomical + // objects being rendered + std::optional labelFile; + + // [[codgen::verbatim(LabelMinSizeInfo.description)]] + std::optional textMinSize; + + // [[codgen::verbatim(LabelMaxSizeInfo.description)]] + std::optional textMaxSize; + + // [[codgen::verbatim(ColorOptionInfo.description)]] + std::optional> colorOption; + + // [[codgen::verbatim(SizeOptionInfo.description)]] + std::optional> sizeOption; + + // This value determines the colormap ranges for the color parameters of the + // astronomical objects + std::optional> colorRange; + + // Transformation matrix to be applied to each astronomical object + std::optional transformationMatrix; + + // [[codgen::verbatim(FadeInDistancesInfo.description)]] + std::optional fadeInDistances; + + // [[codgen::verbatim(DisableFadeInInfo.description)]] + std::optional disableFadeIn; + + // [[codgen::verbatim(BillboardMaxSizeInfo.description)]] + std::optional billboardMaxSize; + + // [[codgen::verbatim(BillboardMinSizeInfo.description)]] + std::optional billboardMinSize; + + // [[codgen::verbatim(CorrectionSizeEndDistanceInfo.description)]] + std::optional correctionSizeEndDistance; + + // [[codgen::verbatim(CorrectionSizeFactorInfo.description)]] + std::optional correctionSizeFactor; + + // [[codgen::verbatim(PixelSizeControlInfo.description)]] + std::optional enablePixelSizeControl; + + // [[codgen::verbatim(UseLinearFiltering.description)]] + std::optional useLinearFiltering; + }; +#include "renderablebillboardscloud_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableBillboardsCloud::Documentation() { - using namespace documentation; - return { - "RenderableBillboardsCloud", - "digitaluniverse_RenderableBillboardsCloud", - { - { - "Type", - new StringEqualVerifier("RenderableBillboardsCloud"), - Optional::No - }, - { - KeyFile, - new StringVerifier, - Optional::Yes, - "The path to the SPECK file that contains information about the " - "astronomical object being rendered." - }, - { - keyColor, - new DoubleVector3Verifier, - Optional::No, - "Astronomical Object Color (r,g,b)." - }, - { - SpriteTextureInfo.identifier, - new StringVerifier, - Optional::Yes, - SpriteTextureInfo.description - }, - { - ScaleFactorInfo.identifier, - new DoubleVerifier, - Optional::Yes, - ScaleFactorInfo.description - }, - { - ColorMapInfo.identifier, - new StringVerifier, - Optional::Yes, - ColorMapInfo.description - }, - { - ExactColorMapInfo.identifier, - new BoolVerifier, - Optional::Yes, - ExactColorMapInfo.description - }, - { - PolygonSidesInfo.identifier, - new IntVerifier, - Optional::Yes, - PolygonSidesInfo.description - }, - { - DrawLabelInfo.identifier, - new BoolVerifier, - Optional::Yes, - DrawLabelInfo.description - }, - { - TextColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - TextColorInfo.description - }, - { - TextOpacityInfo.identifier, - new DoubleVerifier, - Optional::Yes, - TextOpacityInfo.description - }, - { - TextSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - TextSizeInfo.description - }, - { - LabelFileInfo.identifier, - new StringVerifier, - Optional::Yes, - LabelFileInfo.description - }, - { - LabelMinSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LabelMinSizeInfo.description - }, - { - LabelMaxSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LabelMaxSizeInfo.description - }, - { - ColorOptionInfo.identifier, - new StringListVerifier, - Optional::Yes, - ColorOptionInfo.description - }, - { - SizeOptionInfo.identifier, - new StringListVerifier, - Optional::Yes, - SizeOptionInfo.description - }, - { - ColorRangeInfo.identifier, - new Vector2ListVerifier, - Optional::Yes, - ColorRangeInfo.description - }, - { - TransformationMatrixInfo.identifier, - new Matrix4x4Verifier, - Optional::Yes, - TransformationMatrixInfo.description - }, - { - FadeInDistancesInfo.identifier, - new Vector2Verifier, - Optional::Yes, - FadeInDistancesInfo.description - }, - { - DisableFadeInInfo.identifier, - new BoolVerifier, - Optional::Yes, - DisableFadeInInfo.description - }, - { - BillboardMaxSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - BillboardMaxSizeInfo.description - }, - { - BillboardMinSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - BillboardMinSizeInfo.description - }, - { - CorrectionSizeEndDistanceInfo.identifier, - new DoubleVerifier, - Optional::Yes, - CorrectionSizeEndDistanceInfo.description - }, - { - CorrectionSizeFactorInfo.identifier, - new DoubleVerifier, - Optional::Yes, - CorrectionSizeFactorInfo.description - }, - { - PixelSizeControlInfo.identifier, - new BoolVerifier, - Optional::Yes, - PixelSizeControlInfo.description - }, - { - UseLinearFiltering.identifier, - new BoolVerifier, - Optional::Yes, - UseLinearFiltering.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "digitaluniverse_RenderableBillboardsCloud"; + return doc; } RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& dictionary) @@ -481,98 +378,87 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di , _setRangeFromData(SetRangeFromData) , _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableBillboardsCloud" - ); + const Parameters p = codegen::bake(dictionary); - if (dictionary.hasKey(KeyFile)) { - _speckFile = absPath(dictionary.value(KeyFile)); - _hasSpeckFile = true; - } - - if (dictionary.hasKey(DrawElementsInfo.identifier)) { - _drawElements = dictionary.value(DrawElementsInfo.identifier); + if (p.file.has_value()) { + _speckFile = absPath(*p.file); } + _hasSpeckFile = p.file.has_value(); + _drawElements = p.drawElements.value_or(_drawElements); _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); addProperty(_drawElements); _renderOption.addOption(RenderOptionViewDirection, "Camera View Direction"); _renderOption.addOption(RenderOptionPositionNormal, "Camera Position Normal"); - _renderOption = RenderOptionViewDirection; - if (dictionary.hasValue(RenderOptionInfo.identifier)) { - const std::string o = dictionary.value(RenderOptionInfo.identifier); - - if (o == "Camera View Direction") { - _renderOption = RenderOptionViewDirection; - } - else if (o == "Camera Position Normal") { - _renderOption = RenderOptionPositionNormal; + if (p.renderOption.has_value()) { + switch (*p.renderOption) { + case Parameters::RenderOption::ViewDirection: + _renderOption = RenderOptionViewDirection; + break; + case Parameters::RenderOption::PositionNormal: + _renderOption = RenderOptionPositionNormal; + break; } } - + else { + _renderOption = RenderOptionViewDirection; + } addProperty(_renderOption); - if (dictionary.hasKey(keyUnit)) { - std::string unit = dictionary.value(keyUnit); - if (unit == MeterUnit) { - _unit = Meter; - } - else if (unit == KilometerUnit) { - _unit = Kilometer; - } - else if (unit == ParsecUnit) { - _unit = Parsec; - } - else if (unit == KiloparsecUnit) { - _unit = Kiloparsec; - } - else if (unit == MegaparsecUnit) { - _unit = Megaparsec; - } - else if (unit == GigaparsecUnit) { - _unit = Gigaparsec; - } - else if (unit == GigalightyearUnit) { - _unit = GigalightYears; - } - else { - LWARNING( - "No unit given for RenderableBillboardsCloud. Using meters as units." - ); - _unit = Meter; + if (p.unit.has_value()) { + switch (*p.unit) { + case Parameters::Unit::Meter: + _unit = Meter; + break; + case Parameters::Unit::Kilometer: + _unit = Kilometer; + break; + case Parameters::Unit::Parsec: + _unit = Parsec; + break; + case Parameters::Unit::Kiloparsec: + _unit = Kiloparsec; + break; + case Parameters::Unit::Megaparsec: + _unit = Megaparsec; + break; + case Parameters::Unit::Gigaparsec: + _unit = Gigaparsec; + break; + case Parameters::Unit::GigalightYears: + _unit = GigalightYears; + break; } } + else { + LWARNING("No unit given for RenderableBillboardsCloud. Using meters as units."); + _unit = Meter; + } - if (dictionary.hasKey(SpriteTextureInfo.identifier)) { - _spriteTexturePath = absPath(dictionary.value( - SpriteTextureInfo.identifier - )); - + if (p.texture.has_value()) { + _spriteTexturePath = absPath(*p.texture); _spriteTexturePath.onChange([&]() { _spriteTextureIsDirty = true; }); + + // @TODO (abock, 2021-01-31) I don't know why we only add this property if the + // texture is given, but I think it's a bug addProperty(_spriteTexturePath); - _hasSpriteTexture = true; } + _hasSpriteTexture = p.texture.has_value(); - if (dictionary.hasKey(ColorMapInfo.identifier)) { - _colorMapFile = absPath(dictionary.value(ColorMapInfo.identifier)); + + if (p.colorMap.has_value()) { + _colorMapFile = absPath(*p.colorMap); _hasColorMapFile = true; - if (dictionary.hasKey(ColorOptionInfo.identifier)) { - ghoul::Dictionary colorOptionDataDic = dictionary.value( - ColorOptionInfo.identifier - ); - for (int i = 0; i < static_cast(colorOptionDataDic.size()); ++i) { - std::string colorMapInUseName( - colorOptionDataDic.value(std::to_string(i + 1)) - ); - _colorOption.addOption(i, colorMapInUseName); - _optionConversionMap.insert({ i, colorMapInUseName }); - _colorOptionString = colorMapInUseName; + if (p.colorOption.has_value()) { + std::vector opts = *p.colorOption; + for (size_t i = 0; i < opts.size(); ++i) { + _colorOption.addOption(static_cast(i), opts[i]); + _optionConversionMap.insert({ static_cast(i), opts[i] }); + _colorOptionString = opts[i]; } } _colorOption.onChange([&]() { @@ -583,15 +469,8 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di }); addProperty(_colorOption); - if (dictionary.hasKey(ColorRangeInfo.identifier)) { - ghoul::Dictionary rangeDataDict = dictionary.value( - ColorRangeInfo.identifier - ); - for (size_t i = 0; i < rangeDataDict.size(); ++i) { - _colorRangeData.push_back( - rangeDataDict.value(std::to_string(i + 1)) - ); - } + _colorRangeData = p.colorRange.value_or(_colorRangeData); + if (!_colorRangeData.empty()) { _optionColorRangeData = _colorRangeData[_colorRangeData.size() - 1]; } _optionColorRangeData.onChange([&]() { @@ -601,36 +480,25 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di }); addProperty(_optionColorRangeData); - if (dictionary.hasKey(ExactColorMapInfo.identifier)) { - _isColorMapExact = dictionary.value(ExactColorMapInfo.identifier); - } + _isColorMapExact = p.exactColorMap.value_or(_isColorMapExact); } - else if (dictionary.hasKey(keyColor)) { - _pointColor = dictionary.value(keyColor); + else { + _pointColor = p.color; _pointColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_pointColor); } addProperty(_opacity); - if (dictionary.hasKey(ScaleFactorInfo.identifier)) { - _scaleFactor = static_cast( - dictionary.value(ScaleFactorInfo.identifier) - ); - } + _scaleFactor = p.scaleFactor.value_or(_scaleFactor); addProperty(_scaleFactor); - if (dictionary.hasKey(SizeOptionInfo.identifier)) { - ghoul::Dictionary sizeOptionDataDic = dictionary.value( - SizeOptionInfo.identifier - ); - for (int i = 0; i < static_cast(sizeOptionDataDic.size()); ++i) { - std::string datavarSizeInUseName( - sizeOptionDataDic.value(std::to_string(i + 1)) - ); - _datavarSizeOption.addOption(i, datavarSizeInUseName); - _optionConversionSizeMap.insert({ i, datavarSizeInUseName }); - _datavarSizeOptionString = datavarSizeInUseName; + if (p.sizeOption.has_value()) { + std::vector opts = *p.sizeOption; + for (size_t i = 0; i < opts.size(); ++i) { + _datavarSizeOption.addOption(static_cast(i), opts[i]); + _optionConversionSizeMap.insert({ static_cast(i), opts[i] }); + _datavarSizeOptionString = opts[i]; } _datavarSizeOption.onChange([&]() { @@ -642,104 +510,62 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di _hasDatavarSize = true; } - if (dictionary.hasKey(PolygonSidesInfo.identifier)) { - _polygonSides = static_cast( - dictionary.value(PolygonSidesInfo.identifier) - ); - _hasPolygon = true; - } + _polygonSides = p.polygonSides.value_or(_polygonSides); + _hasPolygon = p.polygonSides.has_value(); - if (dictionary.hasKey(LabelFileInfo.identifier)) { - if (dictionary.hasKey(DrawLabelInfo.identifier)) { - _drawLabels = dictionary.value(DrawLabelInfo.identifier); - } + if (p.labelFile.has_value()) { + _drawLabels = p.drawLabels.value_or(_drawLabels); addProperty(_drawLabels); - _labelFile = absPath(dictionary.value(LabelFileInfo.identifier)); + _labelFile = absPath(*p.labelFile); _hasLabel = true; - if (dictionary.hasKey(TextColorInfo.identifier)) { - _textColor = dictionary.value(TextColorInfo.identifier); - _hasLabel = true; - } + _textColor = p.textColor.value_or(_textColor); + _hasLabel = p.textColor.has_value(); _textColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_textColor); _textColor.onChange([&]() { _textColorIsDirty = true; }); - if (dictionary.hasKey(TextOpacityInfo.identifier)) { - _textOpacity = static_cast( - dictionary.value(TextOpacityInfo.identifier) - ); - } + _textOpacity = p.textOpacity.value_or(_textOpacity); addProperty(_textOpacity); - if (dictionary.hasKey(TextSizeInfo.identifier)) { - _textSize = static_cast( - dictionary.value(TextSizeInfo.identifier) - ); - } + _textSize = p.textSize.value_or(_textSize); addProperty(_textSize); - if (dictionary.hasKey(LabelMinSizeInfo.identifier)) { - _textMinSize = static_cast( - dictionary.value(LabelMinSizeInfo.identifier) - ); - } + _textMinSize = p.textMinSize.value_or(_textMinSize); addProperty(_textMinSize); - if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) { - _textMaxSize = static_cast( - dictionary.value(LabelMaxSizeInfo.identifier) - ); - } + _textMaxSize = p.textMaxSize.value_or(_textMaxSize); addProperty(_textMaxSize); } - if (dictionary.hasKey(TransformationMatrixInfo.identifier)) { - _transformationMatrix = dictionary.value( - TransformationMatrixInfo.identifier - ); - } + _transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix); - if (dictionary.hasKey(FadeInDistancesInfo.identifier)) { - glm::dvec2 v = dictionary.value(FadeInDistancesInfo.identifier); - _fadeInDistance = v; - _disableFadeInDistance = false; + if (p.fadeInDistances.has_value()) { + _fadeInDistance = *p.fadeInDistances; addProperty(_fadeInDistance); + + _disableFadeInDistance = false; addProperty(_disableFadeInDistance); } - if (dictionary.hasKey(BillboardMaxSizeInfo.identifier)) { - _billboardMaxSize = static_cast( - dictionary.value(BillboardMaxSizeInfo.identifier) - ); - } + _billboardMaxSize = p.billboardMaxSize.value_or(_billboardMaxSize); addProperty(_billboardMaxSize); - if (dictionary.hasKey(BillboardMinSizeInfo.identifier)) { - _billboardMinSize = static_cast( - dictionary.value(BillboardMinSizeInfo.identifier) - ); - } + _billboardMinSize = p.billboardMinSize.value_or(_billboardMinSize); addProperty(_billboardMinSize); - if (dictionary.hasKey(CorrectionSizeEndDistanceInfo.identifier)) { - _correctionSizeEndDistance = static_cast( - dictionary.value(CorrectionSizeEndDistanceInfo.identifier) - ); - } + _correctionSizeEndDistance = + p.correctionSizeEndDistance.value_or(_correctionSizeEndDistance); addProperty(_correctionSizeEndDistance); - if (dictionary.hasKey(CorrectionSizeFactorInfo.identifier)) { - _correctionSizeFactor = static_cast( - dictionary.value(CorrectionSizeFactorInfo.identifier) - ); - + _correctionSizeFactor = p.correctionSizeFactor.value_or(_correctionSizeFactor); + if (p.correctionSizeFactor.has_value()) { addProperty(_correctionSizeFactor); } - if (dictionary.hasKey(PixelSizeControlInfo.identifier)) { - _pixelSizeControl = dictionary.value(PixelSizeControlInfo.identifier); + _pixelSizeControl = p.enablePixelSizeControl.value_or(_pixelSizeControl); + if (p.enablePixelSizeControl.has_value()) { addProperty(_pixelSizeControl); } @@ -759,9 +585,7 @@ RenderableBillboardsCloud::RenderableBillboardsCloud(const ghoul::Dictionary& di }); addProperty(_setRangeFromData); - if (dictionary.hasKey(UseLinearFiltering.identifier)) { - _useLinearFiltering = dictionary.value(UseLinearFiltering.identifier); - } + _useLinearFiltering = p.useLinearFiltering.value_or(_useLinearFiltering); _useLinearFiltering.onChange([&]() { _dataIsDirty = true; }); addProperty(_useLinearFiltering); } diff --git a/modules/digitaluniverse/rendering/renderabledumeshes.cpp b/modules/digitaluniverse/rendering/renderabledumeshes.cpp index f18785a193..64b6dbc467 100644 --- a/modules/digitaluniverse/rendering/renderabledumeshes.cpp +++ b/modules/digitaluniverse/rendering/renderabledumeshes.cpp @@ -43,8 +43,9 @@ #include #include #include -#include #include +#include +#include namespace { constexpr const char* _loggerCat = "RenderableDUMeshes"; @@ -54,16 +55,6 @@ namespace { "modelViewTransform", "projectionTransform", "alphaValue", "color" }; - constexpr const char* KeyFile = "File"; - constexpr const char* keyUnit = "Unit"; - constexpr const char* MeterUnit = "m"; - constexpr const char* KilometerUnit = "Km"; - constexpr const char* ParsecUnit = "pc"; - constexpr const char* KiloparsecUnit = "Kpc"; - constexpr const char* MegaparsecUnit = "Mpc"; - constexpr const char* GigaparsecUnit = "Gpc"; - constexpr const char* GigalightyearUnit = "Gly"; - constexpr const int RenderOptionViewDirection = 0; constexpr const int RenderOptionPositionNormal = 1; @@ -139,84 +130,59 @@ namespace { "Render Option", "Debug option for rendering of billboards and texts." }; + + struct [[codegen::Dictionary(RenderableDUMeshes)]] Parameters { + // The path to the SPECK file that contains information about the astronomical + // object being rendered + std::string file; + + // [[codegen::verbatim(DrawLabelInfo.description)]] + std::optional drawLabels; + + enum class 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")]], + Gigalightyears [[codegen::key("Gly")]] + }; + std::optional unit; + + // [[codegen::verbatim(TextColorInfo.description)]] + std::optional textColor; + + // [[codegen::verbatim(TextOpacityInfo.description)]] + std::optional textOpacity; + + // [[codegen::verbatim(TextSizeInfo.description)]] + std::optional textSize; + + // [[codegen::verbatim(LabelFileInfo.description)]] + std::optional labelFile; + + // [[codegen::verbatim(LabelMinSizeInfo.description)]] + std::optional textMinSize; + + // [[codegen::verbatim(LabelMaxSizeInfo.description)]] + std::optional textMaxSize; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(MeshColorInfo.description)]] + std::optional> meshColor; + }; +#include "renderabledumeshes_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableDUMeshes::Documentation() { - using namespace documentation; - return { - "RenderableDUMeshes", - "digitaluniverse_renderabledumeshes", - { - { - "Type", - new StringEqualVerifier("RenderableDUMeshes"), - Optional::No - }, - { - KeyFile, - new StringVerifier, - Optional::No, - "The path to the SPECK file that contains information about the " - "astronomical object being rendered." - }, - { - DrawLabelInfo.identifier, - new BoolVerifier, - Optional::Yes, - DrawLabelInfo.description - }, - { - TextColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - TextColorInfo.description - }, - { - TextOpacityInfo.identifier, - new DoubleVerifier, - Optional::Yes, - TextOpacityInfo.description - }, - { - TextSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - TextSizeInfo.description - }, - { - LabelFileInfo.identifier, - new StringVerifier, - Optional::Yes, - LabelFileInfo.description - }, - { - LabelMinSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LabelMinSizeInfo.description - }, - { - LabelMaxSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LabelMaxSizeInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - }, - { - MeshColorInfo.identifier, - new Vector3ListVerifier, - Optional::No, - MeshColorInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "digitaluniverse_renderabledumeshes"; + return doc; } RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) @@ -231,24 +197,20 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) , _lineWidth(LineWidthInfo, 2.f, 0.f, 16.f) , _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableDUMeshes" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - if (dictionary.hasKey(KeyFile)) { - _speckFile = absPath(dictionary.value(KeyFile)); - _hasSpeckFile = true; - _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); - addProperty(_drawElements); - } + _speckFile = absPath(p.file); + _hasSpeckFile = true; + _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); + addProperty(_drawElements); _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; } @@ -257,96 +219,69 @@ RenderableDUMeshes::RenderableDUMeshes(const ghoul::Dictionary& dictionary) } addProperty(_renderOption); - if (dictionary.hasKey(keyUnit)) { - std::string unit = dictionary.value(keyUnit); - if (unit == MeterUnit) { - _unit = Meter; - } - else if (unit == KilometerUnit) { - _unit = Kilometer; - } - else if (unit == ParsecUnit) { - _unit = Parsec; - } - else if (unit == KiloparsecUnit) { - _unit = Kiloparsec; - } - else if (unit == MegaparsecUnit) { - _unit = Megaparsec; - } - else if (unit == GigaparsecUnit) { - _unit = Gigaparsec; - } - else if (unit == GigalightyearUnit) { - _unit = GigalightYears; - } - else { - LWARNING("No unit given for RenderableDUMeshes. Using meters as units."); - _unit = Meter; + if (p.unit.has_value()) { + switch (*p.unit) { + case Parameters::Unit::Meter: + _unit = Meter; + break; + case Parameters::Unit::Kilometer: + _unit = Kilometer; + break; + case Parameters::Unit::Parsec: + _unit = Parsec; + break; + case Parameters::Unit::Kiloparsec: + _unit = Kiloparsec; + break; + case Parameters::Unit::MegaParsec: + _unit = Megaparsec; + break; + case Parameters::Unit::Gigaparsec: + _unit = Gigaparsec; + break; + case Parameters::Unit::Gigalightyears: + _unit = GigalightYears; + break; } } + else { + LWARNING("No unit given for RenderableDUMeshes. Using meters as units."); + _unit = Meter; + } - if (dictionary.hasValue(LineWidthInfo.identifier)) { - _lineWidth = static_cast( - dictionary.value(LineWidthInfo.identifier) - ); - } + _lineWidth = p.lineWidth.value_or(_lineWidth); addProperty(_lineWidth); - if (dictionary.hasKey(DrawLabelInfo.identifier)) { - _drawLabels = dictionary.value(DrawLabelInfo.identifier); - } + _drawLabels = p.drawLabels.value_or(_drawLabels); addProperty(_drawLabels); - if (dictionary.hasKey(LabelFileInfo.identifier)) { - _labelFile = absPath(dictionary.value(LabelFileInfo.identifier)); + if (p.labelFile.has_value()) { + _labelFile = absPath(*p.labelFile); _hasLabel = true; - if (dictionary.hasKey(TextColorInfo.identifier)) { - _textColor = dictionary.value(TextColorInfo.identifier); - _hasLabel = true; - } + _textColor = p.textColor.value_or(_textColor); + _hasLabel = p.textColor.has_value(); _textColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_textColor); _textColor.onChange([&]() { _textColorIsDirty = true; }); - if (dictionary.hasKey(TextOpacityInfo.identifier)) { - _textOpacity = static_cast( - dictionary.value(TextOpacityInfo.identifier) - ); - } + _textOpacity = p.textOpacity.value_or(_textOpacity); addProperty(_textOpacity); - if (dictionary.hasKey(TextSizeInfo.identifier)) { - _textSize = static_cast( - dictionary.value(TextSizeInfo.identifier) - ); - } + _textSize = p.textSize.value_or(_textSize); addProperty(_textSize); - if (dictionary.hasKey(LabelMinSizeInfo.identifier)) { - _textMinSize = static_cast( - floor(dictionary.value(LabelMinSizeInfo.identifier)) - ); - } + _textMinSize = p.textMinSize.value_or(_textMinSize); addProperty(_textMinSize); - if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) { - _textMaxSize = static_cast( - floor(dictionary.value(LabelMaxSizeInfo.identifier)) - ); - } + _textMaxSize = p.textMaxSize.value_or(_textMaxSize); addProperty(_textMaxSize); } - if (dictionary.hasKey(MeshColorInfo.identifier)) { - ghoul::Dictionary colorDict = dictionary.value( - MeshColorInfo.identifier - ); - for (int i = 0; i < static_cast(colorDict.size()); ++i) { - _meshColorMap.insert( - { i + 1, colorDict.value(std::to_string(i + 1)) } - ); + 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] }); } } } diff --git a/modules/digitaluniverse/rendering/renderableplanescloud.cpp b/modules/digitaluniverse/rendering/renderableplanescloud.cpp index 71d7dc33bf..97f27b3264 100644 --- a/modules/digitaluniverse/rendering/renderableplanescloud.cpp +++ b/modules/digitaluniverse/rendering/renderableplanescloud.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include namespace { @@ -52,16 +53,6 @@ namespace { "modelViewProjectionTransform", "alphaValue", "fadeInValue", "galaxyTexture" }; - constexpr const char* KeyFile = "File"; - constexpr const char* keyUnit = "Unit"; - constexpr const char* MeterUnit = "m"; - constexpr const char* KilometerUnit = "Km"; - constexpr const char* ParsecUnit = "pc"; - constexpr const char* KiloparsecUnit = "Kpc"; - constexpr const char* MegaparsecUnit = "Mpc"; - constexpr const char* GigaparsecUnit = "Gpc"; - constexpr const char* GigalightyearUnit = "Gly"; - constexpr int8_t CurrentCacheVersion = 2; constexpr double PARSEC = 0.308567756E17; @@ -180,123 +171,83 @@ namespace { "object." }; + struct [[codegen::Dictionary(RenderablePlanesCloud)]] Parameters { + // The path to the SPECK file that contains information about the astronomical + // object being rendered + std::optional file; + + // [[codegen::verbatim(ScaleFactorInfo.description)]] + std::optional scaleFactor; + + // [[codegen::verbatim(TextColorInfo.description)]] + std::optional textColor; + + // [[codegen::verbatim(TextOpacityInfo.description)]] + std::optional textOpacity; + + // [[codegen::verbatim(TextSizeInfo.description)]] + std::optional textSize; + + // [[codegen::verbatim(LabelFileInfo.description)]] + std::optional labelFile; + + // [[codegen::verbatim(LabelMinSizeInfo.description)]] + std::optional textMinSize; + + // [[codegen::verbatim(LabelMaxSizeInfo.description)]] + std::optional textMaxSize; + + // [[codegen::verbatim(TransformationMatrixInfo.description)]] + std::optional transformationMatrix; + + enum class BlendMode { + Normal, + Additive + }; + + // [[codegen::verbatim(BlendModeInfo.description)]] + std::optional blendMode; + + enum class 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")]], + Gigalightyears [[codegen::key("Gly")]] + }; + std::optional unit; + + // [[codegen::verbatim(TexturePathInfo.description)]] + std::string texturePath; + + // [[codegen::verbatim(LuminosityInfo.description)]] + std::optional luminosity; + + // [[codegen::verbatim(ScaleLuminosityInfo.description)]] + std::optional scaleLuminosity; + + // [[codegen::verbatim(FadeInDistancesInfo.description)]] + std::optional fadeInDistances; + + // [[codegen::verbatim(DisableFadeInInfo.description)]] + std::optional disableFadeIn; + + // [[codegen::verbatim(PlaneMinSizeInfo.description)]] + std::optional planeMinSize; + }; +#include "renderableplanescloud_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderablePlanesCloud::Documentation() { - using namespace documentation; - return { - "RenderablePlanesCloud", - "digitaluniverse_RenderablePlanesCloud", - { - { - "Type", - new StringEqualVerifier("RenderablePlanesCloud"), - Optional::No - }, - { - KeyFile, - new StringVerifier, - Optional::Yes, - "The path to the SPECK file that contains information about the " - "astronomical object being rendered." - }, - { - ScaleFactorInfo.identifier, - new DoubleVerifier, - Optional::Yes, - ScaleFactorInfo.description - }, - { - TextColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - TextColorInfo.description - }, - { - TextOpacityInfo.identifier, - new DoubleVerifier, - Optional::Yes, - TextOpacityInfo.description - }, - { - TextSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - TextSizeInfo.description - }, - { - LabelFileInfo.identifier, - new StringVerifier, - Optional::Yes, - LabelFileInfo.description - }, - { - LabelMinSizeInfo.identifier, - new IntVerifier, - Optional::Yes, - LabelMinSizeInfo.description - }, - { - LabelMaxSizeInfo.identifier, - new IntVerifier, - Optional::Yes, - LabelMaxSizeInfo.description - }, - { - TransformationMatrixInfo.identifier, - new Matrix4x4Verifier, - Optional::Yes, - TransformationMatrixInfo.description - }, - { - BlendModeInfo.identifier, - new StringInListVerifier({ "Normal", "Additive" }), - Optional::Yes, - BlendModeInfo.description, // + " The default value is 'Normal'.", - }, - { - TexturePathInfo.identifier, - new StringVerifier, - Optional::No, - TexturePathInfo.description, - }, - { - LuminosityInfo.identifier, - new StringVerifier, - Optional::Yes, - LuminosityInfo.description, - }, - { - ScaleFactorInfo.identifier, - new DoubleVerifier, - Optional::Yes, - ScaleFactorInfo.description, - }, - { - FadeInDistancesInfo.identifier, - new DoubleVector2Verifier, - Optional::Yes, - FadeInDistancesInfo.description - }, - { - DisableFadeInInfo.identifier, - new BoolVerifier, - Optional::Yes, - DisableFadeInInfo.description - }, - { - PlaneMinSizeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - PlaneMinSizeInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "digitaluniverse_RenderablePlanesCloud"; + return doc; } - RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 300000.f) @@ -315,16 +266,12 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary , _planeMinSize(PlaneMinSizeInfo, 0.5, 0.0, 500.0) , _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderablePlanesCloud" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); - if (dictionary.hasKey(KeyFile)) { - _speckFile = absPath(dictionary.value(KeyFile)); + if (p.file.has_value()) { + _speckFile = absPath(*p.file); _hasSpeckFile = true; _drawElements.onChange([&]() { _hasSpeckFile = !_hasSpeckFile; }); addProperty(_drawElements); @@ -337,32 +284,29 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary addProperty(_renderOption); //_renderOption.set(1); - if (dictionary.hasKey(keyUnit)) { - const std::string& unit = dictionary.value(keyUnit); - if (unit == MeterUnit) { - _unit = Meter; - } - else if (unit == KilometerUnit) { - _unit = Kilometer; - } - else if (unit == ParsecUnit) { - _unit = Parsec; - } - else if (unit == KiloparsecUnit) { - _unit = Kiloparsec; - } - else if (unit == MegaparsecUnit) { - _unit = Megaparsec; - } - else if (unit == GigaparsecUnit) { - _unit = Gigaparsec; - } - else if (unit == GigalightyearUnit) { - _unit = GigalightYears; - } - else { - LWARNING("No unit given for RenderablePlanesCloud. Using meters as units."); - _unit = Meter; + if (p.unit.has_value()) { + switch (*p.unit) { + case Parameters::Unit::Meter: + _unit = Meter; + break; + case Parameters::Unit::Kilometer: + _unit = Kilometer; + break; + case Parameters::Unit::Parsec: + _unit = Parsec; + break; + case Parameters::Unit::Kiloparsec: + _unit = Kiloparsec; + break; + case Parameters::Unit::Megaparsec: + _unit = Megaparsec; + break; + case Parameters::Unit::Gigaparsec: + _unit = Gigaparsec; + break; + case Parameters::Unit::Gigalightyears: + _unit = GigalightYears; + break; } } else { @@ -370,60 +314,30 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary _unit = Meter; } - if (dictionary.hasKey(ScaleFactorInfo.identifier)) { - _scaleFactor = static_cast( - dictionary.value(ScaleFactorInfo.identifier) - ); - } + _scaleFactor = p.scaleFactor.value_or(_scaleFactor); addProperty(_scaleFactor); - _scaleFactor.onChange([&]() { - _dataIsDirty = true; - }); + _scaleFactor.onChange([&]() { _dataIsDirty = true; }); - if (dictionary.hasKey(LabelFileInfo.identifier)) { - _labelFile = absPath(dictionary.value(LabelFileInfo.identifier)); + if (p.labelFile.has_value()) { + _labelFile = absPath(*p.labelFile); _hasLabel = true; - if (dictionary.hasKey(TextColorInfo.identifier)) { - _textColor = dictionary.value(TextColorInfo.identifier); - _hasLabel = true; - } + _textColor = p.textColor.value_or(_textColor); _textColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_textColor); _textColor.onChange([&]() { _textColorIsDirty = true; }); - if (dictionary.hasKey(TextOpacityInfo.identifier)) { - _textOpacity = static_cast( - dictionary.value(TextOpacityInfo.identifier) - ); - } + _textOpacity = p.textOpacity.value_or(_textOpacity); addProperty(_textOpacity); - if (dictionary.hasKey(TextSizeInfo.identifier)) { - _textSize = static_cast( - dictionary.value(TextSizeInfo.identifier) - ); - } + _textSize = p.textSize.value_or(_textSize); addProperty(_textSize); - if (dictionary.hasKey(LabelMinSizeInfo.identifier)) { - _textMinSize = static_cast( - dictionary.value(LabelMinSizeInfo.identifier) - ); - } - - if (dictionary.hasKey(LabelMaxSizeInfo.identifier)) { - _textMaxSize = static_cast( - dictionary.value(LabelMaxSizeInfo.identifier) - ); - } + _textMinSize = p.textMinSize.value_or(_textMinSize); + _textMaxSize = p.textMaxSize.value_or(_textMaxSize); } - if (dictionary.hasKey(TransformationMatrixInfo.identifier)) { - _transformationMatrix = dictionary.value( - TransformationMatrixInfo.identifier - ); - } + _transformationMatrix = p.transformationMatrix.value_or(_transformationMatrix); _blendMode.addOptions({ { BlendModeNormal, "Normal" }, @@ -442,39 +356,33 @@ RenderablePlanesCloud::RenderablePlanesCloud(const ghoul::Dictionary& dictionary } }); - if (dictionary.hasKey(BlendModeInfo.identifier)) { - const std::string& v = dictionary.value(BlendModeInfo.identifier); - if (v == "Normal") { - _blendMode = BlendModeNormal; - } - else if (v == "Additive") { - _blendMode = BlendModeAdditive; + if (p.blendMode.has_value()) { + switch (*p.blendMode) { + case Parameters::BlendMode::Normal: + _blendMode = BlendModeNormal; + break; + case Parameters::BlendMode::Additive: + _blendMode = BlendModeAdditive; + break; } } - _texturesPath = absPath(dictionary.value(TexturePathInfo.identifier)); + _texturesPath = absPath(p.texturePath); - if (dictionary.hasKey(LuminosityInfo.identifier)) { - _luminosityVar = dictionary.value(LuminosityInfo.identifier); - } + _luminosityVar = p.luminosity.value_or(_luminosityVar); + _sluminosity = p.scaleLuminosity.value_or(_sluminosity); - if (dictionary.hasKey(ScaleLuminosityInfo.identifier)) { - _sluminosity = static_cast( - dictionary.value(ScaleLuminosityInfo.identifier) - ); - } - if (dictionary.hasKey(FadeInDistancesInfo.identifier)) { - _fadeInDistance = dictionary.value(FadeInDistancesInfo.identifier); + if (p.fadeInDistances.has_value()) { + _fadeInDistance = *p.fadeInDistances; _disableFadeInDistance = false; addProperty(_fadeInDistance); addProperty(_disableFadeInDistance); } - if (dictionary.hasKey(PlaneMinSizeInfo.identifier)) { - _planeMinSize = static_cast( - dictionary.value(PlaneMinSizeInfo.identifier) - ); + _planeMinSize = p.planeMinSize.value_or(_planeMinSize); + + if (p.planeMinSize.has_value()) { addProperty(_planeMinSize); } } diff --git a/modules/digitaluniverse/rendering/renderablepoints.cpp b/modules/digitaluniverse/rendering/renderablepoints.cpp index cb9332404b..e56a454603 100644 --- a/modules/digitaluniverse/rendering/renderablepoints.cpp +++ b/modules/digitaluniverse/rendering/renderablepoints.cpp @@ -44,6 +44,7 @@ #include #include #include +#include namespace { constexpr const char* _loggerCat = "RenderablePoints"; @@ -53,17 +54,6 @@ namespace { "spriteTexture", "hasColorMap" }; - constexpr const char* KeyFile = "File"; - constexpr const char* keyColor = "Color"; - constexpr const char* keyUnit = "Unit"; - constexpr const char* MeterUnit = "m"; - constexpr const char* KilometerUnit = "Km"; - constexpr const char* ParsecUnit = "pc"; - constexpr const char* KiloparsecUnit = "Kpc"; - constexpr const char* MegaparsecUnit = "Mpc"; - constexpr const char* GigaparsecUnit = "Gpc"; - constexpr const char* GigalightyearUnit = "Gly"; - constexpr int8_t CurrentCacheVersion = 1; constexpr double PARSEC = 0.308567756E17; @@ -91,58 +81,46 @@ namespace { "Color Map File", "The path to the color map file of the astronomical onject." }; + + struct [[codegen::Dictionary(RenderablePoints)]] Parameters { + // The path to the SPECK file that contains information about the astronomical + // object being rendered + std::string file; + + // Astronomical Object Color (r,g,b) + glm::vec3 color; + + enum class 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")]], + Gigalightyears [[codegen::key("Gly")]] + }; + std::optional unit; + + // [[codegen::verbatim(SpriteTextureInfo.description)]] + std::optional texture; + + // [[codegen::verbatim(ScaleFactorInfo.description)]] + std::optional scaleFactor; + + // [[codegen::verbatim(ColorMapInfo.description)]] + std::optional colorMap; + }; +#include "renderablepoints_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderablePoints::Documentation() { - using namespace documentation; - return { - "RenderablePoints", - "digitaluniverse_renderablepoints", - { - { - "Type", - new StringEqualVerifier("RenderablePoints"), - Optional::No - }, - { - KeyFile, - new StringVerifier, - Optional::No, - "The path to the SPECK file that contains information about the " - "astronomical object being rendered." - }, - { - keyColor, - new Vector3Verifier, - Optional::No, - "Astronomical Object Color (r,g,b)." - }, - { - SpriteTextureInfo.identifier, - new StringVerifier, - Optional::Yes, - SpriteTextureInfo.description - }, - { - ScaleFactorInfo.identifier, - new DoubleVerifier, - Optional::Yes, - ScaleFactorInfo.description - }, - { - ColorMapInfo.identifier, - new StringVerifier, - Optional::Yes, - ColorMapInfo.description - }, - - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "digitaluniverse_renderablepoints"; + return doc; } - RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary) : Renderable(dictionary) , _scaleFactor(ScaleFactorInfo, 1.f, 0.f, 64.f) @@ -150,59 +128,52 @@ RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary) ColorInfo, glm::vec3(1.f, 0.4f, 0.2f), glm::vec3(0.f, 0.f, 0.f), - glm::vec3(1.0f, 1.0f, 1.0f) + glm::vec3(1.f, 1.f, 1.f) ) , _spriteTexturePath(SpriteTextureInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderablePoints" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - _speckFile = absPath(dictionary.value(KeyFile)); + _speckFile = absPath(p.file); - if (dictionary.hasKey(keyUnit)) { - const std::string& unit = dictionary.value(keyUnit); - if (unit == MeterUnit) { - _unit = Meter; - } - else if (unit == KilometerUnit) { - _unit = Kilometer; - } - else if (unit == ParsecUnit) { - _unit = Parsec; - } - else if (unit == KiloparsecUnit) { - _unit = Kiloparsec; - } - else if (unit == MegaparsecUnit) { - _unit = Megaparsec; - } - else if (unit == GigaparsecUnit) { - _unit = Gigaparsec; - } - else if (unit == GigalightyearUnit) { - _unit = GigalightYears; - } - else { - LWARNING("No unit given for RenderablePoints. Using meters as units."); - _unit = Meter; + if (p.unit.has_value()) { + switch (*p.unit) { + case Parameters::Unit::Meter: + _unit = Meter; + break; + case Parameters::Unit::Kilometer: + _unit = Kilometer; + break; + case Parameters::Unit::Parsec: + _unit = Parsec; + break; + case Parameters::Unit::Kiloparsec: + _unit = Kiloparsec; + break; + case Parameters::Unit::Megaparsec: + _unit = Megaparsec; + break; + case Parameters::Unit::Gigaparsec: + _unit = Gigaparsec; + break; + case Parameters::Unit::Gigalightyears: + _unit = GigalightYears; + break; } } - - if (dictionary.hasKey(keyColor)) { - _pointColor = dictionary.value(keyColor); + else { + LWARNING("No unit given for RenderablePoints. Using meters as units."); + _unit = Meter; } + + _pointColor = p.color; addProperty(_pointColor); - if (dictionary.hasKey(SpriteTextureInfo.identifier)) { - _spriteTexturePath = absPath(dictionary.value( - SpriteTextureInfo.identifier - )); + if (p.texture.has_value()) { + _spriteTexturePath = absPath(*p.texture); _spriteTextureFile = std::make_unique( _spriteTexturePath ); @@ -216,18 +187,12 @@ RenderablePoints::RenderablePoints(const ghoul::Dictionary& dictionary) _hasSpriteTexture = true; } - if (dictionary.hasKey(ColorMapInfo.identifier)) { - _colorMapFile = absPath(dictionary.value( - ColorMapInfo.identifier - )); + if (p.colorMap.has_value()) { + _colorMapFile = absPath(*p.colorMap); _hasColorMapFile = true; } - if (dictionary.hasKey(ScaleFactorInfo.identifier)) { - _scaleFactor = static_cast( - dictionary.value(ScaleFactorInfo.identifier) - ); - } + _scaleFactor = p.scaleFactor.value_or(_scaleFactor); addProperty(_scaleFactor); } diff --git a/modules/exoplanets/rendering/renderableorbitdisc.cpp b/modules/exoplanets/rendering/renderableorbitdisc.cpp index 15bd28072f..1ad0e6a85b 100644 --- a/modules/exoplanets/rendering/renderableorbitdisc.cpp +++ b/modules/exoplanets/rendering/renderableorbitdisc.cpp @@ -81,11 +81,6 @@ documentation::Documentation RenderableOrbitDisc::Documentation() { "Renderable Orbit Disc", "exoplanets_renderable_orbit_disc", { - { - "Type", - new StringEqualVerifier("RenderableOrbitDisc"), - Optional::No - }, { TextureInfo.identifier, new StringVerifier, diff --git a/modules/exoplanets/tasks/exoplanetsdatapreparationtask.cpp b/modules/exoplanets/tasks/exoplanetsdatapreparationtask.cpp index 46b8953f9c..e4fb0a4801 100644 --- a/modules/exoplanets/tasks/exoplanetsdatapreparationtask.cpp +++ b/modules/exoplanets/tasks/exoplanetsdatapreparationtask.cpp @@ -447,12 +447,6 @@ documentation::Documentation ExoplanetsDataPreparationTask::documentation() { "ExoplanetsDataPreparationTask", "exoplanets_data_preparation_task", { - { - "Type", - new StringEqualVerifier("ExoplanetsDataPreparationTask"), - Optional::No, - "" - }, { KeyInputDataFile, new StringAnnotationVerifier("A valid filepath"), diff --git a/modules/gaia/rendering/renderablegaiastars.cpp b/modules/gaia/rendering/renderablegaiastars.cpp index 4c2bc9cdcc..722f90f8b2 100644 --- a/modules/gaia/rendering/renderablegaiastars.cpp +++ b/modules/gaia/rendering/renderablegaiastars.cpp @@ -310,11 +310,6 @@ documentation::Documentation RenderableGaiaStars::Documentation() { "RenderableGaiaStars", "gaiamission_renderablegaiastars", { - { - "Type", - new StringEqualVerifier("RenderableGaiaStars"), - Optional::No - }, { FilePathInfo.identifier, new StringVerifier, diff --git a/modules/gaia/tasks/constructoctreetask.cpp b/modules/gaia/tasks/constructoctreetask.cpp index 7d1e5621e0..a4edef1372 100644 --- a/modules/gaia/tasks/constructoctreetask.cpp +++ b/modules/gaia/tasks/constructoctreetask.cpp @@ -548,11 +548,6 @@ documentation::Documentation ConstructOctreeTask::Documentation() { "ConstructOctreeTask", "gaiamission_constructoctreefrombin", { - { - "Type", - new StringEqualVerifier("ConstructOctreeTask"), - Optional::No - }, { KeyInFileOrFolderPath, new StringVerifier, diff --git a/modules/gaia/tasks/readfitstask.cpp b/modules/gaia/tasks/readfitstask.cpp index 461d352f34..5139ab6366 100644 --- a/modules/gaia/tasks/readfitstask.cpp +++ b/modules/gaia/tasks/readfitstask.cpp @@ -327,11 +327,6 @@ documentation::Documentation ReadFitsTask::Documentation() { "ReadFitsFile", "gaiamission_fitsfiletorawdata", { - { - "Type", - new StringEqualVerifier("ReadFitsTask"), - Optional::No - }, { KeyInFileOrFolderPath, new StringVerifier, diff --git a/modules/gaia/tasks/readspecktask.cpp b/modules/gaia/tasks/readspecktask.cpp index 89f2970fba..8db543c2de 100644 --- a/modules/gaia/tasks/readspecktask.cpp +++ b/modules/gaia/tasks/readspecktask.cpp @@ -98,11 +98,6 @@ documentation::Documentation ReadSpeckTask::Documentation() { "ReadSpeckTask", "gaiamission_speckfiletorawdata", { - { - "Type", - new StringEqualVerifier("ReadSpeckTask"), - Optional::No - }, { KeyInFilePath, new StringVerifier, diff --git a/modules/globebrowsing/globebrowsingmodule.cpp b/modules/globebrowsing/globebrowsingmodule.cpp index 9e02310d84..ffc5aa159b 100644 --- a/modules/globebrowsing/globebrowsingmodule.cpp +++ b/modules/globebrowsing/globebrowsingmodule.cpp @@ -35,9 +35,10 @@ #include #include #include +#include +#include #include #include -#include #include #include #include @@ -158,6 +159,29 @@ namespace { return result; } + + struct [[codegen::Dictionary(GlobeBrowsingModule)]] Parameters { + // [[codegen::verbatim(WMSCacheEnabledInfo.description)]] + std::optional cacheEnabled [[codegen::key("WMSCacheEnabled")]]; + + // [[codegen::verbatim(OfflineModeInfo.description)]] + std::optional offlineMode; + + // [[codegen::verbatim(WMSCacheLocationInfo.description)]] + std::optional cacheLocation [[codegen::key("WMSCacheLocation")]]; + + // [[codegen::verbatim(WMSCacheSizeInfo.description)]] + std::optional wmsCacheSize [[codegen::key("WMSCacheSize")]]; + + // [[codegen::verbatim(TileCacheSizeInfo.description)]] + std::optional tileCacheSize; + + // If you know what you are doing and you have WMS caching *disabled* but offline + // mode *enabled*, you can set this value to 'true' to silence a warning that you + // would otherwise get at startup + std::optional noWarning; + }; +#include "globebrowsingmodule_codegen.cpp" } // namespace namespace openspace { @@ -180,30 +204,13 @@ GlobeBrowsingModule::GlobeBrowsingModule() void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) { using namespace globebrowsing; - if (dict.hasValue(WMSCacheEnabledInfo.identifier)) { - _wmsCacheEnabled = dict.value(WMSCacheEnabledInfo.identifier); - } - if (dict.hasValue(OfflineModeInfo.identifier)) { - _offlineMode = dict.value(OfflineModeInfo.identifier); - } - if (dict.hasValue(WMSCacheLocationInfo.identifier)) { - _wmsCacheLocation = dict.value(WMSCacheLocationInfo.identifier); - } - if (dict.hasValue(WMSCacheSizeInfo.identifier)) { - _wmsCacheSizeMB = static_cast( - dict.value(WMSCacheSizeInfo.identifier) - ); - } - if (dict.hasValue(TileCacheSizeInfo.identifier)) { - _tileCacheSizeMB = static_cast( - dict.value(TileCacheSizeInfo.identifier) - ); - } - - // Sanity check - const bool noWarning = dict.hasValue("NoWarning") ? - dict.value("NoWarning") : - false; + const Parameters p = codegen::bake(dict); + _wmsCacheEnabled = p.cacheEnabled.value_or(_wmsCacheEnabled); + _offlineMode = p.offlineMode.value_or(_offlineMode); + _wmsCacheLocation = p.cacheLocation.value_or(_wmsCacheLocation); + _wmsCacheSizeMB = p.wmsCacheSize.value_or(_wmsCacheSizeMB); + _tileCacheSizeMB = p.tileCacheSize.value_or(_tileCacheSizeMB); + const bool noWarning = p.noWarning.value_or(false); if (!_wmsCacheEnabled && _offlineMode && !noWarning) { LWARNINGC( diff --git a/modules/globebrowsing/src/dashboarditemglobelocation.cpp b/modules/globebrowsing/src/dashboarditemglobelocation.cpp index 18d02e3a76..8c53564982 100644 --- a/modules/globebrowsing/src/dashboarditemglobelocation.cpp +++ b/modules/globebrowsing/src/dashboarditemglobelocation.cpp @@ -72,11 +72,6 @@ documentation::Documentation DashboardItemGlobeLocation::Documentation() { "DashboardItem Globe Location", "globebrowsing_dashboarditem_globelocation", { - { - "Type", - new StringEqualVerifier("DashboardItemGlobeLocation"), - Optional::No - }, { FontNameInfo.identifier, new StringVerifier, diff --git a/modules/globebrowsing/src/globetranslation.cpp b/modules/globebrowsing/src/globetranslation.cpp index 2ae998fa73..633198ba48 100644 --- a/modules/globebrowsing/src/globetranslation.cpp +++ b/modules/globebrowsing/src/globetranslation.cpp @@ -85,11 +85,6 @@ documentation::Documentation GlobeTranslation::Documentation() { "Globe Translation", "space_translation_globetranslation", { - { - "Type", - new StringEqualVerifier("GlobeTranslation"), - Optional::No - }, { GlobeInfo.identifier, new StringAnnotationVerifier( diff --git a/modules/globebrowsing/src/layer.cpp b/modules/globebrowsing/src/layer.cpp index e28d8e68d7..51a3ebc990 100644 --- a/modules/globebrowsing/src/layer.cpp +++ b/modules/globebrowsing/src/layer.cpp @@ -42,15 +42,7 @@ namespace { constexpr const char* KeyName = "Name"; constexpr const char* KeyDesc = "Description"; constexpr const char* KeyLayerGroupID = "LayerGroupID"; - constexpr const char* KeySettings = "Settings"; constexpr const char* KeyAdjustment = "Adjustment"; - constexpr const char* KeyPadTiles = "PadTiles"; - - constexpr const char* KeyOpacity = "Opacity"; - constexpr const char* KeyGamma = "Gamma"; - constexpr const char* KeyMultiplier = "Multiplier"; - constexpr const char* KeyOffset = "Offset"; - constexpr openspace::properties::Property::PropertyInfo TypeInfo = { "Type", @@ -102,114 +94,94 @@ namespace { "example: Earth is a special place", openspace::properties::Property::Visibility::Hidden }; + + struct [[codegen::Dictionary(Layer), codegen::noexhaustive()]] Parameters { + // The unique identifier for this layer. May not contain '.' or spaces + std::string identifier; + + // A human-readable name for the user interface. If this is omitted, the + // identifier is used instead + std::optional name; + + // A human-readable description of the layer to be used in informational texts + // presented to the user + std::optional description; + + // [[codegen::verbatim(ColorInfo.description)]] + std::optional color; + + // Specifies the type of layer that is to be added. If this value is not + // specified, the layer is a DefaultTileLayer + std::optional type [[codegen::inlist("DefaultTileLayer", + "SingleImageTileLayer", "SizeReferenceTileLayer", "TemporalTileLayer", + "TileIndexTileLayer", "ByIndexTileLayer", "ByLevelTileLayer", "SolidColor")]]; + + // Determine whether the layer is enabled or not. If this value is not specified, + // the layer is disabled + std::optional enabled; + + // Determines whether the downloaded tiles should have a padding added to the + // borders + std::optional padTiles; + + struct Settings { + // The opacity value of the layer + std::optional opacity [[codegen::inrange(0.0, 1.0)]]; + + // The gamma value that is applied to each pixel of the layer + std::optional gamma; + + // The multiplicative factor that is applied to each pixel of the layer + std::optional multiplier; + + // An additive offset that is applied to each pixel of the layer + std::optional offset; + }; + // Specifies the render settings that should be applied to this layer + std::optional settings; + + struct LayerAdjustment { + enum class Type { + None, + ChromaKey, + TransferFunction + }; + + // Specifies the type of the adjustment that is applied + std::optional type; + + // Specifies the chroma key used when selecting 'ChromaKey' for the 'Type' + std::optional chromaKeyColor; + + // Specifies the tolerance to match the color to the chroma key when the + // 'ChromaKey' type is selected for the 'Type' + std::optional chromaKeyTolerance; + }; + // Parameters that set individual adjustment parameters for this layer + std::optional adjustment; + + enum class BlendMode { + Normal, + Multiply, + Add, + Subtract, + Color + }; + // Sets the blend mode of this layer to determine how it interacts with other + // layers on top of this + std::optional blendMode; + + // If the primary layer creation fails, this layer is used as a fallback + std::optional + fallback [[codegen::reference("globebrowsing_layer")]]; + }; +#include "layer_codegen.cpp" } // namespace documentation::Documentation Layer::Documentation() { - using namespace documentation; - return { - "Layer", - "globebrowsing_layer", - { - { - KeyIdentifier, - new StringVerifier, - Optional::No, - "The unique identifier for this layer. May not contain '.' or spaces." - }, - { - KeyName, - new StringVerifier, - Optional::Yes, - "A human-readable name for the user interface. If this is omitted, the " - "identifier is used instead." - }, - { - KeyDesc, - new StringVerifier, - Optional::Yes, - "A human-readable description of the layer to be used in informational " - "texts presented to the user." - }, - { - "Type", - new StringInListVerifier({ - "DefaultTileLayer", "SingleImageTileLayer", "SizeReferenceTileLayer", - "TemporalTileLayer", "TileIndexTileLayer", "ByIndexTileLayer", - "ByLevelTileLayer", "SolidColor" - }), - Optional::Yes, - "Specifies the type of layer that is to be added. If this value is not " - "specified, the layer is a DefaultTileLayer." - }, - { - EnabledInfo.identifier, - new BoolVerifier, - Optional::Yes, - "Determine whether the layer is enabled or not. If this value is not " - "specified, the layer is disabled." - }, - { - KeyPadTiles, - new BoolVerifier, - Optional::Yes, - "Determines whether the downloaded tiles should have a padding added to " - "the borders." - }, - { - KeySettings, - new TableVerifier({ - { - KeyOpacity, - new DoubleInRangeVerifier(0.0, 1.0), - Optional::Yes, - "The opacity value of the layer." - }, - { - KeyGamma, - new DoubleVerifier, - Optional::Yes, - "The gamma value that is applied to each pixel of the layer." - }, - { - KeyMultiplier, - new DoubleVerifier, - Optional::Yes, - "The multiplicative factor that is applied to each pixel of the " - "layer." - }, - { - KeyOffset, - new DoubleVerifier, - Optional::Yes, - "An additive offset that is applied to each pixel of the layer." - } - }), - Optional::Yes, - "Specifies the render settings that should be applied to this layer." - }, - { - KeyAdjustment, - new ReferencingVerifier("globebrowsing_layeradjustment"), - Optional::Yes, - "" - }, - { - BlendModeInfo.identifier, - new StringInListVerifier({ - "Normal", "Multiply", "Add", "Subtract", "Color" - }), - Optional::Yes, - "Sets the blend mode of this layer to determine how it interacts with " - "other layers on top of this." - }, - { - "Fallback", - new ReferencingVerifier("globebrowsing_layer"), - Optional::Yes, - "If the primary layer creation fails, this layer is used as a fallback" - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "globebrowsing_layer"; + return doc; } Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict, @@ -230,59 +202,40 @@ Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict, , _layerGroupId(id) { - documentation::testSpecificationAndThrow(Documentation(), layerDict, "Layer"); + const Parameters p = codegen::bake(layerDict); layergroupid::TypeID typeID; - if (layerDict.hasValue("Type")) { - const std::string& typeString = layerDict.value("Type"); - typeID = ghoul::from_string(typeString); + if (p.type.has_value()) { + typeID = ghoul::from_string(*p.type); + if (typeID == layergroupid::TypeID::Unknown) { + throw ghoul::RuntimeError("Unknown layer type!"); + } } else { typeID = layergroupid::TypeID::DefaultTileLayer; } - if (typeID == layergroupid::TypeID::Unknown) { - throw ghoul::RuntimeError("Unknown layer type!"); - } initializeBasedOnType(typeID, layerDict); - if (layerDict.hasValue(EnabledInfo.identifier)) { - _enabled = layerDict.value(EnabledInfo.identifier); - } + _enabled = p.enabled.value_or(_enabled); - if (layerDict.hasKey(KeyDesc)) { + if (p.description.has_value()) { _guiDescription = description(); addProperty(_guiDescription); } - bool padTiles = true; - if (layerDict.hasValue(KeyPadTiles)) { - padTiles = layerDict.value(KeyPadTiles); - } + const bool padTiles = p.padTiles.value_or(true); TileTextureInitData initData = tileTextureInitData(_layerGroupId, padTiles); _padTilePixelStartOffset = initData.tilePixelStartOffset; _padTilePixelSizeDifference = initData.tilePixelSizeDifference; - if (layerDict.hasValue(KeySettings)) { - ghoul::Dictionary dict = layerDict.value(KeySettings); - if (dict.hasValue(KeyOpacity)) { - _renderSettings.opacity = static_cast(dict.value(KeyOpacity)); - } - - if (dict.hasValue(KeyGamma)) { - _renderSettings.gamma = static_cast(dict.value(KeyGamma)); - } - - if (dict.hasValue(KeyMultiplier)) { - _renderSettings.multiplier = static_cast( - dict.value(KeyMultiplier) - ); - } - - if (dict.hasValue(KeyOffset)) { - _renderSettings.offset = static_cast(dict.value(KeyOffset)); - } + if (p.settings.has_value()) { + _renderSettings.opacity = p.settings->opacity.value_or(_renderSettings.opacity); + _renderSettings.gamma = p.settings->gamma.value_or(_renderSettings.gamma); + _renderSettings.multiplier = + p.settings->multiplier.value_or(_renderSettings.multiplier); + _renderSettings.offset = p.settings->offset.value_or(_renderSettings.offset); } if (layerDict.hasValue(KeyAdjustment)) { _layerAdjustment.setValuesFromDictionary( @@ -302,11 +255,24 @@ Layer::Layer(layergroupid::GroupID id, const ghoul::Dictionary& layerDict, } // Initialize blend mode - if (layerDict.hasValue(BlendModeInfo.identifier)) { - using namespace layergroupid; - std::string blendMode = layerDict.value(BlendModeInfo.identifier); - BlendModeID blendModeID = ghoul::from_string(blendMode); - _blendModeOption = static_cast(blendModeID); + if (p.blendMode.has_value()) { + switch (*p.blendMode) { + case Parameters::BlendMode::Normal: + _blendModeOption = static_cast(layergroupid::BlendModeID::Normal); + break; + case Parameters::BlendMode::Multiply: + _blendModeOption = static_cast(layergroupid::BlendModeID::Multiply); + break; + case Parameters::BlendMode::Add: + _blendModeOption = static_cast(layergroupid::BlendModeID::Add); + break; + case Parameters::BlendMode::Subtract: + _blendModeOption = static_cast(layergroupid::BlendModeID::Subtract); + break; + case Parameters::BlendMode::Color: + _blendModeOption = static_cast(layergroupid::BlendModeID::Color); + break; + } } else { _blendModeOption = static_cast(layergroupid::BlendModeID::Normal); diff --git a/modules/globebrowsing/src/renderableglobe.cpp b/modules/globebrowsing/src/renderableglobe.cpp index a87e2a3372..9f089d8a46 100644 --- a/modules/globebrowsing/src/renderableglobe.cpp +++ b/modules/globebrowsing/src/renderableglobe.cpp @@ -82,8 +82,6 @@ namespace { constexpr const char* KeyRadii = "Radii"; constexpr const char* KeyLayers = "Layers"; constexpr const char* KeyShadowGroup = "ShadowGroup"; - constexpr const char* KeyShadowSource = "Source"; - constexpr const char* KeyShadowCaster = "Caster"; constexpr const char* KeyLabels = "Labels"; const openspace::globebrowsing::AABB3 CullingFrustum{ @@ -468,12 +466,6 @@ documentation::Documentation RenderableGlobe::Documentation() { "RenderableGlobe", "globebrowsing_renderableglobe", { - { - "Type", - new StringEqualVerifier("RenderableGlobe"), - Optional::No, - "" - }, { KeyRadii, new OrVerifier({ new DoubleVector3Verifier, new DoubleVerifier }), diff --git a/modules/kameleon/ext/kameleon b/modules/kameleon/ext/kameleon index 8a5e966659..606edb945b 160000 --- a/modules/kameleon/ext/kameleon +++ b/modules/kameleon/ext/kameleon @@ -1 +1 @@ -Subproject commit 8a5e9666599e9578d50bf3801dd07a9edf95ccdb +Subproject commit 606edb945b62d0151f20270ddb2db4a9f558aaa1 diff --git a/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp b/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp index 54678d14cd..9e4cac12a5 100644 --- a/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp +++ b/modules/kameleonvolume/tasks/kameleondocumentationtask.cpp @@ -152,12 +152,6 @@ documentation::Documentation KameleonDocumentationTask::documentation() { "KameleonDocumentationTask", "kameleon_documentation_task", { - { - "Type", - new StringEqualVerifier("KameleonDocumentationTask"), - Optional::No, - "The type of this task" - }, { KeyInput, new StringAnnotationVerifier("A file path to a cdf file"), diff --git a/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp index dc94504423..ecd1bcccf5 100644 --- a/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp +++ b/modules/kameleonvolume/tasks/kameleonmetadatatojsontask.cpp @@ -75,12 +75,6 @@ documentation::Documentation KameleonMetadataToJsonTask::documentation() { "KameleonMetadataToJsonTask", "kameleon_metadata_to_json_task", { - { - "Type", - new StringEqualVerifier("KameleonMetadataToJsonTask"), - Optional::No, - "The type of this task" - }, { KeyInput, new StringAnnotationVerifier("A file path to a cdf file"), diff --git a/modules/kameleonvolume/tasks/kameleonvolumetorawtask.cpp b/modules/kameleonvolume/tasks/kameleonvolumetorawtask.cpp index 4eb568c56e..fd9c342afe 100644 --- a/modules/kameleonvolume/tasks/kameleonvolumetorawtask.cpp +++ b/modules/kameleonvolume/tasks/kameleonvolumetorawtask.cpp @@ -56,12 +56,6 @@ documentation::Documentation KameleonVolumeToRawTask::documentation() { "KameleonVolumeToRawTask", "kameleon_metadata_to_json_task", { - { - "Type", - new StringEqualVerifier("KameleonVolumeToRawTask"), - Optional::No, - "The type of this task", - }, { KeyInput, new StringAnnotationVerifier("A file path to a cdf file"), diff --git a/modules/space/rendering/planetgeometry.cpp b/modules/space/rendering/planetgeometry.cpp index a021da2cbb..ec68224b61 100644 --- a/modules/space/rendering/planetgeometry.cpp +++ b/modules/space/rendering/planetgeometry.cpp @@ -30,40 +30,29 @@ #include namespace { - constexpr const char* KeyType = "Type"; + struct [[codegen::Dictionary(PlanetGeometry)]] Parameters { + // The type of the PlanetGeometry that will can be constructed + std::string type; + }; +#include "planetgeometry_codegen.cpp" } // namespace namespace openspace::planetgeometry { documentation::Documentation PlanetGeometry::Documentation() { - using namespace documentation; - return { - "Planet Geometry", - "space_geometry_planet", - { - { - KeyType, - new StringVerifier, - Optional::No, - "The type of the PlanetGeometry that will can be constructed." - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_geometry_planet"; + return doc; } std::unique_ptr PlanetGeometry::createFromDictionary( const ghoul::Dictionary& dictionary) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "PlanetGeometry" - ); + const Parameters p = codegen::bake(dictionary); - std::string geometryType = dictionary.value(KeyType); auto factory = FactoryManager::ref().factory(); - PlanetGeometry* result = factory->create(geometryType, dictionary); + PlanetGeometry* result = factory->create(p.type, dictionary); return std::unique_ptr(result); } diff --git a/modules/space/rendering/renderableconstellationbounds.cpp b/modules/space/rendering/renderableconstellationbounds.cpp index 14e8dc60b4..4fe8e5a9cc 100644 --- a/modules/space/rendering/renderableconstellationbounds.cpp +++ b/modules/space/rendering/renderableconstellationbounds.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "SpiceUsr.h" namespace { @@ -74,51 +75,33 @@ namespace { "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::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(SelectionInfo.description)]] + std::optional> constellationSelection; + }; +#include "renderableconstellationbounds_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableConstellationBounds::Documentation() { - using namespace documentation; - return { - "RenderableConstellationBounds", - "space_renderable_constellationbounds", - { - { - VertexInfo.identifier, - new StringVerifier, - Optional::No, - VertexInfo.description - }, - { - ConstellationInfo.identifier, - new StringVerifier, - Optional::Yes, - "Specifies the file that contains the mapping between constellation " - "abbreviations and full name of the constellation. If the file is " - "omitted, the abbreviations are used as the full names." - }, - { - ColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - ColorInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - }, - { - SelectionInfo.identifier, - new StringListVerifier, - Optional::Yes, - SelectionInfo.description - } - } - }; -} + documentation::Documentation doc = codegen::doc(); + doc.id = "space_renderable_constellationbounds"; + return doc; +} // namespace RenderableConstellationBounds::RenderableConstellationBounds( @@ -130,53 +113,33 @@ RenderableConstellationBounds::RenderableConstellationBounds( , _lineWidth(LineWidthInfo, 2.f, 1.f, 32.f) , _constellationSelection(SelectionInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableConstellationBounds" - ); + const Parameters p = codegen::bake(dictionary); _vertexFilename.onChange([&](){ loadVertexFile(); }); addProperty(_vertexFilename); - _vertexFilename = dictionary.value(VertexInfo.identifier); + _vertexFilename = p.file; _constellationFilename.onChange([&](){ loadConstellationFile(); }); + _constellationFilename = p.constellationFile.value_or(_constellationFilename); addProperty(_constellationFilename); - if (dictionary.hasKey(ConstellationInfo.identifier)) { - _constellationFilename = dictionary.value( - ConstellationInfo.identifier - ); - } _color.setViewOption(properties::Property::ViewOptions::Color); + _color = p.color.value_or(_color); addProperty(_color); - if (dictionary.hasKey(ColorInfo.identifier)) { - _color = glm::vec3(dictionary.value(ColorInfo.identifier)); - } + _lineWidth = p.lineWidth.value_or(_lineWidth); addProperty(_lineWidth); - if (dictionary.hasKey(LineWidthInfo.identifier)) { - _lineWidth = static_cast( - dictionary.value(LineWidthInfo.identifier) - ); - } fillSelectionProperty(); _constellationSelection.onChange([this]() { selectionPropertyHasChanged(); }); addProperty(_constellationSelection); - if (dictionary.hasKey(SelectionInfo.identifier)) { - const ghoul::Dictionary& selection = dictionary.value( - SelectionInfo.identifier - ); - + if (p.constellationSelection.has_value()) { std::vector options = _constellationSelection.options(); + std::vector selectedIndices; - - for (size_t i = 1; i <= selection.size(); ++i) { - const std::string& s = selection.value(std::to_string(i)); - + for (const std::string& s : *p.constellationSelection) { const auto it = std::find_if( options.begin(), options.end(), diff --git a/modules/space/rendering/renderablerings.cpp b/modules/space/rendering/renderablerings.cpp index a8684960ea..6e45f719b6 100644 --- a/modules/space/rendering/renderablerings.cpp +++ b/modules/space/rendering/renderablerings.cpp @@ -36,6 +36,7 @@ #include #include #include +#include namespace { constexpr const std::array UniformNames = { @@ -79,53 +80,32 @@ namespace { "This value affects the filtering out of part of the rings depending on the " "color values of the texture. The higher value, the more rings are filtered out." }; + + struct [[codegen::Dictionary(RenderableRings)]] Parameters { + // [[codegen::verbatim(TextureInfo.description)]] + std::string texture; + + // [[codegen::verbatim(SizeInfo.description)]] + float size; + + // [[codegen::verbatim(OffsetInfo.description)]] + std::optional offset; + + // [[codegen::verbatim(NightFactorInfo.description)]] + std::optional nightFactor; + + // [[codegen::verbatim(ColorFilterInfo.description)]] + std::optional colorFilter; + }; +#include "renderablerings_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableRings::Documentation() { - using namespace documentation; - return { - "Renderable Rings", - "space_renderable_rings", - { - { - "Type", - new StringEqualVerifier("RenderableRings"), - Optional::No - }, - { - TextureInfo.identifier, - new StringVerifier, - Optional::No, - TextureInfo.description - }, - { - SizeInfo.identifier, - new DoubleVerifier, - Optional::No, - SizeInfo.description - }, - { - OffsetInfo.identifier, - new DoubleVector2Verifier, - Optional::Yes, - OffsetInfo.description - }, - { - NightFactorInfo.identifier, - new DoubleVerifier, - Optional::Yes, - NightFactorInfo.description - }, - { - ColorFilterInfo.identifier, - new DoubleVerifier, - Optional::Yes, - ColorFilterInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_renderable_rings"; + return doc; } RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary) @@ -138,23 +118,17 @@ RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary) { using ghoul::filesystem::File; - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableRings" - ); + const Parameters p = codegen::bake(dictionary); - _size = static_cast(dictionary.value(SizeInfo.identifier)); + _size = p.size; setBoundingSphere(_size); _size.onChange([&]() { _planeIsDirty = true; }); addProperty(_size); - _texturePath = absPath(dictionary.value(TextureInfo.identifier)); + _texturePath = absPath(p.texture); _textureFile = std::make_unique(_texturePath); - if (dictionary.hasValue(OffsetInfo.identifier)) { - _offset = dictionary.value(OffsetInfo.identifier); - } + _offset = p.offset.value_or(_offset); addProperty(_offset); _texturePath.onChange([&]() { loadTexture(); }); @@ -162,18 +136,10 @@ RenderableRings::RenderableRings(const ghoul::Dictionary& dictionary) _textureFile->setCallback([&](const File&) { _textureIsDirty = true; }); - if (dictionary.hasValue(NightFactorInfo.identifier)) { - _nightFactor = static_cast( - dictionary.value(NightFactorInfo.identifier) - ); - } + _nightFactor = p.nightFactor.value_or(_nightFactor); addProperty(_nightFactor); - if (dictionary.hasValue(ColorFilterInfo.identifier)) { - _colorFilter = static_cast( - dictionary.value(ColorFilterInfo.identifier) - ); - } + _colorFilter = p.colorFilter.value_or(_colorFilter); addProperty(_colorFilter); } diff --git a/modules/space/rendering/renderablesatellites.cpp b/modules/space/rendering/renderablesatellites.cpp index 19430ce7ca..c50736ad34 100644 --- a/modules/space/rendering/renderablesatellites.cpp +++ b/modules/space/rendering/renderablesatellites.cpp @@ -74,53 +74,42 @@ namespace { "Trail Fade", "This value determines how fast the trail fades and is an appearance property. " }; + + struct [[codegen::Dictionary(RenderableSatellites)]] Parameters { + // [[codegen::verbatim(SegmentsInfo.description)]] + double segments; + + // [[codegen::verbatim(PathInfo.description)]] + std::string path; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(LineColorInfo.description)]] + glm::dvec3 color; + + // [[codegen::verbatim(TrailFadeInfo.description)]] + std::optional trailFade; + }; +#include "renderablesatellites_codegen.cpp" } namespace openspace { documentation::Documentation RenderableSatellites::Documentation() { - using namespace documentation; - return { - "RenderableSatellites", - "space_renderable_satellites", - { - { - SegmentsInfo.identifier, - new DoubleVerifier, - Optional::No, - SegmentsInfo.description - }, - { - PathInfo.identifier, - new StringVerifier, - Optional::No, - PathInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - }, - { - LineColorInfo.identifier, - new DoubleVector3Verifier, - Optional::No, - LineColorInfo.description - }, - { - TrailFadeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - TrailFadeInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_renderable_satellites"; + return doc; } RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary) : RenderableOrbitalKepler(dictionary) -{} +{ + // Commented out right now as its not super clear how it works with inheritance. We'd + // probably want a codegen::check function that only does the checking without + // actually creating a Parameter objects + // codegen::bake(dictionary); +} void RenderableSatellites::readDataFile(const std::string& filename) { if (!FileSys.fileExists(filename)) { diff --git a/modules/space/rendering/renderablesmallbody.cpp b/modules/space/rendering/renderablesmallbody.cpp index 49fc5633a3..6963d03a9c 100644 --- a/modules/space/rendering/renderablesmallbody.cpp +++ b/modules/space/rendering/renderablesmallbody.cpp @@ -104,59 +104,42 @@ namespace { name.erase(name.find_last_not_of(trimChars) + 1); return name; } + + struct [[codegen::Dictionary(RenderableSmallBody)]] Parameters { + // [[codegen::verbatim(SegmentQualityInfo.description)]] + double segmentQuality; + + // [[codegen::verbatim(UpperLimitInfo.description)]] + std::optional upperLimit; + + // [[codegen::verbatim(PathInfo.description)]] + std::string path; + + // [[codegen::verbatim(LineWidthInfo.description)]] + std::optional lineWidth; + + // [[codegen::verbatim(LineColorInfo.description)]] + glm::dvec3 color; + + // [[codegen::verbatim(TrailFadeInfo.description)]] + std::optional trailFade; + }; +#include "renderablesmallbody_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableSmallBody::Documentation() { - using namespace documentation; - return { - "RenderableSmallBody", - "space_renderable_small_body", - { - { - SegmentQualityInfo.identifier, - new DoubleVerifier, - Optional::No, - SegmentQualityInfo.description - }, - { - UpperLimitInfo.identifier, - new IntVerifier, - Optional::Yes, - UpperLimitInfo.description - }, - { - PathInfo.identifier, - new StringVerifier, - Optional::No, - PathInfo.description - }, - { - LineWidthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - LineWidthInfo.description - }, - { - LineColorInfo.identifier, - new DoubleVector3Verifier, - Optional::No, - LineColorInfo.description - }, - { - TrailFadeInfo.identifier, - new DoubleVerifier, - Optional::Yes, - TrailFadeInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_renderable_small_body"; + return doc; } RenderableSmallBody::RenderableSmallBody(const ghoul::Dictionary& dictionary) : RenderableOrbitalKepler(dictionary) { + codegen::bake(dictionary); + _upperLimitCallbackHandle = _upperLimit.onChange(_reinitializeTrailBuffers); addProperty(_upperLimit); } diff --git a/modules/space/rendering/renderablestars.cpp b/modules/space/rendering/renderablestars.cpp index 8233058ea5..c1d159cb8e 100644 --- a/modules/space/rendering/renderablestars.cpp +++ b/modules/space/rendering/renderablestars.cpp @@ -51,10 +51,6 @@ namespace { constexpr const char* _loggerCat = "RenderableStars"; - constexpr const char* KeyFile = "File"; - constexpr const char* KeyStaticFilterValue = "StaticFilter"; - constexpr const char* KeyStaticFilterReplacement = "StaticFilterReplacement"; - constexpr const std::array UniformNames = { "modelMatrix", "cameraUp", "cameraViewProjectionMatrix", "colorOption", "magnitudeExponent", "eyePosition", "psfParamConf", @@ -309,120 +305,71 @@ namespace { "Disable Fade-in effect", "Enables/Disables the Fade-in effect." }; + + struct [[codegen::Dictionary(RenderableStars)]] Parameters { + // The path to the SPECK file containing information about the stars being rendered + std::string speckFile [[codegen::key("File")]]; + + // [[codegen::verbatim(ColorTextureInfo.description)]] + std::string colorMap; + + enum class ColorOption { + Color, + Velocity, + Speed, + OtherData [[codegen::key("Other Data")]], + FixedColor [[codegen::key("Fixed Color")]] + }; + // [[codegen::verbatim(ColorOptionInfo.description)]] + std::optional colorOption; + + // [[codegen::verbatim(OtherDataOptionInfo.description)]] + std::optional otherData; + + // [[codegen::verbatim(OtherDataColorMapInfo.description)]] + std::optional otherDataColorMap; + + // [[codegen::verbatim(FilterOutOfRangeInfo.description)]] + std::optional filterOutOfRange; + + // This value specifies a value that is always filtered out of the value ranges on + // loading. This can be used to trim the dataset's automatic value range + std::optional staticFilter; + + // This is the value that is used to replace statically filtered values. Setting this + // value only makes sense if 'StaticFilter' is 'true', as well + std::optional staticFilterReplacement; + + // [[codegen::verbatim(MagnitudeExponentInfo.description)]] + std::optional magnitudeExponent; + + // [[codegen::verbatim(EnableTestGridInfo.description)]] + std::optional enableTestGrid; + + // [[codegen::verbatim(RenderMethodOptionInfo.description)]] + std::string renderMethod; + + // [[codegen::verbatim(PsfTextureInfo.description)]] + std::string texture; + + // [[codegen::verbatim(SizeCompositionOptionInfo.description)]] + std::optional sizeComposition; + + // [[codegen::verbatim(FadeInDistancesInfo.description)]] + std::optional fadeInDistances; + + // [[codegen::verbatim(DisableFadeInInfo.description)]] + std::optional distableFadeIn; + }; +#include "renderablestars_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableStars::Documentation() { - using namespace documentation; - return { - "RenderableStars", - "space_renderablestars", - { - { - "Type", - new StringEqualVerifier("RenderableStars"), - Optional::No - }, - { - KeyFile, - new StringVerifier, - Optional::No, - "The path to the SPECK file that contains information about the stars " - "being rendered." - }, - { - ColorTextureInfo.identifier, - new StringVerifier, - Optional::No, - ColorTextureInfo.description - }, - /*{ - ShapeTextureInfo.identifier, - new StringVerifier, - Optional::No, - ShapeTextureInfo.description - },*/ - { - ColorOptionInfo.identifier, - new StringInListVerifier({ - "Color", "Velocity", "Speed", "Other Data", "Fixed Color" - }), - Optional::Yes, - ColorOptionInfo.description - }, - { - OtherDataOptionInfo.identifier, - new StringVerifier, - Optional::Yes, - OtherDataOptionInfo.description - }, - { - OtherDataColorMapInfo.identifier, - new StringVerifier, - Optional::Yes, - OtherDataColorMapInfo.description - }, - { - FilterOutOfRangeInfo.identifier, - new BoolVerifier, - Optional::Yes, - FilterOutOfRangeInfo.description - }, - { - KeyStaticFilterValue, - new DoubleVerifier, - Optional::Yes, - "This value specifies a value that is always filtered out of the value " - "ranges on loading. This can be used to trim the dataset's automatic " - "value range." - }, - { - KeyStaticFilterReplacement, - new DoubleVerifier, - Optional::Yes, - "This is the value that is used to replace statically filtered values. " - "Setting this value only makes sense if 'StaticFilter' is 'true', as " - "well." - }, - { - MagnitudeExponentInfo.identifier, - new DoubleVerifier, - Optional::Yes, - MagnitudeExponentInfo.description - }, - { - EnableTestGridInfo.identifier, - new BoolVerifier, - Optional::Yes, - EnableTestGridInfo.description - }, - { - RenderMethodOptionInfo.identifier, - new StringVerifier, - Optional::No, - RenderMethodOptionInfo.description - }, - { - SizeCompositionOptionInfo.identifier, - new StringVerifier, - Optional::No, - SizeCompositionOptionInfo.description - }, - { - FadeInDistancesInfo.identifier, - new Vector2Verifier, - Optional::Yes, - FadeInDistancesInfo.description - }, - { - DisableFadeInInfo.identifier, - new BoolVerifier, - Optional::Yes, - DisableFadeInInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_renderablestars"; + return doc; } RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) @@ -482,22 +429,16 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) { using File = ghoul::filesystem::File; - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableStars" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - _speckFile = absPath(dictionary.value(KeyFile)); + _speckFile = absPath(p.speckFile); _speckFile.onChange([&]() { _speckFileIsDirty = true; }); addProperty(_speckFile); - _colorTexturePath = absPath( - dictionary.value(ColorTextureInfo.identifier) - ); + _colorTexturePath = absPath(p.colorMap); _colorTextureFile = std::make_unique(_colorTexturePath); /*_shapeTexturePath = absPath(dictionary.value( @@ -505,10 +446,8 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) )); _shapeTextureFile = std::make_unique(_shapeTexturePath);*/ - if (dictionary.hasKey(OtherDataColorMapInfo.identifier)) { - _otherDataColorMapPath = absPath( - dictionary.value(OtherDataColorMapInfo.identifier) - ); + if (p.otherDataColorMap.has_value()) { + _otherDataColorMapPath = absPath(*p.otherDataColorMap); } _fixedColor.setViewOption(properties::Property::ViewOptions::Color, true); @@ -521,24 +460,23 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) { ColorOption::OtherData, "Other Data" }, { ColorOption::FixedColor, "Fixed Color" } }); - if (dictionary.hasKey(ColorOptionInfo.identifier)) { - const std::string colorOption = dictionary.value( - ColorOptionInfo.identifier - ); - if (colorOption == "Color") { - _colorOption = ColorOption::Color; - } - else if (colorOption == "Velocity") { - _colorOption = ColorOption::Velocity; - } - else if (colorOption == "Speed") { - _colorOption = ColorOption::Speed; - } - else if (colorOption == "OtherData") { - _colorOption = ColorOption::OtherData; - } - else { - _colorOption = ColorOption::FixedColor; + if (p.colorOption.has_value()) { + switch (*p.colorOption) { + case Parameters::ColorOption::Color: + _colorOption = ColorOption::Color; + break; + case Parameters::ColorOption::Velocity: + _colorOption = ColorOption::Velocity; + break; + case Parameters::ColorOption::Speed: + _colorOption = ColorOption::Speed; + break; + case Parameters::ColorOption::OtherData: + _colorOption = ColorOption::OtherData; + break; + case Parameters::ColorOption::FixedColor: + _colorOption = ColorOption::FixedColor; + break; } } _colorOption.onChange([&] { _dataIsDirty = true; }); @@ -556,13 +494,8 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) }); addProperty(_shapeTexturePath);*/ - if (dictionary.hasKey(EnableTestGridInfo.identifier)) { - _enableTestGrid = dictionary.value(EnableTestGridInfo.identifier); - } - - if (dictionary.hasKey(OtherDataOptionInfo.identifier)) { - _queuedOtherData = dictionary.value(OtherDataOptionInfo.identifier); - } + _enableTestGrid = p.enableTestGrid.value_or(_enableTestGrid); + _queuedOtherData = p.otherData.value_or(_queuedOtherData); _otherDataOption.onChange([&]() { _dataIsDirty = true; }); addProperty(_otherDataOption); @@ -572,16 +505,9 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) addProperty(_otherDataColorMapPath); _otherDataColorMapPath.onChange([&]() { _otherDataColorMapIsDirty = true; }); - if (dictionary.hasKey(KeyStaticFilterValue)) { - _staticFilterValue = static_cast( - dictionary.value(KeyStaticFilterValue) - ); - } - if (dictionary.hasKey(KeyStaticFilterReplacement)) { - _staticFilterReplacementValue = static_cast( - dictionary.value(KeyStaticFilterReplacement) - ); - } + _staticFilterValue = p.staticFilter; + _staticFilterReplacementValue = + p.staticFilterReplacement.value_or(_staticFilterReplacementValue); addProperty(_filterOutOfRange); @@ -592,23 +518,14 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) _renderingMethodOption.addOption(RenderOptionTexture, "Textured Based"); addProperty(_renderingMethodOption); - if (dictionary.hasKey(RenderMethodOptionInfo.identifier)) { - std::string renderingMethod = - dictionary.value(RenderMethodOptionInfo.identifier); - if (renderingMethod == "PSF") { - _renderingMethodOption = RenderOptionPointSpreadFunction; - } - else if (renderingMethod == "Texture Based") { - _renderingMethodOption = RenderOptionTexture; - } + if (p.renderMethod == "PSF") { + _renderingMethodOption = RenderOptionPointSpreadFunction; } - else { + else if (p.renderMethod == "Texture Based") { _renderingMethodOption = RenderOptionTexture; } - _pointSpreadFunctionTexturePath = absPath(dictionary.value( - PsfTextureInfo.identifier - )); + _pointSpreadFunctionTexturePath = absPath(p.texture); _pointSpreadFunctionFile = std::make_unique(_pointSpreadFunctionTexturePath); _pointSpreadFunctionTexturePath.onChange([&]() { _pointSpreadFunctionTextureIsDirty = true; @@ -631,26 +548,24 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) _psfMultiplyOption.addOption(4, "Apparent Magnitude"); _psfMultiplyOption.addOption(5, "Distance Modulus"); - if (dictionary.hasKey(MagnitudeExponentInfo.identifier)) { - std::string sizeCompositionOption = - dictionary.value(SizeCompositionOptionInfo.identifier); - if (sizeCompositionOption == "App Brightness") { + if (p.sizeComposition.has_value()) { + if (*p.sizeComposition == "App Brightness") { _psfMultiplyOption = 0; } - else if (sizeCompositionOption == "Lum and Size") { + else if (*p.sizeComposition == "Lum and Size") { _psfMultiplyOption = 1; } - else if (sizeCompositionOption == "Lum, Size and App Brightness") { + else if (*p.sizeComposition == "Lum, Size and App Brightness") { _psfMultiplyOption = 2; } - else if (sizeCompositionOption == "Abs Magnitude") { + else if (*p.sizeComposition == "Abs Magnitude") { _psfMultiplyOption = 3; } - else if (sizeCompositionOption == "App Maginitude") { + else if (*p.sizeComposition == "App Maginitude") { _psfMultiplyOption = 4; } - else if (sizeCompositionOption == "Distance Modulus") { + else if (*p.sizeComposition == "Distance Modulus") { _psfMultiplyOption = 5; } } @@ -663,11 +578,7 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) _parametersOwner.addProperty(_radiusCent); _parametersOwner.addProperty(_brightnessCent); - if (dictionary.hasKey(MagnitudeExponentInfo.identifier)) { - _magnitudeExponent = static_cast( - dictionary.value(MagnitudeExponentInfo.identifier) - ); - } + _magnitudeExponent = p.magnitudeExponent.value_or(_magnitudeExponent); _parametersOwner.addProperty(_magnitudeExponent); auto renderPsf = [&]() { renderPSFToTexture(); }; @@ -693,8 +604,8 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary) addPropertySubOwner(_parametersOwner); addPropertySubOwner(_moffatMethodOwner); - if (dictionary.hasKey(FadeInDistancesInfo.identifier)) { - glm::vec2 v = dictionary.value(FadeInDistancesInfo.identifier); + if (p.fadeInDistances.has_value()) { + glm::vec2 v = *p.fadeInDistances; _fadeInDistance = v; _disableFadeInDistance = false; addProperty(_fadeInDistance); diff --git a/modules/space/rendering/simplespheregeometry.cpp b/modules/space/rendering/simplespheregeometry.cpp index 0f39776640..5c4ed12ef9 100644 --- a/modules/space/rendering/simplespheregeometry.cpp +++ b/modules/space/rendering/simplespheregeometry.cpp @@ -1,4 +1,4 @@ -/**************************************************************************************** +/**************************************************************************************** * * * OpenSpace * * * @@ -41,30 +41,23 @@ namespace { "Segments", "This value specifies the number of segments that this sphere is split into." }; + + struct [[codegen::Dictionary(SimpleSphereGeometry)]] Parameters { + // [[codegen::verbatim(RadiusInfo.description)]] + std::variant radius; + + // [[codegen::verbatim(SegmentsInfo.description)]] + int segments; + }; +#include "simplespheregeometry_codegen.cpp" } // namespace namespace openspace::planetgeometry { documentation::Documentation SimpleSphereGeometry::Documentation() { - using namespace documentation; - return { - "SimpleSphereGeometry", - "space_geometry_simplesphere", - { - { - RadiusInfo.identifier, - new OrVerifier({ new DoubleVerifier, new DoubleVector3Verifier }), - Optional::No, - RadiusInfo.description - }, - { - SegmentsInfo.identifier, - new IntVerifier, - Optional::No, - SegmentsInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_geometry_simplesphere"; + return doc; } SimpleSphereGeometry::SimpleSphereGeometry(const ghoul::Dictionary& dictionary) @@ -72,23 +65,17 @@ SimpleSphereGeometry::SimpleSphereGeometry(const ghoul::Dictionary& dictionary) , _segments(SegmentsInfo, 20, 1, 5000) , _sphere(nullptr) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "SimpleSphereGeometry" - ); + const Parameters p = codegen::bake(dictionary); - if (dictionary.hasValue(RadiusInfo.identifier)) { - const float r = static_cast( - dictionary.value(RadiusInfo.identifier) - ); - _radius = { r, r, r }; + if (std::holds_alternative(p.radius)) { + const float radius = std::get(p.radius); + _radius = glm::dvec3(radius, radius, radius); } else { - _radius = dictionary.value(RadiusInfo.identifier); + _radius = std::get(p.radius); } - _segments = static_cast(dictionary.value(SegmentsInfo.identifier)); + _segments = p.segments; // The shader need the radii values but they are not changeable runtime // TODO: Possibly add a scaling property @AA diff --git a/modules/space/rotation/spicerotation.cpp b/modules/space/rotation/spicerotation.cpp index 3e1f0d51cc..02b1b025c0 100644 --- a/modules/space/rotation/spicerotation.cpp +++ b/modules/space/rotation/spicerotation.cpp @@ -29,10 +29,9 @@ #include #include #include +#include namespace { - constexpr const char* KeyKernels = "Kernels"; - constexpr openspace::properties::Property::PropertyInfo SourceInfo = { "SourceFrame", "Source", @@ -52,76 +51,49 @@ namespace { "Time Frame", "The time frame in which the spice kernels are valid." }; + + struct [[codegen::Dictionary(SpiceRotation)]] Parameters { + // [[codegen::verbatim(SourceInfo.description)]] + std::string sourceFrame + [[codegen::annotation("A valid SPICE NAIF name or integer")]]; + + // [[codegen::verbatim(DestinationInfo.description)]] + std::string destinationFrame; + + // [[codegen::verbatim(DestinationInfo.description)]] + std::optional, std::string>> kernels; + + // [[codegen::verbatim(TimeFrameInfo.description)]] + std::optional timeFrame [[codegen::reference("core_time_frame")]]; + }; +#include "spicerotation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation SpiceRotation::Documentation() { - using namespace openspace::documentation; - return { - "Spice Rotation", - "space_transform_rotation_spice", - { - { - "Type", - new StringEqualVerifier("SpiceRotation"), - Optional::No - }, - { - SourceInfo.identifier, - new StringAnnotationVerifier("A valid SPICE NAIF name or integer"), - Optional::No, - SourceInfo.description - }, - { - DestinationInfo.identifier, - new StringAnnotationVerifier("A valid SPICE NAIF name or integer"), - Optional::No, - DestinationInfo.description - }, - { - KeyKernels, - new OrVerifier({ new StringListVerifier, new StringVerifier }), - Optional::Yes, - "A single kernel or list of kernels that this SpiceTranslation depends " - "on. All provided kernels will be loaded before any other operation is " - "performed." - }, - { - TimeFrameInfo.identifier, - new ReferencingVerifier("core_time_frame"), - Optional::Yes, - TimeFrameInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_transform_rotation_spice"; + return doc; } SpiceRotation::SpiceRotation(const ghoul::Dictionary& dictionary) : _sourceFrame(SourceInfo) , _destinationFrame(DestinationInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "SpiceRotation" - ); + const Parameters p = codegen::bake(dictionary); - _sourceFrame = dictionary.value(SourceInfo.identifier); - _destinationFrame = dictionary.value(DestinationInfo.identifier); + _sourceFrame = p.sourceFrame; + _destinationFrame = p.destinationFrame; - if (dictionary.hasValue(KeyKernels)) { - SpiceManager::ref().loadKernel(dictionary.value(KeyKernels)); - } - else if (dictionary.hasValue(KeyKernels)) { - ghoul::Dictionary kernels = dictionary.value(KeyKernels); - for (size_t i = 1; i <= kernels.size(); ++i) { - if (!kernels.hasValue(std::to_string(i))) { - throw ghoul::RuntimeError("Kernels has to be an array-style table"); + if (p.kernels.has_value()) { + if (std::holds_alternative(*p.kernels)) { + SpiceManager::ref().loadKernel(std::get(*p.kernels)); + } + else { + for (const std::string& s : std::get>(*p.kernels)) { + SpiceManager::ref().loadKernel(s); } - - std::string kernel = kernels.value(std::to_string(i)); - SpiceManager::ref().loadKernel(kernel); } } @@ -130,7 +102,7 @@ SpiceRotation::SpiceRotation(const ghoul::Dictionary& dictionary) dictionary.value(TimeFrameInfo.identifier); _timeFrame = TimeFrame::createFromDictionary(timeFrameDictionary); if (_timeFrame == nullptr) { - throw ghoul::RuntimeError("Invalid dictionary for TimeFrame."); + throw ghoul::RuntimeError("Invalid dictionary for TimeFrame"); } addPropertySubOwner(_timeFrame.get()); } diff --git a/modules/space/spacemodule.cpp b/modules/space/spacemodule.cpp index 95c576e14f..0ebba746cd 100644 --- a/modules/space/spacemodule.cpp +++ b/modules/space/spacemodule.cpp @@ -31,7 +31,6 @@ #include #include #include -//#include #include #include #include diff --git a/modules/space/translation/horizonstranslation.cpp b/modules/space/translation/horizonstranslation.cpp index 3c71906207..6f294d3055 100644 --- a/modules/space/translation/horizonstranslation.cpp +++ b/modules/space/translation/horizonstranslation.cpp @@ -46,32 +46,22 @@ namespace { "This value is the path to the text file generated by Horizons with observer " "range and Galactiv longitude and latitude for different timestamps." }; + + struct [[codegen::Dictionary(HorizonsTranslation)]] Parameters { + // [[codegen::verbatim(HorizonsTextFileInfo.description)]] + std::string horizonsTextFile; + }; +#include "horizonstranslation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation HorizonsTranslation::Documentation() { - using namespace documentation; - return { - "Horizons Translation", - "base_transform_translation_horizons", - { - { - "Type", - new StringEqualVerifier("HorizonsTranslation"), - Optional::No - }, - { - HorizonsTextFileInfo.identifier, - new StringVerifier, - Optional::No, - HorizonsTextFileInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "base_transform_translation_horizons"; + return doc; } - HorizonsTranslation::HorizonsTranslation() : _horizonsTextFile(HorizonsTextFileInfo) { @@ -91,15 +81,8 @@ HorizonsTranslation::HorizonsTranslation() HorizonsTranslation::HorizonsTranslation(const ghoul::Dictionary& dictionary) : HorizonsTranslation() { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "HorizonsTranslation" - ); - - _horizonsTextFile = absPath( - dictionary.value(HorizonsTextFileInfo.identifier) - ); + const Parameters p = codegen::bake(dictionary); + _horizonsTextFile = absPath(p.horizonsTextFile); } glm::dvec3 HorizonsTranslation::position(const UpdateData& data) const { diff --git a/modules/space/translation/keplertranslation.cpp b/modules/space/translation/keplertranslation.cpp index 33ea61adeb..2dcedbe797 100644 --- a/modules/space/translation/keplertranslation.cpp +++ b/modules/space/translation/keplertranslation.cpp @@ -31,7 +31,6 @@ #include namespace { - template T solveIteration(const Func& function, T x0, const T& err = 0.0, int maxIter = 100) { T x2 = x0; @@ -105,6 +104,33 @@ namespace { "Orbit period", "Specifies the orbital period (in seconds)." }; + + struct [[codegen::Dictionary(KeplerTranslation)]] Parameters { + // [[codegen::verbatim(EccentricityInfo.description)]] + double eccentricity [[codegen::inrange(0.0, 1.0)]]; + + // [[codegen::verbatim(SemiMajorAxisInfo.description)]] + double semiMajorAxis; + + // [[codegen::verbatim(InclinationInfo.description)]] + double inclination [[codegen::inrange(0.0, 360.0)]]; + + // [[codegen::verbatim(AscendingNodeInfo.description)]] + double ascendingNode [[codegen::inrange(0.0, 360.0)]]; + + // [[codegen::verbatim(ArgumentOfPeriapsisInfo.description)]] + double argumentOfPeriapsis [[codegen::inrange(0.0, 360.0)]]; + + // [[codegen::verbatim(MeanAnomalyAtEpochInfo.description)]] + double meanAnomaly [[codegen::inrange(0.0, 360.0)]]; + + // [[codegen::verbatim(EpochInfo.description)]] + std::string epoch; + + // [[codegen::verbatim(PeriodInfo.description)]] + double period [[codegen::greater(0.0)]]; + }; +#include "keplertranslation_codegen.cpp" } // namespace namespace openspace { @@ -115,66 +141,9 @@ KeplerTranslation::RangeError::RangeError(std::string off) {} documentation::Documentation KeplerTranslation::Documentation() { - using namespace openspace::documentation; - return { - "Kepler Translation", - "space_transform_kepler", - { - { - "Type", - new StringEqualVerifier("KeplerTranslation"), - Optional::No - }, - { - EccentricityInfo.identifier, - new DoubleInRangeVerifier(0.0, 1.0), - Optional::No, - EccentricityInfo.description - }, - { - SemiMajorAxisInfo.identifier, - new DoubleVerifier, - Optional::No, - SemiMajorAxisInfo.description - }, - { - InclinationInfo.identifier, - new DoubleInRangeVerifier(0.0, 360.0), - Optional::No, - InclinationInfo.description - }, - { - AscendingNodeInfo.identifier, - new DoubleInRangeVerifier(0.0, 360.0), - Optional::No, - AscendingNodeInfo.description - }, - { - ArgumentOfPeriapsisInfo.identifier, - new DoubleInRangeVerifier(0.0, 360.0), - Optional::No, - ArgumentOfPeriapsisInfo.description - }, - { - MeanAnomalyAtEpochInfo.identifier, - new DoubleInRangeVerifier(0.0, 360.0), - Optional::No, - MeanAnomalyAtEpochInfo.description - }, - { - EpochInfo.identifier, - new StringVerifier, - Optional::No, - EpochInfo.description - }, - { - PeriodInfo.identifier, - new DoubleGreaterVerifier(0.0), - Optional::No, - PeriodInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_transform_kepler"; + return doc; } KeplerTranslation::KeplerTranslation() @@ -218,21 +187,17 @@ KeplerTranslation::KeplerTranslation() KeplerTranslation::KeplerTranslation(const ghoul::Dictionary& dictionary) : KeplerTranslation() { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "KeplerTranslation" - ); + const Parameters p = codegen::bake(dictionary); setKeplerElements( - dictionary.value(EccentricityInfo.identifier), - dictionary.value(SemiMajorAxisInfo.identifier), - dictionary.value(InclinationInfo.identifier), - dictionary.value(AscendingNodeInfo.identifier), - dictionary.value(ArgumentOfPeriapsisInfo.identifier), - dictionary.value(MeanAnomalyAtEpochInfo.identifier), - dictionary.value(PeriodInfo.identifier), - dictionary.value(EpochInfo.identifier) + p.eccentricity, + p.semiMajorAxis, + p.inclination, + p.ascendingNode, + p.argumentOfPeriapsis, + p.meanAnomaly, + p.period, + p.epoch ); } diff --git a/modules/space/translation/spicetranslation.cpp b/modules/space/translation/spicetranslation.cpp index f286a1d904..519539d9d6 100644 --- a/modules/space/translation/spicetranslation.cpp +++ b/modules/space/translation/spicetranslation.cpp @@ -33,10 +33,9 @@ #include #include #include +#include namespace { - constexpr const char* KeyKernels = "Kernels"; - constexpr const char* DefaultReferenceFrame = "GALACTIC"; constexpr openspace::properties::Property::PropertyInfo TargetInfo = { @@ -61,54 +60,32 @@ namespace { "This is the SPICE NAIF name for the reference frame in which the position " "should be retrieved. The default value is GALACTIC." }; + + struct [[codegen::Dictionary(SpiceTranslation)]] Parameters { + // [[codegen::verbatim(TargetInfo.description)]] + std::string target + [[codegen::annotation("A valid SPICE NAIF name or identifier")]]; + + // [[codegen::verbatim(ObserverInfo.description)]] + std::string observer + [[codegen::annotation("A valid SPICE NAIF name or identifier")]]; + + std::optional frame + [[codegen::annotation("A valid SPICE NAIF name for a reference frame")]]; + + // A single kernel or list of kernels that this SpiceTranslation depends on. All + // provided kernels will be loaded before any other operation is performed + std::optional, std::string>> kernels; + }; +#include "spicetranslation_codegen.cpp" } // namespace namespace openspace { documentation::Documentation SpiceTranslation::Documentation() { - using namespace openspace::documentation; - - return { - "Spice Translation", - "space_translation_spicetranslation", - { - { - "Type", - new StringEqualVerifier("SpiceTranslation"), - Optional::No - }, - { - TargetInfo.identifier, - new StringAnnotationVerifier("A valid SPICE NAIF name or identifier"), - Optional::No, - "This is the SPICE NAIF name for the body whose translation is to be " - "computed by the SpiceTranslation. It can either be a fully qualified " - "name (such as 'EARTH') or a NAIF integer id code (such as '399')." - }, - { - ObserverInfo.identifier, - new StringAnnotationVerifier("A valid SPICE NAIF name or identifier"), - Optional::No, - ObserverInfo.description - }, - { - FrameInfo.identifier, - new StringAnnotationVerifier( - "A valid SPICE NAIF name for a reference frame" - ), - Optional::Yes, - FrameInfo.description - }, - { - KeyKernels, - new OrVerifier({ new StringListVerifier, new StringVerifier }), - Optional::Yes, - "A single kernel or list of kernels that this SpiceTranslation depends " - "on. All provided kernels will be loaded before any other operation is " - "performed." - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_translation_spicetranslation"; + return doc; } SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary) @@ -117,15 +94,13 @@ SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary) , _frame(FrameInfo, DefaultReferenceFrame) , _cachedFrame(DefaultReferenceFrame) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "SpiceTranslation" - ); + const Parameters p = codegen::bake(dictionary); auto loadKernel = [](const std::string& kernel) { if (!FileSys.fileExists(kernel)) { - throw SpiceManager::SpiceException("Kernel '" + kernel + "' does not exist"); + throw SpiceManager::SpiceException(fmt::format( + "Kernel '{}' does not exist", kernel + )); } try { @@ -136,17 +111,13 @@ SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary) } }; - if (dictionary.hasKey(KeyKernels)) { - // Due to the specification, we can be sure it is either a Dictionary or a string - if (dictionary.hasValue(KeyKernels)) { - std::string kernel = dictionary.value(KeyKernels); - loadKernel(absPath(kernel)); + if (p.kernels.has_value()) { + if (std::holds_alternative(*p.kernels)) { + loadKernel(absPath(std::get(*p.kernels))); } else { - ghoul::Dictionary kernels = dictionary.value(KeyKernels); - for (size_t i = 1; i <= kernels.size(); ++i) { - std::string kernel = kernels.value(std::to_string(i)); - loadKernel(absPath(kernel)); + for (const std::string& k : std::get>(*p.kernels)) { + loadKernel(absPath(k)); } } } @@ -172,12 +143,9 @@ SpiceTranslation::SpiceTranslation(const ghoul::Dictionary& dictionary) }); addProperty(_frame); - _target = dictionary.value(TargetInfo.identifier); - _observer = dictionary.value(ObserverInfo.identifier); - - if (dictionary.hasKey(FrameInfo.identifier)) { - _frame = dictionary.value(FrameInfo.identifier); - } + _target = p.target; + _observer = p.observer; + _frame = p.frame.value_or(_frame); } glm::dvec3 SpiceTranslation::position(const UpdateData& data) const { diff --git a/modules/space/translation/tletranslation.cpp b/modules/space/translation/tletranslation.cpp index 4d6698b7a5..83f5794355 100644 --- a/modules/space/translation/tletranslation.cpp +++ b/modules/space/translation/tletranslation.cpp @@ -29,12 +29,10 @@ #include #include #include +#include #include namespace { - constexpr const char* KeyFile = "File"; - constexpr const char* KeyLineNumber = "LineNumber"; - // The list of leap years only goes until 2056 as we need to touch this file then // again anyway ;) const std::vector LeapYears = { @@ -211,52 +209,32 @@ namespace { // We need the semi major axis in km instead of m return semiMajorAxis / 1000.0; } -} // namespace + struct [[codegen::Dictionary(TLETranslation)]] Parameters { + // Specifies the filename of the Two-Line-Element file + std::string file; + + // Specifies the line number within the file where the group of 3 TLE lines begins + // (1-based). Defaults to 1 + std::optional lineNumber [[codegen::greater(0)]]; + }; +#include "tletranslation_codegen.cpp" +} // namespace namespace openspace { documentation::Documentation TLETranslation::Documentation() { - using namespace openspace::documentation; - return { - "TLE Translation", - "space_transform_tle", - { - { - "Type", - new StringEqualVerifier("TLETranslation"), - Optional::No - }, - { - KeyFile, - new StringVerifier, - Optional::No, - "Specifies the filename of the Two-Line-Element file" - }, - { - KeyLineNumber, - new DoubleGreaterVerifier(0), - Optional::Yes, - "Specifies the line number within the file where the group of 3 TLE " - "lines begins (1-based). Defaults to 1." - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "space_transform_tle"; + return doc; } TLETranslation::TLETranslation(const ghoul::Dictionary& dictionary) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "TLETranslation" - ); + const Parameters p = codegen::bake(dictionary); - const std::string& file = dictionary.value(KeyFile); - int lineNum = 1; - if (dictionary.hasValue(KeyLineNumber)) { - lineNum = static_cast(dictionary.value(KeyLineNumber)); - } - readTLEFile(file, lineNum); + + int lineNum = p.lineNumber.value_or(1); + readTLEFile(p.file, lineNum); } void TLETranslation::readTLEFile(const std::string& filename, int lineNum) { diff --git a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp index 30496b6822..b8371ac55e 100644 --- a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp +++ b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp @@ -87,47 +87,29 @@ namespace { glm::vec2 addToBoundingbox(glm::vec2 lhs, glm::vec2 rhs) { return { std::max(lhs.x, rhs.x), lhs.y + rhs.y }; } + + struct [[codegen::Dictionary(DashboardItemInstruments)]] Parameters { + // [[codegen::verbatim(FontNameInfo.description)]] + std::optional fontName; + + // [[codegen::verbatim(FontSizeInfo.description)]] + std::optional fontSize; + + // [[codegen::verbatim(ActiveColorInfo.description)]] + std::optional activeColor; + + // [[codegen::verbatim(FlashColorInfo.description)]] + std::optional flashColor; + }; +#include "dashboarditeminstruments_codegen.cpp" } // namespace namespace openspace { documentation::Documentation DashboardItemInstruments::Documentation() { - using namespace documentation; - return { - "DashboardItem Instruments", - "spacecraftinstruments_dashboarditem_instuments", - { - { - "Type", - new StringEqualVerifier("DashboardItemInstruments"), - Optional::No - }, - { - FontNameInfo.identifier, - new StringVerifier, - Optional::Yes, - FontNameInfo.description - }, - { - FontSizeInfo.identifier, - new IntVerifier, - Optional::Yes, - FontSizeInfo.description - }, - { - ActiveColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - ActiveColorInfo.description - }, - { - FlashColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - FlashColorInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "spacecraftinstruments_dashboarditem_instuments"; + return doc; } DashboardItemInstruments::DashboardItemInstruments(const ghoul::Dictionary& dictionary) @@ -147,24 +129,15 @@ DashboardItemInstruments::DashboardItemInstruments(const ghoul::Dictionary& dict ) , _font(global::fontManager->font(KeyFontMono, 10)) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "DashboardItemInstruments" - ); - - if (dictionary.hasKey(FontNameInfo.identifier)) { - _fontName = dictionary.value(FontNameInfo.identifier); - } - if (dictionary.hasKey(FontSizeInfo.identifier)) { - _fontSize = static_cast(dictionary.value(FontSizeInfo.identifier)); - } + const Parameters p = codegen::bake(dictionary); + _fontName = p.fontName.value_or(_fontName); _fontName.onChange([this]() { _font = global::fontManager->font(_fontName, _fontSize); }); addProperty(_fontName); + _fontSize = p.fontSize.value_or(_fontSize); _fontSize.onChange([this]() { _font = global::fontManager->font(_fontName, _fontSize); }); diff --git a/modules/spacecraftinstruments/rendering/renderablefov.cpp b/modules/spacecraftinstruments/rendering/renderablefov.cpp index b3c4cf58d8..25111acf83 100644 --- a/modules/spacecraftinstruments/rendering/renderablefov.cpp +++ b/modules/spacecraftinstruments/rendering/renderablefov.cpp @@ -152,6 +152,48 @@ namespace { return 0.5 * bisect(p1, half, testFunction, half); } } + // Needs support for std::map first for the frameConversions +// struct [[codegen::Dictionary(RenderableFov)]] Parameters { +// // The SPICE name of the source body for which the field of view should be +// // rendered +// std::string body; +// +// // The SPICE name of the source body's frame in which the field of view should be +// // rendered +// std::string frame; +// +// struct Instrument { +// // The SPICE name of the instrument that is rendered +// std::string name; +// +// // The aberration correction that is used for this field of view. The default +// // is 'NONE' +// std::optional aberration [[codegen::inlist("NONE", +// "LT", "LT+S", "CN", "CN+S", "XLT", "XLT+S", "XCN", "XCN+S")]]; +// }; +// // A table describing the instrument whose field of view should be rendered +// Instrument instrument; +// +// // A list of potential targets (specified as SPICE names) that the field of view +// // should be tested against +// std::vector potentialTargets; +// +// // A list of frame conversions that should be registered with the SpiceManager +// std::optional> frameConversions; +// +// // [[codegen::verbatim(LineWidthInfo.description)]] +// std::optional lineWidth; +// +// // [[codegen::verbatim(StandoffDistanceInfo.description)]] +// std::optional standOffDistance; +// +// // If this value is set to 'true' the field-of-views bounds values will be +// // simplified on load. Bound vectors will be removed if they are the strict linear +// // interpolation between the two neighboring vectors. This value is disabled on +// // default +// std::optional simplifyBounds; +// }; +//#include "renderablefov_codegen.cpp" } // namespace namespace openspace { diff --git a/modules/spacecraftinstruments/rendering/renderablemodelprojection.cpp b/modules/spacecraftinstruments/rendering/renderablemodelprojection.cpp index 6f960ce5c6..7e4222cf2a 100644 --- a/modules/spacecraftinstruments/rendering/renderablemodelprojection.cpp +++ b/modules/spacecraftinstruments/rendering/renderablemodelprojection.cpp @@ -81,11 +81,6 @@ documentation::Documentation RenderableModelProjection::Documentation() { "Renderable Model Projection", "newhorizons_renderable_modelprojection", { - { - "Type", - new StringEqualVerifier("RenderableModelProjection"), - Optional::No - }, { keyGeometry, new ReferencingVerifier("base_geometry_model"), diff --git a/modules/spacecraftinstruments/rendering/renderableplaneprojection.cpp b/modules/spacecraftinstruments/rendering/renderableplaneprojection.cpp index b93893b9e2..a165d84c5d 100644 --- a/modules/spacecraftinstruments/rendering/renderableplaneprojection.cpp +++ b/modules/spacecraftinstruments/rendering/renderableplaneprojection.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include namespace { constexpr const char* _loggerCat = "RenderablePlaneProjection"; @@ -50,6 +52,16 @@ namespace { constexpr const char* KeyName = "Name"; constexpr const char* KeyTarget = "DefaultTarget"; constexpr const char* GalacticFrame = "GALACTIC"; + + struct [[codegen::Dictionary(RenderablePlaneProjection)]] Parameters { + std::optional spacecraft; + std::optional instrument; + std::optional moving; + std::optional name; + std::optional defaultTarget; + std::optional texture; + }; +#include "renderableplaneprojection_codegen.cpp" } // namespace namespace openspace { @@ -57,24 +69,15 @@ namespace openspace { RenderablePlaneProjection::RenderablePlaneProjection(const ghoul::Dictionary& dict) : Renderable(dict) { - if (dict.hasValue(KeySpacecraft)) { - _spacecraft = dict.value(KeySpacecraft); - } - if (dict.hasValue(KeyInstrument)) { - _instrument = dict.value(KeyInstrument); - } - if (dict.hasValue(KeyMoving)) { - _moving = dict.value(KeyMoving); - } - if (dict.hasValue(KeyName)) { - _name = dict.value(KeyName); - } - if (dict.hasValue(KeyTarget)) { - _defaultTarget = dict.value(KeyTarget); - } - if (dict.hasValue(KeyTexture)) { - _texturePath = dict.value(KeyTexture); - _texturePath = absPath(_texturePath); + const Parameters p = codegen::bake(dict); + _spacecraft = p.spacecraft.value_or(_spacecraft); + _instrument = p.instrument.value_or(_instrument); + _moving = p.moving.value_or(_moving); + _name = p.name.value_or(_name); + _defaultTarget = p.defaultTarget.value_or(_defaultTarget); + + if (p.texture.has_value()) { + _texturePath = absPath(*p.texture); _textureFile = std::make_unique(_texturePath); } } diff --git a/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp b/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp index cfcf3c0270..23ac686770 100644 --- a/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp +++ b/modules/spacecraftinstruments/rendering/renderableplanetprojection.cpp @@ -145,12 +145,6 @@ documentation::Documentation RenderablePlanetProjection::Documentation() { "Renderable Planet Projection", "newhorizons_renderable_planetprojection", { - { - "Type", - new StringEqualVerifier("RenderablePlanetProjection"), - Optional::No, - "" - }, { KeyGeometry, new ReferencingVerifier("space_geometry_planet"), diff --git a/modules/spacecraftinstruments/rendering/renderableshadowcylinder.cpp b/modules/spacecraftinstruments/rendering/renderableshadowcylinder.cpp index 32a766f256..4857d8d23d 100644 --- a/modules/spacecraftinstruments/rendering/renderableshadowcylinder.cpp +++ b/modules/spacecraftinstruments/rendering/renderableshadowcylinder.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include namespace { constexpr const char* ProgramName = "ShadowCylinderProgram"; @@ -104,85 +104,49 @@ namespace { "Aberration", "This value determines the aberration method that is used to compute the shadow " "cylinder." + }; + + struct [[codegen::Dictionary(RenderableShadowCylinder)]] Parameters { + // [[codegen::verbatim(NumberPointsInfo.description)]] + std::optional numberOfPoints [[codegen::key("AmountOfPoints")]]; + + // [[codegen::verbatim(ShadowLengthInfo.description)]] + std::optional shadowLength; + + // [[codegen::verbatim(ShadowColorInfo.description)]] + std::optional shadowColor; + + enum class TerminatorType { + Umbral [[codegen::key("UMBRAL")]], + Penumbral [[codegen::key("PENUMBRAL")]] + }; + // [[codegen::verbatim(TerminatorTypeInfo.description)]] + TerminatorType terminatorType; + + // [[codegen::verbatim(LightSourceInfo.description)]] + std::string lightSource; + + // [[codegen::verbatim(ObserverInfo.description)]] + std::string observer; + + // [[codegen::verbatim(BodyInfo.description)]] + std::string body; + + // [[codegen::verbatim(BodyFrameInfo.description)]] + std::string bodyFrame; + + // [[codegen::verbatim(AberrationInfo.description)]] + std::string aberration [[codegen::inlist("NONE", "LT", "LT+S", "CN", "CN+S")]]; }; +#include "renderableshadowcylinder_codegen.cpp" } // namespace namespace openspace { documentation::Documentation RenderableShadowCylinder::Documentation() { - using namespace documentation; - return { - "RenderableShadowCylinder", - "newhorizons_renderable_shadowcylinder", - { - { - "Type", - new StringEqualVerifier("RenderableShadowCylinder"), - Optional::No, - "" - }, - { - NumberPointsInfo.identifier, - new IntVerifier, - Optional::Yes, - NumberPointsInfo.description - }, - { - ShadowLengthInfo.identifier, - new DoubleVerifier, - Optional::Yes, - ShadowLengthInfo.description - }, - { - ShadowColorInfo.identifier, - new DoubleVector3Verifier, - Optional::Yes, - ShadowColorInfo.description - }, - { - TerminatorTypeInfo.identifier, - new StringInListVerifier({ - // Synchronized with SpiceManager::terminatorTypeFromString - "UMBRAL", "PENUMBRAL" - }), - Optional::No, - TerminatorTypeInfo.description - }, - { - LightSourceInfo.identifier, - new StringVerifier, - Optional::No, - LightSourceInfo.description - }, - { - ObserverInfo.identifier, - new StringVerifier, - Optional::No, - ObserverInfo.description - }, - { - BodyInfo.identifier, - new StringVerifier, - Optional::No, - BodyInfo.description - }, - { - BodyFrameInfo.identifier, - new StringVerifier, - Optional::No, - BodyFrameInfo.description - }, - { - AberrationInfo.identifier, - new StringInListVerifier({ - // SpiceManager::AberrationCorrection::AberrationCorrection - "NONE", "LT", "LT+S", "CN", "CN+S" - }), - Optional::No, - AberrationInfo.description - }, - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "newhorizons_renderable_shadowcylinder"; + return doc; } RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dictionary) @@ -200,34 +164,18 @@ RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dict , _bodyFrame(BodyFrameInfo) , _aberration(AberrationInfo) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "RenderableShadowCylinder" - ); + const Parameters p = codegen::bake(dictionary); addProperty(_opacity); registerUpdateRenderBinFromOpacity(); - if (dictionary.hasKey(NumberPointsInfo.identifier)) { - _numberOfPoints = static_cast( - dictionary.value(NumberPointsInfo.identifier) - ); - } + _numberOfPoints = p.numberOfPoints.value_or(_numberOfPoints); addProperty(_numberOfPoints); - - if (dictionary.hasKey(ShadowLengthInfo.identifier)) { - _shadowLength = static_cast( - dictionary.value(ShadowLengthInfo.identifier) - ); - } + _shadowLength = p.shadowLength.value_or(_shadowLength); addProperty(_shadowLength); - - if (dictionary.hasKey(ShadowColorInfo.identifier)) { - _shadowColor = dictionary.value(ShadowLengthInfo.identifier); - } + _shadowColor = p.shadowColor.value_or(_shadowColor); _shadowColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(_shadowColor); @@ -236,16 +184,21 @@ RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dict { static_cast(SpiceManager::TerminatorType::Umbral), "Umbral" }, { static_cast(SpiceManager::TerminatorType::Penumbral), "Penumbral" } }); - _terminatorType = static_cast(SpiceManager::terminatorTypeFromString( - dictionary.value(TerminatorTypeInfo.identifier) - )); + switch (p.terminatorType) { + case Parameters::TerminatorType::Umbral: + _terminatorType = static_cast(SpiceManager::TerminatorType::Umbral); + break; + case Parameters::TerminatorType::Penumbral: + _terminatorType = static_cast(SpiceManager::TerminatorType::Penumbral); + break; + } addProperty(_terminatorType); - _lightSource = dictionary.value(LightSourceInfo.identifier); - _observer = dictionary.value(ObserverInfo.identifier); - _body = dictionary.value(BodyInfo.identifier); - _bodyFrame = dictionary.value(BodyFrameInfo.identifier); + _lightSource = p.lightSource; + _observer = p.observer; + _body = p.body; + _bodyFrame = p.bodyFrame; using T = SpiceManager::AberrationCorrection::Type; _aberration.addOptions({ @@ -257,7 +210,7 @@ RenderableShadowCylinder::RenderableShadowCylinder(const ghoul::Dictionary& dict }); SpiceManager::AberrationCorrection aberration = SpiceManager::AberrationCorrection( - dictionary.value(AberrationInfo.identifier) + p.aberration ); _aberration = static_cast(aberration.type); } diff --git a/modules/spacecraftinstruments/util/instrumentdecoder.cpp b/modules/spacecraftinstruments/util/instrumentdecoder.cpp index 9527dd3f9e..a17d11f1f2 100644 --- a/modules/spacecraftinstruments/util/instrumentdecoder.cpp +++ b/modules/spacecraftinstruments/util/instrumentdecoder.cpp @@ -24,53 +24,43 @@ #include +#include +#include #include #include #include +#include namespace { constexpr const char* _loggerCat = "InstrumentDecoder"; - constexpr const char* KeyDetector = "DetectorType"; - constexpr const char* KeySpice = "Spice"; - constexpr const char* KeyStopCommand = "StopCommand"; + + struct [[codegen::Dictionary(InstrumentDecoder)]] Parameters { + std::string detectorType; + std::optional stopCommand; + std::vector spice; + }; +#include "instrumentdecoder_codegen.cpp" } // namespace namespace openspace { InstrumentDecoder::InstrumentDecoder(const ghoul::Dictionary& dictionary) { - if (dictionary.hasValue(KeyDetector)) { - _type = dictionary.value(KeyDetector); - std::for_each( - _type.begin(), - _type.end(), - [](char& in) { in = static_cast(toupper(in)); } - ); - } - else { - ghoul_assert(false, "Instrument has not provided detector type"); - throw ghoul::RuntimeError("Instrument has not provided detector type"); - } + const Parameters p = codegen::bake(dictionary); + _type = p.detectorType; + std::for_each( + _type.begin(), + _type.end(), + [](char& in) { in = static_cast(toupper(in)); } + ); - if (dictionary.hasValue(KeyStopCommand) && _type == "SCANNER") { - _stopCommand = dictionary.value(KeyStopCommand); + if (p.stopCommand.has_value() && _type == "SCANNER") { + _stopCommand = *p.stopCommand; } else { LWARNING("Scanner must provide stop command, please check mod file."); } - if (dictionary.hasValue(KeySpice)) { - ghoul::Dictionary spiceDictionary = dictionary.value(KeySpice); - - _spiceIDs.resize(spiceDictionary.size()); - for (size_t i = 0; i < _spiceIDs.size(); ++i) { - std::string id = spiceDictionary.value(std::to_string(i + 1)); - _spiceIDs[i] = std::move(id); - } - } - else { - ghoul_assert(false, "Instrument did not provide spice ids"); - throw ghoul::RuntimeError("Instrument has not provided detector type"); - } + _spiceIDs = p.spice; } const std::string& InstrumentDecoder::stopCommand() { diff --git a/modules/spacecraftinstruments/util/projectioncomponent.cpp b/modules/spacecraftinstruments/util/projectioncomponent.cpp index 472351fd74..83ef37f558 100644 --- a/modules/spacecraftinstruments/util/projectioncomponent.cpp +++ b/modules/spacecraftinstruments/util/projectioncomponent.cpp @@ -42,36 +42,12 @@ #include #include #include +#include +#include namespace { - constexpr const char* keyPotentialTargets = "PotentialTargets"; - - constexpr const char* keyInstrument = "Instrument.Name"; - constexpr const char* keyInstrumentFovy = "Instrument.Fovy"; - constexpr const char* keyInstrumentAspect = "Instrument.Aspect"; - constexpr const char* keyTranslation = "DataInputTranslation"; constexpr const char* keyTimesTranslation = "TimesDataInputTranslation"; - - constexpr const char* keyProjObserver = "Observer"; - constexpr const char* keyProjTarget = "Target"; - constexpr const char* keyProjAberration = "Aberration"; - - constexpr const char* keySequenceDir = "Sequence"; - constexpr const char* keyTimesSequenceDir = "TimesSequence"; - constexpr const char* keySequenceType = "SequenceType"; - - constexpr const char* keyNeedsTextureMapDilation = "TextureMap"; - constexpr const char* keyNeedsShadowing = "ShadowMap"; - constexpr const char* keyTextureMapAspectRatio = "AspectRatio"; - - constexpr const char* sequenceTypeImage = "image-sequence"; - constexpr const char* sequenceTypePlaybook = "playbook"; - constexpr const char* sequenceTypeHybrid = "hybrid"; - constexpr const char* sequenceTypeInstrumentTimes = "instrument-times"; - constexpr const char* sequenceTypeImageAndInstrumentTimes = - "image-and-instrument-times"; - constexpr const char* placeholderFile = "${DATA}/placeholder.png"; constexpr const char* _loggerCat = "ProjectionComponent"; @@ -113,115 +89,84 @@ namespace { "Triggering this property applies a new size to the underlying projection " "texture. The old texture is resized and interpolated to fit the new size." }; + + struct [[codegen::Dictionary(ProjectionComponent)]] Parameters { + // This value specifies one or more directories from which images are being used + // for image projections. If the sequence type is set to 'playbook', this value is + // ignored + std::optional>> sequence; + + struct Instrument { + // The instrument that is used to perform the projections + std::string name [[codegen::annotation("A SPICE name of an instrument")]]; + + // The field of view in degrees along the y axis + float fovy; + + // The aspect ratio of the instrument in relation between x and y axis + float aspect; + }; + Instrument instrument; + + enum class Type { + ImageSequence [[codegen::key("image-sequence")]], + Playbook [[codegen::key("playbook")]], + Hybrid [[codegen::key("hybrid")]], + InstrumentTimes [[codegen::key("instrument-times")]], + ImageAndInstrumentTimes [[codegen::key("image-and-instrument-times")]] + }; + // This value determines which type of sequencer is used for generating image + // schedules. The 'playbook' is using a custom format designed by the New Horizons + // team, the 'image-sequence' uses lbl files from a directory, and the 'hybrid' + // uses both methods + std::optional sequenceType; + + std::optional eventFile; + + // The observer that is doing the projection. This has to be a valid SPICE name + // or SPICE integer + std::string observer + [[codegen::annotation("A SPICE name of the observing object")]]; + + std::optional timesSequence; + + // The observed object that is projected on. This has to be a valid SPICE name or + // SPICE integer + std::string target [[codegen::annotation("A SPICE name of the observed object")]]; + + // The aberration correction that is supposed to be used for the projection. The + // values for the correction correspond to the SPICE definition as described in + // ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/IDL/cspice/spkezr_c.html + std::string aberration [[codegen::inlist("NONE", "LT", "LT+S", "CN", "CN+S", + "XLT", "XLT+S", "XCN", "XCN+S")]]; + + // The list of potential targets that are involved with the image projection + std::optional> potentialTargets; + + // Determines whether the object requires a self-shadowing algorithm. This is + // necessary if the object is concave and might cast a shadow on itself during + // presentation. The default value is 'false' + std::optional textureMap; + + // Determines whether the object requires a self-shadowing algorithm. This is + // necessary if the object is concave and might cast a shadow on itself during + // presentation. The default value is 'false' + std::optional shadowMap; + + // Sets the desired aspect ratio of the projected texture. This might be necessary + // as planets usually have 2x1 aspect ratios, whereas this does not hold for + // non-planet objects (comets, asteroids, etc). The default value is '1.0' + std::optional aspectRatio; + }; +#include "projectioncomponent_codegen.cpp" } // namespace namespace openspace { documentation::Documentation ProjectionComponent::Documentation() { - using namespace documentation; - return { - "Projection Component", - "newhorizons_projectioncomponent", - { - { - keySequenceDir, - new OrVerifier({ new StringVerifier, new StringListVerifier }), - Optional::Yes, - "This value specifies one or more directories from which images are " - "being used for image projections. If the sequence type is set to " - "'playbook', this value is ignored" - }, - { - keyInstrument, - new StringAnnotationVerifier("A SPICE name of an instrument"), - Optional::No, - "The instrument that is used to perform the projections" - }, - { - keyInstrumentFovy, - new DoubleVerifier, - Optional::No, - "The field of view in degrees along the y axis" - }, - { - keyInstrumentAspect, - new DoubleVerifier, - Optional::No, - "The aspect ratio of the instrument in relation between x and y axis" - }, - { - keySequenceType, - new StringInListVerifier( - { sequenceTypeImage, sequenceTypePlaybook, sequenceTypeHybrid, - sequenceTypeInstrumentTimes, sequenceTypeImageAndInstrumentTimes } - ), - Optional::Yes, - "This value determines which type of sequencer is used for generating " - "image schedules. The 'playbook' is using a custom format designed by " - "the New Horizons team, the 'image-sequence' uses lbl files from a " - "directory, and the 'hybrid' uses both methods." - }, - { - keyProjObserver, - new StringAnnotationVerifier("A SPICE name of the observing object"), - Optional::No, - "The observer that is doing the projection. This has to be a valid SPICE " - "name or SPICE integer." - }, - { - keyProjTarget, - new StringAnnotationVerifier("A SPICE name of the observed object"), - Optional::No, - "The observed object that is projected on. This has to be a valid SPICE " - "name or SPICE integer." - }, - { - keyProjAberration, - new StringInListVerifier({ - // from SpiceManager::AberrationCorrection::AberrationCorrection - "NONE", "LT", "LT+S", "CN", "CN+S", "XLT", "XLT+S", "XCN", "XCN+S" - }), - Optional::No, - "The aberration correction that is supposed to be used for the " - "projection. The values for the correction correspond to the SPICE " - "definition as described in " - "ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/IDL/cspice/spkezr_c.html" - }, - { - keyPotentialTargets, - new StringListVerifier, - Optional::Yes, - "The list of potential targets that are involved with the image " - "projection" - }, - { - keyNeedsTextureMapDilation, - new BoolVerifier, - Optional::Yes, - "Determines whether a dilation step of the texture map has to be " - "performed after each projection. This is necessary if the texture of " - "the projected object is a texture map where the borders are not " - "touching. The default value is 'false'." - }, - { - keyNeedsShadowing, - new BoolVerifier, - Optional::Yes, - "Determines whether the object requires a self-shadowing algorithm. This " - "is necessary if the object is concave and might cast a shadow on itself " - "during presentation. The default value is 'false'." - }, - { - keyTextureMapAspectRatio, - new DoubleVerifier, - Optional::Yes, - "Sets the desired aspect ratio of the projected texture. This might be " - "necessary as planets usually have 2x1 aspect ratios, whereas this does " - "not hold for non-planet objects (comets, asteroids, etc). The default " - "value is '1.0'." - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "newhorizons_projectioncomponent"; + return doc; } ProjectionComponent::ProjectionComponent() @@ -244,162 +189,143 @@ ProjectionComponent::ProjectionComponent() void ProjectionComponent::initialize(const std::string& identifier, const ghoul::Dictionary& dictionary) { - documentation::testSpecificationAndThrow( - Documentation(), - dictionary, - "ProjectionComponent" - ); - _instrumentID = dictionary.value(keyInstrument); - _projectorID = dictionary.value(keyProjObserver); - _projecteeID = dictionary.value(keyProjTarget); - _fovy = static_cast(dictionary.value(keyInstrumentFovy)); - _aspectRatio = static_cast(dictionary.value(keyInstrumentAspect)); + const Parameters p = codegen::bake(dictionary); - _aberration = SpiceManager::AberrationCorrection( - dictionary.value(keyProjAberration) - ); + _instrumentID = p.instrument.name; + _projectorID = p.observer; + _projecteeID = p.target; + _fovy = p.instrument.fovy; + _aspectRatio = p.instrument.aspect; - if (dictionary.hasValue(keyPotentialTargets)) { - const ghoul::Dictionary& potentialTargets = dictionary.value( - keyPotentialTargets - ); + _aberration = SpiceManager::AberrationCorrection(p.aberration); - _potentialTargets.reserve(potentialTargets.size()); - for (size_t i = 1; i <= potentialTargets.size(); ++i) { - _potentialTargets.emplace_back( - potentialTargets.value(std::to_string(i)) - ); - } - } - - if (dictionary.hasValue(keyNeedsTextureMapDilation)) { - _dilation.isEnabled = dictionary.value(keyNeedsTextureMapDilation); - } - - if (dictionary.hasValue(keyNeedsShadowing)) { - _shadowing.isEnabled = dictionary.value(keyNeedsShadowing); - } - - if (dictionary.hasValue(keyTextureMapAspectRatio)) { - _projectionTextureAspectRatio = - static_cast(dictionary.value(keyTextureMapAspectRatio)); - } + _potentialTargets = p.potentialTargets.value_or(_potentialTargets); + _dilation.isEnabled = p.textureMap.value_or(_dilation.isEnabled); + _shadowing.isEnabled = p.shadowMap.value_or(_shadowing.isEnabled); + _projectionTextureAspectRatio = p.aspectRatio.value_or(_projectionTextureAspectRatio); - if (!dictionary.hasKey(keySequenceDir)) { + if (!p.sequence.has_value()) { + // we are done here, the rest only applies if we do have a sequence return; } + std::variant> sequence = *p.sequence; + std::vector sequenceSources; - // Due to the documentation check above it must either be one or the other - if (dictionary.hasValue(keySequenceDir)) { - sequenceSources.push_back(absPath(dictionary.value(keySequenceDir))); + if (std::holds_alternative(sequence)) { + sequenceSources.push_back(absPath(std::get(sequence))); } else { - ghoul::Dictionary sourcesDict = dictionary.value( - keySequenceDir + ghoul_assert( + std::holds_alternative>(sequence), + "Something is wrong with the generated documentation" ); - for (int i = 1; i <= static_cast(sourcesDict.size()); ++i) { - sequenceSources.push_back( - absPath(sourcesDict.value(std::to_string(i))) - ); + sequenceSources = std::get>(sequence); + for (std::string& s : sequenceSources) { + s = absPath(s); } } - const std::string& sequenceType = dictionary.value(keySequenceType); - // Important: client must define translation-list in mod file IFF playbook - if (!dictionary.hasKey(keyTranslation)) { - LWARNING("No playbook translation provided, spice calls must match playbook!"); - return; + + if (!p.sequenceType.has_value()) { + throw ghoul::RuntimeError("Missing SequenceType"); } ghoul::Dictionary translationDictionary; if (dictionary.hasValue(keyTranslation)) { translationDictionary = dictionary.value(keyTranslation); } + else { + LWARNING("No playbook translation provided, spice calls must match playbook!"); + return; + } std::vector> parsers; for (std::string& sequenceSource : sequenceSources) { - if (sequenceType == sequenceTypePlaybook) { - parsers.push_back( - std::make_unique( - identifier, - std::move(sequenceSource), - _projectorID, - translationDictionary, - _potentialTargets - ) - ); - } - else if (sequenceType == sequenceTypeImage) { - parsers.push_back( - std::make_unique( - identifier, - std::move(sequenceSource), - translationDictionary - ) - ); - } - else if (sequenceType == sequenceTypeHybrid) { - //first read labels - parsers.push_back( - std::make_unique( - identifier, - std::move(sequenceSource), - translationDictionary - ) - ); - - if (dictionary.hasKey("EventFile")) { - std::string eventFile = dictionary.value("EventFile"); + switch (*p.sequenceType) { + case Parameters::Type::Playbook: parsers.push_back( std::make_unique( identifier, - absPath(eventFile), + std::move(sequenceSource), _projectorID, translationDictionary, _potentialTargets ) ); - } - else { - LWARNING("No eventfile has been provided, please check modfiles"); - } - } - else if (sequenceType == sequenceTypeInstrumentTimes) { - parsers.push_back( - std::make_unique( - identifier, - std::move(sequenceSource), - translationDictionary - ) - ); - } - else if (sequenceType == sequenceTypeImageAndInstrumentTimes) { - parsers.push_back( - std::make_unique( - identifier, - std::move(sequenceSource), - translationDictionary + break; + case Parameters::Type::ImageSequence: + parsers.push_back( + std::make_unique( + identifier, + std::move(sequenceSource), + translationDictionary ) - ); + ); + break; + case Parameters::Type::Hybrid: + // first read labels + parsers.push_back( + std::make_unique( + identifier, + std::move(sequenceSource), + translationDictionary + ) + ); - std::string timesSequenceSource = absPath( - dictionary.value(keyTimesSequenceDir) - ); - ghoul::Dictionary timesTranslationDictionary; - if (dictionary.hasValue(keyTimesTranslation)) { - timesTranslationDictionary = - dictionary.value(keyTimesTranslation); + if (p.eventFile.has_value()) { + parsers.push_back( + std::make_unique( + identifier, + absPath(*p.eventFile), + _projectorID, + translationDictionary, + _potentialTargets + ) + ); + } + else { + LWARNING("No eventfile has been provided, please check modfiles"); + } + break; + case Parameters::Type::InstrumentTimes: + parsers.push_back( + std::make_unique( + identifier, + std::move(sequenceSource), + translationDictionary + ) + ); + break; + case Parameters::Type::ImageAndInstrumentTimes: + { + parsers.push_back( + std::make_unique( + identifier, + std::move(sequenceSource), + translationDictionary + ) + ); + + if (!p.timesSequence.has_value()) { + throw ghoul::RuntimeError("Could not find required TimesSequence"); + } + ghoul::Dictionary timesTranslationDictionary; + if (dictionary.hasValue(keyTimesTranslation)) { + timesTranslationDictionary = + dictionary.value(keyTimesTranslation); + } + + parsers.push_back( + std::make_unique( + identifier, + absPath(*p.timesSequence), + timesTranslationDictionary + ) + ); + break; } - - parsers.push_back( - std::make_unique( - identifier, - std::move(timesSequenceSource), - timesTranslationDictionary - ) - ); } } diff --git a/modules/sync/tasks/syncassettask.cpp b/modules/sync/tasks/syncassettask.cpp index 777a7bf9ad..b670301dff 100644 --- a/modules/sync/tasks/syncassettask.cpp +++ b/modules/sync/tasks/syncassettask.cpp @@ -56,12 +56,6 @@ documentation::Documentation SyncAssetTask::documentation() { "SyncAssetTask", "sync_asset_task", { - { - "Type", - new StringEqualVerifier("SyncAssetTask"), - Optional::No, - "The type of this task" - }, { KeyAsset, new StringAnnotationVerifier("A file path to an asset"), diff --git a/modules/volume/tasks/generaterawvolumetask.cpp b/modules/volume/tasks/generaterawvolumetask.cpp index 0eed96877b..68e889fc72 100644 --- a/modules/volume/tasks/generaterawvolumetask.cpp +++ b/modules/volume/tasks/generaterawvolumetask.cpp @@ -182,12 +182,6 @@ documentation::Documentation GenerateRawVolumeTask::documentation() { "GenerateRawVolumeTask", "generate_raw_volume_task", { - { - "Type", - new StringEqualVerifier("GenerateRawVolumeTask"), - Optional::No, - "The type of this task", - }, { KeyValueFunction, new StringAnnotationVerifier("A lua expression that returns a function " diff --git a/modules/webbrowser/codegentest.exe.manifest b/modules/webbrowser/codegentest.exe.manifest new file mode 100644 index 0000000000..d36f084b65 --- /dev/null +++ b/modules/webbrowser/codegentest.exe.manifest @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f095c64271..6f62fad495 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -476,6 +476,8 @@ target_precompile_headers(openspace-core PRIVATE ) +add_dependencies(openspace-core run_codegen) + configure_file( ${OPENSPACE_CMAKE_EXT_DIR}/openspace_header.template ${CMAKE_BINARY_DIR}/_generated/include/openspace/openspace.h diff --git a/src/documentation/documentation.cpp b/src/documentation/documentation.cpp index 04ba4bf594..ef1bfc8843 100644 --- a/src/documentation/documentation.cpp +++ b/src/documentation/documentation.cpp @@ -239,7 +239,7 @@ void testSpecificationAndThrow(const Documentation& documentation, // Perform testing against the documentation/specification TestResult testResult = testSpecification(documentation, dictionary); if (!testResult.success) { - throw SpecificationError(std::move(testResult), std::move(component)); + throw SpecificationError(testResult, component); } } diff --git a/src/documentation/verifier.cpp b/src/documentation/verifier.cpp index 6cd31004f5..3cea6786bc 100644 --- a/src/documentation/verifier.cpp +++ b/src/documentation/verifier.cpp @@ -133,11 +133,11 @@ std::string DoubleVerifier::type() const { return "Double"; } -TestResult IntVerifier::operator()(const ghoul::Dictionary & dict, +TestResult IntVerifier::operator()(const ghoul::Dictionary& dict, const std::string & key) const { if (dict.hasValue(key)) { - // We we have a key and the value is int, we are done + // We have a key and the value is int, we are done return { true, {}, {} }; } else { @@ -177,6 +177,120 @@ std::string StringVerifier::type() const { return "String"; } +template <> +TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, + const std::string& key) const +{ + if (dict.hasValue(key)) { + return { true, {}, {} }; + } + else { + if (dict.hasKey(key)) { + if (dict.hasValue(key)) { + glm::dvec2 value = dict.value(key); + glm::dvec2 intPart; + glm::bvec2 isInt = { + modf(value.x, &intPart.x) == 0.0, + modf(value.y, &intPart.y) == 0.0 + }; + if (isInt.x && isInt.y) { + return { true, {}, {} }; + } + else { + return { + false, + {{ key, TestResult::Offense::Reason::WrongType }}, + {} + }; + } + } + else { + return { false, {{ key, TestResult::Offense::Reason::WrongType }}, {} }; + } + } + else { + return { false, {{ key, TestResult::Offense::Reason::MissingKey }}, {} }; + } + } +} + +template <> +TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, + const std::string& key) const +{ + if (dict.hasValue(key)) { + return { true, {}, {} }; + } + else { + if (dict.hasKey(key)) { + if (dict.hasValue(key)) { + glm::dvec3 value = dict.value(key); + glm::dvec3 intPart; + glm::bvec3 isInt = { + modf(value.x, &intPart.x) == 0.0, + modf(value.y, &intPart.y) == 0.0, + modf(value.z, &intPart.z) == 0.0 + }; + if (isInt.x && isInt.y && isInt.z) { + return { true, {}, {} }; + } + else { + return { + false, + {{ key, TestResult::Offense::Reason::WrongType }}, + {} + }; + } + } + else { + return { false, {{ key, TestResult::Offense::Reason::WrongType }}, {} }; + } + } + else { + return { false, {{ key, TestResult::Offense::Reason::MissingKey }}, {} }; + } + } +} + +template <> +TestResult TemplateVerifier::operator()(const ghoul::Dictionary& dict, + const std::string& key) const +{ + if (dict.hasValue(key)) { + return { true, {}, {} }; + } + else { + if (dict.hasKey(key)) { + if (dict.hasValue(key)) { + glm::dvec4 value = dict.value(key); + glm::dvec4 intPart; + glm::bvec4 isInt = { + modf(value.x, &intPart.x) == 0.0, + modf(value.y, &intPart.y) == 0.0, + modf(value.z, &intPart.z) == 0.0, + modf(value.w, &intPart.w) == 0.0 + }; + if (isInt.x && isInt.y && isInt.z && isInt.w) { + return { true, {}, {} }; + } + else { + return { + false, + {{ key, TestResult::Offense::Reason::WrongType }}, + {} + }; + } + } + else { + return { false, {{ key, TestResult::Offense::Reason::WrongType }}, {} }; + } + } + else { + return { false, {{ key, TestResult::Offense::Reason::MissingKey }}, {} }; + } + } +} + TableVerifier::TableVerifier(std::vector documentationEntries) : documentations(std::move(documentationEntries)) {} diff --git a/src/interaction/tasks/convertrecfileversiontask.cpp b/src/interaction/tasks/convertrecfileversiontask.cpp index 8bfaac639f..83eea9640c 100644 --- a/src/interaction/tasks/convertrecfileversiontask.cpp +++ b/src/interaction/tasks/convertrecfileversiontask.cpp @@ -107,12 +107,6 @@ documentation::Documentation ConvertRecFileVersionTask::documentation() { "ConvertRecFileVersionTask", "convert_file_version_task", { - { - "Type", - new StringEqualVerifier("ConvertRecFileVersionTask"), - Optional::No, - "The type of this task", - }, { KeyInFilePath, new StringAnnotationVerifier("A valid filename to convert"), diff --git a/src/interaction/tasks/convertrecformattask.cpp b/src/interaction/tasks/convertrecformattask.cpp index cc759a2a99..3651d49868 100644 --- a/src/interaction/tasks/convertrecformattask.cpp +++ b/src/interaction/tasks/convertrecformattask.cpp @@ -314,12 +314,6 @@ documentation::Documentation ConvertRecFormatTask::documentation() { "ConvertRecFormatTask", "convert_format_task", { - { - "Type", - new StringEqualVerifier("ConvertRecFormatTask"), - Optional::No, - "The type of this task", - }, { KeyInFilePath, new StringAnnotationVerifier("A valid filename to convert"), diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index d474297c04..9236c2850a 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -33,10 +33,10 @@ #include #include #include +#include namespace { constexpr const char* KeyType = "Type"; - constexpr const char* KeyTag = "Tag"; constexpr openspace::properties::Property::PropertyInfo EnabledInfo = { "Enabled", @@ -63,49 +63,47 @@ namespace { "Bounding Sphere", "The size of the bounding sphere radius." }; + struct [[codegen::Dictionary(Renderable)]] Parameters { + // [[codegen::verbatim(EnabledInfo.description)]] + std::optional enabled; + // [[codegen::verbatim(OpacityInfo.description)]] + std::optional opacity [[codegen::inrange(0.0, 1.0)]]; + + // A single tag or a list of tags that this renderable will respond to when + // setting properties + std::optional, std::string>> tag; + + // [[codegen::verbatim(RenderableTypeInfo.description)]] + std::optional type; + + // [[codegen::verbatim(BoundingSphereInfo.description)]] + std::optional boundingSphere; + }; +#include "renderable_codegen.cpp" } // namespace namespace openspace { documentation::Documentation Renderable::Documentation() { - using namespace openspace::documentation; - - return { - "Renderable", - "renderable", - { - { - KeyType, - new StringAnnotationVerifier("A valid Renderable created by a factory"), - Optional::No, - "This key specifies the type of Renderable that gets created. It has to " - "be one of the valid Renderables that are available for creation (see " - "the FactoryDocumentation for a list of possible Renderables), which " - "depends on the configration of the application" - }, - { - EnabledInfo.identifier, - new BoolVerifier, - Optional::Yes, - EnabledInfo.description - }, - { - OpacityInfo.identifier, - new DoubleInRangeVerifier(0.0, 1.0), - Optional::Yes, - OpacityInfo.description - } - } - }; + documentation::Documentation doc = codegen::doc(); + doc.id = "renderable"; + return doc; } ghoul::mm_unique_ptr Renderable::createFromDictionary( - const ghoul::Dictionary& dictionary) + ghoul::Dictionary dictionary) { + if (!dictionary.hasKey(KeyType)) { + throw ghoul::RuntimeError("Tried to create Renderable but no 'Type' was found"); + } + + // This should be done in the constructor instead with noexhaustive documentation::testSpecificationAndThrow(Documentation(), dictionary, "Renderable"); std::string renderableType = dictionary.value(KeyType); + // Now we no longer need the type variable + dictionary.removeValue(KeyType); auto factory = FactoryManager::ref().factory(); ghoul_assert(factory, "Renderable factory did not exist"); @@ -130,46 +128,34 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) // I can't come up with a good reason not to do this for all renderables registerUpdateRenderBinFromOpacity(); - if (dictionary.hasValue(KeyTag)) { - std::string tagName = dictionary.value(KeyTag); - if (!tagName.empty()) { - addTag(std::move(tagName)); + const Parameters p = codegen::bake(dictionary); + + if (p.tag.has_value()) { + if (std::holds_alternative(*p.tag)) { + if (!std::get(*p.tag).empty()) { + addTag(std::get(*p.tag)); + } } - } - else if (dictionary.hasValue(KeyTag)) { - const ghoul::Dictionary& tagNames = dictionary.value(KeyTag); - for (std::string_view key : tagNames.keys()) { - std::string tagName = tagNames.value(key); - if (!tagName.empty()) { - addTag(std::move(tagName)); + else { + ghoul_assert(std::holds_alternative>(*p.tag), ""); + for (std::string tag : std::get>(*p.tag)) { + addTag(std::move(tag)); } } } - if (dictionary.hasKey(EnabledInfo.identifier)) { - _enabled = dictionary.value(EnabledInfo.identifier); - } - - if (dictionary.hasKey(OpacityInfo.identifier)) { - _opacity = static_cast(dictionary.value(OpacityInfo.identifier)); - } - + _enabled = p.enabled.value_or(_enabled); addProperty(_enabled); - //set type for UI - if (dictionary.hasKey(RenderableTypeInfo.identifier)) { - _renderableType = dictionary.value( - RenderableTypeInfo.identifier - ); - } - - if (dictionary.hasKey(BoundingSphereInfo.identifier)) { - _boundingSphere = static_cast( - dictionary.value(BoundingSphereInfo.identifier) - ); - } + _opacity = p.opacity.value_or(_opacity); + // We don't add the property here as subclasses should decide on their own whether + // they to expose the opacity or not + // set type for UI + _renderableType = p.type.value_or(_renderableType); addProperty(_renderableType); + + _boundingSphere = p.boundingSphere.value_or(_boundingSphere); addProperty(_boundingSphere); } @@ -198,7 +184,7 @@ SurfacePositionHandle Renderable::calculateSurfacePositionHandle( { const glm::dvec3 directionFromCenterToTarget = glm::normalize(targetModelSpace); return { - directionFromCenterToTarget * static_cast(boundingSphere()), + directionFromCenterToTarget * boundingSphere(), directionFromCenterToTarget, 0.0 }; diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index 9eafbe0650..38ddc471bf 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include "scenegraphnode_doc.inl" @@ -263,16 +264,8 @@ ghoul::mm_unique_ptr SceneGraphNode::createFromDictionary( ghoul::Dictionary renderableDictionary = dictionary.value(KeyRenderable); - renderableDictionary.setValue(KeyIdentifier, result->_identifier); - result->_renderable = Renderable::createFromDictionary(renderableDictionary); - if (result->_renderable == nullptr) { - LERROR(fmt::format( - "Failed to create renderable for SceneGraphNode '{}'", - result->identifier() - )); - return nullptr; - } + ghoul_assert(result->_renderable, "Failed to create Renderable"); result->addPropertySubOwner(result->_renderable.get()); LDEBUG(fmt::format( "Successfully created renderable for '{}'", result->identifier() @@ -689,7 +682,7 @@ void SceneGraphNode::computeScreenSpaceData(RenderData& newData) { glm::ivec2 res = global::windowDelegate->currentSubwindowSize(); // Get the radius of node - double nodeRadius = static_cast(this->boundingSphere()); + double nodeRadius = boundingSphere(); // Distance from the camera to the node double distFromCamToNode = glm::distance(cam.positionVec3(), worldPos) - nodeRadius; diff --git a/support/cmake/set_openspace_compile_settings.cmake b/support/cmake/set_openspace_compile_settings.cmake index 3154376b7f..3dee265c93 100644 --- a/support/cmake/set_openspace_compile_settings.cmake +++ b/support/cmake/set_openspace_compile_settings.cmake @@ -31,6 +31,7 @@ function (set_openspace_compile_settings target) "/w44062" # enumerator 'identifier' in a switch of enum 'enumeration' is not handled "/wd4127" # conditional expression is constant "/wd4201" # nonstandard extension used : nameless struct/union + "/wd5030" # attribute 'attribute' is not recognized "/w44255" # 'function': no function prototype given: converting '()' to '(void)' "/w44263" # 'function': member function does not override any base class virtual member function "/w44264" # 'virtual_function': no override available for virtual member function from base 'class'; function is hidden @@ -173,6 +174,7 @@ function (set_openspace_compile_settings target) "-Wvla" "-Wzero-length-array" "-Wno-missing-braces" + "-Wno-unknown-attributes" ) if (OPENSPACE_WARNINGS_AS_ERRORS) set(CLANG_WARNINGS ${CLANG_WARNINGS} "-Werror") @@ -206,6 +208,8 @@ function (set_openspace_compile_settings target) "-Wold-style-cast" "-Woverloaded-virtual" "-Wno-long-long" + "-Wno-ignored-attributes" + "-Wno-attributes" ) if (OPENSPACE_WARNINGS_AS_ERRORS) set(GCC_WARNINGS ${CLANG_WARNINGS} "-Werror") diff --git a/support/coding/codegen b/support/coding/codegen new file mode 160000 index 0000000000..1e942f53f1 --- /dev/null +++ b/support/coding/codegen @@ -0,0 +1 @@ +Subproject commit 1e942f53f1e9543bc5040c2a8d52eeea1559b788 From 4a80b83df89ffb3ac769bb2a3197d261bfa1059e Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Tue, 9 Feb 2021 13:37:25 +0100 Subject: [PATCH 41/41] Update Ghoul repository --- ext/ghoul | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ghoul b/ext/ghoul index 0b46e63ebe..2f1bb7c483 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 0b46e63ebef03b4c08f3ea6f7e2c43cda73e8ea2 +Subproject commit 2f1bb7c483f4792317b8f1a3da17e2270c0d0ae7