4 replies to this topic

Posted 03 November 2012 - 02:47 PM

Hi, I'm working on a 3D space game built with C++ and DirectX. I've got a question about using quaternions for object rotation and I'm hoping someone might have an idea.

Currently, the player ship's rotation is represented by a quaternion. The ship starts off level and facing directly straight forward (towards the positive Z axis). I create a quaternion based on the 3 axes (positive X to the right, Y is up, and Z is forward).

If I want to apply a rotation to the ship, for example 90 degrees to the right, I can call D3DXQuaternionRotationAxis() to get a rotation quaternion. I then multiply that against the original rotation using D3DXQuaternionMultiply() and I get a new updated rotation where the ship is facing forward along the X axis (perfect!).

The problem I have is in the next step:

If I then want to make a second rotation of pitching the nose of the ship up (based on the current direction it's facing along the X axis), when I try to use the method described above I don't get the intended result. What happens instead is the ship indeed rotates, but as if it were still facing in it's original direction towards the Z axis. So instead of seeing the nose of the ship rotate up, I see the ship roll. Or to be more clear, I see a rotation around the X axis, rather than seeing a rotation around the Z axis.

This is probably a very simple mistake, but for some reason I always have trouble wrapping my head around quaternion math.

Any help is appreciated!

Currently, the player ship's rotation is represented by a quaternion. The ship starts off level and facing directly straight forward (towards the positive Z axis). I create a quaternion based on the 3 axes (positive X to the right, Y is up, and Z is forward).

If I want to apply a rotation to the ship, for example 90 degrees to the right, I can call D3DXQuaternionRotationAxis() to get a rotation quaternion. I then multiply that against the original rotation using D3DXQuaternionMultiply() and I get a new updated rotation where the ship is facing forward along the X axis (perfect!).

The problem I have is in the next step:

If I then want to make a second rotation of pitching the nose of the ship up (based on the current direction it's facing along the X axis), when I try to use the method described above I don't get the intended result. What happens instead is the ship indeed rotates, but as if it were still facing in it's original direction towards the Z axis. So instead of seeing the nose of the ship rotate up, I see the ship roll. Or to be more clear, I see a rotation around the X axis, rather than seeing a rotation around the Z axis.

This is probably a very simple mistake, but for some reason I always have trouble wrapping my head around quaternion math.

Any help is appreciated!

Posted 03 November 2012 - 03:25 PM

If I understand your description correctly, it just sounds like you're applying the rotations in the wrong order; try reversing the order of the multiplication.

Posted 03 November 2012 - 10:15 PM

Ah, the catch is I want the rotations to be independent. For example, the ship first rotates 90 degrees around the Y axis (yaw to the right), then moves in that direction for some amount of time, and finally as a later action it rotates 90 degrees around the Z axis (pitching the nose upwards).

I'm basically trying to give the player the freedom to move/rotate the ship as if it were a real spaceship. ;)

I'm basically trying to give the player the freedom to move/rotate the ship as if it were a real spaceship. ;)

Posted 04 November 2012 - 04:22 AM

Co-ordinates are to be interpreted w.r.t. to a space to give a sense. E.g. if you ever pick (0,1,0) as rotation axis for heading, then you probably mean to rotate in the ship's local space. However, it doesn't work this way. A concatenated transformation is applied in the most global space.

So you need to take explicit steps to first fit the space as you want it, i.e. you to transform it so that the local axes are coincident to the global ones. You do this by first applying the inverse of the current orientation before applying the new rotation. Because you don't want to loose the former orientation, you then have to re-apply a rotation to reconstruct it.

Now, when you think on this further (try it with e.g. 3 rotations on paper), you'll see that the order of all the rotations applied over time is simply reversed. That is probably the reasoning behind SiCrane's post, and it makes sense w.r.t. your problem.

So you need to take explicit steps to first fit the space as you want it, i.e. you to transform it so that the local axes are coincident to the global ones. You do this by first applying the inverse of the current orientation before applying the new rotation. Because you don't want to loose the former orientation, you then have to re-apply a rotation to reconstruct it.

Now, when you think on this further (try it with e.g. 3 rotations on paper), you'll see that the order of all the rotations applied over time is simply reversed. That is probably the reasoning behind SiCrane's post, and it makes sense w.r.t. your problem.

Posted 04 November 2012 - 03:03 PM

Ah, I understand! Thanks haegarr (and SiCrane).

I changed the code so I apply the newest rotation first then reapply the older rotations and it works beautifully!

Thanks so much.

I changed the code so I apply the newest rotation first then reapply the older rotations and it works beautifully!

Thanks so much.