基本變換
平移變換
平移矩陣= (1 0 0 0 )
(0 1 0 0 )
(0 0 1 0 )
(tx ty tz 1)
點p(px,py,pz,1)與平移矩陣相乘以后,就可以得到新點p' = (px+tx,py+ty,pz+tz,1),在計算機(jī)實時圖形學(xué)上面的平移矩陣好象是錯誤的呀,要轉(zhuǎn)置以后才對的。
在書中記錄的平移是:
(1 0 0 tx)
(0 1 0 ty)
(0 0 1 tz)
(0 0 0 1 )
另外平移矩陣的逆矩陣應(yīng)該是:
(1 0 0 -tx)
(0 1 0 -ty)
(0 0 1 -tz)
(0 0 0 1 )
這里采用代數(shù)行列式的形式計算出來的,具體來說,就是將平移矩陣轉(zhuǎn)置,獲得轉(zhuǎn)置矩陣pt(t),那么p-1(t) = pt(-t).
在D3D里面一般用函數(shù)D3DXMatrixTranslation.
旋轉(zhuǎn)變換
繞x軸旋轉(zhuǎn)
(1 0 0 0 )
(0 cosA -sinA 0)
(0 sinA cosA 0)
(0 0 0 1)
假設(shè)存在某個點p(px,py,pz,1),那么經(jīng)過繞x旋轉(zhuǎn)以后,就可以得到
(px,pycosA + pzsinA, pzcosA-pysinA,1)
在D3D里面一般用函數(shù)D3DXMatrixRotationX
繞y軸旋轉(zhuǎn)
(cosA 0 sinA 0)
(0 1 0 0 )
(-sinA 0 cosA 0)
(0 0 0 1)
假設(shè)存在某個點p(px,py,pz,1),那么經(jīng)過繞y旋轉(zhuǎn)以后,就可以得到
(pxcosA-pzsinA,py,pxsinA+pzcosA,1)
在D3D里面一般用函數(shù)D3DXMatrixRotationY
繞z軸旋轉(zhuǎn)
(cosA -sinA 0 0)
(sinA cosA 0 0)
(0 0 1 0)
(0 0 0 1)
假設(shè)存在某個點p(px,py,pz,1),那么經(jīng)過z旋轉(zhuǎn)以后,就可以得到
(pxcosA + pysinA, pycosA - pxsinA, pz, 1)
在D3D里面一般用函數(shù)D3DXMatrixRotationZ
當(dāng)然還有一個可以自定義的旋轉(zhuǎn)軸做法:
D3DXMatrixRotationAxis
對繞任意旋轉(zhuǎn)角度A的3x3旋轉(zhuǎn)矩陣RL來說,其對角線元素之和是一個與坐標(biāo)軸無關(guān)的常量,稱為跡
tr(R) = 1 + 2cosA
縮放變換
縮放矩陣
s = (sx 0 0 0)
(0 sy 0 0)
(0 0 sz 0)
(0 0 0 1)
假設(shè)存在某個點p(px,py,pz,1),那么經(jīng)過縮放變換以后,就可以得到
(pxsx,pyxy,pzsz,1)
在齊次坐標(biāo)系里面,創(chuàng)建一個一致性縮放矩陣的另外一種方式是通過改變(3,3)處的元素實現(xiàn)
比如
s = (1 0 0 0)
(0 1 0 0)
(0 0 1 1)
(0 0 0 factor)
在這里這個factor將起主要作用.
如果對縮放矩陣的一個或者三個分量置為空,就會產(chǎn)生一個反射矩陣,或者成為鏡像矩陣。如果其中兩個縮放因子是-1,那么將會旋轉(zhuǎn)180度
錯切變換
錯切變換是使圖形產(chǎn)生一個扭變。分為x和y方向的錯切變換。
圖形沿x方向的錯切矩陣表示為
[1 0 0]
[x' y' 1] = [x y 1][b 1 0] = [ x+by y 1]
[0 0 1]
此時,圖形的y坐標(biāo)不變,x坐標(biāo)隨坐標(biāo)(x y)和系數(shù)b作線性變化。b>0,圖形沿+x方向做錯切;b<0,圖形沿-x方向做錯切;b≠0。
圖形沿y方向的錯切矩陣表示為
[1 d 0]
[x' y' 1] = [x y 1][1 1 0] = [ x dx+y 1]
[0 0 1]
此時,圖形的x坐標(biāo)不變,y坐標(biāo)隨坐標(biāo)(x y)和系數(shù)d作線性變化。d>0,圖形沿+y方向做錯切;d<0,圖形沿-y方向做錯切;d≠0。
一般在游戲中被用來扭曲整個場景,從而產(chǎn)生某種虛幻效果,或者抖動來產(chǎn)生模糊反射效果。
Hxy:第一下標(biāo)是由錯切矩陣改變的坐標(biāo),第二個下標(biāo)表示要進(jìn)行錯切操作的坐標(biāo)。
(1 0 s 0)
Hxz(s) = (0 1 0 0)
(0 0 1 0)
(0 0 0 1)
假設(shè)存在P點(px,py,pz,1)與矩陣相乘可以得到(px + s pz, py, pz,1)
任何錯切矩陣的行列式值總為1。
變換級聯(lián)
矩陣乘法存在不可交換性,將多個矩陣級聯(lián)為單個矩陣可以獲得比較好的效率。
剛體變換
僅由平移和旋轉(zhuǎn)兩種級聯(lián)所做成的變換稱為剛體變換,這種變換具有長度和角度不變的特性。
可以將剛體矩陣X寫成一個平移矩陣T(t)和一個旋轉(zhuǎn)矩陣R的級聯(lián)。
( r00 r01 r02 tx)
( r10 r11 r12 ty)
X = T(t)R = ( r20 r21 r22 tz)
( 0 0 0 1)
X的逆矩陣 = (T(t)R)的逆矩陣 = R的逆矩陣*T(t)的逆矩陣 = R的逆矩陣 * T(-t)
首先對矩陣R左上角的3x3矩陣進(jìn)行轉(zhuǎn)置,然后改變平移矩陣T的平移值符號,最后將這兩個矩陣進(jìn)行相乘即可以得到相應(yīng)的逆矩陣。
另外一種求X的逆矩陣方法:
(r,0轉(zhuǎn)置)
R = ( r,0 r,1 r,2) = (r,1轉(zhuǎn)置)
(r,2轉(zhuǎn)置)
X = ( R t)
( 0轉(zhuǎn)置 1)
法線變換
法線必須通過用變換集合圖形的逆矩陣的轉(zhuǎn)置矩陣進(jìn)行變換。
在實際應(yīng)用中,如果變換矩陣是正交的,就沒有必要計算該矩陣的逆矩陣
在這種情況下,正交矩陣的逆矩陣就是轉(zhuǎn)置矩陣,可以用這個矩陣本身對法線進(jìn)行變換。
如果使用一個或者多個一致性縮放矩陣進(jìn)行變換,就不需要計算相應(yīng)的逆矩陣,因為這個縮放只影響變換后的法線長度,而不影響其方向,在這種情況下,一般都要在矩陣變換對法線進(jìn)行變化之后,需要對法線進(jìn)行歸一化。
逆矩陣計算
1) 如果矩陣是單個變換或者一些給定參數(shù)的變換,那么很容易通過調(diào)換參數(shù)和矩陣順序計算出相應(yīng)的逆矩陣,比如M = T(t)R(s), 那么M的逆矩陣為R(-s)T(-t)
2) 如果矩陣是正交,那么其逆矩陣就是其轉(zhuǎn)置,任何的旋轉(zhuǎn)變換都是正交的。
3) 在不知道任何特殊信息的情形下,可以采用伴隨矩陣,克萊姆法則,LU分解,或者高斯消去法來計算逆矩陣
歐拉變換
主要用來構(gòu)造一個自定位(如相機(jī))或者任何實體處于特定方向的矩陣。
首先,需要建立一種默認(rèn)的觀察方向,通常情況下,頭部沿著y軸方向,面部朝向為z軸負(fù)方向。
當(dāng)使用歐拉變換的時候,會出現(xiàn)所謂萬向鎖(Gimbal Lock),這種現(xiàn)象通常出現(xiàn)在旋轉(zhuǎn)變換的時候出現(xiàn),其中會缺少一個自由度。
改變head就是使觀察者搖頭說不,改變pitch就是點頭,改變roll就是頭向一邊歪。
矩陣分解
主要應(yīng)用場合:
1)提取縮放因子
2)確定特定系統(tǒng)所需要的變換
3)確定模型是否只經(jīng)歷過剛體變換
4)在動畫的關(guān)鍵幀之間插值
5)從旋轉(zhuǎn)矩陣中消除其中的錯切變換
四元組
四元數(shù)是一個用來構(gòu)造強(qiáng)制變換的有力工具,在某些情況下,要比歐拉角和歐拉矩陣更具有優(yōu)勢,特別是在遇到旋轉(zhuǎn)和定向的情況時更是如此。
數(shù)學(xué)背景
q = (qv,qw) = iqx + jqy + kqz + qw = qv + qw
qv = iqx + jqy + kqz = (qx,qy,qz)
i*i = j*j = k*k = -1, jk = -kj = i, ki = -ik = j, ij = -ji = k
乘法:
QR = (iqx + jqy + kqz + qw)(irx + jry + krz + rw)
= i*(qyrz - qzry + rwqz + qwrx)
+ j*(qzrx - qxrz + rwqy + qwry)
+ k*(qxry - qyrx + rwqz + qwrz)
+ qwrw - qxrx - qyry - qzrz
= qv * rv + rwqw - qxrx - qyry - qzrz
加法:
Q + R = (qv, qw) +(rv,rw) = (qv + rv, qw + rw)
共厄:
Q = (qv,qw)共厄 = (-qv,qw)
范數(shù):
n(Q) = qx * qx + qy * qy + qz * qz + qw * qw
同一性:
i = (0,1)
逆:
q的逆 = 1/n(Q) *Q共厄
共軛法則:
Q共軛 = Q共軛
( Q + R)共軛 = Q共軛 + R共軛
(QR)共軛 = R共軛Q共軛
范數(shù)法則:
n(Q共厄) = n(Q)
n(QR) = n(Q)n(R)
乘法定律:
線性關(guān)系: P(sQ + tR) = sPQ + tPR
(sP +tQ)R = sPR + tQR
組合關(guān)系:P(QR) = (PQ)R
單位四元組Q=(qv,qw)的模n(Q)為1,基于此,Q可以表示為:
Q = (sinAuq,cosA) = sinAuq + cosA
對于一些三維向量uq來說,有||uq|| = 1,因為:
n(Q) = n(sinAuq,cosA) = sinA*sinA*(uq.uq) + cosA*cosA = 1
當(dāng)且僅當(dāng)uq*uq = ||uq|| *||uq||.
球面線性插值
球面線性插值是在給定兩個單位四元組Q和R,以及一個參數(shù)t(0<=t<=1)的情況下計算插值四元組,
該運(yùn)算的代數(shù)形式可以用下面的復(fù)合四元組S表示:
S(Q,R,t) = (RQ的逆)tQ
slerp表示球面線性插值
slerp(Q,R,t) = sinA(1-t)/sinA*Q + sinAt/sinA *R
cosA = qxrx + qyry + qzrz + qwrw
對于0<=t<=1來說,slerp函數(shù)計算是唯一的插值四元組
這些四元組構(gòu)成了四維單位球面上從Q(t=0)到R(t=1)之間的最短弧。
這條弧位于一個圓上,這個圓由Q,R,以及原點組成的平面與四維單位球面相交形成的
Ai = Bi = Qi exp(-(log(QiQi-1)+log(QiQi+1))/4)
使用Qi,Ai和Bi對使用平滑三次樣條的四元組進(jìn)行球面插值
squad(Qi,Qi+1,Ai,Ai+1,t) = slerp(slerp(Qi,Qi+1,t),slerp(Ai,Ai+1,t),2t(1-t))
squad函數(shù)是由slerp函數(shù)重復(fù)使用球面插值而構(gòu)成的,該插值通過初始化方位Qi而不是Ai,Ai主要用來表示初始方位的切線方向。
從一個向量到另外一個向量的旋轉(zhuǎn)
四元組計算規(guī)則:
首先對s和t歸一化,然后,計算出單位旋轉(zhuǎn)軸u,具體通過式u = (s*t)/||s x t||來計算。
其次e = s.t = cos2A,||s * t|| = sin2A
其中2A表示s與t之間的夾角.
這樣,從s到t旋轉(zhuǎn)的四元組可以表示為Q =(sinAu,cosA).