Matrix Transformation

Introduction

Any 3D developer ought to understand the essential mathematics behind transformations. Although the math looks complicated, it really isn't too bad, once you get past the unfamiliar notation.

Points and Vectors

You have been using the term vector quite a bit. It is used to describe a point in 2D or 3D space, and alternatively a line segment between the origin and that point. The term also has a mathematical definition. A vector in 3D geometry would consist of three floats, usually arranged like this:
 _   _
|     |
|  x  |
|     |
|  y  |
|     |
|  z  |
|_   _|
The nice thing about thinking about a point as a vector is there are certain mathematical properties associated with vectors. If you use the computer to apply these principles, you can generate any kind of transformation you wish.

Translation

Essentially, translation refers to adding a vector to each point in a shape. Imagine a point at (0, 0, 0). If you wanted to translate that point up one unit, you could convert the point to a vector and add it to another vector, like this:
 _   _      _   _      _   _
|     |    |     |    |	    |
|  0  |    |  0  |    |	 0  |
|     |    |     |    |	    |
|  0  | +  |  1	 | =  |	 1  |
|     |    |  	 |    |	    |
|  0  |    |  0  |    |	 0  |
|_   _|    |_   _|    |_   _|

In essence, translating an object amounts to adding a vector to each point in the object.

Scaling

If translating an object means adding each point to a vector, scaling could be seen as a multiplying function. For example, if you have a circle with a point at (0, 1, 0) and another point at (1, 0, 0), you could make the circle twice as large by multiplying each x, y, and z value by 2. The resulting calculation would look something like this:
 _   _               _   _              _   _               _   _
|     |             |     |            |     |             |     |
|  0  |             |  0  |            |  1  |             |  2  |
|     |             |     |            |     |             |     |
|  1  |   * 2  =    |  2  |            |  0  |   * 2  =    |  0  |
|     |             |     |            |     |             |     |
|  0  |             |  0  |            |  0  |             |  0  |
|_   _|             |_   _|            |_   _|             |_   _|

In fact, you can actually scale in X, Y, and Z axes independantly. Most 3D packages allow you to specify a vector for scaling which separately indicates how much you scale in each axis. Although it's not exactly done this way mathematically, you can think of multiplying two vectors together for a scale, so if you have a point (2, 2, 2) and you want to scale it by (3, 4, 5), you could (somewhat inaccurately) think of it like this...
 _   _ 	      _   _        _   _
|     |	     |     |      |     |
|  2  |	     |  3  |      |  6  |
|     |	     |     |      |     |
|  2  |	 *   |  4  |   =  |  8  |
|     |	     |     |  	  |     |
|  2  |	     |  5  |   	  |  10 |
|_   _|      |_   _|      |_   _|

Please note that this is NOT exactly how it's done. However, I have simplified the math to make the concept a little easier to understand. In reality, the scale is usually done with either a single value, one direction at a time, or in a 3 x 3 matrix. Since I haven't shown you matrices yet, I'm simplifying the math. See any linear algebra book for the complete truth.

Two - Dimension Rotation

To perform a rotation around the origin in two dimensions, mathematicians have come up with a series of trig formulas. Let's say we have a point at (x, y) and we want to rotate the point by a radians. The new x and y values can be determined by the following formulas:
x' = (x * cos(a)) + (y * -sin(a))
y' = (x * sin(a)) + (y * cos(a))
Given any x, y, and a values, you can use these formulas to generate a new point x'y' that is rotated a radians around the origin. For example, consider the following situation: You have a point at (1, 1) and you want to rotate it 90 degrees (pi/2 radians).

By observation, you can probably tell that the result should be (-1, 1). cos(pi/2) is 0, and sin(pi/2) is 1. Use a calculator to confirm these results if necessary. Now, you can replace the variables with the appropriate values:
x' = (x * cos(a)) + (y * -sin(a))
   = (1 * 0)      + (1 * -1)
   = 0 - 1
   = -1


y' = (x * sin(a)) + (y * cos(a))
   = (1 * 1)      + (1 * 0)
   = 1 + 0
   = 1

(x', y') = (-1,1)

3D Rotations

