Matrix and the 4th line

i have a simple question:
is there any situation in which the 4th line of a matrix is different from ([0 0 0 (1)] the 1 is unimportant …)

1 Matrix as !example!:
1 0 0 0
0 1 0 0
0 0 1 0
x x x 1 => 4th line ( x is always 0? )

The 4th column is to give a vector of translation.
The structure 4 x 4 in OpenGL is a middle to put in the same structure a matrix of rotation and a vector of translation.

As you can see, matrix [3x3] + vector[1x3] = matrix [ 4 x3 ] not easy to manipulate.
So to symetrise this structure, a 4 th line was been created.

So for OpenGL user this 4th line has no utility and it have to worth always {0,0,0,1}.

I haven’t tried for the {0,0,0} but if you put an other value for 1, you can have such problems.

In case of the modelview matrix, you can think of the matrix as representation the orientation and position of the object.

Row1 = Right vector.
Row2 = Up vector.
Row3 = At vector. (direction object is facing)
Row4 = Position.

An identity matrix gives right pointing 1 in the X (1,0,0), up pointing up (0,1,0), and at pointing at the z axis. (0,0,1)

This is how I normally handle it.

Nutty

[This message has been edited by Nutty (edited 04-27-2001).]

the 4th row is used for perspective correction (ie, close objects = large, objects far away = small).

MS has a nice page in its DirectX documentation. http://msdn.microsoft.com/library/psdk/d…on_graphics.htm

[This message has been edited by Lord crc (edited 04-28-2001).]

[This message has been edited by Lord crc (edited 04-28-2001).]

thanks Lord crc, maybe this will help me by understanding how to create a Frustum matrix by myself

PIP, and Nutty, you are both wrong, and i know why:
Matrix in opengl( if you have m[16] !)
m0 m4 m8 m12
m1 m5 m9 m13
m2 m6 m10 m14
m3 m7 m11 m15
^ ^ ^ ^
x y z transform <- Vectors
and not:
m0 m1 m2 m3
m4 m5 m6 m7
m8 m9 m10 m11
m12 m13 m14 m15

:=>translation vector is build of m12-m15 ( 1st diagramm) and not my line: m3, m7, m11, m15

Are you talking about the projection matrix, or the modelview matrix? IF we’re talking modelview matrix, then I am not wrong. Unless by some freak of nature, my wrong matrix format works everytime?!?

If you have a matrix delcared as 16 floats, then the positional elements of that matrix, is elements 12, 13, and 14.

As far as projection matrix goes… I have no idea how that is constructed. Dont really need to most of the time.

Nutty

if you pass the matrix on to opengl via glLoadMatrix, then i dont know (im no matrix guru myself). However if you do all the matrix math yourself, its very possible. There’s two main ways to organize a matrix, and thats column major, and row major. And i keep forgetting which one’s which, but basically you can most easily tell the difference by where the translation data is stored.

This the way opengl stores them: http://msdn.microsoft.com/library/psdk/opengl/glfunc03_9a05.htm

it seems ogl’s way is the one thats gotten a foothold in gfx, and i recall something like that the math community prefers it the “other way around”

but then again, im no expert

Matrices seem to always rear their ugly head. I realise there are reasons why they are implemented like column-major in OpenGL, but I sometimes wish they had followed the mathematical row-major way!

T2k, you are right that a matrix defined as float m[16] is equivalent in OpenGL to the column major representation (see red book 3rd ed. pp105-106):
m0 m4 m8 m12
m1 m5 m9 m13
m2 m6 m10 m14
m3 m7 m11 m15

Nutty’s last post is also right, in that a matrix defined as float m[16] has positional elements at m12, m13 and m14. However, this isn’t the 4th row of the matrix, it’s the 4th column (as defined above). I think in Nutty’s first post, he maybe got confused with the way a float array is defined (see code below). No disrespect intended Nutty, I am well aware you know what you are talking about re coding/OpenGL

The best way to test OpenGL’s matrix representation is to test some code so I changed some stuff in one of my projects:

float test[16] = {
1.0f, 0.0f, 0.0f, 0.0f,   // Column 1.
0.0f, 1.0f, 0.0f, 0.0f,   // Column 2.
0.0f, 0.0f, 1.0f, 0.0f,   // Column 3.
obj_pos[0], obj_pos[1], 2*Z_Offset-obj_pos[2], 1.0f };   // Column 4.
glMultMatrixf(test);
// Swapped the code above for the code below.
//glTranslatef(obj_pos[0], obj_pos[1], 2*Z_Offset-obj_pos[2]);

The test code was identical to the old call to glTranslate(). Notice that the way the array is written, what looks like rows are actually stored as columns by OpenGL, so the last “row” of the array is elements m12, m13, m14 and m15 of a column-major matrix.

For more matrix fun, T2k, search the discussion boards for a thread a few weeks ago with about 90 posts on matrices. I think the answers came out in the end!

