Deciphering OpenGL's ModelView Matrix

Hello,
OK, we all know that OGL stores it’s matricies in arrays like this

[0]    [4]    [8]     [12]
[1]    [5]    [9]     [13]
[2]    [6]    [10]    [14]
[3]    [7]    [11]    [15]

Where the numbers in brackets are the indicies into the array. The part I’m confused about is that I thought this was the standard arangement for a transformation matrix:

ix iy iz X
jx jy jz Y
kx ky kz Z
0 0 0 1

Where <ix, iy, iz> is the i vector (the local x axis), <jx, jy, jz> is the j vector (local y axis), <kx, ky, kz> is the k vector (can you guess?) and the point (X, Y, Z) is the location of the local coordinate system in the global coordinante system. So, using these two pieces of info, I’d expect OGL’s modelview matrix to be constructed like this:

[0]ix [4]iy [8] iz [12]X
[1]jx [5]jy [9] jz [13]Y
[2]kx [6]ky [10]kz [14]Z
[3] 0 [7] 0 [11] 0 [15]1

But my first try at using my j <[1],[5],[9]> and k <[2],[6],[10]>vectors with gluLookAt() was unsuccessful. I couldn’t figure it out, so I just tried something I didn’t think would work, and it did! I used <[4],[5],[6]> for my j matrix and <[8],[9],[10]> for my k matrix. So it seems, from experimentation, that OGL stores the ModelView matrix like this:

[0]ix [4]jx [8] kx [12]X
[1]iy [5]jy [9] ky [13]Y
[2]iz [6]jz [10]kz [14]Z
[3] 0 [7] 0 [11] 0 [15]1

Is this correct? If so, I assume the other matricies are also stored like this… is that the case?

Thanks,
-BradlyP

[This message has been edited by BradlyP (edited 12-03-2000).]

From what I saw, it is wrong. If I take the 3rd line as a vector (only the first three elements of course) and rotate the “matrix” around it (so, only the axises), it looks like one would roll. So, the local z axis, what you call k, is for me in the 3rd row. For the other axes applies the same, respectively.
I’m not sure, but I think, the axises have to be normalized.

Reread your post. Seems funny to me. Could you mail me the code and I’ll have a look at it.

Oops, took out wrong info.

the other info is ok though.

[This message has been edited by Elixer (edited 01-12-2001).]

You’re right, Elixir. OGL’s matrices are… i forget which is which. one is Row dominant, the other is column dominant (the other being the math books), but yes, ogl is the wrong one

like said, you have to use it as float[16], not [4][4], and enumerate them as he showed.

wierd stuff, huh?


tt4n

Just as a side note, I use this for my openGL matrices.

typedef struct {

Vector3 right;
float pad_0;
Vector3 up;
float pad_1;
Vector3 at;
float pad_2;
Vector3 pos;
float pad_3;
}__struc_Matrix;

works fine for me to just load it directly into the modelview matrix.

cheers,
Nutty.

How in the world does loading this structure into the modelview matrix work? Doesn’t it have to be float[16]?

That structure is the same size as a float[16]. Each Vector3 has 3 floats in it, and 4 pads, gives 16 floats.

It just allows me to extract information out of it really easy. eg. if I want an objects position, I just use the pos vector of the matrix. dead easy!

I also union it with a float[16] array so I can access it that way too.

Nutty

Hey Nutty, that is well… Nutty! I would have never thought of doing it that way.

Learn something new everyday I guess.

Now if only I can get my wavefront loader to work correctly, I’ll be happy.

Well, Nutty, you’re the MAN!!! This is a GREAT idea! I’m going to put it to use IMMEADIATELY! Did you come up with this idea yourself?

Remember to set the packing of structures’ variables to bytewise. I had this problem one time when I had a structure that should have the size of x bytes (from the components), but between the components was a little space, wich made serious problems.

How would you go about setting that in MSVC++?

It was something with

#pragma( PACK, 1 )

I think. It’s been a long time. Afterwards I sticked loading the array element per element out of the file, which looked cleaner to me than doing something possibly compiler-specific.

Oh, and because of that, I would prefer to still work in the matrix rows not in any vectors or elements that are “layed” over the actual matrix.

If you use C++ classes for matrices, vectors etc. then write a constructor for your matrix which accepts a float array. Then you can convert the matrix in your own data format and work with it in the way you does with other matrices.

No Punchey, I found the idea in our last project we worked on. I think it might have been in a Renderware header file. I just adapted it to OpenGL’s matrix format.

On the subject of packing, all the elements are 4 byte floats, so I wouldn’t assume the compiler would insert any extra padding into it. However if you think it might you can always tell the compiler to not pad the structure.

Another great thing is that suppose you want to strafe your character. All you do is add or subtract a scaled amount of the right vector to the position!

