Camera Tait-Bryan角的四元数
我正在用SharpDX写一个相机,用四元数旋转它Camera Tait-Bryan角的四元数,camera,rotation,quaternions,sharpdx,Camera,Rotation,Quaternions,Sharpdx,我正在用SharpDX写一个相机,用四元数旋转它 相机旋转设置为俯仰(X旋转)、偏航(Y旋转)和滚动(Z旋转),即所谓的“Tiat Bryan”角度(这些是非欧拉角度,具有XYX旋转,而非XYZ) 我使用的是左手坐标系:X+向右,Y+向上,Z+向下 如果我绕X旋转(“俯仰”),正值会使相机向下看。如果我绕Y旋转(“偏航”),正值会使相机看起来向左。如果我绕Z旋转(“滚动”),相机将顺时针滚动 我已经能够从四元数s中获得俯仰、偏航和滚转。以下C#代码: 我不知道另一个方向。如何通过指定俯仰、偏
- 相机旋转设置为俯仰(X旋转)、偏航(Y旋转)和滚动(Z旋转),即所谓的“Tiat Bryan”角度(这些是非欧拉角度,具有XYX旋转,而非XYZ)
- 我使用的是左手坐标系:X+向右,Y+向上,Z+向下
- 如果我绕X旋转(“俯仰”),正值会使相机向下看。如果我绕Y旋转(“偏航”),正值会使相机看起来向左。如果我绕Z旋转(“滚动”),相机将顺时针滚动
我不知道另一个方向。如何通过指定俯仰、偏航和横摇(例如,从
GetPitchYawRoll
返回向量3中的内容)来获取四元数?这些通常称为欧拉角
可在以下位置找到转换的所有变体:
最初由Ken Shoemake撰写,1993年,来自BlitzBasic.com论坛的Kryzon在这里帮助了我(s.他的帖子位于:
将泰特-布莱恩角称为“欧拉角”是误导性的,因为这些值的解释方式不同。你确定你的资料来源不是维基百科所说的“经典”或“恰当”的吗?我查看了该代码,以检查它需要哪些值-由于变量名和无法解释的EulGetOrd函数,我发现理解这些值非常糟糕:(.Ken Shoemake涵盖了轴旋转的所有可能变体。通过查看代码,可以在他的文章中找到对代码的所有描述。我必须同意@Ray Koopa。正如所指出的,“euler角度表示法”有多个可能变体。代码没有参数来区分正确、cardan、“XYZ”、“ZYX”等表示形式。
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);
}
}
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);
}
}