PDA

View Full Version : glMultMatrixf(GLfloat *m );



FoxDie
01-11-2001, 06:43 AM
I'm trying to transform the modelview matrix.
I had declared pointer matrix[4][4] of GLfloat.
And this is a problem code:

void Transform()
{

glMultMatrix()
glLoadIdentity();

};

Then I recived message:The glMultMatrix request reinterpret_cast.
How I could declare the matrix?

j
01-11-2001, 07:31 AM
As a single dimensioned array:

GLfloat matrix[16];

I forget what order the rows and columns are stored though.

j

Serge K
01-11-2001, 10:12 AM
or -

GLfloat matrix[4][4];

glMultMatrix( matrix[0] );

FoxDie
01-11-2001, 11:18 AM
Thank you very much.

Michael Steinberg
01-11-2001, 11:31 AM
Serge K:
Is that really the clean way to go? I mean, does C guarantee, that in two dimensional arrays, the "columns" follow without physical memory seams?

OpenGL uses matrices in column order meaning:

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

Elixer
01-11-2001, 01:13 PM
No, that is [B]wrong[\b].

OpenGL does:

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

BTW, why would you Mult the matrix, then call identity?
Oh, and it is better to do glfloat Matrix[16] http://www.opengl.org/discussion_boards/ubb/smile.gif As a matter of fact some intresting tricks can be done with this, if you use union. http://www.opengl.org/discussion_boards/ubb/smile.gif (search the message board, there was a good example of this a few weeks (months?) back.

Zadkiel
01-11-2001, 02:41 PM
I never used "d arrayer instead I always used 1d and never had any problems.
If get it to load the check out win32asm.virtualave.net under the programming section for some uses for matrices.

Bob
01-11-2001, 09:25 PM
The Red Book says that a matrix in OpenGL is represented the way Michael says.

Have a look in the online copy of the book. http://ask.ii.uib.no/ebt-bin/nph-dweb/dy...lhtml;pt=7170#X (http://ask.ii.uib.no/ebt-bin/nph-dweb/dynaweb/SGI_Developer/OpenGL_PG/@Generic__BookTextView/7170;cs=fullhtml;pt=7170#X)

Michael Steinberg
01-12-2001, 07:33 AM
Thanks Bob...
Shame on you Elixer! http://www.opengl.org/discussion_boards/ubb/smile.gif

Oh, you wouldn't need unions to have these cool effects, by the way. You can also set the byte aligning for the structs. Might be a bit unclean, but should work.

Elixer
01-12-2001, 08:34 AM
Hmm, well, I know what your looking at, but that is the way math books have it. The way openGL handles it IS the way I said it.

Or if you like:
xX Xy Xz 0
yX yY yZ 0
zX zY zZ 0
lx ly lz 1

And doing a quick seach on google, I found "Matrices can be your Friends. By Steve Baker"
which also says:
Take an opengl matrix:

float m [ 16 ] ;


Consider this as a 4x4 array with it's elements laid out like this:

0 1 2 3
4 5 6 7 THE OPENGL WAY
8 9 10 11
12 13 14 15


Yes, I know mathmaticians like to lay the numbers out differently... They prefer
to number them like this:

0 4 8 12
1 5 9 13 THE MATHEMATICIANS WAY
2 6 10 14
3 7 11 15

--------------

So are we all happy now? And shame on you all for doubting me! http://www.opengl.org/discussion_boards/ubb/smile.gif
(LOL)

Michael Steinberg
01-12-2001, 09:12 AM
I meant the actual order of the elements in memory for opengl. So, physically, the matrix is given to it the way I say.

Michael Steinberg
01-12-2001, 09:16 AM
If it is written in the RedBook, it rules for OpenGL. Did you ever handle the matrices actually in your own program or are you only using the gl functions?

I'm getting totally confused, actually... Shame on you... http://www.opengl.org/discussion_boards/ubb/smile.gif Anyway, explain it to me more exactly, please.

Michael Steinberg
01-12-2001, 09:19 AM
My (german) math book tells me:

0 1 2 3
4 5 6 7
8 9 19 11
12 13 14 15

My openGL book sais that one should keep in mind that opengl matrices are handled the other way.
Anyway, currently reading Stephen Hawkings short story of time. Seems to be very interresting from what I saw yet... http://www.opengl.org/discussion_boards/ubb/smile.gif

Michael Steinberg
01-12-2001, 09:28 AM
It interresting me very much if we're saying the same thing. These are indices of the float[16] array I drew as numbers into the matrix. This is the only logical expression for an opengl matrix, since you can't tell opengl that you want something to be a row or whatever.

To get clear:
float matrix[16];

A mathematical visual represantation of a matrix, indices are obvious

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

So the z axis has the elements 2,6 and 10.

Elixer
01-12-2001, 09:29 AM
Heh http://www.opengl.org/discussion_boards/ubb/smile.gif Confusion rules! http://www.opengl.org/discussion_boards/ubb/smile.gif

