Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transform Functions

Matrix stack operations for positioning, rotating, and scaling objects.

Conventions

  • Y-up right-handed coordinate system
  • Column-major matrix storage (wgpu/WGSL compatible)
  • Column vectors: v' = M * v
  • Angles in degrees for FFI (converted to radians internally)

Transform Stack

push_identity

Resets the current transform to identity (no transformation).

Signature:

#![allow(unused)]
fn main() {
fn push_identity()
}

Example:

#![allow(unused)]
fn main() {
fn render() {
    // Reset before drawing each object
    push_identity();
    draw_mesh(object_a);

    push_identity();
    push_translate(10.0, 0.0, 0.0);
    draw_mesh(object_b);
}
}

transform_set

Sets the current transform from a 4x4 matrix.

Signature:

#![allow(unused)]
fn main() {
fn transform_set(matrix_ptr: *const f32)
}

Parameters:

NameTypeDescription
matrix_ptr*const f32Pointer to 16 floats (4x4 column-major)

Matrix Layout (column-major, 16 floats):

[col0.x, col0.y, col0.z, col0.w,
 col1.x, col1.y, col1.z, col1.w,
 col2.x, col2.y, col2.z, col2.w,
 col3.x, col3.y, col3.z, col3.w]

Example:

#![allow(unused)]
fn main() {
fn render() {
    // Using glam
    let transform = Mat4::from_scale_rotation_translation(
        Vec3::ONE,
        Quat::from_rotation_y(angle),
        Vec3::new(x, y, z)
    );

    let cols = transform.to_cols_array();
    transform_set(cols.as_ptr());
    draw_mesh(model);
}
}

Translation

push_translate

Applies a translation to the current transform.

Signature:

#![allow(unused)]
fn main() {
fn push_translate(x: f32, y: f32, z: f32)
}

Parameters:

NameTypeDescription
xf32X offset (right is positive)
yf32Y offset (up is positive)
zf32Z offset (toward camera is positive)

Example:

#![allow(unused)]
fn main() {
fn render() {
    // Position object at (10, 5, 0)
    push_identity();
    push_translate(10.0, 5.0, 0.0);
    draw_mesh(object);

    // Stack translations (additive)
    push_identity();
    push_translate(5.0, 0.0, 0.0);  // Move right 5
    push_translate(0.0, 3.0, 0.0);  // Then move up 3
    draw_mesh(object);  // At (5, 3, 0)
}
}

Rotation

push_rotate_x

Rotates around the X axis.

Signature:

#![allow(unused)]
fn main() {
fn push_rotate_x(angle_deg: f32)
}

Parameters:

NameTypeDescription
angle_degf32Rotation angle in degrees

Example:

#![allow(unused)]
fn main() {
fn render() {
    push_identity();
    push_rotate_x(45.0); // Tilt forward 45 degrees
    draw_mesh(object);
}
}

push_rotate_y

Rotates around the Y axis.

Signature:

#![allow(unused)]
fn main() {
fn push_rotate_y(angle_deg: f32)
}

Example:

#![allow(unused)]
fn main() {
fn render() {
    push_identity();
    push_rotate_y(elapsed_time() * 90.0); // Spin 90 deg/sec
    draw_mesh(spinning_object);
}
}

push_rotate_z

Rotates around the Z axis.

Signature:

#![allow(unused)]
fn main() {
fn push_rotate_z(angle_deg: f32)
}

Example:

#![allow(unused)]
fn main() {
fn render() {
    push_identity();
    push_rotate_z(45.0); // Roll 45 degrees
    draw_mesh(object);
}
}

push_rotate

Rotates around an arbitrary axis.

Signature:

#![allow(unused)]
fn main() {
fn push_rotate(angle_deg: f32, axis_x: f32, axis_y: f32, axis_z: f32)
}

Parameters:

NameTypeDescription
angle_degf32Rotation angle in degrees
axis_x, axis_y, axis_zf32Rotation axis (will be normalized)

Example:

