彻底搞懂四元数

提要

旋转的表达方式有很多种,有欧拉角,旋转矩阵,轴角,四元素等等,今天要学习的就是游戏开发中最常用的四元素。

 

从欧拉角和轴向角到四元数

在讲四元素之前,我们先来看下简单的欧拉角和轴向角。

欧拉角使用最简单的x,y,z值来分别表示在x,y,z轴上的旋转角度,其取值为0-360(或者0-2pi),一般使用roll,pitch,yaw来表示这些分量的旋转值。需要注意的是,这里的旋转是针对世界坐标系说的,这意味着第一次的旋转不会影响第二、三次的转轴。

欧拉角容易出现的问题是 1)不易在任意方向的旋转轴插值; 2)万向节死锁;3)旋转的次序无法确定。

 

轴角用一个以单位矢量定义的旋转轴,再加上一个标量定义的旋转角来表示旋转。通常的表示[x,y,z,theta],前面三个表示轴,最后一个表示角度。表示非常直观,也很紧凑。

轴角最大的一个局限就是不能进行简单的插值,此外,轴角形式的旋转不能直接施于点或矢量,必转换为矩阵或者四元素。

 

四元素感觉上就是轴角的进化,也是使用一个3维向量表示转轴和一个角度分量表示绕此转轴的旋转角度,即(x,y,z,w), 其中

 

[cpp]  view plain  copy
 
  1. w = cos(theta/2)    
  2. x  = ax * sin(theta/2)    
  3. y  = ay * sin(theta/2)    
  4. z  = az * sin(theta/2)  


其中(ax,ay,az)表示轴的矢量,theta表示绕此轴的旋转角度。四元数中的每个数都是经过“处理”的轴和角,轴角描述的“四元组”并不是一个空间下的东西,首先(ax,ay,az)是一个3维坐标下的矢量,而theta则是级坐标下的角度,简单的将他们组合到一起并不能保证他们插值结果的稳定性,因为他们无法归一化,所以不能保证最终插值后得到的矢量长度(经过旋转变换后两点之间的距离)相等,而四元数在是在一个统一的4维空间中,方便归一化来插值,又能方便的得到轴、角这样用于3D图像的信息数据,所以用四元数再合适不过了。相比于矩阵,四元素也只要存储4个浮点数,优势很明显。

 

 

 

 

四元素的相关计算

乘法

给定两个四元数p和q,分别代表旋转P和Q,则乘积pq表示两个旋转的合成(即旋转了Q之后再旋转P),并不是用加法。四元数的乘法定义如下,利用简单的分配律就是了:


q1 * q2 =
(w1*w2 - x1*x2 - y1*y2 - z1*z2) +
(w1*x2 + x1*w2 + y1*z2 - z1*y2) i +
(w1*y2 - x1*z2 + y1*w2 + z1*x2) j +
(w1*z2 + x1*y2 - y1*x2 + z1*w2) k


由于q = w + x i + y j + z k中可以分为纯量w与向量x i + y j + z k,所以为了方便表示,将q表示为(S, V),其中S表示纯量w,V表示向量x i + y j + z k,所以四元数乘法又可以表示为:
q1 * q2 = (S1 + V1)*(S2 + V2) = S1*S2 - V1.V2 + V1XV2 + S1*V2 + S2*V1

 

求模

N(q) = |q| = x2 + y2 + z2 + w2

 

单位化

Normalize( q ) = q/ | q | = q / (x2 + y2 + z2 + w2)

 

求共轭

q*=(-x, -y, -z, w)

 

求逆

对于向量逆的定义, q-1 =q*/|q|2

对于单位四元素,分母为1,q-1 = q* =(-x, -y, -z, w)

 

用四元数旋转矢量

给定一个矢量v,再给定一个旋转的单位四元素q,让v旋转q。

首先将v改写成四元素的形式v = (x, y ,z, 0),  接下来要旋转v须用q前乘以矢量v,再后乘以q-1。

v‘ = qvq-1

当然用后面乘以共轭的q也是一样的,因为都是单位四元素。

对于旋转多个四元数,比如 R=R1R2R3. 则

注意顺序。

 

四元数的线性插值和球面线性插值

四元素的可以方便地进行插值是四元素最大的优势。线性插值最为简单,效率也很高。给定两个旋转四元素qa和qb代表旋转A和旋转B,找到旋转A到旋转B之间的 t 的旋转:

注意这里的 t 实际上是是沿弦上走了t,而不是在球面上走t,这样就会导致当 t 以恒定速度改变时,角度的变化并非恒定.

 

为了解决这个问题,就出现了球面线性插值。给定四元素q和q,

其中theta是两个四元素的夹角,

 

四元数的各种转换

四元素转欧拉角

欧拉角转四元素

四元素转旋转矩阵

 

[cpp]  view plain  copy
 
  1. Matrix4x4(  
  2.         1.0f - 2.0f*y*y - 2.0f*z*z, 2.0f*x*y - 2.0f*z*w, 2.0f*x*z + 2.0f*y*w, 0.0f,  
  3.         2.0f*x*y + 2.0f*z*w, 1.0f - 2.0f*x*x - 2.0f*z*z, 2.0f*y*z - 2.0f*x*w, 0.0f,  
  4.         2.0f*x*z - 2.0f*y*w, 2.0f*y*z + 2.0f*x*w, 1.0f - 2.0f*x*x - 2.0f*y*y, 0.0f,  
  5.         0.0f, 0.0f, 0.0f, 1.0f  
  6.         )  

 

 

 

 

 

 

参考

游戏引擎架构 第四章

Computer Graphics: 四元數與旋轉 - http://openhome.cc/Gossip/ComputerGraphics/QuaternionsRotate.htm

Quaternion(四元数)和旋转以及Yaw, pitch, roll 的含义 - - http://www.wy182000.com/2012/07/17/quaternion%E5%9B%9B%E5%85%83%E6%95%B0%E5%92%8C%E6%97%8B%E8%BD%AC%E4%BB%A5%E5%8F%8Ayaw-pitch-roll-%E7%9A%84%E5%90%AB%E4%B9%89/

你可能感兴趣的:(3D图形,OpenGL)