11# Wall torch
22
3- A showcase piece, not an example. Procedural wall-mounted torch sconce
4- (running-bond dressed stone plaque, iron plate and arm from named
5- stations, bowl cup, wooden haft, emissive flame) then the shipped
6- pipeline: unique-cell UVs, Cycles high-to-low normal bake, LOD chain,
7- convex collider, Unity glTF export.
8-
9- The plaque back sits on the wall plane Y=0 with zmin at 0. The iron
10- arm is a tube from the plate station to the cup wall, not a pair of
11- square bars aimed at a funnel. The bowl opens upward and holds the
12- haft. Hygiene family 15–19: ` --stray-vert ` , ` --lift-z ` , ` --float-arm ` ,
13- ` --float-plate ` , ` --skinny-plaque ` .
3+ A showcase piece, not an example. A procedural wall-mounted torch sconce: a
4+ running-bond dressed-stone plaque with dark mortar joints, an iron wall
5+ plate bolted to the stones, a level iron arm, an open iron cup, a leaning
6+ wooden haft with a pitch wrap, and upright emissive flames. Then the shipped
7+ pipeline: unique-cell UVs, a Cycles high-to-low normal bake, an LOD chain, a
8+ convex collider and a Unity glTF export.
9+
10+ The plaque back sits on the wall plane Y=0 with zmin at 0. The plate's seat
11+ comes from the face of the facing stones (` stone_face_y() ` ), a named bite
12+ into it. The cup's mid-height is the arm's height, so the arm is level by
13+ construction. It runs from inside the plate into the cup's wall. The cup
14+ sits on the haft's axis, which leans 15° out from the wall. The haft stands
15+ on the cup's floor and runs up into the wrap. The flames stand upright from
16+ the wrap, whatever the haft does.
1417
1518It asserts ** budget conformance** of the generated result. It does not
1619witness an API contract. "It rendered without error" is not a check.
@@ -24,35 +27,39 @@ witness an API contract. "It rendered without error" is not a check.
2427Hygiene combinatorics match ` examples/mesh-hygiene-audit ` (copied, not
2528imported).
2629
27- Intended size: 0.28 m plaque width, 0.40 m plaque height, bowl
28- projecting 0.24 m from the wall; outer AABB 0.304 × 0.293 × 0.424 m.
30+ Intended size: a 0.28 m wide, 0.40 m tall plaque; the cup centre 0.24 m out
31+ from the wall; the flame tip 0.48 m above the floor. Outer AABB
32+ 0.304 × 0.322 × 0.485 m.
2933
3034## Budgets
3135
32- Declared as named constants; every gate ** recomputes** from the mesh,
33- materials, UVs, evaluated LOD, collider, or export file.
36+ Declared as named constants. Every gate ** recomputes** its value from the
37+ mesh, materials, UVs, evaluated LOD, collider or export file.
3438
3539| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) |
3640| --- | --- | --- |
37- | Base triangles | 1400–1700 | 1528 / 1528 / 1528 |
41+ | Base triangles | 1800–2250 | 2004 / 2004 / 2004 |
3842| LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 |
39- | LOD2 ratio | 0.10–0.35 of base | 0.2199 / 0.2199 / 0.2199 |
40- | Materials | exactly 4 distinct, ≥24 stone, ≥24 metal, ≥8 flame | 4 slots, 540 stone, 228 metal, 78 flame |
43+ | LOD2 ratio | 0.10–0.35 of base | 0.2196 / 0.2196 / 0.2196 |
44+ | Materials | exactly 5 distinct; ≥24 stone, ≥24 metal, ≥8 flame, ≥10 pitch | 5 slots; 540 stone, 318 metal, 50 wood, 180 flame, 60 pitch |
4145| UVs | in ` 0..1 ` , AABB overlap ≤ 1e-5 | in range, overlap 0 |
42- | Outer AABB | (0.304, 0.293, 0.424) m ± 0.015 | (0.3040, 0.2930, 0.4240), zmin 0 |
43- | Collider tris | ≤ 180 | 60 |
44- | Export | written, size > 0 | 124608 / 124608 / 124584 bytes |
45-
46- Base triangles rose from ** 848 to 1528** in the quality pass: one
47- mailbox slab became four courses of running-bond ashlar plus a round
48- arm and a triangulated bowl. Outer AABB tightened from 0.384 × 0.360 ×
49- 0.670 m (and zmin 0.140) to 0.304 × 0.293 × 0.424 m at zmin 0.
50-
51- DECIMATE COLLAPSE triangle counts are ** not** identical across series.
52- The gate is a ratio band, not an exact count. Bake pixels are
53- stochastic; the gate is ` has_data ` plus operator ` FINISHED ` , not
54- byte-identity. Construction uses no RNG. Export byte counts differ by
55- 24 B on 5.2.1 (glTF serializer), not a gated axis.
46+ | Outer AABB | (0.304, 0.322, 0.485) m ± 0.015 | (0.3040, 0.3218, 0.4845), zmin 0 |
47+ | Collider tris | ≤ 180 | 116 |
48+ | Export | written, size > 0 | 164408 / 164408 / 164384 bytes |
49+
50+ Base triangles rose from ** 1528 to 2004** in the second quality pass, and the
51+ band moved from 1400–1700 to 1800–2250. The solid cup became an open, walled
52+ cup with a drip boss. The 26 mm haft stub became a 0.20 m haft with a wrap.
53+ The three flame cones became lathed teardrops. The envelope grew from
54+ 0.293 m to 0.322 m in depth and from 0.424 m to 0.485 m in height, because
55+ the torch now stands up out of its cup.
56+
57+ DECIMATE COLLAPSE triangle counts are ** not** identical across series. The
58+ gate is a ratio band, not an exact count. Bake pixels are stochastic; the
59+ gate is ` has_data ` plus operator ` FINISHED ` , not byte-identity. Construction
60+ is closed-form and stone tones are seeded, so repeated runs on one binary
61+ print identical measurements. Export byte counts differ by 24 B on 5.2.1
62+ (glTF serializer), not a gated axis.
5663
5764### Hygiene
5865
@@ -68,31 +75,41 @@ Recomputed from the generated mesh, not asserted about the script.
6875| Coplanar disjoint face pairs | 0 | 0 |
6976| Grounded: ` zmin ` | within 1e-4 of 0 | 0.0000 |
7077
71- ### Joint fit and plaque size
78+ ### Joint fit, seat and bake
7279
7380| Axis | Declared | Measured (all three) |
7481| --- | --- | --- |
75- | Arm-to-cup BVH gap | ≤ 0.008 m | 0.00087 |
76- | Plate-to-plaque BVH gap | ≤ 0.008 m | 0.00400 |
82+ | Arm-to-cup BVH gap | ≤ 0.008 m | 0.00007 |
83+ | Plate-to-stone BVH gap | ≤ 0.008 m | 0.00057 |
7784| Plaque width vs ` WALL_W ` | ± 0.04 m | 0.2800 vs 0.280 |
85+ | Arm level (exit 20): the arm shell's long axis against horizontal | ≤ 1.0° | 0.000° |
86+ | Plate seat (exit 21): plate front proud of the facing stones / plate back into their face | ≥ 0.008 m / 0.001–0.005 m | 0.01300 / 0.00300 |
87+ | Bake texel density (exit 22): smallest UV cell in baked texels | ≥ 12 px | 27.71 px (1024 px bake) |
88+
89+ The plate-to-stone gap is measured to any stone shell. The plate is bolted to
90+ the face of the stones, not to the backing slab behind them, as it was in the
91+ first build.
7892
7993### Falsifiers
8094
81- Each violates one named budget. All were run on 4.5.11, 5.1.2 and 5.2.1
82- and returned the same code on each.
95+ Each violates one named budget. All were run on 4.5.11, 5.1.2 and 5.2.1 and
96+ returned the same code on each.
8397
8498| Flag | Budget violated | Exit |
8599| --- | --- | --- |
86100| ` --skip-decimate ` | LOD1 ratio band | 9 |
87101| ` --stray-vert ` | loose vertex count is 0 | 15 |
88102| ` --lift-z ` | bounding box ` zmin ` is 0 | 16 |
89103| ` --float-arm ` | arm-to-cup BVH gap | 17 |
90- | ` --float-plate ` | plate-to-plaque BVH gap | 18 |
104+ | ` --float-plate ` | plate-to-stone BVH gap (measured 0.07700) | 18 |
91105| ` --skinny-plaque ` | plaque width vs ` WALL_W ` | 19 |
106+ | ` --droop-arm ` | arm level (the old 20 mm drop; measured 9.580°) | 20 |
107+ | ` --sink-plate ` | plate seat (the first build's seat; measured proud −0.00400, seat 0.02000) | 21 |
108+ | ` --low-bake ` | bake texel density (256 px bake; measured 6.93 px) | 22 |
92109
93- ` --float-arm ` shortens the tube to 55 % of the plate-to-cup station
94- vector; the cup stays put. ` --float-plate ` moves only the hang plate
95- off the plaque; the arm still reaches the cup so 17 still passes.
110+ ` --float-arm ` shortens the tube to 55 % of the plate-to-cup station vector,
111+ and the cup stays put. ` --float-plate ` moves only the plate off the stones;
112+ the arm root stays at the seated plate, so 17 still passes.
96113` --skinny-plaque ` scales the back plaque and courses to 0.55 · ` WALL_W ` .
97114
98115## Run
@@ -105,6 +122,9 @@ blender --background --python wall_torch.py -- --lift-z
105122blender --background --python wall_torch.py -- --float-arm
106123blender --background --python wall_torch.py -- --float-plate
107124blender --background --python wall_torch.py -- --skinny-plaque
125+ blender --background --python wall_torch.py -- --droop-arm
126+ blender --background --python wall_torch.py -- --sink-plate
127+ blender --background --python wall_torch.py -- --low-bake
108128blender --background --python wall_torch.py -- --output torch.png
109129```
110130
@@ -114,7 +134,7 @@ Smoke passes no flags.
114134
115135File-local. ` 9 ` is a valid check code. ` 10 ` is reserved for
116136` gallery_framing.check_framing ` on the ` --output ` path. ` 15 ` –` 19 ` are the
117- hygiene and joint-fit family.
137+ hygiene and joint-fit family. ` 20 ` – ` 22 ` are this piece's own.
118138
119139| Code | Meaning |
120140| --- | --- |
@@ -123,7 +143,7 @@ hygiene and joint-fit family.
123143| 2 | argparse / usage |
124144| 3 | Mesh did not build / no UV layer |
125145| 4 | Base triangle count outside range |
126- | 5 | Material count ≠ 4 distinct slots, or stone/metal/flame faces missing |
146+ | 5 | Material count ≠ 5 distinct slots, or stone/metal/flame/pitch faces missing |
127147| 6 | UVs outside 0..1 |
128148| 7 | UV AABB overlap above tolerance |
129149| 8 | World AABB off declared outer size |
@@ -136,5 +156,8 @@ hygiene and joint-fit family.
136156| 15 | Hygiene (` --stray-vert ` lands here) |
137157| 16 | Grounded zmin (` --lift-z ` ) |
138158| 17 | Arm-to-cup gap (` --float-arm ` ) |
139- | 18 | Plate-to-plaque gap (` --float-plate ` ) |
159+ | 18 | Plate-to-stone gap (` --float-plate ` ) |
140160| 19 | Plaque width (` --skinny-plaque ` ) |
161+ | 20 | Arm not level (` --droop-arm ` ) |
162+ | 21 | Plate not seated on the stone face (` --sink-plate ` ) |
163+ | 22 | Bake texel density below floor (` --low-bake ` ) |
0 commit comments