ok... snip type :
..
modelO.gMatrix( rotMatrix2 );
glMultMatrixf( rotMatrix2 );
glTranslatef( -modX, -modY, -modZ );// ... and translation.
OBJmodel.Draw(mod2, GLM_SMOOTH|GLM_MATERIAL|GLM_TEXTURE );
glGetFloatv(GL_MODELVIEW_MATRIX, mat1);
..

now, if we do a dump of mat1, like using:
..
text.Draw("%.2f %.2f %.2f %.2f",mat1[0],mat1[1],mat1[2],mat1[3]);
text.Draw("%.2f %.2f %.2f %.2f",mat1[4],mat1[5],mat1[6],mat1[7]);
text.Draw("%.2f %.2f %.2f %.2f",mat1[8],mat1[9],mat1[10],mat1[11]);
text.Draw("%.2f %.2f %.2f %.2f",mat1[12],mat1[13],mat1[14],mat1[15]);
..
would yeild the idenity matrix (say model was at 0,0,0) so the dump would be
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
and if we would translate the model to (-1,2,3) and dump matrix, it would be
1 0 0 0
0 1 0 0
0 0 1 0
-1 2 3 1
and if we truned model around (z axis) the dump would be
1 0 0 0
0 1 0 0
0 0 -1 0
-1 2 3 1

So that means the bottom row tells you where the object is in the world.

(and yes, this is from a program I am doing).

Elixer
01-12-2001, 09:32 AM
Yeah, so your 2,6,10 is my 8,9,10 http://www.opengl.org/discussion_boards/ubb/smile.gif

Now, lets all have a party. http://www.opengl.org/discussion_boards/ubb/biggrin.gif

Michael Steinberg
01-12-2001, 09:34 AM
So you aren't outputting the matrix correctly. You must output it the way I described.

Michael Steinberg
01-12-2001, 09:36 AM
The identity matrices' elements don't get affected by your wrong output (think about it).

Michael Steinberg
01-12-2001, 09:37 AM
It's wrong what you're doing. wrong wrong wrong. Ahhhhhhhhh.!:="%''"$*
Okay, getting down again... http://www.opengl.org/discussion_boards/ubb/smile.gif have fun, I said all.

Michael Steinberg
01-12-2001, 09:39 AM
Actually, the rightmost column is the translation, not the most bottom row.

Elixer
01-12-2001, 09:45 AM
Huh? What part is wrong? That is the output in my program... grumbles...and it is working, grumble...... ... ..

Heck, I'll just post this: http://www.opengl.org/discussion_boards/ubb/biggrin.gif



Matrices can be your Friends.Matrices can be your Friends.
By Steve Baker
What stops most people from getting friendly with matrices is that they look
like 16 utterly random numbers. However, a little mental picture that I have
seems to help most people to make sense of what's going on. Most programmers are
visual thinkers and don't take kindly to piles of abstract math.
Take an opengl matrix:

float m [ 16 ] ;


Consider this as a 4x4 array with it's elements laid out like this:

0 1 2 3
4 5 6 7 THE OPENGL WAY
8 9 10 11
12 13 14 15


Yes, I know mathmaticians like to lay the numbers out differently... They prefer
to number them like this:

0 4 8 12
1 5 9 13 THE MATHEMATICIANS WAY
2 6 10 14
3 7 11 15


...but we are OpenGL programmers - not mathematicians - right?! The reason
OpenGL arrays are laid out in the opposite direction to mathematical convention
is somewhat lost in the mists of time. However, it turns out to be a happy
accident as we will see later.
If you are dealing with a matrix which only deals with rigid bodies (ie no
scale, shear, squash, etc) then the last column (array elements 3,7,11 and 15)
are always 0,0,0 and 1 respectively and so long as they always maintain those
values, we can safely forget about them for now.
The first three elements of the bottom row of the matrix is just the overall
translation. If you imagine some kind of neat little compact object (like a
teapot), then the bottom row tells you where it is in the world. It doesn't
matter what combinations of rotations and translations it took to produce the
matrix, the bottom row tells you where the object basically is.
OK, so now we are down to only nine random-looking numbers. These are the first
three elements of each of the top three rows - and collectively they represent
the rotation of the object.
The easy way to decode those numbers is to imagine what happens to four points
near to the origin after they are transformed by the matrix:

(0,1,0)
| /(0,0,1)
| /
|/___(1,0,0)
(0,0,0)


These are four vertices on a 1x1x1 cube that has one corner at the origin.
After the matrix has transformed this cube, where does it end up?
Well, if we neglect the translation part (the bottom row), then the pure
rotation part simply describes the new location of the points on the cube:

(1,0,0) ---> ( m[0], m[1], m[2] )
(0,1,0) ---> ( m[4], m[5], m[6] )
(0,0,1) ---> ( m[8], m[9], m[10])
(0,0,0) ---> ( 0, 0, 0 )


After that, you just add the translation onto each point so that:

