Matrix4
4×4 变换矩阵,承载平移、旋转、缩放与投影,是物体最终位置的数学载体。
构造参数
| 参数 | 默认 | 说明 |
|---|---|---|
| 无 | — | 构造函数不接受参数,实例化后即为 16 个元素组成的单位矩阵 |
elements | 单位矩阵 | 需要初始值时应构造后调用 set、make* 或 compose |
属性
| 属性 | 说明 |
|---|---|
elements | Float32Array,长度 16,列主序存储 |
isMatrix4 | 只读标记 |
列主序意味着前四个元素是矩阵的第一列,而不是第一行。
用 elements[12]、elements[13]、elements[14]
读取平移分量,正好对应矩阵第四列的 x、y、z。
常用方法
| 方法 | 说明 |
|---|---|
identity() | 重置为单位矩阵 |
set(n11, …, n44) | 按行主序传入 16 个数,内部会转置存储 |
copy(m) / clone() | 就地复制与新建副本 |
multiply(m) | 右乘,等价于先应用 m 再应用自身 |
premultiply(m) | 左乘 |
multiplyMatrices(a, b) | this = a * b,不产生临时矩阵 |
multiplyScalar(s) | 所有元素乘以标量 |
makeTranslation(x, y, z) | 重建为纯平移矩阵,会清掉原有内容 |
makeRotationX(θ) / makeRotationY(θ) / makeRotationZ(θ) | 重建为绕单轴旋转 |
makeRotationAxis(axis, θ) | 绕任意单位轴旋转 |
makeScale(x, y, z) | 重建为缩放矩阵 |
compose(pos, quat, scale) | 按 T · R · S 顺序合成,是 Object3D 内部使用的方式 |
decompose(pos, quat, scale) | 从矩阵还原出平移、旋转、缩放 |
invert() | 求逆,行列式为 0 时结果无意义 |
transpose() | 转置 |
determinant() | 行列式,负值表示变换含镜像 |
setPosition(x, y, z) | 只写平移分量,其余不动 |
lookAt(eye, target, up) | 生成朝向矩阵,相机与灯光的内部实现 |
makePerspective(l, r, t, b, n, f) | 生成透视投影矩阵 |
makeOrthographic(l, r, t, b, n, f) | 生成正交投影矩阵 |
extractBasis(xAxis, yAxis, zAxis) | 取出三个基向量 |
fromArray(arr) / toArray(arr) | 按列主序与数组互转 |
组合顺序
矩阵乘法不满足交换律。想让一个立方体先缩放、再旋转、最后平移,
顺序必须写成 T · R · S,对应到代码就是从右往左应用:
const m = new THREE.Matrix4();
const T = new THREE.Matrix4().makeTranslation(10, 0, 5);
const R = new THREE.Matrix4().makeRotationY(Math.PI / 6);
const S = new THREE.Matrix4().makeScale(2, 2, 2);
m.multiplyMatrices(T, R).multiply(S); // T · R · S
// 等价写法,语义更清楚
const position = new THREE.Vector3(10, 0, 5);
const quaternion = new THREE.Quaternion().setFromAxisAngle(
new THREE.Vector3(0, 1, 0), Math.PI / 6
);
m.compose(position, quaternion, new THREE.Vector3(2, 2, 2));
compose 内部固定按 T · R · S 合成,这也是
Object3D 从 position、quaternion、scale
计算自身矩阵的方式。手工拼矩阵时照这个顺序,才不会与非均匀缩放打架。
世界矩阵与投影
// 局部 → 世界:父级世界矩阵乘以自身矩阵
mesh.updateMatrix();
const world = new THREE.Matrix4().multiplyMatrices(
mesh.parent ? mesh.parent.matrixWorld : new THREE.Matrix4(),
mesh.matrix
);
// 世界坐标 → 裁剪空间
const clip = new THREE.Vector4(x, y, z, 1).applyMatrix4(camera.projectionMatrix);
// 再除以 w 得到归一化设备坐标
const ndcX = clip.x / clip.w;
Object3D.matrixWorld 每帧由渲染器自动更新。
需要在渲染循环之外读取时,先调用 updateMatrixWorld(true),
否则拿到的是上一帧的结果。
求逆矩阵的用途
把屏幕点转成世界坐标、把世界坐标转回物体局部坐标,都要用到逆矩阵。 例如点击拾取后想知道命中点在某个组内的局部位置:
const inv = new THREE.Matrix4().copy(group.matrixWorld).invert();
const local = hit.point.clone().applyMatrix4(inv);
缩放为 0 的物体会让矩阵不可逆,求逆结果变成 Infinity 或 NaN,
后续数值会全部污染。发现场景突然整体消失时,先检查有没有零缩放的节点。
大坐标会丢失精度。绝对值过大的坐标会让 32 位浮点精度不足, 把地球半径按米写进矩阵、再叠加毫米级偏移,偏移会被直接吃掉。 常见的做法是整体缩放到公里级单位,或每帧把观察中心平移到原点附近。
矩阵只描述变换。three.js 是渲染库,矩阵里没有投影带、基准面与行列号, 这些信息必须在进入场景前换算成平面坐标。
经纬志(2026)。《Matrix4》。https://www.jingweizhi.com/three/api/matrix4.html(访问日期 2026-11-03)。