学了这么久的graphics,居然连四元数都迷迷糊糊的,真是丢人急先锋,索性花点时间相关东西理清楚。

相关内容的C++实现

复数与二维旋转

二维情形下,将某个点绕原点逆时针旋转的变换矩阵为:

也可以利用复数乘法的几何解释来完成旋转:

籍由这两种旋转表示方式的等价性,可以将其拓展到三维空间。

三维旋转公式

现需要在右手系下将向量绕单位向量旋转度,显然可以被分解为平行于和垂直于的两个分量,其中前者无需修改:

若将视为轴,将视为轴,则求它们的叉积即可得到轴。此时只需要将经典的二维旋转变换应用到坐标系中的平面上,即可求出旋转后的,也就求出了。设,则中的坐标为,此时在平面上进行旋转变换,得到:

从而旋转后的

四元数

顾名思义,四元数包含一个实部和三个虚部,虚部单位分别以表示,它们满足:

四元数被定义为的线性组合(没错,四元数定义到这就算结束了),加法减法乘法共轭以及范数都可以直接拓展复数的相关定义得到:

四元数常被记作,其中:

可以验证:

最后来个逆:四元数的逆是指满足的四元数。根据的长度关系,有:

特别地,单位四元数的逆就是其共轭。

四元数和三维旋转

根据之前的讨论,有:

若令四元数,则,于是满足:

可见这一旋转可以认为是将四元数作用到上得到的。

验证可知若为单位向量,则,其意义很直观——如果把单位四元数视为一个旋转变换,那么相当于进行两次这样的变换,即将旋转角翻倍。基于此,若令:

则有:

容易验证,代入上式得:

这就得到了用四元数进行绕任意轴旋转的公式。

球面线性插值

我们通常用旋转矩阵来进行三维空间中的旋转操作,但这在需要对旋转角进行插值时(比如涉及到旋转的动画)并不好用,因为这不能通过直接对矩阵元素进行线性插值来实现。四元数则提供了一种方便的插值方式——由于旋转角在四元数中直接出现,因此可以把将线性插值的四元数用于旋转操作,这将提供一个平滑的旋转过程,称为球面线性插值(Spherical Linear Interpolation,Slerp)。

设初始旋转四元数是,结束旋转四元数是,插值系数为,若令:

也是一个旋转四元数,它必然具有的形式,此时对的旋转角在间进行线性插值即可,即:

在实际应用中,Slerp有个小坑——朝某个方向旋转角度和朝它的反方向旋转在结果上是等价的,在插值过程中却表现得完全不同,因此,若间的夹角超过,即,则有必要将换成后再进行插值。