从Tait-Bryan角度的四元数

时间:2014-04-26 11:36:41

标签: camera rotation quaternions sharpdx

我正在用SharpDX编写相机,并在四元数的帮助下旋转它。

  • 相机旋转设定为俯仰(X旋转),偏航(Y旋转)和滚动(Z旋转),所谓的" Tiat-Bryan"角度(这些是欧拉角,它将具有XYX旋转,而不是XYZ)。
  • 我使用左手坐标系:X +向右,Y +向上,Z +向屏幕向下。
  • 如果我绕X旋转("俯仰"),正值会使相机向下看。如果我绕Y旋转("偏航"),正值会使相机向左看。如果我绕Z旋转("滚动"),相机会顺时针滚动。

我已经能够从四元数中得到俯仰,偏航和滚动。以下C#代码:

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);
    }
}

我不知道反过来。如何通过指定音高,偏航和滚动来获得四元数(例如,GetPitchYawRoll中Vector3中返回的是什么?)

2 个答案:

答案 0 :(得分:2)

来自BlitzBasic.com论坛的Kryzon帮助我({s。他在http://blitzbasic.com/Community/post.php?topic=102458&post=1224801的帖子):

internal static class QuaternionExtensions
{
    internal static Vector3 GetYawPitchRollVector(this Quaternion q)
    {
        return new Vector3(q.GetYaw(), q.GetPitch(), q.GetRoll());
    }

    private static float GetYaw(this Quaternion q)
    {
        float x2 = q.X * q.X;
        float y2 = q.Y * q.Y;
        return (float)Math.Atan2(2f * q.Y * q.W - 2f * q.Z * q.X, 1f - 2f * y2 - 2f * x2);
    }

    private static float GetPitch(this Quaternion q)
    {
        return (float)-Math.Asin(2f * q.Z * q.Y + 2f * q.X * q.W);
    }

    private static float GetRoll(this Quaternion q)
    {
        float x2 = q.X * q.X;
        float z2 = q.Z * q.Z;
        return (float)-Math.Atan2(2f * q.Z * q.W - 2f * q.Y * q.X, 1f - 2f * z2 - 2f * x2);
    }
}

internal static class Vector3Extensions
{
    internal static Quaternion GetYawPitchRollQuaternion(this Vector3 v)
    {
        float c1 = (float)Math.Cos(-v.Z / 2.0);
        float c2 = (float)Math.Cos(-v.Y / 2.0);
        float c3 = (float)Math.Cos( v.X / 2.0);
        float c1c2 = c1 * c2;
        float s1 = (float)Math.Sin(-v.Z / 2.0);
        float s2 = (float)Math.Sin(-v.Y / 2.0);
        float s3 = (float)Math.Sin( v.X / 2.0);
        float s1s2 = s1 * s2;

        return new Quaternion(
            c1 * s2 * c3 - s1 * c2 * s3,
            c1c2 * s3 + s1s2 * c3,
            s1 * c2 * c3 + c1 * s2 * s3,
            c1c2 * c3 - s1s2 * s3);
    }
}

答案 1 :(得分:0)

这通常被称为欧拉角,

http://en.wikipedia.org/wiki/Euler_angles

所有转换变体都可以在http://tog.acm.org/resources/GraphicsGems/gemsiv/euler_angle/找到 Ken Shoemake,1993年