Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified docs/gallery/assets/street-lantern-hero.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/gallery/assets/water-trough-hero.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/gallery/grindstone/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,7 @@ <h2>Source</h2>
<span class="k">for</span> p <span class="k">in</span> me.polygons:
<span class="k">if</span> all(i <span class="k">in</span> member <span class="k">for</span> i <span class="k">in</span> p.vertices):
<span class="k">return</span> p.material_index
<span class="k">return</span> -<span class="n">1</span>
<span class="k">return</span> <span class="k">None</span>


<span class="k">def</span> support_audit(me):
Expand Down
4 changes: 2 additions & 2 deletions docs/gallery/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -947,7 +947,7 @@ <h2><a href="market-stall/">market-stall</a></h2>
<div class="card-body">
<h2><a href="street-lantern/">street-lantern</a></h2>
<p class="teaches">A procedural hanging street lantern through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 3520 tris, three materials with 24 glass and 94 brass faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.403×0.892×1.404 m, LOD ratios in band, convex collider 84 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 3338 tris, three materials with 1530 metal, 24 glass and 209 brass faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.300×0.786×1.287 m, zmin 0, hygiene 0, brace BVH gap 0, hanger-roof gap −1 mm, post 0.100×1.120 m plumb 0, LOD ratios in band (5.2 COLLAPSE 2 tris leaner on LOD2), convex collider 78 tris, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z 16; --float-brace 17; --sink-arm 18; --rake-post 19.</p>
<a class="card-link" href="street-lantern/">View example <span aria-hidden="true">&rarr;</span></a>
</div>
</article>
Expand Down Expand Up @@ -1046,7 +1046,7 @@ <h2><a href="anvil/">anvil</a></h2>
<div class="card-body">
<h2><a href="water-trough/">water-trough</a></h2>
<p class="teaches">A procedural watertight water trough through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 2484 tris, three materials with 192 metal and 6 water faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.152×0.568×0.509 m, LOD ratios in band (5.2 COLLAPSE 8 tris leaner on LOD2), convex collider 32 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 3700 tris, three materials with 1674 wood, 156 metal and 29 water faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.093×0.552×0.504 m, zmin 0, four shoes planted, U end-cap rim span 5 mm, strap BVH gap 0, water-hull gap 2.6 mm, hull 1.045×0.466 m, LOD ratios in band, convex collider 64 tris, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z/--short-legs 16; --box-ends 17; --float-strap 18; --narrow-hull 19.</p>
<a class="card-link" href="water-trough/">View example <span aria-hidden="true">&rarr;</span></a>
</div>
</article>
Expand Down
832 changes: 650 additions & 182 deletions docs/gallery/street-lantern/index.html

Large diffs are not rendered by default.

