Skip to content

Commit 3f51dde

Browse files
TMHSDigitalclaude
andcommitted
fix(showcase): give wooden-ladder through-tenons, iron tie-rods and two-tone timber
Earlier passes only touched lighting, materials and the turned rungs, and the bare ladder stayed the plainest object in its asset sheet: the exact 16-shell parts budget kept every detail inside the existing shells. This pass changes the model and raises the budgets, with the justification in the README. - Two iron tie-rods run through both rails under the bottom and top rungs. Each end is clamped by a square nut over a round washer bedded on the rail's outer face (parts 16 -> 26). - The rungs are through-tenoned: each tenon runs right through its rail and stands 2 mm proud. The old blind-tenon "breakout margin" becomes a through-tenon proud band (0.001-0.004 m). The tenon's inboard ring moves to 4 mm inside the rail, so the joint audit still samples tenon section inside the wood. - A per-shell Species attribute: pale hickory rungs against darker oak rails. End grain (tenon ends, rail tops) reads darker. The iron's rust is darker, so the hardware reads as iron. - The rung finders (rung_pitch, the render's rope coil) now require the wood material, because the tie-rods are as wide as a rung. - New budget: tie-rod seat. It checks 2 rods, 4 washers and 4 nuts: washer into the stile and nut into the washer 0.0002-0.002 m, on the rod axis within 1.5 mm, and the thread >= 3 mm proud of each nut. New falsifier --float-nuts exits 20. Budgets, before -> after: - base tris 2680 -> 3000; ceiling 2800 -> 3100 (hardware +320) - parts 16 -> 26 - metal faces 736 -> 832 - collider 24 -> 92 tris (ceiling 180) - bbox (0.4897, 0.3760, 1.4870) -> (0.4903, 0.3760, 1.4870) - tenon proud 0.00199, tie seat bite 0.00049..0.00051, thread 0.00450 Evidence (live, local): - .scratch/blender-5.2.1-windows-x64/blender.exe (Blender 5.2.1 LTS) and .scratch/blender-4.5.11-windows-x64/blender.exe (Blender 4.5.11 LTS): default exit 0 with identical measurements. - tests/check_falsifier_targets.py --run on both binaries: all 8 wooden-ladder falsifiers land (--skip-decimate 9, --stray-vert 15, --twin-sole 15, --lift-z 16, --fat-rungs 17, --short-stile 18, --drift-rungs 19, --float-nuts 20). The static check passes (338 falsifiers across 36 pieces). --float-nuts measured failure: seat bite -0.00350, thread 0.00050 proud. - Framing on both versions: fill y 0.883, margins l/r 0.416, b 0.044, t 0.072. - Contact sheet: luma 0.210, stage 0.201, warmth +0.086, saturation 0.173. - Asset sheet (docs/gallery/asset-sheets/wooden-ladder.webp): the tie-rods, the two-tone rungs and the tenon ends now read. It is on a par with the hydrant, not clearly the plainest, though a ladder is still the thinnest silhouette in the lineup. - 5.1.2 was not re-run. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent af7a90c commit 3f51dde

8 files changed

