From af20b97dc7d534c2ceec8021411d28e87f44c7ec Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 14 Apr 2025 19:47:54 +0200 Subject: [PATCH] Add ability to configure horizontal field of view per window instead (#3584) --- apps/OpenSpace/main.cpp | 30 ++++++++--- include/openspace/engine/windowdelegate.h | 6 ++- include/openspace/rendering/renderengine.h | 10 +++- modules/skybrowser/src/utility.cpp | 4 +- src/rendering/renderengine.cpp | 60 ++++++++++++++++++---- 5 files changed, 88 insertions(+), 22 deletions(-) diff --git a/apps/OpenSpace/main.cpp b/apps/OpenSpace/main.cpp index ba64091dbb..118846bb0e 100644 --- a/apps/OpenSpace/main.cpp +++ b/apps/OpenSpace/main.cpp @@ -924,24 +924,40 @@ void setSgctDelegateFunctions() { return Engine::instance().windows().front()->id(); }; + sgctDelegate.nameForWindow = [](int windowIdx) { + ZoneScoped; + + ghoul_assert( + windowIdx >= 0 && + windowIdx < Engine::instance().windows().size(), + "Invalid window index" + ); + return Engine::instance().windows()[windowIdx]->name(); + }; sgctDelegate.openGLProcedureAddress = [](const char* func) { ZoneScoped; return glfwGetProcAddress(func); }; - sgctDelegate.getHorizFieldOfView = []() { + sgctDelegate.horizFieldOfView = [](int windowIdx) { ZoneScoped; - return static_cast( - Engine::instance().windows().front()->horizFieldOfViewDegrees() + ghoul_assert( + windowIdx >= 0 && + windowIdx < Engine::instance().windows().size(), + "Invalid window index" ); + return Engine::instance().windows()[windowIdx]->horizFieldOfViewDegrees(); }; - sgctDelegate.setHorizFieldOfView = [](float hFovDeg) { + sgctDelegate.setHorizFieldOfView = [](int windowIdx, float hFovDeg) { ZoneScoped; - for (std::unique_ptr const& w : Engine::instance().windows()) { - w->setHorizFieldOfView(hFovDeg); - } + ghoul_assert( + windowIdx >= 0 && + windowIdx < Engine::instance().windows().size(), + "Invalid window index" + ); + Engine::instance().windows()[windowIdx]->setHorizFieldOfView(hFovDeg); }; #ifdef WIN32 sgctDelegate.getNativeWindowHandle = [](size_t windowIndex) -> void* { diff --git a/include/openspace/engine/windowdelegate.h b/include/openspace/engine/windowdelegate.h index c159289fb5..806adc063b 100644 --- a/include/openspace/engine/windowdelegate.h +++ b/include/openspace/engine/windowdelegate.h @@ -99,9 +99,11 @@ struct WindowDelegate { int (*firstWindowId)() = []() { return 0; }; - double (*getHorizFieldOfView)() = []() { return 0.0; }; + std::string (*nameForWindow)(int windowIdx) = [](int) { return std::string(); }; - void (*setHorizFieldOfView)(float hFovDeg) = [](float) { }; + float (*horizFieldOfView)(int windowIdx) = [](int) { return 0.f; }; + + void (*setHorizFieldOfView)(int windowIdx, float hFovDeg) = [](int, float) {}; void* (*getNativeWindowHandle)(size_t windowIndex) = [](size_t) -> void* { return nullptr; diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index 35ff86b9c4..579dd5b9e8 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -204,7 +204,15 @@ private: properties::IntProperty _framerateLimit; std::chrono::high_resolution_clock::time_point _lastFrameTime; - properties::FloatProperty _horizFieldOfView; + + struct Window : properties::PropertyOwner { + Window(PropertyOwnerInfo info, int id); + + properties::FloatProperty horizFieldOfView; + }; + + properties::PropertyOwner _windowing; + std::vector> _windows; properties::Vec3Property _globalRotation; properties::Vec3Property _screenSpaceRotation; diff --git a/modules/skybrowser/src/utility.cpp b/modules/skybrowser/src/utility.cpp index 3b6ea320bb..7334d4bb7b 100644 --- a/modules/skybrowser/src/utility.cpp +++ b/modules/skybrowser/src/utility.cpp @@ -196,7 +196,9 @@ glm::dvec2 fovWindow() { // OpenSpace FOV const glm::dvec2 windowDim = glm::dvec2(global::windowDelegate->currentWindowSize()); const double ratio = windowDim.y / windowDim.x; - const double hFov = global::windowDelegate->getHorizFieldOfView(); + const double hFov = global::windowDelegate->horizFieldOfView( + global::windowDelegate->currentWindowId() + ); const glm::dvec2 OpenSpaceFOV = glm::dvec2(hFov, hFov * ratio); return OpenSpaceFOV; } diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 291df8e386..cfac2b52ee 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -286,10 +286,30 @@ namespace { "The font color used for disabled options.", openspace::properties::Property::Visibility::AdvancedUser }; + + const openspace::properties::PropertyOwner::PropertyOwnerInfo WindowingInfo = { + "Windowing", + "Windowing", + "Contains properties that concern the specific rendering settings of individual " + "windows. Note that the number of properties in this owner are determined by the " + "configuration file and might be different from run to run." + }; } // namespace namespace openspace { +RenderEngine::Window::Window(PropertyOwnerInfo info, int id) + : properties::PropertyOwner(info) + , horizFieldOfView(HorizFieldOfViewInfo, 80.f, 1.f, 179.f) +{ + horizFieldOfView.onChange([this, id]() { + if (global::windowDelegate->isMaster()) { + global::windowDelegate->setHorizFieldOfView(id, horizFieldOfView); + } + }); + addProperty(horizFieldOfView); +} + RenderEngine::RenderEngine() : properties::PropertyOwner({ "RenderEngine", "Render Engine" }) , _showOverlayOnClients(ShowOverlayClientsInfo, false) @@ -311,7 +331,7 @@ RenderEngine::RenderEngine() , _saturation(SaturationInfo, 1.f, 0.f, 2.f) , _value(ValueInfo, 1.f, 0.f, 2.f) , _framerateLimit(FramerateLimitInfo, 0, 0, 500) - , _horizFieldOfView(HorizFieldOfViewInfo, 80.f, 1.f, 179.f) + , _windowing(WindowingInfo) , _globalRotation( GlobalRotationInfo, glm::vec3(0.f), @@ -418,13 +438,9 @@ RenderEngine::RenderEngine() }); addProperty(_screenshotUseDate); - _horizFieldOfView.onChange([this]() { - if (global::windowDelegate->isMaster()) { - global::windowDelegate->setHorizFieldOfView(_horizFieldOfView); - } - }); - addProperty(_horizFieldOfView); - + addPropertySubOwner(_windowing); + // Adding the actual window owners later in the initialize, as we don't know yet how + // many windows will exist addProperty(_framerateLimit); addProperty(_globalRotation); @@ -482,6 +498,17 @@ void RenderEngine::initializeGL() { LTRACE("RenderEngine::initializeGL(begin)"); + for (int i = 0; i < global::windowDelegate->nWindows(); i++) { + std::string name = global::windowDelegate->nameForWindow(i); + properties::PropertyOwner::PropertyOwnerInfo info = { + .identifier = std::format("Window_{}", i), + .guiName = name.empty() ? std::format("Window {}", i) : name + }; + auto w = std::make_unique(info, i); + _windowing.addPropertySubOwner(w.get()); + _windows.push_back(std::move(w)); + } + _renderer.setResolution(renderingResolution()); _renderer.enableFXAA(_enableFXAA); _renderer.setHDRExposure(_hdrExposure); @@ -493,7 +520,13 @@ void RenderEngine::initializeGL() { // Set horizontal FOV value with whatever the field of view (in degrees) is of the // initialized window - _horizFieldOfView = static_cast(global::windowDelegate->getHorizFieldOfView()); + ghoul_assert( + global::windowDelegate->nWindows() == _windows.size(), + "Invalid number of windows" + ); + for (int i = 0; i < global::windowDelegate->nWindows(); i++) { + _windows[i]->horizFieldOfView = global::windowDelegate->horizFieldOfView(i); + } const Configuration::FontSizes fontSize = global::configuration->fontSize; { @@ -571,8 +604,13 @@ void RenderEngine::updateRenderer() { FR::defaultRenderer().setFramebufferSize(fontResolution()); FR::defaultProjectionRenderer().setFramebufferSize(renderingResolution()); // Override the aspect ratio property value to match that of resized window - _horizFieldOfView = - static_cast(global::windowDelegate->getHorizFieldOfView()); + ghoul_assert( + global::windowDelegate->nWindows() == _windows.size(), + "Invalid number of windows" + ); + for (int i = 0; i < global::windowDelegate->nWindows(); i++) { + _windows[i]->horizFieldOfView = global::windowDelegate->horizFieldOfView(i); + } } _renderer.update();