3D遊戲數學基礎中的計算原理及幾何意義(一、向量)

-前言-

在進一步瀏覽Laya3D源代碼之前,讓我們先補一補關於3D遊戲開發的數學基礎知識,並去了解爲什麼要這麼去運算,這樣更加友好的讓我們去解讀引擎的源代碼實現。

-正文-

向量點乘

現在已知兩個向量分別是\overrightarrow{a}\overrightarrow{b},向量a\cdot b的結果是一個標量等於a1b1 + a2b2 + a3b3 + ..... + an-1bn-1 + anbn;

向量點乘描述兩個向量的“相似”程度。點乘結果越大,兩個向量越相近。

代碼表示:

/**
 * 求點乘
 * @param a 
 * @param b 
 */
public static dot(a:Vector3,b:Vector3):number{
    return (a.x * b.x) + (a.y + b.y) + (a.z * b.z);
}

幾何意義:

點乘結果還有另一個表達方式:

a\cdot b = \left \| a \right \|\left \| b \right \|\cos\Theta,根據這麼一個公式就可以推導出兩個向量之間的夾角公式爲:\Theta =\left ( a\cdot b \div \left \| a\left \| \right \left \| b \right \| \right )

代碼表示爲:

/**
 * 求兩個向量之間的夾角
 * @param x1 
 * @param y1 
 * @param x2 
 * @param y2 
 */
public calAngle(x1,y1,x2,y2):number{
    var dot:number = x1 * x2 + y1 * y2;
    var ma:number = Math.sqrt(Math.pow(x1,2) + Math.pow(y1,2));
    var mb:number = Math.sqrt(Math.pow(x2,2) + Math.pow(y2,2));
    var v:number = Math.acos(dot / (ma * mb));//弧度
    var t:number = v * 180 / Math.PI;//角度
    return v;
}

向量叉乘(叉積)

向量的叉乘只能用於3D向量。上面的點乘滿足交換律,並且點乘結果爲一個標量。向量的叉乘得到一個向量並且不滿足交換律。

叉乘的表示爲:a\times b

向量的叉乘滿足反交換率:a\times b = -(b \times a)

幾何意義

兩個3D向量叉乘得到的向量一定是垂直於原來的兩個向量的。

叉積之後所得到的向量的模等於a、b向量的模乘以它們的夾角,數學公式表示爲:||a\times b|| = ||a|| ||b|| \sin\Theta ,它們的結果也等於a、b所組成的平行四邊形的面積。

叉乘主要應用於創建垂直平面、三角形或多邊形。用於確定平面法向量。

代碼表示

/**
 * 叉乘
 *  |ax|   |bx|     |ay*bz - az*by|
 *  |ay| x |by|   = |az*bx - ax*bz|
 *  |az|   |bz|     |ax*by - ay*bx|
 * @param a 
 * @param b 
 * @param out 輸出向量
 */
public static cross(a:Vector3,b:Vector3,out:Vector3){
    var ax = a.x,ay = a.y,az = a.z;
    var bx = b.x,by = b.y,bz = b.z;
    out.x = ay * bz - az * by;
    out.y = az * bx - ax * bz;
    out.z = ax * by - ay * bx;
}

向量的歸一化

對於任意向量如[x,y]向量的歸一化公式等於:\mathbb{P} = \overrightarrow{a} / ||a||,解釋爲a向量除以a向量的模。

向量的歸一化被稱爲單位向量或者被稱爲“法線”。零向量是不能被歸一化的。因爲零向量的模爲0,0不能被用作除數。

代碼表示

/**
 * 向量歸一化
 * @param a 
 * @param out 
 */
public static normalize(a, out) {
    var x = a.x, y = a.y, z = a.z;
    var len = x * x + y * y + z * z;
    if (len > 0) {//零向量不能歸一化
        len = 1 / Math.sqrt(len);
        out.x = x * len;
        out.y = y * len;
        out.z = z * len;
    }
}

 

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