Math Primitives
Purpose and Scope
This document describes the mathematical primitive classes that form the foundational layer of Three.js. These classes provide essential data structures and operations for 3D graphics computations including vectors, matrices, quaternions, bounding volumes, and spatial queries. Math primitives are used throughout the library for transformations, raycasting, collision detection, and geometric calculations.
For information about how these primitives integrate with scene graph objects, see Scene Graph & Object3D. For their use in raycasting systems, see Raycasting & Object Picking.
Architecture Overview
Math primitives serve as the lowest-level computational layer in Three.js, providing immutable mathematical operations that higher-level systems depend upon. All math primitive classes follow a consistent API pattern: component-wise construction, chainable mutation methods returning this, and separate output parameters for read-only operations.
Vector Classes
Vector2
Vector2 represents a 2D vector with x and y components, used for UV coordinates, screen positions, and 2D geometric operations. The class provides aliases width and height for x and y respectively.
Key Operations:
| 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 is the most frequently used vector class, representing 3D points, directions, and displacements. It supports comprehensive operations for 3D geometry including cross products, projections, and transformations by matrices and quaternions.
Transformation Methods:
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 axisCoordinate System Conversions:
setFromSpherical(s) - From spherical coordinates (radius, phi, theta)
setFromSphericalCoords(r, φ, θ) - Direct spherical conversion
setFromCylindrical(c) - From cylindrical coordinates
setFromCylindricalCoords(r, θ, y) - Direct cylindrical conversionMatrix Extraction:
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 represents homogeneous coordinates (x, y, z, w) used for 4D transformations and shader operations. The w component defaults to 1, enabling proper perspective division. Like Vector2, it provides width and height aliases for the z and w components.
Transformation Classes
Matrix4
Matrix4 represents 4x4 transformation matrices stored in column-major order in the elements array src/math/Matrix4.js82-89 The constructor and set() method accept row-major arguments for convenience, but internal storage is column-major for GPU compatibility.
Decomposition Diagram:
Key Transformation Factories:
| 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 |
Composition and Decomposition:
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 represents 3x3 matrices, primarily used for normal transformations and texture coordinate transformations. Like Matrix4, it uses column-major storage src/math/Matrix3.js62-68 with row-major input.
The getNormalMatrix(matrix4) method src/math/Matrix3.js367-386 extracts the upper 3x3, transposes it, and inverts it to produce a normal transformation matrix that correctly transforms surface normals under non-uniform scaling.
Quaternion
Quaternion represents rotations as a 4-component unit vector (x, y, z, w) where w is the scalar component. Three.js expects quaternions to remain normalized for correct behavior. The class provides static methods slerpFlat() and multiplyQuaternionsFlat() src/math/Quaternion.js60-163 for operating on flat arrays without object allocation, used in animation systems.
Rotation Conversion Methods:
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 directionsThe setFromEuler() implementation src/math/Quaternion.js301-373 handles all six rotation orders (XYZ, YXZ, ZXY, ZYX, YZX, XZY) with optimized trigonometric calculations.
Interpolation:
slerp(q, t) - Spherical linear interpolation
rotateTowards(q, step) - Rotation with angular step limitEuler
Euler represents rotations as three angles (x, y, z) in radians with a specified rotation order. The default order is 'XYZ' src/math/Euler.js35 stored in the DEFAULT_ORDER static constant.
Rotation Orders: XYZ, YXZ, ZXY, ZYX, YZX, XZY
The class uses getter/setter properties src/math/Euler.js59-127 that invoke _onChangeCallback() on modification, enabling automatic updates when Euler angles are used in Object3D transformations.
Conversion Methods:
setFromRotationMatrix(m, order) - Extract from Matrix4
setFromQuaternion(q, order) - Convert from QuaternionSpatial Query Classes
Bounding Volumes
Box3
Box3 represents axis-aligned bounding boxes (AABB) with min and max Vector3 corners. Empty boxes are represented with min = (+∞, +∞, +∞) and max = (−∞, −∞, −∞) src/math/Box3.js14
Construction Methods:
| 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 |
The expandByObject() method src/math/Box3.js298-380 handles two modes:
- Precise mode: Transforms each vertex to world space for tight bounds src/math/Box3.js314-331
- Fast mode: Transforms local bounding volume to world space src/math/Box3.js333-366
Intersection Tests:
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)The triangle intersection src/math/Box3.js521-572 uses the Separating Axis Theorem (SAT) with 13 potential separating axes.
Sphere
Sphere represents bounding spheres defined by a center Vector3 and radius number. The default radius of -1 indicates an empty sphere src/math/Sphere.js20
Bounding Sphere Generation:
setFromPoints(points, optionalCenter) - Ritter's algorithm for approximate boundsThe Ritter algorithm implementation src/math/Sphere.js65-134 iteratively expands the sphere to encompass all points.
Intersection Tests:
containsPoint(point) - Point containment
intersectsSphere(sphere) - Sphere-sphere intersection
intersectsBox(box) - Sphere-box intersection
intersectsPlane(plane) - Sphere-plane intersectionRay
Ray represents an infinite ray with an origin and normalized direction Vector3. Rays are used by the Raycaster class for picking and intersection tests.
Core Operations:
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 segmentIntersection Methods:
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 represents an infinite plane in Hessian normal form with a unit normal Vector3 and scalar constant. The plane equation is: normal · point + constant = 0.
Operations:
distanceToPoint(point) - Signed distance (negative = back)
distanceToSphere(sphere) - Signed distance to sphere
projectPoint(point, target) - Orthogonal projection
intersectLine(line, target) - Line-plane intersectionThe coplanarPoint() method src/math/Plane.js187-191 returns a point on the plane by scaling the normal by -constant.
Frustum
Frustum represents a view frustum as six Plane objects stored in the planes array src/math/Frustum.js23-30 The canonical plane order is: right, left, bottom, top, near, far.
Construction:
setFromProjectionMatrix(m, coordinateSystem)This extracts the six frustum planes from a projection matrix src/math/Frustum.js44-124 with special handling for WebGL vs WebGPU coordinate systems.
Culling Tests:
intersectsObject(object) - Object3D visibility
intersectsSprite(sprite) - Sprite visibility
intersectsSphere(sphere) - Sphere-frustum intersection
intersectsBox(box) - Box-frustum intersection
containsPoint(point) - Point containmentThe intersectsObject() method src/math/Frustum.js126-165 first tests the bounding sphere, then optionally performs a more precise box test.
Triangle
Triangle represents a geometric triangle with three Vector3 corners (a, b, c). It provides static utility methods for triangle operations used throughout the library.
Static Utility Methods:
| 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 |
These static methods are used by raycasting src/objects/Mesh.js440-493 to compute intersection details including UV coordinates, normals, and face indices.
Instance Methods:
getArea() - Triangle area (half cross product magnitude)
getMidpoint(target) - Centroid
getPlane(target) - Plane containing triangle
closestPointToPoint(p, target) - Nearest point on triangleIntegration Patterns
Object3D Transformation Pipeline
Object3D maintains synchronized Euler and Quaternion representations src/core/Object3D.js100-200 When rotation is modified, quaternion updates automatically via callbacks, and vice versa. The matrix is recomputed from position, quaternion, and scale during updateMatrix().
Raycasting Integration
The raycasting system uses a multi-stage culling approach src/objects/Mesh.js226-270:
- Bounding sphere test in world space src/objects/Mesh.js236-251
- Bounding box test in local space src/objects/Mesh.js260-264
- Per-triangle intersection using Möller-Trumbore src/math/Ray.js234-315
Memory Management Pattern
All math primitive classes follow a consistent memory management pattern to minimize allocations:
Output Parameter Pattern:
// BAD: Creates new object on each call
const center = box.getCenter();
// GOOD: Reuses existing object
const center = new Vector3();
box.getCenter(center);Methods that compute derived values accept a target parameter for output src/math/Box3.js219-222 This enables allocation-free operations in performance-critical paths like animation loops.
Singleton Reuse Pattern:
// Module-level reusable instances
const _vector = /*@__PURE__*/ new Vector3();
const _matrix = /*@__PURE__*/ new Matrix4();Internal implementations use module-scoped temporary objects src/math/Vector3.js1256-1257 for intermediate calculations, avoiding repeated allocations within methods.