mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-03-03 02:48:32 -06:00
Feature/anchor and aim (#799)
Introduce the ability to navigate using an anchor and aim. Example use: Set spacecraft as anchor and planet as aim to always look down at a planet, while followin the spacecraft in its orbit.
This commit is contained in:
@@ -55,9 +55,7 @@ public:
|
||||
void deinitialize();
|
||||
|
||||
// Mutators
|
||||
void setFocusNode(SceneGraphNode* node);
|
||||
void setCamera(Camera* camera);
|
||||
void resetCameraDirection();
|
||||
void setInterpolationTime(float durationInSeconds);
|
||||
|
||||
void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict);
|
||||
@@ -69,12 +67,10 @@ public:
|
||||
|
||||
// Accessors
|
||||
ghoul::Dictionary cameraStateDictionary();
|
||||
SceneGraphNode* focusNode() const;
|
||||
glm::dvec3 focusNodeToCameraVector() const;
|
||||
glm::quat focusNodeToCameraRotation() const;
|
||||
Camera* camera() const;
|
||||
const InputState& inputState() const;
|
||||
const OrbitalNavigator& orbitalNavigator() const;
|
||||
OrbitalNavigator& orbitalNavigator();
|
||||
KeyframeNavigator& keyframeNavigator() const;
|
||||
bool isKeyFrameInteractionEnabled() const;
|
||||
float interpolationTime() const;
|
||||
@@ -126,7 +122,6 @@ private:
|
||||
std::unique_ptr<OrbitalNavigator> _orbitalNavigator;
|
||||
std::unique_ptr<KeyframeNavigator> _keyframeNavigator;
|
||||
|
||||
properties::StringProperty _origin;
|
||||
properties::BoolProperty _useKeyFrameInteraction;
|
||||
};
|
||||
|
||||
|
||||
@@ -31,8 +31,10 @@
|
||||
#include <openspace/interaction/interpolator.h>
|
||||
#include <openspace/interaction/joystickcamerastates.h>
|
||||
#include <openspace/interaction/mousecamerastates.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
@@ -51,28 +53,46 @@ public:
|
||||
OrbitalNavigator();
|
||||
|
||||
void updateStatesFromInput(const InputState& inputState, double deltaTime);
|
||||
void updateCameraStateFromStates(Camera& camera, double deltaTime);
|
||||
void updateCameraStateFromStates(double deltaTime);
|
||||
|
||||
void setFocusNode(SceneGraphNode* focusNode);
|
||||
void startInterpolateCameraDirection(const Camera& camera);
|
||||
float rotateToFocusInterpolationTime() const;
|
||||
void setRotateToFocusInterpolationTime(float durationInSeconds);
|
||||
Camera* camera() const;
|
||||
void setCamera(Camera* camera);
|
||||
|
||||
void setFocusNode(const std::string& focusNode);
|
||||
void setAnchorNode(const std::string& anchorNode);
|
||||
void setAimNode(const std::string& aimNode);
|
||||
|
||||
void startRetargetAnchor();
|
||||
void startRetargetAim();
|
||||
float retargetInterpolationTime() const;
|
||||
void setRetargetInterpolationTime(float durationInSeconds);
|
||||
|
||||
JoystickCameraStates& joystickStates();
|
||||
|
||||
bool followingNodeRotation() const;
|
||||
SceneGraphNode* focusNode() const;
|
||||
const SceneGraphNode* anchorNode() const;
|
||||
const SceneGraphNode* aimNode() const;
|
||||
|
||||
bool hasRotationalFriction() const;
|
||||
bool hasZoomFriction() const;
|
||||
bool hasRollFriction() const;
|
||||
|
||||
glm::dvec3 anchorNodeToCameraVector() const;
|
||||
glm::quat anchorNodeToCameraRotation() const;
|
||||
|
||||
private:
|
||||
struct CameraRotationDecomposition {
|
||||
glm::dquat localRotation;
|
||||
glm::dquat globalRotation;
|
||||
};
|
||||
|
||||
struct CameraPose {
|
||||
glm::dvec3 position;
|
||||
glm::dquat rotation;
|
||||
};
|
||||
|
||||
using Displacement = std::pair<glm::dvec3, glm::dvec3>;
|
||||
|
||||
struct Friction : public properties::PropertyOwner {
|
||||
Friction();
|
||||
|
||||
@@ -83,9 +103,28 @@ private:
|
||||
properties::FloatProperty friction;
|
||||
};
|
||||
|
||||
void setFocusNode(const SceneGraphNode* focusNode);
|
||||
void setAnchorNode(const SceneGraphNode* anchorNode);
|
||||
void setAimNode(const SceneGraphNode* aimNode);
|
||||
|
||||
Camera* _camera;
|
||||
|
||||
Friction _friction;
|
||||
|
||||
properties::FloatProperty _followFocusNodeRotationDistance;
|
||||
// Anchor: Node to follow and orbit.
|
||||
properties::StringProperty _anchor;
|
||||
|
||||
// Aim: Node to look at (when camera direction is reset),
|
||||
// Empty string means same as anchor.
|
||||
// If these are the same node we call it the `focus` node.
|
||||
properties::StringProperty _aim;
|
||||
|
||||
// Reset camera direction to the anchor node.
|
||||
properties::TriggerProperty _retargetAnchor;
|
||||
// Reset camera direction to the aim node.
|
||||
properties::TriggerProperty _retargetAim;
|
||||
|
||||
properties::FloatProperty _followAnchorNodeRotationDistance;
|
||||
properties::FloatProperty _minimumAllowedDistance;
|
||||
|
||||
properties::FloatProperty _mouseSensitivity;
|
||||
@@ -95,33 +134,64 @@ private:
|
||||
properties::FloatProperty _stereoscopicDepthOfFocusSurface;
|
||||
properties::FloatProperty _staticViewScaleExponent;
|
||||
|
||||
properties::FloatProperty _rotateToFocusInterpolationTime;
|
||||
properties::FloatProperty _retargetInterpolationTime;
|
||||
properties::FloatProperty _stereoInterpolationTime;
|
||||
properties::FloatProperty _followRotationInterpolationTime;
|
||||
|
||||
MouseCameraStates _mouseStates;
|
||||
JoystickCameraStates _joystickStates;
|
||||
|
||||
SceneGraphNode* _focusNode = nullptr;
|
||||
glm::dvec3 _previousFocusNodePosition;
|
||||
glm::dquat _previousFocusNodeRotation;
|
||||
const SceneGraphNode* _anchorNode = nullptr;
|
||||
const SceneGraphNode* _aimNode = nullptr;
|
||||
|
||||
glm::dvec3 _previousAnchorNodePosition;
|
||||
glm::dquat _previousAnchorNodeRotation;
|
||||
|
||||
glm::dvec3 _previousAimNodePosition;
|
||||
glm::dquat _previousAimNodeRotation;
|
||||
|
||||
double _currentCameraToSurfaceDistance = 0.0;
|
||||
bool _directlySetStereoDistance = false;
|
||||
|
||||
Interpolator<double> _rotateToFocusNodeInterpolator;
|
||||
Interpolator<double> _retargetAimInterpolator;
|
||||
Interpolator<double> _retargetAnchorInterpolator;
|
||||
Interpolator<double> _cameraToSurfaceDistanceInterpolator;
|
||||
Interpolator<double> _followRotationInterpolator;
|
||||
|
||||
/**
|
||||
* Decomposes the cameras rotation in to a global and a local rotation defined by
|
||||
* Decomposes the camera's rotation in to a global and a local rotation defined by
|
||||
* CameraRotationDecomposition. The global rotation defines the rotation so that the
|
||||
* camera points towards the focus node in the direction opposite to the direction
|
||||
* camera points towards the reference node in the direction opposite to the direction
|
||||
* out from the surface of the object. The local rotation defines the differential
|
||||
* from the global to the current total rotation so that
|
||||
* <code>cameraRotation = globalRotation * localRotation</code>.
|
||||
*/
|
||||
CameraRotationDecomposition decomposeCameraRotation(const glm::dvec3& cameraPosition,
|
||||
const glm::dquat& cameraRotation, const glm::dvec3& cameraLookUp,
|
||||
const glm::dvec3& cameraViewDirection);
|
||||
CameraRotationDecomposition decomposeCameraRotationSurface(const CameraPose pose,
|
||||
const SceneGraphNode& reference);
|
||||
|
||||
/**
|
||||
* Decomposes the camera's rotation in to a global and a local rotation defined by
|
||||
* CameraRotationDecomposition. The global rotation defines the rotation so that the
|
||||
* camera points towards the reference node's origin.
|
||||
* The local rotation defines the differential from the global to the current total
|
||||
* rotation so that <code>cameraRotation = globalRotation * localRotation</code>.
|
||||
*/
|
||||
CameraRotationDecomposition decomposeCameraRotation(const CameraPose pose,
|
||||
glm::dvec3 reference);
|
||||
|
||||
/**
|
||||
* Composes a pair of global and local rotations into a quaternion that can be used
|
||||
* as the world rotation for a camera.
|
||||
*/
|
||||
glm::dquat composeCameraRotation(const CameraRotationDecomposition& composition);
|
||||
|
||||
/*
|
||||
* Moves and rotates the camera around the anchor node in order to maintain the
|
||||
* screen space position of the aim node. Also interpolates to the aim node, when
|
||||
* retargeting the aim.
|
||||
*/
|
||||
CameraPose followAim(CameraPose pose, glm::dvec3 cameraToAnchor,
|
||||
Displacement anchorToAim);
|
||||
|
||||
/*
|
||||
* Perform a camera roll on the local camera rotation
|
||||
@@ -137,47 +207,47 @@ private:
|
||||
const glm::dquat& localCameraRotation) const;
|
||||
|
||||
/**
|
||||
* Interpolates the local rotation towards a 0 rotation.
|
||||
* \returns a modified local rotation interpolated towards 0.
|
||||
* Interpolates the camera rotation based on active interpolators.
|
||||
* \returns a new rotation quaternion
|
||||
*/
|
||||
glm::dquat interpolateLocalRotation(double deltaTime,
|
||||
const glm::dquat& localCameraRotation);
|
||||
|
||||
|
||||
double interpolateCameraToSurfaceDistance(double deltaTime,
|
||||
double currentDistance,
|
||||
double targetDistance);
|
||||
Displacement interpolateRetargetAim(double deltaTime, CameraPose pose,
|
||||
glm::dvec3 cameraToAnchor, Displacement anchorToAim);
|
||||
|
||||
double interpolateCameraToSurfaceDistance(double deltaTime, double currentDistance,
|
||||
double targetDistance);
|
||||
|
||||
/**
|
||||
* Translates the horizontal direction. If far from the focus object, this will
|
||||
* Translates the horizontal direction. If far from the anchor object, this will
|
||||
* result in an orbital rotation around the object. This function does not affect the
|
||||
* rotation but only the position.
|
||||
* \returns a position vector adjusted in the horizontal direction.
|
||||
*/
|
||||
glm::dvec3 translateHorizontally(double deltaTime, const glm::dvec3& cameraPosition,
|
||||
const glm::dvec3& objectPosition, const glm::dquat& focusNodeRotationDiff,
|
||||
const glm::dquat& globalCameraRotation,
|
||||
const glm::dvec3& objectPosition, const glm::dquat& globalCameraRotation,
|
||||
const SurfacePositionHandle& positionHandle) const;
|
||||
|
||||
/*
|
||||
* Adds rotation to the camera position so that it follows the rotation of the focus
|
||||
* node defined by the differential focusNodeRotationDiff.
|
||||
* \returns a position updated with the rotation defined by focusNodeRotationDiff
|
||||
* Adds rotation to the camera position so that it follows the rotation of the anchor
|
||||
* node defined by the differential anchorNodeRotationDiff.
|
||||
* \returns a position updated with the rotation defined by anchorNodeRotationDiff
|
||||
*/
|
||||
glm::dvec3 followFocusNodeRotation(const glm::dvec3& cameraPosition,
|
||||
const glm::dvec3& objectPosition, const glm::dquat& focusNodeRotationDiff) const;
|
||||
glm::dvec3 followAnchorNodeRotation(const glm::dvec3& cameraPosition,
|
||||
const glm::dvec3& objectPosition, const glm::dquat& anchorNodeRotationDiff) const;
|
||||
|
||||
/**
|
||||
* Updates the global rotation so that it points towards the focus node.
|
||||
* \returns a global rotation quaternion defining a rotation towards the focus node.
|
||||
* Updates the global rotation so that it points towards the anchor node.
|
||||
* \returns a global rotation quaternion defining a rotation towards the anchor node.
|
||||
*/
|
||||
glm::dquat rotateGlobally(const glm::dquat& globalCameraRotation,
|
||||
const glm::dvec3& objectPosition, const glm::dquat& focusNodeRotationDiff,
|
||||
const glm::dvec3& cameraPosition,
|
||||
const glm::dquat& aimNodeRotationDiff,
|
||||
const SurfacePositionHandle& positionHandle) const;
|
||||
|
||||
/**
|
||||
* Translates the camera position towards or away from the focus node.
|
||||
* Translates the camera position towards or away from the anchor node.
|
||||
* \returns a position vector adjusted in the vertical direction.
|
||||
*/
|
||||
glm::dvec3 translateVertically(double deltaTime, const glm::dvec3& cameraPosition,
|
||||
@@ -189,7 +259,7 @@ private:
|
||||
* \returns a quaternion adjusted to rotate around the out vector of the surface.
|
||||
*/
|
||||
glm::dquat rotateHorizontally(double deltaTime,
|
||||
const glm::dquat& globalCameraRotation, const glm::dvec3& cameraPosition,
|
||||
const glm::dquat& globalCameraRotation,
|
||||
const SurfacePositionHandle& positionHandle) const;
|
||||
|
||||
/**
|
||||
@@ -210,17 +280,15 @@ private:
|
||||
const SurfacePositionHandle& positionHandle);
|
||||
|
||||
/**
|
||||
* Get the vector from the camera to the surface of the focus object in world space.
|
||||
* Get the vector from the camera to the surface of the anchor object in world space.
|
||||
*/
|
||||
glm::dvec3 cameraToSurfaceVector(
|
||||
const glm::dvec3& cameraPos,
|
||||
const glm::dvec3& centerPos,
|
||||
const SurfacePositionHandle& posHandle);
|
||||
glm::dvec3 cameraToSurfaceVector(const glm::dvec3& cameraPos,
|
||||
const glm::dvec3& centerPos, const SurfacePositionHandle& posHandle);
|
||||
|
||||
/**
|
||||
* Calculates a SurfacePositionHandle given a camera position in world space.
|
||||
*/
|
||||
SurfacePositionHandle calculateSurfacePositionHandle(
|
||||
SurfacePositionHandle calculateSurfacePositionHandle(const SceneGraphNode& node,
|
||||
const glm::dvec3 cameraPositionWorldSpace);
|
||||
};
|
||||
|
||||
|
||||
@@ -96,7 +96,6 @@ public:
|
||||
void traversePostOrder(const std::function<void(SceneGraphNode*)>& fn);
|
||||
void update(const UpdateData& data);
|
||||
void render(const RenderData& data, RendererTasks& tasks);
|
||||
void updateCamera(Camera* camera) const;
|
||||
|
||||
void attachChild(std::unique_ptr<SceneGraphNode> child);
|
||||
std::unique_ptr<SceneGraphNode> detachChild(SceneGraphNode& child);
|
||||
@@ -109,7 +108,7 @@ public:
|
||||
void setDependencies(const std::vector<SceneGraphNode*>& dependencies);
|
||||
|
||||
SurfacePositionHandle calculateSurfacePositionHandle(
|
||||
const glm::dvec3& targetModelSpace);
|
||||
const glm::dvec3& targetModelSpace) const;
|
||||
|
||||
const std::vector<SceneGraphNode*>& dependencies() const;
|
||||
const std::vector<SceneGraphNode*>& dependentNodes() const;
|
||||
|
||||
@@ -72,7 +72,6 @@ public:
|
||||
|
||||
// Mutators
|
||||
void setPositionVec3(glm::dvec3 pos);
|
||||
void setFocusPositionVec3(glm::dvec3 pos);
|
||||
void setRotation(glm::dquat rotation);
|
||||
void setScaling(float scaling);
|
||||
void setMaxFov(float fov);
|
||||
@@ -86,7 +85,6 @@ public:
|
||||
const glm::dvec3& positionVec3() const;
|
||||
glm::dvec3 eyePositionVec3() const;
|
||||
const glm::dvec3& unsynchedPositionVec3() const;
|
||||
const glm::dvec3& focusPositionVec3() const;
|
||||
const glm::dvec3& viewDirectionWorldSpace() const;
|
||||
const glm::dvec3& lookUpVectorCameraSpace() const;
|
||||
const glm::dvec3& lookUpVectorWorldSpace() const;
|
||||
@@ -138,18 +136,6 @@ public:
|
||||
mutable std::mutex _mutex;
|
||||
} sgctInternal;
|
||||
|
||||
// Deprecated
|
||||
// [[deprecated("Replaced by Camera::setPositionVec3()")]]
|
||||
void setPosition(psc pos);
|
||||
// [[deprecated("Replaced by Camera::setFocusPositionVec3()")]]
|
||||
void setFocusPosition(psc pos);
|
||||
// [[deprecated("Replaced by Camera::positionVec3()")]]
|
||||
psc position() const;
|
||||
// [[deprecated("Replaced by Camera::unsynchedPositionVec3()")]]
|
||||
psc unsynchedPosition() const;
|
||||
// [[deprecated("Replaced by Camera::focusPositionVec3()")]]
|
||||
psc focusPosition() const;
|
||||
const glm::mat4& sceneMatrix() const;
|
||||
// @TODO use Camera::SgctInternal interface instead
|
||||
// [[deprecated("Replaced by Camera::SgctInternal::viewMatrix()")]]
|
||||
const glm::mat4& viewMatrix() const;
|
||||
@@ -160,10 +146,11 @@ public:
|
||||
|
||||
std::vector<Syncable*> getSyncables();
|
||||
|
||||
private:
|
||||
// Static constants
|
||||
static const glm::dvec3 ViewDirectionCameraSpace;
|
||||
static const glm::dvec3 LookupVectorCameraSpace;
|
||||
static const glm::dvec3 UpDirectionCameraSpace;
|
||||
|
||||
private:
|
||||
|
||||
SyncData<glm::dvec3> _position = glm::dvec3(1.0, 1.0, 1.0);
|
||||
SyncData<glm::dquat> _rotation = glm::dquat(glm::dvec3(1.0, 1.0, 1.0));
|
||||
|
||||
Reference in New Issue
Block a user