Book Trolley

showcase/book-trolley/

A procedural library book truck — arched end panels standing in skids on four swivel casters, a flat deck, and on each side two sloped troughs, a tilted shelf and a backrest square to it, filled with forty-seven rounded-spine hardbacks spines out and two loose stacks — carried through UVs, bake, LOD, convex collider, and Unity glTF, asserting recomputed budgets rather than an API contract.

Rendered headless by the showcase piece itself. Select it to enlarge.

witnesses Recomputed: 17704 tris, seven materials with 568 wood, 2788 cloth, 1476 leather, 312 paper, 2704 gilt, 932 iron and 656 rubber faces, UVs in 0..1 with zero AABB overlap, outer AABB 0.768×0.530×1.000 m, zmin 0, hygiene 0 including zero coplanar cross-shell pairs, four wheels on the floor, ten cross members 8 mm into both end panels, four caster plates 1.0 mm into their skids, carcass and casters mirror-exact in X and Y, 52 books each with one page block 0.6 mm into its boards and two gilt bands 0.3 mm into the spine and 0.8 mm proud, every book seated 1.0–3.2 mm, four troughs each with one backrest and all 47 trough books 0.8 mm into it, thickness and height spread 2.75 and 1.64, zero unplanned book overlaps, zero right-angle wood edges, convex collider 308 tris. --off-back and --deep-back exit 21 on the backrest contact while every seat, the envelope and the overlap budget still pass; --crowd-books exits 22; --skew-caster 19; --drop-plates 18.

category Village

tags mesh export showcase

blender --background --python showcase/book-trolley/book_trolley.py --

A library book truck: two arched end panels standing in skids on four swivel casters, a flat bottom deck, and on each side two sloped troughs under a turned push rail. Each trough is a shelf tilted 14° back toward the centre and a backrest square to it, both housed in the end panels. Forty-seven hardbacks stand in the troughs spines out, leaning back into the corner; five more lie in two loose stacks on the deck. Every book is a rounded-spine cover in cloth or leather, a page block glued into it, and two gilt bands tooled round the spine. A showcase piece, not an example — it witnesses no API contract. It asserts that generated geometry meets declared asset budgets, recomputed from the finished mesh.

What it composes#

Shipped contentUsed for
skills/mesh-editing-and-bmeshchamfered boards in trough frames, n-gon-capped prisms (arched end panels, caster forks, wheels), U-section covers, all in bmesh
skills/custom-propertiesface attributes (PlankTone, GrainDir, Tint) read by the shaders
skills/procedural-materials-and-shadersgrained stain, cloth, leather, ruled page edges, gilt, caster iron, rubber
skills/bake-high-to-lowCycles tangent-space normal bake, high onto low
skills/engine-export-presetsUnity glTF (export_yup=True)
skills/depsgraph-and-evaluated-dataevaluated triangle counts for the LOD ratios
snippets/decimate_to_budget.pyLOD1 / LOD2 COLLAPSE chain
snippets/convex_hull_collider.pyone hull over the carcass and casters
snippets/lod_chain.pyLOD naming and ratio pattern
examples/mesh-hygiene-audithygiene combinatorics (copied, not imported)
showcase/bookshelfthe book builder, the seat, band and overlap audits (copied, not imported)

The budget that matters#

A book on a flat shelf stands on one support. A book in a sloped trough is carried at two: its tail on the shelf and its fore-edge against the backrest. Seated on the shelf and standing off the backrest, it would topple forward on a real trolley, and nothing else sees it:

The piece pairs each tilted shelf with the one backrest whose shell overlaps it, finds each standing book's shelf by the top plane its lowest vertex sits nearest (read off the mesh, on the book's own side of the trolley), and takes the plane of that backrest's face that looks at the book. It asserts how far the book's deepest cover vertex sits behind that plane, as a band of 0.3–2.0 mm, next to the shelf seat's own band. All forty-seven sit at 0.80 mm.

A plane, not the backrest solid, for the same reason as bookshelf's lean contact: a fore-edge driven through the 18 mm board would come out behind it and read as no contact.

--off-back and --deep-back are the falsifiers built for exactly this. One stands every trough book 3 mm off its backrest, the other drives it 4.5 mm in, both along the slope so the shelf seat is untouched. Both exit 21 while every seat, the envelope and the book-overlap budget still pass.

Budgets#

Declared in the script as named constants, recomputed from the generated mesh. Measured values are from Blender 5.2.1; see the cross-version table below.

