|
|
|
3D
Transformations What now? You are probably thinking this sounds crazy, but this is how polygon 3D engines work. This is how almost every 3D game you've ever played works. Even if you wrote an engine that didn't work this way, you will still need to be able to scale, translate and rotate the objects in your 3D world. We will look into how to do this in a second but first I want to talk about object (local), global and camera space. Object,
Global, Camera Space and the 3D Engine Pipeline If you need to scale your objects, then you do this in object space and it is the first transformation you carry out. You will almost definitely want to rotate your objects at some point and this is also carried out in object space. After those two steps are completed you need to translate your objects into global space. Translating means moving, or sliding, so the rotation and size don't change, only the position. Global space is where you put your objects in relation to each other. So once your global space is complete you have your entire 3D world complete with everything in the correct position in relation to everything else, with the exception of your camera. The final transformation is to take account of the position and rotation of the camera. So to get your objects from global space to camera space you need to rotate and translate everything in your 3D world again. This final step is the one that gets the part of your world which should be visible sat along the positive z-axis so we can view it with our 3D to 2D transformation. Matrices Matrix
M = [ M11 M12 M13 M14 ] and a specific matrix will look like this- Matrix
A = [ 1 3 5 1 ] Of course there would be no point in using matrices if they didn't have a practical use. Certain types of matrices can be used to perform geometric transformations, like scaling, rotating and translating. What we have to do is generate a matrix for each transformation. The good thing though is that matrices are cumulative when multiplied, so if we generate a scaling matrix and a rotational matrix and then multiply them together, then the resulting matrix will perform the same transformation as both the scaling and rotational matrix together, which is handy because we don't need to store all the matrices we will be needing (this is called matrix concatenation). We will come to multiplying matrices and how to transform a 3D point by a matrix later, but first I want to show you the kinds of matrix we will be dealing with. Scaling
Matrix Scaling
Matrix M = [ Sx 0 0 0 ] This matrix will scale a 3D point in relation to it's origin in object space by the factors Sx, Sy and Sz in the three axis x, y and z. So if you want to double the size of a 3D object you would generate a scaling matrix with Sx, Sy and Sz each of 2. In other words- Scaling
Matrix M = [ 2 0 0 0 ]
Rotational Matrix -
X X
Rotational Matrix M = [ 1 0
0 0 ] where A is the angle of rotation about the x-axis.
Rotational Matrix -
Y Y
Rotational Matrix M = [ cos A 0 -sin A 0
] again where A is the angle of rotation, but this time about the y-axis.
Rotational Matrix -
Z Z
Rotational Matrix M = [ cos A sin A 0
0 ] once again where A is the angle of rotation, about the z-axis.
Translation Matrix Translation
Matrix M = [ 1 0 0
0 ] where TX, Ty and Tz are the distances along the x, y and z axis that we want to translate our objects.
Multiplying Matrices Instead of explaining how to do this, I'm just going to show you. Matrix multiplication is extremely messy, and the only matrices you will ever be multiplying is 4 by 4 matrices. If you really need to understand the maths behind it then get hold of a good maths book. The following code shows a function that will multiply two matrices A and B and return the result. Obviously how you store a matrix is entirely up to you, the simplest way would be something like this- struct
matrix
}; Assuming we are using the above struct to represent a matrix, then our matrix multiplication routine would be as follows- // Function to multiply matrix A by B and return the result matrix
MultiplyMatrices ( matrix A, matrix B ) matrix
result; // temporary matrix for
( int j = 0; j < 4; j++ ) result.m
[i][j] = 0; result.m
[i][j] += B.m [i][k] * A.m [k][j]; So that's matrix multiplication covered. We could now generate all five matrices (scaling, x rotation, y rotation, z rotation and translation) and we could multiply the result each time (apart from the first time) by the previous result and end up with once single matrix which would perform all five tasks. The only thing left now is how to process 3D points using this resultant matrix. Transforming 3D points
using matrices To transform any point in 3D
space (x, y, z) by the 4*4 matrix M, i.e.. //
matrix A contains the result of scaling, rotational and translation matrices
combined So that's the basics covered. You should now know how to generate a scaling, x, y, z-rotational and translation matrix. You also know how to multiply 4 by 4 matrices and you now know how to use them to process 3d points. With the maths I have shown you in these first three tutorials you should be able to define a simple shape like a cube in 3D space, position in where you want it, and draw it. Since I'm trying to show you the maths and not a complete working program, I'm inevitably leaving out a lot of the little details, like the data types you might want to use, and how to organize the whole engine. In the last section of this tutorial I will (hopefully) show you how to put it all together. Before we get to that though, I want to introduce you to the idea of surface normals and back-face culling which is the subject of the next tutorial. |
|
All
content copyright © Simon Brown 1999-2005. |