说实话关于四元数这一节真的是不好懂,因为里面涉及到好多数学知识,单说推出来的公式就有很多。不怕大家笑话,对于四元数的学习我足足花了两天的时间,包括整理出这篇文章。在前面一章我写到了“变换”,这也是总结的学习笔记。我发现,写博客真是的是一个好多学习方法,加上之前一个博士师兄告诉我,要想好好的学习一本书或者一门技术,那么以此将学习笔记或者经验写成博客专栏是一种有效的方法。现在我要坚持这种方式,给自己留下学习过程中的足迹,也给大家分享一下。欢迎大家指出其中的不足,谢谢!
四元数是表示旋转的另一种数学形式,使用四元数可以节省存储空间,其之间的连接运算需要的算术运算更少,在产生平滑的三维动画时,用四元数更容易进行修改。
四元数集合,在数学上被称为哈密顿四元数环(ring of Hamiltonian quaternions),用H表示,可以理解为四维空间向量,空间中的元素q可以表示为:
q = (x,y,z,w) = w + xi +yj + zk;
也可以用实数和向量的形式进行表示,即:
q = w + v;其中w是实数部分,v是v(x,y,z)。
四元数集合是复数集合的自然扩展。四元数的乘法服从分配率,并且虚部i,j,k之间满足一下关系:
四元数式的乘法不满足交换律,因此在进行乘法运算时要注意顺序。两个四元数q1 = w1 + x1i + y1j + z1k和q2 = w2 + x2i + y2j+z2k的乘积q1q2为:
用数量-向量的形式,则q1=s1+v1和q2=s2+v2的乘积表达式为:
四元数也有共轭,比如一个四元数为 q = s+v,那么它的共轭为q’ = s-v。而qq’=||q||2 = q2.
非零的四元数的逆,记作q-1,所以。
重点来了,下面;来说一下四元数的旋转
三维空间的旋转可以理解为R3到自身的映射函数φ。由于φ代表旋转,所以它必须包含长度,角度,旋转方向等信息。
如果有则长度保持不变。
如果对任意两个点p1和p2有
则从原点到两个点p1和p2的连线所形成 夹角保持不变。
则手向性也保持不变。
如果满足条件φ(s+v) = s+φ(v),则函数φ可以扩展为H到自身的映射,这样就将(4)式改写为
如果将p1和p2看做是数量部分为零的四元数,根据,就可以将(5),(6)式合并成一个等式,在该等式中可以保持角度和手向性不变,等式如下:
满足(7)是的函数φ称为是同态的。
该类函数φ可以用公式(8)表示:
其中q为一个非零的四元数,且满足和,因此可以表示旋转的集合。证明过程如下:
首先证明φq的长度保持不变,因为
其次,φq是同态的,因为
四元数与旋转的关系
假设向量P绕一任意旋转轴的单位向量A(xa,ya,za)旋转θ角,如下图所示:
我们可以将P看作为没有实数部分的四元数xi+yj+zk,设q = s+v,则q-1 = s-v。
那么φq(P) = qPq-1就等于(s+v)P(s-v)。即计算过程如下所示:
设v = tA,则上式可以改写为:
将(13)与绕任意轴旋转的公式P’ = PcosΘ + (A x P)sinΘ + A(A.P)(1-cosΘ),可以推出
则可以得到:
带入q = s+v得到:
推广一下来讲:
对于四元数q的任意数量乘积表示的都是相同的旋转,因为:
两个四元数q1和q2的乘积也可以表示一个旋转。乘积q1q2表示现已q2,后以q1进行旋转。因为:
可以将多个四元数结合起来,形成一系列旋转的一个四元数。将两个四元数相乘需要做16次乘法和加法运算,而两个3×3矩阵相乘就需要做27次类似的操作。因此对物体进行多次旋转时,应用四元数可以获得较高的计算效率。
如何将一个四元数变换成等价的3×3旋转矩阵的形式呢?
首先将改写成矩阵的形式
将四元数q改写成四维向量q = (w,x,y,z),那么w = s,x = tAx,y = tAy,z = tAz。因为A是单位向量,所以x2+y2+z2 = t2A2 = t2。
则上式等价于:
因为q是单位四元数,满足w2+ x2+y2+z2 =1,所以可以得到:
则四元数的旋转矩阵Rq的公式如下:
因为四元数是用向量表示的,所以很适合做插值运算。在产生一个物体动画过程中,在产生位于两个预先计算的关键帧之间的中间过渡定位时,插值非常有用。
最简单的差值类型是线性插值。对于两个四元数q1和q2,线性插值后得到的四元数q(t)为:
当t在[0,1]范围内取值时,函数q(t)在连接q1和q2的线段上平滑变化。如下图所示:
q(t)并不保持q1和q2的单位长度,但可以使用下面的函数在任意点位置对q(t)进行重新规格化:
这样就可以用该函数描绘位于q1和q2间的过渡弧线。在上图中,它将弧描绘成四维单位超球面的二维截面。
尽管线性插值很有效,但是q(t)并没有以恒定的速率描绘q1和q2间的过渡弧线,这就是线性插值的弊端。下图关于cos-1(q(t).q1)的图形表明,q1和q2之间的角度变化速率在端点t = 0 和 t = 1时相对较慢,而在t = 1/2时最快。
我们希望找到一个函数q(t),用它对四元数q1和q2进行插值时,会保持其单位长度不变并且以恒定的速率扫过位于q1和q2之间的夹角。如果q1和q2的夹角为θ,那么这个函数将会产生一个四元数,该四元数在q(t)和q1的形成一个夹角θt,这里t在0到1之间取值。
如下图(a),(b):四元数q(t)位于连接q1和q2的弧上,与q1的形成一个夹角θt,与q2构成夹角θ(1-t)。可以将q(t)写成:
其中a(t)和b(t)分别表示q(t)在q1和q2方向上的分量的长度。
我们可以构造相似三角形来确定长度a(t),q1到以原点和q2为端点的线段的垂直距离为||q1||sinθ,而q(t)到该线段的垂直距离为||q1||sinθ(1-t)。根据相似三角形,可以得到以下关系式:
由于||q1|| = 1,||q(t)|| = 1,可以将上式化简为:
同理可以得到:
这时可以将球型线性插值函数q(t)定义为:
θ角为
因为四元数q和-q表示相同的旋转,所以在旋转四元数q1和q2的正负号时一般要满足q1.q2>=0,这样也可以保证以最短路径的方式进行插值。