Camera Implementation In 3D Engines, Ohad Eder Pressman
aka Kombat/iMMoRTaLS
Heyho,
Must be lots of you out there just dying to put a camera in there 3D
engine, well you wont believe how simple it is :
Till today, U probably used 3 matrices or 1 for rotating an object, if
you had 3 matrices you had one for rotating the object around the x-axis,
one for the y-axis and one for the z-axis. Now, we arent exactly talking
about the rotation of an object, but about the rotation of a whole
3D world or a 3D scene. This means we need to apply some transformation
on all of our vertices.
What we are going to do, is calculate a 3x3 matrix that will represent
the rotation of the whole 3D world around our camera.
If you look at your world and at your camera, you can figure out that
there are 2 steps in this transformation, because we are not only rotating
all our scene, we are rotation all our scene AROUND some point, around the
camera source point.
Lets look at the primitive definition of a camera :
1. An x,y,z component representing the Source of the camera.
2. An x,y,z component representing the Destination of the camera.
3. A Roll value which tells us the angle around the cameras Z axis.
All this information comes in the .3DS format, and I suggest reviewing
3DSRDR by Jare. There is another component called the FOV Field Of
View, which controls the perspective of the camera, this doesnt
interest us at the moment.
Lets take a little look at some scene, from the top :
TOP :
Z-Axis
Camera Destination
Camera Source
X-Axis
0
from the two point we can create a vector which will represent the
direction of our camera in our 3D world.
In all following code I will u simplified variable names, except for
the full code enclosed at the end.
First we create this direction vector :
N.x CameraTarget.x - CameraSource.x
N.y CameraTarget.y - CameraSource.y
N.z CameraTarget.z - CameraSource.z
Now, we need to normalize this vector :
L sqrt N.x*N.x + N.y*N.y + N.z*N.z
N.x / L
N.y / L
N.z / L
Basically you should check if the vector length is 0 so that u dont
fdiv by zero, but 3dstudio speaking the chances are 0
What we have now is the N vector representing the direction of the
camera, we need another vector, that will represent where our up is,
this vector depends on the Roll of the camera. Take your head for instance,
your up vector currently points to the sky or the ceiling...
If you rotate your head 90 degrees to the right, your up is no longer the
ceilings but the door or the wall.
Lets define this up vector :
UP.x sinRoll
Up.y 0
Up.z -CosRoll
The following steps are pure mathematics, so try and keep up :
1. Define 2 new vectors, U and V.
2. U Cross Product of N and Up. U N x Up
3. Normalize U.
4. V Cross Product of U and N. V U x N
5. Normalize V.
6. Build your matrix from the three vectors : -U, V, N.
Steps 1 through 5 are purly mathematical, I showed how to normalize a
vector be4, if you dont know how to calculate the cross production of
two vectors, this is the way :
A cross of two vectors gives a new vector, that its direction is an onyx,
normal to the plane that the two vectors represent
A B Cross C A B x C
A.x B.y * C.z - B.z * C.y
A.y B.z * C.x - B.x * C.z
A.z B.x * C.y - B.y * C.x
Step 6 is the final step in which you build your camera matrix,
Let us define our matrix, cmatrix33 OTM :
cmatrix00 -U.x
cmatrix10 V.x
cmatrix20 N.x
cmatrix01 -U.y
cmatrix11 V.y
cmatrix21 N.y
cmatrix02 -U.z
cmatrix12 V.z
cmatrix22 N.z
Now that we have our matrix, well, we have a matrix, good for us.
Lets take a basic loop of an engine :
1. Hey Im the begining of the loop.
2. Rotate Objects, Move Objects, etc.
3. Perform Camera Transformation.
4. Apply Perspective on Vertices.
5. Draw your scene.
6. Go back to 1 untill you get bored...
What we are dealing with is step 3, which can be broke down to 2
sub-steps :
A. Centering our world around our camera. We need to rotate our world
around the camera, so first we must center the world around the
CameraSource Point.
B. Transforming our would according to the camera. Thats just
multiplying all them damn vertices by that damn camera matrix we
just calculated.
Heres some code to feast on :
Vector U, V
for i0iNumVerticesi++
// Put New vertex in U
U.x Verticesi.x - CameraSource.x
U.y Verticesi.y - CameraSource.y
U.z Verticesi.z - CameraSource.z
// Transform Vertex into V, simple Vector*Matrix multiplication
V.x cmatrix00*N.x+cmatrix01*N.y+cmatrix02*N.z
V.y cmatrix10*N.x+cmatrix11*N.y+cmatrix12*N.z
V.z cmatrix20*N.x+cmatrix21*N.y+cmatrix22*N.z
// V now holds our new Vretex, the only thing left now is some
// Perspective... X/Z, Y/Z or some FOV arctans
Heres the full source for the camera calculation function :
void CameraMatrixCamera *Camera1
Vector Up, N, U, V
Up.x sinCamera1-Roll
Up.y 0
Up.z -cosCamera1-Roll
VecSubCamera1-Target,Camera1-Source,N
VNormN
CrossN,Up,U
VNormU
CrossU,N,V
VNormV
Camera1-Mat.BuildMatrix-U.x,-U.y,-U.z,
V.x,V.y,V.z,
N.x,N.y,N.z
I liked writing this, ofcourse there are many other aspects of Keyframing
3D-Engines like splines, quaternions, hirarchey, etc, but I really dont
have time for all that at the moment... :
if you get any problems with the source, or if you got it working,
or if you want me to write about anything else concerning 3D, or if you
want to tell me about your darkest dreams no 10x
Contacts :
kombat@netvision.net.il Faster
ohadp@shani.net Slower
You can check my groups homepage at :
http://www.geocities.com/SiliconValley/Heights/4443
* All code in this article is written very simply and 100 Non-Optimized,
Your most likely to write all mathematical functions in 100 Assembler
and use that damn FPU, A 1 cycle fmul worths something these days...
thanks to all the dudes who ever tought me something, you know who you
are...
Kombat/iMMoRTaLS, 1997