天天看點

四元數定義、運算、插值

1、複數

1.1 複數的定義

四元數定義、運算、插值

                           圖 1 - 1

從解方程來看,方程在笛卡爾坐标系上應該都有解.

但是象這樣的方程(x² + 1 = 0)還是無解,因為沒有一個實數的平方等于-1。

在十六世紀,由于解方程的需要,人們開始引進一個新數,叫做虛數機關要解決這個方程 x² = -1 ,但是于任何實數的平方都是非負數沖突,是以引入一個新的概念——複數。

虛數的定義如下 i² = -1 ①

i ^ 0 = 1

i ^ 1 = i

i ^ 2 = −1

i ^ 3 = i * i ^ 2 = −i

i ^ 4 = i ^ 2 * i ^ 2 = 1

i ^ 5 = i * i ^ 4 = i

複數的集合是一個實數和一個虛數的和,形式如下:

z = a + bi (a,b∈R, i ^ 2 = −1) ②

1.1.2 虛數的意義

四元數定義、運算、插值

                                                              圖 1 - 2

假設現在點A(1, 0)  點B(-1, 0)

那麼A點經過 逆時針旋轉90度兩次 可以到達B點

可得 1 * (逆時針旋轉90度) *  (逆時針旋轉90度) = -1

設i = (逆時針旋轉90度)  則i * i = -1  也就是說i是旋轉量

實際上i ^ 1——i ^ 4 就是旋轉360度 即虛數的周期

1.2 複數的運算

四元數定義、運算、插值

                                                        圖 1 - 3

1.2.1 共轭複數

如圖(1-3)所示, 根據②可得複數可以由x軸(實數軸)與 y軸(虛數軸)确定唯一的一點,而實數相同,虛數向反的複數被稱為共轭複數。

如 z = a + bi 與 z’= a - bi ⑦

1.2.2 複數的加、減、乘法運算

根據定義② 複數 = 實數 + 虛數 則

(a + bi) + (c + di) = (a + c) + (bi + di) = (a + c) + (b + d)i

(a + bi) - (c + di) = (a + c) - (bi + di) = (a + c) - (b + d)i

(a + bi) * (c + di) = ac + bci + adi + bdi * i

根據定義①          = (ac - bd) + (ad + bc)i

1.2.3 複數的向量與輻角

四元數定義、運算、插值

                    圖  1 - 4

向量: 既有絕對值大小又有方向的量

線段的長度就是這個向量的絕對值(叫做這個向量的模)

線段的方向(用箭頭表示)就是這個向量的方向。

求絕對值 |a| = (a * - a)^ 1/2

a 與 -a 是數軸x上對稱的兩點

而複數對稱的兩點分别為 a + bi 與 a - bi

則 |a + bi| = [(a + bi)(a - bi)] ^ 1/2

|a + bi| = ( a ^ 2 + b ^ 2) ^ 1/2 根據定義①

這個向量與x軸構成的夾角就是複數輻角# tan(b/a)

1.2.4 複數的旋轉

四元數定義、運算、插值

                   圖 1 - 5

在數軸上任何取一點 a + bi 連續與i 相乘4次 根據定義① 可得,則幾個數分别為:

1、 a + bi

2、 -b + ai

3、 -a - bi

4、 b - ai

b - ai 乘以 i  又回到了 a + bi 實際上乘以 i 是複數 a + bi (a = 0, b = 1)的特殊情況那麼一般情況的複數相乘又代表什麼呢?定義以下複數(n為複數向量的模)

p = n1(cosA + i * sinA)

q = n2(cosB + i * sinB)

則 pq = n1 * n2(cosA + i * sinA)(cosB + i * sinB)

      = n1 * n2[(cosAcosB - sinAsinB) + i(sinAcosB + cosAsinB)]

     = n1 * n2[cos(A + B) + isin(A + B)]

可得複數相乘 1、積的模 = 兩複數模的積 (n1 * n2 = n1 * n2)

             2、積的輻角 = 兩複數輻角的和 ( A + B = A + B)

複數的相乘會使複數向量的模增加或減小,并且旋轉改變該向量的方向

而旋轉後的角度為原複數輻角的和 ④

根據④容易用複數求得方向

四元數定義、運算、插值

               圖 1 - 6

如圖(1-6) 在海航上,船原來的坐标是(3 ^ 1/2, i),經過45度的旋轉後

現在船的方向是多少

複數相乘方向不考慮模的大小,是以輻角45度可以設複數為1 + i

則 (3 ^ 1/2 + i)(1 + i) = (3 ^ 1/2 - 1) + (3 ^ 1/2 + 1)i

