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:
Emil Axelsson
2019-02-19 18:46:58 +01:00
committed by GitHub
parent df9fbf8195
commit 2e71eaa4cb
45 changed files with 972 additions and 490 deletions

View File

@@ -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;
};

View File

@@ -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);
};

View File

@@ -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;

View File

@@ -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));