Skip to content

Commit bc0ac6c

Browse files
fix: showcase quality pass — stone-well and cart (#171)
* fix: rebuild stone-well so the joints meet and the bucket opens Quality pass on the stone-well generator after an inspection-sheet review found the curb floating above the masonry, windlass stubs buried in the posts, a crank that was a capped stub, an open pit at the roof peak, a sealed bucket with hoops that ignored the taper, a bail handle floating off the rim, and a rope that ended above the handle. Structural fixes in the generator: curb Z derived from the masonry top, windlass lengthened to pass through both posts, a real crank arm and grip, a peak cap, a manifold open bucket with tapered walls and hoops that follow it, bail legs pinned at the rim, rope terminated at the bail bar. Deterministic per-stone jitter, bevels on structural wood, noise/wear on all three materials, cap_tris everywhere to kill n-gons. New budgets: hygiene (loose/non-manifold/zero-area/doubles/ngons all zero, exit 15), grounded zmin (exit 16, --lift-z falsifier), BVH material-island gaps (exit 17), per-material face floors (exit 5) that catch the materials.clear() index-wipe class. Slot assignment is now index-preserving. Hero re-rendered; framing gate passes. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix: rebuild cart so the axle carries the bed and the wheels read Quality pass on the cart generator after an inspection-sheet review found the axle interpenetrating the bed floor, shafts poking through the bed, corner plates buried inside the wall corners, shaft straps floating off the bed, inconsistent wall heights, torus-profile wheels with round pipe treads, and spokes floating at both ends. Structural fixes in the generator: bed Z derived from the axle top via real bolster beams, shafts dropped to run beside the bed edge and angle down, corner plates moved onto the bed top, straps aligned to the bed bottom, a lower tailgate, flat-tread felloes and iron tyres built as rings, spokes embedded at hub and felloe. Noise/wear on both materials, cap_tris everywhere to kill n-gons. New budgets: hygiene (loose/non-manifold/zero-area/doubles/ngons all zero, exit 15), grounded zmin (exit 16, --lift-z falsifier), BVH metal-wood gap (exit 17), wood face floor (exit 5). Hero re-rendered; framing gate passes. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> * docs: add material face-floor convention and refresh showcase gallery Adds the material face-floor convention to the showcase README: every declared material asserts a named minimum polygon count recomputed from polygon.material_index, which catches the slot-assignment wipe class (materials.clear() resets material_index to 0 on some versions while the slot count still passes). Slot assignment must be index-preserving. Refreshes the stone-well and cart witness strings in showcase/gallery.json for the quality-pass numbers and regenerates docs/gallery. The regeneration also picks up iron-cauldron detail-page drift whose README landed without a gallery rebuild. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> --------- Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 77f884a commit bc0ac6c

14 files changed

Lines changed: 1366 additions & 272 deletions

File tree

docs/gallery/assets/cart-hero.webp

-21.1 KB
Loading
3.07 KB
Loading

docs/gallery/cart/index.html

Lines changed: 266 additions & 58 deletions
Large diffs are not rendered by default.

docs/gallery/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,7 @@ <h2><a href="shipping-crate/">shipping-crate</a></h2>
903903
<div class="card-body">
904904
<h2><a href="stone-well/">stone-well</a></h2>
905905
<p class="teaches">A procedural stone well through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
906-
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 8388 tris, three materials, UVs in 0..1 with zero AABB overlap, outer AABB 1.640×1.640×1.688 m, LOD ratios in band, convex collider 230 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
906+
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 9380 tris, three materials with face floors, UVs in 0..1 with zero AABB overlap, outer AABB 1.640×1.640×1.761 m, LOD ratios in band, convex collider 306 tris, hygiene zero (loose, non-manifold, doubles, n-gons), grounded zmin, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget; --lift-z exits 16 on the grounded budget.</p>
907907
<a class="card-link" href="stone-well/">View example <span aria-hidden="true">&rarr;</span></a>
908908
</div>
909909
</article>
@@ -1002,7 +1002,7 @@ <h2><a href="watchtower/">watchtower</a></h2>
10021002
<div class="card-body">
10031003
<h2><a href="cart/">cart</a></h2>
10041004
<p class="teaches">A procedural two-wheel wooden cart through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1005-
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 2572 tris, two materials with 100 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.547×0.749×0.656 m, LOD ratios in band, convex collider 306 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
1005+
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 2600 tris, two materials with metal and wood face floors, UVs in 0..1 with zero AABB overlap, outer AABB 1.539×0.749×0.640 m, LOD ratios in band, convex collider 122 tris, hygiene zero (loose, non-manifold, doubles, n-gons), grounded zmin, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget; --lift-z exits 16 on the grounded budget.</p>
10061006
<a class="card-link" href="cart/">View example <span aria-hidden="true">&rarr;</span></a>
10071007
</div>
10081008
</article>

docs/gallery/iron-cauldron/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ <h1>iron-cauldron</h1>
265265
<h2>Budgets</h2>
266266
<p>Declared as named constants; every gate <strong>recomputes</strong> from the mesh, materials, UVs, evaluated LOD, collider, or export file.</p>
267267
<p>| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) | | --- | --- | --- | | Base triangles | 3280–3520 | 3388 / 3388 / 3388 | | LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 | | LOD2 ratio | 0.10–0.35 of base | 0.2196 / 0.2196 / 0.2172 | | Materials | exactly 2 distinct, ≥12 wood, ≥24 metal | 2 slots, 450 wood, 1198 metal | | UVs | in <code>0..1</code>, AABB overlap ≤ 1e-5 | in range, overlap 0 | | Outer AABB | (1.013, 0.986, 0.827) m ± 0.01 | (1.0128, 0.9865, 0.8271), zmin 0.002 | | Pot–leg clearance | ≥ 0.04 m (recomputed vs pole axes) | 0.0513 / 0.0513 / 0.0513 | | Collider tris | ≤ 200 | 98 | | Export | written, size &gt; 0 | 245060 / 245060 / 245044 bytes |</p>
268-
<p>DECIMATE COLLAPSE triangle counts are <strong>not</strong> identical across series — 5.2.1 is 4 tris leaner on LOD2. The gate is a ratio band, not an exact count. Bake pixels are stochastic; the gate is <code>has_data</code> plus operator <code>FINISHED</code>, not byte-identity. Construction uses no RNG. Export byte counts differ by 12 B on 5.2.1 (glTF serializer), not a gated axis.</p>
268+
<p>DECIMATE COLLAPSE triangle counts are <strong>not</strong> identical across series — 5.2.1 is 8 tris leaner on LOD2. The gate is a ratio band, not an exact count. Bake pixels are stochastic; the gate is <code>has_data</code> plus operator <code>FINISHED</code>, not byte-identity. Construction uses no RNG. Export byte counts differ by 16 B on 5.2.1 (glTF serializer), not a gated axis. The pot–leg clearance is recomputed from shell verts vs the three pole axes; clipping exits 3.</p>
269269
<p><code>--skip-decimate</code> skips the LOD DECIMATE stage so LOD1 ratio is 1.0 and exit 9 fires. That is the named budget the falsifier violates.</p>
270270
<h2>Run</h2>
271271
<pre><code>blender --background --python iron_cauldron.py --

