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:
pitch/yaw/roll amount in degrees needed to rotate camera towards target position point

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.


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:


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.


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


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