Anyway, back to the original question. The way you wrote the original matrix at the top, T2k, you can have different values for the bottom row of a column-major OpenGL matrix (elements m3, m7, m10, m15). See the red book for the matrix that glFrustum() generates. It has a bottom row of 0.0f, 0.0f, -1.0f, 0.0f (OpenGL Programming Guide Third Edition, p674)

Hope that helps,
Toby

(P.S Nutty, good to see the GeForce 3 is working well - you lucky bastard )

[This message has been edited by ffish (edited 04-28-2001).]

Thanks ffish! Unfortunatly this geforce 3 is still giving me jip, until I get a bigger PSU!!

I might be wrong on this, but the modelview matrix format in opengl is NOT

m0 m4 m8 m12
m1 m5 m9 m13
m2 m6 m10 m14
m3 m7 m11 m15

I shall now explain why I feel this. Firstly, I map the matrix to the following structure.

typedef struct
{
Vector3 right;
float pad0;
Vector3 up;
float pad1;
Vector3 at;
float pad2;
Vector3 pos;
float pad3;
}Matrix;

(I suppose I could vector 4’s but you know…)

Now, If the positional elements (12, 13, and 14) where in the matrix format I listed at the top, then mapping to this matrix would put the positions into all the pading floats. And it doesn’t! I’ve successfully used the above matrix structure loads of times. This leads me to the fact that the matrix format is listed as follows

m0 m1 m2 m3
[ right ]

m4 m5 m6 m7
[ up ]

m8 m9 m10 m11
[ at ]

m12 m13 m14 m15
[ pos ]

With m3, m7, m11, and m15 being the pads.

I am pretty sure I am right on this, or my structure would fall flat on it’s face.

Notice that the way the array is written, what looks like rows are actually stored as columns by OpenGL, so the last “row”

I dont understant this much really. In your example, you call each row a column. Now forgetting about opengl, this is wrong. It’s a row… simple as that. What opengl does with it AFTER you’ve passed it over is irrelevant. OpenGL abstracts from the hardware, and it could very well store the matrix in whatever format it chooses. Implying that we should call our rows, columns because opengl swaps it round internally is wrong in my opinion. We still define the position as the last row in our code.

Nutty

P.S. If I AM wrong, I dont care… I’ve got a geforce 3!! :stuck_out_tongue_winking_eye:

[This message has been edited by Nutty (edited 04-29-2001).]

Nutty,

Unfortunatly this geforce 3 is still giving me jip, until I get a bigger PSU!!

I’ve got a big enough PSU. Just send your card to me and I’ll tell you how it goes

I might be wrong on this, but the modelview matrix format in opengl is NOT

m0 m4 m8 m12
m1 m5 m9 m13
m2 m6 m10 m14
m3 m7 m11 m15

You’re wrong See the red book 3rd ed pp105-106. It clearly says that this is how they are stored internally.

Your struct is fine, though. The reason why it works is your struct is essentially the same as my float m[16], which is the best way to use your own matrices with OpenGL (since that is how you pass them to OpenGL).

The problem arises (as the red book says) when someone who doesn’t know the difference writes a matrix like this: float m[4][4]; and expects that accessing m[i][j] will give them the ith row and the jth column, when it actually gives the ith column and the jth row. As long as you only use arrays (or your struct) you’ll never notice this problem.

An example of the problem is accessing m12. In row major form you’d have m[3][0] when in OpenGL it should be m[0][3].

This is kind of a tricky problem since learning C/C++ you’re always thinking m[i][j] is the ith row and the jth column THAT’S the problem you have to look out for.

I dont understant this much really. In your example, you call each row a column.

What I should have done was something like this:

float test[16];
test[0]=1.0f; test[4]=0.0f; test[8]=0.0f; test[12]=obj_pos[0]; // Row 1.
test[1]=0.0f; test[5]=1.0f; test[9]=0.0f; test[13]=obj_pos[1]; // Row 2.
test[2]=0.0f; test[6]=0.0f; test[10]=1.0f; test[14]=2*Z_Offset-obj_pos[2]; // Row 3.
test[3]=0.0f; test[7]=0.0f; test[11]=0.0f; test[15]=1.0f; // Row 4.

We still define the position as the last row in our code.

It’s not. Again, from the red book 3rd ed p672:

The call to glTranslate*(x, y, z) generates T, where
T =
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1

which is equivalent (as you know) to:

float m = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
x, y, z, 1.0f};
// Or:
Matrix m = new Matrix();
m->right(1.0f, 0.0f, 0.0f);
m->pad0(0.0f);
m->up(0.0f, 1.0f, 0.0f);
m->pad1(0.0f);
m->at(0.0f, 0.0f, 1.0f);
m->pad2(0.0f);
m->pos(x, y, z);
m->pad3(1.0f);

Let me say one more time - your struct and code aren’t wrong (as you know since they work how you think they do) but your way of thinking of the matrix is.

P.S. If I AM wrong, I dont care… I’ve got a geforce 3!!

<grumble>I’m not jealous, no really I’m not </grumble>

[This message has been edited by ffish (edited 04-29-2001).]

I think I get it now…

Nutty