#![allow(unused)]
fn main() {
fn render() {
    push_identity();
    // Rotate around diagonal axis
    push_rotate(45.0, 1.0, 1.0, 0.0);
    draw_mesh(object);
}
}

Scale

push_scale

Applies non-uniform scaling.

Signature:

#![allow(unused)]
fn main() {
fn push_scale(x: f32, y: f32, z: f32)
}

Parameters:

NameTypeDescription
xf32Scale factor on X axis
yf32Scale factor on Y axis
zf32Scale factor on Z axis

Example:

#![allow(unused)]
fn main() {
fn render() {
    push_identity();
    push_scale(2.0, 1.0, 1.0); // Stretch horizontally
    draw_mesh(object);

    push_identity();
    push_scale(1.0, 0.5, 1.0); // Squash vertically
    draw_mesh(squashed);
}
}

push_scale_uniform

Applies uniform scaling (same factor on all axes).

Signature:

#![allow(unused)]
fn main() {
fn push_scale_uniform(s: f32)
}

Parameters:

NameTypeDescription
sf32Uniform scale factor

Example:

#![allow(unused)]
fn main() {
fn render() {
    push_identity();
    push_scale_uniform(2.0); // Double size
    draw_mesh(big_object);

    push_identity();
    push_scale_uniform(0.5); // Half size
    draw_mesh(small_object);
}
}

Transform Order

Transforms are applied in reverse order of function calls (right-to-left matrix multiplication).

#![allow(unused)]
fn main() {
fn render() {
    push_identity();
    push_translate(5.0, 0.0, 0.0);  // Applied LAST
    push_rotate_y(45.0);             // Applied SECOND
    push_scale_uniform(2.0);         // Applied FIRST
    draw_mesh(object);

    // Equivalent to: Translate * Rotate * Scale * vertex
    // Object is: 1) scaled, 2) rotated, 3) translated
}
}

Common Patterns

Object at position with rotation:

#![allow(unused)]
fn main() {
push_identity();
push_translate(obj.x, obj.y, obj.z);  // Position
push_rotate_y(obj.rotation);           // Then rotate
draw_mesh(obj.mesh);
}

Hierarchical transforms (parent-child):

#![allow(unused)]
fn main() {
fn render() {
    // Tank body
    push_identity();
    push_translate(tank.x, tank.y, tank.z);
    push_rotate_y(tank.body_angle);
    draw_mesh(tank_body);

    // Turret (inherits body transform, then adds its own)
    push_translate(0.0, 1.0, 0.0);     // Offset from body
    push_rotate_y(tank.turret_angle);  // Independent rotation
    draw_mesh(tank_turret);

    // Barrel (inherits turret transform)
    push_translate(0.0, 0.5, 2.0);
    push_rotate_x(tank.barrel_pitch);
    draw_mesh(tank_barrel);
}
}

Rotating around a pivot point:

#![allow(unused)]
fn main() {
fn render() {
    push_identity();
    push_translate(pivot_x, pivot_y, pivot_z);  // Move to pivot
    push_rotate_y(angle);                        // Rotate
    push_translate(-pivot_x, -pivot_y, -pivot_z); // Move back
    draw_mesh(object);
}
}

Complete Example

#![allow(unused)]
fn main() {
static mut ANGLE: f32 = 0.0;

fn update() {
    unsafe {
        ANGLE += 90.0 * delta_time(); // 90 degrees per second
    }
}

fn render() {
    unsafe {
        camera_set(0.0, 5.0, 10.0, 0.0, 0.0, 0.0);

        // Spinning cube at origin
        push_identity();
        push_rotate_y(ANGLE);
        draw_mesh(cube);

        // Orbiting cube
        push_identity();
        push_rotate_y(ANGLE * 0.5);    // Orbital rotation
        push_translate(5.0, 0.0, 0.0);  // Distance from center
        push_rotate_y(ANGLE * 2.0);     // Spin on own axis
        push_scale_uniform(0.5);
        draw_mesh(cube);

        // Static cube for reference
        push_identity();
        push_translate(-5.0, 0.0, 0.0);
        draw_mesh(cube);
    }
}
}