// Simple 4×4 matrix helpers (column-major) — exported so consumers can build // their own orbit / trackball controls. export function mat4Perspective( fov: number, aspect: number, near: number, far: number, ): Float32Array { const f = 1.0 / Math.tan(fov / 2); const nf = 1 / (near - far); // prettier-ignore return new Float32Array([ f / aspect, 0, 0, 0, 0, f, 0, 0, 0, 0, (far + near) * nf, -1, 0, 0, 2 * far * near * nf, 0, ]); } export function mat4Multiply(a: Float32Array, b: Float32Array): Float32Array { const out = new Float32Array(16); for (let i = 0; i < 4; i++) { for (let j = 0; j < 4; j++) { out[j * 4 + i] = a[0 * 4 + i] * b[j * 4 + 0] + a[1 * 4 + i] * b[j * 4 + 1] + a[2 * 4 + i] * b[j * 4 + 2] + a[3 * 4 + i] * b[j * 4 + 3]; } } return out; } export function mat4RotateY(angle: number): Float32Array { const c = Math.cos(angle), s = Math.sin(angle); // prettier-ignore return new Float32Array([ c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1, ]); } export function mat4RotateZ(angle: number): Float32Array { const c = Math.cos(angle), s = Math.sin(angle); // prettier-ignore return new Float32Array([ c, s, 0, 0, -s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, ]); } export function mat4RotateX(angle: number): Float32Array { const c = Math.cos(angle), s = Math.sin(angle); // prettier-ignore return new Float32Array([ 1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, ]); } export function mat4Ortho( left: number, right: number, bottom: number, top: number, near: number, far: number, ): Float32Array { const lr = 1 / (left - right); const bt = 1 / (bottom - top); const nf = 1 / (near - far); // prettier-ignore return new Float32Array([ -2 * lr, 0, 0, 0, 0, -2 * bt, 0, 0, 0, 0, 2 * nf, 0, (left + right) * lr, (top + bottom) * bt, (far + near) * nf, 1, ]); } export function mat4Translate(x: number, y: number, z: number): Float32Array { // prettier-ignore return new Float32Array([ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1, ]); }