**Transformation the First**
Well, first of all, our data (say it's a cube, with its center at the origin and width,height,length of 1,1,1) exists someplace. The box is placed somewhere in the world. For example, say that the point (0,0,0) in your coordinate list -- **object space** -- is really at (13,-10,0) in **world space**.

Before we start worrying about getting it in the right place on the screen, first we should move it to the proper place in the universe. So we add (13,-10,0) to every data point.

Our box is now transformed to world space!

**Transformation the First: Redux**

But wait! not only is the box moved somewhere, but it's been turned some, too. Horrors! Obviously, we can't deal with this simply by adding...

So, we break out some high school trig. Say the box was rotated by 45 degrees around the Y axis. So, for every data point we do a bit of math:

- newx = x * cos(45) - z * sin(45)
- newy = y
- newz = x * sin(45) + z * cos(45)

Once we've done that, the box is rotated and all we need to do is add the translation and move the box to its place in the world.
**Transformation the First: But isn't that slow?**

Yes, it is. And to make matters worse, it gets much more complicated if, say, you wanted your box rotated around some arbitrary vector instead of an euler axis. And if you stick to axes, then you'll feel the pain of gimbal lock sooner or later.

Let's take a different approach. Imagine what happens to the coordinate system of the box as it's rotated: What was once directly to the right (along the x axis) becomes 45 degrees back and to the right. What was directly back becomes back and to the left. And so on --- for any rotation, you can come up with a new vectors A, B, and C so that whatever was once n units along the X axis from the origin is now n units along A; whatever was n units along Y is now n units along B, etc.

With this idea in hand, we can rotate things by replacing every point as follows:

(nx,ny,nz) = (x * A) + (y * B) + (z * C)

We can turn it into coordinate form:

- nx = (x * Ax) + (y * Bx) + (z * Cx)
- ny = (x * Ay) + (y * By) + (z * Cy)
- nz = (x * Az) + (y * Bz) + (z * Cz)

This is pretty good, as far as rotating stuff. But wait! That particular result looks somehow familiar.
| Ax Bx Cx | |x| |nx|

| Ay By Cy | * |y| = |ny|

| Az Bz Cz | |z| |nz|

If we multiply this out, we get:

- nx = (x * Ax) + (y * Bx) + (z * Cx)
- ny = (x * Ay) + (y * By) + (z * Cy)
- nz = (x * Az) + (y * Bz) + (z * Cz)

What a coincidence! It looks like 3x3 matrices are perfect for 3D rotation.
Furthermore, they're also useful for scaling: For example, to make something twice as large along the x axis, all we need to do is use an A of (2,0,0) instead of the boring Euler axis of (1,0,0). You can build the matrix using A, and keeping B and C at (0,1,0) and (0,0,1) respectively, and see how every x gets replaced with 2x.

Neat, huh?

**Yet More Transformation the First**

*But I want to rotate around something other than the origin!*

Easy. Just translate your object to the point you want to rotate around (newpoint = point - rotation_center) and do your rotation (newerpoint = newpoint * rotation_matrix), then translate it back (newestpoint = newerpoint + rotation_center).

*So how do I come up with A,B, and C for my rotation?*

Well, you plug your rotation u around an axis Q into this formula. If you're smart, you've already derived it, haven't you?

Ax = (1-cos(u)) * Qx^2 + cos(u)

Ay = (1-cos(u)) * Qx * Qy + sin(u) * Qz

Az = (1-cos(u)) * Qx * Qz - sin(u) * Qy

Bx = (1-cos(u)) * Qx * Qy - sin(u) * Qz

By = (1-cos(u)) * Qy^2 + cos(u)

Bz = (1-cos(u)) * Qy * Qz + sin(u) * Qx

Cx = (1-cos(u)) * Qx * Qz + sin(u) * Qy

Cy = (1-cos(u)) * Qy * Qz - sin(u) * Qx

Cz = (1-cos(u)) * Qz^2 + cos(u)

Please note that, personally, I'm far too lazy to derive anything, so I looked this up and typed it in. I probably made mistakes. Also, if Q isn't unit length, interesting things will happen. Enjoy the troubleshooting!

**The First Transformation: Object -> World**

So now we know how to take a bunch of objects, rotate them appropiately and place them in the world:

- Translate to the center of its rotation
- Rotate around its axis of rotation
- Translate back to its origin
- Translate to its position in world-space

Cake!
So how do we get "the world" onto the screen, then?

**The Camera Transformation**

Not being all-knowing and all-seeing, only part of the world will be visible. Since we're not dealing with perspective yet, that part will be shaped like a box.

We could start by trying to figure out where that box should be in the world, given the camera position and orientation:

- Scale a 1x1x1 cube so its dimensions are equal to the width, height, and depth of the area that the camera can see.
- Rotate it to point in the camera's direction
- Move it to the camera's position in the world

But this is backwards: We're trying to put the world into the camera, not the camera into the world!
So that's what we'll do -- transform **world space** into **camera space**:

- Move the world to the camera origin. (Subtract the camera's position from every point in the world.)
- Rotate the world until the camera isn't rotated at all. (This is the opposite rotation from the one to orient the camera above)
- Scale the world by the inverse of the visible rectangle's dimensions

Now the entirety of the visible world is within a 1x1x1 cube!
**Getting It To the Screen**

But the screen doesn't use coordinates like that -- we need X's and Y's from 640 to 480, not zero to one. The solution? Transform it again, into **viewport space**.

This is a simple matter of scaling X values by 640, and Y by 480 (or whatever the viewport's width and height are.)

Or is it? If your world space is like most world, then positive Y values are "up." But on the screen, increasing Y values are "down." Everything is upside-down! To fix this, we need to make all Y values negative: Scale by (0,-1,0) first.

Thus, the final steps before actually drawing our data:

- Flip the world upside-down by scaling Y values by -1
- Scale X and Y by the size of your scene in pixels.

Pheew!
Finally, you have your data in screen coordinates that can be displayed directly, for pretty 3D goodness. It might be a good idea to sort your data by z and draw from back-to-front, so objects only get drawn over the top of other ones if they're in front, and to clip things to your viewport so you aren't spending a lot of time drawing items that are off the screen, etc etc etc ... (this is a whole 'nother series).

That's it for now, but watch for...

**Next time**: Homogenous coordinate systems and more matrices! Adding a bit of perspective to the picture! The glory and joy that is OpenGL!