Camera orientation using a quaternion

Started by
3 comments, last by Bozebo 13 years, 1 month ago
I have been up all night trying to get this working but my camera orientation is not behaving in the way I want it to.

Firstly, the code:
//capture pitch and yaw from mouse
pitch += mouseState.lY*0.005f;
yaw -= mouseState.lX*0.005f;
//clamp pitch
/*
if(pitch < D3DXToRadian(-90)){
pitch = D3DXToRadian(-90);
} else if(pitch > D3DXToRadian(90)){
pitch = D3DXToRadian(90);
}
*/
//start from identity
D3DXQuaternionIdentity(&cam);
D3DXQuaternionIdentity(&tempQ);
//apply yaw
D3DXVECTOR3 bleh(0.0f,1.0f,0.0f); //y axis
D3DXQuaternionRotationAxis(&tempQ,&bleh,yaw);
D3DXQuaternionMultiply(&cam,&tempQ,&cam);
//apply pitch
bleh.x = 1.0f; //x axis
bleh.y = 0.0f;
bleh.z = 0.0f;
D3DXQuaternionRotationAxis(&tempQ,&bleh,pitch);
D3DXQuaternionMultiply(&cam,&cam,&tempQ);
//normalise the matrix
D3DXQuaternionNormalize(&cam,&cam);
//get the quaternion axis angle
D3DXQuaternionToAxisAngle(&cam,&camTo,&roll); //this could be where I am going wrong... I don't think the roll value is accurate, but I am using 0 for roll in D3DXMatrixLookAtLH anyway
camTo = camTo + camAt; //add the axis angle vector to the current camera location to get the camera to vector

(how do I get a c++ code box in this new forum? :P - edit: nevermind, after posting the thread it started to highlight, client side)

Then I am using D3DXMatrixLookAtLH with my camTo and camAt vectors (0 roll for the time being).

I am using directinput to get the mouse movement which is working nicely, but I am messing up the quaternion or how I am getting the camTo vector but I can't quite see how. I have been trying other things without fully understanding what I am doing so I may have been closer to the solution than the code I have at the moment.

The pitch seems to be responding fine (apart from my failed attempt at clamping the values but I can sort that later) but when changing the yaw it feels quite off and 'curves away' from where the camera should look to - increasingly so as the pitch differs from horizontal. That might be a bad explanation of the outcome but anybody who has done this before should instantly spot what I have done wrong, I can't seem to though.

I have been using gpqiki, this example and the msdn for reference but I am still stuck.

Any pointers in the right direction? At least I have avoided the popular trap of not starting with the identity matrix each frame wink.gif
Advertisement
Any pointers in the right direction? At least I have avoided the popular trap of not starting with the identity matrix each frame[/quote]
Actually, that's probably exactly what you *want* to be doing :)

Before commenting further, are you looking for a typical first-person control scheme here, where pitch is always about the local side axis and yaw is always about the world up axis? (In other words, where the object in question always remains 'upright'.)

Also, I'm not sure what you're doing with the axis-angle conversion there, but that's almost certainly wrong. Again though, it'll be helpful to know what type of control scheme you're trying to implement exactly.

Any pointers in the right direction? At least I have avoided the popular trap of not starting with the identity matrix each frame

Actually, that's probably exactly what you *want* to be doing :)

Before commenting further, are you looking for a typical first-person control scheme here, where pitch is always about the local side axis and yaw is always about the world up axis? (In other words, where the object in question always remains 'upright'.)

Also, I'm not sure what you're doing with the axis-angle conversion there, but that's almost certainly wrong. Again though, it'll be helpful to know what type of control scheme you're trying to implement exactly.
[/quote]

" that's probably exactly what you *want* to be doing :)" - all the other forum posts I have found have a problem where the person was preserving the quaternion between frames and applying changes to it rather than building the quaternion from an identity quaternion and the pitch & yaw each frame.

Yes I am attempting typical first person style camera control, I should have explained that further. Just so that I can navigate around in "noclip" in my d3d scene to work on different things. I could use vectors or matrices for that but I've done so before knowing that I should be using quaternions but not being able to get it working.

I thought the axis angle conversion would somehow output a vector pointing in the look direction, I can't see what else would do that from the other quaternion functions. Of course it would help if I understood the maths better but every time I read about quaternions I just want to use them and not worry about what they actually do - from my understanding they have a vector and an angle of rotation around that vector, but that is probably completely wrong.
all the other forum posts I have found have a problem where the person was preserving the quaternion between frames and applying changes to it rather than building the quaternion from an identity quaternion and the pitch & yaw each frame.[/quote]
In short, preserving the orientation from frame to frame is appropriate for (e.g.) 6DOF motion; for first-person or spectator-cam type motion, you instead want to rebuild the orientation from the pitch and yaw angles each frame.

I could use vectors or matrices for that but I've done so before knowing that I should be using quaternions but not being able to get it working.[/quote]
That's part of the problem right there. The idea that you 'should be using quaternions' for this is completely and absolutely false. You *can* use quaternions for this, but for this type of application they really just amount to an extra, unnecessary step, IMO.

Unless you have a good reason to do otherwise, I'd just stick with matrices.

I thought the axis angle conversion would somehow output a vector pointing in the look direction[/quote]
That's a common misconception, but the axis of rotation actually doesn't have a direct relationship to the 'forward' vector for the object. So no, computing the axis of rotation will not give you the 'look' vector or 'look-at' point in any form.

I can't see what else would do that from the other quaternion functions.[/quote]
The typical way to extract direction vectors from a quaternion is to convert it to a matrix and then extract the vectors directly from the rows or columns of the matrix, as appropriate. (You can write special-case functions to do this that operate on the quaternion directly, but you're really just doing the same work but in a different form.)

from my understanding they have a vector and an angle of rotation around that vector, but that is probably completely wrong.[/quote]
No, it's not completely wrong :) To be specific, a unit-length quaternion can be interpreted as encoding an axis-angle rotation (you can find this 'encoding' described in any reference on the subject). So although the quaternion doesn't store the axis and angle in a direct way, the values of the imaginary and real parts of the quaternion can be thought of as being related to the axis and angle (respectively).
Thanks, I got it working now ^_^

This topic is closed to new replies.

Advertisement