3D数学基础——四元数的介绍

四元数

四元数是由哈密顿在1843年爱尔兰发现的。当时他正研究扩展复数到更高的维次(复数可视为平面上的点)。他不能做到三维空间的例子,但四维则造出四元数。根据哈密顿记述,他于10月16日跟他的妻子在都柏林的皇家运河(Royal Canal)上散步时突然想到
                                                             i² = j² = k² = ijk = -1
的方程解。之后哈密顿立刻将此方程刻在附近布鲁穆桥(Brougham Bridge,现称为金雀花桥 Broom Bridge)。

不只如此,哈密顿还创造了向量的内外积。他亦把四元数描绘成一个有序的四重实数:一个标量(a)和向量(bi + cj + dk)的组合。若两个标量部为零的四元数相乘,所得的标量部便是原来的两个向量部的标量积的负值,而向量部则为向量积的值,但它们的重要性仍有待发掘。

四元数的记法

一个四元数包含一个标量分量 和 一个3D向量分量,经常记标量分量为 w,记向量分量为 单一的 V 或者 (x, y, z):

         [w,V]  或  [ w, x, y, z] 

四元数与复数

四元数扩展了复数系统,一个四元数【w,(x,y,z)】定义了复数 w + xi + yj + zk;它使用3个虚部 i, j, k 关系如下:

i^2 = j^2 = k^2 = -1

ij = k, ji = -k

jk = i, kj = -i

ki = j,ik = -j

四元数和轴—角对

四元数中的数和 旋转轴 和 角度的关系:

  3D数学基础——四元数的介绍_第1张图片

单位四元数

几何上,存在两个“单位”四元数,他们代表没有角位移:【1,(0,0,0)】和 【-1,(0,0,0)】;当角度是360的偶数倍时,对应【1,(0,0,0)】;当角度是360的奇数倍时,对应于【-1,(0,0,0)】;它的意义在于:

当旋转角是360的整数倍时,方位并没有改变,并且旋转轴也是无关紧要的。

数学上,实际只有一个单位四元数:【1,(0,0,0)】,任何四元数q乘以这个单位四元数的结果还是其本身q;而乘以【-1,(0,0,0)】得到的却是-q,数学上 q 和 -q 并不相等,但是在几何上,q 和 -q 代表的角位移相同。

四元数的模

        3D数学基础——四元数的介绍_第2张图片

当旋转轴为单位向量时:

   

四元数共轭和逆

四元数的共轭是通过让四元数的向量部分变负来获得:

3D数学基础——四元数的介绍_第3张图片

四元数的逆定义为 四元数的共轭除以它的模:

3D数学基础——四元数的介绍_第4张图片

一个四元数q 乘以 它的逆,即可得到单位四元数【1,(0,0,0)】

四元数q 与 它的共轭 q* 具有相反的角位移,因为共轭是向量取反,即颠倒了旋转的方向;当然也可理解位另一定义:w 取反,v不变 

四元数的乘法(叉乘)

四元数相乘的公式:

3D数学基础——四元数的介绍_第5张图片

四元数的叉乘满足结合律,但是不满足交换律:

四元数乘积的模等于模的乘积:

   3D数学基础——四元数的介绍_第6张图片

四元数乘积的逆等于各个四元数的逆以相反的顺序相乘:

   3D数学基础——四元数的介绍_第7张图片

一个标准的3D点(x,y,z)到四元数空间,通过定义四元数p【0,(x,y,z)】即可;设 q 为旋转四元素形式 【cos(a/2),nsin(a/2)】,n 为旋转轴,单位向量; a 为 旋转角度,下面乘法为 3D点 p 绕 n 旋转:

   

3D点多次旋转(先 a ,后 b),等价于执行ba 乘积代表的单一旋转:

3D数学基础——四元数的介绍_第8张图片

四元数差

四元数的差被定义为从一个方位到另一个方位的角位移:

    ad = b 

3D数学基础——四元数的介绍_第9张图片

