Skip to content

Commit f67d200

Browse files
TMHSDigitalclaude
andcommitted
fix(showcase): wheelbarrow second quality pass: one-timber shafts, hopper tray
The barrow read as a crate on legs. Each shaft was three boxes: a handle stopping at the tray's rear corner, a level run hidden exactly under the side wall, and a fork turning in a 50-degree V to the hub. The tray was a square box, a spreader stood inside the wheel touching neither fork, and the iron straps ran 12 mm above the wall tops. - Each shaft is one mitred sweep grip -> tray rear -> tray front -> axle, narrowing in plan the whole way, legs and a bearer hung from it. - The tray is a hopper between a bottom and a top outline: sides flared 15 deg, front raked 30 deg over the wheel, rear leaning 12 deg; end boards housed into the sides; straps follow the wall and stop below it. - Seams and seats are measured in each wall's own plane, taken from the boards' faces; AABB tests lie on leaning boards. New budgets: shaft runs = 2 (exit 20, --split-shafts), flare >= 10 deg and rake >= 20 deg (exit 21, --box-tray, same top outline). The handle-join budget is gone: the handle is the shaft. Outer AABB and tray size re-fitted. Tris 2536 -> 2440. Same codes on 4.5.11, 5.1.2 and 5.2.1. Asset sheet added. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
1 parent c463568 commit f67d200

8 files changed

Lines changed: 844 additions & 493 deletions

File tree

35.1 KB
Loading
-10 Bytes
Loading
-20 Bytes
Loading

‎docs/gallery/wheelbarrow/index.html‎

Lines changed: 391 additions & 235 deletions
Large diffs are not rendered by default.

‎showcase/gallery.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@
169169
"name": "wheelbarrow",
170170
"dir": "showcase/wheelbarrow",
171171
"teaches": "A procedural wooden wheelbarrow through UVs, bake, LOD, collider, and Unity glTF, asserting recomputed budgets rather than an API contract.",
172-
"alt": "A wooden wheelbarrow whose tray walls are stacked boards held by iron straps, with a spoked front wheel and two long handles.",
173-
"witnessesFix": "Recomputed: 2536 tris, two materials with 1157 wood and 190 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.556×0.630×0.572 m, zmin 0, hygiene 0, wall-floor seat 12 mm, spoke clearance 40 mm, two boards per side and front wall with 2 mm seams, LOD ratios in band (5.2 COLLAPSE leaner on LOD2), convex collider 90 tris, non-empty glTF. --skip-decimate exits 9 on LOD1; --stray-vert exits 15 on hygiene; --lift-z / --short-legs exit 16 on grounded; --fat-spokes / --float-walls / --wide-seams exit 17 on joint fit; --pipe-rim exits 18 on tread aspect.",
172+
"alt": "A wooden wheelbarrow with a flared tray of stacked boards held by iron straps, its front raked out over a spoked wheel, and two long shafts running from the handles under the tray to the axle.",
173+
"witnessesFix": "Recomputed: 2440 tris, two materials with 1085 wood and 214 metal faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.563x0.594x0.577 m, zmin 0, hygiene 0, both shafts one timber from grip to axle, tray flared 15 deg and raked 30 deg, wall-floor seat 8 mm, spoke clearance 52 mm, two boards per side and front wall with 2 mm seams measured in the wall's plane, LOD ratios in band (5.2 COLLAPSE leaner on LOD2), convex collider 80 tris, non-empty glTF. --skip-decimate exits 9 on LOD1; --stray-vert exits 15 on hygiene; --lift-z / --short-legs exit 16 on grounded; --fat-spokes / --float-walls / --wide-seams exit 17 on joint fit; --pipe-rim exits 18 on tread aspect; --split-shafts exits 20 on shaft runs; --box-tray exits 21 on tray flare.",
174174
"hero": "docs/gallery/assets/wheelbarrow-hero.webp",
175175
"preview": "showcase/wheelbarrow/preview.webp",
176176
"tags": [

‎showcase/wheelbarrow/README.md‎

Lines changed: 85 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
# Wheelbarrow
22

33
A showcase piece, not an example. Procedural wooden wheelbarrow (two
4-
chassis shafts that are the handles, box tray with overlapping floor
5-
slats and walls of stacked boards, iron straps, single flat-tread spoked wheel, rear legs) then the
6-
shipped pipeline: unique-cell UVs, Cycles high-to-low normal bake, LOD
7-
chain, convex collider, Unity glTF export.
4+
shafts that are the handles, each one timber from grip to axle; a
5+
flared hopper tray with overlapping floor slats and walls of stacked
6+
boards; iron straps; a single flat-tread spoked wheel; rear legs) then
7+
the shipped pipeline: unique-cell UVs, Cycles high-to-low normal bake,
8+
LOD chain, convex collider, Unity glTF export.
89

