DirectX 9.0c遊戲開發手記之RPG編程自學日誌之7: Drawing with DirectX Graphics (用DirectX圖形繪圖)(第3節)

        本文由哈利_蜘蛛俠原創,轉載請註明出處!有問題請聯繫[email protected]

 

        這一次我們繼續來講述Jim Adams老哥的RPG編程書籍第二版第二章的第3節:The Math of 3-D。這一節應該比較容易。不過由於篇幅的限制,它講述地特別省略。推薦大家去參考一下其他的書籍,比如說“龍書”第二版(不知道啥叫“龍書”第二版以及找不到下載地址的請聯繫我!)的前三章,對於3-D數學基礎部分講述地比較透徹,學過線性代數的同學都應該能看懂。

 

        另外看了本期的同學們有福了!我把這本書的中譯本找到了,現在分享給大家!

中譯本第一部分

中譯本第二部分


        當然,作爲一個有良心的翻譯者,我是不會參考這本書的,哈哈!下載了這本書後,大家可以從此把這系列博客給棄了;當然,如果你想要繼續追的話,那我也是非常歡迎的!

 

        原文翻譯:

 

===============================================================================

   

2.3 The Math of 3-D(3-D的數學)

 

        正如你現在也許已經看出來的那樣,使用3-D圖形會用到非常多的數學,並且會處理如此多的數以至於很容易把事情弄得一團糟。很多年前,實時的3-D圖形只是一個夢想,而非現實。這是因爲那時候的計算機沒能夠足夠快地進行計算。

        當然,隨着時間的流逝,事情好轉了,現在你可以實現很多炫酷的效果了。與3-D圖形有關的數學的進步是這種改觀的一個原因。

 

 

2.3.1 Matrix Math (矩陣數學)

 

        不,這一節並不是關於基阿努·裏維斯以及他的下一部關於他陷入一個計算器的電影!(當然,這是十年前的事情了。)矩陣數學是這樣一種線性代數,它簡化、減輕了某些運算。就你的目的而言,這些計算是我剛剛提到的3-D變換。

        因爲每一個3-D物體都由很多頂點組成,Direct3D的工作就是將這些頂點變換到準備好將圖形渲染到顯示屏上的座標。在每一幀中,你可以變換組成一個場景的上千個頂點。這可是真的數學——足以讓任何大學教授嚥氣。

 

        注意:

===============================================================================

        注意到矩陣數學只有在你用到3-D座標的時候纔出現。如果你在使用變換後坐標(屏幕空間的座標),你不需要再給它們進行變換了。

===============================================================================

 

        Direct3D通過使用矩陣來處理所有的變換。矩陣是數的一張網格,網格中的每一個元素具有確定的意義。就你目前的目的而言,這些書代表你想要作用在頂點上的變換。通過將所有的必要的計算整合到一個打包的形式——例如一個矩陣——中,其中的數學就大大簡化了。

 

 

2.3.2 Matrix Construction (矩陣的構造)

 

        矩陣可以有很多的尺寸,但是就你目前需要考慮的東西而言,其大小是4×4,這意味着你有一個四行四列的網格。Direct3D用一個D3DMATRIX結構體來存儲矩陣:

typedef struct_D3DMATRIX {
  D3DVALUE _11, _12, _13, _14;
  D3DVALUE _21, _22, _23, _24;
  D3DVALUE _31, _32, _33, _34;
  D3DVALUE _41, _42, _43, _44;
} D3DMATRIX;
</pre><p></p><p>        爲了用你要使用到的變換來填充一個矩陣,你實際上可以使用D3DX庫。不要使用D3DMATRIX結構體,而是使用D3DXMATRIX對象,它包含着跟D3DMATRIX同樣的變量,並且還有一些有用的函數。</p><p>        你要使用的每一個變換都有其自己矩陣,但是旋轉要花去三個矩陣(圍繞每個座標軸的旋轉都有一個)。這意味着你需要五個變換矩陣:繞x-軸旋轉、繞y-軸旋轉、繞z-軸旋轉、平移以及縮放。第一族函數用來建立旋轉矩陣:</p><p></p><pre name="code" class="cpp">D3DXMATRIX*D3DXMatrixRotationX(
  D3DXMATRIX *pOut,            // output matrix
  FLOAT         Angle,         // X angle aroundcenter
);

