Files
OpenSpace/modules/skybrowser/src/targetbrowserpair.cpp

403 lines
14 KiB
C++

/*****************************************************************************************
* *
* 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/targetbrowserpair.h>
#include <modules/skybrowser/include/renderableskytarget.h>
#include <modules/skybrowser/include/screenspaceskybrowser.h>
#include <modules/skybrowser/include/utility.h>
#include <modules/skybrowser/include/wwtdatahandler.h>
#include <modules/skybrowser/skybrowsermodule.h>
#include <openspace/camera/camera.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/misc/assert.h>
#include <glm/gtc/constants.hpp>
#include <functional>
#include <chrono>
namespace openspace {
TargetBrowserPair::TargetBrowserPair(SceneGraphNode* targetNode,
ScreenSpaceSkyBrowser* browser)
: _browser(browser)
, _targetNode(targetNode)
{
ghoul_assert(browser, "Sky browser is null pointer");
ghoul_assert(targetNode, "Sky target is null pointer");
_targetRenderable = dynamic_cast<RenderableSkyTarget*>(_targetNode->renderable());
}
TargetBrowserPair& TargetBrowserPair::operator=(TargetBrowserPair other) {
std::swap(_targetNode, other._targetNode);
std::swap(_browser, other._browser);
return *this;
}
void TargetBrowserPair::setImageOrder(int i, int order) {
_browser->setImageOrder(i, order);
}
void TargetBrowserPair::aimTargetGalactic(glm::dvec3 direction) {
std::string id = _targetNode->identifier();
glm::dvec3 positionCelestial = glm::normalize(direction) *
skybrowser::CelestialSphereRadius;
std::string script = fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Translation.Position', {});",
id, ghoul::to_string(positionCelestial)
);
openspace::global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::RemoteScripting::Yes
);
}
void TargetBrowserPair::startFinetuningTarget() {
_startTargetPosition = _targetNode->worldPosition();
}
// The fine tune of the target is a way to "drag and drop" the target with right click
// drag on the sky browser window. This is to be able to drag the target around when it
// has a very small field of view
void TargetBrowserPair::fineTuneTarget(const glm::vec2& startMouse,
const glm::vec2& translation)
{
glm::vec2 fineTune = _browser->fineTuneVector(translation);
glm::vec2 endMouse = startMouse + fineTune;
// Translation world
glm::dvec3 startWorld = skybrowser::localCameraToGalactic(
glm::vec3(startMouse, skybrowser::ScreenSpaceZ)
);
glm::dvec3 endWorld = skybrowser::localCameraToGalactic(
glm::vec3(endMouse, skybrowser::ScreenSpaceZ)
);
glm::dvec3 translationWorld = endWorld - startWorld;
aimTargetGalactic(_startTargetPosition + translationWorld);
}
void TargetBrowserPair::synchronizeAim() {
if (!_targetAnimation.isAnimating() && _browser->isInitialized()) {
_browser->setEquatorialAim(targetDirectionEquatorial());
_browser->setTargetRoll(targetRoll());
_targetRenderable->setVerticalFov(_browser->verticalFov());
}
}
void TargetBrowserPair::setEnabled(bool enable) {
_browser->setEnabled(enable);
_targetRenderable->property("Enabled")->set(enable);
}
void TargetBrowserPair::setOpacity(float opacity) {
_browser->property("Opacity")->set(opacity);
_targetRenderable->property("Opacity")->set(opacity);
}
bool TargetBrowserPair::isEnabled() const {
return _targetRenderable->isEnabled() || _browser->isEnabled();
}
void TargetBrowserPair::initialize() {
_targetRenderable->setColor(_browser->borderColor());
glm::vec2 dim = _browser->screenSpaceDimensions();
_targetRenderable->setRatio(dim.x / dim.y);
_browser->updateBorderColor();
_browser->hideChromeInterface();
_browser->setIsInitialized(true);
}
glm::ivec3 TargetBrowserPair::borderColor() const {
return _browser->borderColor();
}
glm::dvec2 TargetBrowserPair::targetDirectionEquatorial() const {
glm::dvec3 cartesian = skybrowser::galacticToEquatorial(
glm::normalize(_targetNode->worldPosition())
);
return skybrowser::cartesianToSpherical(cartesian);
}
glm::dvec3 TargetBrowserPair::targetDirectionGalactic() const {
return glm::normalize(_targetNode->worldPosition());
}
std::string TargetBrowserPair::browserGuiName() const {
return _browser->guiName();
}
std::string TargetBrowserPair::browserId() const {
return _browser->identifier();
}
std::string TargetBrowserPair::targetRenderableId() const {
return _targetRenderable->identifier();
}
std::string TargetBrowserPair::targetNodeId() const {
return _targetNode->identifier();
}
float TargetBrowserPair::browserRatio() const {
return _browser->browserRatio();
}
double TargetBrowserPair::verticalFov() const {
return _browser->verticalFov();
}
std::vector<int> TargetBrowserPair::selectedImages() const {
return _browser->selectedImages();
}
ghoul::Dictionary TargetBrowserPair::dataAsDictionary() const {
glm::dvec2 spherical = targetDirectionEquatorial();
glm::dvec3 cartesian = skybrowser::sphericalToCartesian(spherical);
ghoul::Dictionary res;
res.setValue("id", browserId());
res.setValue("name", browserGuiName());
res.setValue("fov", static_cast<double>(verticalFov()));
res.setValue("ra", spherical.x);
res.setValue("dec", spherical.y);
res.setValue("roll", targetRoll());
res.setValue("color", borderColor());
res.setValue("cartesianDirection", cartesian);
res.setValue("ratio", static_cast<double>(browserRatio()));
res.setValue("isFacingCamera", isFacingCamera());
res.setValue("isUsingRae", isUsingRadiusAzimuthElevation());
res.setValue("selectedImages", selectedImages());
res.setValue("scale", static_cast<double>(_browser->scale()));
res.setValue("opacities", _browser->opacities());
res.setValue("borderRadius", _browser->borderRadius());
std::vector<std::pair<std::string, glm::dvec3>> copies = displayCopies();
std::vector<std::pair<std::string, bool>> showCopies = _browser->showDisplayCopies();
ghoul::Dictionary copiesData;
for (size_t i = 0; i < copies.size(); i++) {
ghoul::Dictionary copy;
copy.setValue("position", copies[i].second);
copy.setValue("show", showCopies[i].second);
copy.setValue("idShowProperty", showCopies[i].first);
copiesData.setValue(copies[i].first, copy);
}
// Set table for the current target
res.setValue("displayCopies", copiesData);
return res;
}
void TargetBrowserPair::selectImage(const ImageData& image, int i) {
// Load image into browser
_browser->selectImage(image.imageUrl, i);
// If the image has coordinates, move the target
if (image.hasCelestialCoords) {
// Animate the target to the image coordinate position
glm::dvec3 galactic = skybrowser::equatorialToGalactic(image.equatorialCartesian);
startAnimation(galactic * skybrowser::CelestialSphereRadius, image.fov);
}
}
void TargetBrowserPair::addImageLayerToWwt(const std::string& url, int i) {
_browser->addImageLayerToWwt(url, i);
}
void TargetBrowserPair::removeSelectedImage(int i) {
_browser->removeSelectedImage(i);
}
void TargetBrowserPair::loadImageCollection(const std::string& collection) {
_browser->loadImageCollection(collection);
}
void TargetBrowserPair::setImageOpacity(int i, float opacity) {
_browser->setImageOpacity(i, opacity);
}
void TargetBrowserPair::hideChromeInterface() {
_browser->hideChromeInterface();
}
void TargetBrowserPair::sendIdToBrowser() const {
_browser->setIdInBrowser();
}
void TargetBrowserPair::updateBrowserSize() {
_browser->updateBrowserSize();
}
std::vector<std::pair<std::string, glm::dvec3>> TargetBrowserPair::displayCopies() const {
return _browser->displayCopies();
}
bool TargetBrowserPair::isImageCollectionLoaded() {
return _browser->isImageCollectionLoaded();
}
void TargetBrowserPair::setVerticalFov(double vfov) {
_browser->setVerticalFov(vfov);
_targetRenderable->setVerticalFov(vfov);
}
void TargetBrowserPair::setEquatorialAim(const glm::dvec2& aim) {
aimTargetGalactic(
skybrowser::equatorialToGalactic(skybrowser::sphericalToCartesian(aim))
);
_browser->setEquatorialAim(aim);
}
void TargetBrowserPair::setBorderColor(const glm::ivec3& color) {
_targetRenderable->setColor(color);
_browser->setBorderColor(color);
}
void TargetBrowserPair::setBorderRadius(double radius) {
_browser->setBorderRadius(radius);
_targetRenderable->setBorderRadius(radius);
}
void TargetBrowserPair::setBrowserRatio(float ratio) {
_browser->setRatio(ratio);
_targetRenderable->setRatio(ratio);
}
void TargetBrowserPair::setVerticalFovWithScroll(float scroll) {
_browser->setVerticalFovWithScroll(scroll);
}
void TargetBrowserPair::setImageCollectionIsLoaded(bool isLoaded) {
_browser->setImageCollectionIsLoaded(isLoaded);
}
void TargetBrowserPair::incrementallyAnimateToCoordinate() {
// Animate the target before the field of view starts to animate
if (_targetAnimation.isAnimating()) {
aimTargetGalactic(_targetAnimation.getNewValue());
}
else if (!_targetAnimation.isAnimating() && _targetIsAnimating) {
// Set the finished position
aimTargetGalactic(_targetAnimation.getNewValue());
_fovAnimation.start();
_targetIsAnimating = false;
}
if (_fovAnimation.isAnimating()) {
_browser->setVerticalFov(_fovAnimation.getNewValue());
_targetRenderable->setVerticalFov(_browser->verticalFov());
}
}
void TargetBrowserPair::startFading(float goal, float fadeTime) {
const std::string script = fmt::format(
"openspace.setPropertyValueSingle('Scene.{0}.Renderable.Fade', {2}, {3});"
"openspace.setPropertyValueSingle('ScreenSpace.{1}.Fade', {2}, {3});",
_targetNode->identifier(), _browser->identifier(), goal, fadeTime
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::RemoteScripting::Yes
);
}
void TargetBrowserPair::stopAnimations() {
_fovAnimation.stop();
_targetAnimation.stop();
}
void TargetBrowserPair::startAnimation(glm::dvec3 galacticCoords, double fovEnd) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
double fovSpeed = module->browserAnimationSpeed();
// The speed is given degrees /sec
double fovTime = abs(_browser->verticalFov() - fovEnd) / fovSpeed;
// Fov animation
_fovAnimation = skybrowser::Animation(_browser->verticalFov(), fovEnd, fovTime);
// Target animation
glm::dvec3 start = glm::normalize(_targetNode->worldPosition()) *
skybrowser::CelestialSphereRadius;
double targetSpeed = module->targetAnimationSpeed();
double angle = skybrowser::angleBetweenVectors(start, galacticCoords);
_targetAnimation = skybrowser::Animation(start, galacticCoords, angle / targetSpeed);
_targetAnimation.start();
_targetIsAnimating = true;
}
void TargetBrowserPair::centerTargetOnScreen() {
// Get camera direction in celestial spherical coordinates
glm::dvec3 viewDirection = skybrowser::cameraDirectionGalactic();
// Keep the current fov
double currentFov = verticalFov();
startAnimation(viewDirection, currentFov);
}
double TargetBrowserPair::targetRoll() const {
// To remove the lag effect when moving the camera while having a locked
// target, send the locked coordinates to wwt
glm::dvec3 normal = glm::normalize(
_targetNode->worldPosition() -
global::navigationHandler->camera()->positionVec3()
);
glm::dvec3 right = glm::normalize(
glm::cross(
global::navigationHandler->camera()->lookUpVectorWorldSpace(),
normal
)
);
glm::dvec3 up = glm::normalize(glm::cross(normal, right));
return skybrowser::targetRoll(up, normal);
}
bool TargetBrowserPair::isFacingCamera() const {
return _browser->isFacingCamera();
}
bool TargetBrowserPair::isUsingRadiusAzimuthElevation() const {
return _browser->isUsingRaeCoords();
}
SceneGraphNode* TargetBrowserPair::targetNode() const {
return _targetNode;
}
ScreenSpaceSkyBrowser* TargetBrowserPair::browser() const {
return _browser;
}
bool operator==(const TargetBrowserPair& lhs, const TargetBrowserPair& rhs) {
return lhs._targetNode == rhs._targetNode && lhs._browser == rhs._browser;
}
bool operator!=(const TargetBrowserPair& lhs, const TargetBrowserPair& rhs) {
return !(lhs == rhs);
}
} // namespace openspace