即為此時的方向,此時的輻角為(3 ^ 1/2 + 1) / (3 ^ 1/2 - 1) = tan75

2、 四元數的定義

2.1 四元數的記法

四元數定義、運算、插值

                  圖 2 - 1

歐拉證明了 一個旋轉序列等價于單個旋轉。想象一下,你有一根木棒,其中一端固定在一個地方,通過任意移動木棒,可以達到任意的角度(如圖 2 - 1)

是以, 3D空間中任意角位移都可以表示成繞單一軸的單一旋轉。

四元數的一般形式:

q = w + xi + yj + zk   w,x,y,z∈R

四元數的簡寫形式:

q = [cosA, sinA * n] ⑥

  = [cosA, (sinA * n_x, sinA * n_y, sinA * n_z)]

w == 木棒的長度   (i, j, k)相當于三維空間的坐标

2.1.2 複數與笛卡爾乘積

四元數定義、運算、插值

                                                 圖  2 - 2

設向量OA = A, 向量OB = B, 向量OC = C

向量叉乘公式  C = A × B = |A||B|sin#  #代表向量A、B之間的夾角 ④

四元數定義、運算、插值

                                                       圖 2 - 3

如圖(2 - 3) 假設i代表x軸的正方向, j代表y軸正方向, k代表z軸正方向

根據定義④可得 i × j = k, j × k = i

               k × i = j, j × i = -k

               i × k = -j, i × k = -j ⑤

可由右手定理判斷正反符号,如計算i × j

第一步 将右手的4個指頭指向第一個數i

第二步 将右手向j的方向轉

第三步 此時拇指 指向k的正方向 則i × j = k

如計算j × i

第一步 将右手的4個指頭指向第一個數j

第二步 将右手向i的方向轉

第三步 此時拇指 指向k的負方向(正方向的反方向) 則j × i = -k

2.1.3 負四元數與機關四元數

設四元數q = [w, (x, y, z)], -q = [-w, (-x, -y, -z)]

設點A(x, y, z), B(-x, -y, -z), 向量_OA = (x, y, z), 向量_OB = (-x, -y, -z)

_OA = -_OB,則A,O,B三點共線,也就是說q與 -q旋轉軸相同,又因為對于旋轉軸,長度可以忽略不計,則對于四元數q = -q

在幾何上,機關四元數的定義為乘以任意四元數q,得到的結果為q。如圖2-1,将這條線段繞多少度可以變回原來的樣子,顯然是360度整數倍數,又根據 ⑥ 可得機關四元數為q = [cos(360n), sin(360n)n] = [1, 0] = [-1, 0]

2.1.4 四元數的模

||q|| = ||[w, (x, y, z)]|| = (w ^ 2 + x ^ 2 + y ^ 2 + z ^ 2) ^ 1/2

= ||[w, v]|| = (w ^ 2 + ||v|| ^ 2) ^ 1/2

 根據⑥,代入A和n可得:

||q|| = ||[w, v]||

    = (cosA ^ 2 + (sinA||n||) ^ 2) ^ 1/2

n為機關向量,則:

||q|| = (cosA ^ 2 + sinA ^ 2) ^ 1/2 = 1

可得機關四元數的模為1

2.1.5 四元數的叉乘

q = [w1, (x1, y1, z1)]

p = [w2, (x2, y2, z3)]

pq = (w1w2 − x1x2 − y1y2 − z1z2)

+(w1x2 + w2x1 + y1z2 − y2z1)i

+(w1y2 + w2y1 + z1x2 − z2x1)j

+(w1z2 + w2z1 + x1y2 − x2y1)k

  = (w1w2 − x1x2 − y1y2 − z1z2)

+ w1(x2i + y2j + z2k) + w2(x1i + y1j + z1k)

+ (y1z2 - y2z1)i + (z1x2 - z2x1)j + (x1y2 - x2y1)k

設A = (x2i + y2j + z2k),B = (x1i + y1j + z1k)

又根據:

1、向量的點積 A ▪ B = x1x2(i * i) + y1y2(j * j) + z1z2(k * k)

= x1x2 + y1y2 + z1z2 (向量的點積是标量 此處i = j = k = 1)

2、 向量的叉乘 A × B = x1y1(i * i) + x1y2(i * j) + x1z2(i * k)

                      + y1x2(j * i) + y1y2(j * j) + y1z2(j * k)

                      + z1x2(k * j) + z1y2(k * j) + z1z2(k * k)

