A 2D physics engine built on WebGPU (WGSL compute) that couples two solvers in a single, mutually colliding simulation:
- MPM (Material Point Method) — fluids, gases, granular materials, thermodynamics, phase transitions, chemical reactions
- XPBD (Extended Position Based Dynamics) — constraint-based soft/rigid bodies, ropes, cloth, fracture
Scenes are authored by drawing in Excalidraw — shapes tagged with customData.salina import live into the simulation (Sandblaster, the sandbox package).
bun install
cd packages/sandbox && bun run dev # http://localhost:3000 (requires a WebGPU-capable browser)
bun run build # single-file build (dist/index.html) — sandbox only, no routerPhysics tests (GPU, headless Chromium against a running dev server):
bun packages/sandbox/scripts/run-tests.ts # engine + loader unit suite
bun packages/sandbox/scripts/run-benchmarks.ts --suite xpbd-material-stiffness| Area | What works |
|---|---|
| MPM | APIC transfer, per-material EOS (bulk/gamma/pressure caps), 11 materials: water, oil, lava, gravel, junk, splinters + gases (steam, O₂, N₂, CH₄, CO); viscosity, Coulomb friction against obstacles/walls, per-phase damping |
| Thermodynamics | heat conduction (grid + XPBD particle-particle), heaters/coolers, heat exchange with obstacles (opt-in reservoir model), latent heat (water freezing/melting), Boussinesq convection for fluids, gas buoyancy ∝ 1/T, thermal gas jitter ∝ √T |
| Reactions | CH₄+O₂ combustion (concentration grid, burn modifier), evaporation/condensation |
| XPBD | full XPBD with λ accumulation (stiffness independent of iteration count), distance/area/bending/anchor constraints, graph coloring, substeps (small-steps), mesh↔mesh collisions & rope self-collision, fracture with a damage model (accumulation/recovery/propagation), plasticity (yield + creep), 9 solid materials with physically-derived complianceScale (∝ 1/E) and break thresholds |
| MPM↔XPBD coupling | point–segment contact along isBoundary edges (with per-object collidesWithMpm switch), CCD for thin boundaries (ropes don't tunnel fast particles), heat & momentum exchange, saturating fixed-point accumulators |
| Zones | Force Zone (force/gravity/vortex, shape taken from the drawn element), Fan (arrow: apex + direction + range), Heater, Absorber (material filter), Emitter (arrow, rate/radius/particleRadius), enable/disable-on-frame scheduling |
| Queries | MPM radius query (per-material counts + sample) and XPBD (particle sample), raycast, global telemetry |
| Limits | 16,384 XPBD particles, 65,536 constraints, 16,384 MPM particles, 256×256 grid; per-pass dynamic dispatch sizing |
- Live import from Excalidraw (debounced on edit), Editor / Split / Play view modes, resize-aware canvas
- Object kinds: Game Area, Obstacle (SDF: box/circle/ellipse/rhombus/…), XPBD Solid, MPM Fluid/Gas, Force Zone, Fan, Hole, Heater, Absorber, Emitter
- XPBD Solid: material, particle radius/spacing, per-object Stiffness × multiplier, Break strain (physical per-material thresholds via
breakScale), solid/outline fill, cloth-style constraint groups Structural/Shear/Area/Bending (cloth recipe: Structural only), static particles, temperature,Collides with MPM - Geometries: rect/ellipse/diamond/closed polyline → mesh (ellipse segmented by particle spacing); open polyline → rope with resampling (+ bending = wire); image → vectorization (alpha/chroma-key → contour with holes → mesh); Hole — boolean cut of solids at spawn (may extend past the outline)
- Renderer: XPBD colors 1:1 from Excalidraw (with dark-mode filter mapping), per-material MPM palette + incandescence >400°, triangle fill with edge shading and damage tint, Temp/Dens/Vel/Wet overlays auto-ranged from actual scene values, debug views: constraints (graph coloring), objectId, obstacles, zones
- Tools: loupe (MPM+XPBD aggregates: materials, temperature, damage, O₂:CH₄ ratio), solver params panel (F1), stats HUD (FPS, counts, energy, temperatures), New Scene button, friendly error message when WebGPU is unavailable
- In-browser tests/benchmarks:
/tests(73 GPU tests),/benchmarks(XPBD/MPM calibration suites with video artifacts)
packages/schema— single source of truth for GPU layout: schema-pop generates TS + WGSL codecs and buffers from arktype definitions (bun run buildafter any change toschema.ts/materials.ts; never edit generated files by hand)packages/renderer— standalone WebGPU renderer reading the engine's buffers
See ROADMAP.md.