mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-08 04:20:14 -05:00
Fix comments from pull request
This commit is contained in:
@@ -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}
|
||||
)
|
||||
|
||||
@@ -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 <openspace/documentation/documentation.h>
|
||||
#include <modules/webbrowser/include/webrenderhandler.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/vector/vec2property.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
@@ -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();
|
||||
|
||||
@@ -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 <openspace/rendering/screenspacerenderable.h>
|
||||
#include <modules/skybrowser/include/wwtcommunicator.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/properties/scalar/doubleproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
@@ -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__
|
||||
|
||||
@@ -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 <openspace/rendering/screenspacerenderable.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/scalar/doubleproperty.h>
|
||||
@@ -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__
|
||||
|
||||
@@ -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<int>& 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,
|
||||
|
||||
@@ -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 <openspace/documentation/documentation.h>
|
||||
|
||||
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<float>::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<float>::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__
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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 <modules/skybrowser/include/browser.h>
|
||||
|
||||
#include <openspace/properties/vector/ivec3property.h>
|
||||
#include <openspace/properties/vector/dvec2property.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
@@ -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<int>& 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<int>& 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<int> _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__
|
||||
|
||||
@@ -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<ImageData> _images;
|
||||
std::vector<tinyxml2::XMLDocument*> _xmls;
|
||||
|
||||
};
|
||||
// Images
|
||||
std::vector<ImageData> _images;
|
||||
std::vector<tinyxml2::XMLDocument*> _xmls;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SKYBROWSER___WWTDATAHANDLER___H__
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 <modules/skybrowser/skybrowsermodule.h>
|
||||
|
||||
#include <modules/skybrowser/include/screenspaceskybrowser.h>
|
||||
@@ -30,7 +29,6 @@
|
||||
#include <modules/skybrowser/include/screenspaceskytarget.h>
|
||||
#include <modules/skybrowser/include/wwtdatahandler.h>
|
||||
#include <modules/base/rendering/screenspaceimagelocal.h>
|
||||
#include "skybrowsermodule_lua.inl"
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
@@ -39,9 +37,9 @@
|
||||
#include <openspace/camera/camera.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
|
||||
#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<TargetBrowserPair>& 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<Parameters>(dict);
|
||||
|
||||
// Register ScreenSpaceRenderable
|
||||
auto fScreenSpaceRenderable = FactoryManager::ref().factory<ScreenSpaceRenderable>();
|
||||
ghoul::TemplateFactory<ScreenSpaceRenderable>* fScreenSpaceRenderable =
|
||||
FactoryManager::ref().factory<ScreenSpaceRenderable>();
|
||||
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<WwtDataHandler>();
|
||||
}
|
||||
|
||||
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<TargetBrowserPair> &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<ScreenSpaceSkyTarget*>(
|
||||
global::renderEngine->screenSpaceRenderable(targetId)
|
||||
);
|
||||
);
|
||||
ScreenSpaceSkyBrowser* browser = dynamic_cast<ScreenSpaceSkyBrowser*>(
|
||||
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<TargetBrowserPair>& 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<WwtDataHandler>& SkyBrowserModule::getWwtDataHandler() {
|
||||
const std::unique_ptr<WwtDataHandler>& SkyBrowserModule::getWwtDataHandler() const {
|
||||
return _dataHandler;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<TargetBrowserPair>>& SkyBrowserModule::getPairs()
|
||||
{
|
||||
std::vector<std::unique_ptr<TargetBrowserPair>>& SkyBrowserModule::getPairs() {
|
||||
return _targetsBrowsers;
|
||||
}
|
||||
|
||||
int SkyBrowserModule::nPairs()
|
||||
{
|
||||
int SkyBrowserModule::nPairs() {
|
||||
return static_cast<int>(_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<TargetBrowserPair>& 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<TargetBrowserPair>& 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<documentation::Documentation> SkyBrowserModule::documentations() const {
|
||||
// return {
|
||||
// ExoplanetsDataPreparationTask::documentation(),
|
||||
// RenderableOrbitDisc::Documentation()
|
||||
// };
|
||||
//}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -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 <openspace/documentation/documentation.h>
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/util/distanceconstants.h>
|
||||
#include <openspace/util/mouse.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
@@ -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<std::unique_ptr<TargetBrowserPair>>& getPairs();
|
||||
int nPairs();
|
||||
TargetBrowserPair* getPair(const std::string& id);
|
||||
const std::unique_ptr<WwtDataHandler>& getWwtDataHandler();
|
||||
std::string selectedBrowserId();
|
||||
const std::unique_ptr<WwtDataHandler>& 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<std::unique_ptr<TargetBrowserPair>> _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<WwtDataHandler> _dataHandler;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_SKYBROWSER___SKYBROWSERMODULE___H__
|
||||
|
||||
@@ -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 <modules/skybrowser/skybrowsermodule.h>
|
||||
|
||||
@@ -11,37 +34,36 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
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<int>(L, 1);
|
||||
// Load image
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::selectImage");
|
||||
const int i = ghoul::lua::value<int>(L, 1);
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
|
||||
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<std::string>(L, 1);
|
||||
const int i = ghoul::lua::value<int>(L, 1);
|
||||
int order = ghoul::lua::value<int>(L, 1);
|
||||
auto [id, i, order] = ghoul::lua::values<std::string, int, int>(L);
|
||||
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
|
||||
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<std::string>(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<SkyBrowserModule>();
|
||||
|
||||
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<TargetBrowserPair>& 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<SkyBrowserModule>();
|
||||
std::vector<std::unique_ptr<TargetBrowserPair>>& pairs = module->getPairs();
|
||||
for (std::unique_ptr<TargetBrowserPair>& pair : pairs) {
|
||||
@@ -182,9 +206,10 @@ int initializeBrowser(lua_State* L) {
|
||||
|
||||
LINFO("Initializing sky browser " + id);
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
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<std::string>(L, 1);
|
||||
const std::string browserId = ghoul::lua::value<std::string>(L, 1);
|
||||
auto [targetId, browserId] = ghoul::lua::values<std::string, std::string>(L);
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
|
||||
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<SkyBrowserModule>();
|
||||
// Send image list to GUI
|
||||
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfImages");
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
|
||||
// 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<double> 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<double> 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<int> selectedImagesVector;
|
||||
const std::deque<int> 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<double> cartesianVec = {
|
||||
cartesian.x,
|
||||
cartesian.y,
|
||||
cartesian.z
|
||||
};
|
||||
// Convert color to vector so ghoul can read it
|
||||
glm::ivec3 color = pair->borderColor();
|
||||
std::vector<int> colorVec = { color.r, color.g, color.b };
|
||||
|
||||
// Convert color to vector so ghoul can read it
|
||||
glm::vec2 size = pair->size();
|
||||
std::vector<float> 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<std::string>(L, 1);
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
|
||||
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<std::string>(L, 1);
|
||||
const int i = ghoul::lua::value<int>(L, 1);
|
||||
double opacity = ghoul::lua::value<double>(L, 1);
|
||||
auto [id, i, opacity] = ghoul::lua::values<std::string, int, double>(L);
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
|
||||
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<std::string>(L, 1);
|
||||
float startX = ghoul::lua::value<float>(L, 1);
|
||||
float startY = ghoul::lua::value<float>(L, 1);
|
||||
float transX = ghoul::lua::value<float>(L, 1);
|
||||
float transY = ghoul::lua::value<float>(L, 1);
|
||||
auto [id, startX, startY, transX, transY] =
|
||||
ghoul::lua::values<std::string, float, float, float, float>(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<std::string>(L, 1);
|
||||
// Image index
|
||||
const int i = ghoul::lua::value<int>(L, 1);
|
||||
auto [id, i] = ghoul::lua::values<std::string, int>(L);
|
||||
|
||||
// Get browser
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
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<std::string>(L, 1);
|
||||
double ra = ghoul::lua::value<double>(L, 1);
|
||||
double dec = ghoul::lua::value<double>(L, 1);
|
||||
auto [id, ra, dec] = ghoul::lua::values<std::string, double, double>(L);
|
||||
|
||||
// Get module
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
@@ -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<std::string>(L, 1);
|
||||
float vfov = ghoul::lua::value<float>(L, 1);
|
||||
auto [id, vfov] = ghoul::lua::values<std::string, float>(L);
|
||||
|
||||
// Get module
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
@@ -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<std::string>(L, 1);
|
||||
int r = ghoul::lua::value<int>(L, 1);
|
||||
int g = ghoul::lua::value<int>(L, 1);
|
||||
int b = ghoul::lua::value<int>(L, 1);
|
||||
auto [id, r, g, b] = ghoul::lua::values<std::string, int, int, int>(L);
|
||||
|
||||
glm::ivec3 color{ r, g, b };
|
||||
// Get module
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
@@ -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<std::string>(L, 1);
|
||||
float sizeX = ghoul::lua::value<float>(L, 1);
|
||||
float sizeY = ghoul::lua::value<float>(L, 1);
|
||||
auto [id, sizeX, sizeY] = ghoul::lua::values<std::string, float, float>(L);
|
||||
|
||||
// Get module
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
@@ -597,6 +585,5 @@ int setScreenSpaceSize(lua_State* L) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace openspace::skybrowser::luafunctions
|
||||
|
||||
|
||||
+145
-137
@@ -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 <openspace/engine/moduleengine.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <apps\OpenSpace\ext\sgct\include\sgct\utils\box.h>
|
||||
|
||||
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<glm::vec2> dimensions;
|
||||
|
||||
// [[codegen::verbatim(UrlInfo.description)]]
|
||||
std::optional<std::string> url;
|
||||
|
||||
// [[codegen::verbatim(ReloadInfo.description)]]
|
||||
std::optional<bool> 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<std::string>(UrlInfo.identifier)) {
|
||||
_url = dictionary.value<std::string>(UrlInfo.identifier);
|
||||
}
|
||||
// Handle target dimension property
|
||||
const Parameters p = codegen::bake<Parameters>(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<std::string>(UrlInfo.identifier)) {
|
||||
_url = dictionary.value<std::string>(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<BrowserInstance>(
|
||||
_renderHandler,
|
||||
_keyboardHandler
|
||||
);
|
||||
|
||||
_url.onChange([this]() { _isUrlDirty = true; });
|
||||
_browserPixeldimensions.onChange([this]() { _isDimensionsDirty = true; });
|
||||
_reload.onChange([this]() { _shouldReload = true; });
|
||||
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();
|
||||
if (webBrowser) {
|
||||
webBrowser->addBrowser(_browserInstance.get());
|
||||
}
|
||||
}
|
||||
|
||||
// Create browser and render handler
|
||||
_renderHandler = new RenderHandler();
|
||||
_keyboardHandler = new WebKeyboardHandler();
|
||||
_browserInstance = std::make_unique<BrowserInstance>(
|
||||
_renderHandler,
|
||||
_keyboardHandler
|
||||
);
|
||||
Browser::~Browser() {}
|
||||
|
||||
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();
|
||||
if (webBrowser) {
|
||||
webBrowser->addBrowser(_browserInstance.get());
|
||||
}
|
||||
}
|
||||
|
||||
Browser::~Browser() {
|
||||
|
||||
}
|
||||
|
||||
bool Browser::initializeGL() {
|
||||
_texture = std::make_unique<ghoul::opengl::Texture>(
|
||||
glm::uvec3(glm::ivec2(_browserPixeldimensions.value()), 1),
|
||||
GL_TEXTURE_2D
|
||||
);
|
||||
bool Browser::initializeGL() {
|
||||
_texture = std::make_unique<ghoul::opengl::Texture>(
|
||||
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<WebBrowserModule>();
|
||||
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<WebBrowserModule>();
|
||||
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<float>(_texture->dimensions().x) /
|
||||
static_cast<float>(_texture->dimensions().y);
|
||||
}
|
||||
|
||||
void Browser::setCallbackDimensions(
|
||||
const std::function<void(const glm::dvec2&)>& 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<float>(_texture->dimensions().x) /
|
||||
static_cast<float>(_texture->dimensions().y);
|
||||
}
|
||||
|
||||
void Browser::setCallbackDimensions(
|
||||
const std::function<void(const glm::dvec2&)>& 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
|
||||
|
||||
@@ -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 <modules/skybrowser/include/screenspaceskybrowser.h>
|
||||
|
||||
#include <modules/skybrowser/skybrowsermodule.h>
|
||||
@@ -7,14 +30,12 @@
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/dictionaryjsonformatter.h> // formatJson
|
||||
#include <ghoul/misc/dictionaryjsonformatter.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
#include <optional>
|
||||
#include <glm/gtx/color_space.hpp> // For hsv color
|
||||
#include <random> // For random color
|
||||
#include <glm/gtx/color_space.hpp>
|
||||
#include <random>
|
||||
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
#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<double> animationSpeed;
|
||||
|
||||
@@ -42,7 +62,7 @@ namespace {
|
||||
std::optional<float> 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<std::string>(KeyIdentifier)) {
|
||||
identifier = dictionary.value<std::string>(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<Parameters>(dictionary);
|
||||
_textureQuality = p.textureQuality.value_or(_textureQuality);
|
||||
_animationSpeed = p.animationSpeed.value_or(_animationSpeed);
|
||||
// Handle target dimension property
|
||||
const Parameters p = codegen::bake<Parameters>(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<SkyBrowserModule>();
|
||||
_borderColor = randomBorderColor(module->highlight());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ScreenSpaceSkyBrowser::~ScreenSpaceSkyBrowser() {
|
||||
if (global::windowDelegate->isMaster()) {
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
_borderColor = randomBorderColor(module->highlight());
|
||||
}
|
||||
}
|
||||
|
||||
if (module && module->getPair(identifier())) {
|
||||
module->removeTargetBrowserPair(identifier());
|
||||
}
|
||||
}
|
||||
ScreenSpaceSkyBrowser::~ScreenSpaceSkyBrowser() {
|
||||
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
|
||||
|
||||
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
|
||||
|
||||
@@ -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 <modules/skybrowser/include/screenspaceskytarget.h>
|
||||
|
||||
#include <modules/skybrowser/skybrowsermodule.h>
|
||||
@@ -61,7 +84,6 @@ namespace {
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(ScreenSpaceSkyTarget)]] Parameters {
|
||||
|
||||
// [[codegen::verbatim(CrosshairThresholdInfo.description)]]
|
||||
std::optional<float> crosshairThreshold;
|
||||
|
||||
@@ -76,7 +98,6 @@ namespace {
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> 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;
|
||||
|
||||
|
||||
@@ -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<int>& TargetBrowserPair::getSelectedImages() const
|
||||
{
|
||||
const std::deque<int>& 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<float>(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<float>(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
|
||||
|
||||
+195
-177
@@ -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 <modules/skybrowser/include/utility.h>
|
||||
|
||||
#include <openspace/engine/globals.h>
|
||||
@@ -5,191 +28,186 @@
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/camera/camera.h>
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
#include <cmath> // For atan2
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h> // For M_PI
|
||||
|
||||
#include <cmath>
|
||||
|
||||
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<float>(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<double>());
|
||||
|
||||
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<float>(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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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 <modules/webbrowser/webbrowsermodule.h>
|
||||
#include <modules/webbrowser/include/webkeyboardhandler.h>
|
||||
#include <modules/webbrowser/include/browserinstance.h>
|
||||
#include <ghoul/misc/dictionaryjsonformatter.h> // formatJson
|
||||
#include <ghoul/misc/dictionaryjsonformatter.h>
|
||||
#include <modules/skybrowser/include/utility.h>
|
||||
#include <glm/gtx/vector_angle.hpp>
|
||||
#include <cmath> // For atan2
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h> // 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<int>& 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<int>& 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
|
||||
|
||||
@@ -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 <modules/skybrowser/include/wwtdatahandler.h>
|
||||
|
||||
#include <modules/skybrowser/include/utility.h>
|
||||
#include <modules/space/speckloader.h>
|
||||
#include <openspace/util/httprequest.h> // For downloading files from url
|
||||
#include <openspace/util/httprequest.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <filesystem> // To iterate through files in directory
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -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<tinyxml2::XMLDocument*>& _xmls,
|
||||
const std::string& directory) {
|
||||
for (const auto& entry : std::filesystem::directory_iterator(directory)) {
|
||||
void parseWtmlsFromDisc(std::vector<tinyxml2::XMLDocument*>& _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<tinyxml2::XMLDocument*>& _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<tinyxml2::XMLDocument*>& _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
|
||||
|
||||
Reference in New Issue
Block a user