Damn, this is boring. Bring me back to the Code-Corner!
Table Of Contents
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:
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:
Up.x = sin(roll);
Up.y = -cos(roll);
Up.z = 0;
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.
Forward.x = Look_at.x - Position.x
Forward.y = Look_at.y - Position.y;
Forward.z = Look_at.z - Position.z;
normalize_vector (Forward);
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.
Right = crossproduct(up, forward);
normalize_vector (Right);
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:
Up = crossproduct (Right, forward);
Again, normalize this vector (just in case, it doesn't hurt).
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.
| right.x right.y right.z | | up.x up.y up.z | ; (rotation3x3) | forward.x forward.y forward.z |If you like 4x4 matrices (as I do) you might use:
| 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 |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):
| 0 0 0 -position.x | | 0 0 0 -position.y | | 0 0 0 -position.z | | 0 0 0 1 |The final Camera matrix is simply the translation multiplied with the rotation:
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:
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
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.