A cube falls onto a plane: the box3d Plugin, Rigidbody and Box_Collider lifecycle, and the fixed step (#71) #103

Merged
crowmaki merged 1 commit from issue-71-box3d-plugin into main 2026-09-07 00:28:22 +00:00
Owner

Closes #71. Part of #67.

What

  • plugins/box3d/ is the box3d Plugin. It publishes cinnabar.physics/1 with fixed_delta and body_count, registers the Rigidbody and Box_Collider Schemas in register, creates the Box3D world in init and destroys it in shutdown.
  • Rigidbody.on_add builds a dynamic body at the owner's World Transform with the Component Handle as the Body User Tag, sets Wants Destroy on itself when the owner already has a Rigidbody, and takes over the Implicit Static Body the owner's colliders hung from. Box_Collider.on_add builds a box hull on the owner's body or on an Implicit Static Body shared by every collider on that GameObject and destroyed with the last. Both on_remove hooks destroy what they own and skip what a body's destruction already took.
  • fixed_update steps the world with four substeps and writes rotation and translation back through gameobject_set_world_transform, keeping the scale the transform had. No interpolation.
  • justfile packages entry, a glossary sentence on Implicit Static Body, and a dated note on ADR-0016.

Tests

tests/core/box3d_plugin_test.odin, all Headless: the falling cube rests on the plane; a collider-only plane never moves; removing a Rigidbody or destroying its GameObject lowers body_count by one at the flush while the other cube keeps falling; a second Rigidbody has Wants Destroy set and is gone at the flush; a collider added before its Rigidbody migrates onto the real body; a scaled GameObject keeps its scale; the Interface reports the fixed delta; two Engines produce bit-identical World Transforms.

Deviations from the issue wording

  • Defaults fill only fields still at zero. on_add runs after a Scene document's authored values land, so unconditional defaults would clobber every loaded half extent. Consequence: a document cannot author gravity_scale 0 yet. body_type is always Dynamic, since its zero value is Static; kinematic and static Rigidbodies are follow-up work.
  • The test's plane is loaded from a scene document for the same reason: a hand-added Component has its hull built before its fields can be set.
  • The resting-height check allows Box3D's 0.005 linear slop below the half-extent bound, and the scale check uses a 1e-4 tolerance because the f32 quaternion write-back is not bit-exact. The determinism test is bit-exact.
  • Removing a Rigidbody leaves its owner's colliders shapeless rather than re-hanging them on an Implicit Static Body, because the criterion requires body_count to drop by one.

Verification

just check passes. Core suite 360 tests, platform, vulkan_backend, imgui and luau suites all pass. Two shaderc tests fail on main too (locally stale committed shader output); unrelated.

Closes #71. Part of #67. ## What - `plugins/box3d/` is the `box3d` Plugin. It publishes `cinnabar.physics/1` with `fixed_delta` and `body_count`, registers the `Rigidbody` and `Box_Collider` Schemas in `register`, creates the Box3D world in `init` and destroys it in `shutdown`. - `Rigidbody.on_add` builds a dynamic body at the owner's World Transform with the Component Handle as the Body User Tag, sets Wants Destroy on itself when the owner already has a `Rigidbody`, and takes over the Implicit Static Body the owner's colliders hung from. `Box_Collider.on_add` builds a box hull on the owner's body or on an Implicit Static Body shared by every collider on that GameObject and destroyed with the last. Both `on_remove` hooks destroy what they own and skip what a body's destruction already took. - `fixed_update` steps the world with four substeps and writes rotation and translation back through `gameobject_set_world_transform`, keeping the scale the transform had. No interpolation. - justfile `packages` entry, a glossary sentence on Implicit Static Body, and a dated note on ADR-0016. ## Tests `tests/core/box3d_plugin_test.odin`, all Headless: the falling cube rests on the plane; a collider-only plane never moves; removing a `Rigidbody` or destroying its GameObject lowers `body_count` by one at the flush while the other cube keeps falling; a second `Rigidbody` has Wants Destroy set and is gone at the flush; a collider added before its `Rigidbody` migrates onto the real body; a scaled GameObject keeps its scale; the Interface reports the fixed delta; two Engines produce bit-identical World Transforms. ## Deviations from the issue wording - Defaults fill only fields still at zero. `on_add` runs after a Scene document's authored values land, so unconditional defaults would clobber every loaded half extent. Consequence: a document cannot author `gravity_scale 0` yet. `body_type` is always Dynamic, since its zero value is Static; kinematic and static Rigidbodies are follow-up work. - The test's plane is loaded from a scene document for the same reason: a hand-added Component has its hull built before its fields can be set. - The resting-height check allows Box3D's 0.005 linear slop below the half-extent bound, and the scale check uses a 1e-4 tolerance because the f32 quaternion write-back is not bit-exact. The determinism test is bit-exact. - Removing a `Rigidbody` leaves its owner's colliders shapeless rather than re-hanging them on an Implicit Static Body, because the criterion requires `body_count` to drop by one. ## Verification `just check` passes. Core suite 360 tests, platform, vulkan_backend, imgui and luau suites all pass. Two shaderc tests fail on `main` too (locally stale committed shader output); unrelated.
Closes #71. Part of #67.

plugins/box3d is the box3d Plugin. It publishes cinnabar.physics/1 with
fixed_delta and body_count, registers the Rigidbody and Box_Collider Schemas
in register, creates the Box3D world in init and destroys it in shutdown.

Rigidbody's on_add builds a dynamic body at the owner's World Transform with
the Component Handle as the Body User Tag, refuses a second Rigidbody on one
GameObject by setting Wants Destroy on itself, and takes over the Implicit
Static Body the owner's colliders hung from. Box_Collider's on_add builds a
box hull on the owner's body or on an Implicit Static Body shared by every
collider on that GameObject. Both on_remove hooks destroy what they own and
skip what a body's destruction already took. fixed_update steps the world
with four substeps and writes rotation and translation back through
gameobject_set_world_transform, keeping the scale the transform had.

Defaults fill only fields still at zero, so a Scene document's authored
values survive on_add; body_type is always Dynamic for now. The tests cover
the falling cube, an unmoving collider-only plane, removal and destruction
lowering body_count, the duplicate Rigidbody, a collider added before its
Rigidbody, scale after write-back, the fixed delta, and bit-identical
transforms across two Engines. ADR-0016 carries a dated note.
crowmaki deleted branch issue-71-box3d-plugin 2026-09-07 00:28:22 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
crowmaki/cinnabar!103
No description provided.