docs/gallery/stone-well/index.html

Lines changed: 400 additions & 73 deletions
Large diffs are not rendered by default.

showcase/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ entry in `showcase/gallery.json`, and a rendered still.
4343
characteristic 2 — that is a single-shell contract. Pairs of parts
4444
meant to touch assert a BVH surface gap below a named epsilon
4545
(vert-vert is the wrong metric for thin straps and collars).
46+
- **Material face floors.** Every declared material asserts a named
47+
minimum face count on the finished mesh, recomputed from
48+
`polygon.material_index`. This catches the slot-assignment wipe class:
49+
`obj.data.materials.clear()` resets every polygon's `material_index`
50+
to 0 on some versions, which renders the piece single-material while
51+
the slot count still passes. Assign slots by index-preserving
52+
append/replace, never clear-and-rebuild.
4653
- **Exit codes** are file-local: `0` success, argparse `2`, `3` and above
4754
in check order. `9` is legal. FATAL `sys.exit(1)` is a crash, never a
4855
named check.

showcase/cart/README.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,17 @@ materials, UVs, evaluated LOD, collider, or export file.
2121

2222
| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) |
2323
| --- | --- | --- |
24-
| Base triangles | 2470–2680 | 2572 / 2572 / 2572 |
24+
| Base triangles | 2470–2900 | 2600 / 2600 / 2600 |
2525
| LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 |
26-
| LOD2 ratio | 0.10–0.35 of base | 0.2193 / 0.2193 / 0.2146 |
27-
| Materials | exactly 2 distinct, ≥24 metal faces | 2 slots, 100 metal |
26+
| LOD2 ratio | 0.10–0.35 of base | 0.2200 / 0.2200 / 0.2154 |
27+
| Materials | exactly 2 distinct, metal ≥ 24, wood ≥ 800 faces | 2 slots, floors met |
2828
| UVs | in `0..1`, AABB overlap ≤ 1e-5 | in range, overlap 0 |
29-
| Outer AABB | (1.547, 0.749, 0.656) m ± 0.01 | (1.5473, 0.7486, 0.6560), zmin 0 |
30-
| Collider tris | ≤ 360 | 306 |
31-
| Export | written, size > 0 | 202500 / 202500 / 202492 bytes |
29+
| Outer AABB | (1.539, 0.749, 0.640) m ± 0.01 | (1.5393, 0.7486, 0.6400) |
30+
| Grounded | bbox min Z within 1e-4 of 0 | 0.0000 / 0.0000 / 0.0000 |
31+
| Hygiene | loose V/E, non-manifold, zero-area, doubles @1e-5, n-gons: all 0 | 0 / 0 / 0 on every axis |
32+
| Material-island gap | metal↔wood min distance ≤ 0.008 m | 0.00000 / 0.00000 / 0.00000 |
33+
| Collider tris | ≤ 360 | 122 |
34+
| Export | written, size > 0 | 201048 / 201048 / 201032 bytes |
3235

