2 Matrices
dxtr edited this page 2026-10-14 13:46:25 +02:00

Matrices

mat3 and mat4 are 3x3 and 4x4 matrices, stored column by column, and dmat3 and dmat4 the same of doubles; see Doubles. mat3x2, the 2D affine transform, has a page of its own, 2D Transforms. Read Conventions for the storage and the multiplication order. Functions that return a matrix or a vector take an optional last argument, result; see Results and Allocation.

Making matrices

(gm:mat4-identity)                 ; the identity
(gm:make-mat3 1 2 3 4 5 6 7 8 9)   ; columns (1 2 3), (4 5 6) and (7 8 9)

gm:make-mat3 and gm:make-mat4 take their 9 or 16 elements column by column, as GLSL's constructors do. The transforms on Transforms and Cameras make the usual matrices.

Elements

mref reads the element at a row and a column, counting from 0, of a matrix of either precision, and setf writes it, as any real:

(let ((m (gm:make-mat3 1 2 3 4 5 6 7 8 9)))
  (list (gm:mref m 0 1) (gm:mref m 1 0)))
;; => (4.0 2.0)

Operations

Each exists for both sizes, as mat3-... and mat4-...:

Function Returns
mat4* The product A B: the transform that applies B, then A.
mat4*vec4, mat3*vec3 The matrix times a column vector.
mat4-transpose The transpose.
mat4-determinant The determinant, a single float.
mat4-inverse The inverse. Signals gmath-error for a singular matrix.
mat4-copy A copy.
mat4-approx= True if no element differs by more than an epsilon, 1e-5 by default.
(gm:mat4-inverse (gm:mat4-translation (gm:make-vec3 :x 1 :y 2 :z 3)))
;; => #(1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 -1.0 -2.0 -3.0 1.0)
(gm:mat4-determinant (gm:mat4-scaling (gm:make-vec3 :x 2 :y 3 :z 4)))
;; => 24.0
(gm:mat4-approx= (gm:mat4* (gm:mat4-rotation-y 1.0) (gm:mat4-inverse (gm:mat4-rotation-y 1.0)))
                 (gm:mat4-identity))
;; => T

A vec4 with a W of 1 is a point, which translation moves; with a W of 0, a direction, which it does not:

(let ((move (gm:mat4-translation (gm:make-vec3 :x 1 :y 2 :z 3))))
  (list (gm:mat4*vec4 move (gm:make-vec4 :w 1))     ; a point, at the origin
        (gm:mat4*vec4 move (gm:make-vec4 :x 1))))   ; a direction, along X
;; => (#(1.0 2.0 3.0 1.0) #(1.0 0.0 0.0 0.0))

For vec3 points and directions, mat4-transform-point and mat4-transform-direction do the same without a W; see Transforms and Cameras.

From a 4x4 to a 3x3

  • mat3-from-mat4 takes the upper left 3x3 of a mat4: its rotation and scale, without its translation.
  • mat3-normal-matrix returns the matrix that transforms normals for a model matrix: the inverse transpose of its upper left 3x3, which keeps normals perpendicular to surfaces under a scale that differs between axes. It signals gmath-error if that 3x3 is singular.
(gm:mat3-normal-matrix (gm:mat4-scaling (gm:make-vec3 :x 2 :y 1 :z 1)))
;; => #(0.5 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0)

A model stretched twice as wide has its normals' X halved, so that they still stand straight on its surfaces once normalised.