THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
this.elements = new Float32Array( 16 );
this.set(
( n11 !== undefined ) ? n11 : 1, n12 || 0, n13 || 0, n14 || 0,
n21 || 0, ( n22 !== undefined ) ? n22 : 1, n23 || 0, n24 || 0,
n31 || 0, n32 || 0, ( n33 !== undefined ) ? n33 : 1, n34 || 0,
n41 || 0, n42 || 0, n43 || 0, ( n44 !== undefined ) ? n44 : 1
);
};
在Matrix3对象中出现的几个函数在Matrix4中有相同的作用,这里也略去。
函数identity()将对象重置为单位阵。
函数lookAt(eye,center,up)将对象设定为一个视图矩阵,参数都是Vector3对象,该矩阵只会用到eye和center的相对位置。该视图矩阵表示,摄像机在eye位置看向center位置,且向上的向量(这一点稍后解释)为up时的视图矩阵。视图矩阵又可以看做摄像机的模型矩阵,所以该函数产生的矩阵又可以表示以下变换:将物体从原点平移至位置center-eye,再将其旋转至向上的向量为up。向上的向量up用来固定相机,可以想象当相机固定在一点,镜头朝向固定方向的时候,还是可以在一个维度里自由旋转的,up向量固定相机的这个维度。
复制代码 代码如下:
lookAt: function ( eye, target, up ) {
var te = this.elements;
var x = THREE.Matrix4.__v1; // 空Vector3对象,下同
var y = THREE.Matrix4.__v2;
var z = THREE.Matrix4.__v3;
z.sub( eye, target ).normalize();
if ( z.length() === 0 ) {
z.z = 1;
}
x.cross( up, z ).normalize();
if ( x.length() === 0 ) {
z.x += 0.0001;
x.cross( up, z ).normalize();
}
y.cross( z, x );
te[0] = x.x; te[4] = y.x; te[8] = z.x;
te[1] = x.y; te[5] = y.y; te[9] = z.y;
te[2] = x.z; te[6] = y.z; te[10] = z.z;
return this;
},
函数multiply(a,b),multiplySelf(v)和multiplyToArray(a,b,r)将两个矩阵相乘。
函数multiplyScale(s)将对象所有16个元素都乘以s。
函数multiplyVector3(v)和multiplyVector4(v)将对象矩阵左乘四维行向量,返回vector3和vector4类型的行向量。如果对象矩阵是模型视图矩阵,输入的向量是点位置信息,则输出的向量则是经过模型变换和相机变换后,该点相对于相机的位置。输入vector3类型向量时,自动补足为齐次坐标,返回时再砍掉第四个分量成为普通坐标。
函数rotateAxis(v)使用对象矩阵左上角的3×3子矩阵左乘行向量v,得到一个新的行向量并归一化,返回这个新行向量。该函数同时更新了向量v的值。模型视图矩阵左上角3×3的子矩阵包含了模型矩阵中的旋转信息,将该子矩阵左乘一个向量,得到的新向量实际上就是原向量经过旋转(该旋转效果来自于模型矩阵)得到的。因此该函数名为rotateAxis。
复制代码 代码如下:
rotateAxis: function ( v ) {
var te = this.elements;
var vx = v.x, vy = v.y, vz = v.z;
v.x = vx * te[0] + vy * te[4] + vz * te[8];
v.y = vx * te[1] + vy * te[5] + vz * te[9];
v.z = vx * te[2] + vy * te[6] + vz * te[10];
v.normalize();
return v;
},
函数crossVector(v)计算矩阵对象(调用者)和v的叉乘,实际上就是对象矩阵左乘四维行向量v,返回向量。这个具体是做什么的,我还没弄明白。
复制代码 代码如下:
crossVector: function ( a ) {
var te = this.elements;
var v = new THREE.Vector4();
v.x = te[0] * a.x + te[4] * a.y + te[8] * a.z + te[12] * a.w;
v.y = te[1] * a.x + te[5] * a.y + te[9] * a.z + te[13] * a.w;
v.z = te[2] * a.x + te[6] * a.y + te[10] * a.z + te[14] * a.w;
v.w = ( a.w ) ? te[3] * a.x + te[7] * a.y + te[11] * a.z + te[15] * a.w : 1;
return v;
},
函数determinant()计算矩阵的行列式值。
函数flattenToArray(flat)和函数flattenToArrayOfset(flat,offset)将矩阵转存到一维数组中,前一个函数从flat[0]存储到flat[15],后一个函数允许指定开始存储的位置,从flat[offset]存储到flat[offset+15]。
函数getPosition()和函数setPosition()用来获取或设置矩阵对象的位置分量。正如旋转分量存储在左上角3×3的子矩阵中,位置分量存储在第四行前三个分量上,即element[12], element[13], element[14]中。
函数getColumeX(),getColumeY(),getColumeZ()分别提取左上角3×3子矩阵的三列。
函数compose(translate,rotation,scale)将对象矩阵设置为由vector3类型translate对象表示的平移、由matrix3类型rotation对象表示的旋转、由vector3类型scale对象表示的缩放这三个变换组合到一起的变换矩阵。实际上就是讲其直接填充到模型矩阵的相应子空间。
函数decompose(translate,rotation,scale)将矩阵对象拆开到三个对象中,和上一个函数正好相反。
函数extractPosition(m)和extractRotation(m)将矩阵对象m中表示位置或旋转的分量抽取到调用者对象中,比如两个物体经过多次各不相同的变换,只需要一个物体的模型视图矩阵extractRotation另一个物体的模型视图矩阵,则调用者就和另外一个物体保持着变换之处相同的旋转方位。
函数translate(v)是模型矩阵最基本的变换之一:平移变换,将模型矩阵从属的物体平移向量v。
函数rotateX(angle),rotateY(angle),rotateZ(angle)分别将模型矩阵从属的物体绕X,Y,Z轴旋转角度angle。
函数rotateByAxis(axis, angle)将模型矩阵从属的物体绕一个任意轴axis旋转角度angle,这是上面两条所涉及的变换的多次叠加(叠加参数由当前位置和axis参数决定),我在《模型视图矩阵和投影矩阵:webgl笔记(1)》中曾讨论到绕任意轴旋转的问题。
这里不应该有一个scale(s)函数吗?可是我在源码中没找到。
函数makeTranslate(x,y,z),makeRotationX(theta),makeRotationY(theta),makeRotationZ(theta),makeRotationAxis(axis,angle),makeScale(s)函数将对象矩阵直接重置为单位阵经过一次平移、或绕某轴旋转、或单纯某次缩放后的矩阵。该函数更新对象本身的值,而且更新的结果与对象之前的值毫无关联(这也是make前缀函数的特点)。
函数makeFrustum(...),makePerspective(...),makeOrthographic(...)也是用来初始化新矩阵,具体含义到相机类里面再讨论,我想相机类的构造函数里一定会调用这些函数的。
函数clone()将矩阵对象复制出来并返回。
Core::Face3
该函数创建一个三角形平面对象
复制代码 代码如下: