1. 程式人生 > >第4章 學習Shader所需的數學基礎(中)(矩陣)

第4章 學習Shader所需的數學基礎(中)(矩陣)

4.4 矩陣

不幸的是,沒有人能告訴你母體( matrix)究竟是什麼。你需要自己去發現它。
一一電影《黑客帝國》(英文名: The Matrix )
矩陣,英文名是matrix 。如果你用翻譯軟體去查matrix 這個單詞的翻譯,就會發現它還有一個意思就是母體。事實上,很多人都不知道,那部具有跨時代意義的電影《黑客帝國》的英文名就是《The Matrix ))。在電影《黑客帝國》中,母體是一個龐大的虛擬系統,它看似虛無續紗,但又連線萬物。這一點和矩陣有異曲同工之妙。
沒有人敢否認矩陣在三維數學中的重要性,事實上矩陣在整個線性代數的世界中都扮演了舉足輕重的角色。在三維數學中,我們通常會使用矩陣來進行變換。一個矩陣可以把一個向量從一個座標空間轉換到另一個座標空間。在第2 章渲染流水線中,我們就看到了很多座標變換,例如在頂點著色器中我們需要把頂點座標從模型空間變換到齊次裁剪座標系中。而在這一章中,我們先來認識一下矩陣這個概念。
那麼,現在我們就來看一下,這些放在一個小括號裡的數字怎麼就這麼重要呢?為什麼數學家們都喜歡用這個小東西來搞出這麼多名堂呢?

4.4.1 矩陣的定義

相信很多讀者都見過矩陣的真容,例如像下面這個樣子:

從它的外觀上來看,就是一個長方形的網格,每個格子裡放了一個數字。的確,矩陣就是這麼簡單:它是由m × n 個標量組成的長方形陣列。在上面的式子中,我們是用方括號來圍住矩陣中的數字,而一些其他的資料可能會使用圓括號或花括號來表示,這都是等價的。
既然是網格結構,就意味著矩陣有行( row ) 列( column)之分。例如上面的例子就是一個3 × 4的矩陣,它有三行四列。據此,我們可以給出矩陣的一般表示式。以3 × 3 的矩陣為例,它可以寫成:

mij 表明了這個元素在矩陣M 的第i 行、第j 列。
這樣看起來矩陣也沒什麼神祕的嘛。但是,越簡單的東西往往越厲害,這也是數學的魅力所在。

4.4.2 和向量聯絡起來

前面說到,向量其實就是一個數組,而矩陣也是一個數組。既然都是陣列,那就是一家人了!
我們很容易想到,我們可以用矩陣來表示向量。實際上,向量可以看成是nx 1 的列矩陣( column matrix ) 或1x n 的行矩陣(row matrix ),其中n 對應了向量的維度。例如,向量v=(3, 8,6)可以寫成行矩陣[3 8 6]
或列矩陣(豎著寫);
為什麼我們要把向量和矩陣聯絡在一起呢?這是為了可以讓向量像一個矩陣一樣一起參與矩陣運算。這在空間變換中將非常有用。
到現在,使用行矩陣還是列矩陣來表示向量看起來是沒什麼分別的。的確,我們可以根據自己的喜好來選擇表示方法,但是, 如果要和矩陣一起參與乘法運算時,這種選擇會影響我們的書寫順序和結果。這正是我們下面要講到的。

4.4.3 矩陣運算

矩陣這個傢伙看起來比向量要龐大很多,那麼它的運算是不是很複雜呢?答案是肯定的。但是,幸運的是在寫Shader 的過程中,我們只需要和很簡單的一部分運算打交道。
1. 矩陣和標量的乘法
和向量類似,矩陣也可以和標量相乘,它的結果仍然是一個相同維度的矩陣。它們之間的乘法非常簡單,就是矩陣的每個元素和該標量相乘。以3 ×3 的矩陣為例,其公式如下:

