Documentation
    Preparing search index...

    Class Matrix3

    Mutable 3×3 matrix stored column-major in a Float64Array(9) (§7b).

    Element layout — elements[column * 3 + row], the same order GPU APIs and WebGL2RenderingContext.uniformMatrix3fv expect:

    | e[0] e[3] e[6] |
    | e[1] e[4] e[7] |
    | e[2] e[5] e[8] |
    

    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 Matrix3.clone allocates. Scalar queries (Matrix3.determinant) never allocate and never mutate.

    Change notification (plan D3): every mutator invokes Matrix3.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
    elements: Float64Array

    The nine 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 Matrix3.copy or Matrix3.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 Matrix3

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

      Parameters

      Returns this

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

      Returns number

    • Reads nine column-major elements starting at offset. This is the inverse of reading Matrix3.elements and the entry point used by serialization (§79) and by tests that build matrices from raw numbers.

      Parameters

      • values: ArrayLike<number>
      • offset: number = 0

      Returns this

    • Resets this matrix to the identity.

      Returns this

    • Inverts this matrix in place (general inverse via the adjugate — no assumption of orthogonality or affinity).

      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). Aliasing-safe: m may be this.

      Parameters

      Returns this

    • Copies the upper-left 3×3 of a column-major Matrix4 into this matrix. Translation (e[12..14]) and the homogeneous row are ignored — the linear part that transforms directions, which is what a normal matrix starts from.

      Always writes and always fires the change hook: even a copy of the identity is a write.

      Parameters

      Returns this

    • Builds the normal matrix of m: transpose(inverse(upper 3×3)), the linear map that keeps object-space normals perpendicular to surfaces after a non-uniform scale (§68). Translation does not participate.

      The inverse is Matrix3.invert's general inverse, so a singular upper 3×3 (determinant exactly 0) is the same no-op: this matrix is left unchanged, the change hook does not fire, and the method returns this. Callers that must distinguish "built" from "left alone" check the upper 3×3's determinant first — the same rule invert documents.

      The change hook fires once, after the last write, never per intermediate copy / invert / transpose. That is plan D3: one mutation, one notification.

      Parameters

      Returns this

    • Transposes this matrix in place. Diagonal elements stay put; the three off-diagonal pairs swap. Fires the change hook once, after the last write.

      Returns this