EAGL.Math (eagl v0.8.0)

View Source

GLM-compatible 3D math library for OpenGL applications.

Provides comprehensive vector, matrix, and quaternion operations with OpenGL integration based on the GLM library. All functions work with Erlang's tuple-in-list format required by wx OpenGL bindings.

Usage

import EAGL.Math

# Vector operations
position = vec3(1.0, 2.0, 3.0)
direction = vec3(0.0, 1.0, 0.0)
result = vec_add(position, direction)
length = vec_length(position)

# Matrix transformations
model = mat4_translate(vec3(5.0, 0.0, 0.0))
view = mat4_look_at(
  vec3(0.0, 0.0, 5.0),  # eye
  vec3(0.0, 0.0, 0.0),  # target
  vec3(0.0, 1.0, 0.0)   # up
)
projection = mat4_perspective(radians(45.0), 16.0/9.0, 0.1, 100.0)

# Quaternion rotations
rotation = quat_from_axis_angle(vec3(0.0, 1.0, 0.0), radians(45.0))

# All values work directly with EAGL.Shader uniform functions
set_uniform(program, "model", model)
set_uniform(program, "view", view)
set_uniform(program, "projection", projection)

Summary

Functions

Absolute value.

Calculate angle between two vectors in radians.

Clamp value between min and max.

Compute the cross product of two 3D vectors.

Convert radians to degrees.

Calculate the distance between two points (vectors).

Calculate the squared distance between two points (avoids sqrt).

Compute the dot product of two vectors (2D, 3D, or 4D).

Calculate face normal from three vertices (assumes counter-clockwise winding).

Fractional part of x (x - floor(x)).

Fast inverse square root approximation.

Compute the squared length of a vector (avoids sqrt).

Linear interpolation between two values.

Create a 2x2 matrix.

Create a 2x2 identity matrix. Matrix is stored in column-major order for OpenGL compatibility.

Create a 3x3 matrix.

Create a 3x3 identity matrix. Matrix is stored in column-major order for OpenGL compatibility.

Multiply two 3x3 matrices. All matrices are in column-major order for OpenGL compatibility.

Transpose a 3x3 matrix. Input and output matrices are in column-major order for OpenGL compatibility.

Create a 4x4 identity matrix. Matrix is stored in column-major order for OpenGL compatibility.

Create the inverse of a 4x4 matrix using the adjugate method. Returns the original matrix if it's not invertible (determinant is zero). Input and output matrices are in column-major order for OpenGL compatibility. Note this is the only function not from the original OpenGl GLM library.

Create a look-at view matrix. Matrix is stored in column-major order for OpenGL compatibility.

Multiply two 4x4 matrices. All matrices are in column-major order for OpenGL compatibility.

Create an orthographic projection matrix. Matrix is stored in column-major order for OpenGL compatibility.

Create a perspective projection matrix. Matrix is stored in column-major order for OpenGL compatibility.

Create a rotation matrix from axis and angle.

Create a rotation matrix around the X axis. Matrix is stored in column-major order for OpenGL compatibility.

Create a rotation matrix around the Y axis. Matrix is stored in column-major order for OpenGL compatibility.

Create a rotation matrix around the Z axis. Matrix is stored in column-major order for OpenGL compatibility.

Create a scale matrix. Matrix is stored in column-major order for OpenGL compatibility.

Multiply a 3D vector by a 4x4 matrix (treating vector as point with w=1). Returns a 3D vector with the w component divided out.

Multiply a 4D vector by a 4x4 matrix.

Multiply a 3D vector by a 4x4 matrix (treating vector as direction with w=0). Used for transforming direction vectors (normals, etc.) where translation should be ignored.

Create a translation matrix. Matrix is stored in column-major order for OpenGL compatibility.

Transpose a 4x4 matrix. Input and output matrices are in column-major order for OpenGL compatibility.

Mix (linear interpolation) between two values.

Modulo operation that works with floats.

Normalize a vector to unit length (2D, 3D, or 4D).