2. 矩陣和矩陣的乘法
兩個矩陣的乘法也很簡單,它們的結果會是一個新的矩陣,並且這個矩陣的維度和兩個原矩陣的維度都有關係。
一個r × n 的矩陣A 和一個n × c 的矩陣B 相乘,它們的結果AB 將會是一個r × c 大小的矩陣。
請讀者注意它們的行列關係,第一個矩陣的列數必須和第二個矩陣的行數相同,它們相乘得到的矩陣的行數是第一個矩陣的行數,而列數是第二個矩陣的列數。例如,如果矩陣A 的維度是4 × 3,矩陣B 的維度是3 × 6,那麼AB 的維度就是4 × 6。
如果兩個矩陣的行列不滿足上面的規定怎麼辦?那麼很抱歉,這兩個矩陣就不能相乘, 因為它們之間的乘法是沒有被定義的。那麼為什麼會有上面的規定呢?等我們理解了矩陣乘法的操作過程自然就會明白。
我們先給出看起來很複雜難懂( 當給出直觀的表式後讀者會發現其實它沒那麼難懂)的數學表示式: 設有r × n 的矩陣A 和一個nxc 的矩陣B,它們相乘會得到一個r× c 的矩陣C=AB 。那麼, C中的每一個元素Cij等於A 的第i 行所對應的向量和B 的第 j 列所對應的向量進行向量點乘的結果,即

看起來很複雜對嗎?但是,我們可以用一個更簡單的方式來解釋:對於每個元素cij,我們找到A 中的第i 行和B 中的第j 列,然後把它們的對應元素相乘後再加起來,這個和就是Cij。
一種更直觀的方式如圖4.30 所示。假設A 的大小是4 x 2, B 的大小是2x4,那麼如果要計算C 的元素C23 的話,先找到對應的行矩陣和列矩陣,即A 中的第2 行和B 中的第3 列,把它們進行向量點積後就可以得到結果值。因此, c23=a21*b13+a22*b23.

在Shader 的計算中,我們更多的是使用4 × 4 矩陣來運算的。
矩陣乘法滿足一些性質。
性質一: 矩陣乘法並不滿足交換律。
也就是說,通常情況下:
AB≠BA
性質二: 矩陣乘法滿足結合律。

也就是說,
(AB)C=A(BC)
矩陣乘法的結合律可以擴充套件到更多矩陣的相乘。例如,
ABCDE=((A(BC))D)E=(AB)(CD)E
讀者可根據矩陣乘法的定義很輕鬆地驗證上述結論。

4.4.4 特殊的矩陣

有一些特殊的矩陣型別在Shader 中經常見到。這些特殊的矩陣往往具有一些重要的性質。
1. 方塊矩陣
方塊矩陣( square matrix )
,簡稱方陣,是指那些行和列數目相等的矩陣。在三維渲染裡,最常使用的就是3 × 3 和4 × 4 的方陣。
方陣之所以值得單獨拿出來講,是因為矩陣的一些運算和性質是隻有方陣才具有的。例如,對角元素( diagonal elements )。方陣的對角元素指的是行號和列號相等的元素,例如m11 、m22 、m33 等。如果把方陣看成一個正方形的話,這些元素排列在正方形的對角線上,這也是它們名字的由來。如果一個矩陣除了對角元素外的所有元素都為0 , 那麼這個矩陣就叫做對角矩陣( diagonal
matrix )
. 例如,下面就是一個4 × 4 的對角矩陣:

2. 單位矩陣
一個特殊的對角矩陣是單位矩陣( identity matrix ),用In來表示。一個3x3的單位矩陣如下:

為什麼要為這種矩陣單獨起一個名字呢?這是因為,任何矩陣和它相乘的結果還是原來的矩陣。也就是說: MI=IM=M
這就跟標量中的數字1一樣!
3. 轉置矩陣
轉置矩陣( transposed matrix )
實際是對原矩陣的一種運算,即轉置運算。給定一個r × c 的矩陣M,它的轉置可以表示成MT,這是一個cxr 的矩陣。轉置矩陣的計算非常簡單,我們只需要把原矩陣翻轉一下即可。也就是說,原矩陣的第i 行變成了第i 列,而第j列變成了第j 行。數學公式是:

