From fbc05244e1125cfa3314e2607e98329314be2d17 Mon Sep 17 00:00:00 2001 From: Ylva Selling Date: Tue, 23 Mar 2021 09:44:14 +0100 Subject: [PATCH] Make it possible to add many browsers and targets by moving functionality to ScreenSpaceRenderable --- .../rendering/screenspacerenderable.h | 12 ++ .../include/screenspaceskybrowser.h | 13 +- .../skybrowser/include/screenspaceskytarget.h | 1 + modules/skybrowser/skybrowsermodule.cpp | 178 ++++++++---------- modules/skybrowser/skybrowsermodule.h | 33 ++-- .../skybrowser/src/screenspaceskybrowser.cpp | 39 +--- .../skybrowser/src/screenspaceskytarget.cpp | 8 +- src/rendering/screenspacerenderable.cpp | 30 +++ 8 files changed, 158 insertions(+), 156 deletions(-) diff --git a/include/openspace/rendering/screenspacerenderable.h b/include/openspace/rendering/screenspacerenderable.h index 8d4d073843..5e79c90c74 100644 --- a/include/openspace/rendering/screenspacerenderable.h +++ b/include/openspace/rendering/screenspacerenderable.h @@ -71,6 +71,18 @@ public: bool isEnabled() const; float depth(); + // Added by skybrowser team + // Screen space functionality in these coords: [-1,1][-ratio,ratio] + glm::vec2 getScreenSpacePosition(); + glm::vec2 getScreenSpaceDimensions(); + glm::vec2 getUpperRightCornerScreenSpace(); + glm::vec2 getLowerLeftCornerScreenSpace(); + bool coordIsInsideCornersScreenSpace(glm::vec2 coord); + void translate(glm::vec2 translation, glm::vec2 position); + friend bool operator<(const ScreenSpaceRenderable& lhs, const ScreenSpaceRenderable& rhs); + + // End of addition by skybrowser team + static documentation::Documentation Documentation(); protected: diff --git a/modules/skybrowser/include/screenspaceskybrowser.h b/modules/skybrowser/include/screenspaceskybrowser.h index 51742fbc91..8b2d43459e 100644 --- a/modules/skybrowser/include/screenspaceskybrowser.h +++ b/modules/skybrowser/include/screenspaceskybrowser.h @@ -30,17 +30,12 @@ namespace openspace { void scrollZoom(float scroll); // Translation - void translate(glm::vec2 translation); - void translate(glm::vec2 translation, glm::vec2 position); + //void translate(glm::vec2 translation); + // Position and dimension and corners - glm::vec2 getScreenSpacePosition(); - glm::vec2 getScreenSpaceDimensions(); - glm::vec2 getUpperRightCornerScreenSpace(); - glm::vec2 getLowerLeftCornerScreenSpace(); + glm::vec2 getScreenSpaceBrowserDimension(); - // Mouse interaction - bool coordIsInsideCornersScreenSpace(glm::vec2 coord); glm::vec2 coordIsOnResizeArea(glm::vec2 coord); // Scaling void scale(glm::vec2 scalingFactor); @@ -54,7 +49,7 @@ namespace openspace { properties::FloatProperty _fieldOfView; properties::StringProperty _skyTargetID; private: - glm::vec2 _startSize; + glm::vec2 _startDimensionsSize; float _startScale; properties::Vec2Property _browserDimensions; bool _camIsSyncedWWT; diff --git a/modules/skybrowser/include/screenspaceskytarget.h b/modules/skybrowser/include/screenspaceskytarget.h index 2ad017ebe0..76b8d11f37 100644 --- a/modules/skybrowser/include/screenspaceskytarget.h +++ b/modules/skybrowser/include/screenspaceskytarget.h @@ -32,6 +32,7 @@ namespace openspace { void createShaders(); void setBrowser(ScreenSpaceSkyBrowser* browser); + ScreenSpaceSkyBrowser* getSkyBrowser(); void setDimensions(glm::vec2 currentBrowserDimensions); void updateFOV(float fov); diff --git a/modules/skybrowser/skybrowsermodule.cpp b/modules/skybrowser/skybrowsermodule.cpp index 7f5cfc4142..6e9461b68a 100644 --- a/modules/skybrowser/skybrowsermodule.cpp +++ b/modules/skybrowser/skybrowsermodule.cpp @@ -31,14 +31,13 @@ #include #include #include -#include +#include #include #include +#include #include #include - #include "skybrowsermodule_lua.inl" -#include #include #include #include // For atan2 @@ -46,26 +45,18 @@ #include namespace { - constexpr const openspace::properties::Property::PropertyInfo ShowSkyBrowserInfo = - { - "Show Sky Browser", - "Show Sky Browser", - "Show sky browser and target for WorldWide Telescope imagery." - }; + struct [[codegen::Dictionary(ScreenSpaceSkyBrowser)]] Parameters { - struct [[codegen::Dictionary(SkyBrowserModule)]] Parameters { - - // [[codegen::verbatim(ShowSkyBrowserInfo.description)]] - std::optional show; }; #include "skybrowsermodule_codegen.cpp" + } // namespace namespace openspace { - + scripting::LuaLibrary SkyBrowserModule::luaLibrary() const { scripting::LuaLibrary res; @@ -111,74 +102,66 @@ namespace openspace { SkyBrowserModule::SkyBrowserModule() : OpenSpaceModule(SkyBrowserModule::Name) - , _showBrowserAndTarget(ShowSkyBrowserInfo) - , _skyBrowser(nullptr) - , _skyTarget(nullptr) - , currentlyDraggingBrowser(false) - , currentlyDraggingTarget(false) + , _mouseOnObject(nullptr) , currentlyResizingBrowser(false) - , mouseIsOnBrowser(false) - , mouseIsOnTarget(false) - + , currentlyDraggingObject(false) + , resizeVector(0.f, 0.f) + , shouldInitialize(true) { - addProperty(_showBrowserAndTarget); - - _showBrowserAndTarget.onChange([&]() { - if (_showBrowserAndTarget) { - _skyBrowser->setConnectedTarget(); - _skyTarget->setConnectedBrowser(); - } - }); - global::callback::mousePosition->emplace_back( - [&](double x, double y) { + [&](double x, double y) { + // Quick fix to make all renderables find its corresponding partner + if (shouldInitialize) { + std::for_each(renderables.begin(), renderables.end(), [&](ScreenSpaceRenderable* obj) { + if (to_target(obj)) { + to_target(obj)->setConnectedBrowser(); + } + else if (to_browser(obj)) { + to_browser(obj)->setConnectedTarget(); + } + }); + shouldInitialize = false; + } + glm::vec2 pos = glm::vec2(static_cast(x), static_cast(y)); - _mousePosition = getMousePositionInScreenSpaceCoords(pos); - if (_skyTarget) { - mouseIsOnTarget = _skyTarget->coordIsInsideCornersScreenSpace(_mousePosition); + if (currentlyDraggingObject) { + _mouseOnObject->translate(_mousePosition - startDragMousePos, startDragObjectPos); } - else { - mouseIsOnTarget = false; - } - if (_skyBrowser) { - mouseIsOnBrowser = _skyBrowser->coordIsInsideCornersScreenSpace(_mousePosition); - } - else { - mouseIsOnBrowser = false; - } - - if (currentlyDraggingBrowser) { - _skyBrowser->translate(_mousePosition - startDragMousePosBrowser, startDragObjectPosBrowser); - } - if (currentlyDraggingTarget) { - _skyTarget->translate(_mousePosition - startDragMousePosTarget, startDragObjectPosTarget); - } - if (currentlyResizingBrowser) { + else if (currentlyResizingBrowser) { // Calculate scaling factor - glm::vec2 mouseDragVector = (_mousePosition - startDragMousePosBrowser); + glm::vec2 mouseDragVector = (_mousePosition - startDragMousePos); glm::vec2 scalingVector = mouseDragVector * resizeVector; - glm::vec2 newSizeRelToOld = (startResizeBrowserSize + (scalingVector)) / startResizeBrowserSize; - _skyBrowser->scale(newSizeRelToOld); + // Scale the browser + to_browser(_mouseOnObject)->scale(newSizeRelToOld); + // For dragging functionality, translate so it looks like the browser isn't moving // Make sure the browser doesn't move in directions it's not supposed to - _skyBrowser->translate(mouseDragVector * abs(resizeVector) / 2.f, startDragObjectPosBrowser); - - // _skyTarget->setDimensions(_skyBrowser->getScreenSpaceBrowserDimension()); - + _mouseOnObject->translate(mouseDragVector * abs(resizeVector) / 2.f, startDragObjectPos); + } + // If there is no dragging or resizing, look for new objects + else { + auto currentlyOnObject = std::find_if(renderables.begin(), renderables.end(), [&](ScreenSpaceRenderable* obj) { + return obj->coordIsInsideCornersScreenSpace(_mousePosition); + }); + _mouseOnObject = currentlyOnObject != renderables.end() ? *currentlyOnObject : nullptr; } } ); global::callback::mouseScrollWheel->emplace_back( [&](double, double scroll) -> bool { - if (mouseIsOnBrowser) { - _skyBrowser->scrollZoom(scroll); + // If mouse is on browser, apply zoom + if (to_browser(_mouseOnObject)) { + to_browser(_mouseOnObject)->scrollZoom(scroll); return true; } - + else if (to_target(_mouseOnObject) && to_target(_mouseOnObject)->getSkyBrowser()) { + to_target(_mouseOnObject)->getSkyBrowser()->scrollZoom(scroll); + } + return false; } ); @@ -187,52 +170,42 @@ SkyBrowserModule::SkyBrowserModule() [&](MouseButton button, MouseAction action, KeyModifier modifier) -> bool { if (action == MouseAction::Press) { - - if (mouseIsOnBrowser && button == MouseButton::Left) { - - startDragMousePosBrowser = _mousePosition; - startDragObjectPosBrowser = _skyBrowser->getScreenSpacePosition(); - // Resize browser if mouse is over resize button - resizeVector = _skyBrowser->coordIsOnResizeArea(_mousePosition); - if (resizeVector != glm::vec2{0}) { - _skyBrowser->saveResizeStartSize(); - startResizeBrowserSize = _skyBrowser->getScreenSpaceDimensions(); - currentlyResizingBrowser = true; + if (_mouseOnObject && button == MouseButton::Left) { + startDragMousePos = _mousePosition; + startDragObjectPos = _mouseOnObject->getScreenSpacePosition(); + + // If current object is browser, check for resizing + if (to_browser(_mouseOnObject)) { + // Resize browser if mouse is over resize button + resizeVector = to_browser(_mouseOnObject)->coordIsOnResizeArea(_mousePosition); + if (resizeVector != glm::vec2{ 0 }) { + to_browser(_mouseOnObject)->saveResizeStartSize(); + startResizeBrowserSize = to_browser(_mouseOnObject)->getScreenSpaceDimensions(); + currentlyResizingBrowser = true; + return true; + } } - else { - currentlyDraggingBrowser = true; - } - + currentlyDraggingObject = true; + return true; } - else if (mouseIsOnTarget && button == MouseButton::Left) { - - startDragMousePosTarget = _mousePosition; - startDragObjectPosTarget = _skyTarget->getScreenSpacePosition(); - currentlyDraggingTarget = true; - return true; - } - else if (mouseIsOnBrowser && button == MouseButton::Right) { + else if (to_browser(_mouseOnObject) && button == MouseButton::Right) { - startDragMousePosTarget = _mousePosition; - startDragObjectPosTarget = _skyTarget->getScreenSpacePosition(); - currentlyDraggingTarget = true; + //startDragMousePos = _mousePosition; + //startDragObjectPos = dynamic_cast(_mouseOnObject)->->getScreenSpacePosition(); + //currentlyDraggingObject = true; return true; } } else if (action == MouseAction::Release) { - if (currentlyDraggingBrowser) { - currentlyDraggingBrowser = false; - return true; - } - if (currentlyDraggingTarget) { - currentlyDraggingTarget = false; + if (currentlyDraggingObject) { + currentlyDraggingObject = false; return true; } if (currentlyResizingBrowser) { currentlyResizingBrowser = false; - _skyBrowser->updateBrowserSize(); + to_browser(_mouseOnObject)->updateBrowserSize(); return true; } } @@ -250,7 +223,6 @@ void SkyBrowserModule::internalDeinitialize() { void SkyBrowserModule::internalInitialize(const ghoul::Dictionary& dict) { const Parameters p = codegen::bake(dict); - _showBrowserAndTarget = p.show.value_or(_showBrowserAndTarget); // register ScreenSpaceBrowser auto fScreenSpaceRenderable = FactoryManager::ref().factory(); @@ -274,13 +246,17 @@ glm::vec2 SkyBrowserModule::getMousePositionInScreenSpaceCoords(glm::vec2& mouse return screenSpacePos; } -void SkyBrowserModule::addSkyBrowser(ScreenSpaceSkyBrowser* browser) { - _skyBrowser = browser; +void SkyBrowserModule::addRenderable(ScreenSpaceRenderable* object) { + renderables.push_back(object); + // Sort on z coordinate, objects closer to camera are in beginning of list + std::sort(renderables.begin(), renderables.end()); } - -void SkyBrowserModule::addSkyTarget(ScreenSpaceSkyTarget* target) { - _skyTarget = target; +ScreenSpaceSkyBrowser* SkyBrowserModule::to_browser(ScreenSpaceRenderable* ptr) { + return dynamic_cast(ptr); +} +ScreenSpaceSkyTarget* SkyBrowserModule::to_target(ScreenSpaceRenderable* ptr) { + return dynamic_cast(ptr); } diff --git a/modules/skybrowser/skybrowsermodule.h b/modules/skybrowser/skybrowsermodule.h index ad73291af2..aa26181e56 100644 --- a/modules/skybrowser/skybrowsermodule.h +++ b/modules/skybrowser/skybrowsermodule.h @@ -38,6 +38,7 @@ namespace openspace { class ScreenSpaceSkyBrowser; class ScreenSpaceSkyTarget; +class ScreenSpaceRenderable; class SkyBrowserModule : public OpenSpaceModule { public: @@ -46,30 +47,34 @@ public: SkyBrowserModule(); virtual ~SkyBrowserModule() = default; glm::vec2 getMousePositionInScreenSpaceCoords(glm::vec2& mousePos); + void addRenderable(ScreenSpaceRenderable* object); - void addSkyBrowser(ScreenSpaceSkyBrowser* browser); - void addSkyTarget(ScreenSpaceSkyTarget* target); scripting::LuaLibrary luaLibrary() const override; //std::vector documentations() const override; protected: void internalInitialize(const ghoul::Dictionary& dict) override; void internalDeinitialize() override; - properties::BoolProperty _showBrowserAndTarget; - ScreenSpaceSkyBrowser* _skyBrowser; - ScreenSpaceSkyTarget* _skyTarget; - glm::vec2 startDragMousePosBrowser; - glm::vec2 startDragObjectPosBrowser; - glm::vec2 startDragMousePosTarget; - glm::vec2 startDragObjectPosTarget; + // Using snake case on these casting functions to make them similar to eg std::to_string + ScreenSpaceSkyBrowser* to_browser(ScreenSpaceRenderable* ptr); + ScreenSpaceSkyTarget* to_target(ScreenSpaceRenderable* ptr); + + bool shouldInitialize; + + // Renderable vector and ptr to where mouse is + std::vector renderables; + ScreenSpaceRenderable* _mouseOnObject; + // Dragging + glm::vec2 startDragMousePos; + glm::vec2 startDragObjectPos; + // Resizing glm::vec2 startResizeBrowserSize; glm::vec2 resizeVector; - bool currentlyDraggingBrowser; - bool currentlyResizingBrowser; - bool currentlyDraggingTarget; + // The current mouse position in screenspace coordinates glm::vec2 _mousePosition; - bool mouseIsOnBrowser; - bool mouseIsOnTarget; + // Current interaction status + bool currentlyResizingBrowser; + bool currentlyDraggingObject; }; } // namespace openspace diff --git a/modules/skybrowser/src/screenspaceskybrowser.cpp b/modules/skybrowser/src/screenspaceskybrowser.cpp index 017ad0be93..5a124e7b5e 100644 --- a/modules/skybrowser/src/screenspaceskybrowser.cpp +++ b/modules/skybrowser/src/screenspaceskybrowser.cpp @@ -61,6 +61,7 @@ namespace { } // namespace namespace openspace { + ScreenSpaceSkyBrowser::ScreenSpaceSkyBrowser(const ghoul::Dictionary& dictionary) : ScreenSpaceBrowser(dictionary) , _browserDimensions(BrowserDimensionInfo, _dimensions, glm::ivec2(0.f), glm::ivec2(300.f)) @@ -115,7 +116,7 @@ namespace openspace { } bool ScreenSpaceSkyBrowser::initializeGL() { - global::moduleEngine->module()->addSkyBrowser(this); + global::moduleEngine->module()->addRenderable(this); setConnectedTarget(); if (_skyTarget) { _skyTarget->setDimensions(getScreenSpaceBrowserDimension()); @@ -229,13 +230,13 @@ namespace openspace { // Sleep so we don't bombard WWT with too many messages std::this_thread::sleep_for(std::chrono::milliseconds(50)); sendMessageToWWT(message); + } }); } - glm::dvec2 ScreenSpaceSkyBrowser::convertGalacticToCelestial(glm::dvec3 rGal) const { - + glm::dvec2 ScreenSpaceSkyBrowser::convertGalacticToCelestial(glm::dvec3 rGal) const { // Used the math from this website: https://gea.esac.esa.int/archive/documentation/GD --> // R2/Data_processing/chap_cu3ast/sec_cu3ast_intro/ssec_cu3ast_intro_tansforms.html#SSS1 const glm::dmat3 conversionMatrix = glm::dmat3({ @@ -252,37 +253,14 @@ namespace openspace { return glm::dvec2(glm::degrees(ra), glm::degrees(dec)); } - + /* void ScreenSpaceSkyBrowser::translate(glm::vec2 translation) { glm::vec3 position = _cartesianPosition; _cartesianPosition = glm::translate(glm::mat4(1.f), glm::vec3(translation, 0.0f)) * glm::vec4(position, 1.0f); - } + }*/ - void ScreenSpaceSkyBrowser::translate(glm::vec2 translation, glm::vec2 position) { - _cartesianPosition = glm::translate(glm::mat4(1.f), glm::vec3(translation, 0.0f)) * glm::vec4(position, _cartesianPosition.value().z, 1.0f); - } - glm::vec2 ScreenSpaceSkyBrowser::getScreenSpacePosition() { - return glm::vec2(_cartesianPosition.value().x, _cartesianPosition.value().y); - } - glm::vec2 ScreenSpaceSkyBrowser::getScreenSpaceDimensions() { - return glm::vec2(2.f*_scale* static_cast(_objectSize.x) / static_cast(_objectSize.y), 2.f*_scale); - } - - glm::vec2 ScreenSpaceSkyBrowser::getUpperRightCornerScreenSpace() { - return getScreenSpacePosition() + (getScreenSpaceDimensions()/2.0f); - } - - glm::vec2 ScreenSpaceSkyBrowser::getLowerLeftCornerScreenSpace() { - return getScreenSpacePosition() - (getScreenSpaceDimensions()/2.0f); - } - - bool ScreenSpaceSkyBrowser::coordIsInsideCornersScreenSpace(glm::vec2 coord) { - bool lessThanUpperRight = coord.x < getUpperRightCornerScreenSpace().x && coord.y < getUpperRightCornerScreenSpace().y; - bool moreThanLowerLeft = coord.x > getLowerLeftCornerScreenSpace().x && coord.y > getLowerLeftCornerScreenSpace().y; - return lessThanUpperRight && moreThanLowerLeft; - } glm::vec2 ScreenSpaceSkyBrowser::coordIsOnResizeArea(glm::vec2 coord) { glm::vec2 resizePosition = glm::vec2{ 0 }; @@ -308,7 +286,7 @@ namespace openspace { // equal to the height of the window scale(abs(scalingFactor.y)); // Resize the dimensions of the texture on the x axis - glm::vec2 newSize = abs(scalingFactor) * _startSize; + glm::vec2 newSize = abs(scalingFactor) * _startDimensionsSize; _texture->setDimensions(glm::ivec3(newSize, 1)); _objectSize = _texture->dimensions(); _browserDimensions = newSize; @@ -330,9 +308,10 @@ namespace openspace { } void ScreenSpaceSkyBrowser::saveResizeStartSize() { - _startSize = glm::vec2(_dimensions.value().x, _dimensions.value().y); + _startDimensionsSize = glm::vec2(_dimensions.value().x, _dimensions.value().y); _startScale = _scale.value(); } + // Updates the browser size to match the size of the texture void ScreenSpaceSkyBrowser::updateBrowserSize() { _dimensions = _texture->dimensions(); diff --git a/modules/skybrowser/src/screenspaceskytarget.cpp b/modules/skybrowser/src/screenspaceskytarget.cpp index 113802d770..30d97e479e 100644 --- a/modules/skybrowser/src/screenspaceskytarget.cpp +++ b/modules/skybrowser/src/screenspaceskytarget.cpp @@ -92,7 +92,7 @@ namespace openspace { identifier = makeUniqueIdentifier(identifier); setIdentifier(identifier); - _cartesianPosition.setValue(glm::vec3(_cartesianPosition.value().x, _cartesianPosition.value().y, -2.1f)); + _cartesianPosition.setValue(glm::vec3(_cartesianPosition.value().x, _cartesianPosition.value().y, -2.11f)); } @@ -115,7 +115,7 @@ namespace openspace { } bool ScreenSpaceSkyTarget::initializeGL() { - global::moduleEngine->module()->addSkyTarget(this); + global::moduleEngine->module()->addRenderable(this); setConnectedBrowser(); @@ -175,6 +175,10 @@ namespace openspace { _skyBrowser = browser; } + ScreenSpaceSkyBrowser* ScreenSpaceSkyTarget::getSkyBrowser() { + return _skyBrowser; + } + void ScreenSpaceSkyTarget::render() { glDisable(GL_CULL_FACE); diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index a6710b1980..aa6d868b05 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -558,6 +558,36 @@ glm::mat4 ScreenSpaceRenderable::scaleMatrix() { return scale; } +glm::vec2 ScreenSpaceRenderable::getScreenSpacePosition() { + return glm::vec2(_cartesianPosition.value().x, _cartesianPosition.value().y); +} + +glm::vec2 ScreenSpaceRenderable::getScreenSpaceDimensions() { + return glm::vec2(2.f * _scale * static_cast(_objectSize.x) / static_cast(_objectSize.y), 2.f * _scale); +} + +glm::vec2 ScreenSpaceRenderable::getUpperRightCornerScreenSpace() { + return getScreenSpacePosition() + (getScreenSpaceDimensions() / 2.0f); +} + +glm::vec2 ScreenSpaceRenderable::getLowerLeftCornerScreenSpace() { + return getScreenSpacePosition() - (getScreenSpaceDimensions() / 2.0f); +} + +bool ScreenSpaceRenderable::coordIsInsideCornersScreenSpace(glm::vec2 coord) { + bool lessThanUpperRight = coord.x < getUpperRightCornerScreenSpace().x && coord.y < getUpperRightCornerScreenSpace().y; + bool moreThanLowerLeft = coord.x > getLowerLeftCornerScreenSpace().x && coord.y > getLowerLeftCornerScreenSpace().y; + return lessThanUpperRight && moreThanLowerLeft; +} + +void ScreenSpaceRenderable::translate(glm::vec2 translation, glm::vec2 position) { + _cartesianPosition = glm::translate(glm::mat4(1.f), glm::vec3(translation, 0.0f)) * glm::vec4(position, _cartesianPosition.value().z, 1.0f); +} + +bool operator<(const ScreenSpaceRenderable& lhs, const ScreenSpaceRenderable& rhs) { + // Sort on depth coordinate, larger values are closer to camera + return lhs._cartesianPosition.value().z > rhs._cartesianPosition.value().z; +} glm::mat4 ScreenSpaceRenderable::globalRotationMatrix() { // We do not want the screen space planes to be affected by