feat: add crate-stack and stone-archway showcase pieces - #199
Merged
Merged
Conversation
Three shipping crates stacked, built by one generator called three times with a per-instance seed. The subject is reuse with variation: the seed drives yaw and plank widths so the crates read as three of the same design rather than one model pasted three times, and the README says plainly that true instancing and per-instance geometry variation are mutually exclusive. Budgets recomputed from the finished mesh, measured before they were written: 4380 tris, 2 materials with 216 iron and 2436 timber faces, UVs in 0..1 with zero overlap, outer AABB 0.658x0.524x0.704 m, each crate's own footprint 0.585x0.425 m in its own frame, three ground runners at z=0, both crate-to-crate seats overlapping, LOD ratios in band, 202-tri collider, non-empty glTF, and hygiene zero across loose/non-manifold/zero-area/ doubles/n-gons/coplanar-disjoint. Six falsifiers, each breaking one named budget, all proven on 4.5.11, 5.1.2 and 5.2.1 with identical exit codes: --skip-decimate 9, --stray-vert 15, --lift-z 16, --short-skids 16, --float-stack 18, --same-seed 20. Three findings the budgets forced, all documented in the README: - Shape filters had to move to principal axes. Every part is axis-aligned in its crate's frame then rotated about Z, so a world-AABB filter measures the rotated box: a 0.554 m board yawed 0.09 rad reports 0.061 m of depth instead of 0.013 m, and every thickness-keyed filter matched nothing. - Stack levels had to be clustered from the runners the mesh actually has. Binning against the declared pitch put a lid on the wrong level as soon as a falsifier shifted a crate, and the seat budget then compared a crate against itself. - find_doubles caught two real joints, not false positives: the corner straps sat flush with the post corner, and the lid rested exactly on the rail top. Both now bite into their host. Falsifiers were also retuned so each fails on its own budget rather than on an earlier check: the stray vertex sits inside the silhouette, --short-skids floats one of three runners so the AABB still grounds, and --same-seed collapses only the design stream while placement stays per-instance so the footprint is unchanged. LOD2 is the one value that differs across versions (878 tris on 5.2, 934 on 4.5 and 5.1) — DECIMATE COLLAPSE, which is why the gate is a ratio band. Adds ~1.0 s to smoke on 4.5/5.1 and ~1.2 s on 5.2. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Building the contact sheet against the pinned calibration set (armature-bend, damped-track-aim, bmesh-gear) showed the wedge reading as a cool grey band rather than the warm pool the house style calls for. Move it closer to the backdrop, raise it to 560 W, and shift its colour to (1.0, 0.72, 0.40). Lighting only — no geometry, no budget, no assertion, no exit code changes. Mean luminance 0.2185, inside the calibration band [0.1722, 0.3048]. Hero and preview re-rendered; contact sheet committed under docs/gallery/contact-sheets/. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
A freestanding masonry arch: two coursed piers, projecting imposts, nine voussoirs turning a semicircle, and a keystone standing proud at the crown. The headline budget is the one an arch can fail invisibly. Nine wedge blocks laid in a row are still nine wedge blocks; what makes them an arch is that their intrados vertices sit on a circle. The piece recomputes that circle from vertex positions rather than from the angles the generator used, and asserts every intrados vertex lands within 4 mm of the declared 0.60 m radius over an arc of at least 168 degrees. Measured: 0.97 mm over 178.0 degrees. Other budgets, all recomputed: 924 tris, two materials with 182 dressed and 364 ashlar faces, UVs in 0..1 with zero overlap, outer AABB 1.644x0.510x2.057 m, clear opening 1.203 m, both piers grounded, the springing joint an overlap, all eight mortar joints at 9.70 mm inside a 6-17 mm band, 168-tri collider, non-empty glTF, and hygiene zero across loose/non-manifold/zero-area/doubles/n-gons/coplanar-disjoint. Seven falsifiers, each breaking one named budget, all proven on 4.5.11, 5.1.2 and 5.2.1 with identical exit codes: --skip-decimate 9, --stray-vert 15, --lift-z 16, --float-pier 16, --sink-keystone 17, --wide-mortar 18, --off-circle 19. Four findings the budgets forced, all documented in the README: - bmesh.ops.bevel gives every face it creates material_index 0. Chamfering nineteen blocks left 30 faces on the dressed slot and moved 464 to ashlar; the slot count and the distinct-material check both still passed. Only the per-material face floor caught it. Materials are now re-stamped per block after the bevel. - The impost landed exactly on the top course — same footprint, same plane, coincident face centres. It now sits on its own mortar bed. - BVHTree.find_nearest is unsigned, so a voussoir seated inside the pier head reported a 5.4 mm gap where there was none. Joint gaps now test overlap first. - Joint gaps need measuring both ways: the keystone's radial faces are wider in Y than its neighbours', so every keystone vertex on the joint lies outside the neighbour and read 33 mm instead of 9.7 mm. Three falsifiers needed the model changed rather than the budget loosened. --sink-keystone originally shrank the Y bounding box and tripped the AABB gate, so imposts were added to own the envelope — correct masonry the arch was missing. --off-circle began as --flat-arch, which is 0.62 m shorter and also fails on the bounding box, proving nothing about the circle fit. --float-pier tripped the z-fight budget because the impost was pinned to an absolute height while its courses rose into it. LOD2 is the one value that differs across versions (196 tris on 5.2, 202 on 4.5 and 5.1) — DECIMATE COLLAPSE, which is why the gate is a ratio band. Adds ~0.82 s to smoke on 4.5, ~0.85 s on 5.1, ~0.98 s on 5.2. All 28 showcase pieces together run in 20.9 s on 5.2.1. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Mark crate-stack and stone-archway shipped, and restock the pool with four subjects identified while building them: rope bridge, grain sacks, brazier, apothecary shelf. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two showcase pieces, one commit each, taking the tree from 26 to 28. Every number below was measured on a local binary before the budget band around it was written.
Binaries:
.scratch/blender-4.5.11-windows-x64/blender.exe(Blender 4.5.11 LTS),.scratch/blender-5.1.2-windows-x64/blender.exe(Blender 5.1.2),.scratch/blender-5.2.1-windows-x64/blender.exe(Blender 5.2.1 LTS) — versions as the binaries report them.45 of 45 cases green: 2 pieces × 15 cases (1 default + 6 or 7 falsifiers) × 3 versions, every exit code identical on all three.
crate-stackThree shipping crates stacked, from one generator called three times with a per-instance seed. The seed drives yaw and plank widths, so the crates read as three of the same design rather than one model pasted three times.
The README says plainly what this can and cannot be: true instancing (three objects sharing one mesh datablock) and per-instance geometry variation are mutually exclusive. The piece takes the variation; the shipped asset is the flattened single mesh an engine receives.
Budgets — declared vs measured (5.2.1)
Falsifiers — same exit on 4.5.11 / 5.1.2 / 5.2.1
--skip-decimate--stray-vert--lift-z--short-skids--float-stack--same-seedstone-archwayCoursed piers, projecting imposts, nine voussoirs turning a semicircle, and a keystone standing proud at the crown.
The headline budget is the one an arch can fail invisibly. Nine wedge blocks in a row are still nine wedge blocks; what makes them an arch is that their intrados vertices sit on a circle. The piece recomputes that circle from vertex positions rather than from the angles the generator used.
--off-circleexists for exactly that. It keeps the angles, joints, materials, triangle count and bounding box identical and only wanders the intrados radius by 18 mm. Every other budget still passes. Only the circle fit sees it.Budgets — declared vs measured (5.2.1)
Falsifiers — same exit on 4.5.11 / 5.1.2 / 5.2.1
--skip-decimate--stray-vert--lift-z--float-pier--sink-keystone--wide-mortar--off-circleWhat the budgets caught
These are defects the gates found in my own work, not hypotheticals.
bmesh.ops.bevelsilently repainted 94% of the archway. Every face bevel creates getsmaterial_index0, so chamfering nineteen blocks left 30 faces on the dressed slot and moved 464 to ashlar. The slot count and the distinct-material check both still passed — exactly the wipe classshowcase/README.mdwarns about, arriving by a different route. Only the per-material face floor caught it. Materials are now re-stamped per block after the bevel.find_doublescaught two real joints in crate-stack: the corner straps sat flush with the post corner, and the lid rested exactly on the rail top. Both were welded vertices, not near-misses. Both now bite into their host.BVHTree.find_nearestis unsigned. A voussoir seated inside the pier head reported a 5.4 mm gap where there was none. Joint gaps now test overlap first.Falsifiers retuned so each fails on its own budget
Five falsifiers initially tripped an earlier check, which proves nothing about the budget they were built for. Fixed by changing the model or the falsifier, never by loosening a band:
--stray-vert(both)--short-skids--same-seed--sink-keystone--off-circle--flat-arch, a lintel is 0.62 m shorterContact sheets
Both pieces composited against the pinned calibration set (
armature-bend,damped-track-aim,bmesh-gear), committed underdocs/gallery/contact-sheets/.crate-stack-contact-sheet.webpstone-archway-contact-sheet.webpMean luminance — calibration band is 0.1722 to 0.3048 (
damped-track-aim0.1722,armature-bend0.2787,bmesh-gear0.3048):crate-stackstone-archwayPer-criterion verdicts:
Both sheets drove real changes: the wedge fix above was made because the first pair of sheets showed the pool reading cool against the calibration images.
Asset sheets were not produced. No showcase piece has ever shipped one — all four in
docs/gallery/asset-sheets/are examples, as are all 44 contact sheets — and the gate lives under CLAUDE.md § "Quality Gates for Example Runs". I followed that precedent for the asset sheet and broke it for the contact sheet, on the grounds that a visual claim needs evidence. Flagging the ambiguity rather than silently picking one:showcase/README.mddoes not say whether either gate applies to showcase pieces, and it should.Framing gate
Measured on the render path, not eyeballed. The archway's first framing attempt was refused (
exit 10, fill y=1.000, margins 0.000 / 0.000) and the camera was pulled back until it passed:Cross-version determinism
Every measured value is byte-identical on 4.5.11, 5.1.2 and 5.2.1 except LOD2, the documented
DECIMATE COLLAPSEdivergence:crate-stackstone-archwayThat is why both gates are ratio bands, not exact counts.
Smoke cost
crate-stackstone-archwayAll 28 showcase pieces together: 20.9 s on 5.2.1, measured by running every
showcase/row intests/smoke/catalog.jsonend to end, zero failures. Well inside the ~90 s per-version ceiling.Integration
showcase/gallery.json(28 pieces),.cursor-plugin/plugin.jsonshowcase(28),tests/smoke/catalog.json(88 rows), README counts and preview grid,CLAUDE.mdinventory line,ROADMAP.mdcandidate pool (both marked shipped, four new subjects added), anddocs/gallery/regenerated.Generated HTML read rather than the source JSON, per the CLAUDE.md gate:
The example/showcase noun split from #196 is carrying the new pieces correctly.
Local validators:
tests/check_exit_code_readme.py,tests/check_import_export_rules.py, and the counts validator all pass.One thing noticed, not touched
showcase/shipping-crate/shipping_crate.pycarries an invertedeevee_engine_id():Blender 5.x offers only
BLENDER_EEVEE, so its--outputpath raisesTypeError: enum "BLENDER_EEVEE_NEXT" not foundon 5.1 and 5.2. Every other piece in the tree has the correct form ("BLENDER_EEVEE" if version >= (5, 0, 0)). Render-path only — smoke never passes--output, so it is not red. Left alone under this loop's do-not-touch rule; worth a quality pass.🤖 Generated with Claude Code