910
The tray walls seat into the floor rather than sitting on top of it, so
10-
a wood bevel cannot open daylight at the joint. Handles are thinner in
11-
Y than the chassis they tenon into. The tyre is a flat felloe wrap, not
12-
a torus.
11+
a wood bevel cannot open daylight at the joint. The tyre is a flat
12+
felloe wrap, not a torus.
1313

1414
It asserts **budget conformance** of the generated result. It does not
1515
witness an API contract. "It rendered without error" is not a check.
@@ -20,21 +20,25 @@ witness an API contract. "It rendered without error" is not a check.
2020
`lod_chain.py` / `decimate_to_budget.py`, `convex_hull_collider.py`,
2121
`export_preset_unity.py` (helpers copied, not imported as a package).
2222

23+
Intended size: a 1.56 m long barrow, 0.59 m across the tray top, 0.58 m
24+
to the top of the raked front board; the tray is 0.94 m long at its top
25+
edge and 0.22 m deep.
26+
2327
## Budgets
2428

2529
Declared as named constants; every gate **recomputes** from the mesh,
2630
materials, UVs, evaluated LOD, collider, or export file.
2731

2832
| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) |
2933
| --- | --- | --- |
30-
| Base triangles | 2300–2800 | 2536 / 2536 / 2536 |
34+
| Base triangles | 2300–2800 | 2440 / 2440 / 2440 |
3135
| LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 |
32-
| LOD2 ratio | 0.10–0.35 of base | 0.2192 / 0.2192 / 0.2098 |
33-
| Materials | exactly 2 distinct; ≥700 wood, ≥180 metal faces | 2 slots; 1157 / 190 |
36+
| LOD2 ratio | 0.10–0.35 of base | 0.2197 / 0.2197 / 0.2057 |
37+
| Materials | exactly 2 distinct; ≥700 wood, ≥180 metal faces | 2 slots; 1085 / 214 |
3438
| UVs | in `0..1`, AABB overlap ≤ 1e-5 | in range, overlap 0 |
35-
| Outer AABB | (1.558, 0.630, 0.574) m ± 0.015 | (1.5556, 0.6300, 0.5720), zmin 0 |
36-
| Collider tris | ≤ 220 | 90 |
37-
| Export | written, size > 0 | 193036 / 193036 / 193020 bytes |
39+
| Outer AABB | (1.563, 0.594, 0.577) m ± 0.015 | (1.5630, 0.5938, 0.5773), zmin 0 |
40+
| Collider tris | ≤ 220 | 80 |
41+
| Export | written, size > 0 | 185652 / 185652 / 185636 bytes |
3842

3943
### Hygiene
4044

@@ -50,18 +54,24 @@ Recomputed from the generated mesh, not asserted about the script.
5054
| Coplanar disjoint face pairs | 0 | 0 |
5155
| Grounded: `zmin` | within 1e-4 of 0 | 0.0000 |
5256
| Named supports: 2 shoes + tyre | each `zmin` ≤ 1e-3 | shoe_z 0.00000, tyre_z 0.00000 |
53-
| Tray size | (0.720, 0.532, 0.220) m ± 0.02 | (0.7200, 0.5320, 0.2200) |
57+
| Tray size | (0.939, 0.578, 0.225) m ± 0.02 | (0.9393, 0.5783, 0.2247) |
5458

5559
### Joint fit and seat
5660

