tiramisu/transform
Transform module - position, rotation, and scale for 3D objects.
Transforms define where objects are in 3D space, how they’re rotated, and their size. All transforms are immutable - functions return new transforms instead of modifying existing ones.
Quick Example
import tiramisu/transform
import vec/vec3
let player_transform = transform.identity
|> transform.set_position(vec3.Vec3(0.0, 1.0, 0.0))
|> transform.set_rotation(vec3.Vec3(0.0, 1.57, 0.0)) // 90 degrees in radians
|> transform.set_scale(vec3.Vec3(1.0, 2.0, 1.0)) // Tall player
Types
Transform represents the position, rotation, and scale of an object in 3D space.
- position: World-space coordinates (x, y, z)
- rotation: Euler angles in radians (pitch, yaw, roll / x, y, z)
- scale: Size multiplier per axis (1.0 = original size)
pub type Transform {
Transform(
position: vec3.Vec3(Float),
rotation: vec3.Vec3(Float),
scale: vec3.Vec3(Float),
)
}
Constructors
Values
pub fn at(position position: vec3.Vec3(Float)) -> Transform
Create a transform at a specific position with default rotation and scale.
Example
let t = transform.at(position: vec3.Vec3(5.0, 0.0, -3.0))
// Object positioned at (5, 0, -3)
pub fn compose(first: Transform, second: Transform) -> Transform
Compose two transforms (apply second transform after first).
Useful for relative transformations. Note: This is a simplified composition
that adds positions/rotations and multiplies scales. For proper hierarchical
transforms, use scene Group
nodes instead.
Example
let base = transform.at(vec3.Vec3(5.0, 0.0, 0.0))
let offset = transform.at(vec3.Vec3(0.0, 2.0, 0.0))
let combined = transform.compose(base, offset)
// position: (5.0, 2.0, 0.0)
pub const identity: Transform
Create an identity transform (position at origin, no rotation, scale 1).
Example
let t = transform.identity
// position: (0, 0, 0), rotation: (0, 0, 0), scale: (1, 1, 1)
pub fn lerp(
from: Transform,
to to: Transform,
with t: Float,
) -> Transform
Linearly interpolate between two transforms.
Useful for smooth animations and transitions. Parameter t
should be between 0.0 and 1.0:
t = 0.0
returnsfrom
t = 1.0
returnsto
t = 0.5
returns halfway between
Example
let start = transform.at(vec3.Vec3(0.0, 0.0, 0.0))
let end = transform.at(vec3.Vec3(10.0, 0.0, 0.0))
let halfway = transform.lerp(start, to: end, with: 0.5)
// position: (5.0, 0.0, 0.0)
pub fn look_at(
from from: vec3.Vec3(Float),
to to: vec3.Vec3(Float),
) -> Transform
Create a transform that looks at a target position from a source position.
Calculates the rotation needed to point from from
towards to
.
Uses proper Euler angle conversion with atan2 for stable results.
Returns rotation in radians (pitch, yaw, roll) where:
- Pitch (X): rotation around X axis (looking up/down)
- Yaw (Y): rotation around Y axis (turning left/right)
- Roll (Z): rotation around Z axis (typically 0 for look-at)
Example
let camera_pos = vec3.Vec3(0.0, 5.0, 10.0)
let target_pos = vec3.Vec3(0.0, 0.0, 0.0)
let look_transform = transform.look_at(from: camera_pos, to: target_pos)
// Camera now faces the origin
pub fn rotate_by(
transform: Transform,
rotation: vec3.Vec3(Float),
) -> Transform
Rotate a transform by adding to its current rotation (relative rotation).
Example
let t = transform.identity
|> transform.rotate_by(vec3.Vec3(0.0, 1.57, 0.0)) // Turn 90° right
|> transform.rotate_by(vec3.Vec3(0.0, 1.57, 0.0)) // Turn another 90° right
// rotation: (0.0, 3.14, 0.0) - now facing backward
pub fn rotate_x(transform: Transform, angle: Float) -> Transform
Rotate around the X axis (pitch/look up-down).
Example
let t = transform.identity
|> transform.rotate_x(0.5) // Look up slightly
pub fn rotate_y(transform: Transform, angle: Float) -> Transform
Rotate around the Y axis (yaw/turn left-right).
Example
let t = transform.identity
|> transform.rotate_y(1.57) // Turn 90° right
pub fn rotate_z(transform: Transform, angle: Float) -> Transform
Rotate around the Z axis (roll/tilt left-right).
Example
let t = transform.identity
|> transform.rotate_z(0.3) // Tilt right
pub fn scale_by(
transform: Transform,
scale_factor: vec3.Vec3(Float),
) -> Transform
Scale a transform by multiplying its current scale (relative scaling).
Example
let t = transform.identity
|> transform.scale_by(vec3.Vec3(2.0, 1.0, 2.0))
|> transform.scale_by(vec3.Vec3(2.0, 1.0, 1.0))
// scale: (4.0, 1.0, 2.0)
pub fn scale_uniform(
transform: Transform,
scale: Float,
) -> Transform
Set uniform scale on all axes (width = height = depth).
Example
let t = transform.identity
|> transform.scale_uniform(2.0)
// scale: (2.0, 2.0, 2.0) - twice as big in all dimensions
pub fn translate(
transform: Transform,
by offset: vec3.Vec3(Float),
) -> Transform
Move a transform by adding to its current position (relative movement).
Example
let t = transform.at(vec3.Vec3(5.0, 0.0, 0.0))
|> transform.translate_by(vec3.Vec3(2.0, 1.0, 0.0))
// position: (7.0, 1.0, 0.0)
pub fn with_position(
transform: Transform,
position: vec3.Vec3(Float),
) -> Transform
Update the position of a transform.
Example
let moved = transform.identity
|> transform.set_position(vec3.Vec3(1.0, 2.0, 3.0))
pub fn with_rotation(
transform: Transform,
rotation: vec3.Vec3(Float),
) -> Transform
Update the rotation of a transform (Euler angles in radians).
Example
let rotated = transform.identity
|> transform.set_rotation(vec3.Vec3(0.0, 1.57, 0.0)) // 90° turn around Y axis