From 21e572149e328140121ca7bc2d1de53ddee67b61 Mon Sep 17 00:00:00 2001 From: sylvass Date: Wed, 2 Mar 2022 16:39:44 -0500 Subject: [PATCH] Fix comments from pull request --- data/assets/hoverCircle.asset | 26 +- data/assets/util/webgui.asset | 22 +- .../rendering/screenspacerenderable.h | 2 - modules/skybrowser/CMakeLists.txt | 53 +- modules/skybrowser/include/browser.h | 9 +- .../include/screenspaceskybrowser.h | 113 +-- .../skybrowser/include/screenspaceskytarget.h | 158 ++-- .../skybrowser/include/targetbrowserpair.h | 12 +- modules/skybrowser/include/utility.h | 114 +-- modules/skybrowser/include/wwtcommunicator.h | 73 +- modules/skybrowser/include/wwtdatahandler.h | 82 ++- modules/skybrowser/shaders/target_fs.glsl | 78 +- modules/skybrowser/shaders/target_vs.glsl | 29 +- modules/skybrowser/skybrowsermodule.cpp | 185 ++--- modules/skybrowser/skybrowsermodule.h | 41 +- modules/skybrowser/skybrowsermodule_lua.inl | 227 +++--- modules/skybrowser/src/browser.cpp | 282 ++++---- .../skybrowser/src/screenspaceskybrowser.cpp | 407 +++++------ .../skybrowser/src/screenspaceskytarget.cpp | 89 +-- modules/skybrowser/src/targetbrowserpair.cpp | 145 ++-- modules/skybrowser/src/utility.cpp | 372 +++++----- modules/skybrowser/src/wwtcommunicator.cpp | 532 +++++++------- modules/skybrowser/src/wwtdatahandler.cpp | 677 +++++++++--------- 23 files changed, 1867 insertions(+), 1861 deletions(-) diff --git a/data/assets/hoverCircle.asset b/data/assets/hoverCircle.asset index 4110a238ed..54fc5fd2ce 100644 --- a/data/assets/hoverCircle.asset +++ b/data/assets/hoverCircle.asset @@ -1,18 +1,16 @@ -local assetHelper = asset.require('util/asset_helper') - local id = "HoverCircle" local circle = { - Identifier = id, - Type = "ScreenSpaceImageLocal", - Name = "HoverCircle", - FaceCamera = false, - UseRadiusAzimuthElevation = false, - RadiusAzimuthElevation = {1.0, 0.0, 0.0}, -- use for dome - Scale= 0.025, - Enabled = false, - TexturePath = "${ASSETS}/circle.png", - CartesianPosition = { 0, 0, -2.1 }, + Identifier = id, + Type = "ScreenSpaceImageLocal", + Name = "HoverCircle", + FaceCamera = false, + UseRadiusAzimuthElevation = false, + RadiusAzimuthElevation = {1.0, 0.0, 0.0}, -- use for dome + Scale = 0.025, + Enabled = false, + TexturePath = "${ASSETS}/circle.png", + CartesianPosition = { 0, 0, -2.1 }, }; asset.onInitialize(function () @@ -21,7 +19,7 @@ asset.onInitialize(function () end) asset.onDeinitialize(function () - openspace.removeScreenSpaceRenderable(circle) + openspace.removeScreenSpaceRenderable(circle) end) -asset.export("circle", {circle}) +asset.export("circle", circle) diff --git a/data/assets/util/webgui.asset b/data/assets/util/webgui.asset index c1e0871036..3be431b3ef 100644 --- a/data/assets/util/webgui.asset +++ b/data/assets/util/webgui.asset @@ -1,9 +1,9 @@ -asset.require('./static_server') +asset.require("./static_server") -local guiCustomization = asset.require('customization/gui') +local guiCustomization = asset.require("customization/gui") -- Select which commit hashes to use for the frontend and backend -local frontendHash = "7f2b2b84ef526d7e67ed50462853a0d9a09b4f71" +local frontendHash = "aa9aa521ace55cc25f447d287d34624f2cb56832" local dataProvider = "data.openspaceproject.com/files/webgui" local frontend = asset.syncedResource({ @@ -15,9 +15,9 @@ local frontend = asset.syncedResource({ asset.onInitialize(function () -- Unzip the frontend bundle - local dest = frontend .. "/frontend" + local dest = frontend .. "frontend" if not openspace.directoryExists(dest) then - openspace.unzipFile(frontend .. "/frontend.zip", dest, true) + openspace.unzipFile(frontend .. "frontend.zip", dest, true) end -- Disable the server, add production gui endpoint, and restart server. @@ -31,7 +31,7 @@ asset.onInitialize(function () local directories = openspace.getPropertyValue("Modules.WebGui.Directories") directories[#directories + 1] = "frontend" - directories[#directories + 1] = frontend .. '/frontend' + directories[#directories + 1] = frontend .. "frontend" openspace.setPropertyValueSingle("Modules.WebGui.Directories", directories) openspace.setPropertyValueSingle("Modules.WebGui.DefaultEndpoint", "frontend") @@ -39,12 +39,12 @@ asset.onInitialize(function () -- The GUI contains date and simulation increment, -- so let's remove these from the dashboard. - if openspace.getPropertyValue('Modules.CefWebGui.Visible') then - if openspace.hasProperty('Dashboard.Date.Enabled') then - openspace.setPropertyValueSingle('Dashboard.Date.Enabled', false) + if openspace.getPropertyValue("Modules.CefWebGui.Visible") then + if openspace.hasProperty("Dashboard.Date.Enabled") then + openspace.setPropertyValueSingle("Dashboard.Date.Enabled", false) end - if openspace.hasProperty('Dashboard.SimulationIncrement.Enabled') then - openspace.setPropertyValueSingle('Dashboard.SimulationIncrement.Enabled', false) + if openspace.hasProperty("Dashboard.SimulationIncrement.Enabled") then + openspace.setPropertyValueSingle("Dashboard.SimulationIncrement.Enabled", false) end end end) diff --git a/include/openspace/rendering/screenspacerenderable.h b/include/openspace/rendering/screenspacerenderable.h index 815cd55a70..8fb13795f8 100644 --- a/include/openspace/rendering/screenspacerenderable.h +++ b/include/openspace/rendering/screenspacerenderable.h @@ -75,7 +75,6 @@ public: void setEnabled(bool isEnabled); float depth(); - // Added by skybrowser team // Screen space functionality in these coords: [-1,1][-ratio,ratio] glm::vec2 screenSpacePosition(); glm::vec2 screenSpaceDimensions(); @@ -86,7 +85,6 @@ public: void setCartesianPosition(const glm::vec3& position); void setRaeFromCartesianPosition(const glm::vec3& position); glm::vec3 raePosition() const; - // End of addition by skybrowser team static documentation::Documentation Documentation(); diff --git a/modules/skybrowser/CMakeLists.txt b/modules/skybrowser/CMakeLists.txt index d5f3196a2b..60387683c1 100644 --- a/modules/skybrowser/CMakeLists.txt +++ b/modules/skybrowser/CMakeLists.txt @@ -2,7 +2,7 @@ # # # OpenSpace # # # -# Copyright (c) 2014-2021 # +# Copyright (c) 2014-2022 # # # # Permission is hereby granted, free of charge, to any person obtaining a copy of this # # software and associated documentation files (the "Software"), to deal in the Software # @@ -25,40 +25,35 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES - - skybrowsermodule.h - include/screenspaceskytarget.h - include/wwtdatahandler.h - include/utility.h - include/targetbrowserpair.h - include/wwtcommunicator.h - include/browser.h - include/screenspaceskybrowser.h - ext/tinyxml2/tinyxml2.h - + skybrowsermodule.h + include/screenspaceskytarget.h + include/wwtdatahandler.h + include/utility.h + include/targetbrowserpair.h + include/wwtcommunicator.h + include/browser.h + include/screenspaceskybrowser.h + ext/tinyxml2/tinyxml2.h ) source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES - - skybrowsermodule.cpp - skybrowsermodule_lua.inl - src/screenspaceskytarget.cpp - src/wwtdatahandler.cpp - src/utility.cpp - src/targetbrowserpair.cpp - src/wwtcommunicator.cpp - src/browser.cpp - src/screenspaceskybrowser.cpp - ext/tinyxml2/tinyxml2.cpp - + skybrowsermodule.cpp + skybrowsermodule_lua.inl + src/screenspaceskytarget.cpp + src/wwtdatahandler.cpp + src/utility.cpp + src/targetbrowserpair.cpp + src/wwtcommunicator.cpp + src/browser.cpp + src/screenspaceskybrowser.cpp + ext/tinyxml2/tinyxml2.cpp ) source_group("Source Files" FILES ${SOURCE_FILES}) - create_new_module( - "SkyBrowser" - skybrowser_module - STATIC - ${HEADER_FILES} ${SOURCE_FILES} + "SkyBrowser" + skybrowser_module + STATIC + ${HEADER_FILES} ${SOURCE_FILES} ) diff --git a/modules/skybrowser/include/browser.h b/modules/skybrowser/include/browser.h index 192258d23d..f33d1e6be2 100644 --- a/modules/skybrowser/include/browser.h +++ b/modules/skybrowser/include/browser.h @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2021 * + * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -25,8 +25,8 @@ #ifndef __OPENSPACE_MODULE_SKYBROWSER___BROWSER___H__ #define __OPENSPACE_MODULE_SKYBROWSER___BROWSER___H__ -#include #include +#include #include #include #include @@ -61,9 +61,8 @@ class WebKeyboardHandler; class Browser { public: - Browser(const ghoul::Dictionary& dictionary); - Browser(Browser const&) = default; - ~Browser(); + explicit Browser(const ghoul::Dictionary& dictionary); + virtual ~Browser(); bool initializeGL(); bool deinitializeGL(); diff --git a/modules/skybrowser/include/screenspaceskybrowser.h b/modules/skybrowser/include/screenspaceskybrowser.h index e79bc50265..b9ba42efeb 100644 --- a/modules/skybrowser/include/screenspaceskybrowser.h +++ b/modules/skybrowser/include/screenspaceskybrowser.h @@ -1,8 +1,33 @@ -#ifndef __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER2___H__ -#define __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER2___H__ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER___H__ +#define __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER___H__ #include #include + #include #include #include @@ -10,58 +35,56 @@ namespace openspace { - class ScreenSpaceSkyBrowser : public ScreenSpaceRenderable, public WwtCommunicator - { - public: - constexpr static const double FovThreshold = 0.001f; +class ScreenSpaceSkyBrowser : public ScreenSpaceRenderable, public WwtCommunicator +{ +public: + constexpr static const double FovThreshold = 0.001; - // Constructor and destructor - ScreenSpaceSkyBrowser(const ghoul::Dictionary& dictionary); - ~ScreenSpaceSkyBrowser(); + explicit ScreenSpaceSkyBrowser(const ghoul::Dictionary& dictionary); + ~ScreenSpaceSkyBrowser(); - // Inherited functions - bool initializeGL() override; - bool deinitializeGL() override; - glm::mat4 scaleMatrix() override; - void render() override; - void update() override; + bool initializeGL() override; + bool deinitializeGL() override; + glm::mat4 scaleMatrix() override; + void render() override; + void update() override; - // Animation - bool isAnimated(); - void startFovAnimation(float fov); - void incrementallyAnimateToFov(float deltaTime); + // Animation + bool isAnimated() const; + void startFovAnimation(float fov); + void incrementallyAnimateToFov(float deltaTime); - // Getters - float opacity() const; - glm::vec2 size() const; + // Getters + float opacity() const; + glm::vec2 size() const; - // Setters - void setVerticalFovWithScroll(float scroll); - void setOpacity(float opacity); - void setScreenSpaceSize(const glm::vec2& newSize); - void updateScreenSpaceSize(); + // Setters + void setVerticalFovWithScroll(float scroll); + void setOpacity(float opacity); + void setScreenSpaceSize(const glm::vec2& newSize); + void updateScreenSpaceSize(); - glm::dvec2 fineTuneVector(glm::dvec2 drag); - void setIdInBrowser(); + glm::dvec2 fineTuneVector(glm::dvec2 drag); + void setIdInBrowser(); - void updateTextureResolution(); + void updateTextureResolution(); - private: - properties::DoubleProperty _animationSpeed; - properties::FloatProperty _textureQuality; +private: + properties::DoubleProperty _animationSpeed; + properties::FloatProperty _textureQuality; - void bindTexture() override; + void bindTexture() override; - // Flags - bool _isSyncedWithWwt{ false }; - bool _isFovAnimated{ false }; - bool _textureDimensionsIsDirty{ false }; - bool _sizeIsDirty{ false }; + // Flags + bool _isSyncedWithWwt = false; + bool _isFovAnimated = false; + bool _textureDimensionsIsDirty = false; + bool _sizeIsDirty = false; - // Animation of fieldOfView - float _endVfov{ 0.f }; - glm::vec2 _size{ 0.5f }; - }; -} + // Animation of fieldOfView + float _endVfov = 0.f; + glm::vec2 _size = glm::vec2(0.5f); +}; +} // namespace openspace -#endif // __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER2___H__ +#endif // __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYBROWSER___H__ diff --git a/modules/skybrowser/include/screenspaceskytarget.h b/modules/skybrowser/include/screenspaceskytarget.h index 2fb25ea79d..866a4d9869 100644 --- a/modules/skybrowser/include/screenspaceskytarget.h +++ b/modules/skybrowser/include/screenspaceskytarget.h @@ -1,7 +1,32 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #ifndef __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYTARGET___H__ #define __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYTARGET___H__ #include + #include #include #include @@ -10,92 +35,83 @@ namespace openspace::documentation { struct Documentation; } namespace openspace { - class ScreenSpaceSkyBrowser; +class ScreenSpaceSkyBrowser; - class ScreenSpaceSkyTarget : public ScreenSpaceRenderable { +class ScreenSpaceSkyTarget : public ScreenSpaceRenderable { - public: - constexpr static const float DeltaTimeThreshold = 0.03f; +public: + constexpr static const float DeltaTimeThreshold = 0.03f; - // Constructor & destructor - ScreenSpaceSkyTarget(const ghoul::Dictionary& dictionary); - virtual ~ScreenSpaceSkyTarget(); + explicit ScreenSpaceSkyTarget(const ghoul::Dictionary& dictionary); + virtual ~ScreenSpaceSkyTarget(); - // ScreenSpaceRenderable inherited functions - bool initializeGL() override; - bool deinitializeGL() override; - bool isReady() const override; - void render() override; - void update() override; - glm::mat4 scaleMatrix() override; - void bindTexture() override; // Empty function but has to be defined - void createShaders(); + bool initializeGL() override; + bool deinitializeGL() override; + bool isReady() const override; + void render() override; + void update() override; + glm::mat4 scaleMatrix() override; + void bindTexture() override; // Empty function but has to be defined + void createShaders(); - glm::ivec3 borderColor() const; - float opacity() const; - glm::dvec2 lockedCoordinates() const; + glm::ivec3 borderColor() const; + float opacity() const; + glm::dvec2 lockedCoordinates() const; - // Setters - void setScaleFromVfov(float verticalFov); - void setFovFromScale(); - void setDimensions(glm::vec2 dimensions); - void setColor(glm::ivec3 color); - void setOpacity(float opacity); - void setLock(bool isLocked); - void setEquatorialAim(const glm::dvec2& aim); + void setScaleFromVfov(float verticalFov); + void setFovFromScale(); + void setDimensions(glm::vec2 dimensions); + void setColor(glm::ivec3 color); + void setOpacity(float opacity); + void setLock(bool isLocked); + void setEquatorialAim(const glm::dvec2& aim); - // Target directions - glm::dvec3 directionGalactic() const; - glm::dvec2 equatorialAim() const; + // Target directions + glm::dvec3 directionGalactic() const; + glm::dvec2 equatorialAim() const; - // Locking functionality - bool isLocked() const; + // Locking functionality + bool isLocked() const; - // Animation - bool isAnimated(); - void startAnimation(glm::dvec3 end, bool shouldLockAfter = true); - void incrementallyAnimateToCoordinate(float deltaTime); - // Display - void highlight(glm::ivec3 addition); - void removeHighlight(glm::ivec3 removal); + // Animation + bool isAnimated(); + void startAnimation(glm::dvec3 end, bool shouldLockAfter = true); + void incrementallyAnimateToCoordinate(float deltaTime); + // Display + void highlight(glm::ivec3 addition); + void removeHighlight(glm::ivec3 removal); - private: - // Properties - properties::FloatProperty _showCrosshairThreshold; - properties::FloatProperty _showRectangleThreshold; - properties::FloatProperty _lineWidth; - properties::DoubleProperty _stopAnimationThreshold; - properties::DoubleProperty _animationSpeed; +private: + // Properties + properties::FloatProperty _showCrosshairThreshold; + properties::FloatProperty _showRectangleThreshold; + properties::FloatProperty _lineWidth; + properties::DoubleProperty _stopAnimationThreshold; + properties::DoubleProperty _animationSpeed; - // Flags - bool _isLocked{ false }; - bool _isAnimated{ false }; - bool _shouldLockAfterAnimation{ false }; + // Flags + bool _isLocked = false; + bool _isAnimated = false; + bool _shouldLockAfterAnimation = false; - // Shader - UniformCache( - modelTransform, - viewProj, - showCrosshair, - showRectangle, - lineWidth, - dimensions, - lineColor) _uniformCache; - GLuint _vertexArray = 0; - GLuint _vertexBuffer = 0; + // Shader + UniformCache(modelTransform, viewProj, showCrosshair, showRectangle, lineWidth, + dimensions, lineColor) _uniformCache; + GLuint _vertexArray = 0; + GLuint _vertexBuffer = 0; - // Sky browser - float _verticalFov{ 70.0f }; - glm::dvec2 _equatorialAim{ 0.0 }; - glm::ivec3 _borderColor{ 255 }; + // Sky browser + float _verticalFov = 70.0f; + glm::dvec2 _equatorialAim = glm::dvec2(0.0); + glm::ivec3 _borderColor = glm::ivec3(255); - // Lock target to a coordinate on the sky - glm::dvec3 _lockedCoordinates; // Cartesian equatorial coordinates + // Lock target to a coordinate on the sky + glm::dvec3 _lockedCoordinates; // Cartesian equatorial coordinates - // Animation - glm::dvec3 _animationEnd; // Cartesian equatorial coordinates - glm::dvec3 _animationStart; // Cartesian equatorial coordinates - }; + // Animation + glm::dvec3 _animationEnd; // Cartesian equatorial coordinates + glm::dvec3 _animationStart; // Cartesian equatorial coordinates +}; } #endif // __OPENSPACE_MODULE_SKYBROWSER___SCREENSPACESKYTARGET___H__ diff --git a/modules/skybrowser/include/targetbrowserpair.h b/modules/skybrowser/include/targetbrowserpair.h index a074a5b09f..5fe396cfa8 100644 --- a/modules/skybrowser/include/targetbrowserpair.h +++ b/modules/skybrowser/include/targetbrowserpair.h @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2021 * + * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -37,13 +37,10 @@ class ImageData; class TargetBrowserPair { public: - constexpr static const float FadeThreshold = 0.01f; constexpr static const double AnimationThreshold = 0.0001f; TargetBrowserPair(ScreenSpaceSkyBrowser* browser, ScreenSpaceSkyTarget* target); - TargetBrowserPair(TargetBrowserPair const&) = default; - // user-defined copy assignment (copy-and-swap idiom) TargetBrowserPair& operator=(TargetBrowserPair other); // Target & Browser @@ -73,14 +70,12 @@ public: void lock(); void unlock(); - // Boolean functions bool hasFinishedFading(float goalState) const; bool isFacingCamera() const; bool isUsingRadiusAzimuthElevation() const; bool isEnabled() const; bool isLocked() const; - // Setters void setEnabled(bool enable); void setIsSyncedWithWwt(bool isSynced); void setVerticalFov(float vfov); @@ -90,7 +85,6 @@ public: void setVerticalFovWithScroll(float scroll); void setSelectedWithId(const std::string& id); - // Getters by value float verticalFov() const; glm::ivec3 borderColor() const; glm::dvec2 targetDirectionEquatorial() const; @@ -100,8 +94,7 @@ public: std::string targetId() const; std::string selectedId(); glm::vec2 size() const; - - // Getters by reference + ScreenSpaceSkyTarget* getTarget(); ScreenSpaceSkyBrowser* getBrowser(); const std::deque& getSelectedImages() const; @@ -114,7 +107,6 @@ public: void setImageOpacity(int i, float opacity); void hideChromeInterface(bool shouldHide); - // Comparision operators friend bool operator==(const TargetBrowserPair& lhs, const TargetBrowserPair& rhs); friend bool operator!=(const TargetBrowserPair& lhs, diff --git a/modules/skybrowser/include/utility.h b/modules/skybrowser/include/utility.h index c8c394a411..37756b13f9 100644 --- a/modules/skybrowser/include/utility.h +++ b/modules/skybrowser/include/utility.h @@ -1,63 +1,81 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #ifndef __OPENSPACE_MODULE_SKYBROWSER___UTILITY___H__ #define __OPENSPACE_MODULE_SKYBROWSER___UTILITY___H__ #include -namespace openspace { - namespace skybrowser { - // Constants - constexpr const double ScreenSpaceZ = -2.1; - constexpr const glm::dvec3 NorthPole = { 0.0 , 0.0 , 1.0 }; - constexpr const double CelestialSphereRadius = std::numeric_limits::max(); +namespace openspace::skybrowser { +// Constants +constexpr const double ScreenSpaceZ = -2.1; +constexpr const glm::dvec3 NorthPole = { 0.0 , 0.0 , 1.0 }; +constexpr const double CelestialSphereRadius = std::numeric_limits::max(); - // Conversion matrix - J2000 equatorial <-> galactic - // https://arxiv.org/abs/1010.3773v1 - const glm::dmat3 conversionMatrix = glm::dmat3({ - -0.054875539390, 0.494109453633, -0.867666135681, // col 0 - -0.873437104725, -0.444829594298, -0.198076389622, // col 1 - -0.483834991775, 0.746982248696, 0.455983794523 // col 2 - }); +// Conversion matrix - J2000 equatorial <-> galactic +// https://arxiv.org/abs/1010.3773v1 +const glm::dmat3 conversionMatrix = glm::dmat3({ + -0.054875539390, 0.494109453633, -0.867666135681, // col 0 + -0.873437104725, -0.444829594298, -0.198076389622, // col 1 + -0.483834991775, 0.746982248696, 0.455983794523 // col 2 + }); - // Galactic coordinates are projected onto the celestial sphere - // Equatorial coordinates are unit length - // Conversion spherical <-> Cartesian - glm::dvec2 cartesianToSpherical(const glm::dvec3& coords); - glm::dvec3 sphericalToCartesian(const glm::dvec2& coords); +// Galactic coordinates are projected onto the celestial sphere +// Equatorial coordinates are unit length +// Conversion spherical <-> Cartesian +glm::dvec2 cartesianToSpherical(const glm::dvec3& coords); +glm::dvec3 sphericalToCartesian(const glm::dvec2& coords); - // Conversion J2000 equatorial <-> galactic - glm::dvec3 galacticToEquatorial(const glm::dvec3& coords); - glm::dvec3 equatorialToGalactic(const glm::dvec3& coords); +// Conversion J2000 equatorial <-> galactic +glm::dvec3 galacticToEquatorial(const glm::dvec3& coords); +glm::dvec3 equatorialToGalactic(const glm::dvec3& coords); - // Conversion to screen space from local camera / pixels - glm::dvec3 localCameraToScreenSpace3d(const glm::dvec3& coords); - glm::vec2 pixelToScreenSpace2d(const glm::vec2& mouseCoordinate); +// Conversion to screen space from local camera / pixels +glm::dvec3 localCameraToScreenSpace3d(const glm::dvec3& coords); +glm::vec2 pixelToScreenSpace2d(const glm::vec2& mouseCoordinate); - // Conversion local camera space <-> galactic / equatorial - glm::dvec3 equatorialToLocalCamera(const glm::dvec3& coords); - glm::dvec3 galacticToLocalCamera(const glm::dvec3& coords); - glm::dvec3 localCameraToGalactic(const glm::dvec3& coords); - glm::dvec3 localCameraToEquatorial(const glm::dvec3& coords); +// Conversion local camera space <-> galactic / equatorial +glm::dvec3 equatorialToLocalCamera(const glm::dvec3& coords); +glm::dvec3 galacticToLocalCamera(const glm::dvec3& coords); +glm::dvec3 localCameraToGalactic(const glm::dvec3& coords); +glm::dvec3 localCameraToEquatorial(const glm::dvec3& coords); - // Camera roll and direction - double cameraRoll(); // Camera roll is with respect to the equatorial North Pole - glm::dvec3 cameraDirectionGalactic(); - glm::dvec3 cameraDirectionEquatorial(); +// Camera roll and direction +double cameraRoll(); // Camera roll is with respect to the equatorial North Pole +glm::dvec3 cameraDirectionGalactic(); +glm::dvec3 cameraDirectionEquatorial(); - // Window and field of view - float windowRatio(); - glm::dvec2 fovWindow(); - bool isCoordinateInView(const glm::dvec3& equatorial); +// Window and field of view +float windowRatio(); +glm::dvec2 fovWindow(); +bool isCoordinateInView(const glm::dvec3& equatorial); - // Animation for target and camera - double angleBetweenVectors(const glm::dvec3& start, const glm::dvec3& end); - glm::dmat4 incrementalAnimationMatrix(const glm::dvec3& start, - const glm::dvec3& end, - double deltaTime, - double speedFactor = 1.0); - } -} +// Animation for target and camera +double angleBetweenVectors(const glm::dvec3& start, const glm::dvec3& end); +glm::dmat4 incrementalAnimationMatrix(const glm::dvec3& start, const glm::dvec3& end, + double deltaTime, double speedFactor = 1.0); + +} // namespace openspace::skybrowser #endif // __OPENSPACE_MODULE_SKYBROWSER___UTILITY___H__ - - - diff --git a/modules/skybrowser/include/wwtcommunicator.h b/modules/skybrowser/include/wwtcommunicator.h index 1cc582e293..7ef1c1adf8 100644 --- a/modules/skybrowser/include/wwtcommunicator.h +++ b/modules/skybrowser/include/wwtcommunicator.h @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2021 * + * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -26,6 +26,7 @@ #define __OPENSPACE_MODULE_SKYBROWSER___WWTCOMMUNICATOR___H__ #include + #include #include #include @@ -35,11 +36,10 @@ namespace openspace { class WwtCommunicator : public Browser { - public: - WwtCommunicator(const ghoul::Dictionary& dictionary); - WwtCommunicator(WwtCommunicator const&) = default; - virtual ~WwtCommunicator(); + explicit WwtCommunicator(const ghoul::Dictionary& dictionary); + WwtCommunicator(const WwtCommunicator&) = default; + ~WwtCommunicator(); void update(); void render(); @@ -48,74 +48,65 @@ public: // WorldWide Telescope communication void displayImage(const std::string& url, int i); - void removeSelectedImage(const int i); + void removeSelectedImage(int i); void setImageOrder(int i, int order); void loadImageCollection(const std::string& collection); void setImageOpacity(int i, float opacity); void hideChromeInterface(bool shouldHide); - // Getters - const std::deque& getSelectedImages(); - glm::ivec3 borderColor() const; - float verticalFov() const; - glm::dvec2 fieldsOfView(); bool hasLoadedImages() const; + float verticalFov() const; + glm::ivec3 borderColor() const; glm::dvec2 equatorialAim() const; + glm::dvec2 fieldsOfView() const; + const std::deque& getSelectedImages() const; - // Setters void setHasLoadedImages(bool isLoaded); void setVerticalFov(float vfov); void setIsSyncedWithWwt(bool isSynced); - void setEquatorialAim(const glm::dvec2& equatorial); - void setBorderColor(const glm::ivec3& color); + void setEquatorialAim(glm::dvec2 equatorial); + void setBorderColor(glm::ivec3 color); - // Display void highlight(glm::ivec3 addition); + // The removal parameter decides what will be removed from the border color void removeHighlight(glm::ivec3 removal); void updateBorderColor(); void updateAim(); - protected: - // Web page communication void setIdInBrowser(const std::string& id); - glm::dvec2 _equatorialAim; - float _verticalFov{ 10.f }; - glm::ivec3 _borderColor; - + float _verticalFov = 10.f; + glm::ivec3 _borderColor = glm::ivec3(70); + glm::dvec2 _equatorialAim = glm::dvec2(0.0); + bool _hasLoadedImages = false; std::deque _selectedImages; - bool _hasLoadedImages{ false }; private: - bool _isSyncedWithWwt{ false }; - - bool _borderColorIsDirty{ false }; - bool _equatorialAimIsDirty{ false }; - void setWebpageBorderColor(glm::ivec3 color); void sendMessageToWwt(const ghoul::Dictionary& msg); - int messageCounter{ 0 }; - - ghoul::Dictionary moveCamera(const glm::dvec2& celestCoords, double fov, + // WorldWide Telescope messages + ghoul::Dictionary moveCameraMessage(const glm::dvec2& celestCoords, double fov, double roll, bool shouldMoveInstantly = true); - ghoul::Dictionary loadCollection(const std::string& url); - ghoul::Dictionary setForeground(const std::string& name); - ghoul::Dictionary addImage(const std::string& id, const std::string& url); - ghoul::Dictionary removeImage(const std::string& id); - ghoul::Dictionary setImageOpacity(const std::string& id, double opacity); - ghoul::Dictionary setForegroundOpacity(double val); - ghoul::Dictionary setLayerOrder(const std::string& id, int version); - ghoul::Dictionary hideChromeGui(bool isHidden); + ghoul::Dictionary loadCollectionMessage(const std::string& url); + ghoul::Dictionary setForegroundMessage(const std::string& name); + ghoul::Dictionary addImageMessage(const std::string& id, const std::string& url); + ghoul::Dictionary removeImageMessage(const std::string& id); + ghoul::Dictionary setImageOpacityMessage(const std::string& id, double opacity); + ghoul::Dictionary setLayerOrderMessage(const std::string& id, int version); + ghoul::Dictionary hideChromeGuiMessage(bool isHidden); // Requires a newer CEF version + + bool _isSyncedWithWwt = false; + bool _borderColorIsDirty = false; + bool _equatorialAimIsDirty = false; + int messageCounter{ 0 }; // Time variables // For capping the message passing to WWT - constexpr static const std::chrono::milliseconds _timeUpdateInterval{ 10 }; + constexpr static const std::chrono::milliseconds TimeUpdateInterval{ 10 }; std::chrono::system_clock::time_point _lastUpdateTime; - }; - } // namespace openspace #endif // __OPENSPACE_MODULE_SKYBROWSER___WWTCOMMUNICATOR___H__ diff --git a/modules/skybrowser/include/wwtdatahandler.h b/modules/skybrowser/include/wwtdatahandler.h index fb11d48dd4..eaf32819b8 100644 --- a/modules/skybrowser/include/wwtdatahandler.h +++ b/modules/skybrowser/include/wwtdatahandler.h @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + #ifndef __OPENSPACE_MODULE_SKYBROWSER___WWTDATAHANDLER___H__ #define __OPENSPACE_MODULE_SKYBROWSER___WWTDATAHANDLER___H__ @@ -24,45 +48,41 @@ namespace openspace::wwt { const std::string ZoomLevel = "ZoomLevel"; const std::string DataSetType = "DataSetType"; const std::string Sky = "Sky"; -} // namespace openspace::wwt\ +} // namespace openspace::wwt namespace openspace { - struct ImageData { - std::string name{ wwt::Undefined }; - std::string thumbnailUrl{ wwt::Undefined }; - std::string imageUrl{ wwt::Undefined }; - std::string credits{ wwt::Undefined }; - std::string creditsUrl{ wwt::Undefined }; - std::string collection{ wwt::Undefined }; - bool hasCelestialCoords{ false }; - float fov{ 0.f }; - glm::dvec2 equatorialSpherical{ 0.0 }; - glm::dvec3 equatorialCartesian{ 0.0 }; - }; +struct ImageData { + std::string name{ wwt::Undefined }; + std::string thumbnailUrl{ wwt::Undefined }; + std::string imageUrl{ wwt::Undefined }; + std::string credits{ wwt::Undefined }; + std::string creditsUrl{ wwt::Undefined }; + std::string collection{ wwt::Undefined }; + bool hasCelestialCoords = false; + float fov = 0.f; + glm::dvec2 equatorialSpherical = glm::dvec2(0.0); + glm::dvec3 equatorialCartesian = glm::dvec3(0.0); +}; - class WwtDataHandler { - - public: - WwtDataHandler() = default; - ~WwtDataHandler(); +class WwtDataHandler { +public: + WwtDataHandler() = default; + ~WwtDataHandler(); - void loadImages(const std::string& root, const std::string& directory); - int nLoadedImages() const; - const ImageData& getImage(int i) const; + void loadImages(const std::string& root, const std::filesystem::path& directory); + int nLoadedImages() const; + const ImageData& getImage(int i) const; - private: - void saveImageFromNode(tinyxml2::XMLElement* node, std::string collection); - void saveImagesFromXml(tinyxml2::XMLElement* root, std::string collection); +private: + void saveImageFromNode(tinyxml2::XMLElement* node, std::string collection); + void saveImagesFromXml(tinyxml2::XMLElement* root, std::string collection); - // Images - std::vector _images; - std::vector _xmls; - - }; + // Images + std::vector _images; + std::vector _xmls; +}; } - - #endif // __OPENSPACE_MODULE_SKYBROWSER___WWTDATAHANDLER___H__ diff --git a/modules/skybrowser/shaders/target_fs.glsl b/modules/skybrowser/shaders/target_fs.glsl index d1b3a605a7..4d70cad072 100644 --- a/modules/skybrowser/shaders/target_fs.glsl +++ b/modules/skybrowser/shaders/target_fs.glsl @@ -1,65 +1,85 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +in vec2 vs_st; +in vec4 vs_position; + uniform float lineWidth; uniform vec2 dimensions; uniform bool showCrosshair; uniform bool showRectangle; uniform vec4 lineColor; -in vec2 vs_st; -in vec4 vs_position; - // A factor which states how much thicker vertical lines are rendered than horizontal // This compensates for the optical illusion that vertical lines appear thinner -#define VERTICAL_THICKNESS 1.15f +const float VerticalThickness = 1.15; -float createLine(in float lineCenter, in float lineWidth, in float coord) { +float createLine(float lineCenter, float lineWidth, float coord) { // Calculate edges of line - float start_edge = lineCenter - (lineWidth * 0.5f); - float end_edge = lineCenter + (lineWidth * 0.5f); + float startEdge = lineCenter - (lineWidth * 0.5); + float endEdge = lineCenter + (lineWidth * 0.5); - // Create line - float line = step(start_edge, coord) - step(end_edge, coord); - - return line; + return step(startEdge, coord) - step(endEdge, coord); } -float createRectangle(in float linewidth_y, in float ratio, in vec2 coord) { +float createRectangle(float linewidthY, float ratio, vec2 coord) { // Calculate the widths and centers for the lines - float linewidth_x = linewidth_y * ratio * VERTICAL_THICKNESS; - float linecenter_x = linewidth_x * 0.5f; - float linecenter_y = linewidth_y * 0.5f; + float linewidthX = linewidthY * ratio * VerticalThickness; + float linecenterX = linewidthX * 0.5; + float linecenterY = linewidthY * 0.5; // Create the four lines for the rectangle - float l = createLine(linecenter_x, linewidth_x, coord.x); - float r = createLine(1.0f - linecenter_x, linewidth_x, coord.x); - float b = createLine(linecenter_y, linewidth_y, coord.y); - float t = createLine(1.0f - linecenter_y, linewidth_y, coord.y); + float l = createLine(linecenterX, linewidthX, coord.x); + float r = createLine(1.0 - linecenterX, linewidthX, coord.x); + float b = createLine(linecenterY, linewidthY, coord.y); + float t = createLine(1.0 - linecenterY, linewidthY, coord.y); - // Add all lines together return l + r + b + t; } float createCrosshair(in float linewidth, in float ratio, in vec2 coord) { - float center = 0.5f; - float crosshair_vertical = createLine(center, linewidth * ratio * VERTICAL_THICKNESS, coord.x); - float crosshair_horizontal = createLine(center, linewidth, coord.y); + const float Center = 0.5; + float crosshairVertical = createLine(Center, linewidth * ratio * VerticalThickness, coord.x); + float crosshairHorizontal = createLine(Center, linewidth, coord.y); - return crosshair_horizontal + crosshair_vertical; + return crosshairHorizontal + crosshairVertical; } #include "fragment.glsl" Fragment getFragment() { float ratio = dimensions.y / dimensions.x; - float crosshair = 0.0f; - float rectangle = 0.0f; + float crosshair = 0.0; + float rectangle = 0.0; - if(showCrosshair) { + if (showCrosshair) { crosshair = createCrosshair(lineWidth, ratio, vs_st); - float border = 1.0f - createRectangle(lineWidth * 5.0f, ratio, vs_st); + float border = 1.0 - createRectangle(lineWidth * 5.0, ratio, vs_st); crosshair *= border; } - if(showRectangle) { + if (showRectangle) { rectangle = createRectangle(lineWidth, ratio, vs_st); } diff --git a/modules/skybrowser/shaders/target_vs.glsl b/modules/skybrowser/shaders/target_vs.glsl index c1d2e7c618..9d91c1e636 100644 --- a/modules/skybrowser/shaders/target_vs.glsl +++ b/modules/skybrowser/shaders/target_vs.glsl @@ -1,14 +1,37 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #version __CONTEXT__ +out vec2 vs_st; +out vec4 vs_position; + uniform mat4 modelTransform; uniform mat4 viewProj; layout(location = 0) in vec4 in_position; layout(location = 1) in vec2 in_st; -out vec2 vs_st; -out vec4 vs_position; - void main(){ vs_st = in_st; vs_position = viewProj * modelTransform * in_position; diff --git a/modules/skybrowser/skybrowsermodule.cpp b/modules/skybrowser/skybrowsermodule.cpp index c4d2006b5c..5ed31a0836 100644 --- a/modules/skybrowser/skybrowsermodule.cpp +++ b/modules/skybrowser/skybrowsermodule.cpp @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2021 * + * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -22,7 +22,6 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ - #include #include @@ -30,7 +29,6 @@ #include #include #include -#include "skybrowsermodule_lua.inl" #include #include #include @@ -39,9 +37,9 @@ #include #include +#include "skybrowsermodule_lua.inl" namespace { - constexpr const openspace::properties::Property::PropertyInfo AllowInteractionInfo = { "AllowMouseInteraction", @@ -69,11 +67,8 @@ namespace { #include "skybrowsermodule_codegen.cpp" } // namespace - namespace openspace { - scripting::LuaLibrary SkyBrowserModule::luaLibrary() const { - scripting::LuaLibrary res; res.name = "skybrowser"; res.functions = { @@ -263,8 +258,6 @@ namespace openspace { return res; } - - SkyBrowserModule::SkyBrowserModule() : OpenSpaceModule(SkyBrowserModule::Name) , _allowMouseInteraction(AllowInteractionInfo, true) @@ -276,7 +269,6 @@ SkyBrowserModule::SkyBrowserModule() // Set callback functions global::callback::mouseButton->emplace_back( [&](MouseButton button, MouseAction action, KeyModifier modifier) -> bool { - if (!_isCameraInSolarSystem || !_allowMouseInteraction) { return false; } @@ -304,7 +296,6 @@ SkyBrowserModule::SkyBrowserModule() if (global::windowDelegate->isMaster()) { global::callback::mousePosition->emplace_back( [&](double x, double y) { - if (!_isCameraInSolarSystem || !_allowMouseInteraction) { return false; } @@ -314,30 +305,25 @@ SkyBrowserModule::SkyBrowserModule() glm::vec2 translation = _mousePosition - _startMousePosition; switch (_interactionMode) { - case MouseInteraction::Hover: - setSelectedObject(); - - break; - - case MouseInteraction::Drag: - _mouseOnPair->translateSelected(_startDragPosition, translation); - break; - - case MouseInteraction::FineTune: - _mouseOnPair->fineTuneTarget(_startDragPosition, translation); - break; - - default: - setSelectedObject(); - break; - } + case MouseInteraction::Hover: + setSelectedObject(); + break; + case MouseInteraction::Drag: + _mouseOnPair->translateSelected(_startDragPosition, translation); + break; + case MouseInteraction::FineTune: + _mouseOnPair->fineTuneTarget(_startDragPosition, translation); + break; + default: + setSelectedObject(); + break; + } return false; } ); global::callback::mouseScrollWheel->emplace_back( [&](double, double scroll) -> bool { - if (!_isCameraInSolarSystem || !_mouseOnPair || !_allowMouseInteraction) { return false; } @@ -351,7 +337,6 @@ SkyBrowserModule::SkyBrowserModule() } global::callback::preSync->emplace_back([this]() { - // Disable browser and targets when camera is outside of solar system bool camWasInSolarSystem = _isCameraInSolarSystem; glm::dvec3 cameraPos = global::navigationHandler->camera()->positionVec3(); @@ -375,10 +360,13 @@ SkyBrowserModule::SkyBrowserModule() incrementallyFadeBrowserTargets(_goal, deltaTime); } if (_isCameraInSolarSystem) { - std::for_each(std::begin(_targetsBrowsers), std::end(_targetsBrowsers), + std::for_each( + _targetsBrowsers.begin(), + _targetsBrowsers.end(), [&](const std::unique_ptr& pair) { pair->synchronizeAim(); - }); + } + ); incrementallyAnimateTargets(deltaTime); } if (_isCameraRotating && _allowCameraRotation) { @@ -387,18 +375,12 @@ SkyBrowserModule::SkyBrowserModule() }); } -SkyBrowserModule::~SkyBrowserModule() { -} - -void SkyBrowserModule::internalDeinitialize() { -} - void SkyBrowserModule::internalInitialize(const ghoul::Dictionary& dict) { - const Parameters p = codegen::bake(dict); // Register ScreenSpaceRenderable - auto fScreenSpaceRenderable = FactoryManager::ref().factory(); + ghoul::TemplateFactory* fScreenSpaceRenderable = + FactoryManager::ref().factory(); ghoul_assert(fScreenSpaceRenderable, "ScreenSpaceRenderable factory was not created"); // Register ScreenSpaceSkyTarget @@ -412,8 +394,7 @@ void SkyBrowserModule::internalInitialize(const ghoul::Dictionary& dict) { _dataHandler = std::make_unique(); } -void SkyBrowserModule::setSelectedObject() -{ +void SkyBrowserModule::setSelectedObject() { if (_interactionMode != MouseInteraction::Hover) { return; } @@ -421,13 +402,15 @@ void SkyBrowserModule::setSelectedObject() TargetBrowserPair* previousPair = _mouseOnPair; // Find and save what mouse is currently hovering on - auto it = std::find_if(std::begin(_targetsBrowsers), std::end(_targetsBrowsers), + auto it = std::find_if( + _targetsBrowsers.begin(), + _targetsBrowsers.end(), [&] (const std::unique_ptr &pair) { return pair->checkMouseIntersection(_mousePosition) && !pair->isUsingRadiusAzimuthElevation(); }); - if (it == std::end(_targetsBrowsers)) { + if (it == _targetsBrowsers.end()) { _mouseOnPair = nullptr; } else { @@ -436,7 +419,6 @@ void SkyBrowserModule::setSelectedObject() // Selection has changed if (previousPair != _mouseOnPair) { - // Remove highlight if (previousPair) { previousPair->removeHighlight(_highlightAddition); @@ -449,13 +431,12 @@ void SkyBrowserModule::setSelectedObject() } void SkyBrowserModule::addTargetBrowserPair(const std::string& targetId, const std::string& browserId) { - ScreenSpaceSkyTarget* target = dynamic_cast( global::renderEngine->screenSpaceRenderable(targetId) - ); + ); ScreenSpaceSkyBrowser* browser = dynamic_cast( global::renderEngine->screenSpaceRenderable(browserId) - ); + ); // Ensure pair has both target and browser if (browser && target) { @@ -464,36 +445,35 @@ void SkyBrowserModule::addTargetBrowserPair(const std::string& targetId, const s } void SkyBrowserModule::removeTargetBrowserPair(const std::string& id) { - TargetBrowserPair* found = getPair(id); if (!found) { return; } - auto it = std::remove_if(std::begin(_targetsBrowsers), std::end(_targetsBrowsers), + auto it = std::remove_if( + _targetsBrowsers.begin(), + _targetsBrowsers.end(), [&](const std::unique_ptr& pair) { return *found == *(pair.get()); - }); + } + ); - _targetsBrowsers.erase(it, std::end(_targetsBrowsers)); + _targetsBrowsers.erase(it, _targetsBrowsers.end()); _mouseOnPair = nullptr; } -void SkyBrowserModule::lookAtTarget(std::string id) -{ +void SkyBrowserModule::lookAtTarget(const std::string& id) { TargetBrowserPair* pair = getPair(id); if (pair) { startRotatingCamera(pair->targetDirectionGalactic()); } } -void SkyBrowserModule::setHoverCircle(ScreenSpaceImageLocal* circle) -{ +void SkyBrowserModule::setHoverCircle(ScreenSpaceImageLocal* circle) { _hoverCircle = circle; } -void SkyBrowserModule::moveHoverCircle(int i) -{ +void SkyBrowserModule::moveHoverCircle(int i) { const ImageData& image = _dataHandler->getImage(i); // Only move and show circle if the image has coordinates @@ -516,25 +496,22 @@ void SkyBrowserModule::moveHoverCircle(int i) } } -void SkyBrowserModule::disableHoverCircle() -{ +void SkyBrowserModule::disableHoverCircle() { if (_hoverCircle && _hoverCircle->isEnabled()) { _hoverCircle->setEnabled(false); } } -void SkyBrowserModule::loadImages(const std::string& root, const std::string& directory) -{ +void SkyBrowserModule::loadImages(const std::string& root, + const std::filesystem::path& directory) { _dataHandler->loadImages(root, directory); } -int SkyBrowserModule::nLoadedImages() -{ +int SkyBrowserModule::nLoadedImages() { return _dataHandler->nLoadedImages(); } -void SkyBrowserModule::handleMouseClick(const MouseButton& button) -{ +void SkyBrowserModule::handleMouseClick(const MouseButton& button) { setSelectedBrowser(_mouseOnPair->browserId()); if (button == MouseButton::Left) { @@ -561,28 +538,28 @@ void SkyBrowserModule::handleMouseClick(const MouseButton& button) } } -const std::unique_ptr& SkyBrowserModule::getWwtDataHandler() { +const std::unique_ptr& SkyBrowserModule::getWwtDataHandler() const { return _dataHandler; } -std::vector>& SkyBrowserModule::getPairs() -{ +std::vector>& SkyBrowserModule::getPairs() { return _targetsBrowsers; } -int SkyBrowserModule::nPairs() -{ +int SkyBrowserModule::nPairs() { return static_cast(_targetsBrowsers.size()); } -TargetBrowserPair* SkyBrowserModule::getPair(const std::string& id) -{ - auto it = std::find_if(std::begin(_targetsBrowsers), std::end(_targetsBrowsers), +TargetBrowserPair* SkyBrowserModule::getPair(const std::string& id) { + auto it = std::find_if( + _targetsBrowsers.begin(), + _targetsBrowsers.end(), [&](const std::unique_ptr& pair) { bool foundBrowser = pair->browserId() == id; bool foundTarget = pair->targetId() == id; return foundBrowser || foundTarget; - }); + } + ); if (it == std::end(_targetsBrowsers)) { return nullptr; } @@ -623,16 +600,17 @@ void SkyBrowserModule::incrementallyRotateCamera(double deltaTime) { } } -void SkyBrowserModule::incrementallyFadeBrowserTargets(Transparency goal, float deltaTime) +void SkyBrowserModule::incrementallyFadeBrowserTargets(Transparency goal, + float deltaTime) { float transparency = [](Transparency goal) { switch (goal) { - case Transparency::Transparent: - return 0.f; + case Transparency::Transparent: + return 0.f; - case Transparency::Opaque: - return 1.f; - } + case Transparency::Opaque: + return 1.f; + } }(goal); bool isAllFinished{ false }; @@ -655,8 +633,7 @@ void SkyBrowserModule::incrementallyFadeBrowserTargets(Transparency goal, float } } -void SkyBrowserModule::incrementallyAnimateTargets(double deltaTime) -{ +void SkyBrowserModule::incrementallyAnimateTargets(double deltaTime) { for (std::unique_ptr& pair : _targetsBrowsers) { if (pair->isEnabled()) { pair->incrementallyAnimateToCoordinate(deltaTime); @@ -665,59 +642,51 @@ void SkyBrowserModule::incrementallyAnimateTargets(double deltaTime) } void SkyBrowserModule::setSelectedBrowser(const std::string& id) { - if (getPair(id)) { + TargetBrowserPair* found = getPair(id); + if (found) { _selectedBrowser = id; } } -std::string SkyBrowserModule::selectedBrowserId() { +std::string SkyBrowserModule::selectedBrowserId() const { return _selectedBrowser; } -std::string SkyBrowserModule::selectedTargetId() -{ - if (getPair(_selectedBrowser)) { - return getPair(_selectedBrowser)->targetId(); +std::string SkyBrowserModule::selectedTargetId() { + TargetBrowserPair* found = getPair(_selectedBrowser); + if (found) { + return found->targetId(); } else { return ""; } } -glm::ivec3 SkyBrowserModule::highlight() -{ +glm::ivec3 SkyBrowserModule::highlight() const { return _highlightAddition; } -bool SkyBrowserModule::isCameraInSolarSystem() { +bool SkyBrowserModule::isCameraInSolarSystem() const { return _isCameraInSolarSystem; } -bool SkyBrowserModule::isSelectedPairUsingRae() -{ - if (getPair(_selectedBrowser)) { - return getPair(_selectedBrowser)->isUsingRadiusAzimuthElevation(); +bool SkyBrowserModule::isSelectedPairUsingRae() { + TargetBrowserPair* found = getPair(_selectedBrowser); + if (found) { + return found->isUsingRadiusAzimuthElevation(); } else { return false; } } -bool SkyBrowserModule::isSelectedPairFacingCamera() -{ - if (getPair(_selectedBrowser)) { - return getPair(_selectedBrowser)->isFacingCamera(); +bool SkyBrowserModule::isSelectedPairFacingCamera() { + TargetBrowserPair* found = getPair(_selectedBrowser); + if (found) { + return found->isFacingCamera(); } else { return false; } } - -//std::vector SkyBrowserModule::documentations() const { -// return { -// ExoplanetsDataPreparationTask::documentation(), -// RenderableOrbitDisc::Documentation() -// }; -//} - } // namespace openspace diff --git a/modules/skybrowser/skybrowsermodule.h b/modules/skybrowser/skybrowsermodule.h index 874a81d779..6c81635737 100644 --- a/modules/skybrowser/skybrowsermodule.h +++ b/modules/skybrowser/skybrowsermodule.h @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2021 * + * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -25,8 +25,9 @@ #ifndef __OPENSPACE_MODULE_SKYBROWSER___SKYBROWSERMODULE___H__ #define __OPENSPACE_MODULE_SKYBROWSER___SKYBROWSERMODULE___H__ -#include #include + +#include #include #include #include @@ -53,40 +54,34 @@ enum class MouseInteraction { class SkyBrowserModule : public OpenSpaceModule { public: - constexpr static const char* Name = "SkyBrowser"; - constexpr static const double StopAnimationThreshold{ 0.0005 }; - constexpr static const double FadingTime = { 2.0 }; - constexpr static const double AnimationSpeed = { 1.0 }; + constexpr static const double StopAnimationThreshold = 0.0005; + constexpr static const double FadingTime = 2.0; + constexpr static const double AnimationSpeed = 1.0; const double SolarSystemRadius = 30.0 * distanceconstants::AstronomicalUnit; - // Constructor & destructor SkyBrowserModule(); - virtual ~SkyBrowserModule(); - // Getters std::vector>& getPairs(); int nPairs(); TargetBrowserPair* getPair(const std::string& id); - const std::unique_ptr& getWwtDataHandler(); - std::string selectedBrowserId(); + const std::unique_ptr& getWwtDataHandler() const; + std::string selectedBrowserId() const; std::string selectedTargetId(); - glm::ivec3 highlight(); + glm::ivec3 highlight() const; - // Setters void setSelectedBrowser(const std::string& id); void setSelectedObject(); // Manage mouse interactions void setHoverCircle(ScreenSpaceImageLocal* circle); // Rotation, animation, placement - void lookAtTarget(std::string id); + void lookAtTarget(const std::string& id); void startRotatingCamera(glm::dvec3 endAnimation); // Pass in galactic coordinate void incrementallyRotateCamera(double deltaTime); void incrementallyFadeBrowserTargets(Transparency goal, float deltaTime); void incrementallyAnimateTargets(double deltaTime); - // Boolean functions - bool isCameraInSolarSystem(); + bool isCameraInSolarSystem() const; bool isSelectedPairFacingCamera(); bool isSelectedPairUsingRae(); @@ -99,7 +94,7 @@ public: void disableHoverCircle(); // Image collection handling - void loadImages(const std::string& root, const std::string& directory); + void loadImages(const std::string& root, const std::filesystem::path& directory); int nLoadedImages(); // Mouse interaction @@ -110,21 +105,20 @@ public: protected: void internalInitialize(const ghoul::Dictionary& dict) override; - void internalDeinitialize() override; private: properties::BoolProperty _allowMouseInteraction; properties::BoolProperty _allowCameraRotation; - glm::ivec3 _highlightAddition{ 35 }; // Highlight object when mouse hovers + glm::ivec3 _highlightAddition = glm::ivec3(35); // Highlight object when mouse hovers // The browsers and targets std::vector> _targetsBrowsers; - TargetBrowserPair* _mouseOnPair{ nullptr }; - ScreenSpaceImageLocal* _hoverCircle{ nullptr }; - std::string _selectedBrowser{ "" }; // Currently selected browser + TargetBrowserPair* _mouseOnPair = nullptr; + ScreenSpaceImageLocal* _hoverCircle = nullptr; + std::string _selectedBrowser = ""; // Currently selected browser // Fading - Transparency _goal; + Transparency _goal = Transparency::Opaque; // Flags bool _isCameraInSolarSystem{ true }; // Visualization modes @@ -144,7 +138,6 @@ private: // Data handler for the image collections std::unique_ptr _dataHandler; }; - } // namespace openspace #endif // __OPENSPACE_MODULE_SKYBROWSER___SKYBROWSERMODULE___H__ diff --git a/modules/skybrowser/skybrowsermodule_lua.inl b/modules/skybrowser/skybrowsermodule_lua.inl index 45b04cdeb2..08e062ec9b 100644 --- a/modules/skybrowser/skybrowsermodule_lua.inl +++ b/modules/skybrowser/skybrowsermodule_lua.inl @@ -1,3 +1,26 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #include @@ -11,37 +34,36 @@ #include namespace { - constexpr const char _loggerCat[] = "SkyBrowserModule"; + constexpr const char _loggerCat[] = "SkyBrowserModule"; } // namespace namespace openspace::skybrowser::luascriptfunctions { int selectImage(lua_State* L) { - // Load image - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::selectImage"); - const int i = ghoul::lua::value(L, 1); + // Load image + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::selectImage"); + const int i = ghoul::lua::value(L, 1); SkyBrowserModule* module = global::moduleEngine->module(); if (module->isCameraInSolarSystem()) { TargetBrowserPair* selected = module->getPair(module->selectedBrowserId()); if (selected) { - const ImageData& image = module->getWwtDataHandler()->getImage(i); // Load image into browser LINFO("Loading image " + image.name); selected->selectImage(image, i); - bool isInView = skybrowser::isCoordinateInView(image.equatorialCartesian); + bool isInView = isCoordinateInView(image.equatorialCartesian); // If the coordinate is not in view, rotate camera if (image.hasCelestialCoords && !isInView) { module->startRotatingCamera( - skybrowser::equatorialToGalactic(image.equatorialCartesian) + equatorialToGalactic(image.equatorialCartesian) ); } } } - return 0; + return 0; } int setHoverCircle(lua_State* L) { @@ -96,9 +118,8 @@ int unlockTarget(lua_State* L) { int setImageLayerOrder(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setImageLayerOrder"); - const std::string id = ghoul::lua::value(L, 1); - const int i = ghoul::lua::value(L, 1); - int order = ghoul::lua::value(L, 1); + auto [id, i, order] = ghoul::lua::values(L); + SkyBrowserModule* module = global::moduleEngine->module(); if (module->getPair(id)) { @@ -106,10 +127,10 @@ int setImageLayerOrder(lua_State* L) { } return 0; } - + int loadImagesToWWT(lua_State* L) { - // Load images from url - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadImagesToWWT"); + // Load images from url + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadImagesToWWT"); const std::string id = ghoul::lua::value(L, 1); LINFO("Connection established to WorldWide Telescope application in " + id); LINFO("Loading image collections to " + id); @@ -122,11 +143,11 @@ int loadImagesToWWT(lua_State* L) { SkyBrowserModule* module = global::moduleEngine->module(); if (module->getPair(id)) { - //module->getPair(id)->hideChromeInterface(true); + module->getPair(id)->hideChromeInterface(true); module->getPair(id)->loadImageCollection(root); } - return 0; + return 0; } int startSetup(lua_State* L) { @@ -140,12 +161,15 @@ int startSetup(lua_State* L) { for (std::unique_ptr& pair : pairs) { std::string id = pair->browserId(); glm::ivec3 color = pair->borderColor(); - openspace::global::scriptEngine->queueScript( - "openspace.skybrowser.setBorderColor('" + id + "'," + - std::to_string(color.r) + "," + - std::to_string(color.g) + "," + - std::to_string(color.b) + "" + - ");", + std::string script = fmt::format( + "openspace.skybrowser.setBorderColor('{}', {}, {}, {})", + id, + color.r, + color.g, + color.b + ); + global::scriptEngine->queueScript( + script, scripting::ScriptEngine::RemoteScripting::Yes ); } @@ -153,7 +177,7 @@ int startSetup(lua_State* L) { // To ensure each node in a cluster calls its own instance of the wwt application // Do not send this script to the other nodes - openspace::global::scriptEngine->queueScript( + global::scriptEngine->queueScript( "openspace.skybrowser.sendOutIdsToBrowsers();", scripting::ScriptEngine::RemoteScripting::No ); @@ -165,7 +189,7 @@ int sendOutIdsToBrowsers(lua_State* L) { // This is called when the sky_browser website is connected to OpenSpace ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::sendOutIdsToBrowsers"); - // Send out ID's to the browsers + // Send out identifiers to the browsers SkyBrowserModule* module = global::moduleEngine->module(); std::vector>& pairs = module->getPairs(); for (std::unique_ptr& pair : pairs) { @@ -182,9 +206,10 @@ int initializeBrowser(lua_State* L) { LINFO("Initializing sky browser " + id); SkyBrowserModule* module = global::moduleEngine->module(); - if (module->getPair(id)) { - module->getPair(id)->setIsSyncedWithWwt(true); - module->getPair(id)->initialize(); + TargetBrowserPair* found = module->getPair(id); + if (found) { + found->setIsSyncedWithWwt(true); + found->initialize(); } return 0; @@ -192,12 +217,11 @@ int initializeBrowser(lua_State* L) { int addPairToSkyBrowserModule(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addPairToSkyBrowserModule"); - const std::string targetId = ghoul::lua::value(L, 1); - const std::string browserId = ghoul::lua::value(L, 1); + auto [targetId, browserId] = ghoul::lua::values(L); SkyBrowserModule* module = global::moduleEngine->module(); - LINFO("Add browser " + browserId + " to sky browser module."); - LINFO("Add target " + targetId + " to sky browser module."); + LINFO("Add browser " + browserId + " to sky browser module"); + LINFO("Add target " + targetId + " to sky browser module"); module->addTargetBrowserPair(targetId, browserId); @@ -205,30 +229,26 @@ int addPairToSkyBrowserModule(lua_State* L) { } int getListOfImages(lua_State* L) { - // Send image list to GUI - ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfImages"); - SkyBrowserModule* module = global::moduleEngine->module(); + // Send image list to GUI + ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfImages"); + SkyBrowserModule* module = global::moduleEngine->module(); - // If no data has been loaded yet, download the data from the web! + // If no data has been loaded yet, download the data from the web! - if (module->nLoadedImages() == 0) { + if (module->nLoadedImages() == 0) { std::string root = "https://raw.githubusercontent.com/WorldWideTelescope/" "wwt-web-client/master/assets/webclient-explore-root.wtml"; - std::string directory = absPath("${MODULE_SKYBROWSER}/WWTimagedata/").string(); + std::filesystem::path directory = absPath("${MODULE_SKYBROWSER}/WWTimagedata/"); module->loadImages(root, directory); - } - + } + // Create Lua table to send to the GUI lua_newtable(L); - for (int i = 0; i < module->nLoadedImages(); i++) { + for (int i = 0; i < module->nLoadedImages(); i++) { const ImageData& img = module->getWwtDataHandler()->getImage(i); - glm::dvec3 coords = img.equatorialCartesian; - - // Conversions for ghoul - std::vector cartCoordsVec = { coords.x, coords.y, coords.z }; // Index for current ImageData ghoul::lua::push(L, i + 1); @@ -242,7 +262,7 @@ int getListOfImages(lua_State* L) { lua_settable(L, -3); ghoul::lua::push(L, "dec", img.equatorialSpherical.y); lua_settable(L, -3); - ghoul::lua::push(L, "cartesianDirection", cartCoordsVec); + ghoul::lua::push(L, "cartesianDirection", img.equatorialCartesian); lua_settable(L, -3); ghoul::lua::push(L, "hasCelestialCoords", img.hasCelestialCoords); lua_settable(L, -3); @@ -255,9 +275,9 @@ int getListOfImages(lua_State* L) { // Set table for the current ImageData lua_settable(L, -3); - } + } - return 1; + return 1; } int getTargetData(lua_State* L) { @@ -273,20 +293,14 @@ int getTargetData(lua_State* L) { lua_newtable(L); glm::dvec3 cartesianCam = skybrowser::cameraDirectionEquatorial(); glm::dvec2 sphericalCam = skybrowser::cartesianToSpherical(cartesianCam); - // Convert to vector so ghoul can read it - std::vector viewDirCelestVec = { - cartesianCam.x, - cartesianCam.y, - cartesianCam.z - }; - + // Calculate the smallest FOV of vertical and horizontal glm::dvec2 fovs = skybrowser::fovWindow(); double FOV = std::min(fovs.x, fovs.y); // Push window data ghoul::lua::push(L, "windowHFOV", FOV); lua_settable(L, -3); - ghoul::lua::push(L, "cartesianDirection", viewDirCelestVec); + ghoul::lua::push(L, "cartesianDirection", cartesianCam); lua_settable(L, -3); ghoul::lua::push(L, "ra", sphericalCam.x); lua_settable(L, -3); @@ -314,26 +328,16 @@ int getTargetData(lua_State* L) { // Convert deque to vector so ghoul can read it std::vector selectedImagesVector; const std::deque selectedImages = pair->getSelectedImages(); - std::for_each(selectedImages.begin(), selectedImages.end(), [&](int i) { - selectedImagesVector.push_back(i); - }); + std::for_each( + selectedImages.begin(), + selectedImages.end(), + [&](int i) { + selectedImagesVector.push_back(i); + } + ); glm::dvec2 spherical = pair->targetDirectionEquatorial(); glm::dvec3 cartesian = skybrowser::sphericalToCartesian(spherical); - - - std::vector cartesianVec = { - cartesian.x, - cartesian.y, - cartesian.z - }; - // Convert color to vector so ghoul can read it - glm::ivec3 color = pair->borderColor(); - std::vector colorVec = { color.r, color.g, color.b }; - - // Convert color to vector so ghoul can read it - glm::vec2 size = pair->size(); - std::vector sizeVec = { size.x, size.y }; ghoul::lua::push(L, id); lua_newtable(L); @@ -346,49 +350,47 @@ int getTargetData(lua_State* L) { lua_settable(L, -3); ghoul::lua::push(L, "selectedImages", selectedImagesVector); lua_settable(L, -3); - ghoul::lua::push(L, "cartesianDirection", cartesianVec); + ghoul::lua::push(L, "cartesianDirection", cartesian); lua_settable(L, -3); ghoul::lua::push(L, "ra", spherical.x); lua_settable(L, -3); ghoul::lua::push(L, "dec", spherical.y); lua_settable(L, -3); - ghoul::lua::push(L, "color", colorVec); + ghoul::lua::push(L, "color", pair->borderColor()); lua_settable(L, -3); ghoul::lua::push(L, "isLocked", pair->isLocked()); lua_settable(L, -3); - ghoul::lua::push(L, "size", sizeVec); + ghoul::lua::push(L, "size", pair->size()); lua_settable(L, -3); // Set table for the current target lua_settable(L, -3); - } } return 1; } + int adjustCamera(lua_State* L) { - ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::adjustCamera"); + ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::adjustCamera"); const std::string id = ghoul::lua::value(L, 1); SkyBrowserModule* module = global::moduleEngine->module(); - if(module->isCameraInSolarSystem()) { + if (module->isCameraInSolarSystem()) { module->lookAtTarget(id); } - return 0; + return 0; } int setOpacityOfImageLayer(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setOpacityOfImageLayer"); - const std::string id = ghoul::lua::value(L, 1); - const int i = ghoul::lua::value(L, 1); - double opacity = ghoul::lua::value(L, 1); + auto [id, i, opacity] = ghoul::lua::values(L); SkyBrowserModule* module = global::moduleEngine->module(); - if (module->getPair(id)) { - module->getPair(id)->setImageOpacity(i, opacity); - + TargetBrowserPair* found = module->getPair(id); + if (found) { + found->setImageOpacity(i, opacity); } return 0; @@ -444,23 +446,23 @@ int createTargetBrowserPair(lua_State* L) { "FaceCamera = false," "}"; - openspace::global::scriptEngine->queueScript( + global::scriptEngine->queueScript( "openspace.addScreenSpaceRenderable(" + browser + ");", scripting::ScriptEngine::RemoteScripting::No ); - openspace::global::scriptEngine->queueScript( + global::scriptEngine->queueScript( "openspace.addScreenSpaceRenderable(" + target + ");", scripting::ScriptEngine::RemoteScripting::No ); - openspace::global::scriptEngine->queueScript( + global::scriptEngine->queueScript( "openspace.skybrowser.addPairToSkyBrowserModule('" + idTarget + "','" + idBrowser + "');", scripting::ScriptEngine::RemoteScripting::No ); - openspace::global::scriptEngine->queueScript( + global::scriptEngine->queueScript( "openspace.skybrowser.setSelectedBrowser('" + idBrowser + "');", scripting::ScriptEngine::RemoteScripting::No ); @@ -476,45 +478,42 @@ int removeTargetBrowserPair(lua_State* L) { if (found) { std::string browser = found->browserId(); std::string target = found->targetId(); - found = nullptr; module->removeTargetBrowserPair(id); // Remove from engine - openspace::global::scriptEngine->queueScript( + global::scriptEngine->queueScript( "openspace.removeScreenSpaceRenderable('" + browser + "');", scripting::ScriptEngine::RemoteScripting::Yes ); - openspace::global::scriptEngine->queueScript( + global::scriptEngine->queueScript( "openspace.removeScreenSpaceRenderable('" + target + "');", scripting::ScriptEngine::RemoteScripting::Yes ); } - return 0; } int translateScreenSpaceRenderable(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 5, "lua::translateScreenSpaceRenderable"); - const std::string id = ghoul::lua::value(L, 1); - float startX = ghoul::lua::value(L, 1); - float startY = ghoul::lua::value(L, 1); - float transX = ghoul::lua::value(L, 1); - float transY = ghoul::lua::value(L, 1); + auto [id, startX, startY, transX, transY] = + ghoul::lua::values(L); ScreenSpaceRenderable* renderable = global::renderEngine->screenSpaceRenderable(id); - renderable->translate(glm::vec2(transX, transY), glm::vec2(startX, startY)); + + if (renderable) { + renderable->translate(glm::vec2(transX, transY), glm::vec2(startX, startY)); + } return 0; } int removeSelectedImageInBrowser(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::removeSelectedImageInBrowser"); - const std::string id = ghoul::lua::value(L, 1); - // Image index - const int i = ghoul::lua::value(L, 1); + auto [id, i] = ghoul::lua::values(L); + // Get browser SkyBrowserModule* module = global::moduleEngine->module(); const ImageData& image = module->getWwtDataHandler()->getImage(i); @@ -529,10 +528,7 @@ int removeSelectedImageInBrowser(lua_State* L) { int setEquatorialAim(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setEquatorialAim"); - // Browser id - const std::string id = ghoul::lua::value(L, 1); - double ra = ghoul::lua::value(L, 1); - double dec = ghoul::lua::value(L, 1); + auto [id, ra, dec] = ghoul::lua::values(L); // Get module SkyBrowserModule* module = global::moduleEngine->module(); @@ -547,9 +543,7 @@ int setEquatorialAim(lua_State* L) { int setVerticalFov(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::setVerticalFov"); - // Browser id - const std::string id = ghoul::lua::value(L, 1); - float vfov = ghoul::lua::value(L, 1); + auto [id, vfov] = ghoul::lua::values(L); // Get module SkyBrowserModule* module = global::moduleEngine->module(); @@ -564,11 +558,8 @@ int setVerticalFov(lua_State* L) { int setBorderColor(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::setBorderColor"); - // Browser id - const std::string id = ghoul::lua::value(L, 1); - int r = ghoul::lua::value(L, 1); - int g = ghoul::lua::value(L, 1); - int b = ghoul::lua::value(L, 1); + auto [id, r, g, b] = ghoul::lua::values(L); + glm::ivec3 color{ r, g, b }; // Get module SkyBrowserModule* module = global::moduleEngine->module(); @@ -583,10 +574,7 @@ int setBorderColor(lua_State* L) { int setScreenSpaceSize(lua_State* L) { ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setScreenSpaceSize"); - // Browser id - const std::string id = ghoul::lua::value(L, 1); - float sizeX = ghoul::lua::value(L, 1); - float sizeY = ghoul::lua::value(L, 1); + auto [id, sizeX, sizeY] = ghoul::lua::values(L); // Get module SkyBrowserModule* module = global::moduleEngine->module(); @@ -597,6 +585,5 @@ int setScreenSpaceSize(lua_State* L) { } return 0; } - -} +} // namespace openspace::skybrowser::luafunctions diff --git a/modules/skybrowser/src/browser.cpp b/modules/skybrowser/src/browser.cpp index 88c51f7c0f..e35c31ab0d 100644 --- a/modules/skybrowser/src/browser.cpp +++ b/modules/skybrowser/src/browser.cpp @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2021 * + * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -32,7 +32,6 @@ #include #include #include -#include namespace { constexpr const char* _loggerCat = "Browser"; @@ -42,6 +41,7 @@ namespace { "Browser Dimensions", "Set the dimensions of the web browser window." }; + const openspace::properties::Property::PropertyInfo UrlInfo = { "Url", "URL", @@ -54,158 +54,166 @@ namespace { "Reload the web browser" }; + struct [[codegen::Dictionary(Browser)]] Parameters { + // [[codegen::verbatim(DimensionsInfo.description)]] + std::optional dimensions; + + // [[codegen::verbatim(UrlInfo.description)]] + std::optional url; + + // [[codegen::verbatim(ReloadInfo.description)]] + std::optional reload; + }; + +#include "browser_codegen.cpp" + } // namespace namespace openspace { - void Browser::RenderHandler::draw() {} +void Browser::RenderHandler::draw() {} - void Browser::RenderHandler::render() {} +void Browser::RenderHandler::render() {} - void Browser::RenderHandler::setTexture(GLuint t) { - _texture = t; +void Browser::RenderHandler::setTexture(GLuint t) { + _texture = t; +} + +Browser::Browser(const ghoul::Dictionary& dictionary) + : _url(UrlInfo) + , _browserPixeldimensions(DimensionsInfo, glm::vec2(500.f), glm::vec2(10.f), glm::vec2(3000.f)) + , _reload(ReloadInfo) +{ + if (dictionary.hasValue(UrlInfo.identifier)) { + _url = dictionary.value(UrlInfo.identifier); } + // Handle target dimension property + const Parameters p = codegen::bake(dictionary); + _url = p.url.value_or(_url); + _browserPixeldimensions = p.dimensions.value_or(_browserPixeldimensions); + glm::vec2 windowDimensions = global::windowDelegate->currentSubwindowSize(); + _browserPixeldimensions = windowDimensions; - Browser::Browser(const ghoul::Dictionary& dictionary) - : _url(UrlInfo) - , _browserPixeldimensions(DimensionsInfo, glm::vec2(500.f), glm::vec2(10.f), glm::vec2(3000.f)) - , _reload(ReloadInfo) - { - if (dictionary.hasValue(UrlInfo.identifier)) { - _url = dictionary.value(UrlInfo.identifier); - } + _url.onChange([this]() { _isUrlDirty = true; }); + _browserPixeldimensions.onChange([this]() { _isDimensionsDirty = true; }); + _reload.onChange([this]() { _shouldReload = true; }); - glm::vec2 windowDimensions = global::windowDelegate->currentSubwindowSize(); - _browserPixeldimensions = windowDimensions; + // Create browser and render handler + _renderHandler = new RenderHandler(); + _keyboardHandler = new WebKeyboardHandler(); + _browserInstance = std::make_unique( + _renderHandler, + _keyboardHandler + ); - _url.onChange([this]() { _isUrlDirty = true; }); - _browserPixeldimensions.onChange([this]() { _isDimensionsDirty = true; }); - _reload.onChange([this]() { _shouldReload = true; }); + WebBrowserModule* webBrowser = global::moduleEngine->module(); + if (webBrowser) { + webBrowser->addBrowser(_browserInstance.get()); + } +} - // Create browser and render handler - _renderHandler = new RenderHandler(); - _keyboardHandler = new WebKeyboardHandler(); - _browserInstance = std::make_unique( - _renderHandler, - _keyboardHandler - ); +Browser::~Browser() {} - WebBrowserModule* webBrowser = global::moduleEngine->module(); - if (webBrowser) { - webBrowser->addBrowser(_browserInstance.get()); - } - } - - Browser::~Browser() { - - } - - bool Browser::initializeGL() { - _texture = std::make_unique( - glm::uvec3(glm::ivec2(_browserPixeldimensions.value()), 1), - GL_TEXTURE_2D - ); +bool Browser::initializeGL() { + _texture = std::make_unique( + glm::uvec3(glm::ivec2(_browserPixeldimensions.value()), 1), + GL_TEXTURE_2D + ); - _renderHandler->setTexture(*_texture); + _renderHandler->setTexture(*_texture); - _browserInstance->initialize(); + _browserInstance->initialize(); + _browserInstance->loadUrl(_url); + return isReady(); +} + +bool Browser::deinitializeGL() { + _renderHandler->setTexture(0); + + _texture = nullptr; + + LDEBUG(fmt::format("Deinitializing browser: {}", _url.value())); + + _browserInstance->close(true); + + WebBrowserModule* webBrowser = global::moduleEngine->module(); + if (webBrowser) { + webBrowser->removeBrowser(_browserInstance.get()); + _browserInstance.reset(); + } + else { + LWARNING("Could not find WebBrowserModule"); + } + + return true; +} + +void Browser::render() { + if (!_renderHandler->isTextureReady()) { + return; + } + _renderHandler->updateTexture(); +} + +void Browser::update() { + if (_isUrlDirty) { _browserInstance->loadUrl(_url); - return isReady(); + _isUrlDirty = false; } - - - bool Browser::deinitializeGL() { - _renderHandler->setTexture(0); - - _texture = nullptr; - - std::string urlString; - _url.getStringValue(urlString); - LDEBUG(fmt::format("Deinitializing browser: {}", urlString)); - - _browserInstance->close(true); - - WebBrowserModule* webBrowser = global::moduleEngine->module(); - if (webBrowser) { - webBrowser->removeBrowser(_browserInstance.get()); - _browserInstance.reset(); - } - else { - LWARNING("Could not find WebBrowserModule"); - } - - return true; - } - - void Browser::render() { - if (!_renderHandler->isTextureReady()) { - return; - } - _renderHandler->updateTexture(); - - } - - void Browser::update() { - - if (_isUrlDirty) { - _browserInstance->loadUrl(_url); - _isUrlDirty = false; - } - if (_isDimensionsDirty) { - if (_browserPixeldimensions.value().x > 0 && - _browserPixeldimensions.value().y > 0) { - _browserInstance->reshape(_browserPixeldimensions.value()); - _isDimensionsDirty = false; - } - } - - if (_shouldReload) { - _browserInstance->reloadBrowser(); - _shouldReload = false; - } - } - - bool Browser::isReady() const { - return _texture.get(); - } - - glm::vec2 Browser::browserPixelDimensions() const { - return _browserPixeldimensions.value(); - } - - // Updates the browser size to match the size of the texture - void Browser::updateBrowserSize() { - _browserPixeldimensions = _texture->dimensions(); - } - - float Browser::browserRatio() const - { - return static_cast(_texture->dimensions().x) / - static_cast(_texture->dimensions().y); - } - - void Browser::setCallbackDimensions( - const std::function& function) - { - _browserPixeldimensions.onChange([&]() { - function(_browserPixeldimensions.value()); - }); - } - - void Browser::executeJavascript(const std::string& script) const { - - // Make sure that the browser has a main frame - const bool browserExists = _browserInstance && _browserInstance->getBrowser(); - const bool frameIsLoaded = browserExists && - _browserInstance->getBrowser()->GetMainFrame(); - - if (frameIsLoaded) { - _browserInstance->getBrowser()->GetMainFrame()->ExecuteJavaScript( - script, - _browserInstance->getBrowser()->GetMainFrame()->GetURL(), - 0 - ); + if (_isDimensionsDirty) { + if (_browserPixeldimensions.value().x > 0 && + _browserPixeldimensions.value().y > 0) + { + _browserInstance->reshape(_browserPixeldimensions.value()); + _isDimensionsDirty = false; } } + + if (_shouldReload) { + _browserInstance->reloadBrowser(); + _shouldReload = false; + } +} + +bool Browser::isReady() const { + return _texture.get(); +} + +glm::vec2 Browser::browserPixelDimensions() const { + return _browserPixeldimensions.value(); +} + +// Updates the browser size to match the size of the texture +void Browser::updateBrowserSize() { + _browserPixeldimensions = _texture->dimensions(); +} + +float Browser::browserRatio() const { + return static_cast(_texture->dimensions().x) / + static_cast(_texture->dimensions().y); +} + +void Browser::setCallbackDimensions( + const std::function& function) +{ + _browserPixeldimensions.onChange([&]() { + function(_browserPixeldimensions.value()); + }); +} + +void Browser::executeJavascript(const std::string& script) const { + // Make sure that the browser has a main frame + const bool browserExists = _browserInstance && _browserInstance->getBrowser(); + const bool frameIsLoaded = browserExists && + _browserInstance->getBrowser()->GetMainFrame(); + + if (frameIsLoaded) { + _browserInstance->getBrowser()->GetMainFrame()->ExecuteJavaScript( + script, + _browserInstance->getBrowser()->GetMainFrame()->GetURL(), + 0 + ); + } +} } // namespace openspace diff --git a/modules/skybrowser/src/screenspaceskybrowser.cpp b/modules/skybrowser/src/screenspaceskybrowser.cpp index 5b7d52a441..fb9b142015 100644 --- a/modules/skybrowser/src/screenspaceskybrowser.cpp +++ b/modules/skybrowser/src/screenspaceskybrowser.cpp @@ -1,3 +1,26 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #include #include @@ -7,14 +30,12 @@ #include #include #include -#include // formatJson +#include #include #include -#include // For hsv color -#include // For random color +#include +#include -#include -#pragma optimize("", off) namespace { constexpr const char* _loggerCat = "ScreenSpaceSkyBrowser"; @@ -34,7 +55,6 @@ namespace { }; struct [[codegen::Dictionary(ScreenSpaceSkyBrowser)]] Parameters { - // [[codegen::verbatim(AnimationSpeedInfo.description)]] std::optional animationSpeed; @@ -42,7 +62,7 @@ namespace { std::optional textureQuality; }; -#include "ScreenSpaceSkyBrowser_codegen.cpp" +#include "screenspaceskybrowser_codegen.cpp" } // namespace glm::ivec3 randomBorderColor(glm::ivec3 highlight) { @@ -67,209 +87,190 @@ glm::ivec3 randomBorderColor(glm::ivec3 highlight) { namespace openspace { - ScreenSpaceSkyBrowser::ScreenSpaceSkyBrowser(const ghoul::Dictionary& dictionary) - : ScreenSpaceRenderable(dictionary) - , WwtCommunicator(dictionary) - , _animationSpeed(AnimationSpeedInfo, 5.0, 0.1, 10.0) - , _textureQuality(TextureQualityInfo, 1.f, 0.25f, 1.f) - { - // Set a unique identifier - std::string identifier; - if (dictionary.hasValue(KeyIdentifier)) { - identifier = dictionary.value(KeyIdentifier); - } - else { - identifier = "ScreenSpaceSkyBrowser"; - } - identifier = makeUniqueIdentifier(identifier); - setIdentifier(identifier); +ScreenSpaceSkyBrowser::ScreenSpaceSkyBrowser(const ghoul::Dictionary& dictionary) + : ScreenSpaceRenderable(dictionary) + , WwtCommunicator(dictionary) + , _animationSpeed(AnimationSpeedInfo, 5.0, 0.1, 10.0) + , _textureQuality(TextureQualityInfo, 1.f, 0.25f, 1.f) +{ + _identifier = makeUniqueIdentifier(_identifier); - // Handle target dimension property - const Parameters p = codegen::bake(dictionary); - _textureQuality = p.textureQuality.value_or(_textureQuality); - _animationSpeed = p.animationSpeed.value_or(_animationSpeed); + // Handle target dimension property + const Parameters p = codegen::bake(dictionary); + _textureQuality = p.textureQuality.value_or(_textureQuality); + _animationSpeed = p.animationSpeed.value_or(_animationSpeed); - addProperty(_url); - addProperty(_browserPixeldimensions); - addProperty(_reload); - addProperty(_textureQuality); + addProperty(_url); + addProperty(_browserPixeldimensions); + addProperty(_reload); + addProperty(_textureQuality); - _textureQuality.onChange([this]() { - _textureDimensionsIsDirty = true; - }); + _textureQuality.onChange([this]() { + _textureDimensionsIsDirty = true; + }); - // Ensure that the browser is placed at the z-coordinate of the screen space plane - glm::vec2 screenPosition = _cartesianPosition.value(); - _cartesianPosition.setValue(glm::vec3(screenPosition, skybrowser::ScreenSpaceZ)); + // Ensure that the browser is placed at the z-coordinate of the screen space plane + glm::vec2 screenPosition = _cartesianPosition.value(); + _cartesianPosition = glm::vec3(screenPosition, skybrowser::ScreenSpaceZ); - if (global::windowDelegate->isMaster()) { - SkyBrowserModule* module = global::moduleEngine->module(); - _borderColor = randomBorderColor(module->highlight()); - - } - } - - ScreenSpaceSkyBrowser::~ScreenSpaceSkyBrowser() { + if (global::windowDelegate->isMaster()) { SkyBrowserModule* module = global::moduleEngine->module(); + _borderColor = randomBorderColor(module->highlight()); + } +} - if (module && module->getPair(identifier())) { - module->removeTargetBrowserPair(identifier()); - } - } +ScreenSpaceSkyBrowser::~ScreenSpaceSkyBrowser() { + SkyBrowserModule* module = global::moduleEngine->module(); - bool ScreenSpaceSkyBrowser::initializeGL() { - - WwtCommunicator::initializeGL(); - ScreenSpaceRenderable::initializeGL(); - updateTextureResolution(); - return true; - } - - glm::dvec2 ScreenSpaceSkyBrowser::fineTuneVector(glm::dvec2 drag) { - // Fine tuning of target - glm::dvec2 wwtFov = fieldsOfView(); - glm::dvec2 openSpaceFOV = skybrowser::fovWindow(); - - glm::dvec2 browserDim = screenSpaceDimensions(); - glm::dvec2 angleResult = wwtFov * (drag / browserDim); - glm::dvec2 resultRelativeOs = angleResult / openSpaceFOV; - - // Convert to screen space coordinate system - glm::dvec2 convertToScreenSpace{ (2 * skybrowser::windowRatio()), 2.f }; - glm::dvec2 result = - convertToScreenSpace * resultRelativeOs; - return result; - } - - void ScreenSpaceSkyBrowser::setIdInBrowser() { - WwtCommunicator::setIdInBrowser(identifier()); - } - - void ScreenSpaceSkyBrowser::updateTextureResolution() - { - // Scale texture depending on the height of the window - // Set texture size to the actual pixel size it covers - glm::vec2 pixels = glm::vec2(global::windowDelegate->currentSubwindowSize()); - - // If the scale is 1, it covers half the window. Hence multiplication with 2 - float newResY = pixels.y * 2.f * _scale; - float ratio = _size.x / _size.y; - float newResX = newResY * ratio; - glm::vec2 newSize = glm::vec2(newResX , newResY) * _textureQuality.value(); - - _browserPixeldimensions = glm::ivec2(newSize); - _texture->setDimensions(glm::ivec3(newSize, 1)); - _objectSize = glm::ivec3(_texture->dimensions()); - } - - bool ScreenSpaceSkyBrowser::deinitializeGL() { - ScreenSpaceRenderable::deinitializeGL(); - WwtCommunicator::deinitializeGL(); - - return true; - } - - bool ScreenSpaceSkyBrowser::isAnimated() - { - return _isFovAnimated; - } - - void ScreenSpaceSkyBrowser::startFovAnimation(float fov) - { - _isFovAnimated = true; - _endVfov = fov; - } - - void ScreenSpaceSkyBrowser::incrementallyAnimateToFov(float deltaTime) - { - // If distance too large, keep animating. Else, stop animation - float diff = _endVfov - verticalFov(); - bool shouldAnimate = abs(diff) > FovThreshold; - - if (shouldAnimate) { - float delta = _animationSpeed * (diff * deltaTime); - _verticalFov = std::clamp(_verticalFov + delta, 0.0001f, 70.0f); - } - else { - _isFovAnimated = false; - } - } - - void ScreenSpaceSkyBrowser::render() { - WwtCommunicator::render(); - - draw( - globalRotationMatrix() * - translationMatrix() * - localRotationMatrix() * - scaleMatrix() - ); - } - - void ScreenSpaceSkyBrowser::update() { - // Texture of window is 1x1 when minimized - bool isWindow = global::windowDelegate->currentSubwindowSize() != glm::ivec2(1); - bool isWindowResized = global::windowDelegate->windowHasResized(); - if ((isWindowResized && isWindow) || _textureDimensionsIsDirty) { - updateTextureResolution(); - _textureDimensionsIsDirty = false; - } - if (_sizeIsDirty) { - updateScreenSpaceSize(); - _sizeIsDirty = false; - } - - WwtCommunicator::update(); - ScreenSpaceRenderable::update(); - } - - void ScreenSpaceSkyBrowser::setVerticalFovWithScroll(float scroll) { - // Make scroll more sensitive the smaller the FOV - float x = _verticalFov; - float zoomFactor = atan(x / 50.0) + exp(x / 40) - 0.999999; - float zoom = scroll > 0.0 ? -zoomFactor : zoomFactor; - _verticalFov = std::clamp(_verticalFov + zoom, 0.001f, 70.0f); - } - - void ScreenSpaceSkyBrowser::bindTexture() - { - _texture->bind(); - } - - glm::mat4 ScreenSpaceSkyBrowser::scaleMatrix() { - // To ensure the plane has the right ratio - // The _scale tells us how much of the windows height the - // browser covers: e.g. a browser that covers 0.25 of the - // height of the window will have scale = 0.25 - - glm::mat4 scale = glm::scale( - glm::mat4(1.f), - glm::vec3(browserRatio() * _scale, _scale, 1.f) - ); - return scale; - } - - void ScreenSpaceSkyBrowser::setOpacity(float opacity) - { - _opacity = opacity; - } - - void ScreenSpaceSkyBrowser::setScreenSpaceSize(const glm::vec2& newSize) - { - _size = newSize; - _sizeIsDirty = true; - } - - void ScreenSpaceSkyBrowser::updateScreenSpaceSize() - { - _scale = abs(_size.y) * 0.5f; - updateTextureResolution(); - } - - float ScreenSpaceSkyBrowser::opacity() const { - return _opacity; - } - glm::vec2 ScreenSpaceSkyBrowser::size() const - { - return _size; + if (module && module->getPair(identifier())) { + module->removeTargetBrowserPair(identifier()); } } + +bool ScreenSpaceSkyBrowser::initializeGL() { + WwtCommunicator::initializeGL(); + ScreenSpaceRenderable::initializeGL(); + updateTextureResolution(); + return true; +} + +glm::dvec2 ScreenSpaceSkyBrowser::fineTuneVector(glm::dvec2 drag) { + // Fine tuning of target + glm::dvec2 wwtFov = fieldsOfView(); + glm::dvec2 openSpaceFOV = skybrowser::fovWindow(); + + glm::dvec2 browserDim = screenSpaceDimensions(); + glm::dvec2 angleResult = wwtFov * (drag / browserDim); + glm::dvec2 resultRelativeOs = angleResult / openSpaceFOV; + + // Convert to screen space coordinate system + glm::dvec2 convertToScreenSpace{ (2 * skybrowser::windowRatio()), 2.f }; + glm::dvec2 result = - convertToScreenSpace * resultRelativeOs; + return result; +} + +void ScreenSpaceSkyBrowser::setIdInBrowser() { + WwtCommunicator::setIdInBrowser(identifier()); +} + +void ScreenSpaceSkyBrowser::updateTextureResolution() { + // Scale texture depending on the height of the window + // Set texture size to the actual pixel size it covers + glm::vec2 pixels = glm::vec2(global::windowDelegate->currentSubwindowSize()); + + // If the scale is 1, it covers half the window. Hence multiplication with 2 + float newResY = pixels.y * 2.f * _scale; + float ratio = _size.x / _size.y; + float newResX = newResY * ratio; + glm::vec2 newSize = glm::vec2(newResX , newResY) * _textureQuality.value(); + + _browserPixeldimensions = glm::ivec2(newSize); + _texture->setDimensions(glm::ivec3(newSize, 1)); + _objectSize = glm::ivec3(_texture->dimensions()); +} + +bool ScreenSpaceSkyBrowser::deinitializeGL() { + ScreenSpaceRenderable::deinitializeGL(); + WwtCommunicator::deinitializeGL(); + + return true; +} + +bool ScreenSpaceSkyBrowser::isAnimated() const{ + return _isFovAnimated; +} + +void ScreenSpaceSkyBrowser::startFovAnimation(float fov) { + _isFovAnimated = true; + _endVfov = fov; +} + +void ScreenSpaceSkyBrowser::incrementallyAnimateToFov(float deltaTime) { + // If distance too large, keep animating. Else, stop animation + float diff = _endVfov - verticalFov(); + bool shouldAnimate = abs(diff) > FovThreshold; + + if (shouldAnimate) { + float delta = _animationSpeed * (diff * deltaTime); + _verticalFov = std::clamp(_verticalFov + delta, 0.0001f, 70.0f); + } + else { + _isFovAnimated = false; + } +} + +void ScreenSpaceSkyBrowser::render() { + WwtCommunicator::render(); + + draw( + globalRotationMatrix() * + translationMatrix() * + localRotationMatrix() * + scaleMatrix() + ); +} + +void ScreenSpaceSkyBrowser::update() { + // Texture of window is 1x1 when minimized + bool isWindow = global::windowDelegate->currentSubwindowSize() != glm::ivec2(1); + bool isWindowResized = global::windowDelegate->windowHasResized(); + if ((isWindowResized && isWindow) || _textureDimensionsIsDirty) { + updateTextureResolution(); + _textureDimensionsIsDirty = false; + } + if (_sizeIsDirty) { + updateScreenSpaceSize(); + _sizeIsDirty = false; + } + + WwtCommunicator::update(); + ScreenSpaceRenderable::update(); +} + +void ScreenSpaceSkyBrowser::setVerticalFovWithScroll(float scroll) { + // Make scroll more sensitive the smaller the FOV + float x = _verticalFov; + float zoomFactor = atan(x / 50.f) + exp(x / 40.f) - 0.999999f; + float zoom = scroll > 0.f ? -zoomFactor : zoomFactor; + _verticalFov = std::clamp(_verticalFov + zoom, 0.001f, 70.0f); +} + +void ScreenSpaceSkyBrowser::bindTexture() { + _texture->bind(); +} + +glm::mat4 ScreenSpaceSkyBrowser::scaleMatrix() { + // To ensure the plane has the right ratio + // The _scale tells us how much of the windows height the + // browser covers: e.g. a browser that covers 0.25 of the + // height of the window will have scale = 0.25 + + glm::mat4 scale = glm::scale( + glm::mat4(1.f), + glm::vec3(browserRatio() * _scale, _scale, 1.f) + ); + return scale; +} + +void ScreenSpaceSkyBrowser::setOpacity(float opacity) { + _opacity = opacity; +} + +void ScreenSpaceSkyBrowser::setScreenSpaceSize(const glm::vec2& newSize) { + _size = newSize; + _sizeIsDirty = true; +} + +void ScreenSpaceSkyBrowser::updateScreenSpaceSize() { + _scale = abs(_size.y) * 0.5f; + updateTextureResolution(); +} + +float ScreenSpaceSkyBrowser::opacity() const { + return _opacity; +} + +glm::vec2 ScreenSpaceSkyBrowser::size() const { + return _size; +} +} // namespace openspace diff --git a/modules/skybrowser/src/screenspaceskytarget.cpp b/modules/skybrowser/src/screenspaceskytarget.cpp index 523449fe21..a07ea8bd6a 100644 --- a/modules/skybrowser/src/screenspaceskytarget.cpp +++ b/modules/skybrowser/src/screenspaceskytarget.cpp @@ -1,3 +1,26 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #include #include @@ -61,7 +84,6 @@ namespace { }; struct [[codegen::Dictionary(ScreenSpaceSkyTarget)]] Parameters { - // [[codegen::verbatim(CrosshairThresholdInfo.description)]] std::optional crosshairThreshold; @@ -76,7 +98,6 @@ namespace { // [[codegen::verbatim(LineWidthInfo.description)]] std::optional lineWidth; - }; #include "screenspaceskytarget_codegen.cpp" @@ -118,10 +139,11 @@ namespace openspace { setIdentifier(identifier); // Set the position to screen space z - glm::dvec3 startPos{ _cartesianPosition.value().x, _cartesianPosition.value().y, - skybrowser::ScreenSpaceZ }; - - _cartesianPosition.setValue(startPos); + _cartesianPosition = glm::dvec3( + _cartesianPosition.value().x, + _cartesianPosition.value().y, + skybrowser::ScreenSpaceZ + ); } @@ -134,16 +156,13 @@ namespace openspace { } // Pure virtual in the screen space renderable class and hence must be defined - void ScreenSpaceSkyTarget::bindTexture() { - - } + void ScreenSpaceSkyTarget::bindTexture() {} bool ScreenSpaceSkyTarget::isReady() const { return _shader != nullptr; } bool ScreenSpaceSkyTarget::initializeGL() { - glGenVertexArrays(1, &_vertexArray); glGenBuffers(1, &_vertexBuffer); createShaders(); @@ -151,8 +170,7 @@ namespace openspace { return isReady(); } - bool ScreenSpaceSkyTarget::deinitializeGL() - { + bool ScreenSpaceSkyTarget::deinitializeGL() { return ScreenSpaceRenderable::deinitializeGL(); } @@ -173,7 +191,6 @@ namespace openspace { void ScreenSpaceSkyTarget::createShaders() { - _shader = global::renderEngine->buildRenderProgram( "ScreenSpaceProgram", absPath("${MODULE_SKYBROWSER}/shaders/target_vs.glsl"), @@ -185,7 +202,7 @@ namespace openspace { } void ScreenSpaceSkyTarget::setColor(glm::ivec3 color) { - _borderColor = color; + _borderColor = std::move(color); } glm::ivec3 ScreenSpaceSkyTarget::borderColor() const { @@ -193,7 +210,6 @@ namespace openspace { } void ScreenSpaceSkyTarget::render() { - bool showCrosshair = _verticalFov < _showCrosshairThreshold; bool showRectangle = _verticalFov > _showRectangleThreshold; @@ -224,8 +240,7 @@ namespace openspace { _shader->deactivate(); } - void ScreenSpaceSkyTarget::update() - { + void ScreenSpaceSkyTarget::update() { if (_isLocked) { glm::dvec3 localCamera = skybrowser::equatorialToLocalCamera( _lockedCoordinates @@ -252,11 +267,9 @@ namespace openspace { } glm::dvec3 ScreenSpaceSkyTarget::directionGalactic() const { - glm::vec3 localCamera = _cartesianPosition.value(); if (_useRadiusAzimuthElevation) { - localCamera = raeToCartesian(_raePosition.value()); } @@ -281,8 +294,7 @@ namespace openspace { _scale = std::max(heightRatio, smallestHeightRatio); } - void ScreenSpaceSkyTarget::setFovFromScale() - { + void ScreenSpaceSkyTarget::setFovFromScale() { glm::dvec2 fovs = skybrowser::fovWindow(); _verticalFov = _scale * fovs.y; } @@ -291,14 +303,12 @@ namespace openspace { return _isLocked; } - bool ScreenSpaceSkyTarget::isAnimated() - { + bool ScreenSpaceSkyTarget::isAnimated() { return _isAnimated; } void ScreenSpaceSkyTarget::startAnimation(glm::dvec3 equatorialCoordsEnd, - bool shouldLockAfter) - { + bool shouldLockAfter) { _animationStart = glm::normalize( skybrowser::sphericalToCartesian(equatorialAim()) ); @@ -308,8 +318,7 @@ namespace openspace { _isLocked = false; } - void ScreenSpaceSkyTarget::incrementallyAnimateToCoordinate(float deltaTime) - { + void ScreenSpaceSkyTarget::incrementallyAnimateToCoordinate(float deltaTime) { // At fps that are too low, the animation stops working. Just place target instead bool fpsTooLow = deltaTime > DeltaTimeThreshold; // Find smallest angle between the two vectors @@ -362,52 +371,48 @@ namespace openspace { } glm::dvec2 ScreenSpaceSkyTarget::equatorialAim() const { - + glm::dvec3 cartesian; // Get the local camera coordinates of the target if (_useRadiusAzimuthElevation) { - glm::vec3 cartesian = raeToCartesian(_raePosition.value()); + cartesian = raeToCartesian(_raePosition.value()); glm::dvec3 equatorial = skybrowser::localCameraToEquatorial(cartesian); return skybrowser::cartesianToSpherical(equatorial); } else { - glm::dvec3 cartesian = skybrowser::localCameraToEquatorial(_cartesianPosition.value()); + cartesian = skybrowser::localCameraToEquatorial(_cartesianPosition.value()); return skybrowser::cartesianToSpherical(cartesian); } } - - void ScreenSpaceSkyTarget::highlight(glm::ivec3 addition) - { + void ScreenSpaceSkyTarget::highlight(glm::ivec3 addition) { _borderColor += addition; } - void ScreenSpaceSkyTarget::removeHighlight(glm::ivec3 removal) - { + void ScreenSpaceSkyTarget::removeHighlight(glm::ivec3 removal) { _borderColor -= removal; } float ScreenSpaceSkyTarget::opacity() const { - return _opacity.value(); + return _opacity; } - glm::dvec2 ScreenSpaceSkyTarget::lockedCoordinates() const - { + glm::dvec2 ScreenSpaceSkyTarget::lockedCoordinates() const { return skybrowser::cartesianToSpherical(_lockedCoordinates); } void ScreenSpaceSkyTarget::setOpacity(float opacity) { _opacity = opacity; } - void ScreenSpaceSkyTarget::setLock(bool isLocked) - { + + void ScreenSpaceSkyTarget::setLock(bool isLocked) { _isLocked = isLocked; if (_isLocked) { _lockedCoordinates = skybrowser::sphericalToCartesian(equatorialAim()); } } - void ScreenSpaceSkyTarget::setEquatorialAim(const glm::dvec2& aim) - { + + void ScreenSpaceSkyTarget::setEquatorialAim(const glm::dvec2& aim) { _isAnimated = false; _isLocked = false; diff --git a/modules/skybrowser/src/targetbrowserpair.cpp b/modules/skybrowser/src/targetbrowserpair.cpp index 613b39c7e3..965091c62b 100644 --- a/modules/skybrowser/src/targetbrowserpair.cpp +++ b/modules/skybrowser/src/targetbrowserpair.cpp @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2021 * + * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -37,15 +37,15 @@ namespace openspace { - TargetBrowserPair::TargetBrowserPair(ScreenSpaceSkyBrowser* browser, ScreenSpaceSkyTarget* target) + TargetBrowserPair::TargetBrowserPair(ScreenSpaceSkyBrowser* browser, + ScreenSpaceSkyTarget* target) : _target(target), _browser(browser) { ghoul_assert(browser != nullptr, "Sky browser is null pointer!"); ghoul_assert(target != nullptr, "Sky target is null pointer!"); } - TargetBrowserPair& TargetBrowserPair::operator=(TargetBrowserPair other) - { + TargetBrowserPair& TargetBrowserPair::operator=(TargetBrowserPair other) { std::swap(_target, other._target); std::swap(_browser, other._browser); return *this; @@ -64,34 +64,29 @@ namespace openspace { _browser->setImageOrder(i, order); } - void TargetBrowserPair::removeHighlight(glm::ivec3 color) - { + void TargetBrowserPair::removeHighlight(glm::ivec3 color) { _target->removeHighlight(color); _browser->removeHighlight(color); } - void TargetBrowserPair::highlight(glm::ivec3 color) - { + void TargetBrowserPair::highlight(glm::ivec3 color) { _browser->highlight(color); _target->highlight(color); } - bool TargetBrowserPair::isTargetFadeFinished(float goalState) const - { + bool TargetBrowserPair::isTargetFadeFinished(float goalState) const { // Is fading finished? float targetDiff = abs(_target->opacity() - goalState); return targetDiff < FadeThreshold; } - bool TargetBrowserPair::isBrowserFadeFinished(float goalState) const - { + bool TargetBrowserPair::isBrowserFadeFinished(float goalState) const { float browserDiff = abs(_browser->opacity() - goalState); return browserDiff < FadeThreshold; } - bool TargetBrowserPair::checkMouseIntersection(glm::vec2 mousePosition) - { + bool TargetBrowserPair::checkMouseIntersection(glm::vec2 mousePosition) { bool onBrowser = _browser->intersection(mousePosition); bool onTarget = _target->intersection(mousePosition); if (onBrowser) { @@ -109,50 +104,46 @@ namespace openspace { return onBrowser || onTarget; } - glm::vec2 TargetBrowserPair::selectedScreenSpacePosition() - { + glm::vec2 TargetBrowserPair::selectedScreenSpacePosition() { return _selected->screenSpacePosition(); } - bool TargetBrowserPair::isBrowserSelected() - { + bool TargetBrowserPair::isBrowserSelected() { return _isSelectedBrowser; } - bool TargetBrowserPair::isTargetSelected() - { + bool TargetBrowserPair::isTargetSelected() { return _selected && !_isSelectedBrowser; } void TargetBrowserPair::fineTuneTarget(const glm::vec2& start, const glm::vec2& translation) { - glm::vec2 fineTune = -_browser->fineTuneVector(translation); + glm::vec2 fineTune = _browser->fineTuneVector(translation); openspace::global::scriptEngine->queueScript( "openspace.skybrowser.translateScreenSpaceRenderable(\"" + targetId() + "\"," + std::to_string(start.x) + "," + std::to_string(start.y) + "," - + std::to_string(translation.x) + "," + std::to_string(translation.y) + ")", + + std::to_string(fineTune.x) + "," + std::to_string(fineTune.y) + ")", scripting::ScriptEngine::RemoteScripting::Yes ); } void TargetBrowserPair::translateSelected(const glm::vec2& start, - const glm::vec2& translation) + const glm::vec2& trans) { if (this && _selected) { std::string id = _selected->identifier(); openspace::global::scriptEngine->queueScript( "openspace.skybrowser.translateScreenSpaceRenderable(\"" + id + "\"," + std::to_string(start.x) + "," + std::to_string(start.y) + "," - + std::to_string(translation.x) + "," + std::to_string(translation.y) + ")", + + std::to_string(trans.x) + "," + std::to_string(trans.y) + ")", scripting::ScriptEngine::RemoteScripting::Yes ); } } - void TargetBrowserPair::synchronizeAim() - { + void TargetBrowserPair::synchronizeAim() { if (!_target->isAnimated()) { glm::dvec2 aim; // To remove the lag effect when moving the camera while having a locked @@ -169,82 +160,67 @@ namespace openspace { } } - void TargetBrowserPair::setEnabled(bool enable) - { + void TargetBrowserPair::setEnabled(bool enable) { _browser->setEnabled(enable); _target->setEnabled(enable); } - bool TargetBrowserPair::isEnabled() const - { + bool TargetBrowserPair::isEnabled() const { return _target->isEnabled() && _browser->isEnabled(); } - bool TargetBrowserPair::isLocked() const - { + bool TargetBrowserPair::isLocked() const { return _target->isLocked(); } - void TargetBrowserPair::initialize() - { + void TargetBrowserPair::initialize() { _target->setColor(_browser->borderColor()); _target->setDimensions(_browser->browserPixelDimensions()); _target->setScaleFromVfov(_browser->verticalFov()); _browser->updateBorderColor(); } - glm::ivec3 TargetBrowserPair::borderColor() const - { + glm::ivec3 TargetBrowserPair::borderColor() const { return _browser->borderColor(); } - glm::dvec2 TargetBrowserPair::targetDirectionEquatorial() const - { + glm::dvec2 TargetBrowserPair::targetDirectionEquatorial() const { return _target->equatorialAim(); } - glm::dvec3 TargetBrowserPair::targetDirectionGalactic() const - { + glm::dvec3 TargetBrowserPair::targetDirectionGalactic() const { return _target->directionGalactic(); } - std::string TargetBrowserPair::browserGuiName() const - { + std::string TargetBrowserPair::browserGuiName() const { return _browser->guiName(); } - std::string TargetBrowserPair::browserId() const - { + std::string TargetBrowserPair::browserId() const { return _browser->identifier(); } - std::string TargetBrowserPair::targetId() const - { + std::string TargetBrowserPair::targetId() const { return _target->identifier(); } - std::string TargetBrowserPair::selectedId() - { + std::string TargetBrowserPair::selectedId() { return _selected->identifier(); } - glm::vec2 TargetBrowserPair::size() const - { + glm::vec2 TargetBrowserPair::size() const { return _browser->size(); } - float TargetBrowserPair::verticalFov() const - { + float TargetBrowserPair::verticalFov() const { return _browser->verticalFov(); } - const std::deque& TargetBrowserPair::getSelectedImages() const - { + const std::deque& TargetBrowserPair::getSelectedImages() const { return _browser->getSelectedImages(); } - void TargetBrowserPair::selectImage(const ImageData& image, int i) - { + void TargetBrowserPair::selectImage(const ImageData& image, int i) { // Load image into browser _browser->displayImage(image.imageUrl, i); @@ -257,28 +233,23 @@ namespace openspace { } } - void TargetBrowserPair::removeSelectedImage(int i) - { + void TargetBrowserPair::removeSelectedImage(int i) { _browser->removeSelectedImage(i); } - void TargetBrowserPair::loadImageCollection(const std::string& collection) - { + void TargetBrowserPair::loadImageCollection(const std::string& collection) { _browser->loadImageCollection(collection); } - void TargetBrowserPair::setImageOpacity(int i, float opacity) - { + void TargetBrowserPair::setImageOpacity(int i, float opacity) { _browser->setImageOpacity(i, opacity); } - void TargetBrowserPair::hideChromeInterface(bool shouldHide) - { + void TargetBrowserPair::hideChromeInterface(bool shouldHide) { _browser->hideChromeInterface(shouldHide); } - void TargetBrowserPair::sendIdToBrowser() - { + void TargetBrowserPair::sendIdToBrowser() { _browser->setIdInBrowser(); } @@ -286,46 +257,39 @@ namespace openspace { _browser->updateBrowserSize(); } - void TargetBrowserPair::setIsSyncedWithWwt(bool isSynced) - { + void TargetBrowserPair::setIsSyncedWithWwt(bool isSynced) { _browser->setIsSyncedWithWwt(isSynced); } - void TargetBrowserPair::setVerticalFov(float vfov) - { + void TargetBrowserPair::setVerticalFov(float vfov) { _verticalFov = vfov; _browser->setVerticalFov(vfov); _target->setScaleFromVfov(vfov); } - void TargetBrowserPair::setEquatorialAim(const glm::dvec2& aim) - { + void TargetBrowserPair::setEquatorialAim(const glm::dvec2& aim) { _equatorialAim = aim; _target->setEquatorialAim(aim); _browser->setEquatorialAim(aim); } - void TargetBrowserPair::setBorderColor(const glm::ivec3& color) - { + void TargetBrowserPair::setBorderColor(const glm::ivec3& color) { _borderColor = color; _target->setColor(color); _browser->setBorderColor(color); } - void TargetBrowserPair::setScreenSpaceSize(const glm::vec2& dimensions) - { + void TargetBrowserPair::setScreenSpaceSize(const glm::vec2& dimensions) { _dimensions = dimensions; _target->setDimensions(dimensions); _browser->setScreenSpaceSize(dimensions); } - void TargetBrowserPair::setVerticalFovWithScroll(float scroll) - { + void TargetBrowserPair::setVerticalFovWithScroll(float scroll) { _browser->setVerticalFovWithScroll(scroll); } - void TargetBrowserPair::setSelectedWithId(const std::string& id) - { + void TargetBrowserPair::setSelectedWithId(const std::string& id) { if (browserId() == id) { _isSelectedBrowser = true; _selected = _browser; @@ -340,8 +304,7 @@ namespace openspace { } } - void TargetBrowserPair::incrementallyAnimateToCoordinate(double deltaTime) - { + void TargetBrowserPair::incrementallyAnimateToCoordinate(double deltaTime) { // Animate the target before the field of view starts to animate if (_target->isAnimated()) { _target->incrementallyAnimateToCoordinate(static_cast(deltaTime)); @@ -358,8 +321,7 @@ namespace openspace { _browser->startFovAnimation(fovEnd); } - void TargetBrowserPair::centerTargetOnScreen() - { + void TargetBrowserPair::centerTargetOnScreen() { // Animate the target to the center of the screen unlock(); // Get camera direction in celestial spherical coordinates @@ -369,18 +331,15 @@ namespace openspace { startAnimation(viewDirection, currentFov, false); } - bool TargetBrowserPair::hasFinishedFading(float goalState) const - { + bool TargetBrowserPair::hasFinishedFading(float goalState) const { return isTargetFadeFinished(goalState) && isBrowserFadeFinished(goalState); } - bool TargetBrowserPair::isFacingCamera() const - { + bool TargetBrowserPair::isFacingCamera() const { return _browser->isFacingCamera() || _target->isFacingCamera(); } - bool TargetBrowserPair::isUsingRadiusAzimuthElevation() const - { + bool TargetBrowserPair::isUsingRadiusAzimuthElevation() const { return _browser->isUsingRaeCoords() || _target->isUsingRaeCoords(); } @@ -392,7 +351,8 @@ namespace openspace { return _browser; } - void TargetBrowserPair::incrementallyFade(float goalState, float fadeTime, float deltaTime) + void TargetBrowserPair::incrementallyFade(float goalState, float fadeTime, + float deltaTime) { float opacityDelta = static_cast(deltaTime / fadeTime); if (_target->opacity() > goalState) { @@ -417,9 +377,8 @@ namespace openspace { bool operator==(const TargetBrowserPair& lhs, const TargetBrowserPair& rhs) { return lhs._target == rhs._target && lhs._browser == rhs._browser; } + bool operator!=(const TargetBrowserPair& lhs, const TargetBrowserPair& rhs) { return !(lhs == rhs); } - - } // namespace openspace diff --git a/modules/skybrowser/src/utility.cpp b/modules/skybrowser/src/utility.cpp index 2003724fb0..c98260cdf1 100644 --- a/modules/skybrowser/src/utility.cpp +++ b/modules/skybrowser/src/utility.cpp @@ -1,3 +1,26 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #include #include @@ -5,191 +28,186 @@ #include #include #include -#include // For atan2 -#define _USE_MATH_DEFINES -#include // For M_PI - +#include namespace openspace::skybrowser { - // Converts from spherical coordinates in the unit of degrees to cartesian coordianates - glm::dvec3 sphericalToCartesian(const glm::dvec2& coords) { +// Converts from spherical coordinates in the unit of degrees to cartesian coordianates +glm::dvec3 sphericalToCartesian(const glm::dvec2& coords) { - glm::dvec2 coordsRadians = glm::radians(coords); + glm::dvec2 coordsRadians = glm::radians(coords); - glm::dvec3 cartesian = glm::dvec3( - cos(coordsRadians.x) * cos(coordsRadians.y), - sin(coordsRadians.x) * cos(coordsRadians.y), - sin(coordsRadians.y) - ); - - return cartesian; - } - - // Converts from cartesian coordianates to spherical in the unit of degrees - glm::dvec2 cartesianToSpherical(const glm::dvec3& coord) { - // Equatorial coordinates RA = right ascension, Dec = declination - double ra = atan2(coord.y, coord.x); - double dec = atan2(coord.z, glm::sqrt((coord.x * coord.x) + (coord.y * coord.y))); - - ra = ra > 0 ? ra : ra + (2 * M_PI); - - glm::dvec2 celestialCoords{ ra, dec }; - - return glm::degrees(celestialCoords); - } - - glm::dvec3 galacticToEquatorial(const glm::dvec3& coords) { - return glm::transpose(conversionMatrix) * glm::normalize(coords); - } - - glm::dvec3 equatorialToGalactic(const glm::dvec3& coords) { - // On the unit sphere - glm::dvec3 rGalactic = conversionMatrix * glm::normalize(coords); - return rGalactic * CelestialSphereRadius; - } - - glm::dvec3 localCameraToScreenSpace3d(const glm::dvec3& coords) { - - // Ensure that if the coord is behind the camera, - // the converted coordinate will be there too - double zCoord = coords.z > 0 ? -ScreenSpaceZ : ScreenSpaceZ; - - // Calculate screen space coords x and y - double tan_x = coords.x / coords.z; - double tan_y = coords.y / coords.z; - - glm::dvec3 screenSpace = glm::dvec3(zCoord * tan_x, zCoord * tan_y, zCoord); - - return screenSpace; - } - - glm::dvec3 localCameraToGalactic(const glm::dvec3& coords) { - glm::dmat4 rotation = glm::inverse( - global::navigationHandler->camera()->viewRotationMatrix()); - glm::dvec4 position = glm::dvec4(coords, 1.0); - - return glm::normalize(rotation * position) * skybrowser::CelestialSphereRadius; - } - - glm::dvec3 localCameraToEquatorial(const glm::dvec3& coords) { - // Calculate the galactic coordinate of the target direction - // projected onto the celestial sphere - glm::dvec3 camPos = global::navigationHandler->camera()->positionVec3(); - glm::dvec3 galactic = camPos + skybrowser::localCameraToGalactic(coords); - - return skybrowser::galacticToEquatorial(galactic); - } - - glm::dvec3 equatorialToLocalCamera(const glm::dvec3& coords) - { - // Transform equatorial J2000 to galactic coord with infinite radius - glm::dvec3 galactic = equatorialToGalactic(coords); - glm::dvec3 localCamera = galacticToLocalCamera(galactic); - return localCamera; - } - - glm::dvec3 galacticToLocalCamera(const glm::dvec3& coords) { - // Transform vector to camera's local coordinate system - glm::dvec3 camPos = global::navigationHandler->camera()->positionVec3(); - glm::dmat4 camMat = global::navigationHandler->camera()->viewRotationMatrix(); - glm::dvec3 viewDirectionWorld = glm::normalize(coords - camPos); - glm::dvec3 viewDirectionLocal = camMat * glm::dvec4(viewDirectionWorld, 1.0); - - return glm::normalize(viewDirectionLocal); - } - - double cameraRoll() { - openspace::Camera* camera = global::navigationHandler->camera(); - glm::dvec3 upWorld = camera->lookUpVectorWorldSpace(); - glm::dvec3 forwardWorld = camera->viewDirectionWorldSpace(); - - glm::dvec3 camUpJ2000 = skybrowser::galacticToEquatorial(upWorld); - glm::dvec3 camForwardJ2000 = skybrowser::galacticToEquatorial(forwardWorld); - - glm::dvec3 crossUpNorth = glm::cross(camUpJ2000, skybrowser::NorthPole); - double dotNorthUp = glm::dot(skybrowser::NorthPole, camUpJ2000); - double dotCrossUpNorthForward = glm::dot(crossUpNorth, camForwardJ2000); - - return glm::degrees(atan2(dotCrossUpNorthForward, dotNorthUp)); - } - - glm::dvec3 cameraDirectionEquatorial() { - // Get the view direction of the screen in cartesian J2000 coordinates - return galacticToEquatorial(cameraDirectionGalactic()); - } - - glm::dvec3 cameraDirectionGalactic() { - // Get the view direction of the screen in galactic coordinates - glm::dvec3 camPos = global::navigationHandler->camera()->positionVec3(); - glm::dvec3 view = global::navigationHandler->camera()->viewDirectionWorldSpace(); - glm::dvec3 galCoord = camPos + (skybrowser::CelestialSphereRadius * view); - - return galCoord; - } - - float windowRatio() { - glm::vec2 windowRatio = global::windowDelegate->currentWindowSize(); - return windowRatio.x / windowRatio.y; - } - - bool isCoordinateInView(const glm::dvec3& equatorial) { - // Check if image coordinate is within current FOV - glm::dvec3 localCamera = equatorialToLocalCamera(equatorial); - glm::dvec3 coordsScreen = localCameraToScreenSpace3d(localCamera); - double r = static_cast(windowRatio()); - - bool isCoordInView = abs(coordsScreen.x) < r && abs(coordsScreen.y) < 1.f && - coordsScreen.z < 0; - - // If the coordinate is not in view, rotate camera - return isCoordInView; - } - - // Transforms a pixel coordinate to a screen space coordinate - glm::vec2 pixelToScreenSpace2d(const glm::vec2& mouseCoordinate) { - glm::vec2 size = glm::vec2(global::windowDelegate->currentWindowSize()); - // Change origin to middle of the window - glm::vec2 screenSpacePos = mouseCoordinate - (size / 2.0f); - // Ensure the upper right corner is positive on the y axis - screenSpacePos *= glm::vec2(1.0f, -1.0f); - // Transform pixel coordinates to screen space coordinates [-1,1][-ratio, ratio] - screenSpacePos /= (0.5f * size.y); - return screenSpacePos; - } - - // The horizontal and vertical fov of the OpenSpace window - glm::dvec2 fovWindow() { - // OpenSpace FOV - glm::dvec2 windowDim = glm::dvec2(global::windowDelegate->currentWindowSize()); - double windowRatio = windowDim.y / windowDim.x; - double hFov = global::windowDelegate->getHorizFieldOfView(); - glm::dvec2 OpenSpaceFOV = glm::dvec2(hFov, hFov * windowRatio); - return OpenSpaceFOV; - } - - double angleBetweenVectors(const glm::dvec3& start, const glm::dvec3& end) { - - // Find smallest angle between the two vectors - double cos = glm::dot(start, end) / (glm::length(start) * glm::length(end)); - return std::acos(cos); - } - - glm::dmat4 incrementalAnimationMatrix(const glm::dvec3& start, - const glm::dvec3& end, double deltaTime, - double speedFactor) { - - double smallestAngle = angleBetweenVectors(start, end); - // Calculate rotation this frame - double rotationAngle = smallestAngle * deltaTime * speedFactor; - - // Create the rotation matrix for local camera space - glm::dvec3 rotationAxis = glm::normalize(glm::cross(start, end)); - return glm::rotate(rotationAngle, rotationAxis); - } + glm::dvec3 cartesian = glm::dvec3( + cos(coordsRadians.x) * cos(coordsRadians.y), + sin(coordsRadians.x) * cos(coordsRadians.y), + sin(coordsRadians.y) + ); + return cartesian; } +// Converts from cartesian coordianates to spherical in the unit of degrees +glm::dvec2 cartesianToSpherical(const glm::dvec3& coord) { + // Equatorial coordinates RA = right ascension, Dec = declination + double ra = atan2(coord.y, coord.x); + double dec = atan2(coord.z, glm::sqrt((coord.x * coord.x) + (coord.y * coord.y))); + + ra = ra > 0 ? ra : ra + (2.0 * glm::pi()); + + glm::dvec2 celestialCoords{ ra, dec }; + + return glm::degrees(celestialCoords); +} + +glm::dvec3 galacticToEquatorial(const glm::dvec3& coords) { + return glm::transpose(conversionMatrix) * glm::normalize(coords); +} + +glm::dvec3 equatorialToGalactic(const glm::dvec3& coords) { + // On the unit sphere + glm::dvec3 rGalactic = conversionMatrix * glm::normalize(coords); + return rGalactic * CelestialSphereRadius; +} + +glm::dvec3 localCameraToScreenSpace3d(const glm::dvec3& coords) { + // Ensure that if the coord is behind the camera, + // the converted coordinate will be there too + double zCoord = coords.z > 0 ? -ScreenSpaceZ : ScreenSpaceZ; + + // Calculate screen space coords x and y + double tanX = coords.x / coords.z; + double tanY = coords.y / coords.z; + + glm::dvec3 screenSpace = glm::dvec3(zCoord * tanX, zCoord * tanY, zCoord); + + return screenSpace; +} + +glm::dvec3 localCameraToGalactic(const glm::dvec3& coords) { + glm::dmat4 rotation = glm::inverse( + global::navigationHandler->camera()->viewRotationMatrix()); + glm::dvec4 position = glm::dvec4(coords, 1.0); + + return glm::normalize(rotation * position) * skybrowser::CelestialSphereRadius; +} + +glm::dvec3 localCameraToEquatorial(const glm::dvec3& coords) { + // Calculate the galactic coordinate of the target direction + // projected onto the celestial sphere + glm::dvec3 camPos = global::navigationHandler->camera()->positionVec3(); + glm::dvec3 galactic = camPos + skybrowser::localCameraToGalactic(coords); + + return skybrowser::galacticToEquatorial(galactic); +} + +glm::dvec3 equatorialToLocalCamera(const glm::dvec3& coords) +{ + // Transform equatorial J2000 to galactic coord with infinite radius + glm::dvec3 galactic = equatorialToGalactic(coords); + glm::dvec3 localCamera = galacticToLocalCamera(galactic); + return localCamera; +} + +glm::dvec3 galacticToLocalCamera(const glm::dvec3& coords) { + // Transform vector to camera's local coordinate system + glm::dvec3 camPos = global::navigationHandler->camera()->positionVec3(); + glm::dmat4 camMat = global::navigationHandler->camera()->viewRotationMatrix(); + glm::dvec3 viewDirectionWorld = glm::normalize(coords - camPos); + glm::dvec3 viewDirectionLocal = camMat * glm::dvec4(viewDirectionWorld, 1.0); + + return glm::normalize(viewDirectionLocal); +} + +double cameraRoll() { + openspace::Camera* camera = global::navigationHandler->camera(); + glm::dvec3 upWorld = camera->lookUpVectorWorldSpace(); + glm::dvec3 forwardWorld = camera->viewDirectionWorldSpace(); + + glm::dvec3 camUpJ2000 = skybrowser::galacticToEquatorial(upWorld); + glm::dvec3 camForwardJ2000 = skybrowser::galacticToEquatorial(forwardWorld); + + glm::dvec3 crossUpNorth = glm::cross(camUpJ2000, skybrowser::NorthPole); + double dotNorthUp = glm::dot(skybrowser::NorthPole, camUpJ2000); + double dotCrossUpNorthForward = glm::dot(crossUpNorth, camForwardJ2000); + + return glm::degrees(atan2(dotCrossUpNorthForward, dotNorthUp)); +} + +glm::dvec3 cameraDirectionEquatorial() { + // Get the view direction of the screen in cartesian J2000 coordinates + return galacticToEquatorial(cameraDirectionGalactic()); +} + +glm::dvec3 cameraDirectionGalactic() { + // Get the view direction of the screen in galactic coordinates + glm::dvec3 camPos = global::navigationHandler->camera()->positionVec3(); + glm::dvec3 view = global::navigationHandler->camera()->viewDirectionWorldSpace(); + glm::dvec3 galCoord = camPos + (skybrowser::CelestialSphereRadius * view); + + return galCoord; +} + +float windowRatio() { + glm::vec2 windowRatio = global::windowDelegate->currentWindowSize(); + return windowRatio.x / windowRatio.y; +} + +bool isCoordinateInView(const glm::dvec3& equatorial) { + // Check if image coordinate is within current FOV + glm::dvec3 localCamera = equatorialToLocalCamera(equatorial); + glm::dvec3 coordsScreen = localCameraToScreenSpace3d(localCamera); + double r = static_cast(windowRatio()); + + bool isCoordInView = abs(coordsScreen.x) < r && abs(coordsScreen.y) < 1.f && + coordsScreen.z < 0; + + // If the coordinate is not in view, rotate camera + return isCoordInView; +} + +// Transforms a pixel coordinate to a screen space coordinate +glm::vec2 pixelToScreenSpace2d(const glm::vec2& mouseCoordinate) { + glm::vec2 size = glm::vec2(global::windowDelegate->currentWindowSize()); + // Change origin to middle of the window + glm::vec2 screenSpacePos = mouseCoordinate - (size / 2.0f); + // Ensure the upper right corner is positive on the y axis + screenSpacePos *= glm::vec2(1.0f, -1.0f); + // Transform pixel coordinates to screen space coordinates [-1,1][-ratio, ratio] + screenSpacePos /= (0.5f * size.y); + return screenSpacePos; +} + +// The horizontal and vertical fov of the OpenSpace window +glm::dvec2 fovWindow() { + // OpenSpace FOV + glm::dvec2 windowDim = glm::dvec2(global::windowDelegate->currentWindowSize()); + double windowRatio = windowDim.y / windowDim.x; + double hFov = global::windowDelegate->getHorizFieldOfView(); + glm::dvec2 OpenSpaceFOV = glm::dvec2(hFov, hFov * windowRatio); + return OpenSpaceFOV; +} + +double angleBetweenVectors(const glm::dvec3& start, const glm::dvec3& end) { + + // Find smallest angle between the two vectors + double cos = glm::dot(start, end) / (glm::length(start) * glm::length(end)); + return std::acos(cos); +} + +glm::dmat4 incrementalAnimationMatrix(const glm::dvec3& start, + const glm::dvec3& end, double deltaTime, + double speedFactor) { + + double smallestAngle = angleBetweenVectors(start, end); + // Calculate rotation this frame + double rotationAngle = smallestAngle * deltaTime * speedFactor; + + // Create the rotation matrix for local camera space + glm::dvec3 rotationAxis = glm::normalize(glm::cross(start, end)); + return glm::rotate(rotationAngle, rotationAxis); +} +} // namespace openspace + diff --git a/modules/skybrowser/src/wwtcommunicator.cpp b/modules/skybrowser/src/wwtcommunicator.cpp index 227a96f6e8..4336074f47 100644 --- a/modules/skybrowser/src/wwtcommunicator.cpp +++ b/modules/skybrowser/src/wwtcommunicator.cpp @@ -2,7 +2,7 @@ * * * OpenSpace * * * - * Copyright (c) 2014-2021 * + * Copyright (c) 2014-2022 * * * * Permission is hereby granted, free of charge, to any person obtaining a copy of this * * software and associated documentation files (the "Software"), to deal in the Software * @@ -27,327 +27,291 @@ #include #include #include -#include // formatJson +#include #include -#include -#include // For atan2 -#define _USE_MATH_DEFINES -#include // For M_PI namespace { constexpr const char* _loggerCat = "WwtCommunicator"; - - } // namespace namespace openspace { - WwtCommunicator::WwtCommunicator(const ghoul::Dictionary& dictionary) - : Browser(dictionary) {} +WwtCommunicator::WwtCommunicator(const ghoul::Dictionary& dictionary) + : Browser(dictionary) {} - WwtCommunicator::~WwtCommunicator() { +WwtCommunicator::~WwtCommunicator() {} +void WwtCommunicator::displayImage(const std::string& url, int i) { + // Ensure there are no duplicates + auto it = std::find(_selectedImages.begin(), _selectedImages.end(), i); + if (it == _selectedImages.end()) { + // Push newly selected image to front + _selectedImages.push_front(i); + // Index of image is used as layer ID as it is unique in the image data set + sendMessageToWwt(addImageMessage(std::to_string(i), url)); + sendMessageToWwt(setImageOpacityMessage(std::to_string(i), 1.0)); + } +} + +void WwtCommunicator::removeSelectedImage(int i) { + // Remove from selected list + auto it = std::find(_selectedImages.begin(), _selectedImages.end(), i); + + if (it != std::end(_selectedImages)) { + _selectedImages.erase(it); + sendMessageToWwt(removeImageMessage(std::to_string(i))); + } +} + +void WwtCommunicator::sendMessageToWwt(const ghoul::Dictionary& msg) { + std::string script = "sendMessageToWWT(" + ghoul::formatJson(msg) + ");"; + executeJavascript(script); +} + +const std::deque& WwtCommunicator::getSelectedImages() const { + return _selectedImages; +} + +void WwtCommunicator::setVerticalFov(float vfov) { + _verticalFov = vfov; + _equatorialAimIsDirty = true; +} + +void WwtCommunicator::setWebpageBorderColor(glm::ivec3 color) { + std::string stringColor = std::to_string(color.x) + "," + + std::to_string(color.y) + "," + std::to_string(color.z); + std::string script = "document.body.style.backgroundColor = 'rgb(" + + stringColor + ")';"; + executeJavascript(script); +} + +void WwtCommunicator::setIsSyncedWithWwt(bool isSynced) { + _isSyncedWithWwt = isSynced; +} + +void WwtCommunicator::setEquatorialAim(glm::dvec2 equatorial) { + _equatorialAim = std::move(equatorial); + _equatorialAimIsDirty = true; +} + +void WwtCommunicator::setBorderColor(glm::ivec3 color) { + _borderColor = std::move(color); + _borderColorIsDirty = true; +} + +void WwtCommunicator::highlight(glm::ivec3 addition) { + setWebpageBorderColor(_borderColor + addition); +} + +void WwtCommunicator::removeHighlight(glm::ivec3 removal) { + setWebpageBorderColor(_borderColor - removal); +} + +void WwtCommunicator::updateBorderColor() { + setWebpageBorderColor(_borderColor); +} + +void WwtCommunicator::updateAim() { + double roll = _isSyncedWithWwt ? skybrowser::cameraRoll() : 0.0; + // Message WorldWide Telescope current view + ghoul::Dictionary message = moveCameraMessage( + _equatorialAim, + _verticalFov, + roll + ); + sendMessageToWwt(message); +} + +glm::dvec2 WwtCommunicator::fieldsOfView() const { + glm::dvec2 browserFov = glm::dvec2(verticalFov() * browserRatio(), verticalFov()); + + return browserFov; +} + +bool WwtCommunicator::hasLoadedImages() const { + return _hasLoadedImages; +} + +glm::dvec2 WwtCommunicator::equatorialAim() const { + return _equatorialAim; +} + +void WwtCommunicator::setImageOrder(int i, int order) { + // Find in selected images list + auto current = std::find( + _selectedImages.begin(), + _selectedImages.end(), + i + ); + auto target = std::begin(_selectedImages) + order; + + // Make sure the image was found in the list + if (current != std::end(_selectedImages) && target != std::end(_selectedImages)) { + // Swap the two images + std::iter_swap(current, target); } - void WwtCommunicator::displayImage(const std::string& url, int i) - { - // Ensure there are no duplicates - auto it = std::find(std::begin(_selectedImages), std::end(_selectedImages), i); - if (it == std::end(_selectedImages)) { - // Push newly selected image to front - _selectedImages.push_front(i); - // Index of image is used as layer ID as it is unique in the image data set - sendMessageToWwt(addImage(std::to_string(i), url)); - sendMessageToWwt(setImageOpacity(std::to_string(i), 1.0)); + int reverseOrder = _selectedImages.size() - order - 1; + ghoul::Dictionary message = setLayerOrderMessage(std::to_string(i), reverseOrder); + sendMessageToWwt(message); +} + +void WwtCommunicator::loadImageCollection(const std::string& collection) { + sendMessageToWwt(loadCollectionMessage(collection)); + _hasLoadedImages = true; +} + +void WwtCommunicator::setImageOpacity(int i, float opacity) { + ghoul::Dictionary msg = setImageOpacityMessage(std::to_string(i), opacity); + sendMessageToWwt(msg); +} + +void WwtCommunicator::hideChromeInterface(bool shouldHide) { + ghoul::Dictionary msg = hideChromeGuiMessage(shouldHide); + sendMessageToWwt(msg); +} + +void WwtCommunicator::update() { + Browser::update(); + // Cap how messages are passed + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::chrono::system_clock::duration timeSinceLastUpdate = now - _lastUpdateTime; + + if (timeSinceLastUpdate > TimeUpdateInterval) { + if (_equatorialAimIsDirty) { + updateAim(); + _equatorialAimIsDirty = false; } - } - - void WwtCommunicator::removeSelectedImage(int i) { - // Remove from selected list - auto it = std::find(std::begin(_selectedImages), std::end(_selectedImages), i); - - if (it != std::end(_selectedImages)) { - _selectedImages.erase(it); - sendMessageToWwt(removeImage(std::to_string(i))); + if (_borderColorIsDirty) { + updateBorderColor(); + _borderColorIsDirty = false; } + _lastUpdateTime = std::chrono::system_clock::now(); } +} - void WwtCommunicator::sendMessageToWwt(const ghoul::Dictionary& msg) { - std::string script = "sendMessageToWWT(" + ghoul::formatJson(msg) + ");"; - executeJavascript(script); - } +void WwtCommunicator::render() { + Browser::render(); +} - const std::deque& WwtCommunicator::getSelectedImages() { - return _selectedImages; - } +void WwtCommunicator::initializeGL() { + Browser::initializeGL(); +} - void WwtCommunicator::setVerticalFov(float vfov) { - _verticalFov = vfov; - _equatorialAimIsDirty = true; - } +void WwtCommunicator::deinitializeGL() { + Browser::deinitializeGL(); +} - void WwtCommunicator::setWebpageBorderColor(glm::ivec3 color) { - std::string stringColor = std::to_string(color.x) + "," - + std::to_string(color.y) + "," + std::to_string(color.z); - std::string script = "document.body.style.backgroundColor = 'rgb(" - + stringColor + ")';"; - executeJavascript(script); - } +void WwtCommunicator::setHasLoadedImages(bool isLoaded) { + _hasLoadedImages = isLoaded; +} - void WwtCommunicator::setIsSyncedWithWwt(bool isSynced) - { - _isSyncedWithWwt = isSynced; - } +void WwtCommunicator::setIdInBrowser(const std::string& id) { + // Send ID to it's browser + executeJavascript("setId('" + id + "')"); +} - void WwtCommunicator::setEquatorialAim(const glm::dvec2& equatorial) - { - _equatorialAim = equatorial; - _equatorialAimIsDirty = true; - } +glm::ivec3 WwtCommunicator::borderColor() const { + return _borderColor; +} - void WwtCommunicator::setBorderColor(const glm::ivec3& color) - { - _borderColor = color; - _borderColorIsDirty = true; - } +float WwtCommunicator::verticalFov() const { + return _verticalFov; +} - void WwtCommunicator::highlight(glm::ivec3 addition) - { - setWebpageBorderColor(_borderColor + addition); - } +// WWT messages +ghoul::Dictionary WwtCommunicator::moveCameraMessage(const glm::dvec2& celestCoords, + double fov, double roll, + bool shouldMoveInstantly) { + using namespace std::string_literals; + ghoul::Dictionary msg; - void WwtCommunicator::removeHighlight(glm::ivec3 removal) - { - setWebpageBorderColor(_borderColor - removal); - } + // Create message + msg.setValue("event", "center_on_coordinates"s); + msg.setValue("ra", celestCoords.x); + msg.setValue("dec", celestCoords.y); + msg.setValue("fov", fov); + msg.setValue("roll", roll); + msg.setValue("instant", shouldMoveInstantly); - void WwtCommunicator::updateBorderColor() - { - setWebpageBorderColor(_borderColor); - } + return msg; +} - void WwtCommunicator::updateAim() - { - double roll = _isSyncedWithWwt ? skybrowser::cameraRoll() : 0.0; - // Message WorldWide Telescope current view - ghoul::Dictionary message = moveCamera( - _equatorialAim, - _verticalFov, - roll - ); - sendMessageToWwt(message); - } +ghoul::Dictionary WwtCommunicator::loadCollectionMessage(const std::string& url) { + using namespace std::string_literals; + ghoul::Dictionary msg; + msg.setValue("event", "load_image_collection"s); + msg.setValue("url", url); + msg.setValue("loadChildFolders", true); - glm::dvec2 WwtCommunicator::fieldsOfView() { - glm::dvec2 browserFov = glm::dvec2(verticalFov() * browserRatio(), verticalFov()); + return msg; +} - return browserFov; - } +ghoul::Dictionary WwtCommunicator::setForegroundMessage(const std::string& name) { + using namespace std::string_literals; + ghoul::Dictionary msg; + msg.setValue("event", "set_foreground_by_name"s); + msg.setValue("name", name); - bool WwtCommunicator::hasLoadedImages() const { - return _hasLoadedImages; - } + return msg; +} - glm::dvec2 WwtCommunicator::equatorialAim() const - { - return _equatorialAim; - } +ghoul::Dictionary WwtCommunicator::addImageMessage(const std::string& id, + const std::string& url) { + using namespace std::string_literals; + ghoul::Dictionary msg; + msg.setValue("event", "image_layer_create"s); + msg.setValue("id", id); + msg.setValue("url", url); + msg.setValue("mode", "preloaded"s); + msg.setValue("goto", false); - void WwtCommunicator::setImageOrder(int i, int order) { - // Find in selected images list - auto current = std::find( - std::begin(_selectedImages), - std::end(_selectedImages), - i - ); - auto target = std::begin(_selectedImages) + order; + return msg; +} - // Make sure the image was found in the list - if (current != std::end(_selectedImages) && target != std::end(_selectedImages)) { - // Swap the two images - std::iter_swap(current, target); - } +ghoul::Dictionary WwtCommunicator::removeImageMessage(const std::string& imageId) { + using namespace std::string_literals; + ghoul::Dictionary msg; + msg.setValue("event", "image_layer_remove"s); + msg.setValue("id", imageId); - int reverseOrder = _selectedImages.size() - order - 1; - ghoul::Dictionary message = setLayerOrder(std::to_string(i), - reverseOrder); - sendMessageToWwt(message); - } + return msg; +} - void WwtCommunicator::loadImageCollection(const std::string& collection) { - sendMessageToWwt(loadCollection(collection)); - _hasLoadedImages = true; - } +ghoul::Dictionary WwtCommunicator::setImageOpacityMessage(const std::string& imageId, + double opacity) { + using namespace std::string_literals; + ghoul::Dictionary msg; + msg.setValue("event", "image_layer_set"s); + msg.setValue("id", imageId); + msg.setValue("setting", "opacity"s); + msg.setValue("value", opacity); - void WwtCommunicator::setImageOpacity(int i, float opacity) { - ghoul::Dictionary msg = setImageOpacity(std::to_string(i), opacity); - sendMessageToWwt(msg); - } + return msg; +} - void WwtCommunicator::hideChromeInterface(bool shouldHide) - { - ghoul::Dictionary msg = hideChromeGui(shouldHide); - sendMessageToWwt(msg); - } +ghoul::Dictionary WwtCommunicator::setLayerOrderMessage(const std::string& id, int order) { + // The lower the layer order, the more towards the back the image is placed + // 0 is the background + using namespace std::string_literals; + ghoul::Dictionary msg; + msg.setValue("event", "image_layer_order"s); + msg.setValue("id", id); + msg.setValue("order", order); + msg.setValue("version", messageCounter); - void WwtCommunicator::update() - { - Browser::update(); - // Cap how messages are passed - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - std::chrono::system_clock::duration timeSinceLastUpdate = now - _lastUpdateTime; + messageCounter++; - if (timeSinceLastUpdate > _timeUpdateInterval) { + return msg; +} - if (_equatorialAimIsDirty) { - updateAim(); - _equatorialAimIsDirty = false; - } - if (_borderColorIsDirty) { - updateBorderColor(); - _borderColorIsDirty = false; - } - _lastUpdateTime = std::chrono::system_clock::now(); - } - } - - void WwtCommunicator::render() - { - Browser::render(); - } - - void WwtCommunicator::initializeGL() - { - Browser::initializeGL(); - } - - void WwtCommunicator::deinitializeGL() - { - Browser::deinitializeGL(); - } - - void WwtCommunicator::setHasLoadedImages(bool isLoaded) { - _hasLoadedImages = isLoaded; - } - - void WwtCommunicator::setIdInBrowser(const std::string& id) { - // Send ID to it's browser - executeJavascript("setId('" + id + "')"); - } - - - glm::ivec3 WwtCommunicator::borderColor() const { - return _borderColor; - } - - float WwtCommunicator::verticalFov() const { - return _verticalFov; - } - - // WWT messages - ghoul::Dictionary WwtCommunicator::moveCamera(const glm::dvec2& celestCoords, - double fov, double roll, - bool shouldMoveInstantly) { - using namespace std::string_literals; - ghoul::Dictionary msg; - - // Create message - msg.setValue("event", "center_on_coordinates"s); - msg.setValue("ra", celestCoords.x); - msg.setValue("dec", celestCoords.y); - msg.setValue("fov", fov); - msg.setValue("roll", roll); - msg.setValue("instant", shouldMoveInstantly); - - return msg; - } - - ghoul::Dictionary WwtCommunicator::loadCollection(const std::string& url) { - using namespace std::string_literals; - ghoul::Dictionary msg; - msg.setValue("event", "load_image_collection"s); - msg.setValue("url", url); - msg.setValue("loadChildFolders", true); - - return msg; - } - - ghoul::Dictionary WwtCommunicator::setForeground(const std::string& name) { - using namespace std::string_literals; - ghoul::Dictionary msg; - msg.setValue("event", "set_foreground_by_name"s); - msg.setValue("name", name); - - return msg; - } - - ghoul::Dictionary WwtCommunicator::addImage(const std::string& id, - const std::string& url) { - using namespace std::string_literals; - ghoul::Dictionary msg; - msg.setValue("event", "image_layer_create"s); - msg.setValue("id", id); - msg.setValue("url", url); - msg.setValue("mode", "preloaded"s); - msg.setValue("goto", false); - - return msg; - } - - ghoul::Dictionary WwtCommunicator::removeImage(const std::string& imageId) { - using namespace std::string_literals; - ghoul::Dictionary msg; - msg.setValue("event", "image_layer_remove"s); - msg.setValue("id", imageId); - - return msg; - } - - ghoul::Dictionary WwtCommunicator::setImageOpacity(const std::string& imageId, - double opacity) { - using namespace std::string_literals; - ghoul::Dictionary msg; - msg.setValue("event", "image_layer_set"s); - msg.setValue("id", imageId); - msg.setValue("setting", "opacity"s); - msg.setValue("value", opacity); - - return msg; - } - - ghoul::Dictionary WwtCommunicator::setForegroundOpacity(double val) { - using namespace std::string_literals; - ghoul::Dictionary msg; - msg.setValue("event", "set_foreground_opacity"s); - msg.setValue("value", val); - - return msg; - } - - ghoul::Dictionary WwtCommunicator::setLayerOrder(const std::string& id, int order) { - // The lower the layer order, the more towards the back the image is placed - // 0 is the background - using namespace std::string_literals; - ghoul::Dictionary msg; - msg.setValue("event", "image_layer_order"s); - msg.setValue("id", id); - msg.setValue("order", order); - msg.setValue("version", messageCounter); - - messageCounter++; - - return msg; - } - - ghoul::Dictionary WwtCommunicator::hideChromeGui(bool isHidden) - { - using namespace std::string_literals; - ghoul::Dictionary msg; - msg.setValue("event", "modify_settings"s); - msg.setValue("settings", "[[\"hideAllChrome\", true]]"s); - msg.setValue("target", "app"s); - - return msg; - } +ghoul::Dictionary WwtCommunicator::hideChromeGuiMessage(bool isHidden) { + using namespace std::string_literals; + ghoul::Dictionary msg; + msg.setValue("event", "modify_settings"s); + msg.setValue("settings", "[[\"hideAllChrome\", true]]"s); + msg.setValue("target", "app"s); + return msg; +} } // namespace openspace diff --git a/modules/skybrowser/src/wwtdatahandler.cpp b/modules/skybrowser/src/wwtdatahandler.cpp index 40aeabf4d1..0f3d8944b7 100644 --- a/modules/skybrowser/src/wwtdatahandler.cpp +++ b/modules/skybrowser/src/wwtdatahandler.cpp @@ -1,11 +1,34 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ #include #include #include -#include // For downloading files from url +#include #include #include -#include // To iterate through files in directory +#include #include #include #include @@ -16,351 +39,337 @@ namespace { namespace openspace { - bool hasAttribute(const tinyxml2::XMLElement* element, const std::string& name) { - return element->FindAttribute(name.c_str()); +bool hasAttribute(const tinyxml2::XMLElement* element, const std::string_view& name) { + return element->FindAttribute(std::string(name).c_str()); +} + +std::string attribute(const tinyxml2::XMLElement* element, const std::string& name) { + if (hasAttribute(element, name)) { + return element->FindAttribute(name.c_str())->Value(); } - - std::string attribute(const tinyxml2::XMLElement* element, const std::string& name) { - if (hasAttribute(element, name)) { - return element->FindAttribute(name.c_str())->Value(); - } - else { - return wwt::Undefined; - } + else { + return wwt::Undefined; } +} - // Parsing and downloading of wtml files - bool downloadFile(const std::string& url, const std::string& fileDestination) { - // Get the web page and save to file - HttpFileDownload wtml_root( - url, fileDestination, HttpFileDownload::Overwrite::Yes - ); - wtml_root.start(std::chrono::milliseconds(5)); - return wtml_root.hasSucceeded(); +// Parsing and downloading of wtml files +bool downloadFile(const std::string& url, const std::filesystem::path& fileDestination) { + // Get the web page and save to file + HttpFileDownload wtmlRoot( + url, + fileDestination, + HttpFileDownload::Overwrite::Yes + ); + wtmlRoot.start(std::chrono::milliseconds(10000)); + return wtmlRoot.wait(); +} + +bool directoryExists(const std::filesystem::path& path) { + return std::filesystem::exists(path) && std::filesystem::is_directory(path); +} + +std::string createSearchableString(std::string str) { + // Remove white spaces and all special characters + str.erase(std::remove_if(str.begin(), str.end(), [](char c) { + const bool isNumberOrLetter = std::isdigit(c) || std::isalpha(c); + return !isNumberOrLetter; + }), + std::end(str)); + // Make the word lower case + std::transform(str.begin(), str.end(), str.begin(), [](char c) { + return std::tolower(c); + }); + return str; +} + +tinyxml2::XMLElement* getDirectChildNode(tinyxml2::XMLElement* node, + const std::string& name) +{ + while (node && node->Name() != name) { + node = node->FirstChildElement(); } + return node; +} - bool directoryExists(const std::string& path) - { - struct stat info; - - int statRC = stat(path.c_str(), &info); - if (statRC != 0) - { - // something along the path does not exist - if (errno == ENOENT) { - return false; - } - // something in path prefix is not a dir - if (errno == ENOTDIR) { - return false; - } - return false; - } - - const bool directoryExists = (info.st_mode & S_IFDIR); - - return directoryExists; - } - - std::string createSearchableString(std::string str) { - // Remove white spaces and all special characters - str.erase(std::remove_if(std::begin(str), std::end(str), [](char c) { - const bool isNumberOrLetter = std::isdigit(c) || std::isalpha(c); - return !isNumberOrLetter; - }), - std::end(str)); - // Make the word lower case - std::transform(std::begin(str), std::end(str), std::begin(str), [](char c) { - return std::tolower(c); - }); - return str; - } - - tinyxml2::XMLElement* getDirectChildNode(tinyxml2::XMLElement* node, - const std::string& name) { - while (node && node->Name() != name) { - node = node->FirstChildElement(); - } - return node; - } - - tinyxml2::XMLElement* getChildNode(tinyxml2::XMLElement* node, - const std::string& name) { +tinyxml2::XMLElement* getChildNode(tinyxml2::XMLElement* node, + const std::string& name) +{ - tinyxml2::XMLElement* child = node->FirstChildElement(); - tinyxml2::XMLElement* imageSet = nullptr; + tinyxml2::XMLElement* child = node->FirstChildElement(); + tinyxml2::XMLElement* imageSet = nullptr; - // Traverse the children and look at all their first child to find ImageSet - while (child) { - imageSet = getDirectChildNode(child, name); - // Found - if (imageSet) { - break; - } - child = child->NextSiblingElement(); - } - return imageSet; - } - - std::string getChildNodeContentFromImageSet(tinyxml2::XMLElement* imageSet, - const std::string& elementName) { - // Find the thumbnail image url - // The thumbnail is the last node so traverse backwards for speed - tinyxml2::XMLElement* imageSetChild = imageSet->FirstChildElement( - elementName.c_str() - ); - - if (imageSetChild && imageSetChild->GetText()) { - return imageSetChild->GetText(); - } - else { - return wwt::Undefined; - } - } - - std::string getUrlFromPlace(tinyxml2::XMLElement* place) { - - // If the place has a thumbnail url, return it - if (hasAttribute(place, wwt::Thumbnail)) { - return attribute(place, wwt::Thumbnail); - } - - // If the place doesn't have a thumbnail url data attribute, - // Load the image set it stores instead - tinyxml2::XMLElement* imageSet = getChildNode(place, wwt::ImageSet); - - // If there is an imageSet, collect thumbnail url + // Traverse the children and look at all their first child to find ImageSet + while (child) { + imageSet = getDirectChildNode(child, name); + // Found if (imageSet) { - return getChildNodeContentFromImageSet(imageSet, wwt::ThumbnailUrl); + break; } - else { - // If it doesn't contain an ImageSet, it doesn't have an url - return wwt::Undefined; - } - } + child = child->NextSiblingElement(); + } + return imageSet; +} + +std::string getChildNodeContentFromImageSet(tinyxml2::XMLElement* imageSet, + const std::string& elementName) +{ + // Find the thumbnail image url + // The thumbnail is the last node so traverse backwards for speed + tinyxml2::XMLElement* imageSetChild = imageSet->FirstChildElement( + elementName.c_str() + ); + + if (imageSetChild && imageSetChild->GetText()) { + return imageSetChild->GetText(); + } + else { + return wwt::Undefined; + } +} + +std::string getUrlFromPlace(tinyxml2::XMLElement* place) { + // If the place has a thumbnail url, return it + if (hasAttribute(place, wwt::Thumbnail)) { + return attribute(place, wwt::Thumbnail); + } + + // If the place doesn't have a thumbnail url data attribute, + // Load the image set it stores instead + tinyxml2::XMLElement* imageSet = getChildNode(place, wwt::ImageSet); + + // If there is an imageSet, collect thumbnail url + if (imageSet) { + return getChildNodeContentFromImageSet(imageSet, wwt::ThumbnailUrl); + } + else { + // If it doesn't contain an ImageSet, it doesn't have an url + return wwt::Undefined; + } +} - void parseWtmlsFromDisc(std::vector& _xmls, - const std::string& directory) { - for (const auto& entry : std::filesystem::directory_iterator(directory)) { +void parseWtmlsFromDisc(std::vector& _xmls, + const std::filesystem::path& directory) +{ + for (const auto& entry : std::filesystem::directory_iterator(directory)) { - tinyxml2::XMLDocument* document = new tinyxml2::XMLDocument(); - std::string path = entry.path().u8string(); - tinyxml2::XMLError successCode = document->LoadFile(path.c_str()); + tinyxml2::XMLDocument* document = new tinyxml2::XMLDocument(); + std::string path = entry.path().u8string(); + tinyxml2::XMLError successCode = document->LoadFile(path.c_str()); - if (successCode == tinyxml2::XMLError::XML_SUCCESS) { - _xmls.push_back(document); - } + if (successCode == tinyxml2::XMLError::XML_SUCCESS) { + _xmls.push_back(document); } } - - bool downloadAndParseWtmlFilesFromUrl(std::vector& _xmls, - const std::string& directory, const std::string& url, - const std::string& fileName) - { - // Look for WWT image data folder, create folder if it doesn't exist - if (!directoryExists(directory)) { - std::string newDir = directory; - // Remove the '/' at the end - newDir.pop_back(); - LINFO("Creating directory WWTimagedata"); - std::filesystem::create_directory(newDir); - } - - // Download file from url - std::string file = directory.c_str() + fileName + ".aspx"; - if (!downloadFile(url, file)) { - LINFO("Couldn't download file " + url); - return false; - } - - // Parse file to XML - using namespace tinyxml2; - tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument(); - doc->LoadFile(file.c_str()); - - // Search XML file for folders with urls - XMLElement* root = doc->RootElement(); - XMLElement* element = root->FirstChildElement(wwt::Folder.c_str()); - const bool folderExists = element; - const bool folderContainNoUrls = folderExists && !hasAttribute(element, wwt::Url); - - // If the file contains no folders, or there are folders but without urls, - // stop recursion - if (!folderExists || folderContainNoUrls) { - _xmls.push_back(doc); - LINFO("Saving " + url); - - return true; - } - - // Iterate through all the folders in the XML file - while (element && std::string(element->Value()) == wwt::Folder) { - - // If folder contains urls, download and parse those urls - if (hasAttribute(element, wwt::Url) && hasAttribute(element, wwt::Name)) { - std::string url = attribute(element, wwt::Url); - std::string fileName = attribute(element, wwt::Name); - downloadAndParseWtmlFilesFromUrl(_xmls, directory, url, fileName); - } - element = element->NextSiblingElement(); - } - - } - - WwtDataHandler::~WwtDataHandler() { - // Call destructor of all allocated xmls - _xmls.clear(); - } - - void WwtDataHandler::loadImages(const std::string& root, - const std::string& directory) { - - // Collect the wtml files, either by reading from disc or from a url - if (directoryExists(directory)) { - parseWtmlsFromDisc(_xmls, directory); - LINFO("Loading images from directory"); - } - else { - downloadAndParseWtmlFilesFromUrl(_xmls, directory, root, "root"); - LINFO("Loading images from url"); - } - - // Traverse through the collected wtml documents and collect the images - for (tinyxml2::XMLDocument* doc : _xmls) { - tinyxml2::XMLElement* root = doc->FirstChildElement(); - std::string collectionName = attribute(root, wwt::Name); - saveImagesFromXml(root, collectionName); - } - - // Sort images in alphabetical order - std::sort(_images.begin(), _images.end(), [](ImageData& a, ImageData& b) { - // If the first character in the names are lowercase, make it upper case - if (std::islower(a.name[0])) { - // convert string to upper case - a.name[0] = ::toupper(a.name[0]); - } - if (std::islower(b.name[0])) { - b.name[0] = ::toupper(b.name[0]); - } - return a.name < b.name; - }); - - LINFO("Loaded " + std::to_string(_images.size()) + " WorldWide Telescope " - "images."); - } - - int WwtDataHandler::nLoadedImages() const - { - return _images.size(); - } - - const ImageData& WwtDataHandler::getImage(const int i) const - { - assert(i < _images.size(), "Index outside of image vector boundaries!"); - return _images[i]; - } - - void WwtDataHandler::saveImageFromNode(tinyxml2::XMLElement* node, - std::string collection) { - - // Collect the image set of the node. The structure is different depending on if - // it is a Place or an ImageSet - std::string thumbnailUrl = { wwt::Undefined }; - tinyxml2::XMLElement* imageSet{ nullptr }; - std::string type = std::string(node->Name()); - - if (type == wwt::ImageSet) { - thumbnailUrl = getChildNodeContentFromImageSet(node, wwt::ThumbnailUrl); - imageSet = node; - } // Place - else if (type == wwt::Place) { - thumbnailUrl = getUrlFromPlace(node); - imageSet = getChildNode(node, wwt::ImageSet); - } - - // Only collect the images that have a thumbnail image, that are sky images and - // that have an image - const bool hasThumbnailUrl = thumbnailUrl != wwt::Undefined; - const bool isSkyImage = attribute(node, wwt::DataSetType) == wwt::Sky; - const bool hasImageUrl = imageSet ? hasAttribute(imageSet, wwt::Url) : false; - - if (!(hasThumbnailUrl && isSkyImage && hasImageUrl)) { - return; - } - - // Collect name, image url and credits - std::string name = attribute(node, wwt::Name); - std::string imageUrl = attribute(imageSet, wwt::Url); - std::string credits = getChildNodeContentFromImageSet(imageSet, wwt::Credits); - std::string creditsUrl = getChildNodeContentFromImageSet( - imageSet, wwt::CreditsUrl - ); - - // Collect equatorial coordinates. All-sky surveys do not have this kind of - // coordinate - bool hasCelestialCoords = hasAttribute(node, wwt::RA) && - hasAttribute(node, wwt::Dec); - glm::dvec2 equatorialSpherical{ 0.0 }; - glm::dvec3 equatorialCartesian{ 0.0 }; - - if (hasCelestialCoords) { - // The RA from WWT is in the unit hours: - // to convert to degrees, multiply with 360 (deg) /24 (h) = 15 - double ra = 15.0 * std::stod(attribute(node, wwt::RA)); - double dec = std::stod(attribute(node, wwt::Dec)); - equatorialSpherical = { ra, dec }; - equatorialCartesian = skybrowser::sphericalToCartesian( - equatorialSpherical - ); - } - - // Collect field of view. The WWT definition of ZoomLevel is: VFOV = ZoomLevel / 6 - float fov{ 0.f }; - if (hasAttribute(node, wwt::ZoomLevel)) { - fov = std::stof(attribute(node, wwt::ZoomLevel)) / 6.0; - } - - ImageData image = { - name, - thumbnailUrl, - imageUrl, - credits, - creditsUrl, - collection, - hasCelestialCoords, - fov, - equatorialSpherical, - equatorialCartesian, - }; - - _images.push_back(image); - } - - void WwtDataHandler::saveImagesFromXml(tinyxml2::XMLElement* root, - std::string collection) { - - // Get direct child of node called Place - using namespace tinyxml2; - XMLElement* node = root->FirstChildElement(); - - // Iterate through all siblings of node. If sibling is folder, open recursively. - // If sibling is image, save it. - while (node) { - const std::string name = node->Name(); - // If node is an image or place, load it - if (name == wwt::ImageSet || name == wwt::Place) { - saveImageFromNode(node, collection); - } - // If node is another folder, open recursively - else if (name == wwt::Folder) { - std::string newCollectionName = collection + "/"; - newCollectionName += attribute(node, wwt::Name); - - saveImagesFromXml(node, newCollectionName); - } - node = node->NextSiblingElement(); - } - } - } + +bool downloadAndParseWtmlFilesFromUrl(std::vector& _xmls, + const std::filesystem::path& directory, const std::string& url, + const std::string& fileName) +{ + // Look for WWT image data folder, create folder if it doesn't exist + if (!directoryExists(directory)) { + std::string newDir = directory.string(); + // Remove the '/' at the end + newDir.pop_back(); + LINFO("Creating directory WWTimagedata"); + std::filesystem::create_directory(newDir); + } + + // Download file from url + std::filesystem::path file = directory.string() + fileName + ".aspx"; + if (!downloadFile(url, file)) { + LINFO("Couldn't download file " + url + " to directory " + directory.string()); + return false; + } + + // Parse file to XML + using namespace tinyxml2; + tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument(); + doc->LoadFile(file.string().c_str()); + + // Search XML file for folders with urls + XMLElement* root = doc->RootElement(); + XMLElement* element = root->FirstChildElement(wwt::Folder.c_str()); + const bool folderExists = element; + const bool folderContainNoUrls = folderExists && !hasAttribute(element, wwt::Url); + + // If the file contains no folders, or there are folders but without urls, + // stop recursion + if (!folderExists || folderContainNoUrls) { + _xmls.push_back(doc); + LINFO("Saving " + url); + + return true; + } + + // Iterate through all the folders in the XML file + while (element && std::string(element->Value()) == wwt::Folder) { + + // If folder contains urls, download and parse those urls + if (hasAttribute(element, wwt::Url) && hasAttribute(element, wwt::Name)) { + std::string url = attribute(element, wwt::Url); + std::string fileName = attribute(element, wwt::Name); + downloadAndParseWtmlFilesFromUrl(_xmls, directory, url, fileName); + } + element = element->NextSiblingElement(); + } + return true; +} + +WwtDataHandler::~WwtDataHandler() { + // Call destructor of all allocated xmls + _xmls.clear(); +} + +void WwtDataHandler::loadImages(const std::string& root, + const std::filesystem::path& directory) { + + // Collect the wtml files, either by reading from disc or from a url + if (directoryExists(directory)) { + parseWtmlsFromDisc(_xmls, directory); + LINFO("Loading images from directory"); + } + else { + downloadAndParseWtmlFilesFromUrl(_xmls, directory, root, "root"); + LINFO("Loading images from url"); + } + + // Traverse through the collected wtml documents and collect the images + for (tinyxml2::XMLDocument* doc : _xmls) { + tinyxml2::XMLElement* root = doc->FirstChildElement(); + std::string collectionName = attribute(root, wwt::Name); + saveImagesFromXml(root, collectionName); + } + + // Sort images in alphabetical order + std::sort(_images.begin(), _images.end(), [](ImageData& a, ImageData& b) { + // If the first character in the names are lowercase, make it upper case + if (std::islower(a.name[0])) { + // convert string to upper case + a.name[0] = ::toupper(a.name[0]); + } + if (std::islower(b.name[0])) { + b.name[0] = ::toupper(b.name[0]); + } + return a.name < b.name; + }); + + LINFO("Loaded " + std::to_string(_images.size()) + " WorldWide Telescope " + "images."); +} + +int WwtDataHandler::nLoadedImages() const +{ + return _images.size(); +} + +const ImageData& WwtDataHandler::getImage(const int i) const +{ + ghoul_assert(i < _images.size(), "Index outside of image vector boundaries!"); + return _images[i]; +} + +void WwtDataHandler::saveImageFromNode(tinyxml2::XMLElement* node, + std::string collection) { + + // Collect the image set of the node. The structure is different depending on if + // it is a Place or an ImageSet + std::string thumbnailUrl = { wwt::Undefined }; + tinyxml2::XMLElement* imageSet{ nullptr }; + std::string type = std::string(node->Name()); + + if (type == wwt::ImageSet) { + thumbnailUrl = getChildNodeContentFromImageSet(node, wwt::ThumbnailUrl); + imageSet = node; + } // Place + else if (type == wwt::Place) { + thumbnailUrl = getUrlFromPlace(node); + imageSet = getChildNode(node, wwt::ImageSet); + } + + // Only collect the images that have a thumbnail image, that are sky images and + // that have an image + const bool hasThumbnailUrl = thumbnailUrl != wwt::Undefined; + const bool isSkyImage = attribute(node, wwt::DataSetType) == wwt::Sky; + const bool hasImageUrl = imageSet ? hasAttribute(imageSet, wwt::Url) : false; + + if (!(hasThumbnailUrl && isSkyImage && hasImageUrl)) { + return; + } + + // Collect name, image url and credits + std::string name = attribute(node, wwt::Name); + std::string imageUrl = attribute(imageSet, wwt::Url); + std::string credits = getChildNodeContentFromImageSet(imageSet, wwt::Credits); + std::string creditsUrl = getChildNodeContentFromImageSet( + imageSet, wwt::CreditsUrl + ); + + // Collect equatorial coordinates. All-sky surveys do not have this kind of + // coordinate + bool hasCelestialCoords = hasAttribute(node, wwt::RA) && + hasAttribute(node, wwt::Dec); + glm::dvec2 equatorialSpherical{ 0.0 }; + glm::dvec3 equatorialCartesian{ 0.0 }; + + if (hasCelestialCoords) { + // The RA from WWT is in the unit hours: + // to convert to degrees, multiply with 360 (deg) /24 (h) = 15 + double ra = 15.0 * std::stod(attribute(node, wwt::RA)); + double dec = std::stod(attribute(node, wwt::Dec)); + equatorialSpherical = { ra, dec }; + equatorialCartesian = skybrowser::sphericalToCartesian( + equatorialSpherical + ); + } + + // Collect field of view. The WWT definition of ZoomLevel is: VFOV = ZoomLevel / 6 + float fov{ 0.f }; + if (hasAttribute(node, wwt::ZoomLevel)) { + fov = std::stof(attribute(node, wwt::ZoomLevel)) / 6.0f; + } + + ImageData image = { + name, + thumbnailUrl, + imageUrl, + credits, + creditsUrl, + collection, + hasCelestialCoords, + fov, + equatorialSpherical, + equatorialCartesian, + }; + + _images.push_back(image); +} + +void WwtDataHandler::saveImagesFromXml(tinyxml2::XMLElement* root, + std::string collection) +{ + + // Get direct child of node called Place + using namespace tinyxml2; + XMLElement* node = root->FirstChildElement(); + + // Iterate through all siblings of node. If sibling is folder, open recursively. + // If sibling is image, save it. + while (node) { + const std::string name = node->Name(); + // If node is an image or place, load it + if (name == wwt::ImageSet || name == wwt::Place) { + saveImageFromNode(node, collection); + } + // If node is another folder, open recursively + else if (name == wwt::Folder) { + std::string newCollectionName = collection + "/"; + newCollectionName += attribute(node, wwt::Name); + + saveImagesFromXml(node, newCollectionName); + } + node = node->NextSiblingElement(); + } +} +} // namespace openspace