在根據⑤ 化簡可得 A × B =  (y1z2 - y2z1)i + (z1x2 - z2x1)j + (x1y2 - x2y1)k

則pq = (w1w2 - A ▪ B) + (w1A + w2B + A × B)

= [w1w2 - A ▪ B, w1A + w2B + A × B]  ⑧

結論:四元數乘積的模等于模的乘積 ⑨——> 兩個機關四元數相乘的結果還是機關四元數

假設p, q分别為機關四元數

則p = [1, 0], q = [1, 0]

||pq|| = ||1 + 0 + 0 + 0|| = ||1|| = 1

||p|| * ||q|| = ||1|| * ||1|| = 1

2.1.7 四元數共轭和逆

根據⑦可得

q’ = [w, v]’= [w, v’]

= [w, (-x, -y, -z)] ⑩

四元數的逆為 q ^ -1, 定義為四元數的共轭除以他的模

q ^ -1 = q’/ ||q||

結論:(ab) ^ -1 = (b^-1)(a^-1)

設 a = [w1, v1]

   b = [w2, v2]

則 (ab)^-1 = (ab)’/ ||ab||

根據⑧ (ab) = [w1w2 - v1 ▪ v2, w1v1 + w2v2 + v1 × v2]

根據⑩ (ab)’ = [w1w2 - v1 ▪ v2, -(w1v1 + w2v2 + v1 × v2)]

b’ = [w2, -v2]

a’ = [w1, -v1]

根據⑤⑧可得

b’a’ = [w1w2 - v1 ▪ v2, -(w1v1 + w2v2 + v1 × v2)]

(b^-1)(a^-1) = b’a’/ ||b||||a||

根據⑨ ||ab|| =  ||b||||a||

又因為 (ab)’ = b’a’

則(ab) ^ -1 = (b^-1)(a^-1)成立

可得 (q1q2q3...qn) ^ -1 = (qn)^-1...(q2^-1)(q1^-1)

即四元數的乘積的逆等于各個四元數的逆以相反順序相乘 ⑪

2.1.8 四元數的旋轉

根據④可得 複數的相乘可以表示2D上的旋轉

那麼四元數的相乘是否可以表示3D上的旋轉呢?

就如同三維上的點(x, y, z) 當z = 0時可以表示為二維上的點

同理将四維上的點[w, v] 當w = 0時可以表示三維上的點

設 p = [0, (ai, bj, ck)]

   q = [w1, (x1i, y1j, z1k)] (表示旋轉軸)

   q^-1 = [w1, -(x1, y1, z1)]

qp = [-(ax1 + by1 + cz1), (aw1 + cy1 - bz1)i,

        (bw1 + az1 - cx1)j, (cw1 + ay1 - bx1)k]

pq^-1 = [(ax1 + bx1 + cz1), (aw1 - bz1 + cy1)i,

        (bw1 - cx1 + az1)j, (cw1 - bx1 + ay1)k]

觀察可得qp 與 pq^-1的第四維互為相反數,而在三維坐标上的點相同

也就是說都是沿相同的方向轉過了相同的角度。又因為他們的模相同

則qp 與 pq^-1的幾何意義是兩個相同的旋轉

而qp 可以通過複數q與複數p相乘得到

pq^-1可以通過複數q^-1與複數p相乘得到

将向量q與q^-1平移到圓點,如圖(2-4)所示

四元數定義、運算、插值

                                                       圖  2 - 4

第一次旋轉為qp

第二次旋轉為(qp)q^-1

設旋轉的結果後為p’ 則p’ = qpq^-1 ⑫

