Tuesday, January 26, 2010

3D Rotation: Theory (Part II)

In the previous post, we found the equations for aligning an arbitrary vector with the z axis, in order to perform a rotation around that vector.  What we failed to determine, by the end of the discussion, was how to return the scene to its original coordinate space, so that only the object we rotated around the axis vector appeared to move.  We mentioned "undoing" the axis-alignment rotations, but didn't go into detail.

It turns out to be pretty simple.  Recall that we first made a clockwise rotation around the z axis, followed by a clockwise rotation around the y axis.  In order to return the scene to its original coordinate space, we need to first make a counter-clockwise rotation around the y axis, followed by a counter-clockwise rotation around the z axis.  Intuitively, the rotation angles are the same as those used for the axis-alignment rotations.  That is, to "undo" the rotation around the z axis, you must simply rotate in the opposite direction, through the original angle (only backwards).

It is possible to calculate new values of (x, y, z) for every point we want to rotate around the vector, using combinations of (and variations on) the equations from the previous post.  A given point's coordinates would have to be applied to each equation in turn, however, unless we could find some easy way to combine all of the equations, and apply that result to each of the points we want to rotate.

I mentioned before that the equations can be represented by matrices.  It turns out that matrices are ideal for these kinds of chain-transformations.  For our purposes, we could use 3x3 matrices for all of our rotational needs.  However, if we wished to represent any translation transformations in matrix form, a 3x3 matrix is not sufficient.   Consider the z component of a translation: z` = z + zt.  In a 3x3 matrix representation, it is impossible to represent z except in terms of x and y.  With a 4x4 matrix, however, the translation is easy to find:
That bottom row deals with something called homogeneous coordinates, which basically means we're representing our three-dimensional world in a four-dimensional space, with a fixed fourth coordinate (much like how we moved our rotations into a two-dimensional problem within three-dimensional space).  For our purposes, we'll avoid tweaking that row as much as possible.

It is also easy to find the matrices for rotation around each of the standard axes, using the two-dimensional rotation equations we found previously:
We use the same equations for rotation around the y axis, substituting z for x and x for y:
The same technique applies to rotation around the x axis, substituting y for x and z for y:
Remember that, in order to perform a clockwise rotation (which is how we'll be moving our axis vector) the sign of each of the sin terms will need to be switched.

In the previous post, we found the angles of rotation (in terms of u, v and w) required to align the axis vector with the z axis.  With a minor variation, we can plug those values into the (inverted) rotation matrices:

Here's the variation:

Now that we've got our matrices defined, we need to understand how to use them.  If Rz is the matrix representing the rotation around the z axis, and P is a point we're rotating (represented as a 4x1 matrix), then RzP is the product of the two matrices (resulting in P`--our new point).  We can continue the chain, to rotate around the y axis (using the rotation matrix around y, Ry): RyP` = Ry(RzP).

One property of matrices is that they're associative in multiplication, so Ry(RzP) = (RyRz)P.

The matrix multiplication RyRz is the transformation to align our axis vector with the z axis.  We can take the result of that transformation, and add on the rotation about the axis vector, R: (RRyRz)P.

Once again, we have reached the point at which we need to "undo" our initial rotation transformations, in order to return the scene to its original coordinate space.  The last rotation we performed which we want to undo is the rotation around the y axis, Ry.  The transformation to undo that rotation, we'll call Ry-1.  Appending that operation gives us (Ry-1RRyRz)P.  Likewise, the transformation to undo the original rotation, we'll call Rz-1, so (Rz-1Ry-1RRyRz)P.  So the full transformation we need to apply to each point we're rotating is Rz-1Ry-1RRyRz.

We're using a common matrix notation to denote an inverse transformation.  In the case of a rotation, an inverse is simply the rotation through the same angle, though in the opposite direction (so we switch the signs of each sine in our matrix).  It turns out that the matrix for the opposite rotation is the inverse matrix for the original rotation.  Mathematically, A-1A = AA-1 = I, where A is an invertible square matrix, and I is the identity matrix.  There are many matrix tutorials online, so I won't bother to explain these terms.

For our inverted rotation matrices, Rz-1 and Ry-1,  we can plug in the values for the rotation angles, using a counter-clockwise rotation (remember we used a clockwise rotation above).

Once we have all of our matrices figured out, we can multiply them all together (in sequence--order is important) to obtain a single transformation matrix, T.  We can multiply each point we wish to rotate (every vertex of a complex object, for example) by T to obtain their new positions in the original coordinate space.

No comments:

Post a Comment