数学基元
目的与范围
本文档描述了构成 Three.js 基础层的数学基元类。这些类为 3D 图形计算提供了基本的数据结构和操作,包括向量、矩阵、四元数、包围体和空间查询。数学基元在整个库中用于变换、光线投射、碰撞检测和几何计算。
关于这些基元如何与场景图对象集成,请参阅 场景图与 Object3D。关于它们在光线投射系统中的使用,请参阅 光线投射与对象拾取。
架构概述
数学基元作为 Three.js 中最低级别的计算层,提供高级系统所依赖的不可变数学操作。所有数学基元类都遵循一致的 API 模式:按组件构造、返回 this 的可链式调用变异方法、以及用于只读操作的独立输出参数。
向量类
Vector2
Vector2 表示具有 x 和 y 分量的 2D 向量,用于 UV 坐标、屏幕位置和 2D 几何操作。该类为 x 和 y 分别提供了 width 和 height 别名。
关键操作:
| Operation | Method | Description |
|---|---|---|
| Arithmetic | add(), sub(), multiply(), divide() | Component-wise operations |
| Scalar | addScalar(), multiplyScalar(), divideScalar() | Uniform scaling |
| Length | length(), lengthSq(), normalize() | Magnitude operations |
| Distance | distanceTo(), distanceToSquared() | Euclidean distance |
| Interpolation | lerp(), lerpVectors() | Linear interpolation |
| Clamping | clamp(), clampScalar(), clampLength() | Constraint operations |
Vector3
Vector3 是最常用的向量类,表示 3D 点、方向和位移。它支持 3D 几何的综合操作,包括叉积、投影以及通过矩阵和四元数的变换。
变换方法:
applyMatrix3(m) - Multiply by 3x3 matrix
applyMatrix4(m) - Multiply by 4x4 matrix with perspective division
applyQuaternion(q) - Rotate by quaternion
applyEuler(euler) - Rotate by Euler angles
applyAxisAngle(axis, angle) - Rotate around axis坐标系转换:
setFromSpherical(s) - From spherical coordinates (radius, phi, theta)
setFromSphericalCoords(r, φ, θ) - Direct spherical conversion
setFromCylindrical(c) - From cylindrical coordinates
setFromCylindricalCoords(r, θ, y) - Direct cylindrical conversion矩阵提取:
setFromMatrixPosition(m) - Extract translation from Matrix4
setFromMatrixScale(m) - Extract scale from Matrix4
setFromMatrixColumn(m, i) - Extract column i from Matrix4The implementation uses a reusable _quaternion instance src/math/Vector3.js1257 to avoid allocations during transformations like applyEuler() src/math/Vector3.js388-392
Vector4
Vector4 表示用于 4D 变换和着色器操作的齐次坐标 (x, y, z, w)。w 分量默认为 1,以启用正确的透视除法。与 Vector2 一样,它为 z 和 w 分量提供了 width 和 height 别名。
变换类
Matrix4
Matrix4 表示以列优先顺序存储在 elements 数组 src/math/Matrix4.js82-89 中的 4×4 变换矩阵。构造函数和 set() 方法为方便起见接受行优先参数,但内部存储为列优先以兼容 GPU。
分解图示:
关键变换工厂方法:
| Method | Purpose |
|---|---|
| makeTranslation(x, y, z) | Pure translation matrix |
| makeRotationX/Y/Z(θ) | Axis-aligned rotation |
| makeRotationAxis(axis, angle) | Arbitrary axis rotation |
| makeRotationFromEuler(euler) | Rotation from Euler angles (6 orders) |
| makeRotationFromQuaternion(q) | Rotation from quaternion |
| makeScale(x, y, z) | Non-uniform scaling |
| makeShear(xy, xz, yx, yz, zx, zy) | Shear transformation |
| makePerspective(...) | Perspective projection matrix |
| makeOrthographic(...) | Orthographic projection matrix |
组合与分解:
compose(position, quaternion, scale) - Build TRS matrix
decompose(position, quaternion, scale) - Extract TRS componentsThe compose() method src/math/Matrix4.js1000-1034 directly computes the matrix elements from quaternion components, avoiding intermediate matrix multiplications for performance.
Matrix3
Matrix3 表示 3×3 矩阵,主要用于法线变换和纹理坐标变换。与 Matrix4 一样,它使用列优先存储 src/math/Matrix3.js62-68 和行优先输入。
getNormalMatrix(matrix4) 方法 src/math/Matrix3.js367-386 提取上 3×3 矩阵,转置并求逆,以生成一个在非均匀缩放下正确变换表面法线的法线变换矩阵。
Quaternion
Quaternion 表示为 4 分量单位向量 (x, y, z, w) 的旋转,其中 w 是标量分量。Three.js 期望四元数保持归一化以确保正确行为。该类提供静态方法 slerpFlat() 和 multiplyQuaternionsFlat() src/math/Quaternion.js60-163,用于在不分配对象的情况下对扁平数组进行操作,用于动画系统。
旋转转换方法:
setFromEuler(euler) - Convert from Euler angles
setFromAxisAngle(axis, angle) - Convert from axis-angle
setFromRotationMatrix(m) - Extract from Matrix4 upper 3x3
setFromUnitVectors(vFrom, vTo) - Rotation between two directionssetFromEuler() 实现 src/math/Quaternion.js301-373 处理所有六种旋转顺序 (XYZ, YXZ, ZXY, ZYX, YZX, XZY),并进行了优化的三角函数计算。
插值:
slerp(q, t) - Spherical linear interpolation
rotateTowards(q, step) - Rotation with angular step limitEuler
Euler 表示为三个角度 (x, y, z) 的旋转,单位为弧度,并具有指定的旋转顺序。默认顺序为 'XYZ' src/math/Euler.js35,存储在 DEFAULT_ORDER 静态常量中。
旋转顺序: XYZ, YXZ, ZXY, ZYX, YZX, XZY
该类使用 getter/setter 属性 src/math/Euler.js59-127,在修改时调用 _onChangeCallback(),从而在 Object3D 变换中使用欧拉角时实现自动更新。
转换方法:
setFromRotationMatrix(m, order) - Extract from Matrix4
setFromQuaternion(q, order) - Convert from Quaternion空间查询类
包围体
Box3
Box3 表示具有 min 和 max Vector3 角点的轴对齐包围盒 (AABB)。空盒子表示为 min = (+∞, +∞, +∞) 和 max = (−∞, −∞, −∞) src/math/Box3.js14
构造方法:
| Method | Source |
|---|---|
| setFromArray(array) | Flat array of xyz coordinates |
| setFromBufferAttribute(attribute) | BufferAttribute position data |
| setFromPoints(points) | Array of Vector3 |
| setFromObject(object, precise) | Object3D hierarchy bounds |
| setFromCenterAndSize(center, size) | Center point and dimensions |
expandByObject() 方法 src/math/Box3.js298-380 处理两种模式:
- 精确模式: 将每个顶点变换到世界空间以获得紧密边界 src/math/Box3.js314-331
- 快速模式: 将局部包围体变换到世界空间 src/math/Box3.js333-366
相交测试:
containsPoint(point) - Point containment
containsBox(box) - Box containment
intersectsBox(box) - Box-box intersection
intersectsSphere(sphere) - Box-sphere intersection
intersectsPlane(plane) - Box-plane intersection
intersectsTriangle(triangle) - Box-triangle intersection (SAT)三角形相交 src/math/Box3.js521-572 使用分离轴定理 (SAT),具有 13 个潜在分离轴。
Sphere
Sphere 表示由 center Vector3 和 radius 数值定义的包围球。默认半径 -1 表示空球 src/math/Sphere.js20
包围球生成:
setFromPoints(points, optionalCenter) - Ritter's algorithm for approximate boundsRitter 算法实现 src/math/Sphere.js65-134 迭代扩展球体以包含所有点。
相交测试:
containsPoint(point) - Point containment
intersectsSphere(sphere) - Sphere-sphere intersection
intersectsBox(box) - Sphere-box intersection
intersectsPlane(plane) - Sphere-plane intersectionRay
Ray 表示具有 origin 和归一化 direction Vector3 的无限射线。射线被 Raycaster 类用于拾取和相交测试。
核心操作:
at(t, target) - Point at distance t
closestPointToPoint(point, target) - Nearest point on ray
distanceToPoint(point) - Distance to point
distanceSqToSegment(v0, v1, ...) - Distance to line segment相交方法:
intersectBox(box, target) - Ray-box intersection
intersectSphere(sphere, target) - Ray-sphere intersection
intersectPlane(plane, target) - Ray-plane intersection
intersectTriangle(a, b, c, backfaceCulling, target) - Ray-triangle (Möller-Trumbore)The triangle intersection src/math/Ray.js234-315 implements the Möller-Trumbore algorithm, computing barycentric coordinates for texture interpolation.
Plane
Plane 表示 Hessian 法线形式的无限平面,具有单位 normal Vector3 和标量 constant。平面方程为:normal · point + constant = 0。
操作:
distanceToPoint(point) - Signed distance (negative = back)
distanceToSphere(sphere) - Signed distance to sphere
projectPoint(point, target) - Orthogonal projection
intersectLine(line, target) - Line-plane intersectioncoplanarPoint() 方法 src/math/Plane.js187-191 通过将法线乘以 -constant 返回平面上的一个点。
Frustum
Frustum 表示视锥体,作为六个 Plane 对象存储在 planes 数组 src/math/Frustum.js23-30 中。规范平面顺序为:right、left、bottom、top、near、far。
构造:
setFromProjectionMatrix(m, coordinateSystem)这从投影矩阵 src/math/Frustum.js44-124 中提取六个视锥体平面,并对 WebGL 和 WebGPU 坐标系统进行特殊处理。
剔除测试:
intersectsObject(object) - Object3D visibility
intersectsSprite(sprite) - Sprite visibility
intersectsSphere(sphere) - Sphere-frustum intersection
intersectsBox(box) - Box-frustum intersection
containsPoint(point) - Point containmentintersectsObject() 方法 src/math/Frustum.js126-165 首先测试包围球,然后可选择执行更精确的盒子测试。
Triangle
Triangle 表示具有三个 Vector3 角点 (a, b, c) 的几何三角形。它为整个库中使用的三角形操作提供静态实用方法。
静态实用方法:
| Method | Purpose |
|---|---|
| getNormal(a, b, c, target) | Compute face normal |
| getBarycoord(point, a, b, c, target) | Barycentric coordinates |
| containsPoint(point, a, b, c) | Point-in-triangle test |
| getInterpolation(point, p1, p2, p3, v1, v2, v3, target) | Barycentric interpolation |
| getInterpolatedAttribute(attr, i1, i2, i3, barycoord, target) | Attribute interpolation |
| isFrontFacing(a, b, c, direction) | Backface culling test |
这些静态方法被光线投射 src/objects/Mesh.js440-493 使用,用于计算相交细节,包括 UV 坐标、法线和面索引。
实例方法:
getArea() - Triangle area (half cross product magnitude)
getMidpoint(target) - Centroid
getPlane(target) - Plane containing triangle
closestPointToPoint(p, target) - Nearest point on triangle集成模式
Object3D 变换管线
Object3D 保持同步的欧拉角和四元数表示 src/core/Object3D.js100-200。当 rotation 被修改时,quaternion 通过回调自动更新,反之亦然。matrix 在 updateMatrix() 期间从 position、quaternion 和 scale 重新计算。
光线投射集成
光线投射系统使用多阶段剔除方法 src/objects/Mesh.js226-270:
- 包围球测试 在世界空间 src/objects/Mesh.js236-251
- 包围盒测试 在局部空间 src/objects/Mesh.js260-264
- 逐三角形相交 使用 Möller-Trumbore src/math/Ray.js234-315
内存管理模式
所有数学基元类都遵循一致的内存管理模式以最小化分配:
输出参数模式:
// BAD: Creates new object on each call
const center = box.getCenter();
// GOOD: Reuses existing object
const center = new Vector3();
box.getCenter(center);计算派生值的方法接受用于输出的 target 参数 src/math/Box3.js219-222。这可以在动画循环等性能关键路径中实现无分配操作。
单例重用模式:
// Module-level reusable instances
const _vector = /*@__PURE__*/ new Vector3();
const _matrix = /*@__PURE__*/ new Matrix4();内部实现使用模块作用域的临时对象 src/math/Vector3.js1256-1257 进行中间计算,避免方法内的重复分配。