Edges to Rubies The Complete SketchUp Tutorial


Transformation matrix diagram.

Appendix T—The Transformation Matrix

"Use of the transformation class requires a knowledge of geometrical transformations in 3 dimensions which is covered extensively on the Internet." That's what the Google doc says. I found that statement totally unacceptable.

The more I traced down this extensive coverage, the worse it got. Wikipedia, a resource I otherwise love, is utterly incomprehensible on the Transformation matrix . "Using homogeneous coordinates, both affine transformations and perspective projections on Rn can be represented as linear transformations on RPn+1 ..." (That's from the lead paragraph. Just what you thought, right?)

Fortunately, as Chapter 15 demonstrates, you can make effective use of the Transformation class without the "required" knowledge. I was going to introduce this material in Chapter 15, but it was really not needed. So I stuck it back here in the appendices for those who never stop asking, "Why?"

Introduction

3d computer graphics is built on, among other things, a four-by-four array of real numbers known as the transformation matrix. By plugging appropriate values into this matrix you can move, rotate and scale geometry. OpenGL, the graphics language specified by OpenGL.org (according to itself, "The Industry's Foundation for High Performance Graphics") understands the transformation matrix. Your graphics card understands OpenGL.

The matrix is really a 3x3 matrix, that handles rotation and scale, in the top-left corner of a 4x4 matrix, that adds translation (move) transformations:

RS RS RS U
RS RS RS U
RS RS RS U
Xt Yt Zt Wt

RS Rotation and Scale Matrix
U Unused or application-specific use
(may always be zero)
Xt ... Translation Vector
(Wt may always be one)

The Identity Matrix

This is a four-by-four "identity matrix":

1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
The number one is the identity value in scalar multiplication. One times X equals X. If we call the identity matrix I and another matrix M, I * M = M. We'll have an example of this shortly.

Geometry and the Transformation Matrix

Though experiment: create some geometry. Give your geometry an identity matrix for its starting transformation matrix. (In SketchUp, model something, select it and turn it into a component.) When it's time to draw your geometry, each vertex is multiplied by the transformation matrix to find its translated, rotated and scaled location. (Initially, that's multiplying by the identity matrix, which changes nothing. Draw it exactly where I modeled it, please.)

Now let's rotate. Create a transformation matrix that specifies a rotation. (For the moment, assume this is possible. Details are coming.) Multiply this rotating matrix by the geometry's transformation matrix. The result replaces the geometry's transformation matrix. Now when you multiply each vertex by the new matrix, the result is the vertex's location after applying the rotation.

Now let's scale. It's the same as rotating. A matrix that specifies the desired scaling is multiplied by the existing matrix to get a new matrix that specifies the previous rotating plus the new scaling.

Assume your geometry has a hundred vertices. We just did one hundred matrix multiplications to rotate it; another hundred to scale it. Dumb. Let's get smart.

Take the matrix that specifies rotation. Multiply it by the matrix that specifies scaling. The result matrix specifies both rotation and scaling. Multiply the result by each vertex to locate the vertices in space. That's a hundred and one matrix multiplications. Smart.

Do you want to rotate around three axes and scale by different amounts in two axes? That would be 105 multiplcations if you do it the smart way, 500 multiplications if you're not smart. This matters. Now, how do you multiply a vertex (original location) by a matrix that specifies transformations?

Vertex Times Matrix Equals Vertex

We'll begin with the Rotation/Scale matrix. How do you multiply a 3d vertex by a 3d matrix and get another vertex?
x a b c xa + yb + zc
y * d e f = xd + ye + zf
z g h i xg + yh + zi
Let's multiply a vertex by the identity matrix, just to check.
x 1 0 0 x*1 + y*0 + z*0 x
y * 0 1 0 = x*0 + y*1 + z*0 = y
z 0 0 1 x*0 + y*0 + z*1 z

Rotation

These are the formulae for rotating around the z axis, given an original point (x,y,z) and an angle a (in radians):
xrot = (x * cos(a)) + (y * -sin(a))
yrot = (x * sin(a)) + (y * cos(a))
zrot = z
These formulae could be shown in a table:
Rotation Around the Z Axis
Vertex X * Y * Z *
x cos(a) -sin(a) 0
y sin(a) cos(a) 0
z 0 0 1
And you probably recognize where we're going. We're multiplying a vertex by a matrix:
x cos(a) -sin(a) 0 x*cos(a) + y*-sin(a) + z*0 xrot
y * sin(a) cos(a) 0 = x*sin(a) + y*cos(a) + z*0 = yrot
z 0 0 1 x*0 + y*0 + z*1 zrot
There are similar matrices for rotations around the other axes, which you can look up at Ruth's Ruthless Homepage. If you multiply two rotation matrices you get a combination that performs both rotations at once.

Scaling

Scaling is simpler than rotating. To scale about the origin, multiply by this matrix:
scaleX 0 0
0 scaleY 0
0 0 scaleZ

Let's double our geometry's size in the x and y directions but leave it unchanged in the z direction. (In SketchUp, those are the red, greeen and blue axis directions.)

x 2 0 0 x*2 + y*0 + z*0 x*2
y * 0 2 0 = x*0 + y*2 + z*0 = y*2
z 0 0 1 x*0 + y*0 + z*1 z

Multiplying one scaling matrix by another scaling matrix combines to give both operations. Multiplying a rotating matrix by a scaling matrix combines the operations.

Translation

Adding a vector to a vertex translates the result, an operation @Last wisely labeled "Move." Where to put a translation? Enter the 4x4 transformation matrix. So far we've looked exclusively at its first three rows and columns. Now we expand.

In the last row, add a "homogeneous coordinate", [x,y,z],w. This is trickier to pronounce than to understand. Begin with [0,0,0],1. This specifies no translation. The fourth value is a divisor for the others, so [4,6,8],2 is another way of saying [2,3,4],1.

The translation vector's origin point is unspecified. SketchUp's translation is always relative to the [0,0,0] origin.

To translate you add the translation (after dividing by w if w is not 1) to the rotated and scaled point. For more detail on the homogeneous coordinate, see this Google knol.

Final Thoughts

Did you notice that there are three empty places in the last column? One use I read about stored an origin point there and translated that origin by the first three values in the last row. It ignored the value in the last row and column. SketchUp's final value is almost always one. It is used to hold the inverse of a global scale factor. (See Chapter 15, Scaling.)

I have dug through many of the references Google returns if you ask about a "3d transformation matrix." Not all of them agree on every point. All agree that the exact order of applying transforms matters. Not all agree on what the order should be. I find that rotating, then scaling and last translating seems to work. (That is suggestive, but not definitive. Sorry.)

Do not attempt to code from this summary. It succeeds if it gives you a good idea of what is going on under the covers. It fails if you think you don't need a real 3d textbook to do 3d programming. See the comments to the above-mentioned knol to witness real experts arguing small but critical points. Microsoft's DirectX is, as always, different from the industry standard.

Is there a hand raised in back? "Speak up." The question is, "How do you multiply matrices?" It's like multiplying a vertex by an array, only messier. Stefan Waner at Hofstra explains the process very well. After I learned it from him I thought, "The SketchUp engineers programmed this years back. I should have just believed them."

P.S. I should have just believed them accept for the fatal bug in ComponentInstance.move!(). To get around the bug, for Chapter 16's work, I had to program a matrix class that knew how to multiply. Thank you, Stefan Waner.


View of apartment contents. Transformation matrix diagram.