OpenGL Mathematics (GLM) for Racket (original) (raw)

8.15

OpenGL Mathematics (GLM) for Racket is a Racket port ofOpenGL Mathematics (GLM), a mathematics library for graphics software based on the OpenGL Shading Language (GLSL) specifications.

GLM for Racket provides GLM’s core functions and data types along with support for popular Racket idioms such as sequence-based looping, variadic keyword-based constructors, and match-based de-structuring.

1 Swizzling
2 GLM Core
2.1 Vector Types
2.1.1 Single Precision Floats
2.1.1.1 vec Types
2.1.2 Double Precision Floats
2.1.2.1 dvec Types
2.1.3 Signed Integers
2.1.3.1 ivec Types
2.1.4 Unsigned Integers
2.1.4.1 uvec Types
2.1.5 Booleans
2.1.5.1 bvec Types
2.2 Matrix Types
2.2.1 Single Precision Floats
2.2.1.1 mat Types
2.2.2 Double Precision Floats
2.2.2.1 dmat Types

1 Swizzling🔗

The glm/swizzle meta-language customizes the syntax of identifiers to enable component swizzling.

#lang glm/swizzle racket/base
(define v (vec4 1 2 3 4))
v.x ;; expands to (vec-ref v 0)
v.xy ;; expands to (vec2 (vec-ref v 0) (vec-ref v 1))

All of the bindings exported by glm/vector-types are available whenever swizzling is enabled.

2 GLM Core🔗

This module re-exports glm/matrix-types andglm/vector-types.

2.1 Vector Types🔗

This module re-exports glm/bvec, glm/dvec,glm/ivec, glm/uvec, andglm/vec.

2.1.1 Single Precision Floats🔗

A vector is an array of 32-bit floating point componentvalues.

Two vectors are equal? iff they have the same number of componentsand each pair of consecutive components are =.

Returns #t if v is a vector.

Allocates a vector with the xs as its components.

> (vec 1 2/3 4.5 -670000000.0)
(vec 1 0.67 4.5 -670000000)

The components of any vectors in the xs are spliced into the finalcomponent list.

> (vec (vec 1 2) 3 4 (vec 5 6 (vec 7 8)) 9)
(vec 1 2 3 4 5 6 7 8 9)

When both len and fill are numbers, the final component list can have any number of values. If its length exceeds len, the excess values are truncated; otherwise, any missing values default to fill.

