Page 7-3: Comparing Incremental Rotations

Page 7-3: Comparing Incremental Rotations

Box 1: A simple example that isn't so simple

The real learning goal of this page is to get you to think about axis angle representations. But to do that, I'll use the example we looked at in class: trying to understand what is going on in the first spinning cube demo we did (in class, but also in Workbook 6 on the first page).

The code is in 3-compare-simple.js (it's the same as in lecture, and on page 1 of workbook 6). The key lines are:

function animate() {
    cube.rotation.x += 0.01;
    cube.rotation.z += 0.01;
    renderer.render( scene, camera );
    requestAnimationFrame( animate );
}
animate();

Notice that this animation loop causes a somewhat wobbly and complicated motion, even though it moves through a simple progression in Euler Angles (.01,0,.01), (.02,0,.02), ... THREE's built in Euler Angles are XYZ.

What is going on here is that each time we change the X rotation, which changes the meaning of the Z rotation. So we don't get a simple motion as we might have liked.

For the first Euler angles, that first step would be: (rotation about X followed by a rotation about Z). If we wanted to continue another step, we could repeat that, composing those same rotations again. The left side of that inequality would be uniform steps. The right side is what we did when we just added to the Euler Angles. Since you read page one, you were reminded that just because , this doesn't work when there's a rotation about Z stuck in between.

Box 2: A Simpler Rotation

What if we wanted to keep rotating in the direction we started rotating in on that first step? We could on every frame apply the transformations. We could change the two angle additions to:

cube.rotateX(.01);
cube.rotateZ(.01);

But a thing to note is that this does not lead to a simple progression of the Euler Angles. In fact, after the second step, we would get a configuration that requires a bit of the Y rotation.

We can think of this as follows: the sequence of rotations and is equivalent to a single rotation about some other axis. (The Axis is the vector (.712,-0.0178,.712) if you really want to know - but I'll explain how to figure that out in a moment).

So, if we wanted to just keep spinning around that axis, we could instead write

cube.rotateOnAxis(axis,angle);

where axis is the vector we figured out before, and angle is an amount to rotate about that axis.

In the demo below, you can see these three different versions. For the Euler addition thing, you can see it wobbling all over the place. For the two rotation composition motions, you see the same consistent motion around an axis. I've drawn the axis as a white line to make it clearer. I've computed axis and angle to be the same step as the Euler increment. Over the course of many steps, you'll see they become a little bit different because of rounding errors.

Try starting from zero and going a step at a time. On the first step, all three are the same. But after that, notice how on each step, the Euler incrementing version has a simple increment of the Euler Angles, but the axis angle representation changes (the axis changes on each frame). In contrast, the other two (which, as expected, have the same motion) keep the same axis and step around it uniformly.

Now, you might wonder, given the Euler angles (like the step increment above) how do I convert it to axis angle? The good news is that THREE has a lot of code to help with doing these conversions. However, for this specific one, I first need to convert to a different form (called a Quaternion), because this is what THREE supports the best. In the code (file 3-compare-rot.js, by the way), you can see a function called "axisAngle" that converts an Euler Angle to axis angle form. It will make sense after we talk about Quaternions on the next page.

However, play with the rotation toy below before going on to the next page to learn about Quaternions.

After playing with the incremental comparison toy, go on to the next page where we'll see how we extend axis angle representations into Unit Quaternions.