Documentation
    Preparing search index...

    Class Matrix4

    Mutable 4×4 matrix stored column-major in a Float64Array(16) (§7b) — the transform type of the scene graph (§7) and of camera projections (§47).

    Element layout — elements[column * 4 + row], the order GPU APIs and WebGL2RenderingContext.uniformMatrix4fv expect; for an affine transform the translation therefore lives in e[12..14]:

    | e[0] e[4] e[ 8] e[12] |
    | e[1] e[5] e[ 9] e[13] |
    | e[2] e[6] e[10] e[14] |
    | e[3] e[7] e[11] e[15] |
    

    Float64Array (not Float32Array) is deliberate: the scene graph does its arithmetic in double precision and narrows to float only at the backend boundary (§62), so accumulated transform error stays below anything the determinism tiers (§33) care about.

    Allocation policy (§7b, plan D7): every method mutates in place and returns this; only Matrix4.clone allocates. Matrix4.decompose produces three results that are not this, so it takes three required out objects and allocates nothing either.

    Change notification (plan D3): every mutator invokes Matrix4.onChanged exactly once, after the last element is written. Writing elements directly bypasses the hook by design — the same rule as v.x = 1 on the vector types.

    Index
    • Constructs the identity matrix.

      Returns Matrix4

    elements: Float64Array

    The sixteen elements in column-major order. The array itself is never replaced, so views taken by a renderer stay valid for the matrix's lifetime; only its contents change.

    onChanged?: () => void

    Optional change hook invoked at the end of every mutator that actually writes elements. Engine-internal: owners install it, user code normally leaves it unset. It is intentionally not copied by Matrix4.copy or Matrix4.clone.

    • Allocates a new matrix with the same elements. The clone has no change hook. This is the only allocating method on the type (§7b).

      Returns Matrix4

    • Sets this matrix to the §7 local transform T · Tp · R · S · Tp⁻¹: translate by position, then rotate and scale about pivot. The pivot therefore affects rotation and scale but not position — a node at position with any pivot still has its pivot point at position.

      Expanding the product, the upper-left 3×3 block is exactly R · S (the rotation columns scaled by scale.x/y/z) and the translation column is

      position + (I − R · S) · pivot
      

      which is how the formula is evaluated here — one pass over raw scalars, no intermediate matrices and no allocation. rotation is assumed unit length (§7b); a non-unit quaternion scales the result by its squared length.

      All four inputs are required: pivot has no default because §7 makes it a first-class field of Transform, and an implicit zero would quietly hide a caller that forgot to pass it. Pass a zero vector for "no pivot".

      Parameters

      Returns this

    • Copies the elements of m into this matrix. The change hook is not copied.

      Parameters

      Returns this

    • Splits this matrix into translation, rotation, and scale, writing each into the corresponding required out object (plan D7) and returning this. This matrix is not modified and its own change hook does not fire; each out object is written through a single set(...), so each of their hooks fires exactly once.

      Two documented limitations, both inherent rather than implementation shortcuts:

      • Pivot is not recovered. compose folds the pivot into the translation column, and infinitely many (position, pivot) pairs produce the same matrix. outPosition therefore receives the composed translation position + (I − R · S) · pivot, which equals position exactly when the pivot is zero. Round-tripping a transform means keeping the pivot alongside the matrix (§7 keeps it on Transform).
      • Scale is assumed positive. Column lengths are magnitudes, so a negative (mirroring) scale reads back as positive with the mirror folded into the returned rotation — which is then not the rotation that was composed. Mirrored transforms cannot be decomposed unambiguously by any method; keep the authored values if you need them back.

      A zero scale component collapses a column, leaving no direction to recover: outRotation is set to the identity rather than NaN (defined here — the same "no-op beats poisoning the frame" reasoning as Quaternion.normalize). Shear (a non-orthogonal upper-left block) is not detected; the returned rotation is then the closest thing the column-normalization produces.

      Parameters

      Returns this

    • Determinant of this matrix. Does not mutate and does not allocate.

      Returns number

    • Reads sixteen column-major elements starting at offset. This is the inverse of reading Matrix4.elements and the entry point used by serialization (§79), by matrixAutoUpdate = false authoring (§7), and by tests that build matrices from raw numbers.

      Parameters

      • values: ArrayLike<number>
      • Optionaloffset: number

      Returns this

    • Resets this matrix to the identity.

      Returns this

    • Inverts this matrix in place (general inverse via the adjugate — no assumption that the matrix is affine, orthogonal, or uniformly scaled, so it also inverts projection matrices, §47's inverseProjectionMatrix).

      Singular behaviour (defined here, plan §1 rule 12): a matrix whose determinant is exactly 0 has no inverse, so this method leaves the elements unchanged, returns this, and does not fire the change hook — the hook reports a change, and nothing changed. Callers that must distinguish "inverted" from "left alone" check m.determinant() !== 0 first. Resetting to the identity was rejected: it silently substitutes a different, plausible-looking transform for the failure, which is the hardest kind of bug to trace. Throwing was rejected because inversion sits on per-frame paths (§43, §47) where an exception would take down the frame.

      A nearly singular matrix still inverts, producing large elements; this method deliberately applies no epsilon, since the right threshold depends on the caller's units (§40).

      Returns this

    • Matrix product this = this * m — this matrix is the left operand, so the combined transform applies m first and this matrix second (the same ordering as Quaternion.multiply, and the ordering the §7 composition formula is written in). Aliasing-safe: m may be this.

      Parameters

      Returns this

    • Sets this matrix to a right-handed orthographic projection (plan D8, §47).

      left/right/bottom/top bound the view volume in camera space with +Y up (§7a); the camera looks down its own −Z axis, so near and far are positive distances in front of the camera, not Z coordinates.

      The name says set because this overwrites every element rather than post-multiplying — see Matrix4.setPerspective.

      depthRange selects the backend's clip-space depth convention and defaults to "negative-one-to-one" (WebGL 2, §120); WebGPU passes "zero-to-one".

      A degenerate box (right === left, top === bottom, far === near) produces non-finite elements rather than throwing — see Matrix4.setPerspective.

      Parameters

      • left: number
      • right: number
      • bottom: number
      • top: number
      • near: number
      • far: number
      • OptionaldepthRange: DepthRange

      Returns this

    • Sets this matrix to a right-handed perspective projection (plan D8, §47).

      The camera looks down its own −Z axis with +Y up (§7a), so near and far are positive distances in front of the camera, not Z coordinates: 0 < near < far. fovYRadians is the full vertical field of view in radians (§7a — there is no degree overload) and aspect is width ÷ height.

      The name says set because this overwrites every element rather than post-multiplying — the same reason identity() is a mutator, and the reason it is not called perspective().

      depthRange selects the backend's clip-space depth convention and defaults to "negative-one-to-one" (WebGL 2, §120); WebGPU passes "zero-to-one". Nothing above this method ever sees the difference (§7a).

      Degenerate arguments (near === far, aspect === 0, a field of view at or beyond π) produce non-finite or meaningless elements rather than throwing: the math package validates nothing, and camera types (§47) are the layer that reports configuration errors.

      Parameters

      • fovYRadians: number
      • aspect: number
      • near: number
      • far: number
      • OptionaldepthRange: DepthRange

      Returns this