(1,0,0) ---> ( m[0], m[1], m[2] ) + ( m[12], m[13], m[14] )
(0,1,0) ---> ( m[4], m[5], m[6] ) + ( m[12], m[13], m[14] )
(0,0,1) ---> ( m[8], m[9], m[10]) + ( m[12], m[13], m[14] )
(0,0,0) ---> ( 0, 0, 0 ) + ( m[12], m[13], m[14] )


Once you know this, it becomes quite easy to use matrices to position objects
exactly where you need them without messing around with multiple calls to
glRotate.
Just imagine a little cube at the origin - pretend it's firmly attached to your
model. Think about where the cube ends up as the model moves - write down where
it's vertices would end up and there is your matrix.
So, if I gave you this matrix:

0.707, 0.707, 0, 0
-0.707, 0.707, 0, 0
0 , 0 , 1, 0
10 , 10 , 0, 1


...you could easily see that the X axis of that little cube is now pointing
somewhere between the X and Y axes, the Y axis is pointing somewhere between Y
and negative X and the Z axis is unchanged. The entire cube has been moved 10
units off in X and Y. This is a 45 degree rotation about Z and a 10,10,0
translation! You didn't need any hard math - just a mental picture of what the
little cube did - and no concerns about the order of operations or anything hard
like that. What would have happened to something out at 100,100,0? Well, just
imagine it was glued to the cube (on the end of a long stick)...as the cube
rotated, the thing at 100,100 would have moved quite a bit too - in fact, you
can see that the rotation would put it onto the Y axis and the translation would
have moved it 10 units up and to the right.
With practice, you can figure out what that last column does to the little cube.

So, would you like to know how to use a matrix to squash, stretch, shear, etc?
Just think about where the axes of that little cube end up - write them down and
you are done. What does a cube of jello look like when there is a strong wind
blowing from X=-infinity?

1 , 0 , 0, 0
0.3, 0.9, 0, 0
0 , 0 , 1, 0
0 , 0 , 0, 1


Look - the Y axis is leaning a third of a unit to the right and the cube got a
bit shorter.
Suppose your cartoon character is going to jump vertically, and you want to do a
bit of pre-squash before the jump... and post-stretch during the jump. Just
gradually vary the matrix from:

1 , 0 , 0, 0 1 , 0 , 0, 0
0 , 0.8, 0, 0 0 , 1.2, 0, 0
0 , 0 , 1, 0 ===> 0 , 0 , 1, 0
0 , 0 , 0, 1 0 , 0 , 0, 1


Not bad - he got shorter then longer - how about getting a bit fatter too
(conservation of cartoon volume) ?

1.2, 0 , 0 , 0 0.9,0 , 0 , 0
0 , 0.8, 0 , 0 0 ,1.2, 0 , 0
0 , 0 , 1.2, 0 ===> 0 ,0 ,0.9, 0
0 , 0 , 0 , 1 0 ,0 , 0 , 1


Now the cube got smaller in Y and bigger in X and Z then got bigger in Y and
smaller in X/Z...easy!
Not only is it easier to think transforms out this way, but it's invariably more
efficient too. By seeing the entire transformation as one whole operation on a
unit cube, you save a long sequence of glRotate/glTranslate/glScale commands -
which each imply a complicated set of multiply/add steps to concatenate the new
transform with whatever is on the top of the stack.
Finally, there is one matrix that we all need to know - the "Identity" matrix:

1, 0, 0, 0
0, 1, 0, 0
0, 0, 1, 0
0, 0, 0, 1


As you can see, this matrix leaves all the axes completely alone and performs no
translation. This is a "do nothing" matrix.
Matrices are really easy - it's just a matter of looking at them pictorially.

Michael Steinberg
01-12-2001, 09:50 AM
From official opengl conventions, you're outputting the thing incorrectly. Baker or however he is called is also wrong in that part.

Michael Steinberg
01-12-2001, 09:55 AM
You can see, that he is doing all these operations differently as normally done. He sais mathematians would do it like this:

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

And he sais opengl would have it like this:

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

But that is the other way around. He is not doing any mathematics WRONG. He just mixed the representations of the matrices. The mathematics are adapted carefully so they would perform correctly in this mixed up thing. Any opengl literatur that I read stated the matrix format to be the upper one.
This is more a question of how to write a matrix than how to work with it.

Michael Steinberg
01-12-2001, 09:59 AM
This is a big problem, since when there are any readers, they could use the wrong indices to calculate with. We should clear that up before telling anyone what to do, I think.

Elixer
01-12-2001, 10:05 AM
Hmm..the output is wrong?

Just using the idenity matrix, ie: glLoadIdentity();
glGetFloatv(GL_MODELVIEW_MATRIX, mat1);

the output is:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
Or as the VC++ debugger has it:
0x0,0x5,0xa,0xf = 1.0
all the rest = 0.0, so in other words,
m0,m5,m10,m15 = 1.0 which is correct is it not?

My head hurts now. http://www.opengl.org/discussion_boards/ubb/smile.gif

