Quaternion-based Camera; PointAt() function

I’m trying to write a function that will point my tQuatCamera at a target position.

First, here is how tQuatCamera is setup:

typedef struct
{
   double pitchDegrees, yawDegrees, rollDegrees;

   // the following members are purely for informational purposes.
   // they do not effect how the camera operates.
   Quaternion pitchQ, yawQ, rollQ;
   Matrix4x4 rotationMatrix;
   Quaternion rotationQuaternion;
} tQuatCamera;

To rotate the camera, all I do is set pitchDegrees, yawDegrees, rollDegrees, and call UpdateCamera(&myCamera).

UpdateCamera() rotates the scene by combining pitchQ, yawQ, and rollQ (with quaternion-multiplication), creating a matrix of the combined quaternion, and finally calling glMultMatrix(rotMatrix) followed by glTranslate(-cameraPosition).

So basically:

Given: target position point, camera position (eye) point, camera pitch/yaw/roll in degrees, camera direction (forward) vector, overall camera rotation in quaternion and matrix form

I need:
either:
pitch/yaw/roll amount in degrees needed to rotate camera towards target position point

or:
pitch/yaw/roll in degrees needed to view target position point from camera position point

I’ve already tried 3 different methods. I’m hoping someone here can clue me in. Thanks.

I’ve come close. Using the Shortest-Arc quaternion between the camera direction and the direction to the target, it appears to almost work. But something is odd.

Hi,

I’m doing something like you, given a quaternion I extract the information about roll (rotation around z axes) to remove it (applying a -Theta rotation).

To extract this kind of information I take the up vector of my world (in my case it’s (0, 1, 0) ), I transform it by the quaternion (you can use your global quaternion or your rotation matrix), than I project the result vector onto xy plane (I set z = 0 and normalize the vector) then I calculate the z angle between ( 0, 1, 0 ) and the projected vector as:
atan2( projectedVec.x, projectedVec.y ).

otherwise you can use (atan2 is more accurate):
atan( projectedVec.x / projectedVec.y )

You can apply the same algorithm to different axis and get the three euler angles you need.

Yes! It seems to work somewhat. Only problem is the pitch doesn’t work. I probably messed something up, but it definately is the closest I’ve gotten it. I think I should be able to work it out from here. Thanks very much.

Scratch that! Works perfectly now. You are a life-saver, I can’t believe this actually works. I figured it’d be much, much harder. You kick a$$ :stuck_out_tongue:

Just one small problem. The camera appears to be pitching too fast when the target position is steadily rising above the level of the camera. I just can’t figure it out. So here’s the relevant code:

http://s90927795.onlinehome.us

Fixed! Turns out I must have read some bad code somewhere. Newbies beware, the is such thing as wrong information. I posted the fix at the same URL.

http://s90927795.onlinehome.us/pointAt-FIXED.txt

Scratch all that! LOL. Everything is all messed up. It doesn’t work at all (well, almost!). sigh

:rolleyes:

Fixed…again. LOL. embarassed
Turns out my entire QuaternionGetEulerv() function was somewhat buggy. Anyway, it was fixed by using Matrix4x4GetEulerv() (new function).