Check if two vectors are parallel (dot product close to ±1).

Check if two vectors are perpendicular (dot product close to 0).

Project vector a onto vector b.

Create a quaternion. Quaternions are represented as {x, y, z, w} where w is the scalar component. This follows the (x, y, z, w) convention commonly used in graphics programming.

Conjugate a quaternion (negate x, y, z components).

Create a quaternion from axis-angle representation.

Create a quaternion from Euler angles (pitch, yaw, roll in radians).

Create an identity quaternion (no rotation).

Multiply two quaternions.

Normalize a quaternion.

Rotate a 3D vector by a quaternion.

Spherical linear interpolation between two quaternions.

Convert quaternion to rotation matrix (3x3). Matrix is stored in column-major order for OpenGL compatibility.

Convert quaternion to rotation matrix (4x4). Matrix is stored in column-major order for OpenGL compatibility.

Convert degrees to radians.

Reflect a vector around a normal.

Refract a vector around a normal with given refractive index ratio.

Reject vector a from vector b (perpendicular component).

A sigil to create index data from a string.

A sigil to create a matrix from a string.

A sigil to create vertex data from a string.

Sign function (-1, 0, or 1).

Smooth step function (Hermite interpolation).

Step function (returns 0.0 if x < edge, 1.0 otherwise).

Create a 2D vector.

Create a zero vector (2D).

Create a 3D vector.

Create a 3D vector with all components set to 1.

Create the X unit vector (1, 0, 0).

Create the Y unit vector (0, 1, 0).

Create the Z unit vector (0, 0, 1).

Create a zero vector (3D).

Create a 4D vector.

Create a zero vector (4D).

Add two vectors component-wise.

Compute the length (magnitude) of a vector (2D, 3D, or 4D).

Linear interpolation between two vectors.

Negate a vector (multiply by -1).

Multiply a vector by a scalar.

Subtract two vectors component-wise.

Types

mat2()

@type mat2() :: [{float(), float(), float(), float()}]

mat3()

@type mat3() :: [
  {float(), float(), float(), float(), float(), float(), float(), float(),
   float()}
]

mat4()

@type mat4() :: [
  {float(), float(), float(), float(), float(), float(), float(), float(),
   float(), float(), float(), float(), float(), float(), float(), float()}
]

quat()

@type quat() :: [{float(), float(), float(), float()}]

vec2()

@type vec2() :: [{float(), float()}]

vec3()

@type vec3() :: [{float(), float(), float()}]

vec4()

@type vec4() :: [{float(), float(), float(), float()}]

Functions

abs_val(x)

@spec abs_val(float()) :: float()

Absolute value.

angle_between(a, b)

@spec angle_between(vec3(), vec3()) :: float()

Calculate angle between two vectors in radians.

clamp(value, min_val, max_val)

@spec clamp(float(), float(), float()) :: float()

Clamp value between min and max.

cross(list1, list2)

@spec cross(vec3(), vec3()) :: vec3()

Compute the cross product of two 3D vectors.

degrees(radians)

@spec degrees(float()) :: float()

Convert radians to degrees.

distance(v1, v2)

@spec distance(vec2(), vec2()) :: float()
@spec distance(vec3(), vec3()) :: float()
@spec distance(vec4(), vec4()) :: float()

Calculate the distance between two points (vectors).

distance_squared(v1, v2)

@spec distance_squared(vec2(), vec2()) :: float()
@spec distance_squared(vec3(), vec3()) :: float()
@spec distance_squared(vec4(), vec4()) :: float()

Calculate the squared distance between two points (avoids sqrt).

dot(list1, list2)

@spec dot(vec2(), vec2()) :: float()
@spec dot(vec3(), vec3()) :: float()
@spec dot(vec4(), vec4()) :: float()

Compute the dot product of two vectors (2D, 3D, or 4D).

face_normal(v0, v1, v2)

@spec face_normal(vec3(), vec3(), vec3()) :: vec3()

