Link to home
Start Free TrialLog in
Avatar of Nebmaster
Nebmaster

asked on

Problems with axis rotations!

Hi!

I have a problem with my rotations in my project (using Visual Studio 6 & Directx 8). I have loaded a .x model and with my code I can rotate my object around x,y and z axis (I rotate the object 90 degrees / rotation).


Now to my problem.. If I rotate the object 90 degrees around the "world" y-axis, the objects x-axis turns with the rotation and now points to the same direction as the worlds z-axis. If I then press my "Rotate X-key" to rotate the object around world x-axis, the oject rotates around world z-axis because the objects x-axis had been "moved" to worlds z-axis..
The rotations works fine if I just rotate around a single axis, but if I try to combine the rotations I do not get the result that I need to get.
If I press my button for rotation around x-axis, I just add 90 to my variable m_fXAngle
I also check if m_fXAngle = 360 , set m_fXAngle = 0...
Same thing with m_fYAngle and m_fZAngle!


In my code I use:

D3DXMatrixRotationX(&matRotateX, m_pMesh1->m_fXAngle*D3DX_PI/180);
D3DXMatrixRotationY(&matRotateY, m_pMesh1->m_fYAngle*D3DX_PI/180);
D3DXMatrixRotationZ(&matRotateZ, m_pMesh1->m_fZAngle*D3DX_PI/180);

D3DXMatrixMultiply(&matFig1, &matRotateZ, &matRotateX);
D3DXMatrixMultiply(&matFig1, &matFig1, &matRotateY);
(I have also tested to change the MatrixMultiply order, but no order gives the correct result)

m_pD3DDevice->SetTransform(D3DTS_WORLD, &matFig1);

I have also tested:
D3DXMatrixRotationYawPitchRoll(&matFig1, m_pMesh1->m_fYAngle*D3DX_PI/180, m_pMesh1->m_fXAngle*D3DX_PI/180, m_pMesh1->m_fZAngle*D3DX_PI/180);
but it didn't help, still got the same problem.

What should I do to get the correct rotations ??
If I press my button for rotation around x-axis, I want the object to rotate around WORLD x-axis. (and it does the first time). Then after that I e.g. want to rotate the object around world z-axis. But if i try to do that, the object rotates around world y-axis. (because the objects z-axis points to the same direction as world y-axis on account of the first x-axis rotation).
Is there a way to force the object to rotate around the WORLD x,y,z axis (not the objects x,y,z axis)?
Or is there another way to fix my problem?

thanks
Avatar of joachimc
joachimc

Do you rotate the world or the objects world? It seems to me that you are rotating the object.
Also I would suggest doing the changes to the matrix one by one.

If you have a rotation around x.

void rotateX(float aRotation)
{
   D3DXMATRIX mat;
   D3DXMatrixIdentity(&mat);
   D3DXMatrixRoationX(&mat, aRotation);
   myMatrix = mat * myMatrix;
   m_pD3DDevice->SetTransform(D3DTS_WORLD, myMatrix);
}
Avatar of Nebmaster

ASKER

I rotate the objects world, I think... cause if I would rotate the whole world it would be the same as rotating the camera? or? I don't want to rotate the whole world because I have several objects in the world. I can rotate each of them differently. And if I choose to rotate one of the objects, the rest of them should stay at their position.

I tryed the way you described in your function, to run a different SetTransform for each rotation... but it didn't help.
No it's not the same as rotating the camera it's the opposite. But if you are rotating the object around it's center you don't get what you want.
Ok, I temporary put up two files on a server.

www.multi.fi/~tobbe/experts/source.zip
This is an modified example from a tutorial (from www.andypike.com). In the code you will see my problems with the rotations..

This is my own project ...
www.multi.fi/~tobbe/experts/CubeRuntime.zip
If you run it you may better understand my problem.


Please send a comment when you have downloaded the files.. I don't want them to have them there on the server. =)

thanks
Either of these two will work.

D3DXMatrixMultiply(&matShip2, &matRotateY, &matRotateX);
D3DXMatrixMultiply(&matShip2, &matShip2, &matRotateZ);


//matShip2 = matRotateX * matRotateY * matRotateZ;

/Joachim
Sorry, but that wont work as it should..

If you have
D3DXMatrixMultiply(&matShip2, &matRotateY, &matRotateX);
D3DXMatrixMultiply(&matShip2, &matShip2, &matRotateZ);

... try to rotate first around x-axis -> OK!
... after that rotate around y-axis -> Wrong rotation (the ship rotated around world z-axis, because the ships y-axis was rotated to world z-axis)

This is the problem Im talking about... it doesn't matter in which order you multiply the matrix. It still rotates wrong if you combine different rotations.
But that is completely correct what are you trying to accomplish then ?
If I press the button for rotation around x-axis. I want the object to rotate around WORLD x-axis.
and for the y-axis button, I want to rotate the object around WORLD y-axis.
Z-axis button -> rotate around WORLD z-axis!