5761
| Axis | Declared | Measured (all three) |
5862
| --- | --- | --- |
59-
| Spoke clearance (hub − spoke) | ≥ 0.010 m | 0.04000 |
60-
| Handle-tray overlap | gap ≤ 0.020 m | −0.07062 |
61-
| Wall-floor seat | ≥ 0.005 m | 0.01200 |
63+
| Spoke clearance (hub − spoke) | ≥ 0.010 m | 0.05210 |
64+
| Wall-floor seat (inner bottom edge, lowest board of each wall) | ≥ 0.005 m | 0.00800 |
6265
| Metal-wood BVH gap | ≤ 0.010 m | 0.00000 |
6366
| Tread aspect (tyre width / radial) | ≥ 2.5 | 5.111 |
64-
| **Wall boards** | 2 boards per side wall and in the front wall; every seam 0.001–0.004 m | 2 / 2 / 2; 0.00200 |
67+
| **Wall boards** | 2 boards per side wall and in the front wall; every seam 0.001–0.004 m, measured up the wall's own plane | 2 / 2 / 2; 0.00207–0.00231 |
68+
69+
### Form
70+
71+
| Axis | Declared | Measured (all three) |
72+
| --- | --- | --- |
73+
| **Shaft runs**: wood shells unbroken from behind the tray to past its front | exactly 2 | 2 |
74+
| **Tray flare / rake**, from the boards' own faces | side ≥ 10°, front ≥ 20° | 15.00° / 30.00° |
6575

6676
DECIMATE COLLAPSE triangle counts are **not** identical across series,
6777
so LOD2 ratios differ slightly. The gate is a ratio band, not an exact
@@ -72,28 +82,56 @@ sorted by edge index, so the face order is the same on every run; a
7282
Python set of edges handed to the bevel had made it vary. Export byte counts differ on 5.2.1
7383
(glTF serializer), not a gated axis.
7484

85+
### Why the frame is two timbers and the tray a hopper
86+
87+
The second pass found the barrow read as a crate on legs. The frame was
88+
three boxes per side: a handle that stopped at the tray's rear corner, a
89+
level run hidden exactly under the side wall (both at 0.255 m from the
90+
centreline), and a fork that started at the front corner and turned
91+
in a 50° V to the hub. From outside, the tray carried everything. The
92+
tray itself was a square box, and a spreader between the forks stood
93+
inside the wheel, touching neither fork. The iron straps ran 12 mm above
94+
the wall tops.
95+
96+
- **Shafts.** Each shaft is one mitred sweep through the grip, the tray's
97+
rear, its front and the axle. It narrows in plan the whole way (0.27 m
98+
at the grips, 0.19 and 0.15 m under the tray, 0.038 m at the hub), so
99+
it shows under the tray and reads as one piece of wood. The legs and a
100+
stretcher hang from it, and a bearer under the tray front, its ends
101+
buried in the shafts, replaces the spreader.
102+
- **Hopper.** The tray is built from a bottom outline and a top outline:
103+
sides flared 15°, the front raked 30° out over the wheel for tipping,
104+
the low rear leaning back 12°. Each wall is the planar band between
105+
its bottom and top edges; the end boards are housed half a board into
106+
the sides, and the sides run past the ends' outer faces.
107+
- **Measured in the wall's plane.** A leaning board's outer face sits
108+
lower than its inner one, so AABB tests lie: a Z seam reads negative
109+
and a zmin seat reads deep. Seams are measured along each wall's own
110+
up direction, and the seat on each wall's lowest board's inner face,
111+
both taken from the boards' own faces.
112+
- **Straps** follow the flared wall and stop 10 mm below its top.
113+
114+
`WALL_SEAT` went from 12 mm to 8 mm: a raked board's outer bottom edge
115+
sits `WALL_T·sin(RAKE)` below its inner one, and at 12 mm it would have
116+
broken through the underside of the 22 mm floor. The handle-join budget
117+
is gone, because the handle no longer joins anything: it is the shaft.
118+
The shaft-run budget replaces it. Base triangles went from 2536 to 2440,
119+
and the collider from 90 to 80.
120+
75121
### Walls, wood and iron
76122

