MATRIX MANIPULATION

From:http://www.morrowland.com/apron/tutorials/gl/gl_matrix.php
The creators of OpenGL have made matrix handling like translation rotation and scaling very easy. This is one of the reasons why OpenGL is so popular. Before we learn how to transform geometry in OpenGL it's good to know a little bit of what is goes on behind the curtains.. I will start by explaining some of the mathematics regarding matrices. I will do this by quoting the beginning of a paper I found written by Uche Akotaobi for The University of Southern California.. 


What's a matrix?
It's just a way to specify a whole bunch of n-dimensional transformations in one convenient package. 

That's it. That's all they are, that's all they're used for. 

But my goodness, I once hated these things. Whenever I saw them on a website, I would instantly go back, as if the content of the site offended me. I once swore that I would never use them in my graphics engines, just to demonstrate that it was possible to live without them! 

Well, of course it's possible. There's nothing that you can do with a matrix of transformation that you can't do algebraically, and there's things you can do procedurally that you can't possibly do with matrices (non-rigid body distortions come to mind...but that's besides the point.) Of course, that doesn't mean that matrices are evil--But I was young and brash at the time. The point is that these things do infact make your life easier as a 3D programmer.. 

In any case, here's a 4x4 matrix.

[ A1 A2 A3 A4 ]
[ B1 B2 B3 B4 ]
[ C1 C2 C3 C4 ]
[ D1 D2 D3 D4 ]

A matrix is a two dimensional array of numeric data, where each row or column consists of one or more numeric values. 

Arithmetic operations which can be performed with matrices include addition, subtraction, multiplication and division. 

The size of a matrix is defined in terms of the number of rows and columns. 

A matrix with M rows and N columns is defined as a MxN matrix. 

In C++ a 4x4 matrix can be stored as an array of Matrix[4][4]; or Matrix[16]; 

We can use this number system to transform 3D geometry translate, rotate and scale 3D points and vectors. 

Identity
First take a look at this 4x4 homogeneous identity matrix. The identity matrix is matrix in which has an identical number of rows and columns. Also, all the elements in which i=j are set one. All others are set to zero. For example a 4x4 identity matrix is as follows: 

| 1 0 0 0 |
        | 0 1 0 0 |
        | 0 0 1 0 |
        | 0 0 0 1 |
        

Translate
A translation matrix is used to position an object within 3D space without rotating in any way. Translation operations using matrix multiplication can only be performed using 4x4 matrices. 

If the translation is defined by the vector [X Y Z ], then the 4x4 matrix to implement translation is as follows: 

| 1 0 0 X |
        | 0 1 0 Y |
        | 0 0 1 Z |
        | 0 0 0 1 |
        

Note! If the vector is [0 0 0] then the vertex list will remain as before. 


Scale
A scaling matrix is used to enlarge or shrink the size of a 3D model. 

If the scaling vector is [X Y Z] then the matrix to perform this is as follows: 

| X 0 0 0 |
        | 0 Y 0 0 |
        | 0 0 Z 0 |
        | 0 0 0 1 |
        

Note! If the scaling vector is [1 1 1], then this generates the identity matrix and vertex geometry will remain unchanged. 


Putting transelation and scaling together:
Where x2,y2,z2 transelation values and x,y,z scaling values gives: 

| x 0 0 x2 |
        | 0 y 0 y2 |
        | 0 0 z z2 |
        | 0 0 0 1  |
        

Rotate
The rotation matrix is a little bit more advanced, you will infact need 3 matrices for 3 dimensions.
One for the X-Axis, one for the Y-Axis and one for the Z-Axis, like this: 

 X - Axis:
        |1  0    0    0|
        |0  cos  sin  0|
        |0 -sin  cos  0|
        |0  0    0    1|
        Y - Axis:
        |cos  0 -sin  0|
        |0    1  0    0|
        |sin  0  cos  0|
        |0    0  0    1|
        Z - Axis:
        |cos  sin 0   0|
        |-sin cos 0   0|
        |0    0   1   0|
        |0    0   0   1|
        
