Skip to content

Commit 09453f5

Browse files
fix(showcase): fence-kit and hand-pump visual quality pass (#183)
* docs(showcase): require diagonals from named host stations A hypot-length box rotated about its centroid misses one host and punches the other; braces and goosenecks have to be built from the stations they join. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix(showcase): fence-kit visual quality pass Build the brace from named post stations and U-wrap the rail collars so the bay reads as a fence instead of a hypot-box with coplanar straps. Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> * fix(showcase): hand-pump visual quality pass Replace the sausage-cylinder gooseneck and cube head with a tube from the column radius and a stuffing-box so the silhouette reads as a pump. 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 88e8132 commit 09453f5

13 files changed

Lines changed: 2177 additions & 592 deletions

File tree

-19.2 KB
Loading
1.82 KB
Loading

‎docs/gallery/fence-kit/index.html‎

Lines changed: 482 additions & 96 deletions
Large diffs are not rendered by default.

‎docs/gallery/hand-pump/index.html‎

Lines changed: 547 additions & 193 deletions
Large diffs are not rendered by default.

‎docs/gallery/index.html‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -975,12 +975,12 @@ <h2><a href="terrain-scatter/">terrain-scatter</a></h2>
975975
</article>
976976
<article class="card" data-tags="mesh export showcase">
977977
<a class="card-media" href="fence-kit/" aria-label="fence-kit example detail page">
978-
<img src="assets/fence-kit-hero.webp" alt="fence-kit — A procedural post-and-rail fence section through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." loading="lazy" decoding="async" />
978+
<img src="assets/fence-kit-hero.webp" alt="fence-kit — A procedural post-and-rail fence section whose brace is an oriented box between named post stations, through UVs, bake, LOD, collider, and Unity glTF…" loading="lazy" decoding="async" />
979979
</a>
980980
<div class="card-body">
981981
<h2><a href="fence-kit/">fence-kit</a></h2>
982-
<p class="teaches">A procedural post-and-rail fence section through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
983-
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 1212 tris, two materials with 120 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.642×0.157×1.235 m, LOD ratios in band, convex collider 62 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
982+
<p class="teaches">A procedural post-and-rail fence section whose brace is an oriented box between named post stations, through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
983+
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 1092 tris, two materials with 156 metal and 390 wood faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.624×0.134×1.232 m, grounded zmin, 2 iron shoes, brace-to-post gap 2.4 mm on both posts, rail-to-post gap 0.93 mm, rail span 1.390 m, LOD ratios in band (5.2 COLLAPSE leaner on LOD2), convex collider 32 tris, hygiene all zero, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z/--short-shoes 16; --short-brace 17; --gap-rails 18; --long-rails 19.</p>
984984
<a class="card-link" href="fence-kit/">View example <span aria-hidden="true">&rarr;</span></a>
985985
</div>
986986
</article>
@@ -1074,12 +1074,12 @@ <h2><a href="grindstone/">grindstone</a></h2>
10741074
</article>
10751075
<article class="card" data-tags="mesh export showcase">
10761076
<a class="card-media" href="hand-pump/" aria-label="hand-pump example detail page">
1077-
<img src="assets/hand-pump-hero.webp" alt="hand-pump — A procedural village hand pump with a gooseneck through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract." loading="lazy" decoding="async" />
1077+
<img src="assets/hand-pump-hero.webp" alt="hand-pump — A procedural village hand pump whose gooseneck is a 6-gon tube from the lower-column radius, through UVs, bake, LOD, collider, and Unity glTF, asserting…" loading="lazy" decoding="async" />
10781078
</a>
10791079
<div class="card-body">
10801080
<h2><a href="hand-pump/">hand-pump</a></h2>
1081-
<p class="teaches">A procedural village hand pump with a gooseneck through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1082-
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 1164 tris, two materials with 222 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.610×0.364×1.049 m, LOD ratios in band (5.2 COLLAPSE more aggressive on LOD2), convex collider 110 tris, non-empty glTF. --skip-decimate exits 9 on the LOD1 ratio budget.</p>
1081+
<p class="teaches">A procedural village hand pump whose gooseneck is a 6-gon tube from the lower-column radius, through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.</p>
1082+
<p class="witnesses"><span class="tag">witnesses</span> Recomputed: 1064 tris, two materials with 564 metal and 144 wood faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.610×0.382×1.052 m, grounded zmin, spout-to-column gap 2.7 mm, flange-to-plinth gap 6.0 mm, column radius 62 mm, LOD ratios in band, convex collider 114 tris, hygiene all zero, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z 16; --float-spout 17; --float-flange 18; --skinny-col 19.</p>
10831083
<a class="card-link" href="hand-pump/">View example <span aria-hidden="true">&rarr;</span></a>
10841084
</div>
10851085
</article>

‎showcase/README.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ entry in `showcase/gallery.json`, and a rendered still.
7979
the host's chamfer as a spike — that is the class this catches.
8080
Measure in the construction frame (un-rotate by any rake) so a tilted
8181
host does not inflate its own AABB.
82+
- **Diagonal from stations (exit 17).** A brace, gooseneck or scroll is
83+
an oriented primitive or a tube between named host endpoints, not a
84+
hypot-length box rotated about its centroid. The centroid form is
85+
short of one host and punches through the other. `--short-brace` /
86+
`--float-spout` (or the piece's equivalent) is the falsifier.
8287
- **Seat conformance (exit 18).** A band, hoop, strap or collar wrapped
8388
around a host asserts a **banded** seat depth — a minimum so it cannot
8489
float and a maximum so it cannot sink — sampled per angular segment

‎showcase/fence-kit/README.md‎

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
# Fence kit
22

33
A showcase piece, not an example. Procedural post-and-rail fence
4-
section (two posts, pyramidal caps, three rails, kickboard, brace,
5-
iron shoes and straps) then the shipped pipeline: unique-cell UVs,
6-
Cycles high-to-low normal bake, LOD chain, convex collider, Unity
7-
glTF export.
4+
section (two posts, pyramidal caps, three rails, kickboard, a brace
5+
from named post stations, iron shoes and U-wrap straps) then the
6+
shipped pipeline: unique-cell UVs, Cycles high-to-low normal bake, LOD
7+
chain, convex collider, Unity glTF export.
8+
9+
Posts, rails, kick, brace and collars share named stations
10+
(`POST_XS`, `RAIL_ZS`, `Y_BRACE`, `SHOE_H`). The brace is an oriented
11+
box from the left-post lower-rail station to the right-post upper-rail
12+
station on the back face, not a hypot-length box rotated about its
13+
centroid. Rails and kick tenon into the post volume; rail collars are
14+
U-wraps so the span-facing plate is not coplanar with the rail end.
815

916
It asserts **budget conformance** of the generated result. It does not
1017
witness an API contract. "It rendered without error" is not a check.
@@ -16,6 +23,11 @@ re-witness the `modular-kit-snap` snap contract.
1623
`bake_normal_high_to_low.py`, `setup_bake_target_image.py`,
1724
`lod_chain.py` / `decimate_to_budget.py`, `convex_hull_collider.py`,
1825
`export_preset_unity.py` (helpers copied, not imported as a package).
26+
Hygiene combinatorics match `examples/mesh-hygiene-audit` (copied, not
27+
imported).
28+
29+
Intended size: 1.60 m bay, 1.14 m posts, 0.11 m post stock; outer AABB
30+
1.624 × 0.134 × 1.232 m.
1931

2032
## Budgets
2133

@@ -24,37 +36,92 @@ materials, UVs, evaluated LOD, collider, or export file.
2436

2537
| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) |
2638
| --- | --- | --- |
27-
| Base triangles | 1160–1280 | 1212 / 1212 / 1212 |
39+
| Base triangles | 1000–1400 | 1092 / 1092 / 1092 |
2840
| LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 |
29-
| LOD2 ratio | 0.10–0.35 of base | 0.2195 / 0.2195 / 0.2079 |
30-
| Materials | exactly 2 distinct, ≥24 metal faces | 2 slots, 120 metal |
41+
| LOD2 ratio | 0.10–0.35 of base | 0.2198 / 0.2198 / 0.1832 |
42+
| Materials | exactly 2 distinct, ≥48 metal, ≥24 wood | 2 slots, 156 metal / 390 wood |
3143
| UVs | in `0..1`, AABB overlap ≤ 1e-5 | in range, overlap 0 |
32-
| Outer AABB | (1.642, 0.157, 1.235) m ± 0.01 | (1.6418, 0.1574, 1.2350), zmin 0 |
33-
| Collider tris | ≤ 96 | 62 |
34-
| Export | written, size > 0 | 93232 / 93232 / 93224 bytes |
44+
| Outer AABB | (1.624, 0.134, 1.232) m ± 0.015 | (1.6240, 0.1340, 1.2320), zmin 0 |
45+
| Collider tris | ≤ 180 | 32 |
46+
| Export | written, size > 0 | 82216 / 82216 / 82208 bytes |
47+
48+
Base triangles dropped from **1212 to 1092** in the quality pass: rail
49+
collars became U-wraps (no span-facing plate). Outer AABB tightened from
50+
1.642 × 0.157 × 1.235 m.
3551

3652
DECIMATE COLLAPSE triangle counts are **not** identical across series —
3753
5.2.1 is more aggressive on LOD2. The gate is a ratio band, not an
3854
exact count. Bake pixels are stochastic; the gate is `has_data` plus
3955
operator `FINISHED`, not byte-identity. Construction uses no RNG.
56+
Export byte counts differ by 8 B on 5.2.1 (glTF serializer), not a
57+
gated axis.
58+
59+
### Hygiene
60+
61+
Recomputed from the generated mesh, not asserted about the script.
62+
63+
| Axis | Declared | Measured (all three) |
64+
| --- | --- | --- |
65+
| Non-manifold edges | 0 | 0 |
66+
| Loose verts / edges | 0 / 0 | 0 / 0 |
67+
| Doubles merged at 1e-5 | 0 | 0 |
68+
| Zero-area faces | 0 | 0 |
69+
| N-gons | 0 | 0 |
70+
| Coplanar disjoint face pairs | 0 | 0 |
71+
| Grounded: `zmin` | within 1e-4 of 0 | 0.0000 |
72+
| Named shoes | 2, each `zmin` ≤ 0.002 | 2, 0.00000 |
73+
74+
### Joint fit and span
75+
76+
| Axis | Declared | Measured (all three) |
77+
| --- | --- | --- |
78+
| Brace-to-post BVH gap (both posts) | ≤ 0.008 m | 0.00240 |
79+
| Rail-to-post BVH gap | ≤ 0.008 m | 0.00093 |
80+
| Rail span vs `2·RAIL_HALF` | ± 0.04 m | 1.3900 vs 1.390 |
81+
82+
### Falsifiers
83+
84+
Each violates one named budget. All were run on 4.5.11, 5.1.2 and 5.2.1
85+
and returned the same code on each.
86+
87+
| Flag | Budget violated | Exit |
88+
| --- | --- | --- |
89+
| `--skip-decimate` | LOD1 ratio band | 9 |
90+
| `--stray-vert` | loose vertex count is 0 | 15 |
91+
| `--lift-z` | bounding box `zmin` is 0 | 16 |
92+
| `--short-shoes` | named shoes plant at z=0 | 16 |
93+
| `--short-brace` | brace-to-post BVH gap (both posts) | 17 |
94+
| `--gap-rails` | rail-to-post BVH gap | 18 |
95+
| `--long-rails` | rail span vs `2·RAIL_HALF` | 19 |
4096

41-
`--skip-decimate` skips the LOD DECIMATE stage so LOD1 ratio is 1.0 and
42-
exit 9 fires. That is the named budget the falsifier violates.
97+
`--short-shoes` lifts only the iron shoes. After recenter a post or kick
98+
is the AABB `zmin`, so the AABB gate would still pass; the named-shoe
99+
stations fail. `--short-brace` shortens the left station; `brace_gap` is
100+
the max of the per-post minima so a brace that still hits the right post
101+
cannot sneak through. `--long-rails` adds an extra spanning board; the
102+
tenoned rails stay put so the gap budget still passes.
43103

44104
## Run
45105

46106
```bash
47107
blender --background --python fence_kit.py --
48108
blender --background --python fence_kit.py -- --skip-decimate
109+
blender --background --python fence_kit.py -- --stray-vert
110+
blender --background --python fence_kit.py -- --lift-z
111+
blender --background --python fence_kit.py -- --short-shoes
112+
blender --background --python fence_kit.py -- --short-brace
113+
blender --background --python fence_kit.py -- --gap-rails
114+
blender --background --python fence_kit.py -- --long-rails
49115
blender --background --python fence_kit.py -- --output fence.png
50116
```
51117

52-
Smoke does not pass `--output` or `--skip-decimate`.
118+
Smoke passes no flags.
53119

54120
## Exit codes
55121

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

59126
| Code | Meaning |
60127
| --- | --- |
@@ -63,7 +130,7 @@ File-local. `9` is a valid check code. `10` is reserved for
63130
| 2 | argparse / usage |
64131
| 3 | Mesh did not build / no UV layer |
65132
| 4 | Base triangle count outside range |
66-
| 5 | Material count ≠ 2 distinct slots, or metal faces missing |
133+
| 5 | Material count ≠ 2 distinct slots, or wood/metal faces missing |
67134
| 6 | UVs outside 0..1 |
68135
| 7 | UV AABB overlap above tolerance |
69136
| 8 | World AABB off declared outer size |
@@ -73,3 +140,8 @@ File-local. `9` is a valid check code. `10` is reserved for
73140
| 12 | Bake did not finish or image has no data |
74141
| 13 | Export file missing or empty |
75142
| 14 | `--output` produced no file |
143+
| 15 | Hygiene (`--stray-vert` lands here) |
144+
| 16 | Grounded zmin / named shoes (`--lift-z`, `--short-shoes`) |
145+
| 17 | Brace-to-post gap (`--short-brace`) |
146+
| 18 | Rail-to-post gap (`--gap-rails`) |
147+
| 19 | Rail span (`--long-rails`) |

0 commit comments

Comments
 (0)