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;
    }
}

 

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