Sign in to follow this  
jckut10

3D rotation around the object's axes, not the world's axes

Recommended Posts

I'm trying to write something in 3D and I've run across a problem. When I try to pitch or yaw, the model rotates around vectors parallel to the world's x and y axes instead of the model's x and y axes. Roll (z rotation) seems to be fine. Quaternions (as cool as they are) don't seem to help. When I'm using pitch/yaw/roll angles, future rotations should be relative to the current orientation, not the world's orientation, right? It seems that I am neglecting some fundamental principle of 3d rotation, and I can't figure out where I've gone wrong.

Share this post


Link to post
Share on other sites
Hmm... In which order are you performing your transformations? Are you perhaps translating before you rotate?

If so, try it the other way around (you don't mention which API you're using; I know that OpenGL, at least, applies latter-called trnasformations before previous ones, so that a glTranslate followed by a glRotate will result in the rotation occuring before the translation).

If you perform your rotations before your translations, they should be done around the origin, meaning that once you translate out to the object's position, it should appear as if it rotated around its own origin.

I hope that this helps. ^_^

Share this post


Link to post
Share on other sites
If you posted some of your code code we could probably help. :]

-Edit: Actually you could just fetch the x axis from the matrix and pass it as a parameter to your rotate function, and it's still dead easy to rotate around the world axis if you need it(just pass(1.0, 0.0, 0.0)). But if you really want the object to rotate around it's OWN (1.0, 0.0, 0.0) or whatever axis, try swapping the order in which you multiply your matrix with the rotation matrix. That does the trick in my software transformations BUT this way i can't rotate a sheared/non uniformly scaled reference frame without distortions. We still don't know if you re using any api like ogl or direct 3d.

if you have a basis matrix like this:

[x y z]
[x y z] * Rotation matrix
[x y z]

and do the above multiplication, you are rotating each basis vector about a world axis (you swap the "clockwiseness" of the rotation by transposing the rotation matrix), whatever this basis vector may be. If you do this:

[x x x]
[y y y] * Rotation matrix
[z z z]

or this:

[x y z]
RotationMatrix * [x y z]
[x y z]

you can rotate any ORTHOGONAL basis about a vector defined in this basis, but if your basis is sheared or scaled you ll get some distorions.

[Edited by - D_Tr on May 23, 2007 6:28:11 PM]

Share this post


Link to post
Share on other sites
[edit] DTr, I posted this before your edit.. looking at that now. Thanks.

I'm actually not using an external library -- just some homegrown matrix functions -- but I'll be moving over to OpenGL sooner or later.

As I said, I get the same behavior with quaternions and euler angles, so I'll show you the Euler vecRotate function because its easier to read and there's less stuff to copy and paste :)

As you can see, it's not in full 3D yet. Though all the physics and math is done in 3D, the graphics are not. Up to now I've been drawing a working only on the X-Z plane (essentially, a 2D game); the problems began to arise when I wanted to work in 3D.

Here's some source code, lemme know if you need to see more. The language is freebasic, but you should be able to tell what's what.

FUNCTION vecRotateEuler (byval v as vector, byval angle as vector) AS VECTOR
' Rotates a vector "v" using euler angles
DIM vOut as vector, vertFinal as vertex, Final as Matrix4
DIM ax as single, ay as single, az as single
ax = angle.x
ay = angle.y
az = angle.z
DIM xRot as matrix4, yRot as Matrix4, zRot as matrix4, Temp as matrix4
xRot = mat4set ( 1, 0, 0, 0, _
0, cos(ax), -1*sin(ax), 0, _
0, sin(ax), cos(ax), 0, _
0, 0, 0, 1)

yRot = mat4set (cos(ay), 0, sin(ay), 0, _
0, 1, 0, 0, _
-1*sin(ay), 0, cos(ay), 0, _
0, 0, 0, 1)

zRot = mat4set (cos(az), -1*sin(az), 0, 0, _
sin(az), cos(az), 0, 0, _
0, 0, 1, 0, _
0, 0, 0, 1)


Temp = mat4Multiply(xRot, yRot)
Final = mat4Multiply(Temp, zRot)

vertFinal = mat4MultByVector(Final, v)

vOut = vecMake(vertFinal.x, vertFinal.y, vertFinal.z)


RETURN vOut

END FUNCTION

SUB TriDraw (byref x as single, byref y as single, byref angle as vector)

DIM tx(1 TO 3) AS SINGLE
DIM ty(1 TO 3) AS SINGLE, i as ubyte
DIM rx(1 TO 3) AS SINGLE
DIM ry(1 TO 3) AS SINGLE
DIM a as vector, t(1 to 3) as vector, r(1 to 3) as vector

t(1) = vecMake(0, 0 , 16)
t(2) = vecMake(-8,0, -8)
t(3) = vecMake(8, 0, -8)
'a = vecMake(0, Angle, 0)

FOR i = 1 TO 3

r(i) = vecRotateEuler (t(i), angle)
NEXT

LINE (x + r(2).x, y + r(2).z)-(x + r(3).x, y + r(3).z), 7
LINE (x + r(1).x, y + r(1).z)-(x + r(2).x, y + r(2).z), 15
LINE (x + r(1).x, y + r(1).z)-(x + r(3).x, y + r(3).z), 15
END SUB

function mat4MultByVector (a AS Matrix4, v as vector) as vertex
DIM q as vertex
WITH a
q.x = .n(1,1)*v.x + .n(1,2)*v.y + .n(1,3)*v.z + .n(1,4)
q.y = .n(2,1)*v.x + .n(2,2)*v.y + .n(2,3)*v.z + .n(2,4)
q.z = .n(3,1)*v.x + .n(3,2)*v.y + .n(3,3)*v.z + .n(3,4)
q.t = .n(4,1)*v.x + .n(4,2)*v.y + .n(4,3)*v.z + .n(4,4)
END WITH
RETURN q
END function

FUNCTION mat4Multiply(byref a as matrix4, byref b as matrix4) as matrix4
DIM r as byte, c as byte
DIM i as byte, TEMP AS SINGLE

DIM mOut as matrix4

Temp = 0
FOR r = 1 TO 4
FOR c = 1 TO 4
Temp = 0
FOR i = 1 TO 4
Temp = temp + a.n(r, i) * b.n(i, c)
NEXT
mOut.n(r, c) = Temp
NEXT
NEXT
RETURN mOut
END FUNCTION


Honestly, I think this is the type of thing I could figure out myself if I could see the source code of another program (I'm looking for FS2's source now). Right now, I'm totally baffled.

Thanks for any help....

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this