glMultMatrixf(GLfloat *m );

Actually Michael, what you said previously, i.e.:

Originally posted by Michael Steinberg:

I wanted to state that only the “names” of the elements are flipped in opengl. The matrices always look equal. So gorg, I might have explained me bad, but I wasn’t discussing to calculate differently with opengl matrices. The problem was, that a mathemacian would store the first row in offsets 0, 1, 2, 3 but opengl has it in 0, 4, 8, 12 (all memory offsets). Elixer not only output the matrix incorrectly, he was actually calculating with the wrong offsets.

is correct. The matrix should be written in the form:

x_axis_x y_axis_x z_axis_x trans_X
x_axis_y y_axis_y z_axis_y trans_y
x_axis_z y_axis_z z_axis_z trans_z
x_axis_w y_axis_w z_axis_w trans_w

This is true for OpenGL aswell as math notation, the only difference between the two is what element the index points to. Standard math notation is row-major, that means the elements are labeled like this:

00 01 02 03
04 05 06 07
08 09 10 11
12 13 14 15

OpenGL uses row-major ordering which means the elements are labeled like this:

00 04 08 12
01 05 09 13
02 06 10 14
03 07 11 15

But although the numbering is different it’s still the same matrix that I printed out at the beginning. However if you use a two dimensional array for your matrix it will be row-major and wrong for OpenGL. It’s still the same matrix though. Hopefully that clarifies things.

[This message has been edited by harsman (edited 01-22-2001).]

Thanks harsman.
Since it seems to me that you’re a matrix profi, I hope you can “link” me to some mathematical backgrounders on the topic “matrices”. I actually know what the contain, know how to work with them (at least I can achieve my goals, it might be achievable far easier…).

Another question right now.
I’ve got a function that creates a rotation matrix that rotates a vertex around a vector.
If I want to rotate an object around its local axes, I always need to create the rotation matrices around the global axes (1,0,0 for x etc.) multiply them together and the multiply the resulting matrix to my own copy of the modelview matrix.
However, when I want to rotate the camera around it’s local axes, I need to take the local axes out of it’s modelview matrix and create the rotation matrices around them and not around the global axes. Why is this?
If I misexplained me, tell me…

Thanks!

Harsman wrote:
[0]x_axis_x [4]y_axis_x [8]z_axis_x [12]trans_X
[1]x_axis_y [5]y_axis_y [9]z_axis_y [13]trans_y
[2]x_axis_z [6]y_axis_z [10]z_axis_z [14]trans_z
[3]x_axis_w [7]y_axis_w [11]z_axis_w [15]trans_w

So, when Michael wrote:
matrix[2] is the x for z’
matrix[6] is the y for z’
matrix[10] is the z for z’
it should really be:
m8 is x for z’
m9 is y for z’
m10 is z for z’

