Vectors (std::vec)
std::vec provides floating-point vectors with 2, 3 or 4 components —
useful for game math, animation, physics and colour manipulation.
Import with use std::vec. Operations are functions (vec.add, vec.dot…);
a native primitive type with operator overloading is planned for a future iteration.
Constructors and arithmetic
vec.vec2, vec.vec3 and vec.vec4 create vectors; vec.zero(n) creates the
zero vector of dimension n. Components are accessed as fields .x, .y,
.z, .w.
Addition, subtraction, scaling, dot product, cross product, length, normalisation, distance and linear interpolation.
// Feature: vec stdlib — 2/3/4-component float vectors
// When to use: creative coding, gameplay math, color math, plugin interop.
//
// MVP scope (today): vectors are plain tables with named axes; ops are
// functions, not operators. A future iteration will add primitive
// `vec3<f32>` types with operator overloading and full swizzling.
//
// See `specs/vec-primitive-types.md` for the full target spec.
use std::vec
// Constructors — vec2 / vec3 / vec4 plus a `zero(n)` shortcut.
let p = vec.vec3(1.0, 2.0, 3.0)
let q = vec.vec3(0.5, 0.5, 0.5)
let z3 = vec.zero(3)
// Field access by axis name.
print("p = ({p.x}, {p.y}, {p.z})") // (1, 2, 3)
print("z3 = ({z3.x}, {z3.y}, {z3.z})") // (0, 0, 0)
// Arithmetic — addition, subtraction, scalar scale.
let sum = vec.add(p, q)
print("p + q = ({sum.x}, {sum.y}, {sum.z})") // (1.5, 2.5, 3.5)
let diff = vec.sub(p, q)
print("p - q = ({diff.x}, {diff.y}, {diff.z})") // (0.5, 1.5, 2.5)
let doubled = vec.scale(p, 2.0)
print("p * 2 = ({doubled.x}, {doubled.y}, {doubled.z})") // (2, 4, 6)
// Dot product (scalar).
print("p . q = {vec.dot(p, q)}") // 3
// Cross product (vec3-only).
let cross = vec.cross(vec.vec3(1.0, 0.0, 0.0), vec.vec3(0.0, 1.0, 0.0))
print("x x y = ({cross.x}, {cross.y}, {cross.z})") // (0, 0, 1)
// Length / length squared.
print("|p| = {vec.length(p)}") // 3.7416...
print("|p|^2 = {vec.length_sq(p)}") // 14
// Normalize — handles zero-length gracefully (returns zero vector).
let n = vec.normalize(p)
print("normalize(p) = ({n.x}, {n.y}, {n.z})")
// Distance.
print("distance(p, q) = {vec.distance(p, q)}")
// Componentwise linear interpolation.
let mid = vec.lerp(p, q, 0.5)
print("lerp(p, q, 0.5) = ({mid.x}, {mid.y}, {mid.z})")
Colour aliases and swizzle
vec3/vec4 vectors also expose .r, .g, .b, .a fields —
synonyms for .x, .y, .z, .w. Multi-component access (.rgb, .bgr,
.xxxx…) returns a new reordered or replicated vector. Mixing the xyzw and
rgba sets in the same swizzle returns nil.
rgba aliases; swizzles rgb, bgr, xy, xxxx, bgra; invalid swizzle xr returns nil; lerp between colours.
// Feature: vec stdlib — color aliases and multi-component swizzling
// When to use: graphics code that reads better with rgba than xyzw.
//
// vec3/vec4 expose both .x/.y/.z/.w and .r/.g/.b/.a fields pointing at
// the same component values. Multi-component access (`.xyz`, `.bgr`,
// `.xxxx`, etc.) returns a NEW vector via the swizzle metamethod —
// reorder, reduce, or replicate components as needed.
use std::vec
let color = vec.vec4(1.0, 0.5, 0.25, 0.9)
// Single component (existing):
print("xyzw: ({color.x}, {color.y}, {color.z}, {color.w})")
print("rgba: ({color.r}, {color.g}, {color.b}, {color.a})")
// Multi-component swizzles return a NEW vector componentwise.
// Same set must be used end-to-end — `.xr` mixes xyzw with rgba and
// returns nil.
let rgb = color.rgb // vec3(1, 0.5, 0.25)
print("rgb = ({rgb.r}, {rgb.g}, {rgb.b})")
let bgr = color.bgr // vec3(0.25, 0.5, 1) — reordered
print("bgr = ({bgr.r}, {bgr.g}, {bgr.b})")
let xy = color.xy // vec2(1, 0.5)
print("xy = ({xy.x}, {xy.y})")
let xxxx = color.xxxx // vec4(1, 1, 1, 1) — replicated
print("xxxx = ({xxxx.x}, {xxxx.y}, {xxxx.z}, {xxxx.w})")
let bgra = color.bgra // vec4(0.25, 0.5, 1, 0.9) — color swap
print("bgra = ({bgra.r}, {bgra.g}, {bgra.b}, {bgra.a})")
// Invalid swizzles return nil. Mixing sets and oversize keys:
let mixed = color.xr
print("xr (mixed set) = {mixed}") // nil
// Composing colors with lerp:
let red = vec.vec4(1.0, 0.0, 0.0, 1.0)
let blue = vec.vec4(0.0, 0.0, 1.0, 1.0)
let purple = vec.lerp(red, blue, 0.5)
print("red+blue/2 = ({purple.r}, {purple.g}, {purple.b}, {purple.a})")
Challenge
Create two vec3 vectors representing two points in space, compute the distance
between them with vec.distance and verify that the normalised direction vector has
length ~= 1.0.
See also