Lines changed: 300 additions & 56 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ Budget-conformance props. Not examples. Conventions: [`showcase/README.md`](show
133133
<a href="showcase/wall-torch/"><img src="showcase/wall-torch/preview.webp" width="24%" alt="Wall torch: a dressed stone plaque with an iron plate and arm holding a cup, a leaning wooden torch with a pitch-wrapped head and a bright flame, on a dark studio floor" /></a>
134134
<a href="showcase/tavern-stool/"><img src="showcase/tavern-stool/preview.webp" width="24%" alt="Tavern stool: a dished round wooden seat holding a pewter tankard, on turned splayed legs with stretchers at two heights and iron ferrules on flat treads, on a dark studio floor" /></a>
135135
<a href="showcase/iron-cauldron/"><img src="showcase/iron-cauldron/preview.webp" width="24%" alt="Iron cauldron: a round-bellied cast-iron pot hanging by its bail from a timber tripod on a dark studio floor" /></a>
136-
<a href="showcase/wooden-ladder/"><img src="showcase/wooden-ladder/preview.webp" width="24%" alt="Wooden ladder: a raked timber ladder with six evenly spaced turned rungs and iron shoes, leaning on a weathered barn-board wall with a coil of hemp rope hung over a rung" /></a>
136+
<a href="showcase/wooden-ladder/"><img src="showcase/wooden-ladder/preview.webp" width="24%" alt="Wooden ladder: an oak ladder with six pale turned hickory rungs through-tenoned into its rails, iron tie-rods under the end rungs and iron shoes, leaning on a barn-board wall with a rope coil on a rung" /></a>
137137
<a href="showcase/hay-bale/"><img src="showcase/hay-bale/preview.webp" width="24%" alt="Hay bale: a bound straw bale with two sisal twine belts on a dark studio floor" /></a>
138138
<a href="showcase/crate-stack/"><img src="showcase/crate-stack/preview.webp" width="24%" alt="Crate stack: three slatted shipping crates stacked and yawed, each with iron corner straps and runners, on a dark studio floor" /></a>
139139
<a href="showcase/stone-archway/"><img src="showcase/stone-archway/preview.webp" width="24%" alt="Stone archway: a semicircular masonry arch with coursed piers, projecting imposts, nine voussoirs and a proud keystone, on a dark studio floor" /></a>
16 Bytes
Loading
-624 Bytes
Loading
-100 Bytes
Loading

‎showcase/gallery.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@
326326
"name": "wooden-ladder",
327327
"dir": "showcase/wooden-ladder",
328328
"teaches": "A procedural timber ladder with raked tapered stiles, six turned rungs, ferrule caps, and level shoe plates through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.",
329-
"alt": "A timber ladder with tapered stiles and six evenly spaced lathe-turned rungs, leaning on a weathered board wall with a coil of hemp rope hung over its second-highest rung.",
329+
"alt": "An oak ladder with six pale turned hickory rungs through-tenoned into its rails, iron tie-rods under the end rungs, leaning on a board wall with a rope coil on a rung.",
330330
"witnessesFix": "Recomputed: 2536 tris, two materials with 612 wood and 736 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.490×0.376×1.487 m, zmin 0, hygiene and coplanar pairs 0, tenon clearance 8 mm, shoe bite 20 mm, rung pitch even to 0.002 m, LOD ratios in band, convex collider 24 tris, non-empty glTF. --skip-decimate exits 9; --stray-vert and --twin-sole exit 15; --lift-z exits 16; --fat-rungs exits 17; --short-stile exits 18; --drift-rungs exits 19.",
331331
"hero": "docs/gallery/assets/wooden-ladder-hero.webp",
332332
"preview": "showcase/wooden-ladder/preview.webp",

‎showcase/wooden-ladder/README.md‎

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
# Wooden ladder
22

33
A showcase piece, not an example. Procedural timber ladder: two stiles
4-
tapered from 64 mm to 50 mm, raked 12°, six turned rungs (22 mm tenon, a
4+
tapered from 64 mm to 50 mm, raked 12°, six turned hickory rungs (a
55
barrel that shoulders in just under its radius and swells 14 % at
6-
mid-span, the profile a lathe leaves on a ladder round), iron ferrules at the top, and
7-
level shoe plates under sleeves that follow the rake. Then the shipped
6+
mid-span, the profile a lathe leaves on a ladder round) through-tenoned
7+
into oak rails with their end grain showing 2 mm proud of the outer faces,
8+
two iron tie-rods under the bottom and top rungs clamped by square nuts
9+
over round washers, iron ferrules at the top, and level shoe plates under
10+
sleeves that follow the rake. Then the shipped
811
pipeline: unique-cell UVs, Cycles high-to-low normal bake, LOD chain,
912
convex collider, Unity glTF export.
1013

@@ -37,24 +40,25 @@ imported). Coplanar-pair counting matches `showcase/signpost`.
3740
Declared as named constants; every gate **recomputes** from the mesh,
3841
materials, UVs, evaluated LOD, collider, or export file.
3942

