Add smooth transition when resetting camera direction.

This commit is contained in:
kalbl
2016-10-05 01:47:49 +02:00
parent da947cab7e
commit 6ef366afdd
3 changed files with 60 additions and 29 deletions

View File

@@ -710,30 +710,7 @@ void InteractionHandler::setCamera(Camera* camera) {
void InteractionHandler::resetCameraDirection() {
LINFO("Setting camera direction to point at focus node.");
glm::dquat rotation = _camera->rotationQuaternion();
glm::dvec3 focusPosition = focusNode()->worldPosition();
glm::dvec3 cameraPosition = _camera->positionVec3();
glm::dvec3 lookUpVector = _camera->lookUpVectorWorldSpace();
glm::dvec3 directionToFocusNode = glm::normalize(focusPosition - cameraPosition);
// To make sure the lookAt function won't fail
static const double epsilon = 0.000001;
if (glm::dot(lookUpVector, directionToFocusNode) > 1.0 - epsilon) {
// Change the look up vector a little bit
lookUpVector = glm::normalize(lookUpVector + glm::dvec3(epsilon));
}
// Create the rotation to look at focus node
glm::dmat4 lookAtMat = glm::lookAt(
glm::dvec3(0, 0, 0),
directionToFocusNode,
lookUpVector);
glm::dquat rotationLookAtFocusNode = normalize(quat_cast(inverse(lookAtMat)));
// Update camera Rotation
_camera->setRotation(rotationLookAtFocusNode);
_currentInteractionMode->rotateToFocusNodeInterpolator().start();
}
void InteractionHandler::setInteractionMode(std::shared_ptr<InteractionMode> interactionMode) {

View File

@@ -153,7 +153,10 @@ namespace interaction {
InteractionMode::InteractionMode() {
InteractionMode::InteractionMode()
: _rotateToFocusNodeInterpolator(Interpolator<double>([](double t){
return pow(t, 2);
})) {
}
@@ -174,6 +177,11 @@ SceneGraphNode* InteractionMode::focusNode() {
return _focusNode;
}
Interpolator<double>& InteractionMode::rotateToFocusNodeInterpolator() {
return _rotateToFocusNodeInterpolator;
};
// KeyframeInteractionMode
KeyframeInteractionMode::KeyframeInteractionMode(){
@@ -319,10 +327,11 @@ glm::dvec2 OrbitalInteractionMode::MouseStates::synchedGlobalRollMouseVelocity()
return _globalRollMouseState.velocity.get();
}
OrbitalInteractionMode::OrbitalInteractionMode(std::shared_ptr<MouseStates> mouseStates)
OrbitalInteractionMode::OrbitalInteractionMode(
std::shared_ptr<MouseStates> mouseStates)
: InteractionMode()
, _mouseStates(mouseStates){
, _mouseStates(mouseStates) {
}
OrbitalInteractionMode::~OrbitalInteractionMode() {
@@ -367,12 +376,23 @@ void OrbitalInteractionMode::updateCameraStateFromMouseStates(Camera& camera) {
glm::angleAxis(_mouseStates->synchedLocalRollMouseVelocity().x, dvec3(0, 0, 1));
localCameraRotation = localCameraRotation * cameraRollRotation;
}
if (!_rotateToFocusNodeInterpolator.isInterpolating())
{ // Do local rotation
dvec3 eulerAngles(_mouseStates->synchedLocalRotationMouseVelocity().y, _mouseStates->synchedLocalRotationMouseVelocity().x, 0);
dquat rotationDiff = dquat(eulerAngles);
localCameraRotation = localCameraRotation * rotationDiff;
}
else
{ // Interpolate local rotation to focus node
double t = _rotateToFocusNodeInterpolator.value();
localCameraRotation = slerp(localCameraRotation, dquat(dvec3(0.0)), t);
_rotateToFocusNodeInterpolator.step(0.002); // Should probably depend on dt
// This is a fast but ugly solution to slow regaining of control...
if (t > 0.18) {
_rotateToFocusNodeInterpolator.end();
}
}
{ // Do global rotation
dvec2 smoothMouseVelocity = _mouseStates->synchedGlobalRotationMouseVelocity();
dvec3 eulerAngles(-smoothMouseVelocity.y, -smoothMouseVelocity.x, 0);
@@ -519,12 +539,23 @@ void GlobeBrowsingInteractionMode::updateCameraStateFromMouseStates(Camera& came
glm::angleAxis(_mouseStates->synchedLocalRollMouseVelocity().x, dvec3(0, 0, 1));
localCameraRotation = localCameraRotation * cameraRollRotation;
}
if(!_rotateToFocusNodeInterpolator.isInterpolating())
{ // Do local rotation
glm::dvec3 eulerAngles(_mouseStates->synchedLocalRotationMouseVelocity().y, _mouseStates->synchedLocalRotationMouseVelocity().x, 0);
glm::dquat rotationDiff = glm::dquat(eulerAngles);
localCameraRotation = localCameraRotation * rotationDiff;
}
else
{ // Interpolate local rotation to focus node
double t = _rotateToFocusNodeInterpolator.value();
localCameraRotation = slerp(localCameraRotation, dquat(dvec3(0.0)), t);
_rotateToFocusNodeInterpolator.step(0.002); // Should probably depend on dt
// This is a fast but ugly solution to slow regaining of control...
if (t > 0.2) {
_rotateToFocusNodeInterpolator.end();
}
}
{ // Do global rotation (horizontal movement)
glm::dvec3 eulerAngles = glm::dvec3(
-_mouseStates->synchedGlobalRotationMouseVelocity().y,