Michael Steinberg
01-12-2001, 10:16 AM
So you got what I mean? Your ressource was wrong.

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

is correct.

Michael Steinberg
01-12-2001, 10:18 AM
Oh, ****, I think you didn't get it.
We both have the same things being 1.0, since your misinterpretation of the matrix isn't incorrect for the main diagonal (which is used in the identity matrix).
So, the identity matrix is no good example.

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

Michael Steinberg
01-12-2001, 10:28 AM
But from what I read from you, the indices for the axises are wrong.

matrix[2] is the x for z'
matrix[6] is the y for z'
matrix[10] is the z for z'

Play around with rotation matrices to see what I mean.
I am so sure, because my thing works for me. And I don't think that we're saying the same.

Elixer
01-12-2001, 10:34 AM
Slap...cough... bang.. ok, that cleared it up... (I also that was a bad example, since the idenity matrix is the same in both cases http://www.opengl.org/discussion_boards/ubb/smile.gif) hehe.

So, looking at the openGL FAQ (which lists 2 sites to check, that Steve Baker, and Hexapods (hexapod@netcom.com))
Hexapod says: (which Steve has backwards)

This Document OpenGL
| 0 1 2 3 | | 0 4 8 12 |
| 4 5 6 7 | | 1 5 9 13 |
| 8 9 10 11 | | 2 6 10 14 |
| 12 13 14 15 | | 3 7 11 15 |

--------------

That will show me for only relying on 1 source. I guess it would have shown up as soon as I started rotating the model and wonder why the element had the wrong value http://www.opengl.org/discussion_boards/ubb/smile.gif

So I stand corrected. http://www.opengl.org/discussion_boards/ubb/biggrin.gif
It should have been dummped as:
..%.2f %.2f %.2f %.2f",mat1[0],mat1[4],mat1[8],mat1[12]);
..%.2f %.2f %.2f %.2f",mat1[1],mat1[5],mat1[9],mat1[13]);
..%.2f %.2f %.2f %.2f",mat1[2],mat1[6],mat1[10],mat1[14]);
..%.2f %.2f %.2f %.2f",mat1[3],mat1[7],mat1[11],mat1[15]);




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

Michael Steinberg
01-12-2001, 10:38 AM
Can't see anything inside that... Try [CODE] statement.

Michael Steinberg
01-12-2001, 11:00 AM
Okay. I'm happe not to change my engine... http://www.opengl.org/discussion_boards/ubb/smile.gif
You must know, sometimes inbetween I wasn't sure about my POV.

Elixer
01-12-2001, 11:19 AM
It is kinda funny though, Out of the 2 sites the FAQ lists, 1 had it backwards. So that is a 50/50 shot of getting it correct. http://www.opengl.org/discussion_boards/ubb/smile.gif

It is nice to get it straight though. I also e-mailed Steve, to see what he has to say. http://www.opengl.org/discussion_boards/ubb/smile.gif

Oh, forgot for anyone stumbling onto this long thread,
xX,xY,xZ = m0,m4,m8 (x axsis)
yX,yY,yZ = m1,m5,m9 (y axsis)
zX,zY,zZ = m2,m6,m10 (z axsis)
lX,lY,lZ = m12,m13,m14 (this is the translation)
[Hope I got that correct now. http://www.opengl.org/discussion_boards/ubb/wink.gif]



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

Magnus W
01-13-2001, 05:19 AM
According to Computer Graphics (Hearn & Baker, Prentice Hall publishing):

A transformation matrix for a translation (and they are doing the "mathematical" one) is:

1 0 0 tx
0 1 0 ty
0 0 1 tz
0 0 0 1

i.e. the translation goes to the right "mathematically".

The issue here is that mathematics and openGL don't really label the order of matrix elements differently; instead it is OpenGL that uses the transpose matrix of what a mathematician would use. OpenGL is "column major", whereas mathematics, C and pretty much the rest of the world are "row major". So you're both right, kind of :-)
Michaels is right about the fact that ([2] [6] [8]] is (x y z) for the z axis (mathematically). however, it should be output as elixir does.. Am I making any sense? :-)

An example, for the x translation:
Mathematic[3] = OpenGL[12]
which makes:
Mathematic[tx] = OpenGL[tx]

There's even an OpenGL extension for dealing with this.
http://oss.sgi.com/projects/ogl-sample/registry/ARB/transpose_matrix.txt

So in OpenGLmemory, we would store the (mathematical) matrix
a b c d
e f g h
i j k l
m n o p
as:
[a e i m b f j n c g k n d h l p]

I think it's easier to always number matrices:

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

since that's the mathematical way, and then know that what I read from index 12 in OGL is the x translation. Same numbering for math and OGL that is.

[This message has been edited by Magnus W (edited 01-13-2001).]

Michael Steinberg
01-13-2001, 06:54 AM
Yeah.
Well, since you say that a transformation matrix looks like you stated, elixers output of it was incorrect. With these numbers, I mean the memory distances from the "start" of the array. I would advice anyone to use a [16] array to handle matrices.

