Jump to content
  • Advertisement
Sign in to follow this  
The Rug

OpenGL *sigh* Matrix problems

This topic is 4797 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

What I'm trying to do is create a matrix class which mimics OpenGL's matrix implementation. This is a real bugger, since every article I have found explains things differently and, for the most part, badly. What I want is to: 1. Be able to concatenate transformations like in OpenGL, ie. be able to multiply my one matrix by another 2. Implement rotations by creating a rotation matrix, then multiplying the currewnt matrix by that rotation matrix This is what I have so far:
// These functions are members of class Matrix4x4

             void multiplyBy(const Matrix4x4 &mat) {
                  float newData[16];

                  newData[0]  = data[0] * mat.data[0]  +  data[1] * mat.data[4]  +  data[2] * mat.data[8]  +  data[3] * mat.data[12];
                  newData[1]  = data[0] * mat.data[1]  +  data[1] * mat.data[5]  +  data[2] * mat.data[6]  +  data[3] * mat.data[13];
                  newData[2]  = data[0] * mat.data[2]  +  data[1] * mat.data[6]  +  data[2] * mat.data[10]  +  data[3] * mat.data[14];                  
                  newData[3]  = data[0] * mat.data[3]  +  data[1] * mat.data[7]  +  data[2] * mat.data[11]  +  data[3] * mat.data[15];

                  newData[4]  = data[4] * mat.data[0]  +  data[5] * mat.data[4]  +  data[6] * mat.data[8]  +  data[7] * mat.data[12];
                  newData[5]  = data[4] * mat.data[1]  +  data[5] * mat.data[5]  +  data[6] * mat.data[6]  +  data[7] * mat.data[13];
                  newData[6]  = data[4] * mat.data[2]  +  data[5] * mat.data[6]  +  data[6] * mat.data[10]  +  data[7] * mat.data[14];                  
                  newData[7]  = data[4] * mat.data[3]  +  data[5] * mat.data[7]  +  data[6] * mat.data[11]  +  data[7] * mat.data[15];

                  newData[8]  = data[8] * mat.data[0]  +  data[9] * mat.data[4]  +  data[10] * mat.data[8]  +  data[11] * mat.data[12];
                  newData[9]  = data[8] * mat.data[1]  +  data[9] * mat.data[5]  +  data[10] * mat.data[6]  +  data[11] * mat.data[13];
                  newData[10] = data[8] * mat.data[2]  +  data[9] * mat.data[6]  +  data[10] * mat.data[10]  +  data[11] * mat.data[14];                  
                  newData[11] = data[8] * mat.data[3]  +  data[9] * mat.data[7]  +  data[10] * mat.data[11]  +  data[11] * mat.data[15];

                  newData[12] = data[12] * mat.data[0]  +  data[13] * mat.data[4]  +  data[14] * mat.data[8]  +  data[15] * mat.data[12];
                  newData[13] = data[12] * mat.data[1]  +  data[13] * mat.data[5]  +  data[14] * mat.data[6]  +  data[15] * mat.data[13];
                  newData[14] = data[12] * mat.data[2]  +  data[13] * mat.data[6]  +  data[14] * mat.data[10]  +  data[15] * mat.data[14];                  
                  newData[15] = data[12] * mat.data[3]  +  data[13] * mat.data[7]  +  data[14] * mat.data[11]  +  data[15] * mat.data[15];

                  // copy new information into current matrix
                  for(int count=0; count<16; ++count)
                      data[count] = newData[count];
                  }



             void rotatef(float angle, float x, float y, float z) {
                  // ..convert angle to radians..
                  angle *= 0.0174532925;

                  Matrix4x4 temp;

                  // Rotate around X axis
                  if(x > 0.0) {
                     temp.data[5]  =  cos( angle );
                     temp.data[6]  = -sin( angle );
                     temp.data[9]  =  sin( angle );
                     temp.data[10] =  cos( angle );                                                               
                     }

                  // Rotate around Y axis
                  if(y > 0.0) {
                     temp.data[0]  =  cos( angle );
                     temp.data[2]  =  sin( angle );
                     temp.data[8]  = -sin( angle );
                     temp.data[10] =  cos( angle );                                                               
                     }

                  // Rotate around Z axis
                  if(z > 0.0) {
                     temp.data[0]  =  cos( angle );
                     temp.data[1]  = -sin( angle );
                     temp.data[4]  =  sin( angle );
                     temp.data[5]  =  cos( angle );                                                               
                     }

                     multiplyBy(temp);
                  }



