4

此评论中,强烈建议我们永远不要使用欧拉角。我知道欧拉角存在一些限制,尤其是万向节锁定,但我想知道在没有欧拉角的情况下通常使用的最佳技术或技术集?

关于这个主题的大多数讨论都涉及从欧拉角转换为四元数,这是一件简单的事情。但是我读过的关于在没有欧拉角的情况下进行旋转的唯一方法是从两个向量中创建一个四元数,正如 Stan Melax 在“游戏编程宝石”中的文章“最短弧四元数”中所描述的那样,使用这种技术:

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

这是链接评论中提到的方法吗?

4

3 回答 3

4

方向

方向是变换将在坐标系内定向对象的方式。方向是一个绝对量,如位置或标量。方向在概念上是一个值。并且有一些操作可以应用于方向,这取决于它们的表示。

与向量和标量不同,方向可以用多种方式表示。

“使用欧拉角”是什么意思?

欧拉角是围绕 3 个固定的正交轴的一系列 3 次旋转。这些应用的顺序很重要,通常由惯例确定。

“使用欧拉角”意味着欧拉角是您的代码存储和操作对象方向的方式。你最终如何组合这些角度来生成一个矩阵并不重要。重要的是您的代码会将方向视为 3 个角度。例如,当您对方向应用旋转偏移时,它将作为旋转角度的偏移提供,并且这些偏移将直接应用于存储的欧拉角。

“使用矩阵”是什么意思?

我知道没有人这么说,但我在这里要说明一点。

“使用矩阵”意味着旋转矩阵是您的代码存储和操作对象方向的方式。如果某段代码想要旋转对象,它们将在左侧或右侧应用一个矩阵。即使该矩阵是通过一些轴向旋转计算的,代码仍然对矩阵执行基本操作,而不是角度。

“使用四元数”是什么意思?

出于讨论的目的,“四元数”是用于对方向进行编码的 4 元素单位向量。四元数可以对它们进行类似矩阵的操作,例如合成和反转。四元数必须保持归一化才能正确编码方向。

“使用四元数”意味着您将对象的方向和操作存储为四元数。在最基本的层面上,您对方向的所有操作都在处理四元数数学。

如何调整方向

欧拉角经常被使用,因为它们(理论上)可以直观地调整:你只需增加或减少一个角度。如果您想将对象在 X 轴上旋转 -10 度,您只需从 X 轴旋转中减去 10。但是我们不想使用它们,因为它们很糟糕,所以让我们看看其他的方向表示。

要将方向调整为矩阵,您必须做两件事。您必须将当前方向与偏移旋转矩阵相乘(如果您想在 X 轴上旋转 -10 度,则为此创建一个角度/轴矩阵并将其右乘)。然后,由于计算机的精度有限,您必须重新正交化矩阵。如果你不做第二步,你的矩阵最终将不再是正交的,因此不再是一个方向

对矩阵进行正交归一化很困难。这就是我们使用四元数的(部分)原因。标准化一个四元数很容易;它只是 4 元素向量归一化。而且由于四元数和矩阵具有类似的运算,相同的数学将适用于两者。所以它们看起来几乎相同。

于 2013-06-11T17:29:08.593 回答
1

有几种数学模型可以描述 3D 对象的旋转。欧拉角模型只是其中之一。通常当人们谈论欧拉角时,他们实际上是在谈论 Tait-Bryan 角,欧拉只提出了第一个角度重复的模式,例如 ZXZ 旋转。如果您按照预期使用下摆,则欧拉角没有什么特别的错误,即用于静态表示。或者,它们适用于实际上像万向节一样的许多机械旋转。

欧拉角有两个主要缺点。首先是人们通常认为他们更了解欧拉角数值表示。虽然实际上它只有真正正确,只要只有 2 和非常少的特殊 3 轴旋转旋转正在进行,即使在某些有限情况下它也有点可疑。第二个是你不能真正有意义地插值欧拉模型,因为它没有均匀地填充旋转空间。这意味着数字空间的某些区域具有不同的大小。想象一下矩形地图如何在球体上变形。

今天,我们中的很多人都在为图形制作动画,在模拟工程中,插值是最重要的。这意味着欧拉模型并不真正适合大多数任务。人们在尝试考虑欧拉模型空间中的插值时会想到的一件奇怪的事情是,您实际上可以一次围绕 3 个方向旋转。但这在物理上是不可能的,在 3d 空间中只有一次旋转。

现在您可以使用的其他模型很少。可以使用仿射矩阵作为奖励,您可以定义所有坐标系。但在所有其他模型中,这是最糟糕的解决方案,它甚至没有用数字有意义地插入一个轴。再一次是存储结果的好模型。可以使用基于矢量和旋转的轴角度。这是物理上非常合理的表示旋转的方式,但在解决最短路径时存在某些问题。现在插值的最佳模型可能是四元数,它是一种奇怪的轴角编码。它有几个有趣的属性,例如所有可能旋转的空间正好是 2 倍,因此可用于解决 2 个姿势之间的最短旋转和最长旋转。

所以你有它。欧拉模型描述旋转没有错。只要您不需要进行数值插值,除了非常小的子集。这恰好是空中使用的飞机。或者,如果您不需要统一的空间,也不需要随机生成旋转等。

没有什么说您不能在一个模型中设置值并在另一个模型中进行插值。

于 2013-06-11T17:02:37.677 回答
0

顺便说一句,理想情况下,我希望看到像原始评论员 @NicolBolas 这样的权威专家的回答。但由于到目前为止他还没有回复你的评论问题,我会试一试。

我想知道这里的混淆是否在于“欧拉”角与其他角度的含义。

您提到“有关此主题的大多数讨论都涉及从欧拉角转换为四元数”。但他们真的是从欧拉角度转换的吗?

该评论的作者显然本教程的作者。在本教程的示例 8.1 中,他从轴和角度展示了四元数的公式。这是您所说的“从欧拉角转换为四元数”的那种事情吗?显然他并不是说你不应该从一个角度创建一个四元数。

根据欧拉角的维基百科定义,它们分为三部分。换句话说,欧拉角是由它们组合以表示方向的方式构成的。我怀疑评论所指的是这样一个事实,即您正在累积欧拉角 pitchAccum 和 yawAccum 的旋转,然后将这些角度中的每一个转换为四元数,然后再使用四元数乘法组合它们。

相反,如果您在开始时创建了一个四元数来表示方向;然后在四元数本身中累积方向状态,而不是在欧拉角 pitchAccum 和 yawAccum 中,那么您将做@NicolBolas (Jason) 所倡导的事情。

于 2013-06-11T15:24:44.963 回答