Agent guide - 2D physics and geometry
Choose a supported entry
Section titled “Choose a supported entry”Use @pibbl/core/physics/2d for scheduled bodies/worlds and /physics/2d/geometry for pure shape operations. There is no root physics barrel, Pibbl-owned 3D physics API, renderer-coupled 3D world, or official Three physics binding. Rapier is privately bundled by Pibbl; applications do not initialize or drive it directly.
Read the 2D physics guide for a complete public-browser test fixture and supported manual test harness. Use Stirred Ink for complete application source, or the existing drag-and-throw editor. These sources use public package entries. Do not depend on repository test helpers.
Ownership and coordinate systems
Section titled “Ownership and coordinate systems”PhysicsWorld2D owns one world for its mounted identity. space="root" is the compatibility default; space="local" makes poses, geometry, gravity, and queries relative to the world. Space is creation-only, so changing it requires a new key/lifetime. Parent transforms for a local world must be finite and invertible. Body transforms within the world remain rigid.
Pointer events are root-logical. Convert using toPhysicsPoint2D before a local query or target; use fromPhysicsPoint2D to return. Do not divide by CSS density or assume a Group’s transform has already localized the event.
Dynamic bodies own their pose after mounting. Initial drawing transforms and velocities seed the body; subsequent movement uses commands. Static bodies follow authored geometry. Kinematic bodies follow target signals. Dragging or animation needs an explicit handoff between these owners. Retain body handles and observe enabled/generation; stale handles cannot command a new generation.
Timing and limits
Section titled “Timing and limits”Distances use logical Canvas units, velocities use units per second, angles use degrees, and fixed-step duration uses milliseconds. Gravity defaults to zero. The default world runs 60 fixed ticks per second with at most four catch-up ticks per frame. Sleeping/stationary worlds stop requesting frames; commands wake them through Pibbl scheduling.
The engine uses single-precision values and an internal 100-logical-units-per-meter scale. Use tolerances, not exact floating-point trajectories. CCD helps fast dynamic solids but is bounded: a required substep count above 64 rejects and rolls back. Sensors observe discrete overlaps; use casts for fast triggers. Do not promise arbitrary-speed exact collision detection.
Rounded/elliptical collision shapes use bounded approximations while pure geometry queries retain mathematical shapes. Inspect actual collider bounds when changing visual scale. A physics body with a filter still uses unfiltered logical geometry.
Data flow into textures
Section titled “Data flow into textures”Read committed position in useReaction, normalize it into the texture rectangle, and send displacement messages. Reset previous position on first sample, generation change, or teleport. The body and texture own separate simulation memories. A reaction-diffusion field does not feed forces back into Rapier unless an application explicitly implements and validates that coupling.
Verification
Section titled “Verification”Use inspectPhysics2D outside render to capture JSON-safe body poses, velocities, bounds, contacts, sleep, and failure diagnostics. Inspection does not step or restore the world. PhysicsDebug2D shows authoritative geometry; interpolated presentation can differ between fixed ticks.
Use createPhysicsTestHarness2D from the public testing subpath in an isolated browser fixture. Assert contact/pose/velocity changes with tolerances, then compare presentation. Cover pause, zero gravity, a collision, reset, stale-handle commands, local transforms, and disposal. Report fixed-step configuration and simulated duration with results. A screenshot of a moving ball is not collision evidence.
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.