-
Notifications
You must be signed in to change notification settings - Fork 0
Math Library
MichaelFisher1997 edited this page Jan 5, 2026
·
1 revision
Core mathematical primitives for 3D graphics and physics.
The math library (libs/zig-math/) provides essential types:
-
Vec3- 3D vector -
Mat4- 4x4 transformation matrix -
AABB- Axis-aligned bounding box -
Frustum- View frustum for culling -
Ray- Ray casting and voxel traversal
3D vector for positions, directions, and velocities.
pub const Vec3 = struct {
x: f32,
y: f32,
z: f32,
};| Constant | Value | Description |
|---|---|---|
zero |
(0, 0, 0) | Origin |
one |
(1, 1, 1) | Unit scale |
up |
(0, 1, 0) | +Y direction |
down |
(0, -1, 0) | -Y direction |
forward |
(0, 0, -1) | -Z (into screen) |
back |
(0, 0, 1) | +Z direction |
right |
(1, 0, 0) | +X direction |
left |
(-1, 0, 0) | -X direction |
| Method | Description |
|---|---|
add(other) |
Component-wise addition |
sub(other) |
Component-wise subtraction |
scale(scalar) |
Uniform scaling |
dot(other) |
Dot product (scalar) |
cross(other) |
Cross product (perpendicular Vec3) |
length() |
Euclidean magnitude |
lengthSquared() |
Squared magnitude (faster) |
normalize() |
Unit vector |
negate() |
Flip all components |
lerp(other, t) |
Linear interpolation |
distance(other) |
Distance between points |
toArray() |
Convert to [3]f32
|
4x4 transformation matrix for view, projection, and model transforms.
pub const Mat4 = extern struct {
data: [4][4]f32, // Column-major order
};Note: Uses extern struct for GPU compatibility.
| Constant | Description |
|---|---|
identity |
Identity matrix (no transform) |
zero |
Zero matrix |
| Method | Description |
|---|---|
perspective(fov, aspect, near, far) |
Standard perspective |
perspectiveReverseZ(fov, aspect, near, far) |
Reverse-Z (better precision) |
orthographic(l, r, b, t, near, far) |
Orthographic for UI |
| Method | Description |
|---|---|
lookAt(eye, target, worldUp) |
View matrix from camera position |
| Method | Description |
|---|---|
translate(offset) |
Translation matrix |
scale(s) |
Non-uniform scale |
rotateX(angle) |
X-axis rotation |
rotateY(angle) |
Y-axis rotation |
rotateZ(angle) |
Z-axis rotation |
| Method | Description |
|---|---|
multiply(a, b) |
Matrix multiplication |
inverse() |
Compute inverse (cofactor method) |
transformPoint(v) |
Apply to point (with perspective divide) |
transformDirection(v) |
Apply to direction (ignores translation) |
ptr() |
Raw pointer for GPU upload |
Axis-Aligned Bounding Box for collision and culling.
pub const AABB = struct {
min: Vec3, // Minimum corner
max: Vec3, // Maximum corner
};| Method | Description |
|---|---|
init(min, max) |
From corner points |
fromCenterSize(center, size) |
From center and dimensions |
| Method | Description |
|---|---|
center() |
Get center point |
size() |
Get dimensions |
contains(point) |
Point containment test |
intersects(other) |
AABB-AABB intersection |
| Method | Description |
|---|---|
expand(amount) |
Grow in all directions |
translate(offset) |
Move box |
View frustum for visibility culling.
pub const Plane = struct {
normal: Vec3, // Plane normal
distance: f32, // Distance from origin
};| Method | Description |
|---|---|
signedDistance(point) |
Positive = front, negative = behind |
normalize() |
Normalize plane equation |
pub const Frustum = struct {
planes: [6]Plane, // left, right, bottom, top, near, far
};Frustum extracted from View-Projection matrix using Gribb/Hartmann method:
// Left plane: row4 + row1
planes[0] = Plane.init(
Vec3.init(m[0][3] + m[0][0], m[1][3] + m[1][0], m[2][3] + m[2][0]),
m[3][3] + m[3][0],
).normalize();| Method | Description |
|---|---|
containsPoint(point) |
Point inside all 6 planes |
intersectsSphere(center, radius) |
Sphere-frustum test |
intersectsAABB(aabb) |
Primary culling method |
intersectsChunk(cx, cz) |
Specialized chunk test |
intersectsChunkRelative(...) |
Camera-relative chunk test |
For each plane:
- Find AABB's "positive vertex" (furthest in normal direction)
- If positive vertex is behind plane, AABB is outside
Ray casting and voxel traversal.
pub const Ray = struct {
origin: Vec3,
direction: Vec3, // Normalized
};
pub const RayHit = struct {
t: f32, // Distance to hit
normal: Vec3, // Surface normal
};
pub const VoxelHit = struct {
x: i32, y: i32, z: i32, // Block coordinates
face: Face, // Which face was hit
distance: f32,
};pub fn intersectAABB(ray, aabb) ?RayHit {
// For each axis, compute entry (t1) and exit (t2)
// Track max_entry and min_exit
// If max_entry > min_exit, ray misses
// Returns hit distance and surface normal
}The castThroughVoxels function implements Digital Differential Analyzer (DDA):
Algorithm:
1. Start at origin voxel
2. For each axis, calculate:
- step: direction (+1 or -1)
- tDelta: distance between boundaries
- tMax: distance to next boundary
3. Loop until max_distance:
- Check current voxel for solid block
- Step along axis with smallest tMax
- Update tMax for that axis
- Track which face was crossed
This is the standard algorithm for Minecraft-style block targeting.
const view = Mat4.lookAt(camera_pos, target, Vec3.up);
const proj = Mat4.perspectiveReverseZ(fov, aspect, near, far);
const view_proj = Mat4.multiply(proj, view);const frustum = Frustum.fromViewProjection(view_proj);
for (chunks) |chunk| {
const aabb = AABB.fromCenterSize(chunk.center, chunk.size);
if (frustum.intersectsAABB(aabb)) {
chunk.render();
}
}const ray = Ray{
.origin = camera.position,
.direction = camera.forward,
};
if (ray.castThroughVoxels(world, 5.0)) |hit| {
highlight_block(hit.x, hit.y, hit.z);
target_face = hit.face;
}Source: libs/zig-math/, src/engine/math/ | Last updated: January 2026