四元数点乘

四元数的点乘和 向量的点乘类似,四元数的点乘的绝对值越大,两个四元数代表的角位移就越相似。

3D数学基础——四元数的介绍_第10张图片

四元数的对数、指数和标量乘运算

四元数的对数运算:

       3D数学基础——四元数的介绍_第11张图片

四元数的指数运算:

       p = [0  an] = [0 (ax,ay,az)]

       ||n|| = 1

      3D数学基础——四元数的介绍_第12张图片

四元数求幂

四元数求幂可以从角位移抽取“一部分”,如:四元数q代表一个角位移,想要得到1/3 的这个角位移的四元数,可以这样计算:

q^(1/3)       

四元数表达角位移时使用最短圆弧,不能绕圈;比如q为绕x轴顺时针旋转60°,那么q^4 并不是绕x轴顺时针旋转240°,而是逆时针旋转120°。                                                                                                                                                            

四元数求幂:

      

//四元数求幂代码块

float w,x,y,z;

float exponent;

if(fabs(w) > 0.9999f){
    
    float alpha = acos(w);//alpha = theta *0.5
    float newAlpha = alpha * ecponent;

    w = cos(newAlpha);

    //这里的思想是原始的 x = n sin(alpha) ,利用 n 旋转轴是保持不变的,来求新的x,y,z
    float mult = sin(newalpha) / sin(alpha);
    x *= mult;
    y *= mult;
    z *= mult;
}

 

四元数插值——slerp

slerp的基本思想是沿着4D球面上连接两个四元数的弧插值;可以把这种思想表现在平面上,如下第一张图中显示,两个2D向量 v0 ,v1 都是单位向量,w为两个向量弧所截的角,t为插值参数,在0~1之间变化;所以 vt可以表示为图2显示的线性组合:

由于v0、v1是单位向量,利用三角公式可以计算出:

k0 = sin((1-t)w ) / sinw

k1 = sintw / sin w

Vt 可以表示为:

3D数学基础——四元数的介绍_第13张图片 

将同样的思想扩展到四元数,可得到四元数的slerp插值公式:

3D数学基础——四元数的介绍_第14张图片

四元数q 和 -q 代表相同的方位,但他们作为slerp的参数时可能导致不一样的结果,这是因为4D球面不是欧氏空间的直接扩展,解决方法是选择q0 和 q1的符号使得点乘的结果非负 ?

如果 q0 和 q1 非常接近,sinw的 值非常小,这时候除法会出现问题,为了避免这个问题,当sinw很小时,才用线性插值。

3D数学基础——四元数的介绍_第15张图片         3D数学基础——四元数的介绍_第16张图片

//四元数 slerp 实现的代码段


float w0,x0,y0,z0;
float w1,x1,y1,z1;

float t;

float w,x,y,z;
//用点乘计算两个四元数夹角
float cosOmega = w0*w1 + x0*x1 + y0*y1 + z0*z1;

//如果为负,需要反转一个四元数
if(cosOmega < 0.0f)
{
    w1 = -w1;
    x1 = -x1;
    y1 = -y1;
    z1 = -z1;
    cosOmega = -cosOmega;
}

float k0,k1;

//当sinOmega 很小的时候,做线性插值
if(cosOmega > 0.9999f)
{
    k0 = 1.f - t;
    k1 = t;
}else
{
    float sinOmega = sqrt(1.f - cosOmega*cosOmega);
    float omega = atan2(sinOmega,cosOmega);
    float oneOverSinOmega = 1.f / sinOmega;

    k0 = sin( (1.f - t)* omega) * oneOverSinOmega;
    k1 = sin(t*omega) * oneOverSinOmega;

}

w = w0 * k0 + w1 * k1;
x = x0 * k0 + x1 * k1;
y = y0 * k0 + y1 * k1;
z = z0 * k0 + z1 * k1;

 

四元数样条——squad

 

你可能感兴趣的:(3D数学基础)