since 2,6,10 would be z for X’,Y’,Z’ right?
(or in ascii gfx terms
[1, 0, 0, 0] <- X Components of Vectors
[0, 1, 0, 0] <- Y Components of Vectors
[0, 0, 1, 0] <- Z Components of Vectors
[0, 0, 0, 1] <- w component ??
a, b, c, d
^ ^ ^ ^
d= Translation Vector
c=---- Z Axis Vector
b=------- Y Axis Vector
a=---------- X Axis Vector

Or Michael, is your z’ = z component, and x,y,z are the axis vectors? I think it is a labeling problem that confuses me.

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

No, look more exactly at that what he calls the opengl way of indexing matrices.

My question’s still in the room though.

Oh, ****, harsman, here’s our cutting point.
I say this for a normal translation matrix:

x’xsx x’y x’z tx
y’x y’y
sy y’z ty
z’x z’y z’z*sz tz
0.0f 0.0f 0.0f 1.0f

You say a completely different thing. Which is right???

[b] [BLOCKQUOTE]

x’xsx x’y x’z tx
y’x y’y
sy y’z ty
z’x z’y z’z*sz tz
0.0f 0.0f 0.0f 1.0f

You say a completely different thing. Which is right???[/b]<HR></BLOCKQUOTE>

First of all I’m not sure what the difference is between x and x’, which is a component of a vector and which is a vector?
Second I don’t know what those s’s are, but I assume that t is the translation vector. In that case it’s the same thing i printed earlier. Also, Elixer was right in the interpretation of my previous post.
Now I’ll try to shed some light on why you sometimes see transposed matrices compared to the one I described in my previous post. First of all some basic linear algebra.
There is a direct equivalence between vectors and matrices with a single row or column (not both, then there’s a direct equivalence with a scalar) Vectors interpreted as having a single row are called row vectors and vectors with a single column are called column vectors.

column: row: (x y z)
x
y
z

In OpenGL all vertices are considered column vectors and are additionally given as homogenous coordinates in 4-space which means the fourth component (i.e. W) is one (1). Also, keep in mind that matrix multiplication isn’t commutative, i.e AB is not guaranteed to equal BA. Now the transformed version of a vertex v by the transformation matrix M , v’ is given by the following equation:

v’=M*v

This will give you a new 4 component column vector since the product of two matrices has the same amount of rows as the premultiplier and the same amount of columns as the postmultiplier.
The value of each element i of this vector v’ will be the scalar (or dot or inner, whatever you prefer) product of the i:th row of the premultiplier (i.e. M) with the i:th column of the postmultiplier (i.e v). Since the v vector only has one column, i actually doesn’t change for it but that follows from the rules of matrix multiplication. Try this with a point at the origin, that is a column vector containing (0,0,0,1) transformed by a translation (Identity matrix with the translation vector added to upper right 3 components). It will work.
The reason some matrices you see are transposed is that some people treat vertices as row vectors and then obviously you have to transpose the transformation matrix. That is just the way it is :slight_smile: and if you don’t believe me check out the OpenGL spec.

Joakim

(PS. my attempts at editing mangled the quote at the top somnewhat, hope that isn’t too confusing)

[This message has been edited by harsman (edited 01-23-2001).]

x’y means y component of x’.
sx means scale x.
tx translate x.

The problem is not that I could tell that your thing is wrong, I can only say that if I use indices [2][6][10] I actually get the local z axis of my camera and do a roll (or however it is called) with it. That is confusing me, since you say that mine is wrong (since it is not just rotated around 90’, ie not transposed or how you call it).

Actually is there a good reason why to use the matrix stuff, I mean, what is the mathematical background that is works with them, also why can one combine two translations with them. What’s the brain behind it. I know it’s fast, but don’t know why it is exactly the way it is. Hope that makes sense.

Originally posted by Michael Steinberg:
[b]x’y means y component of x’.
sx means scale x.
tx translate x.

The problem is not that I could tell that your thing is wrong, I can only say that if I use indices [2][6][10] I actually get the local z axis of my camera and do a roll (or however it is called) with it. That is confusing me, since you say that mine is wrong (since it is not just rotated around 90’, ie not transposed or how you call it).

Actually is there a good reason why to use the matrix stuff, I mean, what is the mathematical background that is works with them, also why can one combine two translations with them. What’s the brain behind it. I know it’s fast, but don’t know why it is exactly the way it is. Hope that makes sense.[/b]

First of all, your transformation matrix (it’s not just translation as it performs scaling) is correct as far as translation and scaling go, but the axii should be columns instead of rows (like I laid it out before).
The camera confuses you because it is a bad example and here’s why: The reason that OpenGL combines the view transform and the model transform is that moving the camera forwards is equivalent to moving everything else backwards (think about what it feels like at a traffic light when the other cars move forward before you do, it feels as if you’re going backwards). So the camera transform is “inverted”. To make it look as if the camera is moving forward you actually apply a transform that moves everything else backwards. And the way to do that is of course to use the transpose (the transpose of a transform * the transform will yield the identity matrix). Sorry I didn’t say this earlier it must have been confusing. That’s why what I’ve said seems wrong for your camera, although it actually isn’t. As usual math prevails! :slight_smile: Seriously though, using matrices for this type of stuff has several good reasons, I’ll list some.

  1. Matrix transforms are easy to concatenate, you just multiply them with eachother. this is why both the model and view transform can be expressed as a single matrix.

  2. Transforms are not commutative, i.e. roatating around the x axis 45 degrees and then translating is not the same thing as doing it in the reverse order. Matrix multiplication is not commutative either so it fits nicely here.

  3. If you use homogenous coordinates you can treat vectors and points equal and everything from modelview transform to normalized clip coordinates can be done with 4x4 matrices.

If you get a good linear algebra book and go through this stuff you’ll get a much better understanding of why OpenGL does what it does and as an added bonus it’ll help with nearly all things 3d related. Oh, and you don’t have to rotate around the world axes and combine this together when rotating your objects, just supply the column vectors from the transform (of the axis you want to rotate around) to your rotate around vector function and you should be ok.

[This message has been edited by harsman (edited 01-23-2001).]

Well, I’ve got a ‘linear algebra’ book here, but it’s nearly ununderstandable. It starts with what we call “mengen”(for example all integers) has lots of words in it that I didn’t even hear yet. I’m at page 13, I think.
But you say this will be covered in the book? Then I’m gonna try to get further.

I didn’t get what you meant about my space ship. The problem with the spaceship was, that there was no defined ground or ceiling obviously. So I though that one has to “rotate” the rotation matrix around the local axes of the space ship. Oh man, I don’t understand that.
How to calculate the transpose of a matrix?

Transpose is easy, you just have to swap the values around.

So:
1 2 3
4 5 6
7 8 9
becomes
1 4 7
2 5 8
3 6 9

Now back to coding.

Ok.
Can I use the matrix determinant?
And how I can implement it?

Why do you want to use determinants? I think they are only used for calculating the inverse of a matrix, and caculating multiple solutions. (I think… it has been a very long time since I cracked open a book).

Originally posted by Michael Steinberg:
[b]Well, I’ve got a ‘linear algebra’ book here, but it’s nearly ununderstandable. It starts with what we call “mengen”(for example all integers) has lots of words in it that I didn’t even hear yet. I’m at page 13, I think.
But you say this will be covered in the book? Then I’m gonna try to get further.

I didn’t get what you meant about my space ship. The problem with the spaceship was, that there was no defined ground or ceiling obviously. So I though that one has to “rotate” the rotation matrix around the local axes of the space ship. Oh man, I don’t understand that.
How to calculate the transpose of a matrix?[/b]

If the linear algebra book is too hard, maybe you should wait a while with this stuff until you’ve learned a bit more algebra in school. Since this level math is usually taught at university level, most books assume you’re pretty advanced, so it appears complex although linear algebra isn’t as hard as it might seem. try searching for more introductory texts to matrices and vectors on the net.

Are you trying to rotate the spaceship around one of it’s local axes? That is, the spaceship is described in a local coordinate system where e.g z points along the front of the ship and when you have it positioned in your world pointing in some direction you want to make it do a roll, i.e. rotate around its local z-axis. Was that what you meant? If it was it’s simple. First of all there’s always an origin no matter if there’s a ground or not: the identity matrix. Think about it, it defines the axes as the unit vectors in euclidian 3-space and the position as origo. The local axes of your spaceship are defined relative to this coordinate system, so you just rotate the ship around the vector that is your local z-axis, i.e. the top three elements of the third column in the spaceships transform.

Originally posted by FoxDie:
Ok.
Can I use the matrix determinant?
And how I can implement it?

What do you want to do with the matrix determinant? You can use it to find out if there’s an inverse but for orthogonal matrices the inverse equals the transpose. Since transposing is much faster than inverting just transpose if your matrix is orthogonal.

Yes, harsman, that seems to be quite that what I’m currently doing.

I start with the identity matrix, which means that z axis points to where the ship currently is. Then, when the ship rotates around a certain axis (although it’s rotating around at least 2 axes, x and y, most of the time) I take the local axis out of the matrix and rotate around it. The really strange is, that I don’t get the columns, I get the rows, work with them as the local axes and it actually works!
Where you point out it has to be the columns which define the local axes, for me it works with rows. Or is it that I’m actually working with the transpose for the axis part when I’m not taking the columns but the rows, and transposes apply to cameras?

Now, when I’ve got that camera matrix, I can apply the transpose of it to my ship’s model to transform it to its world position.

With that no up and no down I meant, that I actually have to process my own matrix over all frames and I’m not able to only put up a pitch bob and roll like 1st person shooters can do it.

Oh, and I made ~20 pages yesterday evening… Hope to understand it. Could I bomb you with question emails? Okay, that’s a bit too much…

Okay, I thought about that transpose stuff, and actually think that my code is correct, if I read the rows instead of the columns, I actually read the matrix in the transpose form…

Another question pops out. There was a cube which was positioned at the orgin. I wanted to rotate it around it’s local axes (what is the plural of “axis” after all?). So I made it exactly as with the camera’s transform matrix. I keep my own matrix. Now it seemed logical to me that if I wanted to rotate around it’s local axes, I would have to get them from the current transla…errr transform matrix. When I used them to create a rotation matrix, the cube behaved strange (I would now get the columns instead of the rows, but I don’t believe it will work then). Now when I simply rotated around the worlspaces axes (or axises or…) it worked beatifully. Why that?

Now, is it just me or and I right when I say, it doesn’t matter how you conceptualize the layout of the matrix. i.e.

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

and

1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16

make no difference. That’s just how you conecptualize them. All that really matters is the meaning of each position in the lenear array. For example, matrix[12],[13] and [14] represent the X, Y and Z position of the matrix. For example, if you’re using a matrix with a spaceship, then you can look to elements 12,13, and 14 for the x,y and z (respectively) center of the ship in worldspace. THATS ALL THAT MATTERS! You can list the elements however you want on “paper” but it doesn’t make a lick of difference. Arguing about whether it’s 123 or 321 or what have you is futile! Instead, you should only be concerned about the actual meaning of each array element. Then, you can concoct a structure instead of using an array and it makes things sweet to use:

<pre>
struct matrix
{
VERTEX right;
GLfloat pad0;
VERTEX up;
GLfloat pad1;
VERTEX front;
GLfloat pad2;
VERTEX pos;
GLfloat pad3;
}
</pre>

Where VERTEX is a vertex structure that contains a x,y anx z made of GLfloats. Then right is the right vector (points directly to the right of your ship/character or whatever), up is your up vector (points up from your ship), front points to the front of your ship (defines in which direction your thing is facing), and finally pos is the location of your object. pad1,pad2,etc… are required to lay the matrix out correctly. This makes it a 4x4 matrix. If you’ll notice, under the vast majority of circumstances, these pad values never change once intialized to their identity values. Now all you have to do to use these with OpenGL is to cast them to a float *. And now all you have to do if you want the location of an object is:

matrx object;

object.pos;

or

object.pos.x; // get’s the x coordinate of your object

This is also very useful for using a matrix as a camera with gluLookAt()! If you look at the order of this struct, you’ll see that if can be broken down to a 16 element array (As far as the memory is concerned). The struct’s elements should be stored sequentially just like the elements of an array. I personally use this sort of structure in my programs ALL THE TIME and they work! I have to give credit to Nutty for this as he is the one who showed me this technique. Search for “Deciphering Opengl’s modelview matrix” in the beginner’s forrum for more info.

Well, I hope this helps. Just bear in mind that it doesn’t matter how you lay it out on paper - whether you read it from top to bottom or left to right. If you’re going to discuss matrices, PLEASE only use actual element numbers or something like that since that is the only concrete frame of reference for everybody. Thanks!

I think we already came to that conclusion. This is why I called the elements x’x and so on. Draw these elements on the paper (there is only one correct representation of a matrix on the paper), and lay opengl’s indices over it. I’ve asked more theoretical questions later on. So, harsman, if you’ll be so nice to me, could you look at my previous posting? Thanks!

Punchey, what Nutty uses does work, and if you want to, you can use union m[16] if you want to access the matrix by elements.

For example, in my code, I have:
dirVector = GMZPrime(&cameraMatrix);
Which is = to m8,9,10, but since the camera matrix is actually the transpose of a “normal” matrix, that is what the issue was. Since m8,9,10 = m 2,6,10 (transposed)

So if you use nuttys structure, on a camera matrix, and a normal matrix, the results will be different. Since you (the camera) are looking into a mirror basically. (if you move left, the world moves right…and so on)
Which also means that it depends if you are modifying the camera matrix, or if you are modifying a non-camera matrix, since the 2 are not the same (they are the transpose of each other).

Oh, I forgot to mention that the transpose of the rotation matrix is = to the inverse if the matrix is orthogonal…

Hopefully that is all correct.

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

Michael Steinberg, I did not intend to come across harsh. I apologize. But I will still contend that it doesn’t matter how you write it on paper because you can read it differently regardless of how you write it. If you write it like 123… you can read it from left to right, if you write it like 1 5 9 … you can read it from top to bottom. Believe me, I’ve gone around and around with this and, as far as OpenGL is concerned, you can write it however you want, the trick is in how you read it. And you can’t ensure that another person is reading it correctly unless you make explicit which array elements correspond to which vectors.

Elixer, I think the whole transpose thing completely depends on how you preffer to do your camera operations. I’m using Nutty’s matrix strucure mentioned above for my camera AND for my world objects and have not had any thing like the problem you described that I would have. I am using gluLookAt and all I have to do to orient the camera properly is to reverse my front vector. This way, all I have to worry about is the location, direction, etc. of my camera in world space which is the easiest and most intuitive way to do it, IMHO. Let me know if this works for you.