Calculate face normal from three vertices (assumes counter-clockwise winding).

fract(x)

@spec fract(float()) :: float()

Fractional part of x (x - floor(x)).

inverse_sqrt(x)

@spec inverse_sqrt(float()) :: float()

Fast inverse square root approximation.

length_squared(list)

@spec length_squared(vec2()) :: float()
@spec length_squared(vec3()) :: float()
@spec length_squared(vec4()) :: float()

Compute the squared length of a vector (avoids sqrt).

lerp(a, b, t)

@spec lerp(float(), float(), float()) :: float()

Linear interpolation between two values.

mat2(a, b, c, d)

@spec mat2(float(), float(), float(), float()) :: mat2()

Create a 2x2 matrix.

mat2_identity()

@spec mat2_identity() :: mat2()

Create a 2x2 identity matrix. Matrix is stored in column-major order for OpenGL compatibility.

mat3(a, b, c, d, e, f, g, h, i)

@spec mat3(
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float()
) :: mat3()

Create a 3x3 matrix.

mat3_identity()

@spec mat3_identity() :: mat3()

Create a 3x3 identity matrix. Matrix is stored in column-major order for OpenGL compatibility.

mat3_mul(list1, list2)

@spec mat3_mul(mat3(), mat3()) :: mat3()

Multiply two 3x3 matrices. All matrices are in column-major order for OpenGL compatibility.

mat3_transpose(list)

@spec mat3_transpose(mat3()) :: mat3()

Transpose a 3x3 matrix. Input and output matrices are in column-major order for OpenGL compatibility.

mat4(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p)

@spec mat4(
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float(),
  float()
) :: mat4()

Create a 4x4 matrix.

mat4_identity()

@spec mat4_identity() :: mat4()

Create a 4x4 identity matrix. Matrix is stored in column-major order for OpenGL compatibility.

mat4_inverse(list)

@spec mat4_inverse(mat4()) :: mat4()

Create the inverse of a 4x4 matrix using the adjugate method. Returns the original matrix if it's not invertible (determinant is zero). Input and output matrices are in column-major order for OpenGL compatibility. Note this is the only function not from the original OpenGl GLM library.

mat4_look_at(eye, center, up)

@spec mat4_look_at(vec3(), vec3(), vec3()) :: mat4()

Create a look-at view matrix. Matrix is stored in column-major order for OpenGL compatibility.

This implements GLM's lookAtRH (right-handed) convention to properly support OpenGL's default right-handed coordinate system.

mat4_mul(list1, list2)

@spec mat4_mul(mat4(), mat4()) :: mat4()

Multiply two 4x4 matrices. All matrices are in column-major order for OpenGL compatibility.

mat4_ortho(left, right, bottom, top, z_near, z_far)

@spec mat4_ortho(float(), float(), float(), float(), float(), float()) :: mat4()

Create an orthographic projection matrix. Matrix is stored in column-major order for OpenGL compatibility.

mat4_perspective(fov_y, aspect_ratio, z_near, z_far)

@spec mat4_perspective(float(), float(), float(), float()) :: mat4()

Create a perspective projection matrix. Matrix is stored in column-major order for OpenGL compatibility.

mat4_rotate(axis, angle)

@spec mat4_rotate(vec3(), float()) :: mat4()

Create a rotation matrix from axis and angle.

mat4_rotate_x(angle)

@spec mat4_rotate_x(float()) :: mat4()

Create a rotation matrix around the X axis. Matrix is stored in column-major order for OpenGL compatibility.

mat4_rotate_y(angle)

@spec mat4_rotate_y(float()) :: mat4()

Create a rotation matrix around the Y axis. Matrix is stored in column-major order for OpenGL compatibility.

mat4_rotate_z(angle)

@spec mat4_rotate_z(float()) :: mat4()

Create a rotation matrix around the Z axis. Matrix is stored in column-major order for OpenGL compatibility.

mat4_scale(v)

@spec mat4_scale(vec3()) :: mat4()

