必免不了的是遊戲數學,這裡做一些簡單的筆記。
[座標系統]
在2D座標系統上 ,我們通常已X軸與Y軸來定義一個2D空間資訊。
通常X軸向右,Y軸向下,角度為 sita
如下圖 , (筆者用小畫家畫,請見諒 :D )
但是在程式撰寫時,電腦世界通常為如下圖
此外,我們在定義3D 座標系統的時候,有分為左手、右手系統
下圖即為右手系統的例子。
(圖參考至: 點我)
現在市面上應用於左手、右手系統舉例如下
右手系統 : OpenGL , Microsoft XNA , Unity
左手系統 : Microsoft DirectX
所以在撰寫程式或是空間設計的時候必須先了解清楚是哪一個系統。
[向量基礎]
在XNA程式語法上,點座標 和 向量的資料結構是共用的都定義為一個Vector
2D 系統 : Vector2 (2D 點座標 和 向量) - 資料結構定義
3D 系統 : Vector3 (3D 點座標 和 向量) - 資料結構定義
定義方式如 (以3D座標舉例) :
Vector3 X ;
特別注意,XNA是右手系統,所以Z軸的
向前forward 是指朝向螢幕內部 , Z軸的反向 -- Vector3.Backward (0,0,-1)
向後backward 是指朝向使用者 , Z軸的正向 -- Vector3.Backward (0,0,-1)
[向量運算]
加法可以用Add() 方法或是運算元 +
減法可以用Subtract() 方法或是運算元 -
在XNA裡面,要計算長度可以用以下兩種做法
a. 傳統作法
Vector2 vector_2d = new Vector (3,4) ; //2D
double length_vector2d = Math.Sqrt (vector_2d.X * vector_2d.X + vector_2d.Y * vector_2d.Y) ; // 5
Vector3 vector_3d = new Vector3(1,2,2) ; //3D
double length_vector3d = Math.Sqrt (vector_3d.X * vector_3d.X + vector_3d.Y * vector_3d.Y + vector_3d.Z * vector_3d.Z) ; // 3
b. XNA 方法
Vector2 vector_2d = new Vector (3,4) ; //2D
double length_vector2d = vector_2d.Length();
Vector3 vector_3d = new Vector3(1,2,2) ; //3D
double length_vector3d = vector_3d.Length();
通常必須將向量單位化,也就是將長度調整為1
Vector2 vector_2d = new Vector (3,4) ; //2D
vector_2d.Normalize();
Vector3 vector_3d = new Vector3(1,2,2) ; //3D
vector_3d.Normalize() ;
~~~ (PS)以下皆以單一2D 或 3D 舉例,請依例類推 ~~~
當然求兩點距離,則可以用以下方法
Vector2 A = new Vector2 (1, 0);
Vector2 B = new Vector2 (0,1);
float C = Vector2.Distance(A,B); // C 為距離
float D = Vector2.DistanceSquared(A,B); // 在平方
[向量內積]
公式如下 :
v1 ● v2 = |v1| * |v2| * cos(角度 )
通常我們運用向量內積可以來判斷角度以及是否為平行、垂直、反向。
Vector3 v1 = new Vector3(1,2,3);
Vecotr3 v2 = new Vector3(2,4,6);
v1.Normalize(); //單位化
v2.Normalize(); //單位化
float dot = Vector.Dot(v1,v2); //兩向量取內積
float angle = (float) Math.Acos (dot) ; // 兩向量取夾角
當然,判斷夾角 如下
如果角度 > 90 度 , 則 v1● v2 < 0
如果角度 = 90 度 , 則 v1● v2 = 0
如果角度 < 90 度 , 則 v1● v2 > 0
在XNA裡面,先將向量單位化之後,再套用公式則兩向量的內積 = 夾角 cos 值
在3D程式通常應用於決定光線對頂點的打光程度。
在遊戲裡面通常判斷是否為同方向,或是反方向
if (dot == 1)
//v1, v2 平行
else if ( dot == 0)
// v1,v2 垂直
else if ( dot == -1 )
//v1,v2 反方向
[向量外積]
在3D向量之中,求其外積表示要求其原來兩個3D向量所形成的平面。
數學式子這邊就不多解釋了..
我們直接看XNA 程式部分。
Vector3 v1 = new Vector3 (1,0,0);
Vector3 v2 = new Vector3 (0,1,0);
Vector3 v3 = Vector3.Cross( v1, v2); // 外積
[矩陣]
在3D程式之中,往往需要將3X3 矩陣轉換在4X4矩陣空間作運算。
為什麼呢!? -> 因為便於計算,在矩陣相乘過程之中可以加入動作。
如: 旋轉、平移、縮放等
在數學的意義上是乘上一個轉移矩陣做改變
但是在三維座標上必須一一去乘上轉移矩陣做轉換
在4X4矩陣空間可以涵蓋平移、旋轉、縮放、投影等轉換。
(e.g) 如(2,3,4 ) 要往X軸移動2 ,Y軸移動1 則,
[ 1 0 0 0 ]
[ 2 3 4 1 ] [ 0 1 0 0 ]
[ 0 0 1 0 ]
[ 1 2 0 0 ]
[XNA Matrix]
Matrix 結構的相對位置
Right [ M11 M12 M13 M14 ]
Up [ M21 M22 M23 M24 ]
Backward [ M31 M32 M33 M34 ]
Translation [ M41 M42 M43 M44 ]
反之 left , down ,forward 則 乘上 (-1 )
宣告方式如下 :
Matrix M = Matrix.Identity ; // 宣告單位矩陣
M.M41 = 1.0f ; // 做平移
M.Right = new Vector3 ( 5 , 6, 7); // 設定 right (5,6,7)
Vector3 V = M.Right ; // 取值 (5,6,7)
M = Matrix.Invert(M ); //取反矩陣 ,有時可以做picking
M = Matrix.Transpose(M) ; //取轉至矩陣,顧慮效率時使用
然而矩陣相乘,可以直接使用以下相乘
Matrix M1 = Matrix.Identity ;
Matrix M2 = Matrix.Identity ;
Matrix M3 = Matrix.Identity ;
Matrix M4 = M1 * M2 * M3 ;
也可以使用以下 方法
M = Matrix.Multiply ( M1 , M2 );
M4 = Matrix.Multiply( M , M3) ;
特別注意矩陣相乘有順序問題,順序不同結果會不一樣。
[平移、旋轉、縮放]
平移的用法如 :
Matrix.CreateTranslation (1.0f , 1.0f , .0.0f) ; //會將所有座標移動(1,1,0)
如果以針對有基準點的平移,(-1,2) - > (5,4)
Matrix m1 ;
m1 = Matrix.CreateTranslation(1.0f , -2.0f , 0.0f); // 先將之移動到原點
Matrix m2;
m2 = Matrox.CreateTranslation(5.0f , 4.0f , 0.0f); //平移到 (5,4)
則最後做相乘動作,並且設定世界矩陣
Matrix world ;
world = m1 * m2;
Effect.world = world;
縮放兩倍呢!? (將上列程式碼平移部分改成縮放部分)
Matrix s;
s = Matrix.CreateScale(2);
旋轉呢!?
Matrix r;
float theta;
r = Matrix.CreateRotationZ(theta) ; //依照Z軸旋轉
然而XNA 有提供輔助計算 MathHelper class 可以運用 。
MathHelper (說明請點我)
[攝影機、投影]
根據攝影機位置看到的點,相機上方向量得到視覺矩陣
Vector3 cameraPosition;
Vector3 cameraLookat;
Matrix view = Mareix.CreateLooakAt(cameraPostion , cameraLookat , new Vector3(0.0f , 1.0f , 0.0f));
根據攝影機視角寬高比得到投影矩陣
float viewAngle ;
float aspectRatio ;
Matrix projection = Matrix.CreatePerspectiveFieldOfView(viewAngle , aspectRatio, 1.0f , 1000.0f );
Plane p1 = new Plane (v17 , 15.0f);
Plane p2 = new Plane (v15 , v16 , v17) ;
參考資料來源 : XNA 遊戲程式設計
(上述部分程式碼,皆參考自此書)
沒有留言:
張貼留言