This doesn't work properly, however. I basically create the matrix, load it to identity, and then call rotatef on that matrix. I then load the matrix with glLoadMatrixf. This seems to produce the opposite effect of calling glRotatef with the same values. Using glLoadTransposeMatrixf, however, seems to work. This tells me that my matrices aren't entirely broken, just muddled up- and I have no idea why. Big rates to anyone who can help me!

Share this post


Link to post
Share on other sites
Advertisement
based on what you said at the end (as i cant be bothered to check your maths, heh) you are performing a row major operation when you should be treating the matrix as column major to get the right effect.

Thus, glLoadTransposeMatrixf works as it transposes the matrix from row major to column major.

Share this post


Link to post
Share on other sites
potential insight:

remember that ogl uses column major whereas many tutorials present the row major form of matrix mulitplies in referene to rotations,scale and translates. so for instance the translation vector is in the fourth column, not the fourth row.

this would explain why the transpose resolves the issue, too.

Share this post


Link to post
Share on other sites
Well, I'm in a bit of a pickle now, since it turns out glLoadTransposeMatrixf only worked for the simplest of rotations. So I'm starting to think the problem is something else (orinigating somewhere between my keyboard and my chair, most likely...)

I hate to just ask for code, but I think its the only way I'm going to understand this. If anyone has any OpenGL matrix code for multiplying matrices, I'd love to see it.

Thanks a lot to the previous posters (Ali_B gets an A for effort [wink])

Share this post


Link to post
Share on other sites
for the operation:
ret = mat * v


ret[0] = (mat[0]*v[0]) + (mat[4]*v[1]) + (mat[8]*v[2]) + (mat[12]*v[3]);
ret[4] = (mat[0]*v[4]) + (mat[4]*v[5]) + (mat[8]*v[6]) + (mat[12]*v[7]);
ret[8] = (mat[0]*v[8]) + (mat[4]*v[9]) + (mat[8]*v[10])+ (mat[12]*v[11]);
ret[12]= (mat[0]*v[12])+ (mat[4]*v[13])+ (mat[8]*v[14])+ (mat[12]*v[15]);

ret[1] = (mat[1]*v[0]) + (mat[5]*v[1]) + (mat[9]*v[2]) + (mat[13]*v[3]);
ret[5] = (mat[1]*v[4]) + (mat[5]*v[5]) + (mat[9]*v[6]) + (mat[13]*v[7]);
ret[9] = (mat[1]*v[8]) + (mat[5]*v[9]) + (mat[9]*v[10])+ (mat[13]*v[11]);
ret[13]= (mat[1]*v[12])+ (mat[5]*v[13])+ (mat[9]*v[14])+ (mat[13]*v[15]);

ret[2] = (mat[2]*v[0]) + (mat[6]*v[1]) + (mat[10]*v[2]) + (mat[14]*v[3]);
ret[6] = (mat[2]*v[4]) + (mat[6]*v[5]) + (mat[10]*v[6]) + (mat[14]*v[7]);
ret[10]= (mat[2]*v[8]) + (mat[6]*v[9]) + (mat[10]*v[10])+ (mat[14]*v[11]);
ret[14]= (mat[2]*v[12])+ (mat[6]*v[13])+ (mat[10]*v[14])+ (mat[14]*v[15]);