Create a scale matrix. Matrix is stored in column-major order for OpenGL compatibility.

mat4_transform_point(list1, list2)

@spec mat4_transform_point(mat4(), vec3()) :: vec3()

Multiply a 3D vector by a 4x4 matrix (treating vector as point with w=1). Returns a 3D vector with the w component divided out.

mat4_transform_vec4(list1, list2)

@spec mat4_transform_vec4(mat4(), vec4()) :: vec4()

Multiply a 4D vector by a 4x4 matrix.

mat4_transform_vector(list1, list2)

@spec mat4_transform_vector(mat4(), vec3()) :: vec3()

Multiply a 3D vector by a 4x4 matrix (treating vector as direction with w=0). Used for transforming direction vectors (normals, etc.) where translation should be ignored.

mat4_translate(v)

@spec mat4_translate(vec3()) :: mat4()

Create a translation matrix. Matrix is stored in column-major order for OpenGL compatibility.

mat4_transpose(list)

@spec mat4_transpose(mat4()) :: mat4()

Transpose a 4x4 matrix. Input and output matrices are in column-major order for OpenGL compatibility.

mix(x, y, a)

@spec mix(float(), float(), float()) :: float()

Mix (linear interpolation) between two values.

mod(x, y)

@spec mod(float(), float()) :: float()

Modulo operation that works with floats.

normalize(list)

@spec normalize(vec2()) :: vec2()
@spec normalize(vec3()) :: vec3()
@spec normalize(vec4()) :: vec4()

Normalize a vector to unit length (2D, 3D, or 4D).

parallel?(a, b, tolerance \\ 0.001)

@spec parallel?(vec3(), vec3(), float()) :: boolean()

Check if two vectors are parallel (dot product close to ±1).

perpendicular?(a, b, tolerance \\ 0.001)

@spec perpendicular?(vec3(), vec3(), float()) :: boolean()

Check if two vectors are perpendicular (dot product close to 0).

project(a, b)

@spec project(vec3(), vec3()) :: vec3()

Project vector a onto vector b.

quat(x, y, z, w)

@spec quat(float(), float(), float(), float()) :: quat()

Create a quaternion. Quaternions are represented as {x, y, z, w} where w is the scalar component. This follows the (x, y, z, w) convention commonly used in graphics programming.

quat_conjugate(list)

@spec quat_conjugate(quat()) :: quat()

Conjugate a quaternion (negate x, y, z components).

quat_from_axis_angle(axis, angle)

@spec quat_from_axis_angle(vec3(), float()) :: quat()

Create a quaternion from axis-angle representation.

quat_from_euler(pitch, yaw, roll)

@spec quat_from_euler(float(), float(), float()) :: quat()

Create a quaternion from Euler angles (pitch, yaw, roll in radians).

quat_identity()

@spec quat_identity() :: quat()

Create an identity quaternion (no rotation).

quat_mul(list1, list2)

@spec quat_mul(quat(), quat()) :: quat()

Multiply two quaternions.

quat_normalize(q)

@spec quat_normalize(quat()) :: quat()

Normalize a quaternion.

quat_rotate_vec3(q, v)

@spec quat_rotate_vec3(quat(), vec3()) :: vec3()

Rotate a 3D vector by a quaternion.

quat_slerp(q1, q2, t)

@spec quat_slerp(quat(), quat(), float()) :: quat()

Spherical linear interpolation between two quaternions.

quat_to_mat3(list)

@spec quat_to_mat3(quat()) :: mat3()

Convert quaternion to rotation matrix (3x3). Matrix is stored in column-major order for OpenGL compatibility.

quat_to_mat4(q)

@spec quat_to_mat4(quat()) :: mat4()

Convert quaternion to rotation matrix (4x4). Matrix is stored in column-major order for OpenGL compatibility.

radians(degrees)

@spec radians(float()) :: float()

Convert degrees to radians.

reflect(incident, normal)

@spec reflect(vec3(), vec3()) :: vec3()

