orbit-camera 0.1.0

Third-person orbit/follow camera with pitch-scaled distance, smooth following and geometry clipping
Documentation
  • Coverage
  • 100%
    55 out of 55 items documented1 out of 30 items with examples
  • Size
  • Source code size: 26.48 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 562.55 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 5s Average build duration of successful builds.
  • all releases: 5s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • porky11

orbit-camera

A third-person orbit/follow camera for action-adventure games, extracted from a shared pattern across several games (magic-journey, bad-fates, oneira-woods, cyborg-evolution, ruffy-wonder, open-world-minigolf).

The camera orbits a focus point that smoothly follows a target. Yaw and pitch are set directly; the orbit distance scales with pitch and can be zoomed. Focus and distance interpolate frame-rate independently. An optional clipping pass pulls the camera in when geometry blocks the view.

Design

  • No matrix dependency. view() returns eye, focus, up and projection parameters. Build the view-projection matrix with whatever the renderer uses.
  • Backend-agnostic clipping. clip takes any Clip implementor. Enable the collide-mesh feature for a ready-made impl on collide_mesh::CollisionWorld.
  • Fully configurable. Every constant (pitch range, distances, smoothing, field of view, clip margins) lives in CameraConfig. Default matches a Zelda-style feel.

Built on ga3::Vector<f32>.

Example

use ga3::Vector;
use orbit_camera::OrbitCamera;

let mut camera = OrbitCamera::new(player_position);

// per frame:
camera.rotate([stick.x * sensitivity, stick.y * sensitivity]);
camera.zoom(scroll);
camera.follow(player_position, timestep);
camera.clip(&world); // requires the `collide-mesh` feature, or impl Clip yourself

let view = camera.view();
let view_projection = perspective(view.field_of_view, aspect, view.near_plane, view.far_plane)
    * look_at(view.eye, view.focus, view.up);

// move the player relative to the camera:
let basis = camera.basis();
let movement = basis.forward * input.y + basis.right * input.x;

Features

  • collide-mesh — implement Clip for collide_mesh::CollisionWorld.

AI-coding friendliness

  • Pure-function camera state: view()/basis()/eye() have no side effects.
  • No implicit matrix convention baked in — the consumer owns the projection.
  • Clipping is decoupled behind the one-method Clip trait, so the camera has no hard dependency on any collision backend.