> (vec #:length 5 1 2 3)
(vec 1 2 3 0 0)
> (vec #:length 5 1 2 3 4 5 6 7)
(vec 1 2 3 4 5)

When only len is a number, the final component list must have exactlylen values. Giving more or less than len values is an error.

> (vec #:length 3 #:fill 'no-fill (vec 1 2) (vec 3 4))
vec3: contract violation
expected: exactly 3 values
given: '(1.0 2.0 3.0 4.0)
> (vec #:length 3 #:fill 'no-fill)
vec3: contract violation
expected: exactly 3 values
given: '()

If len ≥ 2 and only one component value is given, every value defaults to it.

> (vec #:length 3 7)
(vec 7 7 7)

vec is also a match pattern identifier for deconstructingvectors.

> (match (vec 1 2 3) [(vec a b c) (+ a b c)])
6.0

Vectors of indeterminate length can be matched with a final #:restpattern.

Constructs a fresh vector on the first len components of some existing data. The array is not copied; the new Racket representation is backed by the existing C representation.

If fixed? is true and len is between 0 and 4, the vectordisplays its length-suffixed name. Otherwise, it uses the more general(vec ...) form.

Example:

> (define v1 (vec #:length 5 1))
> (define v2 (make-vec (vec-data v1) 3 #t 0))
> v2
(vec3 1 1 1)
> (vec-set! v2 2 0)
> v1
(vec 1 1 0 1 1)

Returns the underlying C representation of v.

Example:

Returns the number of components in v.

Example:

> (vec-length (vec 0 1 2))
3

Example:

(vec-copy v) → vec?
v : vec?

Returns a fresh copy of v.

Example:

Returns the length-suffixed name of v.

Example:

> (vec-name (vec #:length 5))
'vec5

Returns the ith component of v.

Example:

> (vec-ref (vec 9 8 7 6) 2)
7.0

Changes the ith component of v to x.

Example:

> (define v (vec 1 2 3))
> (vec-set! v 1 0)
> v
(vec 1 0 3)

Returns the component values of v.

Example:

> (vec->list (vec 1 2 3))
'(1.0 2.0 3.0)

Returns the underlying C representation of v cast as anf32vector.

Example:

Returns a sequence equivalent to v when no optional arguments are supplied.

The optional arguments start, stop, and step are as inin-vector.

Example:

(for/vec maybe-length (for-clause ...) body-or-break ... body)
(for*/vec maybe-length (for-clause ...) body-or-break ... body)

Like for/list and for*/list, but the results are accumulated into a vector instead of a list.

If the optional #:length clause is specified, it determines the length of the result vector.

If an optional #:fill clause is specified and its value is not'no-fill, it determines the value of any unspecified components.

(vec 0 0 0 1 2 3 2 4 6 -1)

Returns a constructor function for vectors with the same length as v.

Example:

> ((vec-constructor (vec 1 2 3)) 4 5)
(vec 4 5 0)

Overwrites the component values of v with the values of u.

Example:

> (define v (vec 1 2 3))
> (vec=! v (vec 4 5 6))
> v
(vec 4 5 6)
> (vec=! v (vec 7 8))
> v
(vec 7 8 6)
> (vec=! v (vec 9 10 11 12))
> v
(vec 9 10 11)

Like +, -, *, and /, but generalized to consume vectors or numbers.

> (vec- 3 (vec 4 5))
(vec -1 -2)
> (vec* (vec 6 7) 8)
(vec 48 56)
> (vec/ (vec 9 0) (vec 3 11))
(vec 3 0)

Like vec+, vec-, vec*, and vec/, except the result is stored in a.

> (define v (vec 1 2))
> (vec+=! v (vec 3 4))
> v
(vec 4 6)
> (vec-=! v 5)
> v
(vec -1 1)
> (vec*=! v (vec 6 7 8))
> v
(vec -6 7)
> (vec/=! v (vec 9 10))
> v
(vec -0.67 0.7)
(++vec! v) → vec? v : vec?
(--vec! v) → vec? v : vec?

Increments or decrements the components of v by 1 and then returnsv.

Example:

> (define v (vec 1 2))
> (++vec! v)
(vec 2 3)
> v
(vec 2 3)
(vec++! v) → vec? v : vec?
(vec--! v) → vec? v : vec?

Increments or decrements the components of v by 1 and then returns a fresh vector with the original components of v.

Example:

> (define v (vec 1 2))
> (vec++! v)
(vec 1 2)
> v
(vec 2 3)

A parameter that controls the maximum number of digits displayed after the decimal point of a vector component.

Example:

> (current-vec-precision 3)
> (vec 1/2 2/3 3/4)
(vec 0.5 0.667 0.75)

Creates a vector type whose Racket representation is an array that works with array-ref and array-set!.

(define-vec-type id #:length len)

Binds variables related to vectors of a specific length.

A define-vec-type form defines 2 names:

Example:

> (define-vec-type vec5 #:length 5)
> (vec5? (vec5))
#t
> (vec5? (vec 1 2 3))
#f

id is also a match pattern identifier similar tovec, except it only matches vectors with exactly len components.

match: no matching clause for (vec 1 2 3)
> (match (vec 1 2 3 4 5 6 7) [(vec5 #:rest xs) (apply + xs)])
match: no matching clause for (vec 1 2 3 4 5 6 7)
2.1.1.1 vec Types🔗
2.1.2 Double Precision Floats🔗

Arrays of 64-bit floating point numbers.

(dvec-copy v) → dvec?
v : dvec?
(for/dvec maybe-length (for-clause ...) body-or-break ... body)
(for*/dvec maybe-length (for-clause ...) body-or-break ... body)
(dvec=! v u) → void?
v : dvec?
u : dvec?
(++dvec! v) → dvec? v : dvec?
(--dvec! v) → dvec? v : dvec?
(dvec++! v) → dvec? v : dvec?
(dvec--! v) → dvec? v : dvec?

(define-dvec-type id #:length len)

2.1.2.1 dvec Types🔗
2.1.3 Signed Integers🔗

Arrays of signed integers.

(ivec-copy v) → ivec?
v : ivec?
(for/ivec maybe-length (for-clause ...) body-or-break ... body)
(for*/ivec maybe-length (for-clause ...) body-or-break ... body)
(ivec=! v u) → void?
v : ivec?
u : ivec?
(++ivec! v) → ivec? v : ivec?
(--ivec! v) → ivec? v : ivec?
(ivec++! v) → ivec? v : ivec?
(ivec--! v) → ivec? v : ivec?

(define-ivec-type id #:length len)

2.1.3.1 ivec Types🔗
2.1.4 Unsigned Integers🔗

Arrays of unsigned integers.

(uvec-copy v) → uvec?
v : uvec?
(for/uvec maybe-length (for-clause ...) body-or-break ... body)
(for*/uvec maybe-length (for-clause ...) body-or-break ... body)
(uvec=! v u) → void?
v : uvec?
u : uvec?
(++uvec! v) → uvec? v : uvec?
(--uvec! v) → uvec? v : uvec?
(uvec++! v) → uvec? v : uvec?
(uvec--! v) → uvec? v : uvec?

(define-uvec-type id #:length len)

2.1.4.1 uvec Types🔗
2.1.5 Booleans🔗

Arrays of boolean values.

(bvec-copy v) → bvec?
v : bvec?
(for/bvec maybe-length (for-clause ...) body-or-break ... body)
(for*/bvec maybe-length (for-clause ...) body-or-break ... body)
(bvec=! v u) → void?
v : bvec?
u : bvec?

(define-bvec-type id #:length len)

(bvec-and a ...+) → bvec?
a : bvec?

Returns the pointwise logical conjunction of the as.

Example:

> (bvec-and (bvec3 #t #t #t) (bvec3 #t #t #f) (bvec3 #f #t #t))
(bvec #f #t #f)
(bvec-or a ...+) → bvec?
a : bvec?

Returns the pointwise logical disjunction of the as.

Example:

> (bvec-or (bvec3 #f #f #f) (bvec3 #t #f #f) (bvec3 #f #f #t))
(bvec #t #f #t)
(bvec-not a) → bvec?
a : bvec?

Returns the pointwise logical negation of a.

Example:

> (bvec-not (bvec3 #f #t #f))
(bvec #t #f #t)
2.1.5.1 bvec Types🔗

2.2 Matrix Types🔗

This module re-exports glm/dmat and glm/mat.

2.2.1 Single Precision Floats🔗

A matrix is a two-dimensional array of 32-bit floating pointcomponent values.

Two matrices are equal? iff they have the same dimensions, the same number of components, and each pair of consecutive components are =.

Returns #t if m is a matrix.

Allocates a matrix with the xs as its components in column-major order.

> (mat #:rows 2 1 2 3 4 5 6)
[ 1 | 3 5 ][ 2 4 6 ]
> (mat #:rows 3 1 2 3 4 5 6)
[ 1 | 4 ][ 2 5 ][ 3 6 ]

When no xs are given, the result is an N×M (cols×rows) matrix with 1’s along its diagonal and 0’s everywhere else.

> (mat #:cols 3 #:rows 2)
[ 1 | 0 0 ][ 0 1 0 ]
> (mat #:cols 2 #:rows 3)
[ 1 | 0 ][ 0 1 ][ 0 0 ]

When N is given and the xs consist of a lone scalar value x, the result is an N×M matrix with x along its diagonal and fill everywhere else.

> (mat #:cols 3 #:rows 2 -1/2)
[ -0.5 | 0 0 ][ 0 -0.5 0 ]

If the lone x is a matrix, the result is an N×M matrix with xembedded in its upper-left corner.

> (mat #:cols 3 #:rows 4 #:fill -3 (mat #:rows 2 2))
[ 2 | 0 -3 ][ 0 2 -3 ][ -3 -3 1 ][ -3 -3 -3 ]
> (mat #:cols 3 #:rows 2 #:fill -3 (mat #:rows 4 2))
[ 2 | 0 0 ][ 0 2 0 ]

When N = (length '(x ...)), each of the xs becomes the sole argument to a column vector constructor.

> (mat #:cols 3 #:rows 2 9 8 7)
[ 9 | 8 7 ][ 9 8 7 ]
> (mat #:cols 2 #:rows 3 (vec2 1 2) (vec3 3 4 5))
[ 1 | 3 ][ 2 4 ][ 0 5 ]

When N is #f and (length '(x ...)) ≤ 1, the result is an M×Mmatrix.

> (mat #:rows 2)
> (mat #:rows 3 2)
[ 2 | 0 0 ][ 0 2 0 ][ 0 0 2 ]

If 2 ≤ (length '(x ...)) ≤ M, the result is an 1×M matrix.

If L = (length '(x ...)) > M, the result is an L’×M matrix, where L’ = L mod M + (0 if M divides L else 1).

> (mat #:rows 2 1 2 3 4)
> (mat #:rows 3 1 2 3 4)
[ 1 | 4 ][ 2 0 ][ 3 0 ]

mat is also a match pattern identifier for deconstructingmatrices.

'((4.0 5.0 6.0) (1.0 2.0 3.0))

Optional #:cols or #:rows patterns may be given, andmatrices of indeterminate length can be matched with a final#:rest pattern.

> (match (mat #:rows 3 1 2 3 4 5 6) [(mat #:cols cols #:rows rows x y z #:rest rgb) (list cols rows rgb x y z)])
'(2 3 (4.0 5.0 6.0) 1.0 2.0 3.0)
> (match (mat #:rows 3 1 2 3 4 5 6) [(mat #:cols cols #:rows rows #:rest _) (* cols rows)])
6

Constructs a fresh matrix on the first num-cols×num-rows components of some existing data. The array is not copied; the new Racket representation is backed by the existing C representation.

Example:

> (define m1 (mat #:rows 5))
> (define m2 (make-mat (mat-data m1) 3 3))
> m2
[ 1 | 0 0 ][ 0 1 0 ][ 0 0 1 ]
> (mat-set! m1 1 1 -1)
> m2
[ 1 | 0 0 ][ 0 -1 0 ][ 0 0 1 ]

Returns the underlying C representation of m.

Example:

Returns the number of columns or rows in m.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> m
[ 1 | 3 5 ][ 2 4 6 ]
> (mat-length m)
3
> (mat-num-cols m)
3
> (mat-num-rows m)
2

Example:

(mat-copy m) → mat?
m : mat?

Returns a fresh copy of m.

Example:

Returns the dimension-suffixed name of m.

Example:

> (mat-name (mat #:rows 5))
'mat5
> (mat-name (mat #:cols 5 #:rows 4))
'mat5x4
> (mat-name (mat #:cols 4 #:rows 5))
'mat4x5

Returns a component value of m.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> m
[ 1 | 3 5 ][ 2 4 6 ]
> (mat-ref m 5)
6.0
> (mat-ref m 2 1)
6.0

Returns a copy of the ith row vector of m.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> m
[ 1 | 3 5 ][ 2 4 6 ]
> (mat-row m 1)
(vec 2 4 6)

Returns the ith column vector of m. The data is not copied; the new Racket representation is backed by the existing C representation.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> m
[ 1 | 3 5 ][ 2 4 6 ]
> (mat-column m 1)
(vec2 3 4)
> (vec-set! (mat-column m 1) 0 -1)
> m
[ 1 | -1 5 ][ 2 4 6 ]

Changes a component of m to x.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> (mat-set! m 5 -1)
> (mat-set! m 2 0 -2)
> m
[ 1 | 3 -2 ][ 2 4 -1 ]

Changes the ith row of m to the components of v.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> (mat-set-row! m 1 (vec -2 -4 -6))
> m
[ 1 | 3 5 ][ -2 -4 -6 ]

Changes the ith column of m to the components of v.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> (mat-set-column! m 1 (vec -3 -4))
> m
[ 1 | -3 5 ][ 2 -4 6 ]

Returns the component columns, rows, or values of m.

Example:

> (define m (mat #:rows 3 1 2 3 4 5 6))
> m
[ 1 | 4 ][ 2 5 ][ 3 6 ]
> (mat-columns m)
'((vec3 1 2 3) (vec3 4 5 6))
> (mat-rows m)
'((vec 1 4) (vec 2 5) (vec 3 6))
> (mat->list m)
'(1.0 2.0 3.0 4.0 5.0 6.0)

mat-columns is also a match pattern identifier for deconstructing the columns of a matrix.

'((vec3 4 5 6) (vec3 1 2 3))

Matrices of indeterminate length can be matched with a final#:rest pattern.

'(((vec3 4 5 6)) 3.0 2.0 1.0)
(mat->f32vector m) → f32vector?
m : mat?

Returns the underlying C representation of m cast as anf32vector.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> (define fv (mat->f32vector m))
> (f32vector-set! fv 5 0.0)
> m
[ 1 | 3 5 ][ 2 4 0 ]

Returns a sequence equivalent to m.

Example:

Returns a sequence equivalent to the rows of m.

Example:

Returns a sequence equivalent to the columns of m.

Example:

(for/mat maybe-cols #:rows length-expr maybe-fill (for-clause ...) body-or-break ... body) maybe-cols = | #:cols length-expr maybe-fill = #:fill length-expr
(for*/mat maybe-cols #:rows length-expr maybe-fill (for-clause ...) body-or-break ... body)

Like for/list and for*/list, but the results are accumulated into a matrix instead of a list.

[ 1 | 3 5 ][ 2 4 6 ]
[ 0 | 100 ][ 1 101 ][ 2 102 ]

If the optional #:cols clause is specified, it determines the shape of the result matrix.

> (for/mat #:cols 5 #:rows 3 ([x (in-range 5)]) (* x x))
[ 0 | 1 4 9 16 ][ 0 1 4 9 16 ][ 0 1 4 9 16 ]

If the optional #:fill clause is specified, it determines the value of any unspecified components.

> (for/mat #:rows 3 #:fill -1 ([x (in-range 4)]) x)
[ 0 | 3 ][ 1 -1 ][ 2 -1 ]

Returns a predicate function that returns #t when applied to amatrix or vector with the same dimension(s) as m.

Example:

> (define m (mat #:cols 5 #:rows 4))
> (define mat4x5? (mat-predicate m))
> (define vec5? (mat-row-predicate m))
> (mat4x5? m)
#t
> (vec5? (mat-row m 0))
#t
> (vec5? (mat-column m 0))
#f

Returns a constructor function for matrices or vectors with the same dimension(s) as m.

Example:

> (define m (mat #:cols 5 #:rows 4))
> (define mat4x5 (mat-constructor m))
> (define vec5 (mat-row-constructor m))
> (mat4x5)
[ 1 | 0 0 0 0 ][ 0 1 0 0 0 ][ 0 0 1 0 0 ][ 0 0 0 1 0 ]
> (vec5)
(vec 0 0 0 0 0)

Overwrites the component values of m with the values of n.

Example:

> (define m (mat #:rows 2 1 2 3 4 5 6))
> m
[ 1 | 3 5 ][ 2 4 6 ]
> (mat=! m (mat #:rows 2 9 8 7 6 5 4))
> m
[ 9 | 7 5 ][ 8 6 4 ]

Like +, -, *, and /, but generalized to consume matrices, vectors, or numbers.

> (mat- 3 (vec 4 5))
(vec -1 -2)
> (mat* (mat #:rows 3 2) (vec 1 2 3))
(vec 2 4 6)
> (mat/ (mat #:rows 3) 2)
[ 0.5 | 0 0 ][ 0 0.5 0 ][ 0 0 0.5 ]
> (mat/ (mat #:rows 3) (mat #:rows 3 2))
[ 0.5 | 0 0 ][ 0 0.5 0 ][ 0 0 0.5 ]

Like mat+, mat-, mat*, and mat/, except the result is stored in m.

> (define m (mat #:cols 3 #:rows 2 1 2 3))
> m
[ 1 | 2 3 ][ 1 2 3 ]
> (mat+=! m (mat #:cols 3 #:rows 2 10 10 10))
> m
[ 11 | 12 13 ][ 11 12 13 ]
> (mat-=! m (mat #:cols 3 #:rows 2 1 2 3))
> m
[ 10 | 10 10 ][ 10 10 10 ]
> (define m (mat #:rows 3 1 2 3 4 5 6 7 8 9))
> m
[ 1 | 4 7 ][ 2 5 8 ][ 3 6 9 ]
> (mat*=! m (mat #:rows 3 2))
> m
[ 2 | 4 6 ][ 8 10 12 ][ 14 16 18 ]
> (define m (mat #:rows 3 1 2 3 4 5 6 7 8 9))
> m
[ 1 | 4 7 ][ 2 5 8 ][ 3 6 9 ]
> (mat/=! m (mat #:rows 3 2))
> m
[ 0.5 | 1 1.5 ][ 2 2.5 3 ][ 3.5 4 4.5 ]
(++mat! m) → mat? m : mat?
(--mat! m) → mat? m : mat?

Increments or decrements the components of m by 1 and then returns m.

Example:

> (define m (mat #:rows 2 1 2 3 4))
> (++mat! m)
> m
(mat++! m) → mat? m : mat?
(mat--! m) → mat? m : mat?

Increments or decrements the components of m by 1 and then returns a fresh matrix with the original components of m.

Example:

> (define m (mat #:rows 2 1 2 3 4))
> (mat++! m)
> m

Creates a matrix type whose Racket representation is an array that works with array-ref and array-set!.

(define-mat-type id #:cols N #:rows M)

Binds variables related to matrices of specific dimensions.

A define-mat-type form defines 2 names:

Example:

> (define-mat-type mat5 #:cols 5 #:rows 5)
> (mat5? (mat5))
#t
> (mat5? (mat #:rows 3))
#f

id is also a match patterns similar to mat, except it only matches matrices with exactly N columns and M rows.

> (match (mat5 1 2 3 4 5) [(mat5 a b c #:rest xs) (list a b c (apply + xs))])
'(1.0 1.0 1.0 72.0)
match: no matching clause for [ 1 | 0 0 ]
[ 0 | 1 0 ]
[ 0 | 0 1 ]
2.2.1.1 mat Types🔗
2.2.2 Double Precision Floats🔗

Two-dimensional arrays of 64-bit floating point numbers.

(dmat-copy m) → dmat?
m : dmat?
(for/dmat maybe-cols #:rows length-expr maybe-fill (for-clause ...) body-or-break ... body) maybe-cols = | #:cols length-expr maybe-fill = #:fill length-expr
(for*/dmat maybe-cols #:rows length-expr maybe-fill (for-clause ...) body-or-break ... body)
(dmat=! m n) → void?
m : dmat?
n : dmat?
(++dmat! m) → dmat? m : dmat?
(--dmat! m) → dmat? m : dmat?
(dmat++! m) → dmat? m : dmat?
(dmat--! m) → dmat? m : dmat?

(define-dmat-type id #:cols N #:rows M)

2.2.2.1 dmat Types🔗