天天看點

3D圖形向量基礎

向量乘法

向量之間可以互相作乘法,但與标量乘法不一樣,向量乘法有許多種不同類型。在遊戲程式設計中,我們最常使用以下兩種乘法:

  • 點乘(也被稱作标量乘或内積),和
  • 叉乘(也被稱作向量乘或外積)。

兩個向量之間的點乘将産生一個标量,它被定義為向量各部分乘積的和:

3D圖形向量基礎

點乘還可以被寫作是兩向量的大小乘積再乘以兩向量夾角的餘弦值:

3D圖形向量基礎

向量投影

如果u是一個機關向量(|u| = 1),那麼點乘(a · u)代表了向量a投影在由向量u的方向所定義的無限長直線上的投影長度,如圖4.10所示。這個概念同等地适用于二維、三維以及更高的次元,以解決各種各樣的三維問題。

3D圖形向量基礎

作為點乘的大小

一個向量的平方大小可以由向量與自身的點乘得出。是以向量的大小可以簡單地做平方根運算後得出:

3D圖形向量基礎

這之是以可行是因為角度0的餘弦值為1,是以剩下來的就是|a||a| = |a|^2。

點乘測試

點乘非常适合用來測試兩個向量是否共線或垂直,以及他們是否大緻上指向同一方向或相反方向。對于兩個任意的向量a和b,遊戲程式員通常使用以下測試,如圖4.11所示:

  • 共線。  (a b) = |a||b|= ab(也就是說,兩個向量之間的夾角正好為0度 —— 當兩個向量均為機關向量時,結果為+1)。
  • 共線但反向。 (a b) = –a(也就是說,兩個向量之間的夾角為180度 —— 當兩個向量均為機關向量時,結果為-1)。
  • 垂直。 (a b) = 0(也就是說,兩個向量之間的夾角為90度)。
  • 同向。(a b) > 0(也就是說,他們之間的夾角小于90度)。
  • 反向。(a b) < 0(也就是說,他們之間的夾角大于90度)。
3D圖形向量基礎

點乘的一些其他應用

點乘可運用于遊戲程式設計中的方方面面。例如,假設我們想要知道一個敵人是處于玩家的身前還是處于玩家的身後。我們可以通過将玩家的位置P與敵人的位置E相減(v = E - P)。假設我們擁有一個向量f指向玩家面對的方向。(我們将會在4.3.10.3中看到,向量f可以直接從玩家的模型世界矩陣中取得。)點乘d = v  f可以被用來測試敵人是否在玩家身前 —— 如果結果為正數則敵人在玩家身前,負數則是在身後。

點乘還可以用于判斷一個點是處于平面的上方還是下方(這在編寫一個月球登陸遊戲中可能會很有用)。我們可以使用兩個向量來定義一個平面:平面上的任意一點Q,以及一個垂直于平面的機關向量n(法向量)。為了找出點P相對于平面的高度h,我們首先要計算出從平面上任意點(點Q就很好)指向點P的向量。是以我們有了v = P - Q。向量v與機關向量n的點乘結果就是向量v在由向量n定義的直線上的投影。這正是我們想要尋找的高度。是以,h = vn =(P - Q)n。這如圖4.12所示。

3D圖形向量基礎

叉乘

兩個向量的叉乘(也被稱作外積和向量積)将産生另一個垂直于這兩個向量的向量,如圖4.13所示。以下僅給出三維的叉乘運算:

3D圖形向量基礎
3D圖形向量基礎

叉乘的大小

叉乘結果向量的大小是每個被乘向量大小的積再乘以兩向量夾角的正弦值。(這與點乘大小的定義十分相似,不過要把餘弦換成正弦)。

3D圖形向量基礎

叉乘|a x b|的大小等于以a和b為邊的平行四邊形的面積,如圖4.14所示。因為一個三角形是一個平行四邊形的一半,以位置向量V1、V2和V3圍成的三角形面積可以由其任意兩條邊的外積的大小的一半求得:

3D圖形向量基礎

叉乘的方向

當使用右手坐标系時,你可以使用右手定則來确定叉乘的方向。将你的手握成杯狀,手指從向量a轉向向量b,則拇指指向的方向即為叉乘(a x b)的方向。

注意當使用左手坐标系時,叉乘的方向由左手定則确定。這意味着叉乘的方向取決于所選擇的坐标系統。這可能在最開始看上去有點奇怪,但請記住,坐标系統的選擇并不會影響我們将要進行的數學計算 —— 它僅改變了數字在三維空間中的可視化效果。當将右手坐标系和左手坐标系互相轉換時,所有點和向量的數值保持不變,隻是一條軸發生了反轉。是以如果叉乘正好發生在我們進行了反轉的那條軸(例如z軸)上時,我們需要将那一條軸所對應的值反轉。如果不這樣做,那我們就需要對叉乘本身的數學定義進行修改,以使得叉乘後z軸的值會在心坐标系中取反。我不會讓這些規則導緻我失眠。隻需要記住:當可視化叉乘時,在右手坐标系中使用右手定則,而在左手坐标系中使用左手定則。

叉乘的屬性

叉乘不符合交換率(是以是順序相關的):

a × b ≠ b × a

然而,它符合反交換率:

a × b = -b × a

叉乘符合加法配置設定律:

a × (b + c) = (a × b) + (a × c)

它和标量的乘法結合如下:

(sa) × b = a × (sb) = s(a × b)

笛卡爾基本向量與叉乘的關系如下:

(i x j) = -(j x i) = k

(j x k) = -(k x j) = i

(k x i) = -(i x k) = j

這三個叉乘定義了繞軸的正方向旋轉。從x到y的正方向旋轉(繞z軸),從y到z的正方向旋轉(繞x軸),以及從z到x的正方向旋轉(繞y軸)。正如我們将會看到的,這給了我們一個提示,那就是為什麼繞y軸旋轉的矩陣看上去與繞x或繞z軸旋轉的矩陣相反。

實際中運用的叉乘

叉乘在遊戲中有許多應用。其中一個最常見的用法是用來尋找垂直于另兩個向量的向量。正如我們将在章節4.3.10.2所看到的,如果我們已經知道一個對象的本地機關向量組(本地向量i、j和k),那麼我們就可以很容易找到表示這個對象朝向的矩陣。假設我們隻知道一個對象的本地向量k —— 也就是該物體面對的方向。如果我們假設物體沒有繞k方向的旋轉,我們就可以通過将本地向量k(我們已知的)與世界坐标系的上方向向量(等于[0 1 0])做叉乘,以求得本地向量i。然後我們就可以通過簡單地對i和k做如下叉乘j = k x i以求得本地向量j。

繼續閱讀