# webgl开发第一道坎——矩阵与坐标变换

x = X / w

y = Y / w

z = Z / w

Ax + By + Cz + D = 0

Ax + By + Cz + d = 0;

D不等于d；根据解析几何知识我们可以知道这是两条在欧几里得空间中这是两条相交的平行线，它们不可能有交点。如果d = D两条直线会重合。现在我们把他们用齐次坐标来表示：

A（X/w） + B(Y/w) + C(Z/w) + D = 0;

A (X / w) + B (Y/w) + C (Z/w) + d = 0;

AX + BY + CZ + Dw = 0;

AX + BY + CZ + dw = 0;

x = r * cosβ

y = r * sinβ

x' = r * cos(α + β) = rcosβcosα- rsinαsinβ = xcosα - ysinα

y' = r * sin(α + β) = rcosαsinβ + rsinαcosβ = ycosα + xsinα

1）webgl中使用的是列向量，对应的缩放、平移、旋转矩阵为：

2）webgl使用的是列存储

3）webgl中矩阵的运算顺序是从右往左进行的

C = TR

T代表平移变换，R代表旋转变换（R的前三列代表相机旋转后的三个坐标轴），那么这时候的模型视图矩阵为：

mat4.lookAt = function (eye, center, up, dest) {

if (!dest) { dest = mat4.create(); }

var x0, x1, x2, y0, y1, y2, z0, z1, z2, len,

eyex = eye[0],

eyey = eye[1],

eyez = eye[2],

upx = up[0],

upy = up[1],

upz = up[2],

centerx = center[0],

centery = center[1],

centerz = center[2];

if (eyex === centerx &amp;&amp; eyey === centery &amp;&amp; eyez === centerz) {

return mat4.identity(dest);

}

//vec3.direction(eye, center, z);

// 首先根据观察点和相机位置求得相机轴向量

z0 = eyex - centerx;

z1 = eyey - centery;

z2 = eyez - centerz;

// normalize (no check needed for 0 because of early return)

// 对相机轴做标准化

len = 1 / Math.sqrt(z0 \* z0 + z1 \* z1 + z2 \* z2);

z0 \*= len;

z1 \*= len;

z2 \*= len;

//vec3.normalize(vec3.cross(up, z, x));

// up向量叉乘z轴得到x轴，即我们说的right向量

x0 = upy \* z2 - upz \* z1;

x1 = upz \* z0 - upx \* z2;

x2 = upx \* z1 - upy \* z0;

len = Math.sqrt(x0 \* x0 + x1 \* x1 + x2 \* x2);

if (!len) {

x0 = 0;

x1 = 0;

x2 = 0;

} else {

len = 1 / len;

x0 \*= len;

x1 \*= len;

x2 \*= len;

}

//vec3.normalize(vec3.cross(z, x, y));

// 然后根据z轴叉乘x轴得到相机的y轴

y0 = z1 \* x2 - z2 \* x1;

y1 = z2 \* x0 - z0 \* x2;

y2 = z0 \* x1 - z1 \* x0;

len = Math.sqrt(y0 \* y0 + y1 \* y1 + y2 \* y2);

if (!len) {

y0 = 0;

y1 = 0;

y2 = 0;

} else {

len = 1 / len;

y0 \*= len;

y1 \*= len;

y2 \*= len;

}

// 最终得到的模型视图矩阵为：R^T \* T^-1

dest[0] = x0;

dest[1] = y0;

dest[2] = z0;

dest[3] = 0;

dest[4] = x1;

dest[5] = y1;

dest[6] = z1;

dest[7] = 0;

dest[8] = x2;

dest[9] = y2;

dest[10] = z2;

dest[11] = 0;

dest[12] = -(x0 \* eyex + x1 \* eyey + x2 \* eyez); // -x轴点乘eye向量

dest[13] = -(y0 \* eyex + y1 \* eyey + y2 \* eyez); // -y轴点乘eye向量

dest[14] = -(z0 \* eyex + z1 \* eyey + z2 \* eyez); // -z轴点乘eye向量

dest[15] = 1;

return dest;

};