<长期更新>
SLERP 球面插值
参考:https://zhuanlan.zhihu.com/p/538653027,由于参考文章的方法不容易想,这里用正交的思路来记忆。
四元数球面插值的核心,就是通过角度比例插值的方法来实现插值的保范性。如下图所示,我们的目标是寻找到一组合适的插值参数 \([a, b]^T\),使得 \(r = a \cdot p + b \cdot q \)。

对于这类向量计算,我们可以通过找正交的角度来简化思考,我们可以很容易得到 \(p\) 的正交单位向量(这里我们假设两个向量之间的角度小于 90 度,图里面大于 90 度的情况放后面讨论):
\[p_{\perp} = \frac{q-p \cdot \cos\theta}{\sin\theta}\]由此,我们可以得到 \(r\) 关于 \(p\) 和 \(p_{\perp}\)的关系:
\[r = p \cdot \cos(t\theta) + p_{\perp} \cdot \sin(t\theta)\]将 \(p_{\perp}\) 的定义带入上述公式可以得到:
\[r = \frac{p \cdot \cos(t\theta) \cdot \sin \theta + q \cdot \sin(t\theta)-p \cdot \cos(\theta) \sin(t\theta)}{\sin\theta}\]由于 \(\sin(a+b)=\sin a\cos b + \cos a \sin b\),我们有:
\[r = \frac{p \cdot \sin [(1-t)\theta]+q \cdot \sin(t\theta)}{\sin \theta}\]由此可以得到插值系数:
\[\begin{bmatrix} a \\ b \end{bmatrix} = \begin{bmatrix} \frac{\sin[(1-t)\theta]}{\sin \theta} \\ \frac{\sin (t\theta)}{\sin \theta} \end{bmatrix} \]当然,这里有两点需要注意:
- 如果夹角极小,此时涉及到除零,需要使用 NLERP (即正规线性插值,在线性插值后通过除以范数来确保长度为 1)来代替 SLERP
- 如果夹角大于 90 度,插值会跑到较长的圆弧上。这个时候,我们只需把其中一个向量取反(因为四元数 \(-q\) 和 \(q\) 代表同一个旋转),就可以得到结果了。
四元数
这个参考文献太神了,推导非常详细,完全不需要我增加多余的内容:
https://github.com/Krasjet/quaternion