关于 Quaternion 旋转正确性的学习资料推荐
正文
用 Quaternion 做旋转有省空间、连续多个 Quaternion 旋转和矩阵一样可以复合成单个 Quaternion 、复合操作的计算量比矩阵少、不受 Gimbal Lock 影响、更容易做插值等特点,因此在图形学领域被广泛使用。
本文将推荐 Quaternion 的学习资料,这些资料专注于把 Quaternion 用于旋转,而不专注于 Quaternion 作为一个代数系统的属性,特别的,我们仅使用到该代数系统的非常小一部分子集。
首先推荐阅读的是 Quaternions for Computer Graphics 2nd ,专门为图形学领域讲解的 Quaternion ,这本书我的评价不是很高,等下讲原因,首先这本书可以肯定的是, Quaternion 的历史背景讲的很丰富,还穿插了很多其他的、相关的、有用的信息,但是很多地方讲解比较生硬,解释也比较含糊,让我对这本书评分骤降的地方在于,在第8章 Quaternions in Space 中讲解 Quaternion 如何用于旋转的时候,作者是用特例进行来“说服”读者 Quaternion 可以用来旋转的,而不是用代数的方法去证明,或者你至少举个一般的例子,不管怎么样,这本书仍然很值得一读,有用的信息很多。
然后推荐阅读的是 Eric Arnebäck 的文章: Showing the Correctness of Quaternion Rotation ,正如这篇文章说的, Rodrigues 旋转公式的正确性远比 Quaternion 旋转更符合直觉,所以这篇文章选择使用代数的方法证明 Quaternion 旋转公式等价于 Rodrigues 旋转公式,从而证明 Quaternion 旋转公式的正确性,读者需要先看 Rodrigues 旋转公式的推导,在信任 Rodrigues 旋转公式的正确性后,再去看 Eric Arnebäck 的文章, Wikipedia 中有 Rodrigues 旋转公式的详细推导,见: Rodrigues' rotation formula 。
综上,推荐阅读顺序是:
- Quaternions for Computer Graphics 2nd
- Rodrigues' rotation formula
- Showing the Correctness of Quaternion Rotation
其中可以跳过 Quaternions for Computer Graphics 2nd 直接按顺序阅读后两篇文章,但是如果跳过第一本书的话,读者在阅读 Showing the Correctness of Quaternion Rotation 看到 Simplifying Quaternion Rotation 的时候需要注意:
上面利用到了 \( \vec{v} = 0 + \vec{v} \) ,即向量等于标量项为 \( 0 \) 的 Quaternion ,这个关键点文章的作者漏了提到。
最后,读者可以阅读 Mathematics for 3D Game Programming and Computer Graphics 3rd 的章节 4.6 : Quaternions ,里面一样以代数的方法给了 Quaternion 旋转非常简洁的推导(同时也省略了很多细节,读者要自己补上),虽然该推导最终和 Showing the Correctness of Quaternion Rotation 一样,还是证明了 Quaternion 旋转公式和 Rodrigues 旋转公式(书中直接叫它绕任意轴旋转公式)的等价性,但是推导的前半部分是比较不一样的,该推导前半部分对于读者是否可信,取决于读者是否相信所有同时保长度、直线之间的角度、手性的变换就是旋转变换(注:平移变换不考虑,因为我们这里处理的对象是向量,是被我们视为仅有方向,没有位置的对象,由于没有位置的概念,自然没有平移这个操作,当然,在引入基向量,即有了坐标系后,你可以把向量的坐标认为是它的“位置”而不认为是它的“方向”,但此时平移量不为\( 0 \)的平移操作就一定会改变向量的“位置”,进而不保向量的模长,也就是我们所谓的“长度”)。需要注意的是,书中的推导有个小错误,接下来,我将一步步说明错误在哪,为什么 我觉得 这是个错误,具体的:书上说在要求变换 \( \varphi \) 满足 \( \varphi(s + \vec{v}) = s + \varphi(\vec{v}) \) 的前提下,以下等式 4.41 :
\[ \varphi(\vec{P_1}) \cdot \varphi(\vec{P_1}) = \vec{P_1} \cdot \vec{P_2} \qquad \text{(4.41)} \]
可以改写成以下等式 4.43 :
\[ \varphi(\vec{P_1}) \cdot \varphi(\vec{P_1}) = \varphi(\vec{P_1} \cdot \vec{P_2}) \qquad \text{(4.43)} \]
这点是没问题的,因为等式 4.41 右侧是标量 \( \vec{P_1} \cdot \vec{P_2} \) ,加上如果\( \varphi \)真的是旋转变换的话,则旋转变换是线性变换,会将\( \vec{0} \)映射到\( \vec{0} \),因此可得 \( \varphi(\vec{P_1} \cdot \vec{P_2}) = \varphi((\vec{P_1} \cdot \vec{P_2}) + \vec{0}) = (\vec{P_1} \cdot \vec{P_2}) + \varphi(\vec{0}) = (\vec{P_1} \cdot \vec{P_2}) + 0 = \vec{P_1} \cdot \vec{P_2} \) 。
紧接着,书上说利用等式 \( \vec{P_1}\vec{P_2} = -\vec{P_1} \cdot \vec{P_2} + \vec{P_1} \times \vec{P_2} \) (1) (这里把向量看成标量项为 \( 0 \) 的 Quaternion ,用的是 Quaternion 乘法),以及之前要求的 \( \varphi(s + \vec{v}) = s + \varphi(\vec{v}) \) (2) ,就可以把等式 4.42 和 等式 4.43 合并成等式 4.44 ,这里先补充下等式 4.42 和等式 4.44 ,如下:
\[ \varphi(\vec{P_1} \times \vec{P_2}) = \varphi(\vec{P_1} \times \vec{P_2}) \qquad \text{(4.42)} \]
\[ \varphi(\vec{P_1}) \varphi(\vec{P_2}) = \varphi(\vec{P_1} \vec{P_2}) \qquad \text{(4.44)} \]
很容易证明等式 4.42 加上等式 4.43 可以推出等式 4.44 ,但反过来,单靠 (1) 和 (2) ,等式 4.44 似乎无法推出等式 4.42 和等式 4.43 ,也就是等式 4.42 和等式 4.43 并不等价于等式 4.44 ,但是额外要求 \( \varphi \) 满足将纯向量(标量项为 \( 0 \) 的 Quaternion )映射到纯向量,即要求 \( \varphi(\vec{P}) \) 也为纯向量的话,则等式 4.44 就也能推出等式 4.42 和等式 4.43 了,此时等式 4.42 和等式 4.43 才等价于等式 4.44 ,之后很容易验证变换 \( \varphi_q(\vec{P}) = q \vec{P} q^{-1} \) 确实同时满足 \( \varphi(s + \vec{v}) = s + \varphi(\vec{v}) \) 以及会将纯向量映射到纯向量,故我认为应该额外要求变换 \( \varphi \) 将纯向量映射到纯向量。
以上就是我认为的、书中的错误点,读者需要留意下。
额外的, Mathematics for 3D Game Programming and Computer Graphics 3rd 的章节 4.3 : Rotation Transforms 中也给了 Rodrigues 旋转公式的证明(书中直接叫它绕任意轴旋转公式),证明的阐述比 Wikipedia 的简洁不少,且只要你顺着章节 4.3 读下来,也很容易读懂。
附件
这里为了避免两篇文章链接失效,这里保存成图片,作为附件: