Matrix & Vector Library

The scripting engine includes a complete linear algebra library available as the global Matrix namespace. All types extend Float32Array for zero-copy interop with the image processing pipeline.

Based on glMatrix — rewritten as an object-oriented API with chainable methods instead of the original functional style.

Mat3 / Mat4 storage layout — column-major reference card generated by the demo_matrix_toolbox script

Visual reference, rendered live: the image above is the output of the demo_matrix_toolbox example — the same engine documents itself. The flat backing array stores columns, not rows; translation lives at [6]/[7] for Mat3 and [12]/[13]/[14] for Mat4. Open the demo in the Playground to tweak the SVG output and rerender at any scale.

Vectors

Vec2 — 2D Vector

const a = new Matrix.Vec2(3, 4);
const b = Matrix.Vec2.fromValues(1, 0);

a.add(b);                    // [4, 4]
a.normalize();               // unit vector
a.dot(b);                    // dot product
a.cross(b);                  // scalar (z component)
a.distance(b);               // euclidean distance
a.lerp(b, 0.5);              // linear interpolation
a.rotate(Matrix.Vec2.fromValues(0, 0), Math.PI / 4);  // rotate around origin
a.transformMat3(matrix);     // apply 3x3 transform

Key methods: add, subtract, multiply, divide, scale, normalize, dot, cross, lerp, distance, length, angle, rotate, transformMat2, transformMat2d, transformMat3, transformMat4

Vec3 — 3D Vector

const v = new Matrix.Vec3(1, 2, 3);
const up = Matrix.Vec3.fromValues(0, 1, 0);

v.cross(up);                 // cross product
v.transformMat4(mvp);        // apply model-view-projection
v.transformQuat(rotation);   // apply quaternion rotation
v.rotateX(origin, Math.PI);  // rotate around X axis

Additional methods: rotateX, rotateY, rotateZ, transformQuat

Vec4 — 4D Vector

Same interface as Vec3 with a w component. Used for homogeneous coordinates and color values.


Matrices

Mat2 — 2x2 Matrix

const m = new Matrix.Mat2();       // identity
m.rotate(Math.PI / 6);            // rotate 30°
m.scale(Matrix.Vec2.fromValues(2, 1));  // scale x by 2

Mat2d — 2x3 Affine Transform

const m = new Matrix.Mat2d();      // identity
m.translate(Matrix.Vec2.fromValues(100, 50));
m.rotate(Math.PI / 4);
m.scale(Matrix.Vec2.fromValues(0.5, 0.5));

Compact representation of 2D affine transforms [a, b, c, d, tx, ty].

Mat3 — 3x3 Matrix

The workhorse for 2D image transforms, perspective mapping, and normal matrices.

const m = new Matrix.Mat3();
m.translate(Matrix.Vec2.fromValues(100, 200));
m.rotate(0.5);
m.scale(Matrix.Vec2.fromValues(2, 2));

// Projection matrix for 2D rendering
const proj = new Matrix.Mat3();
proj.projection(800, 600);

// Derive normal matrix from a 4x4 model-view
const normal = new Matrix.Mat3();
normal.normalFromMat4(modelView);

// Matrix operations
const det = m.determinant();
m.invert();                  // returns null if singular
m.transpose();

Key methods: multiply, translate, rotate, scale, invert, transpose, determinant, projection, fromTranslation, fromRotation, fromScaling, fromMat2d, fromQuat, normalFromMat4

Mat4 — 4x4 Matrix

Full 3D transform matrix with camera and projection support.

const model = new Matrix.Mat4();
model.translate(Matrix.Vec3.fromValues(0, 1, -5));
model.rotateY(Math.PI / 3);
model.scale(Matrix.Vec3.fromValues(2, 2, 2));

// Perspective projection
const proj = new Matrix.Mat4();
proj.perspectiveNO(Math.PI / 4, 16 / 9, 0.1, 100);

// Orthographic projection
const ortho = new Matrix.Mat4();
ortho.orthoNO(-1, 1, -1, 1, 0.1, 100);

// Camera
const view = new Matrix.Mat4();
view.lookAt(
  Matrix.Vec3.fromValues(0, 5, 10),   // eye
  Matrix.Vec3.fromValues(0, 0, 0),    // center
  Matrix.Vec3.fromValues(0, 1, 0)     // up
);

// Decompose
const rotation = new Matrix.Quat();
const translation = new Matrix.Vec3();
const scale = new Matrix.Vec3();
model.decompose(rotation, translation, scale);

Projection methods: perspectiveNO, perspectiveZO, orthoNO, orthoZO, frustum, lookAt Transform methods: translate, rotate, rotateX/Y/Z, scale, fromRotationTranslation, fromRotationTranslationScale


Quaternions

Quat — Unit Quaternion

Represents rotations without gimbal lock.

const q = new Matrix.Quat();          // identity [0, 0, 0, 1]

// From axis-angle
q.setAxisAngle(Matrix.Vec3.fromValues(0, 1, 0), Math.PI / 2);

// From Euler angles (degrees)
q.fromEuler(45, 0, 90);

// From rotation matrix
q.fromMat3(rotMatrix);

// Spherical interpolation (smooth rotation blending)
const a = new Matrix.Quat().fromEuler(0, 0, 0);
const b = new Matrix.Quat().fromEuler(0, 90, 0);
a.slerp(b, 0.5);            // halfway rotation

// Apply to vector
const v = new Matrix.Vec3(1, 0, 0);
v.transformQuat(q);

Quat2 — Dual Quaternion

Represents rigid transformations (rotation + translation) in a single 8-component type.


Homography — Perspective Image Mapping

The engine provides a built-in homography solver for mapping images onto arbitrary quadrilaterals.

stampAt — High-Level API

// Place an image onto 4 destination corners
const canvas = Engine.createImage(800, 600);
const photo = Engine.loadImage("INPUT");

// Define where the photo corners land on the canvas
canvas.stampAt(photo, [
  { x: 100, y:  80 },    // top-left
  { x: 500, y:  60 },    // top-right
  { x: 520, y: 400 },    // bottom-right
  { x: 120, y: 380 },    // bottom-left
], 1.0, BlendMode.Over);

warpPerspective — Low-Level API

// Compute your own homography matrix
const matrix = computeMyTransform();  // 9-element array, row-major

img.warpPerspective(
  outputWidth, outputHeight,
  matrix,
  Interp.Bilinear     // 0=Nearest, 1=Bilinear, 2=Bicubic
);

Practical Example: 3D Cube

// Map an image onto a cube face using perspective transform
const face = photo.clone();
const srcCorners = [
  [0, 0], [photo.width, 0],
  [photo.width, photo.height], [0, photo.height]
];
const dstCorners = [
  [150, 100], [350, 120],
  [340, 350], [160, 330]
];
face.stampAt(photo, dstCorners.map(([x,y]) => ({x, y})));

See demo_cube.js and demo_drum.js in the examples for complete 3D projection implementations with Lambertian shading.