因為是旋轉了兩次,是以需要用四元數計算旋轉的時候,角度是 (2 * #) / 2 = 2

即按照目标角度的一半來計算 (2 * #)的幾何意義為目标角度

3、 四元數的插值

3.1 普通線性插值

四元數定義、運算、插值

                                圖 3 - 1

如圖(3-1),在一條直線AB上插入任意一個值,我們需要的是點D的坐标。如圖所示過A、B點分别做x軸的垂線。分别交予x軸與點E、F。過A點做與BF的垂線,交于點C,連接配接AC。

在AB上任意取一點D,過D點做與AC的垂線,交于點M。

設D(x0, y0)

則x0 - x1 = AM

顯然∠BAC = ∠DAM

tan∠BAC = BC / AC

tan∠DAM = DM / AM

則 BC / AC = DM / AM

AC = x2 - x1, BC = y2 - y1

DM = (y2 - y1 / x2 - x1 )(x0 - x1)

y0 = AE + DM = y1 + (y2 - y1 / x2 - x1 )(x0 - x1)

即 y0 = y1 + (y2 - y1 / x2 - x1 )(x0 - x1)

四元數定義、運算、插值

                                               圖 3 - 2

在平面上任意取A點與B點,做向量_OA與向量_OB。連接配接AB,做向量_AB。在AB上任意取一點C,做向量_OC。

則1. _OA + _AB = _OB, _OA + _AC = _OC

因為點C在直線AB上,則_AC 與 _AB共線, 設_AC = t _AB

則2. _OC = _OA + t_AB

标準線性插值公式:lerp(a0, a1, t) = a0 + t△a △a = a1 - a0 ⑬

設a0 = _OA, a1 = _OB 根據1與2可得

_OC = a0 + t△a △a = a1 - a0

3.2 四元數插值——slerp

四元數定義、運算、插值

                                                圖  3 - 3

在球形體中插值,顯然軌迹是弧形的,如圖(3-3)所示。

顯然點C在弧AB的運動過程中,線段OC的長度的不變的

而普通的線性插值_OC的長度是會改變的, 如圖(3-2)

四元數定義、運算、插值

                                                圖 3 - 4

sleap的基本思想是 沿4D球面上連接配接的兩個四元數的弧插值(球面插值)

把這種思想表現在平面上

如圖(3-4),設兩個2D向量_OA與_OB,我們需要計算_OC,設w是_OA到_OB弧所截的角

為了友善計算 設v0 = _OA,   v1 = _OB,   vt = _OC

将vt表示成v0與v1的線性組合: vt = kovo + k1v1

四元數定義、運算、插值

                                                        圖  3 - 5

過C點做OB的平行線,交OA與點M。分别過點B與點C做于OA的垂線,分别交線段OA于點E、M。

易得△BOE與△CMF是相似三角形

則 OB / BE = CM / CF

OB = |v1|, BE = OB * sinw = |v1|sinw

CM = k1|v1|, CF = OC*sintw = |vt|sintw = |v1|sintw (線段OC與OB長度相同,則|vt| = |v1|)

代入可得: k1 = sintw / sinw ⒂

四元數定義、運算、插值

                                                                 圖 3 - 6

 過C點做于OA的平行線,交OB于點E。過點E做OC的垂線,交OC于點F。

易得_OE = _MC = k1v1, _EC = _OM = k0v0

∠EOC = (1-t)w,  ∠ECO = W

線段EF = OE sin∠EOC = EC sin∠ECO

則 k1|v1| sin((1-t)w) = k0|v0| sinw = k0|v1|sinw

根據⒂可得: k0 = sin(1 - t)w / sinw ⒃

将⒂⒃代入到 vt = kovo + k1v1

可得vt = (sin(1 - t)w / sinw )vo + ( sintw / sinw)v1

将同樣的思想擴充到四元數,重寫slerp可得:

slerp(q0, q1, t) = (sin(1 - t)w / sinw )q0 + ( sintw / sinw)q1

而w, 可以計算q1和q2的點積進而得出角度w:

cosw = q1▪q2 / |q1||q2|

這樣的作法會産生兩個問題:

四元數定義、運算、插值

                                              圖  3 - 7

1. 可能會繞遠路,将點A旋轉到OB旋轉軸,可以順時針旋轉也可以逆時針旋轉。

設∠BOA = w, 顯然當w小于90度的時候,順時針旋轉所需要的路徑較短,而當w大于90度的時候,逆時針旋轉所需要的路徑較短。

首先我們需要确定w是否大于90度,可以使用:

cosw = q1▪q2 / |q1||q2|   0 < w < 180

因為 |q1||q2| > 0恒成立

是以實際上需要計算的是q1▪q2

當q1▪q2 > 0的時候, cosw > 0   w < 90

當q1▪q2 < 0的時候, cosw < 0   w > 90

确定了角度之後,我們需要的是按順時針還是逆時針旋轉

而四元數代表旋轉軸的時候q = -q

我們可以将其中一個四元數取反,總結:

q1▪q2 > 0時, 旋轉為q1q2

q1▪q2 <= 0時,  旋轉為(-q1)q2或(-q2)

2. 當w較小的時候,sinw ——> 0,sin(1 - t)w ——> 1

則(sin(1 - t)w / sinw )q0 ——> ∞

計算機沒有真正的∞,是以我們需要确定一個sinw的範圍,如當sinw < 0.0001的時候

sinw = 0.0001。

4、 個人說明

本文參考于《3D數學基礎:圖形與遊戲開發》,文中内容屬于個人(萌新)了解,可能會出現一些錯誤,歡迎大佬指正,本文僅供參考。