Magnus W
01-13-2001, 07:09 PM
I'm not even sure what's right and wrong anymore : )

Let's just say Elixir outputs it the way it's stored in memory, given that C/C++ is row major. It -is- supposed to come out with translations at the bottom, i.e. as the transpose of the mathematical counterpart.

Next question tho', is it more expensive (processing-wise) to use [4][4] in C than to use [16]?

Gorg
01-13-2001, 09:08 PM
Boy was that a fun discussion!!! I just would like to add by saying that mathematics has nothing do with that. The math and opengl Matrix is the same, they represent the same concept.

the only thing is that C/C++ is row major(look at the standard) and Opengl wants column major. That only means the representation in memory.

Magnus, the performance depends on your compiler and whether the number of elements is a power of 2.

If the number of elements is not a power of 2, the speed is the same.

If it is, then a clever compiler will use shift and instead of normal multi to map an [i][j] call to (in row major) [(j*num_elems + i)*sizeof(data) ]

the efficient version is [(j<<num_elems + i)*sizeof(data) ]

in column major the formula is
[(i<<num_elems + j)*sizeof(data) ]


[This message has been edited by Gorg (edited 01-13-2001).]

Michael Steinberg
01-14-2001, 11:19 AM
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.

harsman
01-15-2001, 01:53 AM
Originally posted by Magnus W:
According to Computer Graphics (Hearn & Baker, Prentice Hall publishing):

A transformation matrix for a translation (and they are doing the "mathematical" one) is:

1 0 0 tx
0 1 0 ty
0 0 1 tz
0 0 0 1

i.e. the translation goes to the right "mathematically".

The issue here is that mathematics and openGL don't really label the order of matrix elements differently; instead it is OpenGL that uses the transpose matrix of what a mathematician would use. OpenGL is "column major", whereas mathematics, C and pretty much the rest of the world are "row major". So you're both right, kind of :-)
[This message has been edited by Magnus W (edited 01-13-2001).]


I thought I might clarify that OpenGL doesn't use transposed matrices, they are exactly the same matrices as in your book. The difference is what index points to what cell (which you point out very well with the examples). In linear algebra the index increases along each row, so 3 is top right, OpenGL indices increase downwards along the column so 3 is bottom left. C 2d arrays (eg. float m[4][4]) are row-major whihch means the indices will be wrong. That's why you should use float m[16] instead. If you have column major matrices you can write to the columns sequentially whihch might give a slight speed increase (since you often want to edit the axes or the position).

Elixer
01-21-2001, 11:06 PM
Michael wrote:
matrix[2] is the x for z'
matrix[6] is the y for z'
matrix[10] is the z for z'

Wait, is this correct or not then?:

/* Matrixes can be thought of as:
* 0 4 8 12
* 1 5 9 13
* 2 6 10 14
* 3 7 11 15
*/

/* alternately:
X'x Y'x Z'x Tx
X'y Y'y Z'y Ty
X'z Y'z Z'z Tz
0 0 0 1
*/

I was looking at another source, and they have the matrix as:
Xx Xy Xz Tx
Yx Yy Yz Ty
Zx Zy Zz Tz
0 0 0 1

It is 4AM now... so I can't think straight now... there is lots of conflicting info. Argh.

Michael Steinberg
01-22-2001, 04:15 AM
Oh, ****.
My stomach sais that the second and my said stuff IS correct. However, I need to get far behind all that mathematic stuff.

Will cost lots of time. Stop. Don't know where to get documention. Stop. Anybody knows. Stops. Waiting. Stop. Stop.

On the other side it may be that we all say the same stuff, but I can't see it. (And I think that this is quite probable, since I didn't see so many different answers to only one question yet.)

harsman
01-22-2001, 06:26 AM
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).]

Michael Steinberg
01-22-2001, 06:45 AM
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... http://www.opengl.org/discussion_boards/ubb/smile.gif

Thanks!

Elixer
01-22-2001, 08:26 AM
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 http://www.opengl.org/discussion_boards/ubb/smile.gif
[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).]

Michael Steinberg
01-22-2001, 12:49 PM
No, look more exactly at that what he calls the opengl way of indexing matrices.

My question's still in the room though.

Michael Steinberg
01-22-2001, 12:55 PM
Oh, ****, harsman, here's our cutting point.
I say this for a normal translation matrix:



x'x*sx 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???

harsman
01-23-2001, 01:38 AM
[BLOCKQUOTE]



x'x*sx 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???<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 A*B is not guaranteed to equal B*A. 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 :-) 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).]

Michael Steinberg
01-23-2001, 05:06 AM
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.

harsman
01-23-2001, 06:13 AM
Originally posted by Michael Steinberg:
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.


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! :-) 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).]

Michael Steinberg
01-23-2001, 10:40 AM
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?

Elixer
01-23-2001, 11:52 AM
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. http://www.opengl.org/discussion_boards/ubb/smile.gif

