Orientation matrix

Started by
7 comments, last by Aressera 16 years, 6 months ago
Hi, I'm representing the orientation of an object using two vectors: forward and up. This is similar to how you might represent a camera. In the case of a camera, I can use a "look at" matrix to rotate the world to the correct orientation. Such a matrix would look like this:

	f = forward
	u = up
	r = right = f x u

	[  r.x   r.y   r.z  0 ]
	[  u.x   u.y   u.z  0 ]
	[ -f.x  -f.y  -f.z  0 ]
	[   0     0     0   1 ]
Which works perfectly well. However, what I want to do is to be able to rotate an object in a similar way, but obviously with a slight difference because the look at matrix is a sort of inverse rotation matrix, as it were. If I try to use the look at matrix then although my object is rotated, it tends becomes transformed so that it's back to front and so on. I've tried to work out the matrix for correctly transforming an object but I can't get quite get it to work! I presume I can use something very similar to the look at matrix above, but can't work out what it is. Can anybody help me? Cheers, Chris. [Edited by - chris00 on September 25, 2007 5:15:43 AM]
Advertisement
Just transpose the look-at matrix to get the rotation matrix. The inverse of a rotation matrix is its transpose. Although I'm not sure if you should be negating an axis like that...your problem could be from using reflection matrices instead of rotation matrices, but it's hard to tell, since different graphics APIs use different conventions for their matrices and handedness.
Thanks. I'm not sure about negating the f axis either - I just read it somewhere (on this site I think), and it seemed to work!

So, I've now got:

        [  r.x  u.x  -f.x  0 ]	[  r.y  u.y  -f.y  0 ]	[  r.z  u.z  -f.z  0 ]	[   0    0     0   1 ]


This almost works. x and y rotations are correct, but my object is reflected in the z direction and z rotation is inverted. I think this may possibly be down to me using the OpenGL right hand co-ordinate system?? Is that it, and if so, do you know how I can fix it?

Thanks.
Actually, ignore that - I think it does work.
Cheers.
OpenGL uses a right-handed coordinate system, so that last column should not be negated. However, if you were using directX, it would be.

What you should be doing is building your model-view matrices out of rotation matrices, not the other way around.

standard rotation matrix:
[ x.x  y.x  z.x ][ x.y  y.y  z.y ][ x.z  y.z  z.z ]


where the vectors x, y, and z are the local axes of the coordinate system given by the rotation. These should be unit vectors that orthogonal (are all perpendicular to each other), such that z = x cross y.

Now, in order to convert this matrix into a format that your rendering API can use, you need to switch things around. Technically this is unnecessary, but it depends on how you want the matrix to be represented.

both OpenGL and DirectX use row vectors instead of column vectors, so your 4x4 modelview matrix is given by the following:

[ m[0] = x.x | m[1] = x.y | m[2] = x.z  | m[3] = 0  ][ m[4] = y.x | m[5] = y.y | m[6] = y.z  | m[7] = 0  ][ m[8] = z.x | m[9] = z.y | m[10] = z.z | m[11] = 0 ][ m[12] = 0  | m[13] = 0  | m[14] = 0   | m[15] = 1 ]


or alternatively:
[ m[0] = x.x | m[4] = y.x | m[8] = z.x  | m[12] = 0 ][ m[1] = x.y | m[5] = y.y | m[9] = z.y  | m[13] = 0 ][ m[2] = x.z | m[6] = y.z | m[10] = z.z | m[14] = 0 ][ m[3] = 0   | m[7] = 0   | m[11] = 0   | m[15] = 1 ]


in DirectX, since it uses a left hand coordinates (this is abnormal), you need to negate the z vector.

Finally, if you want to encode a translation into the matrix as well, put the x, y, and z components of the position in indexes 12, 13, and 14.
Thanks for the clarification. After messing around with it a bit myself I also came to the conclusion that the last column should not be negated.

Final question: Have I got the look at matrix right, ie. with the forward vector negated? It certainly "appears" to work correctly...

        f = forward	u = up	r = right = f x u	[  r.x   r.y   r.z  0 ]	[  u.x   u.y   u.z  0 ]	[ -f.x  -f.y  -f.z  0 ]	[   0     0     0   1 ]
Yes, that seems correct, assuming you want the right vector to represent the x vector, up to represent the y, and forward to represent the z vector, which seems correct.

One last thing, your cross product is in the wrong order (it's not commutative). Your r = f x u should be r = u x f. This is why you have to negate the f vector.

the following should all be equivalent:
f = r x ur = u x fu = f x r
If I have up x forward then in a RH system wouldn't that make the right vector go along the +ve x axis? If so, then this must be left, not right - correct? I just checked the gluLookAt() documentation and they also use forward x up, and -ve forward in the matrix:

http://pyopengl.sourceforge.net/documentation/manual/gluLookAt.3G.html

I did try it with up x forward and +ve forward in the matrix, but I ended up looking backwards!

The things I said come from the right-hand rule and the definition of an orthogonal basis for coordinate systems.

geometrical interpretation for a cross product:

a = b x c

let vector b be your index finger, vector c be your middle finger perpendicular to your palm. Then vector a is given by the direction of your thumb sticking up in the air. This is the right-hand rule, and is used to determine the direction of the result of a cross product in a right-handed coordinate system.

Likewise, do the same thing with your left hand, and the result of the cross product will be opposite what it would be with your right hand. This is what left-handed coordinate systems use.

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

Basically, depending on which two vectors you are given, you will use some permutation of the following:
f = r x ur = u x fu = f x r

to generate the other, where r = x, u = y, f = z.

This topic is closed to new replies.

Advertisement