ret[3] = (mat[3]*v[0]) + (mat[7]*v[1]) + (mat[11]*v[2]) + (mat[15]*v[3]);
ret[7] = (mat[3]*v[4]) + (mat[7]*v[5]) + (mat[11]*v[6]) + (mat[15]*v[7]);
ret[11]= (mat[3]*v[8]) + (mat[7]*v[9]) + (mat[11]*v[10])+ (mat[15]*v[11]);
ret[15]= (mat[3]*v[12])+ (mat[7]*v[13])+ (mat[11]*v[14])+ (mat[15]*v[15]);


This is my operator * code and I use my matrix class with opengl (including glmultmatrixf). So if this doesnt work for you then your problem is elsewhere.

About rotation, when you create temp, does the constructor initialize it to the identity?

Share this post


Link to post
Share on other sites
Thankyou, that is awesome!

Yes, it was my numbers that were jiggered. Ah well, I should pay more attention. Just so you know the_phantom, I did rate you up again, but it made absolutely no difference [grin]

Ahhh, GameDev. Is there anything it can't do?

Share this post


Link to post
Share on other sites

float mtx[16];
/*
IN OpenGL:
|Rx 0 0 Tx|
|0 Ry 0 Ty|
|0 0 Rz Tz|
|0 0 0 1 |

therefore:
|0 1 2 3 |
|4 5 6 7 |
|8 9 10 11|
|12 13 14 15|

and thusly:

mtx[0] == Rx
mtx[5] == Ry
mtx[10] == Rz
tehTranslate3f = mtx[3], mtx[7], mtx[11]
*/




Now when you do rotations with matrices you perform them in some developer defined order, right? let's pretend you multiply matrices A by B by C in Dx/row major/LHSsystems. Notice that the ANS matrix will be also be in Dx/Row Major/LHS form.

ANS = A * B * C

However to accomplish the same results when the matrices are in OGL/column major/RHS systems would be to multiply them in reverse order, which results in the ANS matrix to be in the OGL/Column Major/RHS form.

ANS = C * B * A


consider the following example:

let A and b be LHS matrices where
A =
|1 2|
|3 4|
B=
|5 6|
|7 8|
ANS = A * B =
|(1*5 + 2*7) (1*6 + 2*8)|
|(3*5 + 4*7) (3*6 + 4*8)|
=
|19 22|
|43 42|

now let's try it in RHS where A and B are
A =
|1 3|
|2 4|
B=
|5 7|
|6 8|
ANS = B * A =
|(5*1 + 7*2) (5*3 + 7*4)|
|(6*1 + 8*2) (6*3 + 8*4)|
=
|19 43|
|22 42|
= transpose of ANS in the LHS system


now why all this info .. perhaps you have the order matrix mulitplies backwards (for the rotations, translations and projections) in your code, and you mulitply method is actually a-ok? after all, in general matrix mulitplicaiton is not commutative. just another possibility for you to consider.

Share this post


Link to post
Share on other sites
Maybe I'm being an ass, but it seems that OpenGL can do these things for you and possibly be more efficent(not to insult anybody).

// R = M * V

float* multMatrix(const float M[16], const float V[16]) // you guys seem to like those letters
{
float R[16]; // result

glMatrixMode (GL_MODELVIEW); // you can use any matrix, but we need to choose one
glPushMatrix ();
glLoadMatrixf(M); // GL_MATRIX = M
glMultMatrixf(V); // GL_MATRIX = M * V
glGetFloatv (GL_MODELVIEW_MATRIX, R); // R = GL_MATRIX -> R = M * V
glPopMatrix();

return R;
}

// optional matrix:
// glMatrixMode can have GL_MODELVIEW, GL_PROJECTION or GL_TEXTURE
// thus glGetFloatv must have GL_MODELVIEW_MATRIX, GL_PROJECTION_MATRIX or GL_TEXTURE_MATRIX respectivly


this way you can also preform OpenGL operations and output the matrix to see the resulting matrix, just trying to help

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
glLoadTransposeMatrixf is it extension or what i can't find it in the blue book??

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!