Note! Above I'm talking about rotating in radians not degrees! 



OPENGL MAKES IT EASY
Don't worry if you don't understand all this because here's how it all works in opengl..
In OpenGL we can use glTranslate, glRotate and glScale to do our dirty work for us.. That's right we got three very easy function calls for moving, rotating (in degrees) and scaling that works like this: 

glTranslate(x direction, y direction, z direction); // for translation/moving your geometry 

glRotate(RotationAngle, x axis, y axis, z axis); // for rotating your geometry 

glScale(x direction, y direction, z direction); // for scaling your geometry 

But if you are drawing more than one object and you don't want the glTranslate, glRotate or glScale to affect all the next objects, you should use glPushMatrix and glPopMatrix.. 

In the example below object1 will be translated 5 units in x direction, object2 will be rotated 90 degrees. Object2 will not be translated because you use glPushMatrix and glPopMatrix around the process of object1 

glPushMatrix();
  glTranslatef(5.0f, 0.0f, 0.0f); // Translate 5 Units Left
  DrawObject1();
glPopMatrix();

glPushMatrix();
  glRotatef(90.0f, 0.0f, 1.0f, 0.0f); // Rotate 90 Degrees
  DrawObject2();
glPopMatrix();


Now for the code below, we will be drawing 3 triangles they will all be translated 6 units into the screen, and bositioned left, center and right in that order. 
- The first one will be animated up and down regarding to the value of fTranslate. 
- The second one will be rotatet 0 to 360 degrees with the value of fRotate (0.0f - 360.0f). 
- The third one will be scaled in x, y and z direction depending on the value fScale (1.0f being the default value)..

int DrawGLScene(GLvoid)		// Here's Where We Do All The Drawing
        {
        // Clear Screen And Depth Buffer
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        // Reset The Current Modelview Matrix
        glLoadIdentity();
        //NEW//////////////////NEW//////////////////NEW//////////////////NEW/////////////
        glPushMatrix();
        glTranslatef(-2.0f, 0.0f,-6.0f);		// Place the triangle Left
        glTranslatef(0.0f, fTranslate, 0.0f);	// Translate in Y direction
        Draw_Triangle();			// Draw triangle
        glPopMatrix();
        glPushMatrix();
        glTranslatef(0.0f, 0.0f,-6.0f);		// Center The Triangle
        glRotatef(fRotate, 0, 1.0f, 0);		// Rotate around Y axis
        Draw_Triangle();			// Draw triangle
        glPopMatrix();
        glPushMatrix();
        glTranslatef(2.0f,0.0f,-6.0f);		// Place the triangle Right
        glScalef(fScale, fScale, fScale);	// Scale In X,Y,Z Direction
        Draw_Triangle();			// Draw triangle
        glPopMatrix();
        fTranslate += 0.005f; 	// Speed Of The  Translation
        fRotate    += 0.5f;   	// Speed Of The Rotation
        fScale     -= 0.005f; 	// Speed Of The Scaling
        if(fTranslate > 0.5f) fTranslate = 0.0f;   // Reset Translation
        if(fScale < 0.5f)     fScale     = 1.0f;   // Reset Scaling to 1.0f
        //NEW//////////////////NEW//////////////////NEW//////////////////NEW/////////////
        return TRUE;			// Keep Going
        }
        

That's how we transform objects easy in OpenGL..
Try removing all the glPushMatrix and glPopMatrix and see what happens you can download the source code below.. As I have said before the best way to learn this stuff is by trial and error..
If you want to dig deeper into the world of matrices then read the great matrix article that can be found here click here to enter the matrix. 

Have Fun!
Ronny Andr� Reierstad
posted @ 2009-09-01 14:52  Revive and Strive  阅读(418)  评论(0编辑  收藏  举报