physics_sandbox
A small, dependency-free rigid-body physics sandbox in Rust. Pluggable
integrators, environment forces (gravity, wind, air density), simple
sphere–sphere collisions, and a tiny event bus for collisions and threshold
triggers. Optional retro ASCII terminal visualization and SVG trajectory
export behind the viz feature.
100 kg missile, v₀ = 500 m/s @ 45°, thrust = 5 kN for 3 s. Generated by
examples/missile_svg.rs. An animated version that draws the trajectory in real time and tracks the body with a moving marker is atdocs/missile_trajectory_animated.svg.
5 drones (2 kg each) in a V formation, cruising at 15 m/s and banking right at t = 12 s. Generated by
examples/drones_formation.rs. Animated version (each drone drawn in real time):docs/drones_formation_animated.svg.
Add it
[]
= "0.1"
# with the terminal visualization + SVG export helpers:
= { = "0.1", = ["viz"] }
Quick start
use ;
let env = new;
let mut world = new;
let id = world.add_body;
for _ in 0..10_000
Modules
| Module | What's in it |
|---|---|
math |
Vec3 and basic linear algebra |
dynamics |
RigidBody, force/torque application, drag |
environment |
Gravity, wind, air density |
integrator |
Integrator trait, EulerIntegrator, RK4Integrator |
collision |
Sphere–sphere collision tests |
events |
EventBus, SimEvent, threshold triggers |
viz (opt.) |
AsciiScope, MultiView, Recorder, MultiRecorder |
Examples
# Plain numeric output
# Visualization (requires the `viz` feature)
Visualization API at a glance
use ;
// 2D ortho scope
let mut scope = new;
// 3D perspective scope (depth-buffered, with a ground reference grid)
let mut scope3d = new_3d
.with_ground_grid;
// Three-panel instrument cluster (SIDE X-Y, TOP X-Z, FRONT Z-Y).
// The most readable option for 3D trajectories in a terminal.
let mut cluster = three_view;
// Record samples during the sim and export an SVG report at the end.
let mut rec = new;
rec.push;
rec.export_svg?;
rec.export_svg_animated?; // SMIL-animated
// Multiple parallel trajectories (e.g. drones in formation) on one SVG,
// each in its own color.
use MultiRecorder;
let mut multi = new;
let lead = multi.add_track;
let wing = multi.add_track;
multi.push;
multi.push;
multi.export_svg?;
multi.export_svg_animated?;
Accuracy knobs
The defaults match v0.1.x: uniform gravity, constant air density. Opt into
higher-fidelity physics on the Environment:
use ;
let env = earth
// ρ(h) = ρ₀·exp(-h / 8500 m) — drag falls off correctly with altitude
.with_exponential_atmosphere
// |g(h)| = 9.81 · (R / (R+h))² — matters above a few km
.with_inverse_square_gravity;
Rotational dynamics now include the gyroscopic / Euler term ω × (I·ω),
so a torque-free body with non-equal principal moments of inertia
precesses correctly and conserves both angular momentum and rotational
kinetic energy (verified by rk4_conserves_angular_momentum_for_torque_free_asymmetric_body).
Threshold events (add_speed_threshold, add_altitude_threshold) are
edge-triggered: they fire on the step the value crosses the threshold,
not every step it stays past it.
Features
viz— opt-in terminal visualization and SVG export. Pulls incrosstermfor live rendering; the SVG path is pure Rust string output and adds no extra deps. Gives you:AsciiScope— 2D ortho or 3D perspective, depth-buffered, motion trails with per-cell aging so trails always read against the ground.MultiView— three side-by-side ortho panels (SIDE / TOP / FRONT) for clear readout of 3D trajectories without fighting perspective.Recorder+export_svg— record(t, pos, phase)samples during the sim, then write a 2×2 SVG (SIDE / TOP / FRONT / summary box) with axis ticks, gridlines, color-coded boost/coast segments and an impact marker. All panels share the same nice-rounded span and matching tick labels so axis scales read 1:1.MultiRecorder+export_svg— same SVG layout but with multiple independently-colored tracks for fleet/formation runs. Each track gets a hollow start ring, a filled end dot, and a legend entry in the summary panel.Recorder::export_svg_animated/MultiRecorder::export_svg_animated— same layout, but emits SMIL<animate>+<animateMotion>so each path is drawn progressively (real-time playback, looped) with a dot following the body's current position. Renders inline in GitHub README previews and any SMIL-capable browser.
License
Dual-licensed under either of:
- MIT license (LICENSE-MIT)
- Apache License, Version 2.0 (LICENSE-APACHE)
at your option.