【译】理解基础3d数学(上)

550 阅读5分钟

作者:Sumeet Arora

书名:WebGl Game Development

开发一个webgl3d游戏需要良好的3d数学基础,但是我们不会介绍3d数学的全部,这会花费一本书的时间。

这一章节我们会介绍理解webgl渲染所需要的3d数学基本概念。我们同时会建立一个我们在游戏中使用的3d数学库。一个强大的数学库,glMatrix

JavaScript或者webgl不提供对向量和矩阵进行操作的内建函数。因此,我们使用第三方库,glMatrix。它用来操作向量和矩阵,速度极快。下面,我们一起学习这些操作并理解它们的实现。

3d游戏引擎使用向量代表空间中的点,比如物体的坐标或者多边形网格的顶点。同时也用来表示空间方向,比如摄像机方向或者三角形表面法线。 3d空间中的一个点可以用向量x,y,z表示。 下面,让我们看一下3d数学库对向量的操作。

var out=vec3.create()  //Creates an empty vector object.
var out1=vec3.create()  //Creates an empty vector object.
var out2=vec3.create()  //Creates an empty vector object.
var v2=vec3.fromValues(10, 12, 13); //Creates vector i
nitialized with given values.
var v3=vec3.fromValues(2,3,4);    //Creates vector initialized with given values.
vec3.cross(out, v2, v3) //Cross product of vector v2 & v3 placed in vector out.
vec3.normalize(out1, v2) // V2 is normalized. Converted to a unit vector and placed in out1.
var result=vec3.dot(v2, v3) // Calculates dot product of two vectors.
var v4= vec4.fromValues(x, y, z, w)// Creates a vector with w value
var v5= vec4(v2, w)

上述代码主要创建了向量,同时对向量作点积和交叉积运算,同时求了一次标准向量。 (译者备注,省略掉无用的广告信息)

矩阵(matix)

矩阵用来描述3d数学中两个坐标系空间间的关系。将向量从一个坐标系转换到另一个坐标系的计算,比如物体空间到世界空间(world space,也称作世界坐标系)的转换,世界空间到视空间的转换。 下面是一些有用的矩阵操作。

var mat=mat3.create() //Creates a new identity mat3
var out=mat3.create() //Creates a new identity mat3
mat3.identity(out) //Set a mat3 to the identity matrix
var result=mat3.determinant(mat) //Calculates the determinant of a mat3  
mat3.invert(out, mat) //Inverts a mat3
mat3.transpose(out, mat) //Transpose the values of a mat3

这段代码主要创建了一个矩阵,同时标准化一个矩阵,对矩阵进行转置运算和逆运算。 (译者备注)

理解变换

在所有的计算机图形学中,你会经常性得见到变换这个词。这个词用来表示物体状态的变化。我们可以对一个物体进行缩放,旋转,转向和平移操作。

我们可以对物体进行一系列的变换,这些变换被称作线性变换或者仿射变换。

线性变换和放射变换的分类

线性变换是3d游戏中最常用的变换。你的游戏职业生涯将会大量使用旋转,缩放和转向变换。这些变换将会从上一次变换状态变换而来。

如果我们缩放然后旋转一个物体,或者旋转然后缩放一个物体,其最终结果将会一样。所以变换是线性的,他保存了加法和乘法的基本操作。线性变换一些有用的方法如下:

var a=mat3.create();
var out=mat3.create();
var rad=1.4; //in Radians
var v=vec2.fromValues(2,2);
mat3.rotate(out, a, rad);  //Rotates "a" mat3 by the given angle and puts data in out.
mat3.scale(out, a, v)  //Scales the mat3
 by the dimensions in the given vec2

仿射变换是伴随着平移的线性变换。3行3列矩阵用于线性变换,它们不包含平移变换。

矩阵的乘法和转置变换可以组成复杂变换。 仿射变换的例子如下:

var a=mat3.create(); //Identity matrix created
var vertex=vec3.fromValues(1,1,1);
var scale=mat3.create(); //Identity Matrix created
var final=mat3.create(); //Identity Matrix created
var factor=vec2.fromValues(2,2); //Scaling factor of double create 2x height and 2x width
mat3.scale(scale,a,factor); // a new scale create after multiplication
mat3.rotate(final,scale,.4);// new matrix scale created which contains scaling & rotation
var newVertex=final*vertex;

在上述代码中,我们创建了终极矩阵包含缩放和平移操作。

我们创建了一个组合变换,然后将它应用到顶点去获取它新的位置。

现在,这个终极矩阵可以改变一个3d对象的顶点。

创建3行3列变换矩阵去处理平移变换将会是一个好主意,我们可以通过将顶点向量扩展到四维坐标系,然后使用4行4列矩阵去进行变换。

M是一个包含平移的矩阵,第4行给出了平移变换。代码和图示如下:

2ad224a4d962dc2a75fc71a58100e16.jpg

var a=mat4.create();//mat4 identity matrix
var final=mat4.create();//mat4 identity matrix
var rad=.5;
var v=vec3.fromValues(0.5,0.5,0.5);
var translate=vec3.fromValues(10,10,10);
mat4.rotateX(final, a, rad) //Rotates a matrix by the given angle around the X axis
mat4.rotateY(final, final, rad) //Rotates a matrix by the given angle around the Y axis
mat4.rotateZ(final, final, rad) //Rotates a matrix by the given angle around the Z axis
mat4.scale(final, final, v) //Scales the mat4 by the dimensions in the given vec3
mat4.translate(final, final, v) //Translate a mat4 by the given vector

现在,最终矩阵包含了围绕坐标系旋转,缩放和平移操作。

理解渲染3d物体需要的变换

在一个游戏中,我们加载并初始化一个物体,一个物体的不同部分的坐标相对于它的中心点定义。

比如说我们的设计师在玛雅软件中导出一个模型,汽车轮子的坐标系相对于车身给出。当我们旋转或平移我们的小汽车,汽车轮子也要跟着走。

接下来,我们要将3d对象投射到2d屏幕上。投影不仅仅依赖于摄像机的位置,也依赖于摄像机的透镜。

下个章节中,我们将讨论两种变换,视变换和投影变换帮我们在2d屏幕上更好展示3d对象。

译文完