BudgetBandMeasured
Base triangles16800–1860017704
LOD1 ratio0.32–0.620.5000
LOD2 ratio0.10–0.350.2200
Material slotsexactly 7, distinct7
Wood / cloth / leather faces≥ 510 / 2500 / 1320568 / 2788 / 1476
Paper / gilt faces≥ 280 / 2430312 / 2704
Iron / rubber faces≥ 840 / 590932 / 656
UV boundsinside 0..1(0.0003, 0.0003)–(0.9997, 0.9997)
UV AABB overlap≤ 1e-50.000000
Outer AABB0.768 × 0.530 × 1.000 m ± 0.0200.7680 × 0.5300 × 1.0000
Collider triangles≤ 360308
Normal bake{'FINISHED'} with image data{'FINISHED'}, has_data=True
glTF exportfile written, non-empty~1.30 MB
Hygieneall zeroloose 0/0, non-manifold 0, zero-area 0, doubles 0, n-gons 0, coplanar cross-shell pairs 0
Grounded AABB\zmin\≤ 1e-40.00000
Named wheels4 wheels, each zmin ≤ 1e-44 at 0.00000
Dado2 end panels; 10 cross members (deck, 4 shelves, 4 backrests, rail), each ≥ 5 mm into both panels and ≥ 6 mm clear of the far face8.00 mm in, 10.00 mm clear
Page block52 books, one block and two bands each; every block corner 0.3–1.2 mm inside its boards0.60 mm
Book seat52 books, each 0.5–3.6 mm into its shelf (along the shelf normal), the deck or the book below1.00–3.16 mm
Band seatinner face 0.1–0.8 mm inside the spine, outer face ≥ 0.4 mm proud0.29 mm in, 0.80 mm proud
Caster plates4 plates, each top 0.5–2.0 mm into the skid above1.00 mm
Mirror symmetrycarcass and casters, every vertex's X and Y mirror image on the mesh within 1e-4 m0.0000000
Size spreadthickest / thinnest ≥ 2.5; tallest / shortest ≥ 1.52.750 / 1.640
Backrest contact47 trough and 5 lying books; 4 troughs each with one backrest; every trough book 0.3–2.0 mm into its backrest0.80 mm
Book overlaps0, book against book and against the carcass, designed contacts exempt0
Edge treatmentright-angle wood edges0

Real-world size: 0.77 m long over the skids, 0.53 m deep and 1.00 m tall over the arched ends, on 70 mm casters. Each trough is 170 mm deep and its backrest 170 mm tall; the books run from a 150 mm pocket book to a 245 mm octavo.

Construction#

Findings the budgets forced#

Conventions walked#

Every convention in showcase/README.md, and whether it applies here.

ConventionAppliesHow
Deterministic, budgets declared, assertions recomputeyesno RNG; every value above is read off the mesh
Falsifier fails the budget it targetsyestable below, proven on all three binaries
Hygiene incl. cross-shell coplanaryesexit 15; stepped seats, the yaw cycle and the shelf tail keep it at 0
Named supportsyesthe four wheels (--float-caster); the plates, forks and skids stop above the floor
Joint-fit budgetsyesdado bite and far-face clearance per cross member (--short-shelves)
A member is tenoned into its seatyespanels in skids, backrests in shelves, rail blind in the panels, each caster part into the one above
A platform bears on somethingyesdeck and every shelf housed in both end panels
Carried parts bite their bearersyesbooks into shelves, the deck and the book below (--float-books); caster plates into the skids (--drop-plates)
A joint bites; touching is not joiningyespage blocks into their boards (--loose-pages); the backrest contact as a band
Bands on a curved host are built on the host's arcyesgilt bands on the spine's own chain (--float-bands)
A leaning prop rests on somethingyesevery trough book against its backrest, exit 21 (--off-back, --deep-back)
Mirrored assembliesyescarcass and casters mirror in X and Y, exit 19 (--skew-caster, 6 mm inside the 20 mm AABB tolerance)
Scattered parts do not interpenetrateyesexit 22 (--crowd-books), designed contacts exempt
Scatter varies in sizeyesthickness and height spread, exit 20 (--uniform-books)
Edge treatment: no right anglesyesexit 23 (--sharp-deck), wood only; iron chamfered 0.8 mm, rubber rounded
Aim an edge falsifier at one memberyesthe deck left square: 12 edges
Chamfer n-gon caps, then triangulateyesend panels, forks, races, axles, wheels and the rail are n-gon-capped prisms, bevelled then triangulated
Sort bmesh operator inputsyesbevel edges sorted by index, carcass, iron, rubber and covers
Identical boards read as CGyesper-board PlankTone and GrainDir; per-book Tint
Variation goes into surface, never into functionyessizes, tints, gaps and yaw vary; tier pitch, slope and seats are budgets
Shading is part of the modelyesspines, rail and wheels smooth (round); every edge over 35° hard, so boards and chamfers read crisp
One substance, one slotyeswood, cloth, leather, paper, gilt, iron, rubber
Iron is not chromeyesnear-black, roughness 0.52–0.78
Bake texels per UV cellmeasured, not a budget1024 px over a 98-cell grid, about 10 px per cell
The bake cage is narrower than the nearest neighbouryesCAGE_EXTRUSION 3 mm, and the bake source leaves the books out, since they sit inside any cage of the deck and shelves
Level on the stage; stage 60 myesturned about Z only; 60 m floor and wall
Keep a falsifier's envelope stillyesevery falsifier except --lift-z keeps the AABB within tolerance
Plumb, rope, masonry, roofs, rings, terrain, vesselsnothe piece has none of these

