Skip to main content
Version: Next 🚧

Camera

Murali's camera is pure state — no input handling, no magic. It owns a position, a target, and a projection mode. The scene owns the camera.

scene.camera_mut().position = Vec3::new(0.0, 0.0, 10.0);

Projection modes

Orthographic (default)

The default for 2D math scenes. Objects don't shrink with distance — only view_width controls how much of the world is visible.

use murali::engine::camera::{Camera, Projection};

scene.camera_mut().projection = Projection::Orthographic {
width: 16.0, // visible world units horizontally
height: 9.0, // visible world units vertically
near: -100.0,
far: 100.0,
};

The default is width: 16.0, height: 9.0 — giving a canonical [-8, 8] × [-4.5, 4.5] world space. Moving the camera position in orthographic mode does not change what's visible. Use set_view_width instead.

Perspective

For 3D scenes where depth perception matters.

scene.camera_mut().projection = Projection::Perspective {
fov_y_rad: std::f32::consts::FRAC_PI_4, // 45°
aspect: 16.0 / 9.0,
near: 0.1,
far: 1000.0,
};

Controlling the viewport (orthographic)

set_view_width — the ground truth

Controls how much of the world is visible horizontally. Height is derived automatically to maintain 16:9.

scene.camera_mut().set_view_width(8.0); // zoom in — less world visible, objects appear larger
scene.camera_mut().set_view_width(24.0); // zoom out — more world visible, objects appear smaller

view_width — the getter

let w = scene.camera().view_width(); // 16.0 by default

Useful for relative adjustments:

// Zoom in to half the current view
scene.camera_mut().set_view_width(scene.camera().view_width() * 0.5);

zoom_in / zoom_out

Convenience wrappers around set_view_width. The factor describes how much larger or smaller objects appear.

scene.camera_mut().zoom_in(2.0); // objects appear 2× bigger (width /= 2)
scene.camera_mut().zoom_out(2.0); // objects appear 2× smaller (width *= 2)

Positioning the camera

scene.camera_mut().position = Vec3::new(0.0, 0.0, 10.0); // standard 2D setup
scene.camera_mut().target = Vec3::ZERO; // look at origin
scene.camera_mut().up = Vec3::Y; // Y is up

For 2D scenes, keep position.z positive and target at the origin. The Z value doesn't affect orthographic rendering but is needed for the view matrix.

For 3D scenes, orbit freely — the preview window's orbit controller handles mouse drag automatically.

Animating the camera

Camera animations go through the timeline like any other animation:

timeline
.animate_camera()
.at(0.0)
.for_duration(2.0)
.ease(Ease::InOutQuad)
.move_to(Vec3::new(2.0, 1.0, 10.0))
.spawn();

Available camera animation kinds:

MethodEffect
.move_to(Vec3)Animate camera position
.look_at(Vec3)Animate camera target
.frame_to(position, target)Animate both position and target together
.zoom_to(width)Animate orthographic view width
.fov_to(radians)Animate perspective field of view

Example — zoom in over 2 seconds:

timeline
.animate_camera()
.at(1.0)
.for_duration(2.0)
.ease(Ease::InOutCubic)
.zoom_to(8.0) // from default 16.0 → 8.0
.spawn();

Preview controls

When running in preview mode, the camera is controlled by mouse input:

ActionEffect
Left dragOrbit (3D)
ScrollZoom
Right dragPan