Reflect a vector around a normal.

refract(incident, normal, eta)

@spec refract(vec3(), vec3(), float()) :: vec3()

Refract a vector around a normal with given refractive index ratio.

reject(a, b)

@spec reject(vec3(), vec3()) :: vec3()

Reject vector a from vector b (perpendicular component).

sigil_i(string, opts)

A sigil to create index data from a string.

Returns a flat list of integers, perfect for element array buffer indices, face definitions, or any other integer-based data.

Supports comments using '#' - everything after '#' on a line is ignored. Works with module attributes since sigils are evaluated at compile time.

Examples

# Simple triangle indices
~i"0 1 2"

# Quad indices (two triangles)
~i"0 1 2  2 3 0"

# Cube indices with comments
~i'''
# Front face
0 1 2  2 3 0
# Back face
4 5 6  6 7 4
# Left face
7 3 0  0 4 7
# Right face
1 5 6  6 2 1
# Top face
3 2 6  6 7 3
# Bottom face
0 1 5  5 4 0
'''

# Triangle strip indices
~i'''
0 1 2   # first triangle
1 3 2   # second triangle (shares edge 1-2)
2 3 4   # third triangle (shares edge 2-3)
'''

Module Attributes

# Define index data as module attributes
@quad_indices ~i'''
0 1 2  # first triangle
2 3 0  # second triangle
'''

@cube_indices ~i'''
# All 12 triangles for a cube
0 1 2  2 3 0    # front
4 5 6  6 7 4    # back
7 3 0  0 4 7    # left
1 5 6  6 2 1    # right
3 2 6  6 7 3    # top
0 1 5  5 4 0    # bottom
'''

def get_quad_indices, do: @quad_indices
def get_cube_indices, do: @cube_indices

sigil_m(string, opts)

A sigil to create a matrix from a string.

Automatically determines matrix size based on the number of floats:

  • 4 floats: creates a 2x2 matrix
  • 9 floats: creates a 3x3 matrix
  • 16 floats: creates a 4x4 matrix

Supports comments using '#' - everything after '#' on a line is ignored. Works with module attributes since sigils are evaluated at compile time.

Examples

# 2x2 matrix (single line)
~m"1.0 0.0 0.0 1.0"

# 2x2 matrix with comments
~m'''
1.0 0.0  # row 1
0.0 1.0  # row 2
'''

# 3x3 identity matrix with detailed comments
~m'''
1.0 0.0 0.0  # X axis
0.0 1.0 0.0  # Y axis
0.0 0.0 1.0  # Z axis
'''

# 4x4 transformation matrix
~m'''
1.0 0.0 0.0 5.0  # X axis + translation
0.0 1.0 0.0 0.0  # Y axis
0.0 0.0 1.0 0.0  # Z axis
0.0 0.0 0.0 1.0  # homogeneous coordinate
'''

Module Attributes

# Define matrices as module attributes for reuse
@identity_4x4 ~m'''
1.0 0.0 0.0 0.0  # identity matrix
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0
'''

@projection_matrix ~m'''
1.81 0.0  0.0   0.0   # perspective projection
0.0  2.41 0.0   0.0   # 45° FOV, 16:9 aspect
0.0  0.0 -1.002 -0.2  # near=0.1, far=100.0
0.0  0.0 -1.0   0.0
'''

def get_identity, do: @identity_4x4
def get_projection, do: @projection_matrix

sigil_v(string, opts)

A sigil to create vertex data from a string.

Returns a flat list of floats, perfect for vertex arrays, texture coordinates, normals, colors, or any other vertex attribute data.

Supports comments using '#' - everything after '#' on a line is ignored. Works with module attributes since sigils are evaluated at compile time.

Examples

# Simple triangle vertices (x, y, z)
~v"0.0 0.5 0.0  -0.5 -0.5 0.0  0.5 -0.5 0.0"