77-
Each tray wall was one plain slab beside a floor of planks, and every
78-
piece was one flat tone. Side and front walls are now two boards
79-
stacked with a 2 mm seam, held by the existing straps; the low rear
80-
wall stays one board. `tray_size` and `wall_floor_seat` now take a side
81-
wall as the union of its boards. **Wall boards** asserts the count and
82-
the seam; `--wide-seams` opens the seams to 8 mm (same boards, same
83-
triangles) and exits 17.
84-
85-
The extra boards cost 324 triangles, which would have broken the
86-
2800 ceiling. They are paid for with faces nobody sees: wall bottoms
87-
buried in the floor and slat undersides no longer get a bevel (faces
88-
beveled on some edges come out n-gons and are split, at the same
89-
triangle count). Base triangles went from 2500 to 2536. Wood has a tone
90-
and grain per board and shaft; the iron is dark and rusted instead of
91-
glossy black. The temp `.glb` is removed after its size is measured.
123+
Side and front walls are two boards stacked with a 2 mm seam, held by
124+
the straps; the low rear wall stays one board. **Wall boards** asserts
125+
the count and the seam; `--wide-seams` opens the seams to 8 mm (same
126+
boards, same triangles) and exits 17. Faces nobody sees get no bevel:
127+
wall bottoms buried in the floor and slat undersides. Wood has a tone
128+
and grain per board and shaft; the iron is dark and rusted. The temp
129+
`.glb` is removed after its size is measured.
92130

93131
### Falsifiers
94132

95-
Each violates one named budget. All nine were run on 4.5.11, 5.1.2 and
96-
5.2.1 and returned the same code on each.
133+
Each violates one named budget. All eleven were run on 4.5.11, 5.1.2
134+
and 5.2.1 and returned the same code on each.
97135

98136
| Flag | Budget violated | Exit |
99137
| --- | --- | --- |
@@ -102,9 +140,15 @@ Each violates one named budget. All nine were run on 4.5.11, 5.1.2 and
102140
| `--lift-z` | bounding box `zmin` is 0 | 16 |
103141
| `--short-legs` | named shoe supports at Z=0 | 16 |
104142
| `--fat-spokes` | spoke clearance inside the hub | 17 |
105-
| `--float-walls` | wall-floor seat | 17 |
143+
| `--float-walls` | wall-floor seat (measures −0.00691 m) | 17 |
106144
| `--pipe-rim` | tread aspect (torus on a flat felloe) | 18 |
107145
| `--wide-seams` | wall boards (seam band) | 17 |
146+
| `--split-shafts` | two unbroken shaft runs (measures 0) | 20 |
147+
| `--box-tray` | tray flare / rake (measures 0° / 0°) | 21 |
148+
149+
`--box-tray` stands every wall vertical on the flared tray's top
150+
outline, so the envelope and the tray-size budget stay put and only the
151+
flare gate can fail.
108152

109153
## Run
110154

@@ -118,6 +162,8 @@ blender --background --python wheelbarrow.py -- --fat-spokes
118162
blender --background --python wheelbarrow.py -- --float-walls
119163
blender --background --python wheelbarrow.py -- --pipe-rim
120164
blender --background --python wheelbarrow.py -- --wide-seams
165+
blender --background --python wheelbarrow.py -- --split-shafts
166+
blender --background --python wheelbarrow.py -- --box-tray
121167
blender --background --python wheelbarrow.py -- --output barrow.png
122168
```
123169

@@ -148,6 +194,8 @@ hygiene and joint-fit family.
148194
| 14 | `--output` produced no file |
149195
| 15 | Mesh hygiene: loose, non-manifold, zero-area, doubles, n-gons, z-fight |
150196
| 16 | Not grounded: bounding box `zmin` off 0, or a named shoe/tyre floats |
151-
| 17 | Joint fit: spoke clearance, handle join, wall-floor seat, metal-wood gap, or wall boards and seams |
197+
| 17 | Joint fit: spoke clearance, wall-floor seat, metal-wood gap, or wall boards and seams |
152198
| 18 | Seat: tread aspect of the tyre |
153199
| 19 | Tray size off the stated real-world dimensions |
200+
| 20 | A shaft is not one timber from grip to axle (`--split-shafts`) |
201+
| 21 | Tray flare or front rake under its floor (`--box-tray`) |

‎showcase/wheelbarrow/preview.webp‎

-142 Bytes
Loading

0 commit comments

Comments
 (0)