FoxDie
01-23-2001, 07:51 PM
Ok.
Can I use the matrix determinant?
And how I can implement it?

Elixer
01-23-2001, 08:20 PM
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).

harsman
01-24-2001, 02:15 AM
Originally posted by Michael Steinberg:
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?

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.

harsman
01-24-2001, 02:18 AM
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.

Michael Steinberg
01-24-2001, 05:50 AM
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...

Michael Steinberg
01-24-2001, 06:05 AM
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?

Punchey
01-24-2001, 07:11 AM
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!

Michael Steinberg
01-24-2001, 08:54 AM
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!

Elixer
01-24-2001, 09:07 AM
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. http://www.opengl.org/discussion_boards/ubb/biggrin.gif



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

Punchey
01-24-2001, 09:34 AM
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.

Michael Steinberg
01-24-2001, 09:47 AM
Well, I didn't think you had been harsh and I also not intended to be it. So let's forget that.

I never saw any guy that would write a translation matrix different than this:
1, 0, 0, tx
0, 1, 0, ty
0, 0, 1, tz
0, 0, 0, 1

I'm creative so I could think of that:

0, 1, 0, 0
tx, 0, 1, 1
1, tz, 0, 0
0, 0, 0, ty

I'm quite laughin a bit now... http://www.opengl.org/discussion_boards/ubb/smile.gif http://www.opengl.org/discussion_boards/ubb/smile.gif http://www.opengl.org/discussion_boards/ubb/smile.gif
But, to get to what I mean. There is kind of STANDARD REPRESENTATAION OF A MATRIX, AND STANDARD OPERATIONS APPLYING TO THAT REPRESENTATION. If not, any book would contain different ways of drawing matrices. I bet you will never find any other representation of that column based (the first one of cause) translation matrix.

Now if you lay the opengl pattern over it:

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

You can find the memory offsets of the elements when you want to put your drawn matrix into memory. I wouldn't understand if anybody drifted off from that easy line.

And in case, I don't mean to offend you. It's just that my theoretical question go in the background with this discussion... And I'm an ignorant! http://www.opengl.org/discussion_boards/ubb/smile.gif

harsman
01-24-2001, 10:22 AM
Originally posted by Punchey:
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.

You can label the elements of the matrix anyway you want provided the layout in memory is column major which is what OpenGL and your matrix struct uses. That was what the previous discussion was about, some people had got the layout in memory wrong, they used rowmajor matrices. You can't write it anyway you want on paper and expect people to understand it. A translation matrix is always:

1 0 0 tx
0 1 0 ty
0 0 1 tz
0 0 0 1

