PDA

View Full Version : Quaternion to Euler



Paran
11-27-2009, 04:13 PM
Hi,
I successfully implemented a third person camera like this (http://www.gamedev.net/reference/articles/article1591.asp).
It works perfectly.

But my problem is now, that I only get the object's rotation, which the camera should follow, as a quaternion from the Bullet physics engine. I especially require the rotation around the Up-Axis ("y"-axis in my case) but every method to convert quaternions to euler angles, that I could find, uses arcsin to get the angle (e.g. here (http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm)).
Because it uses arcsin, the y-rotation is always limited to -90 until 90 degrees, resulting in a camera, that can only partly rotate with the object (only in half range).

So the question is now: How can I get the full-range up-axis rotation information from a quaternion?
Or is this the complete wrong way to go? (since I searched and tried now for days but couldn't find anything)

Please help me, this issue keeps me from further developing my game and I can't solve it. :(

Regards

Y-tension
11-28-2009, 07:51 AM
From 3D Game Engine Design(A heavily mathematical book I really recommend):

for quaternion w + xi + yj + zk

and 3x3 rotation matrix R

R = [1-2y^2-2z^2, 2xy-2wz, 2xz+2wy]
[2xy+2wz, 1-2x^2-2z^2, 2yz-2wx]
[2xz-2wy, 2yz+2wx, 1-2x^2-2y^2]

Paran
11-28-2009, 05:49 PM
Thanks, but with a rotation matrix, I have the same problem again: in all conversion documents I found, they use arcsin to get the up-axis rotation.
This is usually ok, because if you apply all 3 rotations, then only two arctans are needed to produce all possible rotations.
But if I only want to apply one single rotation (the one around the y-axis, which is unfortunately the one that is "optimized" to arcsin), then I need the full rotation information.

After another very frustrating day, I found the solution.
So for people that have the problem as me, here is it:
If the quaternion is (x,y,z,w) then the yaw is:


Real fTx = 2.0*x;
Real fTy = 2.0*y;
Real fTz = 2.0*z;
Real fTwy = fTy*w;
Real fTxx = fTx*x;
Real fTxz = fTz*x;
Real fTyy = fTy*y;

return Radian(Math::ATan2(fTxz+fTwy, 1.0-(fTxx+fTyy)));