3336
DECIMATE COLLAPSE triangle counts are **not** identical across series —
3437
5.2.1 is more aggressive on LOD2. The gate is a ratio band, not an
@@ -38,17 +41,20 @@ Export byte counts differ by 8 B on 5.2.1 (glTF serializer), not a
3841
gated axis.
3942

4043
`--skip-decimate` skips the LOD DECIMATE stage so LOD1 ratio is 1.0 and
41-
exit 9 fires. That is the named budget the falsifier violates.
44+
exit 9 fires. `--lift-z` raises the finished mesh 0.05 m so the grounded
45+
budget fails and exit 16 fires. Those are the named budgets the two
46+
falsifiers violate.
4247

4348
## Run
4449

4550
```bash
4651
blender --background --python cart.py --
4752
blender --background --python cart.py -- --skip-decimate
53+
blender --background --python cart.py -- --lift-z
4854
blender --background --python cart.py -- --output cart.png
4955
```
5056

51-
Smoke does not pass `--output` or `--skip-decimate`.
57+
Smoke does not pass `--output`, `--skip-decimate`, or `--lift-z`.
5258

5359
## Exit codes
5460

@@ -72,3 +78,6 @@ File-local. `9` is a valid check code. `10` is reserved for
7278
| 12 | Bake did not finish or image has no data |
7379
| 13 | Export file missing or empty |
7480
| 14 | `--output` produced no file |
81+
| 15 | Hygiene: loose geometry, non-manifold, zero-area, doubles, or n-gons |
82+
| 16 | Bbox min Z not grounded (`--lift-z` lands here) |
83+
| 17 | Material-island gap above tolerance (parts meant to touch) |

0 commit comments

Comments
 (0)