11# Tavern stool
22
3- A showcase piece, not an example. Procedural tavern stool (lathed round
4- seat, turned splayed legs, tenoned stretchers, iron ferrule cups) then
5- the shipped pipeline: unique-cell UVs, Cycles high-to-low normal bake,
6- LOD chain, convex collider, Unity glTF export.
7-
8- Legs are one loft per leg, not stacked cones. Ferrules are vertical cups
9- the foot drops into; wood ends above the cup so a splayed cone does not
10- sawtooth through the wall. Stretchers are classified as compact rails,
11- not the seat disc.
3+ A showcase piece, not an example. A procedural tavern stool: a lathed round
4+ seat, turned splayed legs, tenoned stretchers at two heights, and iron
5+ ferrules on level treads. Then the shipped pipeline: unique-cell UVs, a
6+ Cycles high-to-low normal bake, an LOD chain, a convex collider and a Unity
7+ glTF export.
8+
9+ Legs are one loft per leg, not stacked cones. Each foot is an iron ferrule
10+ sleeve on the leg's own axis, its inner wall a named grip (1.2 mm) inside the
11+ leg. The sleeve's raked bottom rim is buried in a level iron tread, and the
12+ leg ends inside the sleeve, above the tread. The first build ended every leg
13+ 3 mm above a vertical ring on the floor, with a 1 mm air gap around the foot.
14+ The front-back and side stretchers sit at different heights, so their tenons
15+ do not meet inside the leg. Each member has its own wood tone and grain.
1216
1317It asserts ** budget conformance** of the generated result. It does not
1418witness an API contract. "It rendered without error" is not a check.
@@ -21,19 +25,31 @@ witness an API contract. "It rendered without error" is not a check.
2125
2226## Budgets
2327
24- Declared as named constants; every gate ** recomputes** from the mesh,
25- materials, UVs, evaluated LOD, collider, or export file.
28+ Declared as named constants. Every gate ** recomputes** its value from the
29+ mesh, materials, UVs, evaluated LOD, collider or export file.
2630
2731| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) |
2832| --- | --- | --- |
29- | Base triangles | 2300–3200 | 2528 / 2528 / 2528 |
33+ | Base triangles | 2750–3350 | 3040 / 3040 / 3040 |
3034| LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 |
31- | LOD2 ratio | 0.10–0.35 of base | 0.2199 / 0.2199 / 0.2199 |
32- | Materials | exactly 2 distinct; ≥200 wood, ≥48 metal faces | 2 slots; 1168 / 256 |
35+ | LOD2 ratio | 0.10–0.35 of base | 0.2197 / 0.2197 / 0.2197 |
36+ | Materials | exactly 2 distinct; ≥200 wood, ≥48 metal faces | 2 slots; 1168 / 576 |
3337| UVs | in ` 0..1 ` , AABB overlap ≤ 1e-5 | in range, overlap 0 |
34- | Outer AABB | (0.341, 0.341, 0.470) m ± 0.015 | (0.3400, 0.3400, 0.4700), zmin 0 |
35- | Collider tris | ≤ 640 | 396 |
36- | Export | written, size > 0 | 215912 / 215912 / 215900 bytes |
38+ | Outer AABB | (0.341, 0.341, 0.470) m ± 0.015 | (0.3406, 0.3406, 0.4700), zmin 0 |
39+ | Collider tris | ≤ 640 | 468 |
40+ | Export | written, size > 0 | 259676 / 259676 / 259668 bytes |
41+
42+ Base triangles rose from ** 2528 to 3040** in the second quality pass, and the
43+ band moved from 2300–3200 to 2750–3350. Each foot gained a tread, and the
44+ sleeves are walled on both ends. The bake went from 256 px to 1024 px, and
45+ its cage extrusion from 60 mm to 10 mm. See the bake texel budget below.
46+
47+ DECIMATE COLLAPSE triangle counts are ** not** identical across series. The
48+ gate is a ratio band, not an exact count. Bake pixels are stochastic; the
49+ gate is ` has_data ` plus operator ` FINISHED ` , not byte-identity. Construction
50+ is closed-form and member tones are seeded, so repeated runs on one binary
51+ print identical measurements. Export byte counts may differ by a few bytes
52+ across series.
3753
3854### Hygiene
3955
@@ -48,35 +64,41 @@ Recomputed from the generated mesh, not asserted about the script.
4864| N-gons | 0 | 0 |
4965| Coplanar disjoint face pairs | 0 | 0 |
5066| Grounded: ` zmin ` | within 1e-4 of 0 | 0.0000 |
51- | Named supports: 4 ferrule cups | each ` zmin ` ≤ 1e-3 | 4 , cup_z 0.00000 |
67+ | Named supports: 4 treads (plus 4 sleeves) | each ` zmin ` ≤ 1e-3 | 8 , cup_z 0.00000 |
5268| Seat | 0.340 m dia × 0.470 m high ± 0.02 | 0.3400 × 0.4700 |
5369
54- ### Joint fit and seat
70+ ### Joint fit, feet and bake
5571
5672| Axis | Declared | Measured (all three) |
5773| --- | --- | --- |
5874| Stretcher-leg BVH gap | ≤ 0.008 m | 0.00000 |
59- | Ferrule inner clearance (` r_wood − r_in ` ) | −0.005 .. 0.000 m | −0.00125 |
75+ | Ferrule grip (exit 18): leg radius where the sleeve wraps it, less the sleeve's inner radius, radially about the leg's own axis; 4 sleeves | 0.0006–0.0025 m | 0.00120 |
76+ | Foot stack (exit 20): leg end above its tread's top / sleeve bottom buried below it; 4 legs, 4 treads | ≥ 0.0005 m / ≥ 0.001 m | 0.00113 / 0.00943 |
77+ | Bake texel density (exit 21): smallest UV cell in baked texels | ≥ 12 px | 22.43 px (1024 px bake) |
6078
61- DECIMATE COLLAPSE triangle counts are ** not** identical across series —
62- the gate is a ratio band, not an exact count. Bake pixels are
63- stochastic; the gate is ` has_data ` plus operator ` FINISHED ` , not
64- byte-identity. Construction uses no RNG. Export byte counts may differ
65- by a few bytes across series.
79+ At 256 px the bake gave each of the 1,744 UV cells about 6 px. The hero then
80+ sampled the neighbouring cells' normals across cell borders, which showed as
81+ dark slivers on the legs above the ferrules.
6682
6783### Falsifiers
6884
69- Each violates one named budget. All seven were run on 4.5.11, 5.1.2 and
70- 5.2.1 and returned the same code on each.
85+ Each violates one named budget. All were run on 4.5.11, 5.1.2 and 5.2.1 and
86+ returned the same code on each.
7187
7288| Flag | Budget violated | Exit |
7389| --- | --- | --- |
7490| ` --skip-decimate ` | LOD1 ratio band | 9 |
7591| ` --stray-vert ` | loose vertex count is 0 | 15 |
7692| ` --lift-z ` | bounding box ` zmin ` is 0 | 16 |
77- | ` --short-legs ` | named ferrule cups at Z=0 | 16 |
93+ | ` --short-legs ` | named ferrule supports at Z=0 | 16 |
7894| ` --float-stretchers ` | stretcher-leg join | 17 |
79- | ` --pipe-ferrule ` | ferrule inner-clearance band | 18 |
95+ | ` --pipe-ferrule ` | ferrule grip (a pipe ring on the tread; measured −0.00011) | 18 |
96+ | ` --sink-legs ` | foot stack (leg ends 10 mm into the tread; measured −0.00887) | 20 |
97+ | ` --low-bake ` | bake texel density (256 px bake; measured 5.61 px) | 21 |
98+
99+ ` --pipe-ferrule ` keeps the treads, so the triangle band and the envelope
100+ cannot steal its failure. ` --sink-legs ` keeps the leg inside its sleeve, so
101+ the grip still passes.
80102
81103## Run
82104
@@ -88,6 +110,8 @@ blender --background --python tavern_stool.py -- --lift-z
88110blender --background --python tavern_stool.py -- --short-legs
89111blender --background --python tavern_stool.py -- --float-stretchers
90112blender --background --python tavern_stool.py -- --pipe-ferrule
113+ blender --background --python tavern_stool.py -- --sink-legs
114+ blender --background --python tavern_stool.py -- --low-bake
91115blender --background --python tavern_stool.py -- --output stool.png
92116```
93117
@@ -97,7 +121,7 @@ Smoke passes no flags.
97121
98122File-local. ` 9 ` is a valid check code. ` 10 ` is reserved for
99123` gallery_framing.check_framing ` on the ` --output ` path. ` 15 ` –` 19 ` are the
100- hygiene and joint-fit family.
124+ hygiene and joint-fit family. ` 20 ` and ` 21 ` are this piece's own.
101125
102126| Code | Meaning |
103127| --- | --- |
@@ -117,7 +141,9 @@ hygiene and joint-fit family.
117141| 13 | Export file missing or empty |
118142| 14 | ` --output ` produced no file |
119143| 15 | Mesh hygiene: loose, non-manifold, zero-area, doubles, n-gons, z-fight |
120- | 16 | Not grounded: bounding box ` zmin ` off 0, or a named ferrule cup floats |
144+ | 16 | Not grounded: bounding box ` zmin ` off 0, or a named ferrule support floats |
121145| 17 | Joint fit: stretcher-leg gap |
122- | 18 | Seat: ferrule inner-clearance band |
146+ | 18 | Ferrule grip out of band, or a sleeve missing ( ` --pipe-ferrule ` ) |
123147| 19 | Seat diameter or height off the stated real-world size |
148+ | 20 | Foot stack: leg end below its tread's top, or sleeve not buried (` --sink-legs ` ) |
149+ | 21 | Bake texel density below floor (` --low-bake ` ) |
0 commit comments