If it's not it's transposed. I think this is what you meant but I thought I'd make sure. Secondly you _are_ inverting (part of) the camera transform before putting it on the matrix stack, you said you are reverse the direction vector of your cameras transform, and provided you don't do any rolls (which you aren't if you're using gluLookAt) this is the same thing as transposing before applying it. Either you transpose or you reverse every modification to the transform (negate translation vectors and rotation angles etc). It all bogs down to the same thing, to get the effect of a camera you apply the inverse (transpose if it's orthogonal, which it should be) of the cameras transform. The reason you do this is because moving the camera forwards is the same thing as moving the rest of the world backwards.

harsman
01-24-2001, 10:25 AM
Originally posted by Michael Steinberg:
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?

Think about it, if you apply the transposed rotations it'll still look correct but with rotation angles reversed and translations going in the wrong direction. Try it with the columns and a camera and some other static objects and see what happens.

Punchey
01-24-2001, 10:29 AM
That's okay. I just know that if you say
<pre>
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
</pre>

I can read that as the top row being the first four elements of the array, or I can read it as the left most column being the first four elements of the array, or I can read it as the top row being the order in which the elements are interpreted by opengl but the rows are... for those who don't really know what they're doing, it's very difficult to tell what you're trying to say when you just list a bunch of numbers. And to make any sense of a number grid, you have to be very familiar with the traditional layout of a matrix used for 3D stuff.
Anyway, in my previous post, I forgot to mention that the best thing about being able to use the same matrix for objects and cameras without having to do any sort of transposing is the ability to simply jump around from object to object using each as the camera. For example, let's say you have a bunch of soldiers in a map and you want to be able to jump around and see through each of their eyes. All you have to do is switch your pointer (or copy the contents) to that object's matrix and BAM! You're suddenly looking from that object's perspective. If you used a different camera matrix format, then you'd need to do some conversion before being able to do this. But using this technique, it's a simple matter of changing a pointer:
<pre>
matrix soldier1, soldier2, *camera;

camera=&soldier1;
gluLookAt((float*)&camera...)
/* render scene */
camera=&soldier2;
gluLookAt(...
/* render scene */
<pre>

You get the idea. Anyway, it's really nice when all your matrices are interchangeable!

Punchey
01-24-2001, 10:52 AM
Okay, I wasn't doing any rolling, but now I tried it and I see what you mean. You're right I was reversing the front vector and I knew that. But I didn't do any rolling so I didn't notice that. Still, if you're not rolling, then it still might be a good way to go. If not, I suppose you could overload the = operator for your camera class to do the matrix assignments for your camera. But it'd be a shame to have to copy all 16 elements each frame if you're viewing through another object. But once you have the data loaded properly into your camera matrix, do you still just use the standard glRotate and glTranslate routines on it?

Elixer
01-24-2001, 11:02 AM
I don't bother with gluLookAt, I use loadmatrix, or multmatrix, because I am working in 6DOF, and as Harsman said, you don't have 6DOF (no rolls).

But in any case, you can still attach the camera with your method, or by using multmatrix (or loadmatrix for that matter), it just depends on what your code is doing.

Oh, also Punchey said: "But it'd be a shame to have to copy all 16 elements each frame if you're viewing through another object"

You do this no matter what, using lookat or mult/load matrix.
And you can still use glrotate/translate before or after the calls to multmatrix, again, it depends on what effect you want. But then you also can get that gimbal (sp?) lock, so I use quaternions for rotations, to avoid that.




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

Punchey
01-24-2001, 11:11 AM
Hmmm... I hate to do this, but, I beg to differ. As I just said, I tried doing rolls and I can roll using gluLookAt, it's just that it seems to be rolling backwards. gluLookAt should, indeed, represent a roll because it makes use of your up vector. Anyway, can someone detail for me how to transpose a matrix? And after you have a matrix that's been transposed, how can you mess with it from there? For example, if I'm using the matrix from an object, can I just transpose it and then continue to modify it using glRotate etc.? Or do I have to transpose it back, then glRotate it, THEN transpose it back again to use it for display?

Elixer
01-24-2001, 11:52 AM
If you are modifying the objects matrix directly, then you do need to use your own matrix routines. Then, you transpose the matrix if your are going to use it for a camera view. The only time I transpose the matrix is if I am going to attach a camera to it. Otherwise, it would be backwards in the world.
I use quaternions for rotations, then I convert the quaternions to a matrix, then if I want to attach camera to that object, I do a transpose to the matrix, and then I loadmatrix with the objects matrix. If I don't want to use the object as a camera, I do the same, but I don't transpose the object matrix.


Here is some code:
(this is inverse, n=a copy of matrix m)
m[0 ] = n[0 ]; m[1 ] = n[4 ];
m[2 ] = n[8 ]; m[4 ] = n[1 ];
m[5 ] = n[5 ]; m[6 ] = n[9 ];
m[8 ] = n[2 ]; m[9 ] = n[6 ];
m[10] = n[10];
m[12] *= -1.0f;
m[13] *= -1.0f;
m[14] *= -1.0f;
--
(this is transpose, again, n=copy of m)
m[0 ] = n[0 ]; m[1 ] = n[4 ];
m[2 ] = n[8 ]; m[3 ] = n[12];
m[4 ] = n[1 ]; m[5 ] = n[5 ];
m[6 ] = n[9 ]; m[7 ] = n[13];
m[8 ] = n[2 ]; m[9 ] = n[6 ];
m[10] = n[10]; m[11] = n[14];
m[12] = n[3 ]; m[13] = n[7 ];
m[14] = n[11]; m[15] = n[15];
-------------
So then you do:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
MCopy(&iCameraMatrix, &cameraMatrix);
MInverse(&iCameraMatrix);
VCopy(&iCameraPosition, MGetTranslation(&iCameraMatrix));
glLoadMatrixf(iCameraMatrix.m);
glTranslatef(iCameraPosition.v[X], iCameraPosition.v[Y], iCameraPosition.v[Z]);
...
drawobjects();
...




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

harsman
01-25-2001, 12:00 AM
Originally posted by Punchey:
Hmmm... I hate to do this, but, I beg to differ. As I just said, I tried doing rolls and I can roll using gluLookAt, it's just that it seems to be rolling backwards. gluLookAt should, indeed, represent a roll because it makes use of your up vector. Anyway, can someone detail for me how to transpose a matrix? And after you have a matrix that's been transposed, how can you mess with it from there? For example, if I'm using the matrix from an object, can I just transpose it and then continue to modify it using glRotate etc.? Or do I have to transpose it back, then glRotate it, THEN transpose it back again to use it for display?

Sure you can do rolls, you can treat your camera just like a normal matrix but then every operation you apply to ir will be reversed, translations will go the wrong way and rotations will rotate CW instead of CCW etc. I also spotted an error in my previous post by the way, the transpose only equals the inverse if the vectors of the matrix are both orthogonal and unitlength, i.e. the matrix is orthonormal. All rotation matrices are orthonormal and transforms are provided they don't contain translation or scaling. So to inverse a transform without scaling you could transpose the upper left 3x3 sub-matrix and negate the translation vector. That should be pretty quick.

Michael Steinberg
01-26-2001, 07:50 AM
What does it mean that a matrix is orthogonal?

DFrey
01-26-2001, 08:31 AM
An orthogonal matrix is simply a matrix whose inverse is equal to its transpose. Or if that sounds like circular logic, more exactly, for a square matrix A with components a(ij), if Sum over i of a(ij)*a(ik)=d(jk) , for all j,k where d is the Kronecker delta, then that matrix is orthogonal.



[This message has been edited by DFrey (edited 01-26-2001).]

Michael Steinberg
01-26-2001, 12:47 PM
Okay, which matrices happen to have the same inverse as transpose? http://www.opengl.org/discussion_boards/ubb/smile.gif
Thanks

DFrey
01-26-2001, 01:02 PM
The only transformation matrices that are orthogonal are rotational transformations, reflection transformations, and combinations thereof.

Michael Steinberg
01-26-2001, 01:41 PM
Where to find the inverse of the left transformation matrices is rather easy...

harsman
01-27-2001, 05:35 AM
Originally posted by Michael Steinberg:
What does it mean that a matrix is orthogonal?

It means that all the vectors are at right angles to eachother. If they're also of length one then the matrix multiplied by it's transpose will give you the Identity matrix.

DFrey
01-27-2001, 06:19 AM
If they're also of length one then the matrix multiplied by it's transpose will give you the Identity matrix.
Well, that follows simply because for any orthogonal matrix A, A^-1=A'. Since MM^-1=I for any non-singular matrix M, AA'=AA^-1=I. This has nothing to do with the length of the column or row vectors per se.

Michael Steinberg
01-27-2001, 08:29 AM
How to calculate M/1?

harsman
01-28-2001, 02:36 AM
Originally posted by DFrey:

If they're also of length one then the matrix multiplied by it's transpose will give you the Identity matrix.
Well, that follows simply because for any orthogonal matrix A, A^-1=A'. Since MM^-1=I for any non-singular matrix M, AA'=AA^-1=I. This has nothing to do with the length of the column or row vectors per se.




Yeah I know, I just wanted to give a definition that was easier to visualize. If a matrix is orthogonal that is defined to mean what you say but if you haven't read any linear algebra you might assume orthogonal means "all vectors are orthogonal". I just wanted to clarify in laymans terms, sorry if it came out somewhat uncorrect mathematically.

Nil_z
01-28-2001, 02:37 AM
I have studied both Michael and Elixer's code in these posts. I think you are talking about the same thing, maybe you are mixed up.

Elixer's matrix is exactly the same with Michael's, except the form of matrix. Elixer's matrix is in a D3D like form, and Michael's is in a OpenGL form. In D3D, if you have a vector, it is like (x, y, z), and in OpenGL, it is (x, y z)'. You see, one is the transpose of the other. So in D3D, if you transform v with a matrix M, it is vM, and in OpenGL, it is Mv. Anyway, although Elixer write his matrix in a D3D form, the item layout is correct, you will get the right answer under OpenGL.
I am confused about these two diffrent forms of matrix before. http://www.opengl.org/discussion_boards/ubb/smile.gif

harsman
01-28-2001, 02:40 AM
Originally posted by Michael Steinberg:
How to calculate M/1?
The inverse? It's kind of complicated, especially since there doesn't have to exist an inverse. I think there's source in the matrix and quaternion FAQ, do a web search on that. That FAQ should not be trusted completely though, it has a tendency to say quaternions are great for everything and that all other alternatives suck.

Elixer
01-28-2001, 08:57 AM
Ack, no...

You see, the way I had my matrix was the correct way, and so was the other way. The difference was that if you take the matrix from the "camera" and modify that, that is actually the inverse of a "regular" matrix.

Remember the camera is looking at something, so it would be like in a mirror. My left is World right and so on...

Michael Steinberg
01-28-2001, 11:10 AM
Yep, I had the correct matrix from my point of view, elixer the correct from his point of view.
I didn't happen to need my own modelview matrix for models yet, only for cameras.

Elixer
01-29-2001, 09:54 AM
Now I wonder if all this info will be put into a FAQ? It seems every 2 days someone asks about this... http://www.opengl.org/discussion_boards/ubb/smile.gif

Michael Steinberg
01-29-2001, 11:43 AM
Should we work on a FAQ? I'll join.

FoxDie
02-05-2001, 07:44 AM
Exist some web page with
matrixes operations?

Elixer
02-05-2001, 12:51 PM
I know someone was working on a FAQ, I forgot who took it over though. Too bad we can't forward all this thread to them. http://www.opengl.org/discussion_boards/ubb/smile.gif

(BTW, I meant the official openGL FAQ)

Nil_z
02-05-2001, 04:23 PM
I have downloaded the NVToolKit from nVIDIA, in its utility section there are some matrix class. Guess what? You needn't to take care about whether the matrix is in a D3D form of OpenGL form, you just apply translation and rotation using its interface function, and transform vector like v*M in D3D and M*v in OpenGL, all will get the correct answer! It is really a well designed user friendly matrix class for both D3D and OpenGL developers, although it is a little lack of function description.

[This message has been edited by Nil_z (edited 02-05-2001).]