Add option to orbit at constant latitude

This commit is contained in:
Emma Broman
2021-07-09 09:34:30 +02:00
parent 2241673b15
commit 7ba319e52e
2 changed files with 50 additions and 5 deletions

View File

@@ -182,7 +182,8 @@ private:
struct IdleBehavior : public properties::PropertyOwner {
enum Behavior {
Orbit = 0
Orbit = 0,
OrbitAtConstantLat
};
IdleBehavior();
@@ -351,11 +352,21 @@ private:
glm::dquat& localRotation, glm::dquat& globalRotation);
/**
* IdleBehavior::Behavior::Orbit
* Orbit the current anchor node, in a right-bound orbit, by updating the position
* and global rotation of the camera
*/
void orbitAnchor(double deltaTime, glm::dvec3& position,
glm::dquat& globalRotation, double speedScale);
/**
* IdleBehavior::Behavior::OrbitAtConstantLat
* Orbit the current anchor node, but stay on the current latitude band. Note that
* this creates a rolling motion if looking at any of the anchor's poles, and should
* be used with care
*/
void orbitAtConstantLatitude(double deltaTime, glm::dvec3& position,
glm::dquat& globalRotation, double speedScale);
};
} // namespace openspace::interaction

View File

@@ -28,6 +28,7 @@
#include <openspace/util/updatestructures.h>
#include <openspace/query/query.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <cmath>
@@ -277,7 +278,8 @@ OrbitalNavigator::IdleBehavior::IdleBehavior()
{
addProperty(apply);
chosenBehavior.addOptions({
{ IdleBehavior::Behavior::Orbit, "Orbit" }
{ IdleBehavior::Behavior::Orbit, "Orbit" },
{ IdleBehavior::Behavior::OrbitAtConstantLat, "OrbitAtConstantLatitude" }
});
chosenBehavior = IdleBehavior::Behavior::Orbit;
addProperty(chosenBehavior);
@@ -1174,7 +1176,6 @@ OrbitalNavigator::interpolateRetargetAim(double deltaTime, CameraPose pose,
glm::dvec3 prevCameraToAnchor,
Displacement anchorToAim)
{
if (_retargetAimInterpolator.isInterpolating()) {
double t = _retargetAimInterpolator.value();
_retargetAimInterpolator.setDeltaTime(static_cast<float>(deltaTime));
@@ -1547,6 +1548,9 @@ void OrbitalNavigator::applyIdleBehavior(double deltaTime, glm::dvec3& position,
case IdleBehavior::Behavior::Orbit:
orbitAnchor(deltaTime, position, globalRotation, speedScale);
break;
case IdleBehavior::Behavior::OrbitAtConstantLat:
orbitAtConstantLatitude(deltaTime, position, globalRotation, speedScale);
break;
default:
throw ghoul::MissingCaseException();
}
@@ -1570,10 +1574,40 @@ void OrbitalNavigator::orbitAnchor(double deltaTime, glm::dvec3& position,
// Rotate to find the difference in position
const glm::dvec3 anchorCenterToCamera = position - _anchorNode->worldPosition();
const glm::dvec3 rotationDiffVec3 =
anchorCenterToCamera * rotationDiffWorldSpace -
anchorCenterToCamera;
anchorCenterToCamera * rotationDiffWorldSpace - anchorCenterToCamera;
position += rotationDiffVec3;
}
void OrbitalNavigator::orbitAtConstantLatitude(double deltaTime, glm::dvec3& position,
glm::dquat& globalRotation,
double speedScale)
{
ghoul_assert(_anchorNode != nullptr, "Node to orbit must be set!");
const glm::dmat4 modelTransform = _anchorNode->modelTransform();
// Assume north coincides with the local z-direction
// @TODO (2021-07-09, emmbr) Make each scene graph node aware of its own north/up, so
// that we can query this information rather than assuming it
const glm::dvec3 northInWorldCoords =
glm::dmat3(modelTransform) * glm::dvec3(0.0, 0.0, 1.0);
// Compute rotation around the north axis to be applied
double angle = deltaTime * speedScale;
const glm::dquat spinRotation =
glm::angleAxis(angle, glm::normalize(northInWorldCoords));
// Rotate the position vector from the center to camera and update position
const glm::dvec3 anchorCenterToCamera = position - _anchorNode->worldPosition();
const glm::dvec3 rotationDiffVec3 =
spinRotation * anchorCenterToCamera - anchorCenterToCamera;
position += rotationDiffVec3;
// Also apply the rotation to the global rotation, so the camera up vector is
// rotated around the axis as well
globalRotation = spinRotation * globalRotation;
}
} // namespace openspace::interaction