Top stuff indeed!

I’m not sure about the 4th element in each row. Should this always be 0, in OpenGL’s matrix, and 1 for element [3][3]. What happens if you chnage them. (They’re the padding floats in my structure)

Nutty

First, I’m not all that familiar with compiler options, so how would you tell the compiler to not pad your structure? BTW, I don’t see how (or why) it could be throwing stuff into your structure because that would totally mess you up with file I/O. I’ve relied for years on the fact that I can create something in C/C++ and then just dump it to disk and then just read that number of bytes back from disk to re-populate a structure. Unless there’s something else going on that I’m not aware of, it looks to me like what you put in a structure is how many bytes the structure is. Period. After all, when you use malloc or memcpy or something like that, you’re allocating the number of bytes it takes to make that structure and nothing more… AFAIK.

On another note, as Nutty mentioned, does anyone out there have a comprehensive definitions of all the elements of an OpenGL array? I am also wondering what [15] which is usually 1 and [3],[7], and [11] which are usually 0. Wait a minute, I don’t know about the others, but I think I remember someone telling me that [15] is a scalar value? Would this represent the scale of the coordinate system being used? Or am I way out in left field here?

Originally posted by Punchey:
nothing more… AFAIK.
On another note, as Nutty mentioned, does anyone out there have a comprehensive definitions of all the elements of an OpenGL array? I am also wondering what [15] which is usually 1 and [3],[7], and [11] which are usually 0. Wait a minute, I don’t know about the others, but I think I remember someone telling me that [15] is a scalar value? Would this represent the scale of the coordinate system being used? Or am I way out in left field here?

First of all, let me say that my linear algebra knowledge is next to 0. What I know is basically limited to some things I picked up in a graphics class so my explanation below might not be completely accurate.

Those 0,0,0,1 elements are just to fill out a 4x4 matrix, I believe. In mathematical terms you could use a 4x3 matrix like so…

A11 A12 A13 A14
A21 A22 A23 A24
A31 A32 A33 A34

The above matrix would be perfectly valid for doing various transformations with. The last row is added as 0 0 0 1 in order to make the matrix multiplication nice and so that an identity matrix can be defined.

From your results, it appears that what is typically in the right colum of the matrix is actually on the bottom of an OpenGL matrix, so it seems reasonable that what is usually on the botton of a matrix would be the right colum of an OpenGL matrx.

Actually, it is impossible (AFAIK) to multiply two matrices without one matrix having the same number of columns as the other matrix has rows. Basically because you multiply the rows of one matrix with the columns of the other matrix. Which would cause me to think that, at some point, those bottom values are going to get multiplied with some other meaningful values (I can’t say which because I don’t know the order and direction OpenGL uses). But, then again, I don’t really fully understand it myself.

Hello all, I’m very new to the whole idea of OpenGL programming, but I do have some Linear Algebra experience, and will attempt to shed some light on your confusion. Please don’t take anything I say here as final truth, I definitely do not have all of the answers to this problem!
Anyways, from what you all say about the modelview matrix tells me that if you wrote out a matrix in “standard” form i.e. like the math books:

a11 a12 a13 0
a21 a22 a23 0
a31 a32 a33 0
a41 a42 a43 1

where the rows are your vectors and the last column is there to flesh out the 4x4 so that you could indeed use it with an identity matrix or take it’s determinant etc. If you took the transpose of this matrix you would get:

a11 a21 a31 a41
a12 a22 a32 a42
a13 a23 a33 a43
0 0 0 1

which, if i understand what you are all saying correctly, would be the proper form for the matrix in OGL, with each column being a vector.

Now with vectors that have only 3 fields in them (x, y, z) then you’d have to add on a zero to the end in order to be able to multiply it with the matrix described above. Some concern was expressed about the last row of zeros creating a problem, this shouldn’t be the case. A quick little bit of info on matrix math, matrices can only be multiplied if the number of columns on the first matrix is equal to the number of rows on the second matrix, this was stated by someone earlier in this thread. i.e. our 4x4 matrix needs a 4x1 matrix to multiply with. If you have your vector (x,y,z) with a zero on the end so that it will multiply (x,y,z,0), and then transpose it as well, it will give you this 4x1 matrix and all will be well.

[a11 a21 a31 a41] [x] [x’]
[a12 a22 a32 a42] X [y] = [y’]
[a13 a23 a33 a43] [z] [z’]
[0 0 0 1 ] [0] [0 ]

Thus your concern about the bottom row of zeros, while warranted, is unneccessary. That last row says: (0x + 0y + 0z + 01) thus it all adds up to zero and gives you the fourth element in the resulting 4x1 matrix.

I hope this has helped with any confusion and that I haven’t confused anyone more than they were before reading this.

-Spline