D3DXMATRIX*D3DXMatrixRotationY(
  D3DXMATRIX *pOut,            // output matrix
  FLOAT         Angle,         // Y angle aroundcenter
);

D3DXMATRIX *D3DXMatrixRotationZ(
  D3DXMATRIX *pOut,            // output matrix
  FLOAT        Angle,          // Z angle around center
);

        注意:

===============================================================================

        注意到D3DX使用的所有的矩陣函數也返回一個D3DXMATRIX指針。這是一個指向輸出矩陣的指針,並且它讓你能夠將矩陣函數內嵌地(inline)與其他的函數使用,如下所示:

D3DXMATRIX matMatrix, matResult;
matResult = D3DXMatrixRotationZ(&matMatrix, 1.57f);

===============================================================================

 

        通過向前面的每個函數傳遞一個矩陣(的地址)以及提供一個有理數值(以弧度計量的表示沿着軸心旋轉的角),你獲得了你需要使用的值。

        下一個函數創建一個平移矩陣,它用於移動物體:

D3DXMATRIX*D3DXMatrixTranslation(
  D3DXMATRIX *pOut,            // output matrix
  FLOAT  x,                    // X coordinateoffset
  FLOAT  y,                    // Y coordinateoffset
  FLOAT  z);                   // Z coordinateoffset

        這些座標實際上是基於物體原點的offsets(不知道怎麼翻譯)。平移值用於將物體從局部空間座標轉換到世界空間座標。下一行是讓物體以其中心進行縮放的函數:

D3DXMATRIX*D3DXMatrixScaling(
  D3DXMATRIX *pOut,            // output matrix
  FLOAT sx,                    // X scale
  FLOAT sy,                    // Y scale
  FLOAT sz);                   // Z scale

        正常狀態下,一個物體的縮放值是1.0。爲了讓一個物體的尺寸加倍,將值設爲2.0;爲了讓一個物體的尺寸減半,使用0.5。你還會用到一個特殊類型的矩陣,稱爲恆等矩陣(identity matrix)。除了幾個值以外,它的所有值都設爲零;那幾個例外值設爲一。當作用於另外一個矩陣時,恆等矩陣沒有產生任何影響,使得結果值與原來的值一樣。在你想結合兩個矩陣、但是不想改變原來的矩陣的值時,恆等矩陣是有用的。

        爲了創建一個恆等矩陣,你可以使用下面的函數(它只將輸出矩陣作爲參數):

D3DXMATRIX*D3DXMatrixIdentity(D3DXMATRIX *pOut);
</pre><p></p><p>        雖然函數的原型沒什麼好看的,但是我還是給了一些例子:</p><p></p><pre name="code" class="cpp">D3DXMATRIX matXRot,matYRot, matZRot;
D3DXMATRIX matTrans,matScale;
 
// Setup therotations at 45 degrees (.785 radians)
D3DXMatrixRotationX(&matXRot,0.785f);
D3DXMatrixRotationY(&matYRot,0.785f);
D3DXMatrixRotationZ(&matZRot,0.785f);
 
// Setup thetranslation to move to 100, 200, 300
D3DXMatrixTranslation(&matTrans,100.0f, 200.0f, 300.0f);
 
// Scale object totwice the size in all directions
D3DXMatrixScaling(&matScale,2.0f, 2.0f, 2.0f);


2.3.3 Combining Matrices (矩陣的結合)

 

        在將變換中用到的數值填充進各種各樣的矩陣中後,你可以將它們運用於每個單獨的頂點。事實上,爲了讓計算更加簡單,你可以通過矩陣的相乘來將包含着平移、旋轉和縮放的數值的矩陣結合起來。這個過程叫做矩陣串聯(matrix concatenation),並且這是優化所有的矩陣運算的核心。

        通過在每一幀中一次性創建一個矩陣,你可以使用該矩陣來對場景中的每一個頂點進行操作。當運用於一個頂點的時候,這個單個的矩陣達到的效果跟依次運用那些分開的矩陣的效果是一樣的。

        矩陣要用起來並不難。它們只需要一點點理解。事實上,有了D3DX的力量,你可以通過使用D3DXMatrixMultiply函數不費吹灰之力地結合矩陣:

D3DXMATRIX *D3DXMatrixMultiplly(
  D3DXMATRIX        *pOut,      // output matrix
  CONST D3DXMATRIX *pM1,        // Source matrix1
  CONST D3DXMATRIX *pM1);       // Source matrix1

        通過將兩個矩陣作爲參數pM1和pM2傳遞進去,你得到一個結果矩陣(pOut),它是通過將前兩個矩陣相乘而得到的。爲了擴展上一節中給出的創建縮放、旋轉和平移矩陣的例子,我們將它們合併成一個單個的矩陣,它代表所有的變換的總和:

D3DXMATRIX matResult;                  // The resulting matrix
 
// Clear theresulting matrix to identity
D3DXMatrixIdentity(&matResult);
 
// Multiply in thescaling matrix
D3DXMatrixMultiply(&matResult,&matResult, &matScale);
 
// Multiply inrotation matrices
D3DXMatrixMultiply(&matResult,&matResult, &matXRot);
D3DXMatrixMultiply(&matResult,&matResult, &matYRot);
D3DXMatrixMultiply(&matResult,&matResult, &matZRot);
 
// Multiply intranslation matrix
D3DXMatrixMultiply(&matResult,&matResult, &matTrans);

        另外一個將矩陣相乘的方法是使用D3DXMATRIX的乘法運算符(*),就如我在這裏做的:

matResult = matXRot *matYRot * matZRot * matTrans;

 

        注意:

===============================================================================

        D3DXMATRIX的擴展,像乘法運算符,使得像單個數值一樣處理矩陣成爲可能。你可以使用這裏展示的同樣的方法對矩陣進行加法、減法、乘法甚至是除法運算,就像矩陣是單個的數一樣。

===============================================================================

 

        注意你結合矩陣的順序是很重要的。在前面的例子中,我以這樣的順序將它們結合起來:縮放、繞x-軸旋轉、繞y-軸旋轉、繞z-軸旋轉,最後是平移。如果你想用其他任何順序進行結合的話,那麼最終的結果矩陣會有所不同,並且會導致一些未來的不可預測的結果。

 


2.3.4 The Steps from Local to View Coordinates (從局部座標到觀察座標的步驟)

 

        爲了讓一個頂點用於渲染一個面,這個頂點必須從局部座標(未變換的座標)轉換到世界座標。世界座標又被轉換爲觀察座標,最後被投影到2-D座標(變換後的座標)。

        你通過使用一個世界變換矩陣(world transformation matrix)(或者簡稱爲世界矩陣)來將局部座標轉換到世界座標。這個矩陣包含了用於將物體放置到3-D世界中(從局部到世界)的變換。第二個變換矩陣用來將物體變換到觀察座標,稱爲觀察矩陣(viewing matrix)。最後是投影座標(projection matrix),它將觀察座標的3-D座標轉換到用於渲染圖形的變換後的頂點。

        當構造世界矩陣和觀察矩陣的時候,你必須特別注意你結合單獨的矩陣的順序。對於世界變換,你以下列順序結合單獨的變換矩陣:

R = S * X * Y * Z *T

 

        R是結果矩陣,S是縮放矩陣,X是繞x-軸旋轉的矩陣,Y是繞y-軸旋轉的矩陣,Z是繞z-軸旋轉的矩陣,而T是平移矩陣。觀察矩陣必須以下列順序結合單獨的變換矩陣(只使用平移和旋轉):

R = T * X * Y * Z

 

 

        注意:

===============================================================================

        當使用觀察變換的時候,你必須使用觀察位置的相反數來將物體擺放到視角中。你這樣做是因爲觀察點實際上鎖定在座標0, 0, 0處。當視角“移動”的時候,世界以及所有的東西實際上在繞着你轉。例如,如果你想往前走10個單位,那麼就將世界的物體朝着你往後移動10個單位。向左看10度,那麼實際上世界上的物體向你的右邊轉了10度。

===============================================================================

 

        投影矩陣是一種特殊的情形,用起來難一些。在建立投影矩陣的時候,你必須考慮很多事情,因爲它並不是與平移、縮放或者旋轉那樣的變換有關的。我將在稍後的“投影變換”一節中使用D3DX庫來幫助構建一個投影矩陣。

    

        圖2.10展示了一個頂點歷經各種變幻到達最終的繪製座標所需要走的路徑。

 

===============================================================================

 

        好了,這一期到這裏就結束了,下一期我們將正式開始Direct3D的繪製工作!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章