(After rotation, objects are moved to their right positions)
Ok, then rotate the world and have the object as the identity matrix.
mmm, exactly HOW do I rotate the world? Can you give an example on how to do it?
Try this then

matShip2 = matRotateY * matShip2;
matShip2 = matRotateX * matShip2;
matShip2 = matRotateZ * matShip2;

Still can't see why you would want to do like this anyway :) What is your ultimate goal ?
Obviously you did not download my real (not finished) project (CubeRuntime.zip). =)

I have 6 pieces (objects) in my game and the goal in the game is to form a cube, by rotating and moving these pieces to the right position.
Then I also have my own collision detection code that creates a 5x5x5 matrix for each piece.
When I press my X-rot key, I want the active piece to rotate around world x-axis. My 5x5x5 collision matrix rotates also, (the rotation for the collision matrix is ok in all rotation combinations).
The same thing with y and z rotations.

So if I rotate the piece in a random number of combinations, my collisionmatrix would be right, but the visible piece on screen is not rotated as it should be.  


I want to be able to rotate each piece around WORLD x,y,z axis. Thats also what the "end-user" wants to do in the "game".

Maybe I have to somehow read in all the vertices from the .x file to memory. And then if I rotated the piece around any axis, I would have to manually change the positions of the objects vertices.

Because another problem is that when I load a .x file, the position of the object will be at 0,0,0. If I want to move it on the screen, I use the move matrix and then render the object... BUT the object still is at position 0,0,0. Its only moved for rendering at another position. Thats why I cant get my MousePick() function to work. It always picks the object in 0,0,0.. even if it looks on the screen that it is on another place...

Thats about it... dont know if you understood my problem better but.. =)
The program doesn't run that's why I haven't seen it. I have the same problem using DShow to render music. It crashes on XP.
Strange, on my XP it works fine. I have DX9SDK installed, but the project uses DX8...

I put some pics on the net, haven't got any nice screenshots but.. =)

www.multi.fi/~tobbe/experts/pic.zip
Well the rotations from the example works at least.
Look at this site:

http://sjbaker.org/steve/omniv/eulers_are_evil.html

It will explain why you have gimbal lock on your rotations.

Leathal.
ok, now I tested:

D3DXMatrixTranslation(&matMove1, m_pMesh1->m_fXPos, m_pMesh1->m_fYPos, m_pMesh1->m_fZPos);

D3DXQUATERNION quatYPR;
D3DXQuaternionRotationYawPitchRoll( &quatYPR, m_pMesh1->m_fYAngle*D3DX_PI/180, m_pMesh1->m_fXAngle*D3DX_PI/180, m_pMesh1->m_fZAngle*D3DX_PI/180);
D3DXMatrixRotationQuaternion( &matFig1, &quatYPR);

D3DXMatrixMultiply(&matFig1, &matFig1, &matMove1);

m_pD3DDevice->SetTransform(D3DTS_WORLD, &matFig1);

but it still won't work as it should. Or is there an another way to rotate the object with quaternions?
This still works

matShip2 = matRotateY * matShip2;
matShip2 = matRotateX * matShip2;
matShip2 = matRotateZ * matShip2;

But of course gimbal lock is a problem.
No.. not the way that I want it to rotate.

ok, now i tested the tutorial sample with:
matShip2 = matRotateY * matShip2;
matShip2 = matRotateX * matShip2;
matShip2 = matRotateZ * matShip2;

If I want to rotate the object around world y-axis, I press my key for y-rot -> ok, ship rotated around world y-axis.

After the world y-axis rotation I want to rotate the object around world x-axis, I press the key for x-rot -> wrong rotation! the object rotated around world z-axis...

ok, I dont know what you mean with "this still works", cause to me it is not working until I get the object to rotate around the world axis I want to. =)
... and I want to be abel to rotate a random number of times around any world axis with the correct rotation. And to combine these x,y and z rotations..
If I press my rotX button, I want the object ALWAYS to rotate around world x-axis.
Same with my y and z buttons... no matter how the object is rotated before.
Do you understand what I mean?
ok then quaternions is for you. You have to restrict one of your angles to +- 90 degrees to avoid gimbal locks.
But I read somewhere that Gimbal Lock would not happen if you are using Quaternions? Why do I then have to restrict one of my rotations to +- 90 deg. ?

Anyway... I'll give it a try this weekend.. hope it works. =)
ASKER CERTIFIED SOLUTION
Avatar of joachimc
joachimc

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yes! Finally !!!

My Gimbal Lock problem is now history! =)

I read the article about quaternions:
http://www.gamedev.net/reference/articles/article1095.asp
and converted his opengl code to directx..

Now I really need some sleep.
The problem was "Gimblal Lock", but now I have fixed it! I would recommend you to read this article
http://www.gamedev.net/reference/articles/article1095.asp
and look at the sample code.

Happy coding! =)