Sign in to follow this  

Quaternion Interpolation - Camera 'Popping" during interpolation

Recommended Posts

gbMike    152
I'm having some difficulty replicating a bit of code, after switching from Euler, to Quaternions. The rotation value (a vec3) in my transform class, has each value (x, y, z) constrained between -180 and 180. So, if I was to rotate an object with 0 degrees rotation, 190 degrees, the new rotation would be -170.

My camera's transform needs to be rubber banded to the player. Heres how it was setup with Euler angles (This was called each frame):

vec3 posDif = coreTransform->getTranslation() - lastCoreTransform->getTranslation();
vec3 rotDif = coreTransform->getRotation() - lastCoreTransform->getRotation();

//Adjust values
if( rotDif.x > 180.0f )
rotDif.x -= 360;
if( rotDif.y > 180.0f )
rotDif.y -= 360;
if( rotDif.z > 180.0f )
rotDif.z -= 360;
if( rotDif.x < -180.0f )
rotDif.x += 360;
if( rotDif.y < -180.0f )
rotDif.y += 360;
if( rotDif.z < -180.0f )
rotDif.z += 360;

//reduce the position and rotation by a %
posDif *= 0.25f;
rotDif *= 0.5f;
vec3 newRot = -(lastCoreTransform->getRotation() + rotDif);
vec3 newPos = lastCoreTransform->getTranslation() + posDif;

Here, it is pretty easy to constrain the rotation difference. That way if last rotation was 170, and new rotation is -170, the difference will be the correct 20, rather than -340. So my question is, how do I replicate this with Quaternions? Here is the current interpolation code:

//Interpolate between this transform, and the passed in 'target'
Transform* Transform::interpolate( Transform *target, float rotMultiplier, float posMultiplier )
quat thisQuat = cdata->quaternion;
quat targetQuat = target->getQuat();
quat newRotQuat = glm::mix( thisQuat, targetQuat, rotMultiplier );

//check for infinities in return values
if ( newRotQuat.w <= FLT_MAX && newRotQuat.w >= -FLT_MAX)
//Number is real, within boudaries.
//then our quat has returned overflow numbers, either to large or too small
// -1.#IND or 1.#IND
newRotQuat = target->getQuat();

vec3 newRot = glm::eulerAngles( newRotQuat );

vec3 newPos = cdata->translation + ( (target->getTranslation() - cdata->translation ) * posMultiplier );

//create the new Transform, and pass in values
Transform *nTrans = new Transform();
//nTrans->setMatrix( newPos, newRot, vec3(1.0f, 1.0f, 1.0f) );
nTrans->setMatrix( vec3(0.0f,0.0f,0.0f), newRot, vec3(1.0f, 1.0f, 1.0f) );
return nTrans;

It causes the camera to start spinning wildly after a certain rotation is reached. How can I properly constrain the value like I used to, while the code for quaternion interpolation is handled through GLM? (glm::mix)

Alternatively, if anyone has a suggestion, for another way to add easing animation to the camera, I'd be interested in trying it. Edited by gbMike

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this