對於行矩陣和列矩陣來說,我們可以使用轉置操作來轉換行列矩陣:

轉置矩陣也有一些常用的性質。

4. 逆矩陣
逆矩陣(inverse matrix )
大概是本書講到的關於矩陣最複雜的一種操作了。不是所有的矩陣都有逆矩陣,第一個前提就是,該矩陣必須是一個方陣。給定一個方陣M, 它的逆矩陣用M-1 來表示。逆矩陣最重要的性質就是, 如果我們把M 和M-1 相乘,那麼它們的結果將會是一個單位矩陣。也就是說,

前面說了,並非所有的方陣都有對應的逆矩陣。一個明顯的例子就是一個所有元素都為0 的
矩陣, 很顯然,任何矩陣和它相乘都會得到一個零矩陣,即所有的元素仍然都是0 。如果一個矩
陣有對應的逆矩陣,我們就說這個矩陣是可逆的( inver“hie ) 或者說是非奇異的( nonsingular) ;
相反的,如果一個矩陣沒有對應的逆矩陣,我們就說它是不可逆的( noninver位hie ) 或者說是奇
異的(singular ) 。
那麼如何判斷一個矩陣是否是可逆的呢?簡單來說, 如果一個矩陣的行列式(determinant)不為0,那麼它就是可逆的。關於矩陣的行列式是什麼以及如何求解一個矩陣的逆矩陣, 可以參見本章的擴充套件閱讀部分。由於這部分內容涉及較多計算和其他定義,本書不再贅述。在寫Shader的過程中, 這些矩陣通常可以通過呼叫第三方庫(如C++數學庫Eigen)來直接求得,不需要開發者手動計算。在Unity 中,重要變換矩陣的逆矩陣Unity 也提供了相應的變數供我們使用。關於這些Unity 內建的矩陣, 讀者可以在本章的
3.8 節找到更詳細的解釋。


