Hamburg (Germany), the 25th May 1998. Written by Nils Pipenbrinck aka Submissive/Cubic & $eeN

Damn, this is boring. Bring me back to the Code-Corner!

Table Of Contents

- Introduction
- How to define the Camera
- The Camera Transformation
- Making a Camera Matrix
- How to use the Matrix
- Final Words

Doing a 3D-Engine without a camera is quite easy. If you write your first 3D-engine or never dealed with the camera stuff you might have problems figuring out how to do the camera transformation. As usually it turns out to be very simple.

We don't need that much informations to define a camera. The only values are:

- The position of the camera itself
- The camera's look-at point
- the roll angle (rotation) of the camera around it's view axis

I made myself a structure which looks like this:

**struct tcamera { tvector position; tvector target; float roll; }**Now, how do we calculate something useable out of these informations? At first we have to move the entire world that the position of the camera becomes the origin of the world coordinate system. This is done by translating by the tcamera.position scaled by -1.

Then we have to find 3 vectors that form our new coordinate system. The three vectors must all have the length of one, and must not be colinear.

The first vector which can be calculated is our new y-vector. It's the vector that will point to the up of our screen. Calculated it by rotating a y-vector around the z-axis by the roll-value:

Now we calculate the new z-Vector. This vector has the same direction as the camera look direction, but it must be normalized to get the length = 1.**Up.x = sin(roll); Up.y = -cos(roll); Up.z = 0;**

The third vector can be calculated by the cross-product of Up and Forward. It'll result in a vector pointing to the right of our screen, or - speaking in our new coordinate system - to the positive x-axis. Normalize this vector, since it's not guaranteed, that up and forward are collinear.**Forward.x = Look_at.x - Position.x Forward.y = Look_at.y - Position.y; Forward.z = Look_at.z - Position.z; normalize_vector (Forward);**

We're almost finished now.. But there ist still one thing: It's not guaranteed, that the up-vector and the direction-vector are colinear. (think about a camera that'll look to the sky). To avoid distiortion we have to recalculate the Up vector again:**Right = crossproduct(up, forward); normalize_vector (Right);**

Again, normalize this vector (just in case, it doesn't hurt).**Up = crossproduct (Right, forward);**How do we build a rotation-matrix out of these three vectors? We only have to put the vectors into the three rows of our rotation-matrix.

If you like 4x4 matrices (as I do) you might use:**| right.x right.y right.z | | up.x up.y up.z | ; (rotation3x3) | forward.x forward.y forward.z |**

We also know the Camera translation matrix (which can only be build if you use 4x4 matrices since translation can not be expressed as a 3x3 matrix):**| right.x right.y right.z 0 | | up.x up.y up.z 0 | | forward.x forward.y forward.z 0 | ; (rotation4x4) | 0 0 0 1 |**

The final Camera matrix is simply the translation multiplied with the rotation:**| 0 0 0 -position.x | | 0 0 0 -position.y | | 0 0 0 -position.z | | 0 0 0 1 |****matrixmul (final, translation, rotation);**Assuming that you use 4x4 matrices for your object transformation you can just concatenate (multiply) your object matrix with the camera matrix. That's all.

If you however still use 3x3 matrices you have something more to do:

- Subtract Pivot-Point from Point (if any)
- Multiply point with object_matrix (rotation + scaling)
- Add Pivot-Point from Point (if any)
- Add Object-Position to point
- Subtract Camera-Position from Point
- Multiply point with camera-rotation-matrix

The resulting point can then be clipped and projected.

I think this is a good example why 4x4 matrices are better than 3x3 matrices. Transforming points using 3x3 matrices is almost three times as expensive as using 4x4 matrices. Of cause the setup-costs (4 matrix-multiplications per object) are higher when you use 4x4 matrices. If you want to rotate a bunch of cubes 3x3 might be the better choice. (anyways, who draws cubes these times?).I hope you learned something. Well, there might still be a bug in the math. it's possible that this camera modell will mirror on some axis (I haven't tested it) If so you only have to change the order of the crossproduct somewhere.. And as usual there are hundrets of typos in the text.. You know:

*foreign languages are difficult languages*.Instead of flaming me you might press the »Save As« button, fix the typos and send it back to me... thank you

Maybe I'll add a tutorial which explains 4x4 matrices in detail. I think there are still a lot of folks out there who don't see the advantage and only use them cause they're »state of the art«

If you want to contact me you might write me a mail.

And now bring me back to the Code-Corner!

colinear means, that a vector can not be expressed as the scaled summ of any other vectors.

For example the vector (1,0,0) can not be expressed by either (0,1,0) or (0,0,1)

Three vectors that are colinear form a basis for a 3d coordinate system.