Skip to content

Commit 1c85142

Browse files
TMHSDigitalclaude
andcommitted
fix(showcase): garden-gate quality pass: real oak grain, braced side on show, brace-direction witness
- Each member gets its own grain direction from a per-member GrainCo attribute: warm silver-brown oak with streaks and checks. This replaces the fingerprint-line texture. - The straps move onto the ledges, as on a real hook-and-band gate. - The hero now shows the braced side with the leaf swung 32 degrees, so the ledges, braces, straps, knuckles and barrel bolt all read. - The posts get V-groove necks. The flags get knocked corners and 7 mm joints, and two added flags close the void that showed beneath the swing. - New witness: each brace rises from the hinge side. Measured from the pin axis, brace 0 runs 0.178 to 0.741 m and brace 1 runs 0.215 to 0.703 m. --reversed-braces exits 21. - 27-run falsifier matrix on 4.5.11 / 5.1.2 / 5.2.1, every run on its declared code. - Tris 3936 (band 3700-4200). Framing, asset quality and the asset sheet pass. - Contact sheet: luma 0.245, stage 0.202. Saturation is 0.143, just under the 0.153 floor; this is accepted as the cost of greyed, weathered oak. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent f09f795 commit 1c85142

8 files changed

Lines changed: 765 additions & 249 deletions

File tree

-1.88 KB
Loading
968 Bytes
Loading
-2.52 KB
Loading
636 Bytes
Loading

‎docs/gallery/garden-gate/index.html‎

Lines changed: 434 additions & 116 deletions
Large diffs are not rendered by default.

‎showcase/garden-gate/README.md‎

Lines changed: 82 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# garden-gate
22

3-
![A ledged and braced garden gate of six weathered oak boards with a bow top, standing ajar on two black strap hinges between square oak posts on sandstone flags, a ring pull on its face](preview.webp)
3+
![A weathered oak garden gate swung ajar between two square posts on sandstone flags, seen from its braced side: three ledges with a Z of braces between them, black hook-and-band straps bolted along the top and bottom ledges and a barrel bolt on the middle one](preview.webp)
44

55
A 900 mm ledged-and-braced garden gate: six vertical oak boards under a
66
bow top, nailed to three back ledges with two diagonal braces between
7-
them, hung from a squared hinge post on two hook-and-band hinges and
8-
closing against a latch post. A barrel bolt sits on the back, a keeper
7+
them, hung from a squared hinge post on two hook-and-band hinges whose
8+
straps are bolted along the top and bottom ledges, and closing against a
9+
latch post. A barrel bolt sits on the middle ledge, a keeper
910
staple on the latch post, a ring pull on the front, and both posts stand
1011
in sandstone flags. **A showcase piece, not an example** — it witnesses
1112
no API contract. It asserts that generated geometry meets declared asset
@@ -16,7 +17,7 @@ budgets, recomputed from the finished mesh.
1617
| Shipped content | Used for |
1718
| --- | --- |
1819
| `skills/mesh-editing-and-bmesh` | prisms, revolved knuckles, pins, domes and nail heads, a torus ring, all in one `bmesh`, chamfered with `bmesh.ops.bevel` |
19-
| `skills/custom-properties` | face attributes: `Part` (what each shell is), `GrainDir` (vertical or horizontal fibre) and `WoodTone` (one tone per board or flag) |
20+
| `skills/custom-properties` | face attributes `Part` (what each shell is) and `WoodTone` (one tone per board or flag); a point attribute `GrainCo` (each vertex in its member's own along / across / through frame) |
2021
| `skills/procedural-materials-and-shaders` | weathered oak with grain along each member, a tone per board and grime toward the ground; black forged iron rusting in patches; sandstone flags |
2122
| `skills/bake-high-to-low` | Cycles tangent-space normal bake, a 24-segment high onto the 12-segment low |
2223
| `skills/engine-export-presets` | Unity glTF (`export_yup=True`) |
@@ -40,8 +41,13 @@ It can fail without looking wrong:
4041
- **Each knuckle must rest on its hook**, a seat, not a float.
4142
- **The gate must clear the latch post as it swings.** A closed gate shows
4243
nothing; only the swing circle does.
44+
- **Each brace must rise from the hinge side.** Its lower end sits next to
45+
the hinge stile and its upper end toward the latch, so it works in
46+
compression and carries the free edge's weight back into the bottom
47+
hinge. Mirrored, the same timber hangs the free edge off a strut in
48+
tension and the gate sags; it looks just as plausible from a distance.
4349

44-
The piece measures all four off the finished mesh. Every shell carries a
50+
The piece measures all five off the finished mesh. Every shell carries a
4551
`Part` face attribute written at build time, so the audit finds the two
4652
knuckles, the two pins, the two hooks, every member that hangs on the
4753
hinges and the latch post with its keeper, without guessing from shape.
@@ -63,16 +69,23 @@ hinges and the latch post with its keeper, without guessing from shape.
6369
axes. Every vertex that hangs on the hinges (boards, ledges, braces,
6470
straps, knuckles, bolts, nails, the barrel bolt and the ring) gives the
6571
swing circle's radius; every vertex of the latch post and its keeper
66-
gives the nearest obstacle. Clearance 8–30 mm; measured 14.87 mm
67-
(radius 0.9153 m, keeper at 0.9301 m).
72+
gives the nearest obstacle. Clearance 8–30 mm; measured 12.96 mm
73+
(radius 0.9161 m, keeper at 0.9290 m).
74+
75+
- **Brace direction.** Each brace's lower end (its vertices within 5 mm
76+
of its lowest point) and upper end, as mean plan distance from the
77+
measured hinge axis: the upper end must be at least 0.30 m farther out.
78+
Measured 0.178 → 0.741 m and 0.215 → 0.703 m.
6879