逆矩陣是具有幾何意義的。我們知道一個矩陣可以表示一個變換(詳見4.5 節〉,而逆矩陣允許我們還原這個變換,或者說是計算這個變換的反向變換。因此,如果我們使用變換矩陣M對矢量v 進行了一改變換,然後再使用它的逆矩陣M-1 進行另一次變換,那麼我們會得到原來的向量。 這個性質可以使用矩陣乘法的結合律很容易地進行證明:

5. 正交矩陣
另一個特殊的方陣是正交矩陣(orthogonal matrix )。正交是矩陣的一種屬性。如果一個方陣M 和它的轉置矩陣的乘積是單位矩陣的話,我們就說這個矩陣是正交的( orthogonal )。反過來也是成立的。也就是說,矩陣M 是正交的等價於:

這個式子非常有用,因為在三維變換中我們經常會需要使用逆矩陣來求解反向的變換。而逆矩陣的求解往往計算量很大,但轉置矩陣卻非常容易求解: 我們只需要把矩陣翻轉一下就可以了。
那麼,我們如何提前判斷一個矩陣是否是正交矩陣呢?讀者可能會說, 判斷MMT=I 是否成立就可以了嘛!但是,求解這樣一個表示式無疑是需要一定計算量的,這些計算量可能和直接求解逆矩陣無異。而且,如果我們判斷出來這不是一個正交矩陣,那麼這些花在驗證是否是正交矩陣上的計算就浪費了。因此,我們更想不需要計算,而僅僅根據一個矩陣的構造過程來判斷這個矩陣是否是正交矩陣。為此, 我們需要來了解正交矩陣的幾何意義。
我們來看一下對於3 × 3 的正交矩陣有什麼特點。根據正交矩陣的定義,我們有:

這樣,我們就有了9 個等式:

我們可以得到以下結論:
  •  矩陣的每一行,即c1、c2和c3 是單位向量,因為只有這樣它們與自己的點積才能是1; 
  •  矩陣的每一行,即c1、c2 和c3 之間互相垂直,因為只有這樣它們之間的點積才能是0 。
  • 上述兩條結論對矩陣的每一列同樣適用,因為如果M是正交矩陣的話, MT 也會是正交矩陣。
也就是說,如果一個矩陣滿足上面的條件,那麼它就是一個正交矩陣。讀者可以注意到, 一組標準正交基(定義詳見4.2.2 節〉可以精確地滿足上述條件。在4.6.2 節中,我們會使用座標空間的基向量來構建用於空間變換的矩陣。因此,如果這些基向量是一組標準正交基的話(例如只存在旋轉變換),那麼我們就可以直接使用轉置矩陣來求得該變換的逆變換。
讀者: 我被標準正交、正交這些概念搞混了,可以再說明一下是什麼意思嗎?
我們:讀者應該已經知道, 一個座標空間需要指定一組基向量,也就是我們理解的座標軸。
如果這些基向量之間是互相垂直的,那麼我們就把它們稱為是一組正交基( orthogonal basis ) .但是,它們的長度並不要求一定是1 。如果它們的長度的確是1 的話,我們就說它們是一組標準正交基( orthonormal basis )。因此,一個正交矩陣的行和列之間分別構成了一組標準正交基。但是, 如果我們使用一組正交基來構建一個矩陣的話,這個矩陣可能就不是一個正交矩陣,因為這些基向量的長度可能不為1 ,也就是說它們不是標準正交基。

4.4.5 行矩陣還是列矩陣

我們己經瞭解了足夠多的數學概念,但在學習矩陣的幾何意義之前,我們有必要說明一下行矩陣和列矩陣的問題。
在前面的章節中我們講到,可以把一個向量轉換成一個行矩陣或是列矩陣。它們本身是沒有區別的,但是,當我們需要把它和另一個矩陣相乘時,就會出現一些差異。


讀者認真對比就會發現,結果矩陣除了行列矩陣的區別外,裡面的元素也是不一樣的。這就意味著, 在和矩陣相乘時選擇行矩陣還是列矩陣來表示向量是非常重要的,因為這決定了矩陣乘法的書寫次序和結果值。
在Unity 中,常規做法是把向量放在矩陣的右側, 即把向量轉換成列矩陣來進行運算。因此,在本書後面的內容中, 如無特殊情況, 我們都將使用列矩陣。這意味著, 我們的矩陣乘法通常都是右乘, 例如:

如果你還是不能明白上面的含義,可以參見練習題3 。 (給定一個向量v, 分別把它當成行矩陣和列矩陣與矩陣M相乘,得到的結果是不一致的;為了得到一致的結果,我們可以對矩陣進行轉置,Mv = v乘以M的轉置)

4.4.6 練習題



4.5 矩陣的幾何意義:變換

關於矩陣,很多困擾初學者的問題都是類似的:
  •  點和向量都可以在影象中畫出來,那麼矩陣可以嗎?
  •  我聽說矩陣和線性變換、仿射變換有關,這些變換到底是什麼意思呢? . 我總是聽到齊次座標這個名詞,它是什麼意思呢?
  •  變換和矩陣的關係又是什麼呢?或者說,給定一個變換,我如何得到它對應的矩陣呢?
在學習完本節後,希望讀者們能夠回答出這些問題。
對於第一個問題,在三維渲染中矩陣可以視覺化嗎? 幸運的是,答案是肯定的,這個視覺化的結果就是變換。因此,如果讀者在後面的內容中看到了一個矩陣,那麼你可以認為自己看到的就是一個變換(當然,線上性代數中矩陣的用處不僅是用於變換,但本書的討論範圍僅在於此)。
在遊戲的世界中,這些變換一般包含了旋轉、縮放和平移。遊戲開發人員希望給定一個點或向量,再給定一個變換〈例如把點平移到另一個位置,把向量的方向旋轉30度等〉,就可以通過某個數學運算來求得新的點和向量。聰明的先人們發現,可以使用矩陣來完美地解決這個問題。那麼問題就變成了,我們如何使用矩陣來表示這些變換?

4.5.1 什麼是變換

變換( transform ), 指的是我們把一些資料,如點、方向向量甚至是顏色等,通過某種方式進行轉換的過程。在計算機圖形學領域,變換非常重要。儘管通過變換我們能夠進行的操作是有限的,但這些操作已經足夠奠定變換在圖形學領域舉足輕重的地位了。
我們先來看一個非常常見的變換型別一一線性變換(linear transform ) . 線性變換指的是那些可以保留向量加和標量乘的變換。用數學公式來表示這兩個條件就是:

上面的式子看起來很抽象。縮放( scale ) 就是一種線性變換。例如, f(x)=2x,可以表示一個大小為2 的統一縮放,即經過變換後向量x 的模將被放大兩倍。可以發現, f(x)=2x 是滿足上面的兩個條件的。同樣, 旋轉( rotation ) 也是一種線性變換。對於線性變換來說,如果我們要對一個三維的向量進行變換,那麼僅僅使用3 × 3 的矩陣就可以表示所有的線性變換。
線性變換除了包括旋轉和縮放外,還包括錯切( shear ) 、映象( mirroring,也被稱為reflection ) 、正交投影( orthographic projection ) 等,但本書著重講述旋轉和縮放變換。
但是,僅有線性變換是不夠的。我們來考慮平移變換,例如f(x)=x+(1 ,2,3) 。這個變換就不是一個線性變換,它滿足標量乘法,但不滿足向量加法。如果我們令x=(1, 1, 1 ),那麼:

可見,兩個運算得到的結果是不一樣的。因此,我們不能用一個3 × 3 的矩陣來表示一個平移變換。這是我們不希望看到的,畢竟平移變換是非常常見的一種變換。
這樣,就有了仿射變換(affine transform )。仿射變換就是合併線性變換和平移變換的變換型別。仿射變換可以使用一個4x4 的矩陣來表示,為此,我們需要把向量擴充套件到四維空間下,這就是齊次座標空間( homogeneous space )
表4.1 給出了圖形學中常見變換矩陣的名稱和它們的特性。

在下面的內容中,我們將學習其中一些基本的變換型別: 旋轉,縮放和平移。對於正交投影和透視投影, 我們將在4.6.7 節中給出它們的表示方法。而對於其他變換型別, 本書不再具體討論,讀者可以在本章的擴充套件閱讀中找到更多內容。

4.5.2 齊次座標

我們知道,由於3 × 3 矩陣不能表示平移操作,我們就把其擴充套件到了4 × 4 的矩陣(是的,只要多一個維度就可以實現對平移的表示〉。為此,我們還需要把原來的三維向量轉換成四維向量,也就是我們所說的齊次座標( homogeneous coordinate) (事實上齊次座標的維度可以超過四維,但本書中所說的齊次座標將泛指四維齊次座標〉。我們可以發現,齊次座標並沒有神祕的地方,它
只是為了方便計算而使用的一種表示方式而己。
如上所說,齊次座標是一個四維向量。那麼,我們如何把三維向量轉換成齊次座標呢?對於一個點,從三維座標轉換成齊次座標是把其w 分量設為1 ,而對於方向向量來說,需要把其w 分量設為0。這樣的設定會導致,當用一個4x4 矩陣對一個點進行變換時,平移、旋轉、縮放都會施加於該點。但是如果是用於變換一個方向向量,平移的效果就會被忽略。我們可以從下面的內容中理解,這些差異的原因。

4.5.3 分解基礎變換矩陣

我們已經知道,可以使用一個4x4的矩陣來表示平移、旋轉和縮放。我們把表示純平移、純旋轉和純縮放的變換矩陣叫做基礎變換矩陣。這些矩陣具有一些共同點,我們可以把一個基礎變換矩陣分解成4 個組成部分:

其中, 左上角的矩陣M3 x 3 用於表示旋轉和縮放, t3x1用於表示平移,01x3是零矩陣, 即01 x 3=[0, 0, 0],右下角的元素就是標量 1。
接下來,我們來具體學習如何用這樣一個4 × 4 的矩陣來表示平移、旋轉和縮放。

4.5.4 平移矩陣

我們可以使用矩陣乘法來表示對一個點進行平移變換:

從結果來看我們可以很容易看出為什麼這個矩陣有平移的效果: 點的x、y、z 分量分別增加了一個位置偏移。在3D 中的視覺化效果是,把點(x,y,z)在空間中平移了(tx, ty, tz)個單位。
有趣的是,如果我們對一個方向向量進行平移變換,結果如下:

可以發現,平移變換不會對方向向量產生任何影響。這點很容易理解,我們在學習向量的時候就說過了,向量沒有位置屬性,也就是說它可以位於空間中的任意一點,因此對位置的改變(即平移)不應該對四維向量產生影響。
現在, 讀者應該明白當給定一個平移操作時如何構建一個平移矩陣:基礎變換矩陣中的t
3x1向量對應了平移向量,左上角的矩陣 M3 x3 為單位矩陣I3
平移矩陣的逆矩陣就是反向平移得到的矩陣,即

可以看出,平移矩陣並不是一個正交矩陣。

4.5.5 縮放矩陣

我們可以對一個模型沿空間的x 軸、y 軸和z 軸進行縮放。同樣,我們可以使用矩陣乘法來表示一個縮放變換:

對方向向量可以使用同樣的矩陣進行縮放:
如果縮放系數kx=ky=kz,我們把這樣的縮放稱為統一縮放( uniform scale ), 否則稱為非統一縮放( nonuniform scale ) 從外觀上看,統一縮放是擴大整個模型,而非統一縮放會拉伸或擠壓模型。更重要的是,統一縮放不會改變角度和比例資訊,而非統一縮放會改變與模型相關的角度和比例。例如在對法線進行變換時,如果存在非統一縮放,直接使用用於變換頂點的變換矩陣的 話,就會得到錯誤的結果。正確的變換方法可參見4 .7 節。
縮放矩陣的逆矩陣是使用原縮放係數的倒數來對點或方向向量進行縮放,即

縮放矩陣一般不是正交矩陣。
上面的矩陣只適用於沿座標軸方向進行縮放。如果我們希望在任意方向上進行縮放,就需要使用一個複合變換。其中一種方法的主要思想就是,先將縮放軸變換成標準座標軸,然後進行沿座標軸的縮放,再使用逆變換得到原來的縮放軸朝向。

4.5.6 旋轉矩陣

旋轉是三種常見的變換矩陣中最複雜的一種。我們知道,旋轉操作需要指定一個旋轉軸,這個旋轉軸不一定是空間中的座標軸,但本節所講的旋轉就是指繞著空間中的x 軸, y 軸或z 軸進行旋轉。
如果我們需要把點繞著x 軸旋轉θ度,可以使用下面的矩陣:

                                     
旋轉矩陣的逆矩陣是旋轉相反角度得到的變換矩陣。旋轉矩陣是正交矩陣,而且多個旋轉矩陣之間的串聯同樣是正交的。

4.5.7 複合變換

我們可以把平移、旋轉和縮放組合起來,來形成一個複雜的變換過程。例如,可以對一個模型先進行大小為(2, 2, 2)的縮放,再繞y 軸旋轉30。,最後向z 軸平移4 個單位。複合變換可以通過矩陣的串聯來實現。上面的變換過程可以使用下面的公式來計算:

由於上面我們使用的是列矩陣,因此閱讀順序是從右到左,即先進行縮放變換,再進行旋轉變換,最後進行平移變換。需要注意的是,變換的結果是依賴於變換順序的,由於矩陣乘法不滿足交換律,因此矩陣的乘法順序很重要。也就是說,不同的變換順序得到的結果可能是一樣的。
想象一下,如果讓讀者向前一步然後左轉,記住此時的位置。然後回到原位,這次先左轉再向前走一步,得到的位置和上一次是不一樣的。究其本質,是因為矩陣的乘法不滿足交換律,因此不同的乘法順序得到的結果是不一樣的。
在絕大多數情況下,我們約定變換的順序就是先縮放,再旋轉,最後平移。
讀者:為什麼要約定這樣的順序,而不是其他順序呢?
我們:因為這樣的變換順序是我們需要的。想象我們對奶牛妞妞進行一個複合變換。如果我們按先平移、再縮放的順序進行變換,假設初始情況下妞妞位於原點,我們先按(0, 0, 5)平移它,現在它距離原點5 個單位。然後再將它放大2 倍,這樣所有的座標都變成了原來的2倍,而這意味著妞妞現在的位置是(0, 0, 10),這不是我們希望的。正確的做法是,先縮放再平移。也就是說,我們先在原點對妞妞進行2 倍的縮放,再進行平移,這樣妞妞的大小正確了,位置也正確了。
為了從數學公式上理解變換順序的本質,我們可以對比不同變換順序產生的變換矩陣的表示式。如果我們只考慮對y 軸的旋轉的話,按先縮放、再旋轉、最後平移這樣的順序組合3 種變換得到的變換矩陣是:

而如果我們使用了其他變換順序,例如先平移,再縮放,最後旋轉,那麼得到的變換矩陣是:

從兩個結果可以看出,得到的變換矩陣是不一樣的。
除了需要注意不同型別的變換順序外,我們有時還需要小心旋轉的變換順序。在4.5.6 節中,我們給出了分別繞x 軸、y 軸和z 軸旋轉的變換矩陣。一個問題是,如果我們需要同時繞著3 個軸進行旋轉,是先繞x 軸、再繞y 軸最後繞z 軸旋轉還是按其他的旋轉順序呢?
當我們直接給出( θx, θy, θz)這樣的旋轉角度時,需要定義一個旋轉順序。在Unity 中,這個旋轉順序是zxy,這在旋轉相關的API 文件中都有說明。這意味著,當給定(θx, θy, θz)這樣的旋轉角度時,得到的組合旋轉變換矩陣是:

一些讀者會有疑問:上面的公式書寫順序是不是反了?不是說列矩陣要從右往左讀嗎?這樣一來順序不就顛倒了嗎?實際上,有一個非常重要的東西我們沒有說明白,那就是旋轉時使用的座標系。給定一個旋轉順序(例如這裡的zxy ),以及它們對應的旋轉角度(θx, θy, θz),有兩種座標系可以選擇。
  •  繞座標系E下的z 軸旋轉θz,繞座標系E 下的y 軸旋轉θy,繞座標系E 下的x 軸旋轉θx,即進行一次旋轉時不一起旋轉當前座標系。
  •  繞座標系E下的z 軸旋轉θz,在座標系E 下在繞z 軸旋轉θz 後的新座標系E’下的y 軸旋轉θy , 在座標系E’下再繞y 軸旋轉θy 後的新座標系E”下的x 軸旋轉θx,即在旋轉時,把座標系一起轉動。
很容易知道,這兩種選擇的結果是不一樣的。但如果把它們的旋轉順序顛倒一下,它們得到的結果就會是一樣的!說得明白點,在第一種情況下,按zxy 順序旋轉和在第二種情況下,按yxz順序旋轉是一樣的。而Unity 文件中說明的旋轉順序指的是在第一種情況下的順序。 和上面不同型別的變換順序導致的問題類似,不同的旋轉順序得到的結果也可能是不一樣的。我們同樣可以通過對比不同旋轉順序得到的變換矩陣來理解為什麼會出現這樣的不同。而這個驗證過程留給讀者作為練習。