3D数学读书笔记——四元数
本系列文章由birdlove1987編寫,轉載請注明出處。
文章鏈接:http://blog.csdn.net/zhurui_idea/article/details/25400659
什么是四元數
復數是由實數加上虛數單位 i 組成,當中
i2 = -1
相似地,四元數都是由實數加上三個元素 i、j、k 組成,并且它們有例如以下的關系:
i2 = j2 = k2 = ijk = -1
每一個四元數都是 1、i、j 和 k 的線性組合,即是四元數一般可表示為a + bi + cj + dk。
關于四元數的歷史
四元數是由哈密頓在1843年愛爾蘭發現的。當時他正研究擴展復數到更高的維次(復數可視為平面上的點)。他不能做到三維空間的樣例,但四維則造出四元數。依據哈密頓記述,他于10月16日跟他的妻子在都柏林的皇家運河(Royal
Canal)上散步時突然想到
i2 = j2 = k2 = ijk = -1
的方程解。之后哈密頓立馬將此方程刻在附近布魯穆橋(Brougham Bridge,現稱為金雀花橋 Broom Bridge)。
不僅僅如此,哈密頓還創造了向量的內外積(大神就是大神,創造力旺盛啊-_-!)。他亦把四元數描繪成一個有序的四重實數:一個標量(a)和向量(bi + cj + dk)的組合。若兩個標量部為零的四元數相乘,所得的標量部便是原來的兩個向量部的標量積的負值,而向量部則為向量積的值,但它們的重要性仍有待發掘。
四元數的記法
一個四元數包括一個標量分量和一個3D向量分量。常常記標量分量為w,記向量分量為單一的v或分開的x,y,z。兩種記法分別例如以下:
[w,v]
[w,(x,y,z)]
四元數的性質(當年計算機圖形學考的就是這題。。嗚嗚嗚~~)
四元數不像實數或復數那樣,它的乘法是不可交換的,比如
i j = k, , j i = -k ;
j k = i , k j = -i ;
k i = j , i k = -j .
四元數是除法環的一個樣例。除了沒有乘法的交換律外,除法環與域是相類的。特別地,乘法的結合律仍舊存在、非零元素仍有唯一的逆元素。
負四元數
四元數能求負。做法非常直接:將每一個分量都變負。
-q = - [ w ( x y z ) ] = [ -w ( -x -y -z ) ]
= - [ w v ] = [ -w -v ]
ps:q 和 - q代表的實際角位移是同樣的,因此,3D中的隨意角位移都有兩中不同的四元數表示方法,它們互相為負。(由于繞某個軸旋轉360°物體相當于沒有旋轉)
單位四元數
幾何上,存在兩個單位四元數,它們代表沒有角位移:[ 1, 0 ] 和 [ -1, 0 ]
數學上,實際僅僅有一個單位四元數 [ 1 , 0 ] 用隨意四元數q乘以單位四元數,結果仍是q。數學上覺得[ -1 , 0]不是正在的單位四元數。
四元數的模、共軛和逆
四元數的模的記法和求法公式:
四元數的共軛記作 q*
,可通過讓四元數的向量部分變負來獲得。
四元數的逆記作,定義為四元數的共軛除以它的模。
四元數的乘法(叉乘)
四元數叉乘滿足結合律,但不滿足交換律。
(ab)c=a(bc)
ab≠ba
四元數乘積的模等于模的積
||pq|| = ||p|| ||q||
四元數的“差”
四元數的“差”被定義為一個方位到還有一個方位的角位移。換句話說,給定方位a和b,就能計算a旋轉到b的角位移d。
四元數點乘
對于單位四元數a和b,有-1 ≤ a·b ≤ 1。通常我們僅僅關心a·b的絕對值,由于a·b=-(a·-b),所以b和-b代表同樣的角位移。
四元數點乘的幾何解釋類似于向量點乘的幾何解釋。四元數點乘a·b的絕對值越大,a和b代表的角位移越相似。
四元數的對數、指數和標量乘運算
四元數求冪
對四元數求冪在3D編程中很實用,由于它能夠從角位移中抽取一部分,比如四元數q代表一個角位移,如今想得到代表1/3這個角位移的四元數,能夠計算q^1/3
四元數數冪的求法
在實際3D轉換中我們使用這個的代碼進行抽取角位移的部分
// 四元數(輸入、輸出)
float w,x,y,z;
// 指數(輸入)
float zhishu;
// 為了避免除零,我們這里做一個推斷,由于第一個變量時cos,所以這里是.9999f
if (fabs(w) < .9999f) {
// 提取半角alpha
float alpha = acos(w);
// 計算新的alpha
float newAlpha = alpha * exponent;
// 計算新的w值
w = cos(newAlpha);
// 計算新的xyz的值
float temp = sin(newAlpha) / sin(alpha);
x *= temp;
y *= temp;
z *= temp;
}
使用程序前應先進行單位四元數的檢查,由于w=±1會導致temp的計算中出現除零的現象,假設檢測出是單位四元數,直接返回原四元數就可以。
四元數插值
當今3D數學中四元數存在的理由是由于一種叫做slerp的運算,它是球面線性插值的縮寫(Spherical Linear Interpolation)。slerp運算很實用,由于它能夠在兩個四元數間平滑插值。slerp運算避免了歐拉角插值的全部問題。
slerp是一種三元運算,這意味著它有三個操作數。前兩個操作數是兩個四元數,將在它們中間插值。設這兩個開始和結束的四元數分別為q0和q1.差值參數設為變量 t,t 在0到1之間變化。slerp函數:slerp(q0,q1,t)
將返回q0和q1之間的插值方位。
// 兩個輸入四元數
float w0,x0,y0,z0;
float w1,x1,y1,z1;
// 差值變量
float t;
// 輸出四元數
float w,x,y,z;
// 用點乘計算兩個四元數夾角的cos值
float cosJiao = w0*w1 + x0*x1 + y0*y1 + z0*z1;
// 假設點乘為負,則反轉一個四元數以取得短的4D弧
if (cosJiao < 0.0f) {
w1 = –w1;
x1 = –x1;
y1 = –y1;
z1 = –z1;
cosJiao = –cosJiao;
}
// 檢查防止除零
float k0, k1;
if (cosJiao > 0.9999f) {
// 假設很接近,就線性插值
k0 = 1.0f–t;
k1 = t;
} else {
// 利用三角公式sin2+cos2=1計算sin值
float sinJiao = sqrt(1.0f – cosJiao*cosJiao);
// 通過sin和cos計算角度
float Jiao = atan2(sinJiao, cosJiao);
// 計算分母的倒數從而避免使用除法
float oneOverSinJiao = 1.0f / sinJiao;
// 計算插值變量
k0 = sin((1.0f – t) * Jiao) * oneOverSinJiao;
k1 = sin(t * Jiao) * oneOverSinJiao;
}
// 插入值
w = w0*k0 + w1*k1;
x = x0*k0 + x1*k1;
y = y0*k0 + y1*k1;
z = z0*k0 + z1*k1;
嘿嘿,四元數這個地方確實有點難度。。只是3D總體都不太簡單,全部好好加油!
—End—
參考文獻: (1)《3D Math Primer for Graphics and Game Development》
(2) 維基百科
(3) 《計算機圖形學》
總結
以上是生活随笔為你收集整理的3D数学读书笔记——四元数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 爬取微博用户公开信息,分析听李逼的逼粉们
- 下一篇: 杨宗纬最火的10首歌