From bf2fee7d71f1c537149ef9bedaf715bdb24cf918 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 31 Mar 2025 22:30:31 +0200 Subject: [PATCH 01/11] Submodule updates (#3586) Update submodules and also provide compatibility with CMake 4.0. - assimp: `v5.4.1` -> `v5.4.3` - catch: `v3.5.3` -> `3.8.0` - date: `master` -> `v3.0.3` - freetype2: `v2.10.4` -> `v2.13.3`. Also change to freetypes original Git server - glbindings: `v3.3.0` -> `v3.4.0` - glm: `master` -> `v1.0.2` - scnlib: `v4.0.1` -> `v2.0.2` - soloud: `master` -> `master` - tinyxml: `master` -> `v11.0.0` - tracy: `v0.10.1` -> `v0.11.0` --- CMakeLists.txt | 6 ++++++ apps/OpenSpace/ext/sgct | 2 +- ext/date | 2 +- ext/ghoul | 2 +- modules/audio/ext/soloud | 2 +- modules/fitsfilereader/ext/CCfits | 2 +- modules/fitsfilereader/ext/cfitsio | 2 +- modules/kameleon/ext/kameleon | 2 +- modules/webbrowser/CMakeLists.txt | 2 +- 9 files changed, 14 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d4304ad6d..32390f3be2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,12 @@ cmake_policy(VERSION 3.25) project(OpenSpace) +# CMake 4.0 will no longer allow minimum required version below 3.5 and some of our +# dependencies have not been updated to reflect this. To make things work, we blanked +# require to 3.10 here to remove those issues. Once CMake configures and generates +# successfully without this next line, it can be removed +set(CMAKE_POLICY_VERSION_MINIMUM 3.10) + set(OPENSPACE_RELEASE_BUILD OFF) set(OPENSPACE_VERSION_MAJOR) set(OPENSPACE_VERSION_MINOR) diff --git a/apps/OpenSpace/ext/sgct b/apps/OpenSpace/ext/sgct index 1418d9beb2..7ac1bd4891 160000 --- a/apps/OpenSpace/ext/sgct +++ b/apps/OpenSpace/ext/sgct @@ -1 +1 @@ -Subproject commit 1418d9beb25ad325f9e9e831acee22317e6b2578 +Subproject commit 7ac1bd4891efb2e34f6574a26e591d4a984e8e6b diff --git a/ext/date b/ext/date index 569b2d6785..5bdb7e6f31 160000 --- a/ext/date +++ b/ext/date @@ -1 +1 @@ -Subproject commit 569b2d678547985d0ead3b73ee93a28919000887 +Subproject commit 5bdb7e6f31fac909c090a46dbd9fea27b6e609a4 diff --git a/ext/ghoul b/ext/ghoul index 2972e7b963..8d73afb420 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit 2972e7b963abe1a0ddd57efd8aaf28840a8da37e +Subproject commit 8d73afb420eee59881df53ee3dba998fbeaec595 diff --git a/modules/audio/ext/soloud b/modules/audio/ext/soloud index 1157475881..e82fd32c1f 160000 --- a/modules/audio/ext/soloud +++ b/modules/audio/ext/soloud @@ -1 +1 @@ -Subproject commit 1157475881da0d7f76102578255b937c7d4e8f57 +Subproject commit e82fd32c1f62183922f08c14c814a02b58db1873 diff --git a/modules/fitsfilereader/ext/CCfits b/modules/fitsfilereader/ext/CCfits index 15e78f599d..d9f9811b3e 160000 --- a/modules/fitsfilereader/ext/CCfits +++ b/modules/fitsfilereader/ext/CCfits @@ -1 +1 @@ -Subproject commit 15e78f599dcf619a573cc011e32b2635be9bf3dc +Subproject commit d9f9811b3ef639d4d185385dc9b6cefe7f722c59 diff --git a/modules/fitsfilereader/ext/cfitsio b/modules/fitsfilereader/ext/cfitsio index 8d98f1495b..49258f81de 160000 --- a/modules/fitsfilereader/ext/cfitsio +++ b/modules/fitsfilereader/ext/cfitsio @@ -1 +1 @@ -Subproject commit 8d98f1495b8c762f1c56e79da33cbd3c7d623d80 +Subproject commit 49258f81ded8e78bc2bcc74fab44770c822b32b6 diff --git a/modules/kameleon/ext/kameleon b/modules/kameleon/ext/kameleon index eee25cf7f4..91485053e1 160000 --- a/modules/kameleon/ext/kameleon +++ b/modules/kameleon/ext/kameleon @@ -1 +1 @@ -Subproject commit eee25cf7f4d06dc72fd057326cf6b337a4df8e24 +Subproject commit 91485053e1c260b337d1a9fd770c441abc0aa4a1 diff --git a/modules/webbrowser/CMakeLists.txt b/modules/webbrowser/CMakeLists.txt index fac4e9a432..51e6610443 100644 --- a/modules/webbrowser/CMakeLists.txt +++ b/modules/webbrowser/CMakeLists.txt @@ -38,7 +38,7 @@ set(PROJECT_ARCH "x86_64") # reserved. Use of this source code is governed by a BSD-style license that # can be found in the LICENSE file. -cmake_minimum_required(VERSION 2.8.12.1) +cmake_minimum_required(VERSION 3.10) # Use folders in the resulting project files. set_property(GLOBAL PROPERTY OS_FOLDERS ON) From 070d1180e53665999c72d8baf4c7250d976fe4a4 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 1 Apr 2025 10:13:47 +0200 Subject: [PATCH 02/11] Fix issue with scnlib update --- modules/space/kepler.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/modules/space/kepler.cpp b/modules/space/kepler.cpp index 8cf8cbadfc..730594b7d9 100644 --- a/modules/space/kepler.cpp +++ b/modules/space/kepler.cpp @@ -208,12 +208,25 @@ namespace { if (e.find('.') == std::string::npos) { e += ".0"; } - // @TODO(abock, 2024-05-20) 'd' suffix is needed until scnlib updates to v3 - auto res = scn::scan(e, "{:2d}{}"); - if (!res) { + if (e.size() <= 2) { + throw ghoul::RuntimeError( + std::format("Error parsing epoch '{}'. Invalid date string", epoch) + ); + } + + std::string_view yearStr = std::string_view(e).substr(0, 2); + std::string_view daysInYearStr = std::string_view(e).substr(2); + auto resYear = scn::scan(yearStr, "{}"); + if (!resYear) { throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch)); } - auto [year, daysInYear] = res->values(); + int year = resYear->value(); + + auto resDaysInYear = scn::scan(daysInYearStr, "{}"); + if (!resDaysInYear) { + throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch)); + } + double daysInYear = resDaysInYear->value(); year += year > 57 ? 1900 : 2000; const int daysSince2000 = countDays(year); @@ -336,9 +349,8 @@ namespace { // We have the first form int month = 0; int days = 0; - // @TODO(abock, 2024-05-20) 'd' suffix is needed until scnlib updates to v3 auto res = scn::scan( - epoch, "{:4d}-{:2d}-{:2d}T{:2d}:{:2d}:{}" + epoch, "{:4}-{:2}-{:2}T{:2}:{:2}:{}" ); if (!res) { throw ghoul::RuntimeError(std::format("Error parsing epoch '{}'", epoch)); @@ -350,9 +362,8 @@ namespace { else if (pos == 8) { // We have the second form - // @TODO(abock, 2024-05-20) 'd' suffix is needed until scnlib updates to v3 auto res = scn::scan( - epoch, "{:4d}-{:3d}T{:2d}:{:2d}:{}" + epoch, "{:4}-{:3}T{:2}:{:2}:{}" //date.year, date.nDays, date.hours, date.minutes, date.seconds ); if (!res) { From 80955e3ec1fb821af95f48a0242fd5e7d0fda58c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 1 Apr 2025 12:45:35 +0200 Subject: [PATCH 03/11] Add ScreenSpaceRenderableRenderable class (#3575) --- .../renderablerenderable.asset | 22 ++ .../renderablerenderable_axes.asset | 24 ++ .../renderablerenderable_model-distance.asset | 41 +++ .../renderablerenderable_model.asset | 47 +++ modules/base/CMakeLists.txt | 2 + modules/base/basemodule.cpp | 5 + .../base/rendering/screenspacedashboard.cpp | 2 +- modules/base/rendering/screenspacedashboard.h | 2 +- .../base/rendering/screenspaceframebuffer.cpp | 31 +- .../base/rendering/screenspaceframebuffer.h | 6 +- .../screenspacerenderablerenderable.cpp | 307 ++++++++++++++++++ .../screenspacerenderablerenderable.h | 76 +++++ src/properties/propertyowner.cpp | 3 +- src/scene/scenegraphnode.cpp | 2 +- 14 files changed, 540 insertions(+), 30 deletions(-) create mode 100644 data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable.asset create mode 100644 data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_axes.asset create mode 100644 data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_model-distance.asset create mode 100644 data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_model.asset create mode 100644 modules/base/rendering/screenspacerenderablerenderable.cpp create mode 100644 modules/base/rendering/screenspacerenderablerenderable.h diff --git a/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable.asset b/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable.asset new file mode 100644 index 0000000000..636a0d96b8 --- /dev/null +++ b/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable.asset @@ -0,0 +1,22 @@ +-- Basic +-- Creates a screenspace image that shows a spherical grid as an example for any +-- [Renderable](#renderable) that can be displayed. + +local Object = { + Type = "ScreenSpaceRenderableRenderable", + Identifier = "ScreenSpaceRenderableRenderable_Example", + Renderable = { + Type = "RenderableSphericalGrid", + Opacity = 1.0, + Color = { 0.3, 0.84, 1.0 }, + LineWidth = 2.0 + } +} + +asset.onInitialize(function() + openspace.addScreenSpaceRenderable(Object) +end) + +asset.onDeinitialize(function() + openspace.removeScreenSpaceRenderable(Object) +end) diff --git a/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_axes.asset b/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_axes.asset new file mode 100644 index 0000000000..48e264e518 --- /dev/null +++ b/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_axes.asset @@ -0,0 +1,24 @@ +-- Axes +-- Creates a screenspace image that renders three Cartesian axes into the screen space +-- window. This example also modifies the original camera position to give an oblique view +-- onto the axes and increases the field of view of the camera to a wider degree. We also +-- set the background color to be fully opaque to make it easier to see the axes. + +local Object = { + Type = "ScreenSpaceRenderableRenderable", + Identifier = "ScreenSpaceRenderableRenderable_Example_Axes", + Renderable = { + Type = "RenderableCartesianAxes" + }, + BackgroundColor = { 0.0, 0.0, 0.0, 1.0 }, + CameraPosition = { 1.0, 1.0, 1.0 }, + CameraFov = 80.0 +} + +asset.onInitialize(function() + openspace.addScreenSpaceRenderable(Object) +end) + +asset.onDeinitialize(function() + openspace.removeScreenSpaceRenderable(Object) +end) diff --git a/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_model-distance.asset b/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_model-distance.asset new file mode 100644 index 0000000000..ec19a4bd1b --- /dev/null +++ b/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_model-distance.asset @@ -0,0 +1,41 @@ +-- Model Distance +-- Creates a screen space window into which 3D model of the Eiffel tower is rendered. As +-- the objects are rendered in meter scale, and the Eiffel tower is about 300m tall, we +-- place the camera at a great distance to be able to see the entire Eiffel tower at the +-- same time. + +-- Download the model file for the Eiffel tower +local modelFolder = asset.resource({ + Name = "Scale Eiffel Tower", + Type = "HttpSynchronization", + Identifier = "scale_model_eiffel_tower", + Version = 1 +}) + +local Object = { + Type = "ScreenSpaceRenderableRenderable", + Identifier = "ScreenSpaceRenderableRenderable_Example_ModelDistance", + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "eiffeltower.osmodel", + RotationVector = { 0.0, 45.0, 0.0 }, + LightSources = { + { + Identifier = "Camera", + Type = "CameraLightSource", + Intensity = 5.0 + } + } + }, + Scale = 1.25, + CameraPosition = { 0.0, 3500.0, 9000.0 }, + CameraCenter = { 0.0, 2750.0, 0.0 } +} + +asset.onInitialize(function() + openspace.addScreenSpaceRenderable(Object) +end) + +asset.onDeinitialize(function() + openspace.removeScreenSpaceRenderable(Object) +end) diff --git a/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_model.asset b/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_model.asset new file mode 100644 index 0000000000..19abddfac3 --- /dev/null +++ b/data/assets/examples/screenspacerenderable/screenspacerenderablerenderable/renderablerenderable_model.asset @@ -0,0 +1,47 @@ +-- Model +-- Creates a screen space window into which 3D model of the Eiffel tower is rendered. As +-- the objects are rendered in meter scale, and the Eiffel tower is about 300m tall, we +-- both shrink the rendering to make the entire model fit into the view and also modify +-- the position of the camera. + +-- Download the model file for the Eiffel tower +local modelFolder = asset.resource({ + Name = "Scale Eiffel Tower", + Type = "HttpSynchronization", + Identifier = "scale_model_eiffel_tower", + Version = 1 +}) + +local Object = { + Type = "ScreenSpaceRenderableRenderable", + Identifier = "ScreenSpaceRenderableRenderable_Example_Model", + Transform = { + Scale = { + Type = "StaticScale", + Scale = 0.0002 + } + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = modelFolder .. "eiffeltower.osmodel", + RotationVector = { 0.0, 45.0, 0.0 }, + LightSources = { + { + Identifier = "Camera", + Type = "CameraLightSource", + Intensity = 5.0 + } + } + }, + Scale = 1.25, + CameraPosition = { 0.0, 1.0, 2.0 }, + CameraCenter = { 0.0, 0.5, 0.0 } +} + +asset.onInitialize(function() + openspace.addScreenSpaceRenderable(Object) +end) + +asset.onDeinitialize(function() + openspace.removeScreenSpaceRenderable(Object) +end) diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index 296add425e..d03de639d8 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -72,6 +72,7 @@ set(HEADER_FILES rendering/screenspaceframebuffer.h rendering/screenspaceimagelocal.h rendering/screenspaceimageonline.h + rendering/screenspacerenderablerenderable.h rotation/timelinerotation.h rotation/constantrotation.h rotation/fixedrotation.h @@ -142,6 +143,7 @@ set(SOURCE_FILES rendering/screenspaceframebuffer.cpp rendering/screenspaceimagelocal.cpp rendering/screenspaceimageonline.cpp + rendering/screenspacerenderablerenderable.cpp rotation/timelinerotation.cpp rotation/constantrotation.cpp rotation/fixedrotation.cpp diff --git a/modules/base/basemodule.cpp b/modules/base/basemodule.cpp index bc4641b24f..d41cf1b052 100644 --- a/modules/base/basemodule.cpp +++ b/modules/base/basemodule.cpp @@ -68,6 +68,7 @@ #include #include #include +#include #include #include #include @@ -110,6 +111,9 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) { fSsRenderable->registerClass("ScreenSpaceImageLocal"); fSsRenderable->registerClass("ScreenSpaceImageOnline"); fSsRenderable->registerClass("ScreenSpaceFramebuffer"); + fSsRenderable->registerClass( + "ScreenSpaceRenderableRenderable" + ); ghoul::TemplateFactory* fDashboard = @@ -281,6 +285,7 @@ std::vector BaseModule::documentations() const { ScreenSpaceFramebuffer::Documentation(), ScreenSpaceImageLocal::Documentation(), ScreenSpaceImageOnline::Documentation(), + ScreenSpaceRenderableRenderable::Documentation(), ConstantRotation::Documentation(), FixedRotation::Documentation(), diff --git a/modules/base/rendering/screenspacedashboard.cpp b/modules/base/rendering/screenspacedashboard.cpp index e43a7bb1e2..1a4ca00033 100644 --- a/modules/base/rendering/screenspacedashboard.cpp +++ b/modules/base/rendering/screenspacedashboard.cpp @@ -101,7 +101,7 @@ bool ScreenSpaceDashboard::initializeGL() { ScreenSpaceFramebuffer::initializeGL(); addRenderFunction([this]() { - glm::vec2 penPosition = glm::vec2(0.f, _size.value().w); + glm::vec2 penPosition = glm::vec2(0.f, _size.value().x); if (_useMainDashboard) { global::dashboard->render(penPosition); diff --git a/modules/base/rendering/screenspacedashboard.h b/modules/base/rendering/screenspacedashboard.h index 23a5e4c81e..ba453ff8e5 100644 --- a/modules/base/rendering/screenspacedashboard.h +++ b/modules/base/rendering/screenspacedashboard.h @@ -40,7 +40,7 @@ namespace openspace { namespace documentation { struct Documentation; } namespace scripting { struct LuaLibrary; } -class ScreenSpaceDashboard: public ScreenSpaceFramebuffer { +class ScreenSpaceDashboard : public ScreenSpaceFramebuffer { public: explicit ScreenSpaceDashboard(const ghoul::Dictionary& dictionary); virtual ~ScreenSpaceDashboard() override = default; diff --git a/modules/base/rendering/screenspaceframebuffer.cpp b/modules/base/rendering/screenspaceframebuffer.cpp index 36aa7f2f2f..e6233961bf 100644 --- a/modules/base/rendering/screenspaceframebuffer.cpp +++ b/modules/base/rendering/screenspaceframebuffer.cpp @@ -55,7 +55,7 @@ documentation::Documentation ScreenSpaceFramebuffer::Documentation() { ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictionary) : ScreenSpaceRenderable(dictionary) - , _size(SizeInfo, glm::vec4(0), glm::vec4(0), glm::vec4(16384)) + , _size(SizeInfo, glm::vec2(16), glm::vec2(16), glm::vec2(16384)) { documentation::testSpecificationAndThrow( Documentation(), @@ -75,14 +75,8 @@ ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictiona } } - if (_guiName.empty()) { - // Adding an extra space to the user-facing name as it looks nicer - setGuiName("ScreenSpaceFramebuffer " + std::to_string(iIdentifier)); - } - - const glm::vec2 resolution = global::windowDelegate->currentDrawBufferResolution(); + _size = global::windowDelegate->currentDrawBufferResolution(); addProperty(_size); - _size = glm::vec4(0.f, 0.f, resolution.x, resolution.y); } ScreenSpaceFramebuffer::~ScreenSpaceFramebuffer() {} @@ -107,22 +101,13 @@ bool ScreenSpaceFramebuffer::deinitializeGL() { void ScreenSpaceFramebuffer::render(const RenderData& renderData) { const glm::vec2& resolution = global::windowDelegate->currentDrawBufferResolution(); - const glm::vec4& size = _size.value(); - - const float xratio = resolution.x / (size.z - size.x); - const float yratio = resolution.y / (size.w - size.y); + const glm::vec2& size = _size.value(); + const glm::vec2 ratio = resolution / size; if (!_renderFunctions.empty()) { std::array viewport; - //glGetIntegerv(GL_VIEWPORT, viewport); - global::renderEngine->openglStateCache().viewport(viewport.data()); - glViewport( - static_cast(-size.x * xratio), - static_cast(-size.y * yratio), - static_cast(resolution.x * xratio), - static_cast(resolution.y * yratio) - ); - global::renderEngine->openglStateCache().setViewportState(viewport.data()); + glGetIntegerv(GL_VIEWPORT, viewport.data()); + glViewport(0, 0, static_cast(size.x), static_cast(size.y)); const GLint defaultFBO = ghoul::opengl::FramebufferObject::getActiveObject(); _framebuffer->activate(); @@ -142,7 +127,7 @@ void ScreenSpaceFramebuffer::render(const RenderData& renderData) { const glm::mat4 localRotation = localRotationMatrix(); const glm::mat4 scale = glm::scale( scaleMatrix(), - glm::vec3((1.f / xratio), (1.f / yratio), 1.f) + glm::vec3((1.f / ratio.x), (1.f / ratio.y), 1.f) ); const glm::mat4 modelTransform = globalRotation*translation*localRotation*scale; draw(modelTransform, renderData); @@ -153,7 +138,7 @@ bool ScreenSpaceFramebuffer::isReady() const { return _shader && _texture; } -void ScreenSpaceFramebuffer::setSize(glm::vec4 size) { +void ScreenSpaceFramebuffer::setSize(glm::vec2 size) { _size = std::move(size); } diff --git a/modules/base/rendering/screenspaceframebuffer.h b/modules/base/rendering/screenspaceframebuffer.h index 7b134614bc..5d9ef522ab 100644 --- a/modules/base/rendering/screenspaceframebuffer.h +++ b/modules/base/rendering/screenspaceframebuffer.h @@ -27,7 +27,7 @@ #include -#include +#include namespace ghoul::opengl { class FramebufferObject; @@ -56,7 +56,7 @@ public: void render(const RenderData& renderData) override; bool isReady() const override; - void setSize(glm::vec4 size); + void setSize(glm::vec2 size); void addRenderFunction(RenderFunction renderFunction); void removeAllRenderFunctions(); @@ -64,7 +64,7 @@ public: protected: void createFramebuffer(); - properties::Vec4Property _size; + properties::Vec2Property _size; private: void bindTexture() override; diff --git a/modules/base/rendering/screenspacerenderablerenderable.cpp b/modules/base/rendering/screenspacerenderablerenderable.cpp new file mode 100644 index 0000000000..45367c6b7e --- /dev/null +++ b/modules/base/rendering/screenspacerenderablerenderable.cpp @@ -0,0 +1,307 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2025 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +namespace { + constexpr openspace::properties::Property::PropertyInfo TimeInfo = { + "Time", + "Time", + "The time (in J2000 seconds) that is used to calculate transformations and the " + "renderable's data." + }; + + constexpr openspace::properties::Property::PropertyInfo CameraPositionInfo = { + "CameraPosition", + "Camera Position", + "Specifies the location of the virtual camera that is showing the renderable " + "class. This position is provided in meters." + }; + + constexpr openspace::properties::Property::PropertyInfo CameraCenterInfo = { + "CameraCenter", + "Camera Center", + "The location of the camera's focal point. The camera's view direction will " + "always be pointing at the provided center location. This position is provided " + "in meters." + }; + + constexpr openspace::properties::Property::PropertyInfo CameraUpInfo = { + "CameraUp", + "Camera Up", + "The direction that is 'up' for the provided camera. This value does not have " + "any units." + }; + + constexpr openspace::properties::Property::PropertyInfo CameraFovInfo = { + "CameraFov", + "Camera Field of view", + "The camera's field of view in degrees." + }; + + const openspace::properties::PropertyOwner::PropertyOwnerInfo TransformInfo = { + "Transform", + "Transform", + "The Translation, Rotation, and Scale that are applied to the rendered " + "Renderable." + }; + + // This [ScreenSpaceRenderable](#core_screenspacerenderable) object can render any + // [Renderable](#renderable) type into an image that is shown in screen space. This + // can be used to display a rendered object as an overlay in front of the regular 3D + // rendering of the scene. + // + // Note that to use this `ScreenSpaceRenderable`, it might be necessary to specify the + // `size` parameter, which determines the resolution of the inset window into which + // the Renderable is rendered. For many use cases, the default should suffice, + // however. + // + // A possible use-case for the ScreenSpaceRenderable would be to show a 3D model of a + // spacecraft without the need to place it at a position in the 3D scene with the need + // to fly to that object to talk about it. + struct [[codegen::Dictionary(ScreenSpaceRenderableRenderable)]] Parameters { + std::optional identifier [[codegen::private()]]; + + // The [Renderable](#renderable) object that is shown in this ScreenSpace object. + // See the list of creatable renderable objects for options that can be used for + // this type. + ghoul::Dictionary renderable [[codegen::reference("renderable")]]; + + struct Transform { + // The [Translation](#core_transform_translation) object that is used for the + // provided [Renderable](#renderable). If no value is specified, a + // [StaticTranslation](#base_transform_translation_static) is created instead. + std::optional translation + [[codegen::reference("core_transform_translation")]]; + + // The [Rotation](#core_transform_rotation) object that is used for the + // provided [Renderable](#renderable). If no value is specified, a + // [StaticRotation](#base_transform_rotation_static) is created instead. + std::optional rotation + [[codegen::reference("core_transform_rotation")]]; + + // The [Scale](#core_transform_scale) object that is used for the provided + // [Renderable](#renderable). If no value is specified, a + // [StaticScale](#base_transform_scale_static) is created instead. + std::optional scale + [[codegen::reference("core_transform_scale")]]; + }; + // The collection of transformations that are applied to the + // [Renderable](#renderable) before it is shown on screen. + std::optional transform; + + // Specifies the start date that is used to control the renderable and the + // transforms. If no value is specified the date of 2000 JAN 01 12:00:00 is used + // instead. + std::optional time [[codegen::datetime()]]; + + // [[codegen::verbatim(CameraPositionInfo.description)]] + std::optional cameraPosition; + + // [[codegen::verbatim(CameraCenterInfo.description)]] + std::optional cameraCenter; + + // [[codegen::verbatim(CameraUpInfo.description)]] + std::optional cameraUp; + + // [[codegen::verbatim(CameraFovInfo.description)]] + std::optional cameraFov; + }; +#include "screenspacerenderablerenderable_codegen.cpp" +} // namespace + +namespace openspace { + +documentation::Documentation ScreenSpaceRenderableRenderable::Documentation() { + return codegen::doc( + "base_screenspace_renderable", + ScreenSpaceFramebuffer::Documentation() + ); +} + +ScreenSpaceRenderableRenderable::ScreenSpaceRenderableRenderable( + const ghoul::Dictionary& dictionary) + : ScreenSpaceFramebuffer(dictionary) + , _time( + TimeInfo, + 0.0, + -std::numeric_limits::max(), + std::numeric_limits::max() + ) + , _cameraPosition( + CameraPositionInfo, + glm::vec3(0.f, 2.f, 2.f), + glm::vec3(-10.f, -10.f, -10.f), + glm::vec3(10.f, 10.f, 10.f) + ) + , _cameraCenter(CameraCenterInfo, glm::vec3(0.f), glm::vec3(-1.f), glm::vec3(1.f)) + , _cameraUp(CameraUpInfo, glm::vec3(0.f, 1.f, 0.f), glm::vec3(-1.f), glm::vec3(1.f)) + , _cameraFov(CameraFovInfo, 45.f, 5.f, 90.f) +{ + const Parameters p = codegen::bake(dictionary); + + std::string identifier = p.identifier.value_or("ScreenSpaceRenderableRenderable"); + setIdentifier(makeUniqueIdentifier(std::move(identifier))); + + if (p.time.has_value()) { + _time = Time(*p.time).j2000Seconds(); + } + _time.onChange([this]() { _previousTime = _time; }); + addProperty(_time); + + _cameraPosition = p.cameraPosition.value_or(_cameraPosition); + addProperty(_cameraPosition); + _cameraCenter = p.cameraCenter.value_or(_cameraCenter); + addProperty(_cameraCenter); + _cameraUp = p.cameraUp.value_or(_cameraUp); + addProperty(_cameraUp); + _cameraFov = p.cameraFov.value_or(_cameraFov); + addProperty(_cameraFov); + + _renderable = Renderable::createFromDictionary(p.renderable); + _renderable->initialize(); + addPropertySubOwner(_renderable.get()); + + _transform = ghoul::mm_unique_ptr( + new properties::PropertyOwner(TransformInfo) + ); + addPropertySubOwner(_transform.get()); + + if (p.transform.has_value() && p.transform->translation.has_value()) { + _translation = Translation::createFromDictionary(*p.transform->translation); + } + else { + ghoul::Dictionary translation; + translation.setValue("Type", std::string("StaticTranslation")); + translation.setValue("Position", glm::dvec3(0.0)); + _translation = Translation::createFromDictionary(translation); + } + _translation->initialize(); + _transform->addPropertySubOwner(_translation.get()); + + if (p.transform.has_value() && p.transform->rotation.has_value()) { + _rotation = Rotation::createFromDictionary(*p.transform->rotation); + } + else { + ghoul::Dictionary rotation; + rotation.setValue("Type", std::string("StaticRotation")); + rotation.setValue("Rotation", glm::dvec3(0.0)); + _rotation = Rotation::createFromDictionary(rotation); + } + _rotation->initialize(); + _transform->addPropertySubOwner(_rotation.get()); + + if (p.transform.has_value() && p.transform->scale.has_value()) { + _scale = Scale::createFromDictionary(*p.transform->scale); + } + else { + ghoul::Dictionary scale; + scale.setValue("Type", std::string("StaticScale")); + scale.setValue("Scale", 1.0); + _scale = Scale::createFromDictionary(scale); + } + _scale->initialize(); + _transform->addPropertySubOwner(_scale.get()); +} + +ScreenSpaceRenderableRenderable::~ScreenSpaceRenderableRenderable() {} + +bool ScreenSpaceRenderableRenderable::initializeGL() { + ScreenSpaceFramebuffer::initializeGL(); + + _renderable->initializeGL(); + + addRenderFunction([this]() { + glm::vec4 bg = _backgroundColor; + glClearColor(bg.r, bg.g, bg.b, bg.a); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + Camera camera; + // @TODO (2025-03-24, abock): These two lines can be removed once #3573 is fixed + camera.setPositionVec3(glm::dvec3(0.0, 0.0, 0.0)); + camera.setRotation(glm::dvec3(0.0, 0.0, 0.0)); + + glm::mat4 view = glm::lookAt( + _cameraPosition.value(), + _cameraCenter.value(), + glm::normalize(_cameraUp.value()) + ); + camera.sgctInternal.setViewMatrix(view); + + glm::mat4 proj = glm::perspectiveFov( + glm::radians(_cameraFov.value()), + _size.value().x, + _size.value().y, + 0.1f, + 20.f + ); + camera.sgctInternal.setProjectionMatrix(proj); + + openspace::RenderData renderData = { + .camera = camera, + .time = Time(_time), + .modelTransform = { + .translation = _translation->position(), + .rotation = _rotation->matrix(), + .scale = _scale->scaleValue() + } + }; + RendererTasks tasks; + _renderable->render(renderData, tasks); + }); + return true; +} + +bool ScreenSpaceRenderableRenderable::deinitializeGL() { + _renderable->deinitializeGL(); + _renderable->deinitialize(); + return ScreenSpaceFramebuffer::deinitializeGL(); +} + +void ScreenSpaceRenderableRenderable::update() { + UpdateData updateData = { + .time = Time(_time), + .previousFrameTime = Time(_previousTime) + }; + + _translation->update(updateData); + updateData.modelTransform.translation = _translation->position(); + + _rotation->update(updateData); + updateData.modelTransform.rotation = _rotation->matrix(); + + _scale->update(updateData); + updateData.modelTransform.scale = _scale->scaleValue(); + + _renderable->update(updateData); +} + +} // namespace openspace diff --git a/modules/base/rendering/screenspacerenderablerenderable.h b/modules/base/rendering/screenspacerenderablerenderable.h new file mode 100644 index 0000000000..199f030c0f --- /dev/null +++ b/modules/base/rendering/screenspacerenderablerenderable.h @@ -0,0 +1,76 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2025 * + * * + * 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___SCREENSPACERENDERABLERENDERABLE___H__ +#define __OPENSPACE_MODULE_BASE___SCREENSPACERENDERABLERENDERABLE___H__ + +#include + +#include +#include +#include +#include + +namespace openspace { + +namespace properties { class PropertyOwner; } + +class Renderable; +class Rotation; +class Scale; +class Translation; + +namespace documentation { struct Documentation; } + +class ScreenSpaceRenderableRenderable : public ScreenSpaceFramebuffer { +public: + using RenderFunction = std::function; + + explicit ScreenSpaceRenderableRenderable(const ghoul::Dictionary& dictionary); + virtual ~ScreenSpaceRenderableRenderable() override; + + bool initializeGL() override; + bool deinitializeGL() override; + void update() override; + + static documentation::Documentation Documentation(); + +private: + ghoul::mm_unique_ptr _translation = nullptr; + ghoul::mm_unique_ptr _transform = nullptr; + ghoul::mm_unique_ptr _rotation = nullptr; + ghoul::mm_unique_ptr _scale = nullptr; + ghoul::mm_unique_ptr _renderable = nullptr; + + double _previousTime = 0.0; + properties::DoubleProperty _time; + properties::Vec3Property _cameraPosition; + properties::Vec3Property _cameraCenter; + properties::Vec3Property _cameraUp; + properties::FloatProperty _cameraFov; +}; + +} //namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___SCREENSPACERENDERABLERENDERABLE___H__ diff --git a/src/properties/propertyowner.cpp b/src/properties/propertyowner.cpp index e1589f859f..3d238f8715 100644 --- a/src/properties/propertyowner.cpp +++ b/src/properties/propertyowner.cpp @@ -302,7 +302,8 @@ void PropertyOwner::addPropertySubOwner(openspace::properties::PropertyOwner* ow const bool hasProp = hasProperty(owner->identifier()); if (hasProp) { LERROR(std::format( - "PropertyOwner '{}'s name already names a Property", owner->identifier() + "PropertyOwner '{}'s identifier is already in use for a Property", + owner->identifier() )); return; } diff --git a/src/scene/scenegraphnode.cpp b/src/scene/scenegraphnode.cpp index b7e8a38ab3..c32b171cf0 100644 --- a/src/scene/scenegraphnode.cpp +++ b/src/scene/scenegraphnode.cpp @@ -924,7 +924,7 @@ void SceneGraphNode::renderDebugSphere(const Camera& camera, double size, void SceneGraphNode::setParent(SceneGraphNode& parent) { ghoul_assert(_parent != nullptr, "Node must be attached to a parent"); - parent.attachChild(_parent->detachChild(*this)); + _parent = &parent; } void SceneGraphNode::attachChild(ghoul::mm_unique_ptr child) { From eb709b830cc91dd84f685e5464a928a50c82e14a Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Wed, 2 Apr 2025 09:28:11 +0200 Subject: [PATCH 04/11] Small option property cleanup (#3577) * Notify change listeners I can't come up with a reason for why we would not want to do this * Remove the Display Type for OptionProperty (only used in ImGui) * Replace extra boolean with internal anonymous addOption function * Tiny refactor * removed dropdown on a couple of more places * Update optionproperty.cpp --------- Co-authored-by: ElonOlsson --- .../properties/misc/optionproperty.h | 29 +------- modules/base/dashboard/dashboarditemangle.cpp | 15 +--- .../base/dashboard/dashboarditemdistance.cpp | 12 +--- .../base/dashboard/dashboarditemframerate.cpp | 2 +- .../dashboarditemsimulationincrement.cpp | 2 +- .../base/dashboard/dashboarditemvelocity.cpp | 2 +- .../pointcloud/renderablepointcloud.cpp | 5 +- .../pointcloud/sizemappingcomponent.cpp | 5 +- .../rendering/renderabledistancelabel.cpp | 2 +- modules/base/rendering/renderablelabel.cpp | 12 +--- modules/base/rendering/renderablemodel.cpp | 5 +- modules/base/rendering/renderableplane.cpp | 2 +- modules/base/rendering/renderablesphere.cpp | 7 +- modules/base/rendering/renderabletrail.cpp | 5 +- modules/base/rotation/fixedrotation.cpp | 15 +--- .../rendering/renderabledumeshes.cpp | 2 +- .../renderablefieldlinessequence.cpp | 9 +-- .../gaia/rendering/renderablegaiastars.cpp | 9 +-- modules/galaxy/rendering/renderablegalaxy.cpp | 7 +- .../src/geojson/geojsoncomponent.cpp | 5 +- .../src/geojson/geojsonproperties.cpp | 10 +-- .../src/globelabelscomponent.cpp | 5 +- modules/globebrowsing/src/layer.cpp | 4 +- modules/globebrowsing/src/layeradjustment.cpp | 2 +- modules/imgui/src/renderproperties.cpp | 65 +++++++---------- .../rendering/renderablekameleonvolume.cpp | 2 +- .../space/rendering/renderablefluxnodes.cpp | 8 +-- .../rendering/renderableorbitalkepler.cpp | 5 +- modules/space/rendering/renderablestars.cpp | 14 ++-- .../rendering/renderableshadowcylinder.cpp | 5 +- .../rendering/renderabletimevaryingvolume.cpp | 2 +- src/navigation/pathnavigator.cpp | 5 +- src/properties/misc/optionproperty.cpp | 70 +++++++++---------- src/rendering/colormappingcomponent.cpp | 2 +- 34 files changed, 115 insertions(+), 236 deletions(-) diff --git a/include/openspace/properties/misc/optionproperty.h b/include/openspace/properties/misc/optionproperty.h index 6507d43a45..a833bf4830 100644 --- a/include/openspace/properties/misc/optionproperty.h +++ b/include/openspace/properties/misc/optionproperty.h @@ -48,11 +48,6 @@ public: std::string description; }; - enum class DisplayType { - Radio, - Dropdown - }; - /** * The constructor delegating the `identifier` and the `guiName` to its super class. * @@ -64,18 +59,6 @@ public: */ OptionProperty(Property::PropertyInfo info); - /** - * The constructor delegating the `identifier` and the `guiName` to its super class. - * - * \param info The PropertyInfo structure that contains all the required static - * information for initializing this Property - * \param displayType Optional DisplayType for GUI (default RADIO) - * - * \pre \p info.identifier must not be empty - * \pre \p info.guiName must not be empty - */ - OptionProperty(PropertyInfo info, DisplayType displayType); - /** * Returns the name of the class for reflection purposes. * @@ -86,21 +69,14 @@ public: using TemplateProperty::operator=; - /** - * Returns the type for GUI display. - * - * \return OptionType for display purposes - */ - DisplayType displayType() const; - /** * Adds the passed option to the list of available options. The `value` of the * `option` must not have been registered previously, or a warning will be logged. * * \param value The option that will be added to the list of available options - * \param desc The description of the value that will be added + * \param description The description of the value that will be added */ - void addOption(int value, std::string desc); + void addOption(int value, std::string description); /** * Adds multiple options to the OptionProperty. Each value in the vector consists of @@ -171,7 +147,6 @@ private: /// The list of options which have been registered with this OptionProperty std::vector