# Triangle with comments
~v'''
0.0  0.5 0.0   # top vertex
-0.5 -0.5 0.0  # bottom left
0.5  -0.5 0.0  # bottom right
'''

# Quad vertices with texture coordinates
~v'''
# Position    # Texture coords
-1.0  1.0 0.0  0.0 1.0  # top left
 1.0  1.0 0.0  1.0 1.0  # top right
 1.0 -1.0 0.0  1.0 0.0  # bottom right
-1.0 -1.0 0.0  0.0 0.0  # bottom left
'''

# Color data (RGB)
~v'''
1.0 0.0 0.0  # red
0.0 1.0 0.0  # green
0.0 0.0 1.0  # blue
'''

Module Attributes

# Define vertex data as module attributes
@triangle_vertices ~v'''
0.0  0.5 0.0   # top
-0.5 -0.5 0.0  # bottom left
0.5  -0.5 0.0  # bottom right
'''

@quad_indices ~v"0 1 2  2 3 0"  # triangle indices

def get_triangle_vertices, do: @triangle_vertices
def get_quad_indices, do: @quad_indices

sign(x)

@spec sign(float()) :: float()

Sign function (-1, 0, or 1).

smooth_step(edge0, edge1, x)

@spec smooth_step(float(), float(), float()) :: float()

Smooth step function (Hermite interpolation).

step(edge, x)

@spec step(float(), float()) :: float()

Step function (returns 0.0 if x < edge, 1.0 otherwise).

vec2(x, y)

@spec vec2(float(), float()) :: vec2()

Create a 2D vector.

vec2_zero()

@spec vec2_zero() :: vec2()

Create a zero vector (2D).

vec3(x, y, z)

@spec vec3(float(), float(), float()) :: vec3()

Create a 3D vector.

vec3_one()

@spec vec3_one() :: vec3()

Create a 3D vector with all components set to 1.

vec3_unit_x()

@spec vec3_unit_x() :: vec3()

Create the X unit vector (1, 0, 0).

vec3_unit_y()

@spec vec3_unit_y() :: vec3()

Create the Y unit vector (0, 1, 0).

vec3_unit_z()

@spec vec3_unit_z() :: vec3()

Create the Z unit vector (0, 0, 1).

vec3_zero()

@spec vec3_zero() :: vec3()

Create a zero vector (3D).

vec4(x, y, z, w)

@spec vec4(float(), float(), float(), float()) :: vec4()

Create a 4D vector.

vec4_zero()

@spec vec4_zero() :: vec4()

Create a zero vector (4D).

vec_add(list1, list2)

@spec vec_add(vec2(), vec2()) :: vec2()
@spec vec_add(vec3(), vec3()) :: vec3()
@spec vec_add(vec4(), vec4()) :: vec4()

Add two vectors component-wise.

vec_length(list)

@spec vec_length(vec2()) :: float()
@spec vec_length(vec3()) :: float()
@spec vec_length(vec4()) :: float()

Compute the length (magnitude) of a vector (2D, 3D, or 4D).

vec_lerp(list1, list2, t)

@spec vec_lerp(vec2(), vec2(), float()) :: vec2()
@spec vec_lerp(vec3(), vec3(), float()) :: vec3()
@spec vec_lerp(vec4(), vec4(), float()) :: vec4()

Linear interpolation between two vectors.

vec_negate(list)

@spec vec_negate(vec2()) :: vec2()
@spec vec_negate(vec3()) :: vec3()
@spec vec_negate(vec4()) :: vec4()

Negate a vector (multiply by -1).

vec_scale(list, s)

@spec vec_scale(vec2(), float()) :: vec2()
@spec vec_scale(vec3(), float()) :: vec3()
@spec vec_scale(vec4(), float()) :: vec4()

Multiply a vector by a scalar.

vec_sub(list1, list2)

@spec vec_sub(vec2(), vec2()) :: vec2()
@spec vec_sub(vec3(), vec3()) :: vec3()
@spec vec_sub(vec4(), vec4()) :: vec4()

Subtract two vectors component-wise.