40-
| Axis | Declared | Measured (4.5.11 / 5.2.1; 5.1.2 not re-run after the turned-rung pass) |
43+
| Axis | Declared | Measured (4.5.11 / 5.2.1; 5.1.2 not re-run after the tie-rod pass) |
4144
| --- | --- | --- |
42-
| Base triangles | 1800–2800 | 2680 / 2680 |
45+
| Base triangles | 1800–3100 | 3000 / 3000 |
4346
| LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 |
44-
| LOD2 ratio | 0.10–0.35 of base | 0.2194 / 0.2194 |
45-
| Materials | exactly 2 distinct, ≥280 wood, ≥180 metal | 2 slots, 684 wood, 736 metal |
47+
| LOD2 ratio | 0.10–0.35 of base | 0.2200 / 0.2200 |
48+
| Materials | exactly 2 distinct, ≥280 wood, ≥180 metal | 2 slots, 684 wood, 832 metal |
4649
| UVs | in `0..1`, AABB overlap ≤ 1e-5 | in range, overlap 0 |
47-
| Outer AABB | (0.490, 0.376, 1.487) m ± 0.01 | (0.4897, 0.3760, 1.4870) |
50+
| Outer AABB | (0.490, 0.376, 1.487) m ± 0.01 | (0.4903, 0.3760, 1.4870) |
4851
| Grounded | `abs(zmin)` ≤ 1e-4, each sole at 0, rail end ≥ 0.012 m | zmin 0, sole 0, rail 0.02037 |
4952
| Mesh hygiene | non-manifold, loose v/e, doubles at 1e-5, zero-area, n-gons, coplanar pairs all 0 | all 0 |
50-
| Parts | 16 shells (2 stiles, 6 rungs, 2 sleeves, 2 cap sleeves, 2 plates, 2 soles) | 16 (2 / 6 / 2 / 2) |
53+
| Parts | 26 shells (2 stiles, 6 rungs, 2 sleeves, 2 cap sleeves, 2 plates, 2 soles, 2 tie-rods, 4 washers, 4 nuts) | 26 (2 / 6 / 2 / 2) |
5154
| Rung depth clearance | ≥ 0.003 m inside the stile faces | 0.00800 |
52-
| Tenon engagement | ≥ 0.008 m past the stile inner face | 0.01399 |
53-
| Tenon breakout margin | ≥ 0.008 m short of the stile outer face | 0.03787 |
55+
| Tenon engagement | ≥ 0.008 m past the stile inner face | 0.05387 (through) |
56+
| Through-tenon proud | tenon end 0.001–0.004 m past the stile outer face | 0.00199 |
5457
| Shoe bite / cover | bite ≥ 0.010 m, cover ≥ 0.016 m | 0.02000 / 0.03800 |
5558
| **Rung pitch** | 6 rungs; every rung-to-rung gap within 0.002 m of the mean | 6; 0.00000 |
56-
| Collider tris | ≤ 180 | 24 |
57-
| Export | written, size > 0 | 197604 / 197584 bytes |
59+
| **Tie-rod seat** | 2 rods, 4 washers, 4 nuts; washer into stile and nut into washer 0.0002–0.002 m; on the rod axis within 0.0015 m; thread ≥ 0.003 m proud of each nut | 2 / 4 / 4; bite 0.00049–0.00051; axis 0; thread 0.00450 |
60+
| Collider tris | ≤ 180 | 92 |
61+
| Export | written, size > 0 | 230268 bytes (5.2.1) |
5862