742 changes: 605 additions & 137 deletions docs/gallery/water-trough/index.html

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion showcase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@ entry in `showcase/gallery.json`, and a rendered still.
flat fan cap are coplanar and close-centred by construction, and
counting those makes the budget unsatisfiable rather than meaningful.
Multi-body props do **not** require Euler characteristic 2 — that is a
single-shell contract. Pairs of parts meant to touch assert a BVH
single-shell contract. Two boxes that share a coplanar face z-fight;
two that share a vertex weld into one shell. Seat a joint with a named
overlap or rebate computed from the host (a cage post into its rail, a
glass pane behind its muntin, a plinth step into its base) rather than
hoping the numbers happen not to coincide. A hang-station versus
arm-station split lets a contact falsifier move one member without
dragging the rest of the assembly. Pairs of parts meant to touch assert a BVH
surface gap below a named epsilon (vert-vert is the wrong metric for
thin straps and collars). A spanning board whose only vertices sit at
the far ends will report a false gap to a mid-span knuckle; put a
Expand Down
4 changes: 2 additions & 2 deletions showcase/gallery.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"name": "street-lantern",
"dir": "showcase/street-lantern",
"teaches": "A procedural hanging street lantern through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.",
"witnessesFix": "Recomputed: 3520 tris, three materials with 24 glass and 94 brass faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.403×0.892×1.404 m, LOD ratios in band, convex collider 84 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.",
"witnessesFix": "Recomputed: 3338 tris, three materials with 1530 metal, 24 glass and 209 brass faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.300×0.786×1.287 m, zmin 0, hygiene 0, brace BVH gap 0, hanger-roof gap −1 mm, post 0.100×1.120 m plumb 0, LOD ratios in band (5.2 COLLAPSE 2 tris leaner on LOD2), convex collider 78 tris, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z 16; --float-brace 17; --sink-arm 18; --rake-post 19.",
"hero": "docs/gallery/assets/street-lantern-hero.webp",
"preview": "showcase/street-lantern/preview.webp",
"tags": [
Expand Down Expand Up @@ -177,7 +177,7 @@
"name": "water-trough",
"dir": "showcase/water-trough",
"teaches": "A procedural watertight water trough through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.",
"witnessesFix": "Recomputed: 2484 tris, three materials with 192 metal and 6 water faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.152×0.568×0.509 m, LOD ratios in band (5.2 COLLAPSE 8 tris leaner on LOD2), convex collider 32 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.",
"witnessesFix": "Recomputed: 3700 tris, three materials with 1674 wood, 156 metal and 29 water faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.093×0.552×0.504 m, zmin 0, four shoes planted, U end-cap rim span 5 mm, strap BVH gap 0, water-hull gap 2.6 mm, hull 1.045×0.466 m, LOD ratios in band, convex collider 64 tris, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z/--short-legs 16; --box-ends 17; --float-strap 18; --narrow-hull 19.",
"hero": "docs/gallery/assets/water-trough-hero.webp",
"preview": "showcase/water-trough/preview.webp",
"tags": [
Expand Down
108 changes: 88 additions & 20 deletions showcase/street-lantern/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@

A showcase piece, not an example. Procedural hanging street lantern
(stepped iron foot, tapered octagonal post, brass collars, braced arm,
muntined cage with amber panes, pyramidal brass roof and finial) then
the shipped pipeline: unique-cell UVs, Cycles high-to-low normal bake,
LOD chain, convex collider, Unity glTF export.
muntined cage with amber panes, square pyramidal brass roof and finial)
then the shipped pipeline: unique-cell UVs, Cycles high-to-low normal
bake, LOD chain, convex collider, Unity glTF export.

The arm axis, drop length, and roof stack are one closed-form chain: the
roof peak stays below the arm, the hanger is the arm's far station, and
the brace is an oriented box between a post-radius station and an arm
station. The square pyramid is lofted on the cage axes, not a 4-gon cone.
Cage posts and rails share a named overlap (`CAGE_JOINT`); glass sits
behind the muntins by `PANE_REBATE`. Collars and the arm root evaluate
`post_radius_at(z)`.

It asserts **budget conformance** of the generated result. It does not
witness an API contract. "It rendered without error" is not a check.
Expand All @@ -14,6 +22,12 @@ witness an API contract. "It rendered without error" is not a check.
`bake_normal_high_to_low.py`, `setup_bake_target_image.py`,
`lod_chain.py` / `decimate_to_budget.py`, `convex_hull_collider.py`,
`export_preset_unity.py` (helpers copied, not imported as a package).
Hygiene combinatorics match `examples/mesh-hygiene-audit` (copied, not
imported).

Intended size: 0.30 m square foot, 1.12 m octagonal post (0.10 m across
at the base), 0.50 m arm, 0.24 × 0.30 m cage; outer AABB
0.300 × 0.786 × 1.287 m.

## Budgets

Expand All @@ -22,38 +36,87 @@ materials, UVs, evaluated LOD, collider, or export file.

| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) |
| --- | --- | --- |
| Base triangles | 3400–3650 | 3520 / 3520 / 3520 |
| LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 |
| LOD2 ratio | 0.10–0.35 of base | 0.2199 / 0.2199 / 0.2199 |
| Materials | exactly 3 distinct, ≥8 glass faces, ≥8 brass faces | 3 slots, 24 glass, 94 brass |
| Base triangles | 3000–3800 | 3338 / 3338 / 3338 |
| LOD1 ratio | 0.32–0.62 of base | 0.4997 / 0.4997 / 0.4997 |
| LOD2 ratio | 0.10–0.35 of base | 0.2199 / 0.2199 / 0.2193 |
| Materials | exactly 3 distinct; ≥200 metal, ≥8 glass, ≥24 brass | 3 slots; 1530 / 24 / 209 |
| UVs | in `0..1`, AABB overlap ≤ 1e-5 | in range, overlap 0 |
| Outer AABB | (0.403, 0.892, 1.404) m ± 0.01 | (0.4032, 0.8916, 1.4041), zmin 0 |
| Collider tris | ≤ 110 | 84 |
| Export | written, size > 0 | 254552 / 254552 / 254536 bytes |
| Outer AABB | (0.300, 0.786, 1.287) m ± 0.01 | (0.3000, 0.7860, 1.2874), zmin 0 |
| Collider tris | ≤ 120 | 78 |
| Export | written, size > 0 | 250980 / 250980 / 250964 bytes |

Base triangles dropped from **3520 to 3338** in the quality pass: the
open 4-gon cone roof became a closed square pyramid, cage crossings
stopped sharing vertices, and a pane rebate replaced coplanar glass.