Falsifiers#

Each breaks one pipeline stage so a named budget fails. All fifteen were run on 4.5.11, 5.1.2 and 5.2.1 and exited the same declared code on all three.

FlagTarget budgetBreaksExit
--skip-decimateLOD1 ratiodrops the DECIMATE modifiers, LOD1 ratio goes to 1.00009
--stray-vertmesh hygieneadds one loose vertex inside the deck15
--lift-zgrounded zminlifts the whole mesh 50 mm16
--float-casternamed wheelslifts one caster 5 mm; the other three still ground the AABB16
--short-shelvesdado bitestops the four shelves 4 mm short of the ends; −4.0 mm17
--loose-pagespage-block bitebuilds every page block 0.9 mm clear of its boards; −0.9 mm17
--float-booksbook seatlifts every book 6 mm off its shelf or the deck; −5.0 mm18
--float-bandsband seatbuilds every band 1.1 mm off its spine; −1.1 mm18
--drop-platescaster plate seatdrops every caster plate 2.5 mm, clear of its skid; −1.5 mm18
--skew-castermirror symmetrymoves one caster 6 mm along the trolley; 6.0 mm19
--uniform-bookssize spreadone height and depth, thickness within ±1.5 %; 1.030 / 1.00020
--off-backbackrest contactstands every trough book 3 mm off its backrest; −3.0 mm21
--deep-backbackrest contactdrives every trough book 4.5 mm into its backrest; 4.5 mm21
--crowd-booksbook overlapscloses the front upper trough's gaps to −6 mm; 13 overlaps22
--sharp-deckedge treatmentleaves the deck unchamfered; 12 right-angle edges23

Exit codes#

File-local and sequential. 9 is a valid check code. 1 is the FATAL wrapper — a crash, never a named check.

CodeMeaning
0Success
1Uncaught exception (FATAL wrapper)
2argparse / usage
3Mesh did not build, or has no UV layer
4Base triangle count outside band
5Material slots, or a material's face floor
6UVs outside 0..1
7UV AABB overlap above tolerance
8Outer AABB off declared size
9LOD1 or LOD2 ratio outside band (--skip-decimate)
10Framing gate (examples/gallery_framing.py, render path only)
11Collider triangles above ceiling
12Normal bake failed or produced no image data
13glTF export missing or empty
14--output produced no file
15Mesh hygiene (--stray-vert)
16Grounded zmin, or a wheel floating (--lift-z, --float-caster)
17Dado or page-block bite, or a book without one block and two bands (--short-shelves, --loose-pages)
18Book, band or caster-plate seat (--float-books, --float-bands, --drop-plates)
19Carcass and casters off mirror symmetry (--skew-caster)
20Size spread below floor (--uniform-books)
21Backrest contact, trough / lying count, or a trough without one backrest (--off-back, --deep-back)
22Books overlap each other or the carcass (--crowd-books)
23Right-angle wood edges (--sharp-deck)
24Gallery asset-quality violation (render path; the floors' 11 is remapped here)

Run it#

# Budget check, no render.
blender --background --python book_trolley.py --

# Falsifier: every trough book stands off its backrest. Must exit 21.
blender --background --python book_trolley.py -- --off-back

# Falsifier: every trough book cuts into its backrest. Must exit 21.
blender --background --python book_trolley.py -- --deep-back

# Render the gallery still (EEVEE; --engine cycles on a GPU-less host).
blender --background --python book_trolley.py -- --output book-trolley.webp

Smoke runs the check-only path. It does not pass --output or any falsifier.

Cross-version measurements#

Value4.5.115.1.25.2.1
Base triangles177041770417704
LOD1 / LOD2 tris8852 / 38948852 / 38948852 / 3894
Face counts (wood / cloth / leather / paper / gilt / iron / rubber)568 / 2788 / 1476 / 312 / 2704 / 932 / 656samesame
Outer AABB0.7680 × 0.5300 × 1.0000samesame
Collider tris308308308
Seat / backrest contact / mirror1.00–3.16 mm / 0.80 mm / 0.0samesame
glTF bytes130331613033161303308

The glTF size differs by 8 bytes on 5.2 (exporter metadata, not a budget). Every other value, including the DECIMATE COLLAPSE LOD counts, is identical on all three.

Source

showcase/book-trolley/book_trolley.py View the script on GitHub →
A double-sided wooden library book trolley on four casters, its two sloped troughs of cloth and leather hardbacks leaning back spines out, with loose books stacked on the bottom deck.