首先要說明的是,本文的標題事實上來自於知乎上的一個同名問題:爲何directX裏表示三維座標要建一個4*4的矩陣? - 編程 。所以,正如Milo Yip大神所說的這個標題事實上是存在問題的:矩陣是用於表示變換而不是座標的。再瞭解了矩陣的做用以後,咱們就要繼續思考爲何變換要使用一個4×4的矩陣而不是3×3的矩陣呢?是否是畫蛇添足呢?下面咱們就來聊聊這個話題。編程
咱們應該怎麼平移一個三維空間中的點呢?答案很簡單,咱們只須要對這個點的座標中的每一個份量(x,y,z)和對應軸上的平移距離相加便可。數組
例如,點p1(x1,y1,z1)在X軸Y軸以及Z軸上分別平移Δx,Δy,Δz到新的點p2(x2,y2,z2),那麼咱們只需在座標對應的份量上加上這些增量就能夠肯定點p2的座標了。函數
> x2 = x1 + Δx > > y2 = y1 + Δy > > z2 = z1 + Δz
很簡單是嗎?那麼接下來再讓咱們來看一看另外一種變換:旋轉。spa
旋轉相比較平移來講,會略顯複雜一些。由於咱們須要指明如下幾個方面來描述一個旋轉:code
旋轉軸blog
旋轉方向遊戲
旋轉角度圖片
在這裏,咱們假設點p須要繞Z軸順時針旋轉β度。ip
如這個很難看的圖所示,咱們的點P1(x1,y1,z1)以Z軸位軸順時針旋轉β度以後來到了點P2(x2,y2,z2)。接下來,讓咱們假設原點到P1的距離位L,且P1和Y軸之間的夾角位α,那麼根據三角函數公式咱們就能夠計算出P1點的具體座標了:get
> x1 = L·sinα > > y1 = L·cosα
因爲是繞Z軸旋轉,所以z座標不變,所以此處不考慮。
一樣根據三角函數公式,咱們能夠繼續計算出P2的具體座標:
> x2 = L·sin(α + β) > > y2 = L·cos(α + β)
再讓咱們回憶一下中學時代的幾何數學的內容,對青春的回憶又把咱們帶回了課堂上老師聲嘶力竭向咱們傳授的內容——兩角和與差:
> cos(α+β)=cosα·cosβ-sinα·sinβ > cos(α-β)=cosα·cosβ+sinα·sinβ > sin(α+β)=sinα·cosβ+cosα·sinβ > sin(α-β)=sinα·cosβ-cosα·sinβ
回憶起老師傳授給咱們的知識以後,接下來結合P1的座標表示形式咱們就能夠把P2的座標換一個表示形式了。
> x2 = L·(sinα·cosβ+cosα·sinβ) = cosβ·x1 + sinβ·y1 > > y2 = L·(cosα·cosβ-sinα·sinβ) = cosβ·y1 - sinβ·x1 > > z2 = z1
所以,在已知P1點座標以及旋轉角度β的狀況下,咱們就能夠根據以上公式分別求出P2點座標的各個份量。若是再結合上一小節中平移一個點的公式來看,咱們能夠發現彷佛並不須要矩陣,而僅僅經過兩組表達式就能實現座標的變換。可是……
固然,從理論上講咱們的確能夠只經過數學公式就能實現變換,但實際的狀況倒是在變換十分複雜時,直接使用數學表達式來進行運算也是至關繁複的。所以,在現實中經常使用矩陣(由m × n個標量組成的長方形數組)來表示諸如平移、旋轉以及縮放等線性變換。而另外一個更有趣的事實是,當兩個變換矩陣A和B的積爲P=AB時,則變換矩陣P至關於A和B所表明的變換。舉一個例子,若A爲旋轉矩陣,B爲平移矩陣,則矩陣P就可以實現旋轉和平移變換。不過須要注意的是,矩陣乘法不符合交換律,所以AB和BA並不相等。
說了這麼多,咱們彷佛仍是沒有回答爲何三維空間須要一個4×4矩陣來實現變換呢?下面咱們就帶着這個問題,分別看看3×3矩陣和4×4矩陣的使用吧。
首先,咱們先來看一個矩陣乘以一個三維矢量的算式:
能夠看到該矩陣爲一個3×3的矩陣,矩陣的右側是點P1的座標,而矩陣的左側則是點P2的座標。根據這個表達式,咱們能夠求出x二、y二、z2的值:
> x2 = a·x1 + b·y1 + c·z1 > > y2 = d·x1 + e·y1 + f·z1 > > z2 = g·x1 + h·y1 + i·z1
爲了將矩陣等式和以前小節的數學表達式聯繫起來,下面咱們就將旋轉表達式和該矩陣等式作一個對比。
> x2 = a·x1 + b·y1 + c·z1 > x2 = cosβ·x1 + sinβ·y1 > > y2 = d·x1 + e·y1 + f·z1 > y2 = cosβ·y1 - sinβ·x1 > > z2 = g·x1 + h·y1 + i·z1 > z2 = z1
經過對比 x2,咱們能夠發現 $$a=cosβ,b=sinβ,c=0;$$
對比 y2,也能夠發現 $$d=-sinβ,e=cosβ,f=0;$$
最後對比 z2,能夠肯定 $$g=0,h=0,i=1;$$
將這個結果帶入到以前的矩陣中,咱們的等式就能夠變成下面這個樣子:
也就是說,經過這個3×3的變換矩陣,咱們就已經實現了三維空間的旋轉變換。那麼爲何還須要使用4×4矩陣呢?
咱們已經經過一個3×3矩陣搞定了旋轉變換,顯然若是這個3×3矩陣真的是完美的解決變換的方案的話,那麼它顯然也必需要適合於其餘的變換,例如平移。可是它到底可否知足平移的需求呢?下面咱們仍是經過對比矩陣等式和數學表達式的方式,來尋找答案。
> x2 = a·x1 + b·y1 + c·z1 > x2 = x1 + Δx > > y2 = d·x1 + e·y1 + f·z1 > y2 = y1 + Δy > > z2 = g·x1 + h·y1 + i·z1 > z2 = z1 + Δz
經過對比,咱們發現平移和旋轉之間頗有趣的一個區別,那就是平移的表達式中帶有常量Δx,而不管是旋轉的表達式仍是矩陣等式中都不存在這樣一個常量可以與之對應。那麼問題就來,咱們沒有辦法使用3×3的矩陣來表示平移。這個問題該如何解決呢?答案其實很簡單,那就是使用4×4矩陣來實現。可是隨之而來的一個問題就是如何讓一個三維座標和一個4×4的矩陣相乘呢?
爲了解決三維矢量和4×4矩陣相乘的問題,咱們機智的爲三維矢量添加了第四個份量,這樣以前的三維矢量(x,y,z)就變成了四維的(x,y,z,w),這樣由4個份量組成的矢量便被稱爲齊次座標。須要說明的是,齊次座標(x,y,z,w)等價於三維座標(x/w,y/w,z/w),所以只要w份量的值是1,那麼這個齊次座標就能夠被看成三維座標來使用,並且所表示的座標就是以x,y,z這3個值爲座標值的點。
所以,爲了和4×4矩陣相乘,咱們的P1點座標就變成了(x1,y1,z1,1)。而矩陣等式也變成了下面這個樣子:
咱們再將這個新的矩陣等式和平移的數學表達式作一番對比:
> x2 = a·x1 + b·y1 + c·z1 + d > x2 = x1 + Δx > > y2 = e·x1 + f·y1 + g·z1 + h > y2 = y1 + Δy > > z2 = i·x1 + j·y1 + k·z1 + l > z2 = z1 + Δz > > 1 = m·x1 + n·y1 + o·z1 + p
經過對比x2,咱們能夠發現 $$a=1,b=0,c=0,d=Δx;$$
對比y2,也能夠發現 $$e=0,f=1,g=0,h=Δy;$$
再對比z2,能夠肯定 $$i=0,j=0,k=1,l=Δz;$$
最後還能夠根據表達式求出 $$m=0,n=0,o=0,p=1;$$
這樣,咱們就求出了咱們的4×4的平移矩陣:
寫到這裏,不知各位是否還記得以前在介紹矩陣乘法的時候我有提到過兩個變換矩陣A和B的積P=AB,至關於A和B所表明的變換。事實上在遊戲編程中,經常須要把一連串的變換預先經過計算成爲單一矩陣,因此就不能即存在3×3的矩陣又存在4×4的矩陣。而將3×3矩陣拓展成4×4矩陣仍是相對更加容易的。這樣,就經過一個4×4矩陣整合了平移矩陣、旋轉矩陣。