Rust · no physics crate · no math crate
Newton is a 2D physics engine in Rust built entirely from scratch. The integrator, the collision detection, and the impulse resolution are all plain code you can read start to finish, with no engine dependency underneath.
click or tap the canvas to drop a ball · same integrator and impulse resolution as the Rust engine
Click or tap anywhere on the canvas to drop a new ball. Balls fall under gravity, collide with each other and the walls, and settle into rest. Drag the Gravity and Restitution sliders to change how hard they fall and how bouncy they are, and press Reset to clear the scene. Everything runs the same semi-implicit Euler integrator and impulse solver as the Rust engine.
Three steps run every frame, in this order, with no shortcuts taken.
Semi-implicit Euler: gravity updates velocity first, then the new velocity moves position. Stable under constant acceleration where explicit Euler drifts.
Every circle pair is checked against the sum of their radii. Walls are checked as four half-plane tests against the bounding box.
An impulse along the collision normal separates the pair by mass and restitution, then a small positional correction removes any leftover overlap so bodies do not sink.
The CLI builds a small demo scene, steps it forward, and prints where every body ends up. This is a real run.
$ cargo run -- run --steps 300
newton: ran 300 steps at dt=0.01667
body 0: pos=(6.000, 2.985) vel=(0.000, -0.041) radius=1.00 mass=1.00 restitution=0.60
body 1: pos=(6.000, 0.997) vel=(0.000, -0.163) radius=1.00 mass=1.00 restitution=0.60
body 2: pos=(14.000, 1.500) vel=(0.000, 0.000) radius=1.50 mass=2.00 restitution=0.40
body 3: pos=(10.000, 1.000) vel=(0.000, 0.000) radius=1.00 mass=1.00 restitution=0.30
Bodies 2 and 3 have come to rest exactly one radius above the floor with zero velocity, at rest instead of tunneling through.
Not the fastest engine. The one whose every line you can follow.
No physics crate and no math crate. The vector type, the integrator, and the impulse solver are plain Rust in this repo, readable top to bottom.
Velocity updates before position on every step. It stays stable under constant gravity where plain explicit Euler drifts and quietly gains energy.
A fixed timestep and the same step order every frame: integrate, resolve walls, resolve pairs. No NaNs, no panics, and resting bodies actually rest.
Circles only, one solver, positional correction with a small slop term. Small enough to verify against real physical laws, and it is.
Five behaviors are asserted directly against the simulation, not eyeballed from a screen.
A body with no initial velocity gains downward speed and moves toward the floor, step by step.
A dropped body comes to rest just above the floor line and never tunnels through it, even at high fall speed.
Two equal-mass bodies in a head-on elastic collision swap velocities within a small tolerance, the textbook case.
The sum of mass times velocity across a collision matches before and after, to within floating-point tolerance.
A ball bouncing with restitution under 1.0 reaches a lower peak height on each successive bounce.
# from the project root
cargo test
The same engine behind a library API, a CLI, and this browser demo.
Add bodies to a World and call step(dt). The public types are World, Body, Vec2, and Bounds.
cargo run -- run --steps N --dt D builds a demo scene, steps it, and prints the final state of every body.
cargo test runs the suite that asserts gravity, resting, velocity exchange, momentum conservation, and energy loss below restitution 1.
This page runs a JavaScript port of the same integrator and impulse solver on a canvas, with no build step at all.