6980
`--offset-knuckle` moves the upper knuckle 1.5 mm off its pin and leaves
7081
everything else where it was: exit 17. `--tilt-pintle` leans the upper pin
7182
about the knuckle's mid-height, so its axis still passes through the
7283
knuckle and the coaxial budget holds; only plumb fails, exit 19.
7384
`--tight-post` sets the latch post 14 mm closer; the paving defines the
7485
envelope, so the AABB does not move, and the swing clearance drops to
75-
0.89 mm: exit 20.
86+
−1.04 mm: exit 20. `--reversed-braces` mirrors both braces about the
87+
gate's centre line, lower ends at the latch side, on the same ledges and
88+
in the same envelope: exit 21.
7689

7790
## Budgets
7891

@@ -82,24 +95,25 @@ cross-version table for 4.5.11 and 5.1.2.
8295

8396
| Budget | Band | Measured |
8497
| --- | --- | --- |
85-
| Base triangles | 3100–3550 | 3320 |
98+
| Base triangles | 3700–4200 | 3936 |
8699
| LOD1 ratio | 0.32–0.62 | 0.5000 |
87-
| LOD2 ratio | 0.10–0.35 | 0.2193 |
100+
| LOD2 ratio | 0.10–0.35 | 0.2185 |
88101
| Material slots | exactly 3, distinct | 3 |
89-
| Timber / iron / ground faces | ≥ 330 / 1400 / 140 | 370 / 1534 / 156 |
90-
| UV bounds | inside 0..1 | (0.0009, 0.0009)–(0.9991, 0.9991) |
102+
| Timber / iron / ground faces | ≥ 400 / 1400 / 400 | 434 / 1534 / 464 |
103+
| UV bounds | inside 0..1 | (0.0008, 0.0008)–(0.9992, 0.9992) |
91104
| UV AABB overlap | ≤ 1e-5 | 0.000000 |
92-
| Outer AABB | 1.560 × 0.560 × 1.245 m ± 0.020 | 1.5600 × 0.5600 × 1.2450 |
93-
| Collider triangles | ≤ 400 | 344 (four hulls) |
105+
| Outer AABB | 1.560 × 0.880 × 1.245 m ± 0.020 | 1.5560 × 0.8759 × 1.2450 |
106+
| Collider triangles | ≤ 400 | 394 (four hulls) |
94107
| Normal bake | `{'FINISHED'}` with image data | `{'FINISHED'}`, `has_data=True` |
95-
| glTF export | file written, non-empty | ~281 kB |
108+
| glTF export | file written, non-empty | ~332 kB |
96109
| Hygiene | all zero | loose 0/0, non-manifold 0, zero-area 0, doubles 0, n-gons 0, coplanar cross-shell pairs 0 |
97110
| Grounded AABB | \|zmin\| ≤ 1e-4 | 0.00000 |
98-
| Parts | 6 flags, 2 posts, 6 boards, 3 ledges, 2 braces, 2 straps, 2 knuckles, 2 pins, 2 hooks, 6 bolt heads, 26 nails, 5 bolt pieces, 1 keeper, 3 ring pieces | as stated |
111+
| Parts | 8 flags, 2 posts, 6 boards, 3 ledges, 2 braces, 2 straps, 2 knuckles, 2 pins, 2 hooks, 6 bolt heads, 26 nails, 5 bolt pieces, 1 keeper, 3 ring pieces | as stated |
99112
| Knuckle on pin | coaxial ≤ 0.3 mm, clearance 0.3–1.0 mm | 0.000 mm, 0.600 mm (both hinges) |
100113
| Knuckle seat | −1.0 to −0.2 mm on the hook | −0.500 mm (both) |
101114
| Plumb shared axis | each pin ≤ 0.2 mm, pins ≤ 0.3 mm apart | 0.000 mm, 0.000 mm |
102-
| Swing clearance | 8–30 mm past the latch post and keeper | 14.87 mm |
115+
| Swing clearance | 8–30 mm past the latch post and keeper | 12.96 mm |
116+
| Brace direction | each brace's upper end ≥ 0.30 m farther from the hinge axis than its lower end | 0.178 → 0.741 m, 0.215 → 0.703 m |
103117
| Real-world size | gate 0.900 ± 0.003 × 0.960 ± 0.005, post 1.205 ± 0.005 above its flag, strap 0.400 ± 0.005, pin Ø 12 ± 0.5 mm | 0.9000 × 0.9599, 1.2050, 0.3995, 12.000 mm |
104118

