Using the Cinder timeline to rotate something more than 180 degrees

Hey Embers,

I’ve started using the sweet timeline feature in Cinder to animate some text. However, I’ve hit a small snag. I’ve not really figured out if it’s possible to rotate anything using a quarternion more than 180 degrees with just a line of code or two, like so:

auto tempQuat = ci::quat();
tempQuat = glm::rotate( tempQuat, ci::toRadians( 800 ), { 0.0f, 1.0f, 0.0f } );
ci::app::timeline().apply( &refToBatch.animRotation, tempQuat, 1.0f );

Instead this will rotate (as far as I know) the object to an angle more along the lines of 800 % 360. I have a vague idea of why, but I honestly am just keen to know if someone knows a way around it that doesn’t look like this:

auto tempQuat = ci::quat();
tempQuat = glm::rotate( tempQuat, ci::toRadians( 180 ), { 0.0f, 1.0f, 0.0f } );
ci::app::timeline().apply( &refToBatch.animRotation, tempQuat, 1.0f );

tempQuat = glm::rotate( tempQuat, ci::toRadians( 180 ), { 0.0f, 1.0f, 0.0f } );
ci::app::timeline().appendTo( &refToBatch.animRotation, tempQuat, 1.0f );

tempQuat = glm::rotate( tempQuat, ci::toRadians( 180 ), { 0.0f, 1.0f, 0.0f } );
ci::app::timeline().appendTo( &refToBatch.animRotation, tempQuat, 1.0f );

180 is seemingly the largest number to rotate before we rotate the other way :E

Thanks in advance!

Cheers,

Gazoo

Hi,

you’re making the same mistake again. Like matrices, quaternions can not be interpolated using the formula a + t * ( b - a ) (where a and b are quaternions and t is a float).

Use an Anim<float> mRadians instead.

-Paul

The matrices I had a suspicion about - the quarternions I didn’t. I guess fool me twice, shame on me applies here.

Consider me shamed :E

Thanks for the help @paul.houx

I believe the timeline allows you to pass a custom lerp function, so if i’m not mistaken you could use slerp to interpolate between the quaternions?

*edit hmm, appears there’s already a quaternion template specialization for lerp<T> that uses slerp. Ignore my prattling.

The rotations now behave as intended, however, there’s one point that still puzzles me a bit.

Rotations aren’t commutative (thanks to this sweet gif).

So if we rotate around x, y, z there are 6 different orders of permutation and each will effectively achieve a different rotational outcome. I’m trying to figure out a smart way to use Timeline and Anim to allow the the flexibility using either of the 6 permutations. One ugly way would be to maintain a x,y,z rotation value for each of the 6 permutations and subsequently only change the numbers (from 0 to something else) on the rotations intended. In essence, all 6 permutations would be applied but only the ones you alter will provide you with something other than the identity matrix.

Hopefully what I’m trying to say is clear.

In any case, my idea feels super clunky but I’ve not come up with a better simpler one thus far. Any ideas are welcome.

Cheers,

Gazoo

Hi Gazoo,

it’s true that rotations aren’t commutative and the order is important. For that purpose, quaternions were invented. One way to look at quaternions, is that they encode a rotation around an arbitrary axis. What you could do, is animate both the axis and angle over time. Just make sure to normalize the axis before using it and to use radians for the angle.

You can then call: const quat rotation = glm::angleAxis( radians, axis );

And if you need a matrix from that (not always necessary), use glm::toMat4( rotation ).

-Paul

P.S.: one way to come up with an axis is to move two points a and b in space, then do axis = glm::normalize( b - a ).