5963
Base triangles rose from **936 to 2536**. The previous mesh was two
6064
boxes, six cloned dowels, and four chrome cubes. Turned rungs (tenon
@@ -75,6 +79,25 @@ across the stile's 50 mm width at a readable scale (`WOOD_GRAIN_SCALE`
7579
spanned a stile, so it rendered as flat tan. A short-range AO term darkens
7680
the rung housings and the wood under the iron sleeves.
7781

82+
A third pass changed the model itself. The bare ladder was still the
83+
plainest object in its asset sheet, because the exact parts budget left
84+
every detail inside the existing shells. The parts budget is now **26**:
85+
two iron tie-rods run through both rails under the bottom and top rungs,
86+
each end clamped by a square nut over a round washer bedded on the rail's
87+
outer face. That is the rod a wooden ladder carries to stop the rails
88+
spreading off the rungs. The triangle ceiling rose **2800 → 3100** for the
89+
hardware (+320 triangles; the old ceiling had 120 to spare). The rungs are
90+
now through-tenoned: each tenon runs right through its rail and stands
91+
2 mm proud, so the old *breakout margin* (a blind tenon stopping short of
92+
the outer face) became a **through-tenon proud** band, and the tenon's
93+
inboard ring moved to 4 mm inside the rail so the joint audit always
94+
samples tenon section in the wood. The shader reads a per-shell
95+
`Species` attribute: rungs are pale hickory against darker oak rails, and
96+
end grain (the tenon ends, the rail tops) takes the finish darker. The
97+
rung finders now require the wood material, because the tie-rods are as
98+
wide as a rung. The new **tie-rod seat** budget gets its own falsifier,
99+
`--float-nuts` (exit 20).
100+
78101
The joint budgets are measured per rung against each stile, from vertex
79102
positions in the un-raked construction frame, and the reported value is
80103
the worst case. Clearance is the tenon, not the barrel: the barrel is
@@ -106,7 +129,8 @@ rake toward, with its face through the rail tops, and turns the ladder
106129
so that side faces away from the camera.
107130

108131
Each falsifier violates exactly one named budget. Proven on Blender
109-
4.5.11 LTS, 5.1.2, and 5.2.1 LTS (the binaries' own `--version`):
132+
4.5.11 LTS and 5.2.1 LTS (the binaries' own `--version`; 5.1.2 not re-run
133+
after the tie-rod pass):
110134

111135
| Falsifier | Budget violated | Exit | Measured failure |
112136
| --- | --- | --- | --- |
@@ -117,8 +141,9 @@ Each falsifier violates exactly one named budget. Proven on Blender
117141
| `--fat-rungs` | Rung depth clearance | 17 | clearance 0 |
118142
| `--short-stile` | Shoe bite / cover | 18 | bite 0.070, cover −0.012 |
119143
| `--drift-rungs` | Rung pitch | 19 | worst gap 0.03287 off the mean |
144+
| `--float-nuts` | Tie-rod seat | 20 | seat bite −0.00350, thread 0.00050 proud |
120145

121-
Default exit is 0 on all three.
146+
Default exit is 0 on both.
122147

123148
## Run
124149

@@ -131,6 +156,7 @@ blender --background --python wooden_ladder.py -- --lift-z
131156
blender --background --python wooden_ladder.py -- --fat-rungs
132157
blender --background --python wooden_ladder.py -- --short-stile
133158
blender --background --python wooden_ladder.py -- --drift-rungs
159+
blender --background --python wooden_ladder.py -- --float-nuts
134160
blender --background --python wooden_ladder.py -- --output preview.webp --engine cycles
135161
```
136162

@@ -160,6 +186,7 @@ File-local. `9` is a valid check code. `10` is reserved for
160186
| 14 | `--output` produced no file |
161187
| 15 | Mesh hygiene, including coplanar pairs (`--stray-vert`, `--twin-sole`) |
162188
| 16 | Grounded zmin, or a rail end sitting in the tread (`--lift-z`) |
163-
| 17 | Part count or rung-to-stile joint fit (`--fat-rungs`) |
189+
| 17 | Part count or rung-to-stile joint fit, including through-tenon proud (`--fat-rungs`) |
164190
| 18 | Shoe bite / cover (`--short-stile`) |
165191
| 19 | Rung pitch (`--drift-rungs`) |
192+
| 20 | Tie-rod seat (`--float-nuts`) |
-486 Bytes
Loading

0 commit comments

Comments
 (0)