
type Id = Ball | Floor
bodies : List ( Id, Body )
bodies =
[ ( Ball
, Physics.sphere
(Sphere3d.atOrigin (Length.meters 0.5))
Material.rubber
|> Physics.moveTo (Point3d.meters 0 0 5)
)
, ( Floor, Physics.plane Plane3d.xy Material.wood )
]
step model =
let
( newBodies, newContacts ) =
Physics.simulate
{ onEarth | contacts = model.contacts }
model.bodies
in
{ model | bodies = newBodies, contacts = newContacts }simulate is a function, not a stateful world; deterministic, replayable, time-travel friendly.List ( id, Body ); add with (::), remove with List.filter.WorldCoordinates and BodyCoordinates apart, and forces, masses, velocities, and durations all carry units.Shape.plus / minus / sum and per-shape densities; mass, center of mass, and the full inertia tensor are derived for you.constrain and collide as functions to simulate; the engine asks per body-pair what applies, so there's no constraint registry and no filter-group API.simulate for stable stacks.Inspired by Cannon.js and Bullet — this project is an experiment in what a purely functional 3D physics engine can look like.