Unity3D--四元数【Quaternion】

   四元数
    定义:简单来说,四元数本质上是一种高阶复数,是一个四维空间,相对于复数的二维空间。(我们高中的时候应该都学过复数,一个复数由实部和虚部组成,即x = a + bi,i是虚数单位,如果你还记得的话应该知道i^2 = -1。而四元数其实和我们学到的这种是类似的,不同的是,它的虚部包含了三个虚数单位,i、j、k,即一个四元数可以表示为x = a + bi + cj + dk。)

    在Unity 中,tranform组件有一个变量名为rotation,它的类型就是四元数。 
    而 rotation是属于一种旋转,说到旋转就简单有三种:
    1. 矩阵旋转
    • 优点:
      • 旋转轴可以是任意向量;
    • 缺点:
      • 旋转其实只需要知道一个向量+一个角度,一共4个值的信息,但矩阵法却使用了16个元素;
      • 而且在做乘法操作时也会增加计算量,造成了空间和时间上的一些浪费;
    2. 欧拉旋转
    • 优点:
      • 很容易理解,形象直观;
      • 表示更方便,只需要3个值(分别对应x、y、z轴的旋转角度);但按我的理解,它还是转换到了3个3*3的矩阵做变换,效率不如四元数;
    • 缺点:
      • 之前提到过这种方法是要按照一个固定的坐标轴的顺序旋转的,因此不同的顺序会造成不同的结果;
      • 会造成万向节锁(Gimbal Lock)的现象。这种现象的发生就是由于上述固定坐标轴旋转顺序造成的。理论上,欧拉旋转可以靠这种顺序让一个物体指到任何一个想要的方向,但如果在旋转中不幸让某些坐标轴重合了就会发生万向节锁,这时就会丢失一个方向上的旋转能力,也就是说在这种状态下我们无论怎么旋转(当然还是要原先的顺序)都不可能得到某些想要的旋转效果,除非我们打破原先的旋转顺序或者同时旋转3个坐标轴。
      • 由于万向节锁的存在,欧拉旋转无法实现球面平滑插值;
      3. 四元数旋转
    • 优点:
      • 可以避免万向节锁现象;
      • 只需要一个4维的四元数就可以执行绕任意过原点的向量的旋转,方便快捷,在某些实现下比旋转矩阵效率更高;
      • 可以提供平滑插值;
    • 缺点:
      • 比欧拉旋转稍微复杂了一点点,因为多了一个维度;
      • 理解更困难,不直观;

          說完了旋转的优缺点,不得不把四元数比较的难理解的部分粘贴出来;
         
          基础含义和公式计算
   我们可以使用一个四元数 q = ( ( x , y , z ) sin
θ2 cosθ2) 来执行一个旋转。具体来说,如果我们想要把空间的一个点P绕着单位向量轴u = (x, y, z)表示的旋转轴旋转 θ角度,我们首先把点P扩展到四元数空间,即四元数p = (P, 0)。那么,旋转后新的点对应的四元数(当然这个计算而得的四元数的实部为0,虚部系数就是新的坐标)为:

p=qpq1

其中, q = (cosθ2 , ( x , y , z ) sin θ2 ) , q1=qN(q) ,由于u是单位向量,因此
N
(q)
=1,即q1=q。右边表达式包含了四元数乘法。相关的定义如下:
  • 四元数乘法:q1q2=(v1×v2+w1v2+w2v1,w1w2v1v2)

  • 共轭四元数:q=(v⃗ ,w)

  • 四元数的模:N(q) = √(x^2 + y^2 + z^2 +w^2),即四元数到原点的距离

  • 四元数的逆q1=qN(q)

           例子: 把点P(1, 0, 1)绕旋转轴u = (0, 1, 0)旋转90°,求旋转后的顶点坐标。首先将P扩充到四元数,即p = (P, 0)。而q = (u*sin45°, cos45°)。求
p=qpq1 的值。建议大家一定要在纸上计算一边,这样才能加深印象,连笔都懒得动的人还是不要往下看了。最后的结果p` = ((1, 0, -1), 0),即旋转后的顶点位置是(1, 0, -1)。

          四元数和其他类型的转换
         1. 轴角到四元数 给定一个单位长度的旋转轴(x, y, z)和一个角度 θ 。对应的四元数为:
q = ( ( x , y , z ) sin θ2 cosθ2) 

          2. 欧拉角到四元数
                 给定一个欧拉旋转(X, Y, Z)(即分别绕x轴、y轴和z轴旋转X、Y、Z度),则对应的四元数为:

x = sin(Y/2)sin(Z/2)cos(X/2)+cos(Y/2)cos(Z/2)sin(X/2)
y = sin(Y/2)cos(Z/2)cos(X/2)+cos(Y/2)sin(Z/2)sin(X/2)
z = cos(Y/2)sin(Z/2)cos(X/2)-sin(Y/2)cos(Z/2)sin(X/2)
w = cos(Y/2)cos(Z/2)cos(X/2)-sin(Y/2)sin(Z/2)sin(X/2)
q = ((x, y, z), w)

      官方文档的链接:
       http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm
       Euler to Quaternion
      Quaternion To Euler
      AngleAxis to Quaternion
      Quaternion to AngleAxis

        3. 四元数的插值
          插值指的是球面线性插值。 设t是一个在0到1之间的变量。我们想要基于t求Q1到Q2之间插值后四元数Q。它的公式是:

Q3  = (sin((1-t)A)/sin(A))*Q1 + (sin((tA)/sin(A))*Q2)
Q = Q3/|Q3|,即单位化

        四元数创建
       四元数在Unity 中常用的一些方法: http://www.ceeger.com/Script/Quaternion/Quaternion.AngleAxis.html 

你可能感兴趣的:(unity3D)