105119
Real-world size: hook-and-band hinges are usually sized at a third of the
@@ -117,8 +131,10 @@ above the flags.
117131
rise from the hinge side to the latch side (the strut that carries the
118132
free edge's weight back down into the bottom hinge); their ends are
119133
bitten 2 mm into the ledges and their faces sit off the ledges' planes.
120-
- **Hinges.** The strap is a tapered prism 0.5 mm into the boards, with
121-
three domed carriage-bolt heads. The knuckle is a revolved tube 6.6 mm
134+
- **Hinges.** Hook-and-band straps go on the ledged side: each strap is
135+
a tapered prism lying along the top or bottom ledge, let 0.5 mm into
136+
it, with three domed carriage-bolt heads through the ledge, so the
137+
hinge axis sits behind the boards, in line with the ledges. The knuckle is a revolved tube 6.6 mm
122138
bore, 11.2 mm outside, 40 mm tall, 2 mm taller than the strap so their
123139
ends are not one plane. The hook is a 14 mm square shank driven 70 mm
124140
into the hinge post and a 12 mm pin rising through it, chamfered at the
@@ -130,17 +146,28 @@ above the flags.
130146
rod drawn back inside the gate's edge and its knob), a keeper staple
131147
bitten 6 mm into the latch post, and a ring pull on a round rose that
132148
hangs from its staple and leans out at the bottom.
133-
- **Posts and paving.** Square posts with chamfered arrises and a
134-
pyramid weathering, sunk 20 mm into the flags. A pad flag under each
135-
post and four flags across the opening, 12 mm joints, the opening's
136-
flags 4–6 mm proud or shy of the pads so no two flag tops are one plane.
149+
- **Posts and paving.** Square posts with chamfered arrises, a V-groove
150+
necking each one 70 mm below a pyramid weathering, sunk 20 mm into the
151+
flags. A pad flag under each post, four flags across the opening and
152+
two more on the side the gate swings to, so the open leaf hangs over
153+
paving (a gateway is paved where the gate sweeps), 7 mm joints, each flag dressed with knocked-off corners and edges a few
154+
millimetres out of true, the opening's flags 4–6 mm proud or shy of the
155+
pads so no two flag tops are one plane.
156+
- **Timber surface.** `GrainCo` puts every vertex in its member's own
157+
frame (along the grain, across the face, through the thickness), offset
158+
per shell, so fibres run up the boards and posts, along the ledges and
159+
down each brace's diagonal, and no two members share a figure. The oak
160+
is a low-contrast silver-brown: mid-scale streaks, thin latewood lines
161+
spaced irregularly, sparse checking cracks, long weathering patches,
162+
a tone per member and grime toward the ground.
137163
- **Collider.** One hull per post, one over the gate's timber, one over
138164
the paving. The ironwork is left out: millimetres of strap and bolt on
139165
faces the gate's hull already covers.
140-
- **The still.** The gate is swung 24° open about the measured hinge axis
141-
for the render only, so the knuckles are seen turning on their pins and
142-
the keeper shows on the latch post. Every budget is asserted on the
143-
closed gate.
166+
- **The still.** Seen from the braced side, so the ledges, the Z of
167+
braces, the straps and the barrel bolt all read; the gate is swung 32°
168+
toward the viewer about the measured hinge axis for the render only,
169+
so the knuckles are seen turning on their pins. Rendered in Cycles with
170+
denoising. Every budget is asserted on the closed gate.
144171

145172
## Findings the budgets forced
146173

@@ -154,9 +181,18 @@ above the flags.
154181
to break the swing, but it moves the gate's width before the swing is
155182
read, so it would fail the real-world size first. `--tight-post` moves
156183
the latch post instead.
157-
- **The swing has a limit the other way.** Swung inward the gate's
158-
hinge-side back corner meets the hinge post at about 35°; the still
159-
uses 24°.
184+
- **The swing has a limit the other way.** Swung away from the straps
185+
the gate's hinge-side corner meets the hinge post; the still swings it
186+
32° toward the strap side, the way a gate hung on the ledged face opens.
187+
- **Quality pass findings.** Moving the straps onto the ledges first
188+
reported four coplanar pairs: a ledge's end chamfer and the strap's end
189+
chamfer fell on one plane while the ledges stopped 4 mm from the board
190+
edge; they stop 6 mm in now. Dressing the flags turned each underside
191+
into an n-gon whose ear-clipped triangles sat within reach of the next
192+
flag's (all undersides lie at z = 0), two more pairs; the undersides
193+
are fanned from their centres. The first still left the open leaf
194+
hanging past the paving's back edge, and the bare floor under it read
195+
as a black hole; the paving now runs on under the swing.
160196

161197
## Conventions walked
162198

@@ -171,7 +207,7 @@ Every convention in `showcase/README.md`, and whether it applies here.
171207
| A member is tenoned into its seat | yes | posts into the flags, ledges and straps into the boards, braces into the ledges, the keeper into the post, the hook into the post |
172208
| Seat conformance (a band: minimum so it cannot float) | yes | each knuckle on its hook (`--lift-gate`), exit 18 |
173209
| Mirrored assemblies | no | a gate is handed; nothing is mirrored |
174-
| Material face floors | yes | timber 330, iron 1400, ground 140 |
210+
| Material face floors | yes | timber 400, iron 1400, ground 400 |
175211
| One substance, one slot | yes | oak, forged iron, sandstone |
176212
| Shading is part of the model | yes | timber and flags faceted; knuckles, pins, domes, rod and ring smooth, every edge over 35° hard |
177213
| Edge treatment | yes | every prism chamfered; no separate budget, removing the chamfers moves the triangle band first |
@@ -194,7 +230,8 @@ were run on Blender 4.5.11, 5.1.2 and 5.2.1 and exited the declared code.
194230
| `--offset-knuckle` | knuckle on pin | moves the upper knuckle 1.5 mm along the gate; clearance −0.90 mm | 17 |
195231
| `--lift-gate` | knuckle seat | lifts everything that hangs 3 mm off the hooks; seat +2.50 mm | 18 |
196232
| `--tilt-pintle` | plumb shared axis | leans the upper pin 3.4° about the knuckle's mid-height; top 3.96 mm off its foot | 19 |
197-
| `--tight-post` | swing clearance | sets the latch post 14 mm closer; clearance 0.89 mm | 20 |
233+
| `--tight-post` | swing clearance | sets the latch post 14 mm closer; clearance −1.04 mm | 20 |
234+
| `--reversed-braces` | brace direction | mirrors both braces, lower ends at the latch side; brace 0 rises 0.741 → 0.178 m | 21 |
198235

199236
## Exit codes
200237

@@ -224,6 +261,7 @@ wrapper — a crash, never a named check.
224261
| 18 | Knuckle seat on its hook (`--lift-gate`) |
225262
| 19 | Pin plumb, shared hinge axis or real-world size (`--tilt-pintle`) |
226263
| 20 | Swing clearance at the latch post (`--tight-post`) |
264+
| 21 | A brace does not rise from the hinge side (`--reversed-braces`) |
227265
| 24 | Asset-quality floors (`examples/gallery_asset_quality.py`, render path only) |
228266

229267
## Run it
@@ -235,11 +273,14 @@ blender --background --python garden_gate.py --
235273
# Falsifier: the latch post 14 mm closer. Must exit 20.
236274
blender --background --python garden_gate.py -- --tight-post
237275

276+
# Falsifier: both braces mirrored, lower ends at the latch side. Must exit 21.
277+
blender --background --python garden_gate.py -- --reversed-braces
278+
238279
# Falsifier: the upper knuckle 1.5 mm off its pin. Must exit 17.
239280
blender --background --python garden_gate.py -- --offset-knuckle
240281

241-
# Render the gallery still (EEVEE; --engine cycles on a GPU-less host).
242-
blender --background --python garden_gate.py -- --output garden_gate.webp
282+
# Render the gallery still (Cycles, 64 samples, denoised).
283+
blender --background --python garden_gate.py -- --output garden_gate.png --engine cycles
243284
```
244285

245286
Smoke runs the check-only path. It does not pass `--output` or any falsifier.
@@ -253,11 +294,11 @@ gate is a ratio band; every hinge, swing and size value is identical.
253294

254295
| Value | 4.5.11 | 5.1.2 | 5.2.1 |
255296
| --- | --- | --- | --- |
256-
| Base triangles | 3320 | 3320 | 3320 |
257-
| LOD1 / LOD2 triangles | 1660 / 730 | 1660 / 730 | 1660 / 728 |
258-
| LOD2 ratio | 0.2199 | 0.2199 | 0.2193 |
259-
| Faces timber / iron / ground | 370 / 1534 / 156 | 370 / 1534 / 156 | 370 / 1534 / 156 |
260-
| Collider triangles | 344 | 344 | 344 |
297+
| Base triangles | 3936 | 3936 | 3936 |
298+
| LOD1 / LOD2 triangles | 1968 / 864 | 1968 / 864 | 1968 / 860 |
299+
| LOD2 ratio | 0.2195 | 0.2195 | 0.2185 |
300+
| Faces timber / iron / ground | 434 / 1534 / 464 | 434 / 1534 / 464 | 434 / 1534 / 464 |
301+
| Collider triangles | 394 | 394 | 394 |
261302
| Coaxial, clearance, seat | 0.000 / 0.600 / −0.500 mm | same | same |
262-
| Swing clearance | 14.869 mm | 14.869 mm | 14.869 mm |
263-
| Falsifier exits 9 / 15 / 16 / 17 / 18 / 19 / 20 | all as declared | all as declared | all as declared |
303+
| Swing clearance | 12.959 mm | 12.959 mm | 12.959 mm |
304+
| Falsifier exits 9 / 15 / 16 / 17 / 18 / 19 / 20 / 21 | all as declared | all as declared | all as declared |

0 commit comments

Comments
 (0)