The falling-cubes sample: a Scene of GameObjects dropping cubes onto a plane (#74) #106

Merged
crowmaki merged 3 commits from issue-74-falling-cubes-sample into main 2026-09-07 01:10:42 +00:00
Owner

Closes #74, the last child of #67.

The sample

sample_scene requires the mesh and Physics Interfaces and builds a Scene of GameObjects: a static plane with a wide, thin Box_Collider and a Mesh_Renderer on the shared cube mesh scaled by its local transform, and a fixed camera framing the plane and the drop column. It has no draw hook and never submits.

Spawning runs in fixed_update: the first cube on the first fixed step, then one every spawn interval of fixed steps. Each cube is a GameObject at the drop height with a seeded random offset inside the spawn radius, a uniformly random unit quaternion (Shoemake), a random colour, and Mesh_Renderer, Rigidbody (Dynamic) and Box_Collider (half extents 0.5). A cube whose World Transform falls 20 m under the plane is destroyed.

Params is seed, spawn interval, drop height, spawn radius and plane half extent. -instances and -degeneracy go (reported as unknown flags), -seed:N arrives, -frames and -dump-frame stay. app.scene_plugins lists mesh_pipeline, box3d, sample_scene, then controls, with a comment on which orderings Core enforces.

The plane's collider arrives by a Scene Document: the box3d Plugin builds the hull in on_add, which component_add runs before the caller can write half extents, so a document is the one path that lands the authored extents first. A comment in the sample records this.

mat4_translate and mat4_from_quaternion join mat4_mul in core/math.

Tests

All eight acceptance criteria are covered in tests/core/sample_test.odin: plane plus one cube at the first frame and N+1 cubes after N seconds; spawn interval as a parameter; two cubes differ in colour and rotation; a cube descends and settles within the resting range and then stays; a cube that misses the plane is destroyed; the same seed reproduces Draw Records bit for bit and a different seed does not; every cube's corners are inside the clip volume on its spawn tick; listing sample_scene before box3d fails engine_init. The winding, projection and vertex-layout tests survive; the grid, hero, instance and degeneracy tests are gone.

One deviation from the acceptance text: a mis-ordered list fails with Requires_Order_Violation, which is what Core's existing requires-order check produces. Missing_Interface is only reported when nobody publishes the Interface at all.

imgui_test listed the sample without a physics Plugin and now lists box3d.

Shader test failures

tests/shaderc compared the committed generated Odin and shaders/cinnabar.slang byte for byte against the generator, which writes LF, while core.autocrlf=true checked them out as CRLF. A .gitattributes with * text=auto eol=lf pins every text file to LF on checkout. The index was already LF, so no committed content changed.

just all passes. The headless sample runs to its frame budget and the windowed sample runs 240 frames and quits cleanly.

Closes #74, the last child of #67. ## The sample `sample_scene` requires the mesh and Physics Interfaces and builds a Scene of GameObjects: a static plane with a wide, thin `Box_Collider` and a `Mesh_Renderer` on the shared cube mesh scaled by its local transform, and a fixed camera framing the plane and the drop column. It has no `draw` hook and never submits. Spawning runs in `fixed_update`: the first cube on the first fixed step, then one every spawn interval of fixed steps. Each cube is a GameObject at the drop height with a seeded random offset inside the spawn radius, a uniformly random unit quaternion (Shoemake), a random colour, and `Mesh_Renderer`, `Rigidbody` (Dynamic) and `Box_Collider` (half extents 0.5). A cube whose World Transform falls 20 m under the plane is destroyed. `Params` is seed, spawn interval, drop height, spawn radius and plane half extent. `-instances` and `-degeneracy` go (reported as unknown flags), `-seed:N` arrives, `-frames` and `-dump-frame` stay. `app.scene_plugins` lists `mesh_pipeline`, `box3d`, `sample_scene`, then controls, with a comment on which orderings Core enforces. The plane's collider arrives by a Scene Document: the `box3d` Plugin builds the hull in `on_add`, which `component_add` runs before the caller can write half extents, so a document is the one path that lands the authored extents first. A comment in the sample records this. `mat4_translate` and `mat4_from_quaternion` join `mat4_mul` in `core/math`. ## Tests All eight acceptance criteria are covered in `tests/core/sample_test.odin`: plane plus one cube at the first frame and N+1 cubes after N seconds; spawn interval as a parameter; two cubes differ in colour and rotation; a cube descends and settles within the resting range and then stays; a cube that misses the plane is destroyed; the same seed reproduces Draw Records bit for bit and a different seed does not; every cube's corners are inside the clip volume on its spawn tick; listing `sample_scene` before `box3d` fails `engine_init`. The winding, projection and vertex-layout tests survive; the grid, hero, instance and degeneracy tests are gone. One deviation from the acceptance text: a mis-ordered list fails with `Requires_Order_Violation`, which is what Core's existing requires-order check produces. `Missing_Interface` is only reported when nobody publishes the Interface at all. `imgui_test` listed the sample without a physics Plugin and now lists `box3d`. ## Shader test failures `tests/shaderc` compared the committed generated Odin and `shaders/cinnabar.slang` byte for byte against the generator, which writes LF, while `core.autocrlf=true` checked them out as CRLF. A `.gitattributes` with `* text=auto eol=lf` pins every text file to LF on checkout. The index was already LF, so no committed content changed. `just all` passes. The headless sample runs to its frame budget and the windowed sample runs 240 frames and quits cleanly.
sample_scene now requires the mesh and Physics Interfaces and builds its
Scene from GameObjects: a static plane whose wide Box_Collider arrives by
Scene Document, and one cube per spawn interval of fixed steps, each with a
Mesh_Renderer, a Dynamic Rigidbody and a Box_Collider at a seeded random
offset, orientation and colour. Cubes that fall well below the plane are
destroyed. The sample has no draw hook; the mesh pipeline draws it.

Params become seed, spawn interval, drop height, spawn radius and plane
half extent. -instances and -degeneracy go, -seed:N arrives, and both
executables list mesh_pipeline, box3d, sample_scene, then controls.
crowmaki deleted branch issue-74-falling-cubes-sample 2026-09-07 01:10:42 +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!106
No description provided.