• 10
• 10
• 12
• 12
• 14

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

This topic is 3991 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

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 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 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 on other sites
 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 FUNCTIONSUB 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), 15END SUBfunction 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 qEND functionFUNCTION 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 mOutEND 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....