To consider 3D rotation around the Z axis, all you need to do is recognize that the z value does not change at all. So a 3D rotation around the Z axis can be calculated with three formulas:
x' = (x * cos(a)) + (y * -sin(a))
y' = (x * sin(a)) + (y * cos(a))
z' = z
Likewise, a rotation around the Y axis keeps the Y value alone, but involves trig functions on the X and Z values. Here's the function list for rotating around the Y axis:
x' = (x * cos(a)) + (z * sin(a))
y' = y
z' = (x * -sin(a)) + (z * cos(a))
... and rotation about the x axis uses a similar set of functions.
x' = x
y' = (y * cos(a)) + (z * -sin(a))
z' = (y * sin(a)) + (z * cos(a))
Don't get all hung up on memorizing these formulas. You can look them up when you need them. The more important thing is to understand the pattern. You'll see a technique for combining these formulas into a cleaner structure in a few minutes. For the time being, note that there is a consistent pattern emerging.

Finding the pattern

Take another look at rotation around the Z axis. The formulas look like this:
x' = (x * cos(a)) + (y * -sin(a))
y' = (x * sin(a)) + (y * cos(a))
z' = z
Here is another way of viewing the same information:
  x * y * z *
x' cos(a) -sin(a) 0
y' sin(a) cos(a) 0
z' 0 0 1
The table is a more concise way of summarizing the formulas. Each row pertains to a part of the target vector. Each column represents an element that will be multiplied. You can expand the formulas by reading the chart. You could read the first row as this:
x' = (x * cos(a)) + (y * -sin(a)) + (z * 0)
All the data of all three functions can be encapsulated on this table.

Introducing the Matrix

Mathematicians use this type of structure all the time, and they call it the matrix. Here is the exact same table in matrix form:
 _                      _
|                        |
| cos(a)   -sin(a)    0  |
|                        |
| sin(a)    cos(a)    0  |
|                        |
| 0    	        0     1  |
|_                      _|

This particular matrix can be set at any angle of a. Given any value of A, this matrix can generate the formulas to calculate a rotation of a radians around the z axis. Similar matrices can be formulated for the other axes.

Multiplying a matrix and a vector

You can multiply a vector by a matrix, giving the following results:
 _   _       _          _      _               _
|  x  |     |   a  b  c  |    |	  xa + yb + zc  |
|     |     |            |    |	                |
|  y  |  *  |   d  e  f  | =  |	  xd + ye + zf  |
|     |     |            |    |	       	       	|
|  z  |     |   g  h  i  |    |	  xg + yh + zi  |
|_   _|     |_          _|    |_       	       _|
You can also multiply a matrix by another matrix of the same size, resulting in a third matrix of the same size as the first two.

This becomes useful because a point can be stored as a vector, and a rotation can be stored as a matrix. Given any angle a you can generate a matrix to rotate a radians around the X, Y, or Z axis. You can multiply these three matrices to get a new matrix combining all three rotations. Each point in a geometry can be written as a vector, and you can get a new geometry by multiplying each point vector by the rotation matrix.

Revisiting Scale

I mentioned above that scaling 'feels' like multiplying a vector, but that's not exactly what happens. If you want to scale some point by the vector <sx, sy, sz>, you can think of it as multiplying by the following matrix:
           _            _
          |   Sx  0  0   |
          |              |
          |   0  Sy  0   |
          |              |
          |   0  0  Sz   |
          |_            _|
If you multiply this scale matrix by each of the rotation matrices, you'll get a three-by-three matrix which encapsulates all the rotation and scaling on each point in the shape.

Note on translation

You might wonder how translation (which is really done with a vector rather than a matrix) fits into all this matrix multiplication. It turns out that computer scientists use a dirty trick. Since they simply want to add a vector to the rest of the matrix multiplication, they work with a four-by-four matrix instead of three-by-three. The fourth row is always all zeros, and the fourth column contains the translation elements. It's a sneaky trick, but it works.

Conclusion

In the final analysis, all the transformations you do to a shape are calculated as individual matrices, and then these matrices are multiplied together to make one master matrix of transformation. That matrix is multiplied by each point in the shape to produce the transformed shape. Although you don't have to do the math yourself, it's very handy to know what's going on under the skin.
© Andy Harris
Indiana University / Purdue University, Indianapolis
email: aharris@cs.iupui.edu
homepage: http://www.cs.iupui.edu/~aharris