在this comment中强烈建议我们永远不要使用欧拉角。我知道欧拉角有一些限制,最值得注意的是万向节锁定,但我想知道在没有欧拉角的情况下通常使用的最佳技术或技术组合?关于这个主题的大多数讨论涉及从欧拉角转换为四元数,这是一件简单的事情。但是我读过的关于没有欧拉角的旋转的唯一方法就是使用这种技术从Stan Melax在“Game Programming Gems”中的文章“The Shortest Arc Quaternion”中描述的两个向量创建一个四元数: / p>
template <typename T>
inline QuaternionT<T> QuaternionT<T>::CreateFromVectors(const Vector3<T>& v0, const Vector3<T>& v1)
{
Vector3<T> c = v0.Cross(v1);
T d = v0.Dot(v1);
T s = std::sqrt((1 + d) * 2);
QuaternionT<T> q;
q.x = c.x / s;
q.y = c.y / s;
q.z = c.z / s;
q.w = s / 2.0f;
return q;
}
这是链接评论中引用的方法吗?
答案 0 :(得分:3)
方向是变换在坐标系内定向对象的方式。方向是绝对数量,如位置或标量。取向在概念上是一种价值。并且有一些操作可以应用于方向,具体取决于它们的表示。
与矢量和标量不同,方向可以用多种方式表示。
“使用欧拉角”意味着欧拉角是您的代码存储和操纵对象方向的方式。你最终如何组成这些角度来生成矩阵并不重要。重要的是你的代码会将方向视为3个角度。例如,当您将旋转偏移应用于方向时,它将作为旋转角度的偏移量提供,并且这些偏移将直接应用于存储的欧拉角度。
我知道没有人这么说,但我有一点要说。
“使用矩阵”意味着旋转矩阵是代码存储和操纵对象方向的方式。如果某段代码想要旋转对象,它们将在左侧或右侧应用矩阵。即使通过一些轴向旋转计算该矩阵,代码仍然在矩阵上执行基本操作,而不是角度。
出于本讨论的目的,“四元数”是用于编码方向的4元素单位向量。四元数可以对它们进行类似矩阵的运算,例如组合和反演。四元数必须保持标准化,以便正确编码方向。
“使用四元数”意味着您将对象的方向和操作存储为四元数。所有关于方向的操作,在最基本的层面上,都是处理四元数数学。
经常使用欧拉角,因为它们(理论上)直观地调整:你只需增加或减少一个角度。如果要在X中将对象旋转-10度,则只需从X轴旋转中减去10。但我们不想使用它们,因为它们很糟糕,所以让我们看看其他方向表示。
要将方向调整为矩阵,您必须做两件事。必须将当前方向与偏移旋转矩阵相乘(如果要在X轴上旋转-10度,则为其创建角度/轴矩阵并将其右对齐)。然后,因为计算机具有有限的精度,所以必须重新对矩阵进行正交化。如果你不做第二步,你的矩阵最终会停止正交,因此不再是方向。
对矩阵进行正交化非常困难。这是(部分)我们使用四元数的原因。规范化四元数很容易;它只是4元素矢量归一化。由于四元数和矩阵具有类似的运算,因此相同的数学运算将同时适用于两者。所以他们看起来非常相似。
答案 1 :(得分:1)
有几种数学模型可用于描述3D中的旋转和物体。欧拉角模型只是其中之一。通常当人们谈到欧拉角时,他们实际上谈论的是Tait-Bryan角度,欧拉只提出了第一个角度重复的模式,例如ZXZ旋转。如果你像他们想要的那样使用下摆,那就是欧拉角没有什么特别的错误,那就是静态表示。或者它们适用于许多机械旋转,实际上就像万向节一样。
欧拉角有两个主要缺点。首先,人们通常认为他们更好地理解欧拉角数字表示。实际上它只是真正的,只要只有2和很少的特殊3轴旋转进行,甚至在一些有限的情况下它有点可疑。第二个是你不能真正有意义地插入欧拉模型,因为它没有均匀地填充旋转空间。这意味着数字空间的某些区域具有不同的大小。想象一下矩形地图如何在球体上扭曲。
今天我们中的很多人都在做图形动画,模拟工程,其中插值是最重要的。这意味着欧拉模型并不适合大多数任务。人们开始考虑在欧拉模型空间中思考插值的一个奇怪的事情是你实际上可以同时围绕3个方向旋转。但这在物理上是不可能的,在3d空间中只有一次旋转。
现在您可以使用的其他型号很少。可以使用仿射矩阵作为奖励,您可以定义所有坐标系。但是在所有其他模型中,这是最糟糕的解决方案,它甚至不会插入一个有意义的数字轴。然后再次是用于存储结果的良好模型。可以使用基于矢量和旋转的轴角度。这是表示旋转的物理上非常理智的方式,但是在解决最短路径时存在某些问题。现在,用于插值的最佳模型可以是四元数,其是一种编码奇怪的轴角度。它具有几个有趣的特性,例如具有所有可能旋转的空间的2倍,因此可以用于解决2个姿势之间的最短旋转以及最长的旋转。 quats的缺点是大多数人无法以任何有意义的方式读取数值的结果。
所以你有它。用Euler模型描述旋转没有错。只要您不需要进行数值插值,除非是非常小的子集。这恰好是空中使用的飞机。或者,如果你不需要一个统一的空间,没有随机生成旋转等等。
没有什么说你不能在一个模型中设置值并在另一个模型中插值。
答案 2 :(得分:0)
我想知道这里的混淆是否超过了“欧拉”角度与其他角度的含义。
你提到“关于这个主题的大多数讨论涉及从欧拉角转换为四元数”。但他们真的是从 Euler 角度转换吗?
该评论的作者apparently是this tutorial的作者。在本教程的示例8.1中,他显示了轴和角度的四元数公式。这是你所指的那种“从欧拉角转换为四元数”的东西吗?显然,他并不是说你不应该从一个角度创建一个四元数。
从wikipedia definition of Euler angles开始,他们排在第三位。换句话说,角度 Euler 角度的作用是它们组合以表示方向的方式。我怀疑comment提到的是你在欧拉角度pitchAccum和yawAccum中累积旋转的事实,然后在使用四元数乘法组合它们之前将每个角度转换为四元数。
相反,如果您在开头创建了一个四元数来表示方向;然后在四元数本身累积定向状态,而不是欧拉角度pitchAccum和yawAccum,那么你就会做@NicolBolas(Jason)所倡导的。