Skip to content

[Feature] Camera2D and Camera3D with Controllers #83

@vmarcella

Description

@vmarcella

Overview

Provide ready-to-use 2D and 3D camera abstractions that build on the existing scene_math helpers, reducing boilerplate for common rendering scenarios.

Current State

The engine provides low-level matrix helpers in scene_math:

// crates/lambda-rs/src/render/scene_math.rs
pub struct SimpleCamera {
  pub position: [f32; 3],
  pub field_of_view_in_turns: f32,
  pub near_clipping_plane: f32,
  pub far_clipping_plane: f32,
}

pub fn compute_model_matrix(...) -> [[f32; 4]; 4];
pub fn compute_view_matrix(camera_position: [f32; 3]) -> [[f32; 4]; 4];
pub fn compute_perspective_projection_matrix(...) -> [[f32; 4]; 4];

Users must manually compose these these matrices and manage camera state. There is no orthographic projection helper or camera controller abstraction

Scope

Camera2D (Orthographic)

  • Position, zoom, and rotation
  • Orthographic projection with configurable bounds
  • Screen-to-world and world-to-screen coordinate conversion

Camera3D (Perspective)

  • Position, orientation (look-at or Euler angles)
  • Perspective projection with FOV, aspect ratio, near/far planes
  • Orbit mode: rotate around a focal point
  • Fly mode: free movement with orientation

Common Infrastructure

  • Camera trait for unified view-projection matrix access
  • Methods to produce combined VP or MVP matrices
  • Integration (Or re-implementation) of scene_math helpers

Proposed API

// crates/lambda-rs/src/render/camera.rs

pub trait Camera {
  fn view_matrix(&self) -> [[f32; 4]; 4];
  fn projection_matrix(&self) -> [[f32; 4]; 4];
  fn view_projection_matrix(&self) -> [[f32; 4]; 4];
}

pub struct Camera2D {
  pub position: [f32; 2],
  pub zoom: f32,
  pub rotation: f32,  // radians or turns
}

impl Camera2D {
  pub fn new() -> Self;
  pub fn with_position(self, x: f32, y: f32) -> Self;
  pub fn with_zoom(self, zoom: f32) -> Self;
  pub fn orthographic_bounds(&self, width: f32, height: f32) -> [[f32; 4]; 4];
  pub fn screen_to_world(&self, screen: [f32; 2], viewport: [f32; 2]) -> [f32; 2];
  pub fn world_to_screen(&self, world: [f32; 2], viewport: [f32; 2]) -> [f32; 2];
}

pub struct Camera3D {
  pub position: [f32; 3],
  pub target: [f32; 3],      // look-at point
  pub up: [f32; 3],
  pub fov_turns: f32,
  pub aspect_ratio: f32,
  pub near: f32,
  pub far: f32,
}

impl Camera3D {
  pub fn new() -> Self;
  pub fn look_at(position: [f32; 3], target: [f32; 3], up: [f32; 3]) -> Self;
  pub fn with_perspective(self, fov_turns: f32, aspect: f32, near: f32, far: f32) -> Self;
  
  /// Orbit around the current target by yaw/pitch deltas (in turns).
  pub fn orbit(&mut self, yaw_delta: f32, pitch_delta: f32);
  
  /// Move the camera in its local coordinate frame.
  pub fn translate_local(&mut self, delta: [f32; 3]);
}

Example Usage

// 2D orthographic camera for UI or 2D games
let camera_2d = Camera2D::new()
  .with_position(0.0, 0.0)
  .with_zoom(1.0);
let ortho = camera_2d.orthographic_bounds(800.0, 600.0);

// 3D perspective camera looking at origin
let camera_3d = Camera3D::look_at(
  [0.0, 2.0, 5.0],  // position
  [0.0, 0.0, 0.0],  // target
  [0.0, 1.0, 0.0],  // up
).with_perspective(0.125, 16.0 / 9.0, 0.1, 100.0);

let vp = camera_3d.view_projection_matrix();

Acceptance Criteria

  • Camera trait with view, projection, and combined matrix methods
  • Camera2D with orthographic projection and coordinate conversion
  • Camera3D with perspective projection and look-at construction
  • Camera3D::orbit for orbital camera movement
  • Camera3D::translate_local for fly-camera movement
  • Integration with (or re-implementation of) existing scene_math matrix helpers
  • Example demonstrating both camera types
  • Documentation for camera usage patterns

Notes

  • Rotation conventions SHOULD match existing scene-math (right-handed, angles in turns)
  • Camera3D MAY later be extended with Euler angle accessors
  • Controller input handling is out of scope for now; cameras provide state and matrix computation only

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions