I am writing a camera with SharpDX and rotate it with the help of a quaternion.
- The camera rotation is set with pitch (X rotation), yaw (Y rotation) and roll (Z rotation), so called "Tiat-Bryan" angles (these are not Euler angles which would have an XYX rotation, and not XYZ).
- I am using a left-handed coordinate system: X+ is rightwards, Y+ is upwards, Z+ is downwards the screen.
- If I rotate around X ("pitching"), positive values make the camera look downwards. If I rotate around Y ("yawing"), positive values make the camera look leftwards. If I rotate around Z ("rolling"), the camera rolls clockwise.
I was already able to get pitch, yaw and roll from the quaternion, s. the following C# code:
public static class QuaternionExtensions
{
public static Vector3 GetPitchYawRoll(this Quaternion q)
{
return new Vector3(q.GetPitch(), q.GetYaw(), q.GetRoll());
}
public static float GetPitch(this Quaternion q)
{
return q.GetK().GetPitch();
}
public static float GetYaw(this Quaternion q)
{
return q.GetK().GetYaw();
}
public static float GetRoll(this Quaternion q)
{
// This is M12 * M22 of rotation matrix
float xx = q.X * q.X;
float xy = q.X * q.Y;
float zz = q.Z * q.Z;
float wz = q.W * q.Z;
return (float)Math.Atan2(2f * (xy - wz), 1f - 2f * (xx + zz));
}
public static Vector3 GetK(this Quaternion q)
{
float xz = q.X * q.Z;
float wy = q.W * q.Y;
float yz = q.Y * q.Z;
float wx = q.W * q.X;
float xx = q.X * q.X;
float yy = q.Y * q.Y;
return new Vector3(
2f * (xz - wy),
2f * (yz + wx),
1f - 2f * (xx + yy));
}
}
public static class Vector3Extensions
{
public static float GetPitch(this Vector3 v)
{
return (float)-Math.Atan2(v.Y, Math.Sqrt(v.X * v.X + v.Z * v.Z));
}
public static float GetYaw(this Vector3 v)
{
return (float)-Math.Atan2(v.X, v.Z);
}
}
I don't know the other way round. How to get the quaternion by specifying pitch, yaw and roll (e.g. what's returned in the Vector3 from GetPitchYawRoll
)?
Kryzon from the BlitzBasic.com forum helped me out here (s. his post at http://blitzbasic.com/Community/post.php?topic=102458&post=1224801):
This all often called Euler Angles,
http://en.wikipedia.org/wiki/Euler_angles
all variants of conversion can be found at http://tog.acm.org/resources/GraphicsGems/gemsiv/euler_angle/ Ken Shoemake, 1993