DECIMATE COLLAPSE triangle counts are **not** identical across series —
5.2.1 is 2 tris leaner on LOD2. The gate is a ratio band, not an exact
count. Bake pixels are stochastic; the gate is `has_data` plus operator
`FINISHED`, not byte-identity. Construction uses no RNG. Export byte
counts differ by 16 B on 5.2.1 (glTF serializer), not a gated axis.

### Hygiene

Recomputed from the generated mesh, not asserted about the script.

| Axis | Declared | Measured (all three) |
| --- | --- | --- |
| Non-manifold edges | 0 | 0 |
| Loose verts / edges | 0 / 0 | 0 / 0 |
| Doubles merged at 1e-5 | 0 | 0 |
| Zero-area faces | 0 | 0 |
| N-gons | 0 | 0 |
| Coplanar disjoint face pairs | 0 | 0 |
| Grounded: `zmin` | within 1e-4 of 0 | 0.0000 |
| Post plan | 0.100 m across × 1.120 m high ± (0.02, 0.04) | 0.1000 × 1.1200 |
| Post plumb (top vs bottom XY) | ≤ 0.008 m | 0.00000 |

### Joint fit and seat

| Axis | Declared | Measured (all three) |
| --- | --- | --- |
| Brace-to-arm BVH gap | ≤ 0.006 m | 0.00000 |
| Arm underside vs roof peak | ≥ 0.008 m clearance | 0.05300 |
| Hanger-to-roof BVH gap | ≤ 0.004 m | −0.00100 |

DECIMATE COLLAPSE triangle counts are **not** guaranteed identical across
series — the gate is a ratio band, not an exact count. This mesh happened
to match on 4.5.11 / 5.1.2 / 5.2.1. Bake pixels are stochastic; the gate
is `has_data` plus operator `FINISHED`, not byte-identity. Construction
uses no RNG. glTF byte size differs by a few bytes across series.
### Falsifiers

Each violates one named budget. All six were run on 4.5.11, 5.1.2 and
5.2.1 and returned the same code on each.

| Flag | Budget violated | Exit |
| --- | --- | --- |
| `--skip-decimate` | LOD1 ratio band | 9 |
| `--stray-vert` | loose vertex count is 0 | 15 |
| `--lift-z` | bounding box `zmin` is 0 | 16 |
| `--float-brace` | brace-to-arm BVH gap | 17 |
| `--sink-arm` | arm-over-roof clearance | 18 |
| `--rake-post` | post plumb | 19 |

`--skip-decimate` skips the LOD DECIMATE stage so LOD1 ratio is 1.0 and
exit 9 fires. That is the named budget the falsifier violates.
`--sink-arm` lowers only the arm. Hang-station `hang_z` stays at post
top so the cage does not follow, which is what lets the clearance budget
fire.

## Run

```bash
blender --background --python street_lantern.py --
blender --background --python street_lantern.py -- --skip-decimate
blender --background --python street_lantern.py -- --stray-vert
blender --background --python street_lantern.py -- --lift-z
blender --background --python street_lantern.py -- --float-brace
blender --background --python street_lantern.py -- --sink-arm
blender --background --python street_lantern.py -- --rake-post
blender --background --python street_lantern.py -- --output lantern.png
```

Smoke does not pass `--output` or `--skip-decimate`.
Smoke passes no flags.

## Exit codes

File-local. `9` is a valid check code. `10` is reserved for
`gallery_framing.check_framing` on the `--output` path.
`gallery_framing.check_framing` on the `--output` path. `15`–`19` are the
hygiene and joint-fit family.

| Code | Meaning |
| --- | --- |
Expand All @@ -62,7 +125,7 @@ File-local. `9` is a valid check code. `10` is reserved for
| 2 | argparse / usage |
| 3 | Mesh did not build / no UV layer |
| 4 | Base triangle count outside range |
| 5 | Material count ≠ 3 distinct slots, or glass/brass faces missing |
| 5 | Material count ≠ 3 distinct slots, or a face-count floor missed |
| 6 | UVs outside 0..1 |
| 7 | UV AABB overlap above tolerance |
| 8 | World AABB off declared outer size |
Expand All @@ -72,3 +135,8 @@ File-local. `9` is a valid check code. `10` is reserved for
| 12 | Bake did not finish or image has no data |
| 13 | Export file missing or empty |
| 14 | `--output` produced no file |
| 15 | Mesh hygiene: loose, non-manifold, zero-area, doubles, n-gons, z-fight |
| 16 | Not grounded: bounding box `zmin` off 0 |
| 17 | Joint fit: brace-to-arm gap (`--float-brace`) |
| 18 | Seat: arm-roof clearance or hanger-roof gap (`--sink-arm`) |
| 19 | Post plumb or post size off the stated real-world size (`--rake-post`) |
Binary file modified showcase/street-lantern/preview.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading