圖形變換是一個將例如點、向量或者顏色等實體進行某種轉換的操做。對於計算機圖形學的先驅者,掌握圖形變換是極爲重要的。有了他們,你就能夠對象、光源以及攝像機進行定位,變形以及動畫添加。你也能夠確認全部的計算都是在同一個座標系統下面進行的,而物體以不一樣的方式投影到平面上。在圖形變換隻有少數操做運行,但它們足以證實圖形變換在實時圖形學中的重要性,甚至能夠說是任何一種計算機圖形學。算法
線性變換是一種保留了向量加法和標量乘法的變換。具體以下:編程
f(x) + f(y) = f(x+y), kf(x) = f(kx) (4.1)數組
例如,f(x)=5x就是變換,即將向量中的每一個元素都乘以5。這種變換是線性的,由於兩個向量先乘以5再相加的出的結果與它們先相加後乘以5的結果是同樣的。標量乘法條件是知足的。這個函數叫作縮放變換,由於它改變了對象的縮放比例(尺寸)。使向量繞原點轉動的旋轉變換是另外一種線性變換。縮放和旋轉變換,以及全部用於三元向量的線性變換,均可以用一個3×3的矩陣表示。緩存
然而,這個矩陣的大小還不夠。用於三元向量x的函數,例如f(x)=x+(7,3,2)不是線性的。分別在兩個向量上運行這個函數時,會將(7,3,2)中的每一個元素都加兩次而造成結果。將一個固定數值的向量加到另外一個向量上是執行了平移,便是,它以一樣的大小移動全部位置。這是一種十分有用的變換類型,而咱們但願將各類變換組合到一塊兒,例如,將對象縮小至一半,移動它到不一樣的位置。目前爲止保持函數的簡單形式,使得很難將它們組合起來。架構
線性變換和平移的結合能夠經過仿射變換實現,典型的是將其存儲在一個4×4的矩陣中。仿射變換執行線性變換,接着進行平移。爲表明四元向量,咱們使用以一樣方法(粗體小寫)指示點和方向的齊次標記。v = (vx vy vz 0)T表明一個方向向量,而v = (vx vy vz 1)T表明一個點。在這一章,咱們會大量使用到附錄A中解釋的術語。你如今或許須要看看附錄,特別是905頁的關於齊次標記的A.4章節。框架
全部的平移,旋轉,縮放,反射,以及剪切矩陣都是仿射的。仿射矩陣的主要特色是它保持了直線間的平行關係,但不必定保持其長度和角度。一個仿射變換也能夠多個個體仿射變換的任意次序的鏈接。函數
這一章節將從最基本的,最基礎的仿射變換開始。這確實是很基本的,而且這章節能夠看着簡單轉換的「參考手冊」。而後更多的是關於專用矩陣的描述,接着的是一個強大的圖形變換工具——四元數的描述。而後是頂點混合和變形,這二者都是簡單但功能強大的網格的動畫表示方式。最後,投影矩陣被描述。大部分的圖形變換,他們的符號,函數和屬性將在表格4.1中總結。工具
圖形變換是一個操縱幾何圖形的基本工具。全部的圖形應用程序編程接口(APIs)包含了矩陣操做,這些操做實現了不少這章所討論的圖形變換。可是去了解真正的矩陣,以及它們在函數調用背後的互動是值得的。知道在函數調用後矩陣作了什麼只是一個開始,但理解矩陣自己的屬性會讓你更爲深刻。例如,當你正處理正交的矩陣時,這些理解能幫助你認識到它的逆矩陣也就是它的轉置矩陣(見904頁),從而得出更快的矩陣求逆。這類知識能夠優化代碼,加速執行。測試
符號優化 |
名稱 |
特性 |
T(t) |
平移矩陣 |
移動一個點。 仿射。 |
Rx(ρ) |
旋轉矩陣 |
繞x軸旋轉ρ的角度。類似的標記用於y軸和z軸。 正交且仿射。 |
R |
旋轉矩陣 |
全部的旋轉矩陣。 正交且仿射。 |
S(s) |
縮放矩陣 |
根據s,沿x、y、z軸進行縮放。 仿射。 |
Hij(s) |
剪切矩陣 |
相對j對i進行參數爲s的剪切變形,i, j∈{x, y, z}。 仿射。 |
E(h, p, r) |
歐拉變換 |
歐拉角(head/yaw,pitch,roll)給出的朝向矩陣。 仿射。 |
Po(s) |
正交投影 |
向某個平面或體積進行平行投影。 仿射。 |
Pp(s) |
透視投影 |
向一個平面或體積進行透視投影。 |
slerp() |
插值變換 |
根據四元數和以及參數t,建立一個插值的四元數 |
表格4.1 這一章中討論的大部分圖形變換的總結
4.1 基本圖形變換
這一節描述了最基本的圖形變換,例如平移,旋轉,縮放,剪切,圖形變換的連結,剛體轉換,法線變換(這並不常見),和矩陣求逆。對於已有相應經驗的讀者,這能夠用做簡單圖形變換的參考手冊;而對於新手,它能夠用做該主題的入門。這些材料是這章剩餘部分以及本書中其它各章的必須的背景知識。咱們從最簡單的變換——平移變換開始。
4.1.1 平移
由一個位置到其餘位置的變換是由平移矩陣,T所表明。這個矩陣經過一個向量t=(tx,ty,tz)變換一個實體。下面的方程4.2給出T:
圖4.1展現了平移變換產生的效果。容易看到的是一個點P=(px, py, pz, 1)與T(t)相乘產生新的點P’=(px+tx, py+ty, pz+tz, 1),這就是平移。注意到向量v=(vx, vy, vz, 0)左乘T後沒有變化,由於一個方向向量不能被平移。相反的,其他的仿射變換都能影響點和向量。平移矩陣的逆矩陣是T-1(t)=T(-t),換句話說,向量t是取反的。
圖4.1 左邊的一個正方形被平移矩陣T(5,2,0)所轉換,據此,正方形向右移動了5個單元而向上移動了2個單元。
4.1.2 旋轉
一個旋轉變換繞給定的過原點的軸將一個向量(位置或方向)旋轉給定的角度。就像平移變換那樣,它是剛體變換,也就是它保存被變換的點之間的距離,而且保持旋向性(也就是說他從不會使圖形左右交換)。這兩種圖形變換在計算機圖形學中的物體的定位和定向是十分有用的。一個方向矩陣是一個與攝像機視圖或者一個定義其在空間中的朝向的對象相關的旋轉矩陣,也就是說他的方向是向上和向前。經常使用的旋轉矩陣是Rx(φ),Ry(φ)和Rz(φ),它們使實體繞相應的x,y和z軸轉動φ個弧度。方程4.3~4.5給出了相應的矩陣:
對於每一個3×3的旋轉矩陣,R,繞任何軸旋轉φ弧度,它的跡(定義見898頁)是獨立於軸的常量,計算以下:
tr(R) = 1 + 2cosφ (4.6)
能夠在62頁的圖4.4看到旋轉矩陣的效果。Ri(φ)表徵一個旋轉矩陣,除了它繞i軸轉動φ個弧度外,它還保持i軸上全部的點不變。注意到R也用於指示繞任意軸的旋轉矩陣。上面給出的軸旋轉矩陣可用於一系列的三個圖形變換去執行繞任意軸的旋轉。這個過程將在4.2.1節中討論。4.2.4節中直接涵蓋了執行一個繞任意軸的旋轉。
全部的旋轉矩陣行列式爲1而且是正交的,十分容易經過904頁的附錄A給出的正交矩陣定義去驗證。對於任意數量的這種變換的鏈接,這個性質也是保持的。這是另外一個得到逆矩陣的方法:Ri-1(φ) = Ri(-φ),也就是,繞同一軸的相反方向轉動。由於旋轉矩陣是正交,其行列式老是爲1.
例子:繞一個點旋轉。假設咱們想讓一個對象以z軸爲軸,以某個點P爲旋轉中心,旋轉φ弧度。這是什麼圖形變換?這個情景在圖4.2中描繪。由於一個繞一點的旋轉的特色是點自己事實上不能被旋轉所影響,因而圖形變換首先平移對象,經過T(-p)使得P與原點重合。其後接着的是真正的旋轉:Rz(φ)。最後,對象使用T(p)被平移回原來的位置。產生的變換,X,以下
X=T(p)Rz(φ)T(-p) (4.7)
圖4.2 繞指定點P旋轉的例子。
4.1.3 縮放
一個縮放矩陣,S(s)=S(sx, sy, sz),根據對應x,y和z軸的因子sx,sy,sz縮放一個實體。這意味着一個縮放矩陣能夠用於物體的放大縮小。si(i∈{x, y, z})越大,縮放的實體在相應的方向就越大。將S的任何份量設置爲1一般避免該方向發生縮放變化。方程4.8展現了S:
62頁的圖4.4展現了縮放矩陣的效果。若是sx=sy=sz則將縮放操做叫作一致的,不然就是不一致的。有時會用各向同性和各向異性代替一致的和不一致的。其逆矩陣爲S-1(s)=S(1/sx, 1/sy, 1/sz)。
另外一個使用齊次座標建立一個一致的縮放矩陣的合法方法是操縱矩陣中位於(3,3)位置的元素,也就是右下角的元素。這個數字影響齊次座標的w份量,所以全部的座標都經過矩陣進行縮放變換。例如,一致地以因子5進行縮放,(0,0),(1,1)(2,2)位置上的元素能夠設置爲5,或者(3,3)位置上的元素設置爲1/5。執行這個操做的兩個不一樣矩陣以下:
與將S用於一致縮放相反,S’的使用必須遵照均勻化,縮放要一致。這多是低效的,由於它在均勻化過程當中涉及了除法;若是右下角((3,3)位置)的元素爲1,則不須要相除。固然,若是系統老是執行除法而不先測試除數爲1,那麼這裏就沒有額外的消耗。
一或三個S份量爲一負值給出了反射矩陣,也叫作鏡像矩陣。若是隻有兩個縮放因子是-1,那麼咱們會旋轉π個弧度。當發現反射矩陣時,一般須要特殊處理。例如,一個頂點順序是逆時針的三角形通過反射變換後會獲得順時針順序。這個順序的改變會致使不正確的光照和背部消隱產生。爲檢測一個給定矩陣是屬於那種狀況,計算左上3×3的元素組成的矩陣的行列式。若是數值是負的,矩陣就是反射的。
例子:某個方向上的縮放。縮放矩陣S僅沿着x,y和z軸進行縮放。若是須要在其餘方向上進行縮放,那麼就須要複合變換了。假設須要沿着標準正交的,右手定則的向量fx,fy和fz進行縮放。首先,以下構建矩陣F:
其思路是使這三個軸給出的座標系與標準的軸重合,接着使用標準的縮放矩陣,而後再轉換回來。第一步經過與F的轉置矩陣,也就是逆矩陣,相乘而得出。方程4.11展現了這個變換:
X=FS(s)FT (4.11)
4.1.4 剪切變換
另外一類圖形變換是一組剪切矩陣。它們能夠作,例如被用於遊戲中去扭曲場景中的實體以營造迷幻的效果或是經過抖動創造模糊反射(見9.3.1節)。這有6種基本的剪切矩陣,它們被標記爲Hxy(s),Hxz(s),Hyx(s),Hyz(s),Hzx(s)和Hzy(s)。第一個下標用於標記那個座標被剪切矩陣改變,而第二個下標指出那個座標執行這個剪切。方程4.12展現了剪切矩陣Hxz(s)。觀察到下標能夠用於肯定參數s在下面矩陣的位置;x(其數字索引是0)標記爲第0行,而z(其數字索引爲2)標記爲第2列,因此s定位於那兒:
這個矩陣與一個點P相乘產生一個點:(px+spz py pz)T。圖4.3生動地將其展現在單元正方形上。Hij(s)的逆矩陣(相對第j號座標,剪切第i號座標,且i≠j)經過反方向的剪切變換生成,即H-1ij(s) = Hij(-s)。
圖4.3 使用Hxz(s)剪切單位正方形的效果。y和z的值都沒有受到圖形變換的影響,而x值則是x的原數值與s與z的乘積的和,使得正方形傾斜。
一些計算機圖形學的文章使用稍不一樣種的剪切矩陣:
但在這裏,全部的下標都用於標記被第三個座標剪切的座標。這兩種不一樣種類的描述之間的關聯是H’ij(s,t)=Hik(s)Hjk(t), k用做第三個座標的索引。使用何種矩陣是我的的喜愛和API是否提供支持。
最後,應該注意到的是任何剪切矩陣的行列式|H|=1,這是一個保存體積不變的圖形變換。
4.1.5 圖形變換的串接
由於矩陣乘法的不可交換性,矩陣出現的順序變得十分要緊。圖形變換的串接所以被認爲是依賴於順序的。
舉個順序依賴的例子,考慮兩個矩陣,S和R。S(2,0.5,1)對x進行2倍,對y進行0.5倍的縮放。Rz(π/6)以逆時針繞z軸(其指向從書頁面向外)轉π/6。這些矩陣能夠以兩種方式相乘,而產生徹底相反的結果。圖4.4展現了兩個結果。
圖4.4 這展現了矩陣相乘時的順序相關。在上面一行中,旋轉矩陣Rz(π/6)被應用,緊接着的是縮放矩陣S(s),其中s=(2, 0.5, 1)。其複合矩陣爲S(s)Rz(π/6)。在下面一行中,矩陣以相反的順序被應用,產生爲Rz(π/6)S(s)。二者的結果是明顯地不一樣。對於任意的矩陣M和N,整體上是MN≠NM的。
將一系列矩陣串接合成一個單一矩陣的一個顯而易見的緣由是效率。例如,想象一下你須要對一個有數千個頂點的對象進行縮放,旋轉,以及最後的平移。如今,全部的頂點不是和三個矩陣的每一個都相乘,而是三個矩陣串接結合成一個單獨的矩陣。這個單獨的矩陣被應用在頂點上。這個複合的矩陣C=TRS。注意到這裏的順序:縮放矩陣S將會首先應用在頂點上,所以出如今複合矩陣的右邊。這順序爲TRSp=(T(R(Sp)))。
值得注意的是矩陣的串接是順序相關的,但矩陣能夠按須要進行分組。例如,對於TRSp你但願一次計算出剛體運動的圖形變換TR。將這兩個矩陣分爲一組(TR)(Sp),而後用中間結果替換是合法的。所以,矩陣是相關的。
4.1.6 剛體圖形變換
當一我的拿一個固體的物體,例如從桌上拿一支鋼筆,而且將它移動到另外一個位置,例如她襯衫的口袋裏,僅僅是物體的朝向和位置發生變換,而物體的形狀整體上沒有受到影響。這種由平移和旋轉串接而組成的圖形變換,被稱爲剛體圖形變換,其特色爲保持物體的長度,角度和旋向性。
任何剛體矩陣X能夠被寫成平移矩陣T(t)和旋轉矩陣R的串接。所以X形如方程4.14中的矩陣:
X求逆矩陣的計算爲X-1=(T(t)R)-1=R-1T(t)-1=RTT(-t),所以,爲了計算逆矩陣,左上3×3矩陣R被轉置,而T的平移數值改變了符號。這兩個新的矩陣以相反的順序相乘在一塊兒獲得逆矩陣。計算X逆矩陣的另外一個方法是將R(R爲3×3的矩陣)和X認爲是以下的標記:
這裏,0是一個以0填充的3×1的列向量。產生逆矩陣的一些簡單的計算展現在方程4.16的表達式中:
4.1.7 法向圖形變換
一個單獨的矩陣能夠用於點,線,多邊形和其餘幾何體的一致變換。一樣的矩陣能夠變換沿着這些線或多邊形表面的切線向量。可是這些矩陣不能用於變換一個重要的圖形屬性,表面法線(以及頂點光照法線)。圖4.5展現了若是一樣的矩陣被使用將會發生什麼狀況。
圖4.5 在左邊的是原來的幾何體,從側面展現了一個多邊形和它的法線。中間的圖展現了通過沿x軸進行0.5倍的縮小,並且法線使用一樣的矩陣進行變化後圖片發生了什麼變化。右邊的圖展現了法線的正確變換。
不是乘以矩陣自己,合適的方法是使用矩陣的伴隨矩陣的轉置。伴隨矩陣的計算在A.3.1節中描述。伴隨矩陣老是被認爲是存在的。法線在變換之後不保證其爲單位長度,所以必須對其標準化。
對於法線變換的傳統方法是計算逆矩陣的轉置。這個方法一般是可行的。徹底求逆(full inverse)是沒必要要的,但偶爾不能建立。逆矩陣是鄰接矩陣除以原矩陣的行列式。若是這個行列式爲0,矩陣是奇異的,那麼他的逆矩陣就不存在。
即便是計算一個4×4矩陣的鄰接矩陣,其運算量也是很大的,並且一般是不須要的。由於法線是一個向量,平移是不會影響它的。此外,多數模型的變換是仿射的。它們不會改變傳入的齊次座標的w份量,也就是說它們不會進行投影。在這些(一般的)環境下,法線變換的計算僅須要計算左上3×3份量的鄰接矩陣。
一般甚至這個鄰接矩陣也不須要計算。咱們知道圖形變換矩陣由整個平移,旋轉,和總體縮放操做(沒有拉伸或壓縮)串接而成的。平移不影響法線。總體縮放因子簡單地改變法線的長度。剩下的是一系列旋轉,它們老是產生某種純粹的旋轉,僅此而已。一個旋轉矩陣的特性是它的轉置矩陣就是它的逆矩陣。逆矩陣的轉置能夠用於變換法線,而且兩次轉置(或者兩次求逆)能夠互相消去。將這些放在一塊兒,其結果是在這樣的環境下,原來的矩陣自己能夠直接用於變換法線。
最後,完整的重標準化不老是須要的。若是隻是平移和旋轉串接在一塊兒,當經過矩陣變換時,法線長度不會變化。若是總體縮放也被串接,那麼總體縮放因子(出自4.2.3節)能夠直接用於輸出法線標準化。例如,若是咱們知道一系列的縮放被使用使得對象變爲5.2倍大,那麼法線變換直接經過這個矩陣,其經過除以5.2實現標準化。或者,要建立一個產生標準化結果的法線變換矩陣的方法是,原來的矩陣左上3×3除以這個縮放因子。
注意到法線變換不是一個問題,在系統中,變換後表面法線源自三角形(例如,三角形的邊的叉積)。切線向量與法線在本質上是不一樣的,並且老是直接被原矩陣所變換。
4.1.8 矩陣求逆
不少的地方須要求逆矩陣,例如,在兩個座標系統中來回變換。基於可獲得的圖形變換信息,可使用如下三種計算逆矩陣的方法中的一種。
·若是矩陣是一個單獨的圖形變換或者一些列帶有給定參數的簡單變換,那麼矩陣能夠經過「參數取反」和矩陣的順序,容易地計算得出。例如,若是M=T(t)R(φ),那麼M-1=R(-φ)T(-t)。
·若是已知矩陣是正交的,那麼M-1=MT,也就是說轉置矩陣就是逆矩陣。任何順序的旋轉都是旋轉,而且所以是正交的。
·若是沒有已知任何特性,那麼鄰接矩陣方法(902頁的方程A.38),克拉默法則,LU分解,或者高斯消元能夠被用於計算逆矩陣(見A.3.1節)。克拉默法則和鄰接矩陣整體上是更好的,由於他們有較少的分支操做;在現代架構中避免「if」測試是好的。見4.1.7節中如何使用鄰接矩陣求逆去變換法線。
在優化時,能夠將計算逆矩陣的目的也考慮上。例如,若是逆矩陣將被用於變換向量時,一般僅矩陣左上3×3部分須要被求逆(見前面章節)。
4.2 特殊矩陣以及其操做
在這一節,一些與實時計算機圖形學息息相關的矩陣的變換和操做將被介紹和推導。首先咱們展現歐拉變換(以及它的參數的提取),一個描述朝向的直觀方法。而後咱們涉及從一個單獨矩陣返回一系列基礎的圖形變換。最後,一個讓實體繞任意軸旋轉的方法被推導出來。
4.2.1 歐拉變換
這個圖形變換是一個直觀的方法,去構建一個矩陣,以肯定你本身(也就是說攝像機)或者其餘實體在某個方向的朝向。它的名字來自偉大的瑞士數學家萊昂哈特·歐拉(1707-1783)。
圖4.6 以歐拉變換的術語描述,你轉動你的head, pitch和roll。默認的視圖方向被展現,朝z軸負向看並且head朝向沿着y軸。
某種默認的視覺方向必須首先被創建。一般它會沿z軸負向且head朝向沿y軸,就像圖4.6所示的那樣。歐拉變換是三個的矩陣的相乘,即圖中所示的旋轉。更確切地說,這個以E標記的轉換矩陣,以方程4.17給出:
E(h, p, r)=Rz(r)Rx(p)Ry(h) (4.17)
由於E是一個旋轉矩陣的串接。它無疑也是正交的。所以它的逆矩陣能夠表達爲E-1=ET=(RzRxRy)T=RyTRxTRzT,儘管固然是更容易使用的E的轉置矩陣直接。
歐拉角h,p和r表明順序和head,pitch和roll應該繞他們對應的軸轉過多少度。這變換是直觀的而且所以易於與外行人討論。例如,改變head角度使得觀察者搖晃他的頭說不,改變pitch使得他點頭,而roll使他的頭側傾。注意到的是這個圖形變換不只能夠給攝像機定向,也能夠用於其餘對象或實體。這些變換能夠用於世界空間的全局座標軸或者相對一個局部框架的參考。
當你使用歐拉變換,一種叫作萬向鎖的狀況可能出現。發生這種狀況是,旋轉使得物體失去一個自由度。例如,變換的順序是x、y、z。考慮一個繞y軸轉π/2的轉動,第二個旋轉運行。實施這樣的旋轉後局部座標的z軸將會與原來座標的x軸重合,如此的話最後繞z的旋轉成了冗餘的。
另外一個看到失去一個自由度的方法是設置p=π/2並檢查歐拉矩陣E(h, p, r)發生了什麼:
由於矩陣是依賴於一個角(r+h),咱們判定失去了一個自由度。
歐拉角通常按x、y、z的順序出如今模型系統中,然而繞局部座標的旋轉也能夠按照其餘順序的。例如,用於動畫的z、x、y和用於動畫和物理的y、x、z。全部都是合法的指定三個分離旋轉的方式。最後一個順序,y、x、z,對於某些應用場景是表現優秀的,由於只有當繞x軸轉過π弧度(轉一半)纔會引起萬向鎖。這就是說,「毛球定理」萬向鎖是不可避免的,沒有完美的順序能夠避免它。
雖然對於小角度的改變和觀察者定位十分有用,歐拉角有其餘很嚴重的限制。將兩個歐拉角組合起來是很困難的。例如,一個歐拉角與另外一個之間的插值不是簡單地對每一個角進行插值。事實上,兩個不一樣的歐拉角能夠得出相同的朝向,因此任何插值都不該該旋轉對象。這些是使用另外的一些朝向表達,例如後面討論的四元數,的緣由。
4.2.2 從歐拉變換中提取參數
在某些狀況,可以從正交矩陣中提取歐拉參數h,p和r是頗有用的。這個提取步驟如方程4.19所示:
串接這方程4.19產生的三個旋轉矩陣
從這能夠明顯地看到參數pitch由sinp=f21給出。一樣的,f01除以f11,以及類似的f20除以f22,推導出了接下來用於參數head和roll的提取公式:
所以,歐拉參數h(head),p(pitch),r(roll)使用函數atan2(y, x)(見第一章中的第7頁)從矩陣F中提取如公式4.22所示:
可是,這裏有一個特殊例子咱們須要處理。當cosp=0時它發生,由於這時f01=f11=0,而所以函數atan2不能使用。Cosp=0意味着sinp=±1,因此F能夠簡化爲
剩餘的參數能夠經過任意設置h=0,那麼sinr/cosr=tanr=f10/f00,經過r=atan2(f10, f00)獲得。
注意到arcsin(見B.1節)的定義域爲[-π/2, π/2],這意味着若是F若是由這個範圍之外的值p建立,那麼就不能提取原來的參數。h,p和r不是惟一的,多於一組的歐拉角參數能夠產生一樣的變換。更多歐拉角的轉換能夠在Shoemake的1994的論文中看到。以上描述的簡單的方法會產生數值不穩定的問題,這在損失必定速度後能夠避免。
例子:圖形變換的限制。想象你正拿着一個靠在螺栓上的扳手並繞x軸旋轉扳手以上緊螺栓。如今假設你的輸入設備(鼠標,數據手套,軌跡球等)給出扳手運動的正交變換。你遇到的問題是你並不肯意將變換應用在這個通常應該只繞x軸旋轉的扳手上。所以爲了將輸入的變換P,限制在繞x軸的旋轉,使用本節介紹的方法提取歐拉角h,p和r而且建立新的矩陣Rx(p)。這是一個很好用的能使扳手繞x軸旋轉的變換(若是P包含了這樣的運動)。
4.2.3 矩陣分解
到現時爲止,全部的工做都基於假設咱們知道所用的變換矩陣的變化的源頭和歷史。這並非常見的狀況:例如,除了與變換對象相關的已串接矩陣外沒有其餘東西。從串接矩陣中返回多個矩陣的任務叫作矩陣分解。
須要返回一系列變換的緣由有不少,包括:
·爲對象提取縮放因子。
·查找粒子系統所需的圖形變換。例如,VRML使用變換節點(見4.1.5節)而且不容許使用任意的4×4矩陣。
·檢測模型的變換是否只含有剛體圖形變換。
·當僅能夠得到對象的矩陣時,能夠在關鍵幀之間進行動畫插值。
·將剪切變換從旋轉矩陣中移除。
咱們已經展現了兩種分解,這些包括在一個剛體變換中劃分平移和旋轉矩陣(見4.1.6節),以及在一個正交矩陣中劃分出歐拉角(見4.2.2節)。
像咱們看到的,返回整個平移矩陣並非重要的,由於咱們只須要這個4×4矩陣的最後一行。咱們也能夠經過檢查矩陣的行列式是否爲負從而肯定反射是否發生。爲了區分旋轉,縮放和剪切須要更多工做。
幸運的是在網上能夠獲取到至關多的關於這方面的論文,以及代碼。Thomas和Goldman都提出了稍微不一樣的對應各類類型變換的方法。Shoemake對用於仿射矩陣的技術進行改進,他的算法獨立於參照物的框架並試圖分解矩陣以獲得剛體變換。
4.2.1 繞任意軸的旋轉
某些時候若是可以讓一個實體繞任意軸轉動必定角度是十分方便的。假設旋轉軸r是標準化的並且變換被建立爲繞r旋轉α弧度。
爲此,首先找到任意兩個單位長度的,與r都兩兩相互正交,也就是標準正交的軸。由這些造成一個空間的基。其方法就是將空間的基從標準空間的基轉變爲這個新的基,而後繞x軸(與r軸相對應)旋轉α個弧度,而且最後變換回標準空間基。這個過程在圖4.7展現。
圖4.7 繞任意軸r的選擇是經過找到由r,s和t組成的標準正交的基完成的。接下來將這個基與標準基對齊,使得r與x軸對齊。繞x軸的選擇在此執行,而後變換回去。
第一步是計算基的標準正交的軸。第一個軸是r,也就是旋轉所繞的那一個。咱們如今集中到尋找第二個軸s,而第三個軸t將會是第一個軸和第二個軸的叉乘,t=r×s。一個數值穩定的實現方法是找到r的最小份量(絕對值)並將它設置爲0。交換另外兩個份量,而後將這些數字的第一個取負。數學上能夠表示爲:
這保證了是正交(垂直)於r,而(r,s,t)是一個標準正交的基。咱們能夠以下將這三個向量做爲矩陣的行:
這個矩陣將r變換到x軸(ex),s變換到y軸和t變換到z軸。因此繞標準化向量r旋轉α個弧度最終的矩陣爲
X=MTRx(α)M (4.26)
簡而言之,這意味着咱們先變換已使得r成爲x軸(使用M),接着咱們繞x軸旋轉α個弧度(使用Rx(α)),接着咱們使用M的逆矩陣變換回來,在這個例子中是MT,由於M是正交的。
Goldman展現了另外一個繞任意軸r旋轉φ個弧度的方法。咱們在這簡單展現他的變換:
在4.3.2節,咱們展現瞭解決這種問題的另外一種方法,使用四元數。這也是這章中處理相關問題,例如從一個向量旋轉到另外一個向量的更高效的算法。
4.3 四元數
儘管四元數能夠追溯到1843年Sir William Rowan Hamilton關於複數的擴展,它直到1985年才被Shoemake引入到計算機圖形學科中。四元數是一個功能強大的工具,在構造圖形變換有着引人注目的特性,在某些方面,它超越了歐拉角與矩陣,尤爲是對於旋轉和定向。給出座標軸和角度的表明,變換或計算一個四元數是很直觀的。然而歐拉角在任意一個角度的變換都是困難的。四元數能夠用於穩定不變的朝向插值,歐拉角在這方面變現很差。
一個複數包含了實數和虛數。二者都由實數字表明,第二個實數乘以。類似地四元數有四個部分。前三個數值與旋轉的軸緊密相關,旋轉的角度影響全部四部分(關於這些的更多在4.3.2節)。每一個四元數由4個與不一樣部分關聯的實數表明。由於四元數有四個部分,咱們使用向量去表明它,但爲了區分它們,咱們給它們戴個帽子:
。咱們由一些四元數的數學背景開始,這些將用於四元數的構建和有用的變換。
4.3.1數學背景
咱們從四元素的定義開始。
定義 四元數q可被下列方法定義,這些方法都是等效的
變量qw被稱爲四元數的實數部分,虛數部分是qv,而i,j和k叫作虛單元
對於虛部,,咱們使用正常的向量運算,例如加減數乘,點乘,叉乘及更多其它。根據四元數的定義,兩個四元數和
相乘推導以下。注意到虛單元的乘法是不知足交換律的。
乘法:
如方程所示,咱們對兩個四元數的相乘使用了叉乘和點乘。由四無數的定義可得出其加法,共軛,標準化和單位四元數以下:
當被簡化(結果展現如上),其虛部被消除而只有實數部分保留。標準化有時可標記爲
。上述的結果是乘法逆元,標房爲
,這可被推導。方程式
必須成立(由於這是乘法逆元共有的)。咱們取模的定義推導出公式
這給出乘法逆元以下:
逆元的公式使用了標量乘法,這個運算源自公式4.29的乘法:,而
,這意味着標量乘法是可交換的:
如下一系列的定理能夠容易從定義中獲是:
乘法法則:
對於一些三維向量uq,例如||uq||=1,由於
這些且僅當uq.uq=1=||uq||2才成立。像在下一節所見,單位四元數是十分適合構建高效旋轉和朝向。但在此以前,一些對於單位四元數的額外運算將被引入。
對於單位四元數的對數及冪運算如方程4.38:
圖4.8 由單位四元數表明的旋轉變換的圖例。變換繞uq軸旋轉2φ個弧度。
4.3.2 四元數圖形變換
咱們如今研究四元數的一個子類,即其長度爲單位長,稱爲單位四元數。單位四元數的重要之處在於它們可表明任意三維旋轉,而且其表示是極爲簡潔和簡單。
如今咱們描述什麼使單位四元素對於旋轉和朝向如引有用。首先,將點或向量的四個座標(Px Py Pz Pw)T放入四元數的份量,並假定咱們有一個單位四元數
。那麼
旋轉(並由此點P)繞軸uq轉2φ弧度。注意到由於
是一個單位四元數,
。這個旋轉在圖4.8上展現出來,它顯然可被用於繞任意軸旋轉。
任何的非零實數乘法也表明相同的變換,這意味着
和-
表明相同的旋轉。這就是對uq取負軸,和實數部分,qw,建立一個像原來的四元數那樣旋轉和四元數。這也意味着由矩陣中提取四元數能夠返回
和-
。
給出兩個單位四元數,和
,串聯連結是前後將
和
應用到一個四元數,
(可認爲是點P),由公式4.41給出:
矩陣轉換
由於某些系統將矩陣乘法用硬件實現,並且事實上矩陣乘法相較公式4.40有更高的效率,咱們須要一個矩陣與四元數的相互轉換的方法。四元數,,能夠被轉換成矩陣Mq,像公式4.42所表達的:
一旦四元數被構建,就再也不須要計算三解函數了,所以在實踐中,這轉換過程是高效的。
相反的轉換,從正交矩陣,Mq,轉換到一個單位四元數,,泛及更多方面。這過程的關健是下面由方程4.43中的矩陣的不一樣之處:
這組公式暗示若是qw是已知,向量vq可似被算出,而因些可被導出,Mq的跡(見898頁)能夠被計算爲
這個結果對單位四元數產生如下的變換:
爲了在數值上能穩定,應避免除以一個小值數。所以,首先設由此可得
這意味着最大的m00,m11,m22以及u決定了qx,qy,qz和qw那個最大,若是qw是最大,那麼公式4.46被用於導出四元數。不然,咱們注意到下面:
在方程4.44用於計算剩餘的部分以後,以上之一的合適方程用於計算qx,qy和qz之間的最大值。幸運的是在這一章最後的進一步閱讀和資源中有這方面的代碼。
球面線性插值
球面線性插值是一個這樣的運算,給出兩個單位四元數,和
,以及參數t∈[0,1],計算之間的插值四元數。這對動畫對象頗有用。它在攝像機朝向的插值用處不大,由於攝像機的「上」向量會在插值中變傾斜,這一般是很差的效果。
可是,對於軟件實現,如下的形式,球形線性插值點,是更爲合適:
爲了計算φ這一方程所需的值,如下可用:,對於t∈[0,1],球面插值函數計算一系列(惟一的)插值四元數一塊兒組成了四維單位球上由
(t=0)到
(t=1)的最短弧。圓弧落在
、
以及原點所給出的平面與四維單位球體相交所造成的圓形上。這如圖4.9所示。計算的旋轉四元數繞固定軸似恆定速度旋轉。這樣的以常速運行,所以加速爲零的曲線,叫作測地曲線。
圖4.9 單位四元數用於表示單位圓上的點。Slerp函數用於四元數間的插值,而且插值路徑是球上的弧,注意到由到
的插值與由
到
再到
的插值不是同同樣,即便他們最後都到達同一朝向。
Slerp函數十分適合在兩個朝向間的插值而且它表現得很好(固定軸,常速)。在使用一些歐拉角進行插值時並不是如此。在實踐中,直接計算slerp是一個昂貴的運算,涉及了三角函數的調用。Li提供了更快的遞增方式去計算Slerps並用不犧牲精度。
當多於兩個朝向,記爲,可得,而咱們但願從
到
再到
,直到
進行插值,Slerp可直接使用。如今當咱們接近
,咱們會以
和
爲Slerp插值的參數。以後越過
,咱們會使用
和
做爲Slerp的參數。這會使朝向插值出現忽然間的急速變化,這可見於圖4.9。與之類似的是點被線性插值,見578頁圖13.2的右上部分。一些讀者可能想在讀完13章關於樣條曲線後重讀接下來的段落。
一個更好的插值方法是使用某種樣條曲線。咱們在和
之間引入四元數
和
。球面立方插可被定義一系列四元數,
,
,
和
中。出乎意料地,三個額外的四元數可以下被計算:
和
會用於四元數的球面插值,使用三次樣條平滑,如方程4.52:
由上可見,squad函數經過重複球面插值使用slerp構建(見13.1.1節中關於點的重複線性插值的信息)。插值會通過初始朝向,i∈[0,...,1],缺不穿過
——這是用於指示初始朝向的切線朝向。
從一個向量旋轉到另外一個
一般的操做是從一個方向s經過最短路徑轉到t。四元數數學極大地簡化了這一步驟,而且展現了四元數與這一表示方式的緊密關係。首先,規範化s和t ,而後計算單位旋轉軸,稱爲u,經過計算,下一步,
並有
,這2φ是s和t之間的夾角。四元數表示由s旋轉到t是
,實際上使用半角關係(見19頁)以及三角函數恆等式(公式B.9)可將
簡化爲
以這種方式直接生成四元數(相較於規範化s與t 的叉乘)避免了當s與指向幾乎相同的t叉乘時數值上的不穩定。穩定性問題一樣出如今s和t指向相反方向,由於出現了除以零。當檢測到這樣的特殊例子,任何垂直於s的轉動軸可用於旋轉至t。
有時咱們須要矩陣表示從s到t 的旋轉。在代數和三角函數簡化公式4.43後,旋轉矩陣變爲
在這個方程,咱們使用如下的中間計算:
就像可見的,全部平方根和三角函數因爲化簡而消失,所以這是一個高效的構建矩陣的方法
需特別注意到,當s與t 是平行或都幾乎平行,所以||s×t||≈0。若是φ≈0那麼咱們可似返回單元矩陣。然而,若是2φ≈π,那麼咱們可似繞任何軸旋轉π個弧度。這個軸能夠由s和其它任意不平行於s的向量的叉積而得(見4.24節)。Moller和Hughes使用戶主矩陣以不一樣的方式處理這種特殊的狀況。
例子:爲攝像機設置位置和朝向。假設默認的虛攝像機(或視點)的位置是(0 0 0)T而且默認的視覺方向v是沿z軸負向,也就是說是v=(0 0 -1)T。如今,目標是建立一個變換將攝像機移到新的位置p,看向新的方向w。由攝像機的定向開始,這能夠由從默認視圖方向轉到目標視圖方向實現。R(v,w)負責這些。定位是簡單地由平移到p實現,這產生告終果變換X=T(p)R(v,w)。在實踐中,在第一次旋轉以後其它的向量與向量間的旋轉極可能會將視圖向上方向旋轉到所須要的方向。
4.4頂點混合
設想一個數字人物的手臂動畫化被分爲兩部分,前臂和上臂,像圖4.10左邊那樣顯示。這個模型的動畫可以使用剛體變換(見4.1.6節)。但兩部分間的鏈接點卻不像真正的手肘。這是由於使用的是兩個分離的對像,並且所以鏈接點由兩個分離的對像的重合部分組成。顯然,使用一個獨立的對象更好。然而,靜態模型部分並不能使鏈接點靈活。
圖4.10 一個手臂由前臂和上臂組成,其動畫化使用左邊的兩個分離對象的剛體變換。手肘並未表現真實。對於右邊,頂點混合用於一個單獨的對象。最右邊旁邊的手臂展現了當一個簡單的皮膚直接鏈接兩部分覆蓋手肘將會發生什麼。最右邊手臂展現了當頂點混合被使用將會發生什麼,而且一些頂點被以不一樣的權重進行混合:(2/3, 1/3)意味着頂點的變換的權重是上臂2/3,前臂1/3。這圖也在最右邊展現了頂點混合的不足,這裏,在手肘內部的摺疊是可見的,更好的結果能夠由更多骨骼,以及更細的權值設定而得到。
頂點混合是這個問題的一個解決方案。這技術有許多其它名稱,例如蒙皮,包絡和骨骼子空間變形。雖然這所展現的算法的精確起源不爲人所清楚,但定義骨骼並使皮膚對變化做出反應是計算機動畫的舊概念。在它最簡單的形式,前臂及上臂像此前那樣,但在鏈接點,兩個部件經過彈性的「表皮」鏈接。所以,這個彈性部分將會有一組頂點由前臂矩陣變換,而另外一組由上臂矩陣變換。這個結果爲三角形,其頂點可能被不一樣的矩陣變換,與每一個三角形都使用單獨的矩陣造成鮮明的對比。見圖4.10。這種基本的技術叫作拼接。
在這步繼續深刻,一個單獨的頂點能夠被多個不一樣矩陣變換,幷包含告終果位置的加權混合。這由擁有骨骼的動畫對象實現,其每一個骨骼的變換會經過用戶自定義的權重影響每一各頂點。由於整個手臂可能都是「有彈性的」,也就是,全部的頂點能夠被一個以上的矩陣影響,整個網格一般稱爲皮膚(包裹着骨骼)。見圖4.11。不少商業建模系統擁有這同種骨骼建模的功能。雖然有這樣一個名稱,但骨骼並不是必定須要是剛硬的。例如,Mohr和Gleicher提出了關於增長額外的鏈接點以啓用例如肌肉膨脹的效果的想法。James和Twigg討論了動畫蒙皮使用能夠壓縮和拉伸的骨骼。
圖4.11 一個真實的頂點混合例子。左上圖片在一個延伸的位置上展現手臂的兩個骨骼。右上圖展現了網格,而且以顏色標記了每根骨骼所擁有的頂點。下面的圖:着色後的手臂網格,與前圖位置稍異。
這在數學上被表示爲公式4.56,其p是頂點本來位置,而u(t)是變換後頂點,其位置由時間參數t肯定。n塊骨骼影響着p的位置(即其世界座標)。矩陣Mi從原來的骨骼座標系統變換到世界座標系。典型的是骨骼有它在其座標系統原點的控制節點。例如,前臂骨骼會以手肘節點爲原點,以動畫旋轉矩陣繞着該節點移動手臂的這部分。Bi(t)矩陣是第i塊骨骼隨時間變化使對象動畫化的世界變換,而且一般是一些列矩陣的串聯,例如層次化中以前的骨骼變換以及局部動畫矩陣。Woodland深刻討論了一個維護和更新Bi(t)矩陣動畫功能的方法。最後,wi是骨骼i對定點p的權重。定點混合公式是
每塊骨骼都就自有的框架參考點變換頂點,而最終的位置是由一些列計算出來的點插值得出的。在蒙皮的一些討論中,矩陣Mi不是顯式展現的,而是被當作Bi(t)的一部分。咱們在這展現它是由於它是有用的矩陣,幾乎老是矩陣串接過程的一部分。
在實踐中,每幀動畫的每塊骨骼的矩陣Bi(t)和Mi-1串接一塊兒,並且每一個結果矩陣都是用於變換頂點的。頂點p被不一樣骨骼串接後的矩陣變換,而且使用權重wi混合到一塊兒——所以名爲頂點混合。權重爲非負數值以及其和爲1,所以頂點根據一些位置變換並在其中插值的狀況將會發生。一樣地,變換後的點u會位於一些列點Bi(t)Mi-1p(固定時刻t下由0到n-1的全部的i)。法向量一般也能夠由公式4.56變換。根據變換的使用(例如若是一塊骨骼被延伸或者壓縮一個至關大的數值),Bi(t)Mi-1的逆矩陣能夠由轉置矩陣代替,就像4.1.7節中討論的那樣。
頂點混合十分適合用於GPU。網格中的一系列頂點能夠至於靜態緩存中,一次性提交給GPU而後重複使用。在每一幀中只有骨骼矩陣發生變化,頂點着色器計算他們在已存儲的網格上產生的做用。在這個方法中,數據處理和與CPU交互的數據量是最少的,容許GPU高效地渲染網格。若是模型的整套骨骼能夠一塊兒使用的話是最容易的;不然模型就必須分割而且一些骨骼將會重複。
使用頂點着色器時,能夠指定[0,1]之外,或者總和不爲1的一組權重。可是,這樣使得場景只能使用其餘的混合算法,例如目標變形(見4.5節)正被使用。
原始的頂點混合的一個缺點是會發生不須要的摺疊、扭曲和自相交。見圖4.12。一個最佳的解決方法是使用Kavan以及其餘人所展現的對偶四元數。這個處理蒙皮的技術幫助保留原變換的剛性,故避免了肢體發生「糖果包裹紙」般的扭曲。計算量小於線性蒙皮混合的1.5倍,而且結果優秀,致使該技術的快速普及。感興趣的讀者能夠參考該論文,它也包括了一關於以前關於線性混合改進的簡述。
圖4.12 左邊的圖展現了使用線性混合時在鏈接點發生的問題。在右邊,使用對偶四元數的混合改進了其外觀。
4.5 變形
在展現動畫時,從一個三維模型變形到另外一個是十分有用的。一個模型的圖像在時刻t0顯示而咱們但願它在時刻t1變換到另外一個模型。對於t0到t1之間的全部時間,由某種差值得出一個連續的「混合」模型。圖4.13展現了一個變形的例子。
圖4.13 頂點變形。兩個位置和法線定義了每一個頂點。每一幀中,中間位置和法線被頂點着色器線性差值得出。
變形由兩個主要的問題構成,分別是頂點對應問題和插值問題。給出兩個任意的模型,它們有着不一樣拓撲結構、不一樣頂點和不一樣的網格鏈接,首先一般須要從設置這些頂點的對應關係開始。這是一個困難的問題,並且這方面已有不少的研究。感興趣的讀者能夠參考Alexa的綜述[16]。
然而,若是兩個模型間頂點的一對一對應,那麼插值能夠在逐頂點的基礎上實現。這就是,對於第一個模型的每一個頂點,在第二個模型中必須存在惟一一個對應的頂點,反之亦然。這使得插值成了簡單的任務。例如,線性插值能夠直接應用到頂點中(見13.1節中其餘插值的方法)。爲了計算時間在[t0,t1]之間的變形頂點,咱們首先計算s=(t-t0)/(t1-t0),而線性頂點混合爲
m=(1-s)p0+sp1 (4.57)
其中p0和p1 對應同一頂點在不一樣時刻t0和t1 。
一個有趣的變形的變體被稱做爲目標變形或者形狀混合[671],它使得用戶可以更爲直觀地控制。其基本的理念可由圖4.14解析。
圖4.14 給出兩個嘴巴的姿式,一組不一樣的向量被計算出來去控制內插插值,或甚至外推插值。在目標變形,不一樣頂點的向量被用於向中性的面部「增長」動做。隨不一樣的向量的位置權重,咱們得出了一個微笑的嘴巴,而負值的權重能夠給出相反的效果。
咱們從一箇中性的模型開始,在這個例子中是一張臉。咱們標記這個模型爲N。此外,咱們也有一組不一樣的面部表情。在例子中僅有一個微笑的表情。一般,咱們能夠容許標記爲Pi,i∈[1,...,k]的不一樣表情的k≥1。做爲前處理,「表情的差別」被計算爲:Di=Pi-N,也就是每一個表情模型中減去中性表情。
在這一點,咱們有中性模型,N,以及一組姿式差別,Di。一個變形後的模型M可使用一下公式獲得:
這是中性模型,而緊接着咱們按須要使用權重wi增長不一樣的姿式。對於圖4.14,設置w1=1給出了圖中間的精確的笑臉。使用 w1=0.5給出半笑的表情,等等。也可使用負向或者大於1的權重。
對於這個簡單的面部模型,咱們能夠以增長另外的擁有憂傷眉毛的臉。由於位移是可附加的,這個眉毛的位置能夠結合微笑嘴巴的姿式使用。目標變形是一個強大的技術爲動畫製做人提供更多的控制,由於模型的不一樣突出部能夠獨立與其餘部分而被操控。Lweis等人[770]介紹了骨骼(姿式)空間變形,它結合了頂點混合和目標變形。硬件支持的DirectX 10可使用流輸出和其餘改進的功能實如今單個模型上使用多個目標而且僅在GPU中計算效果[793]。
圖4.15展現了一個使用蒙皮和變形的真實例子。
圖4.15 瑞秋角色面部表情和動做由蒙皮和頂點變形控制,它在使用圖形硬件支持下能夠加速
4.6 投影
在渲染一個場景以前,全部在場景中相關的對象必須投影在某個平面上或者投影到某個簡單形體中。此後再執行裁剪和渲染(見2.3節)。
這章中迄今爲止所見的變換都留下第四個份量,w,不做改變。也就是說點和向量在變換後仍保留着他們的類型。一樣的是4×4矩陣的最底一行老是(0 0 0 1)。透視投影矩陣對這些屬性而言是個例外:底行包含向量和點的操縱數字,並且一般須要齊次化過程(也就是w一般不是1,所以須要除以w去得到非齊次點)。這節中先前處理的正交投影,是一種簡單的被廣泛應用的投影。它不會影響w份量。
在這一節中,假設視角是朝z軸的負向看,y軸朝上而x軸朝右。這是右手座標系。一些文章和軟件,例如DirectX,使用的是左手座標系,其視角是朝z軸正。二者都是一樣正確的,而且能達到一樣的效果。
4.6.1 正交投影
一個正交投影的特徵是在投影后平行線依然是平行線。下面所示的矩陣Po是一個簡單的正交投影矩陣,它留下點的x和y份量不變,而設置z份量爲0,也就是它正交地投影到z=0的平面上:
這個投影的效果展現在圖4.16。明顯的,Po是不可逆,由於它的行列式|Po|=0。簡而言之,變換從三維降到二維,並且沒有辦法從新得到所丟棄的那一維。使用這種正交投影成像存在一個問題,那就是它將z份量正值和負值的點都投影到一個投影平面上。它能將z值(或者x,y值)限制在某一個區間,造成所說的從n(近平面)到f(遠平面)。這是下一個變換的目的。
圖4.16 公式4.59生成的簡單正交投影的三個不一樣的視角。這投影能夠認爲視角是沿着z軸負向,這意味着投影簡單地略過座標z(或者設置爲0),但保留x和y座標。注意到z=0的兩邊都被投影到投影面上。
一個更爲廣泛的執行正交投影的矩陣以一個六個數組合的方式表述,(l,r,b,t,n,f),標記爲左、右、下、上、近、遠平面。這個矩陣本質上是軸對齊(AABB;定義見16.2節)地縮放和平移,由這些平面造成一個軸對齊的以原點爲中心的立方體。AABB的最小轉角是(l,b,n)而最大轉角是(r,t,f)。認識到n>f很重要,由於咱們是在空間是沿着z軸負向去看。咱們的常識是近的數值應該小於遠的。一樣是朝z軸負向看的OpenGL,在調用glOrtho生成正交投影矩陣時以小於遠值的近值做爲輸入參數,然後在內部將兩個參數取負。另外一種方法是認爲OpenGL的近值和遠值是沿視角方向(負向z軸)的(正的)距離,而非z視點座標值。
OpenGL的軸對齊立方體有最小轉角(-1,-1,-1)以及最大轉角(1,1,1);DirectX的範圍則是(-1,-1,0)到(1,1,1)。這個立方體叫作正規化可視空間而這個空間的座標叫作規範化設備座標。圖4.17展現了變換的過程。轉換到正規化可視空間的緣由是在這個狀態下裁剪更爲高效。
圖4.17 在正規化視圖空間中變換軸對齊。在左邊的盒子是第一個變換,使得它的中心位於原點。以後它像右邊所示的,縮小至正規化視圖空間。
在變換到正規化視圖空間後,將被渲染的幾何體的頂點會被這個立方體裁剪。不在立方體外的幾何體最終經過將剩餘的單位正方形映射到屏幕而被渲染。OpenGL中這個正交投影以下:
正如公式所示,Po可被寫成變換的串接,T(t),接着是縮放矩陣,S(s),其中s=(2/(r-l), 2/(t-b), 2/(f-n)),而t=(-(r+l)/2, -(t+b)/2, -(f+n)/2)。這個矩陣是可逆的,也就是說Po-1=T(t)S((r-l)/2, (t-b)/2, (f-n)/2)。
在計算機圖形學中,投影后一般使用左手座標系——也就是說,對於視口,x軸指向右,y軸指向上,而z軸指向裏。由於咱們定義軸對齊包圍盒(AABB)的方式是遠值小於近值,因此正交投影變換一般包含一個鏡像變換。要明白這個,所謂軸對齊包圍盒大小保持不變是規範化視圖空間的目標。因而,軸對齊包圍盒的座標是(-1, -1, -1)對應(l, b, n)而(1, 1, -1)對應(r, t, f)。公式4.60推導出:
這是一個鏡像矩陣。這個鏡像將右手座標系(朝z軸負向看)轉換爲左手的規範化的設備座標系。
DirectX將z深度映射到範圍[0, 1]而OpenGL則是[-1, 1]。這能夠在應用正交投影矩陣後經過應用簡單的縮放和平移矩陣而實現,這就是,
所以,DirectX使用的正交投影矩陣爲
這一般以轉置的形式出現,由於DirectX使用行主元去輸出矩陣。
4.6.2 透視投影
一個相較正交投影更爲有趣的投影是透視投影,它被應用於大多數的計算機圖形程序。此時,投影后平行線通常再也不平行,他們會在極遠處匯聚成一個點。透視投影更爲接近咱們對真實世界感知,簡而言之,遠處的物體一般更小。
首先,咱們展現一個啓發性的透視投影矩陣的推導,這個投影投影到z = -d的平面,d > 0。咱們從世界空間開始推導,簡化關於世界到視圖轉換的理解。這個推導以後就是更爲經常使用的矩陣使用,例如OpenGL。
圖4.18 用於導出透視投影矩陣的圖標。點p被投影到z = -d平面(d > 0),產出投影點q。投影由位處原點的透視攝像機產生。推導時使用的x份量的類似三角形如右圖所示。
假設攝像機(視點)被放置在原點,而咱們但願投影一個點,p,到z = -d的平面(d > 0)而產生一個新的點q(qx, qy, -d)。這個場景如圖4.18所描述。從這幅圖所示的類似三角形,如下關於q的x份量的推導可得:
q的另外一個份量的表達式爲qy=-dpy/pz(推導與qx類似),而且qz=-d。聯合上面的公式,咱們得出投影透視矩陣,Pp,以下:
這個矩陣是否產生正確的透視投影可簡單地經過公式4.66驗證:
最後一步是整個向量都除以w份量(例子中的-pz/d),使得w份量保持爲1。Z值的結果老是爲-d,由於咱們投影到一個平面。
直覺上容易理解爲什麼齊次座標容許投影。一幾何的解釋是齊次化的過程是將點(px,py,pz)投影到w=1的平面。
對於正交變換,也是一個透視變換,不是實際投影到一個平面上(這是不可逆的),而是將視圖平截頭體變換到前面所說的標準視圖空間。這裏的視圖平截頭體設定爲始於z = n而終於z = f,其中0 > n > f。在z=n的正方形有小角(l, b, n)而最大角在(r, t, n)。這展現在圖4.19中。
圖4.19 矩陣Pp將視圖平截頭體變換到單元立方體(也就是所謂的規範化可視空間)
參數(l, r, b, t, n, f)決定了攝像機的視圖平截頭體。視體的水平視野由平截頭體的左右平面(由l和r肯定)間的夾角決定。水平視野越大,攝像機看到的就越多。非對稱平截頭體經過r≠-l或t≠-b建立。非對稱平截頭體用於諸如立體感的觀察(見18.1.4節)和CAVEs[210]。
視體的視野是一個給出場景真實感受的重要因素。相比計算機屏幕,視點自己有一個物理實體上的視野,其關係爲:
Φ=2arctan(w/(2d)) (4.67)
其中φ是視野,w是對象垂直於視線的寬度,而d是對象的距離。例如,一個21英寸監視器是大約16英寸寬,而最小的推薦觀看距離(產生35度的實體視野)是25英寸。當距離爲12英寸,視野是67度;18英寸,則爲48度;30英寸,則爲30度。這個簡單的公式能夠用於將攝像機鏡頭轉換到視野,例如,一個標準的50mm鏡頭對於35mm攝像機(擁有36mm外框尺寸)給出Φ=2arctan(36/(2*50))=39.6度。
使用一個相比實體更窄的視野設置會下降透視的效果,就像觀察者在場景中被放大。設置一個更寬的視野會使得對象表現得出現扭曲(像使用廣角鏡),尤爲是在靠近屏幕的邊緣會增大旁邊對象的比例。可是,更寬的視野使得觀察者感受場景更爲廣大和震撼,並有提供用戶更多周遭信息的好處。
將平截頭體變換到單元立方體的透視變換矩陣由公式4.68給出:
在對點應用變換後,咱們獲得另外一個點q=(qx,qy,qz,qw)T。這個點的W份量,qw,既非零也不等於1。爲了獲得投影的點,p,咱們須要除以qw:p=(qx/qw,qy/qw,qz/qw,1)T。矩陣Pp老是實現z=f對應+1而z=n對應-1。透視投影被執行,裁剪和齊次化(除以w)會被執行以獲得規範化的設備座標。
爲了獲得OpenGL的透視變換,由於與正交投影相同的緣由首先乘以s(1,1,-1)。這能夠簡單地經過對公式4.68的第三列數值取負實現。在這鏡像變換被應用後,其遠值和近值會變成正值,其中0< n’< f’,就像它傳統展現給用戶那樣。然而,它依然表明沿着世界座標系的z軸負向,這個視圖的方向。爲了提供參照,這是OpenGL的公式:17
一些APIs(例如DirectX)將近平面對應爲z = 0(而非z = -1)而遠平面z = 1。還有,DirectX使用左手座標系定義它的投影矩陣。這意味着DirectX沿z軸正向看,而且近值和遠值都爲正數。如下是DirectX的公式:
DirectX在它的文檔中使用行主元的形式,因此這個矩陣一般以轉置的形式出現。
使用透視變換的一個效果是深度計算值並不是與輸入的pz值成線性變化。例如,若是n’= 10和f’= 110(使用OpenGL的術語),當pz是60個單位沿z軸負向(也就是中間點)規範化設備座標深度值爲0.833,而非0。圖4.20展現了不一樣的近平面到原點距離的影響。近遠平面的放置影響着Z緩存的精度。這個影響將在18.1.2節中深刻討論。
圖4.20 不一樣近平面與原點距離的影響。距離n’- f’恆定保持爲100。當近平面靠近原點,遠平面附近的點使用一個較小的規範化設備座標深度空間。這個影響使得當點距離近平面遠時z緩存下降精度
進一步閱讀和資源
一本以較不痛苦的方式創建一我的對矩陣的直覺的書是Farin和Hansford的《The Geometry Toolbox》[333]。另外一本有用的著做是Lengyel的《Mathematics for 3D Game Programming and Computer Graphics》[761]。對於不一樣的視角,不少計算機圖形學文章,例如Hearn和Baker[516],Shirley[1172],Watt和Watt[1330],和Foley等人的兩本書[348,349],都包括了矩陣的基本知識。《Graphics Gems》系列[36,405,522,667,982]展現各類變換相關的算法並在線提供相應的代碼。Golub和Van Loan的《Matrix Computations》[419]是綜合研究矩陣技術的一個起點。見http://www.realtimerendering.com中用於不一樣變換的代碼,包括四元數。更多的關於骨骼子空間的變形、頂點混合和形體插值能夠閱讀Lewis等人的SIGGRAPH論文[770]。
Hart等人[507]和Hanson[498]提供了一個可視化的四元數。Pletinckx[1019]和Schlag[1126]展現在一系列的四元數見進行平滑插值的不一樣方法。Vlachos和Isidoro[1305]堆到了用於四元數C2插值的公式。與四元數插值問題相關的是沿曲線計算一個一致的座標系統。這爲Dougan[276]嘗試。
Alexa[16]和Lazarus和Verroust[743]展現了關於不一樣變形技術的綜述。