Cart

showcase/cart/

A procedural two-wheel handcart through UVs, bake, LOD, 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: 5284 tris, two materials with metal and wood face floors, UVs in 0..1 with zero AABB overlap, outer AABB 1.580×0.842×0.640 m, LOD ratios in band, convex collider 164 tris, hygiene zero (loose, non-manifold, doubles, n-gons), zero coplanar cross-shell face pairs, both tyres and both prop legs grounded, two wall boards per side with 3 mm seams, tyre seat depth in band over 48 angular stations, every shell in one BVH-contact assembly, the two wheels mirrored within 5e-5 m, no unchamfered right-angle edge, 17.45 bake texels per UV cell, non-empty glTF. --flush-tyre exits 15 on the z-fight budget; --float-wheel and --short-props exit 16 on the named-support budget; --wide-seams exits 17 on the board seams; --sink-tyre exits 18 on the tyre seat band; --lift-bed exits 18 on the one-assembly budget; --skew-wheel exits 19 on the wheel mirror; --sharp-bar exits 20 on edge treatment; --low-bake exits 21 on texel density; --skip-decimate exits 9 on the LOD1 ratio budget; --lift-z exits 16 on the grounded budget.

category Village

tags mesh export showcase

blender --background --python showcase/cart/cart.py --

A showcase piece, not an example. A procedural two-wheel handcart built on two rails that run on past the bed as shafts, with a pull bar through their tips and two prop legs under them. It has a planked floor, board walls with iron corner straps, and spoked wheels on long naves with iron bands, tyres and washers. The piece then runs the shipped pipeline: unique-cell UVs, a Cycles high-to-low normal bake, an LOD chain, a convex collider, and a Unity glTF export.

The chassis is stacked from the axle up, and every member bites the one below it by a named depth: axle, bolster, rails, floor planks, walls. The cart stands level on four named supports: two tyres and two legs. Stated size is 1.58 m long, 0.84 m across the axle ends and 0.64 m tall. The wheels are 0.64 m in diameter and the bed is 0.92 × 0.50 m.

It asserts budget conformance of the generated result. It does not witness an API contract. "It rendered without error" is not a check.

Composes skills mesh-editing-and-bmesh, bake-high-to-low, depsgraph-and-evaluated-data, engine-export-presets, and snippets bake_normal_high_to_low.py, setup_bake_target_image.py, lod_chain.py / decimate_to_budget.py, convex_hull_collider.py, export_preset_unity.py (helpers copied, not imported as a package).

Budgets#

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

AxisDeclaredMeasured (4.5.11 / 5.1.2 / 5.2.1)
Base triangles5160–54105284 / 5284 / 5284
LOD1 ratio0.32–0.62 of base0.5000 / 0.5000 / 0.5000
LOD2 ratio0.10–0.35 of base0.2199 / 0.2199 / 0.2146
Materialsexactly 2 distinct, metal ≥ 800, wood ≥ 1200 faces2 slots; 1196 metal, 1694 wood
UVsin 0..1, AABB overlap ≤ 1e-5in range, overlap 0
Outer AABB(1.580, 0.842, 0.640) m ± 0.01(1.5800, 0.8420, 0.6400)
Collider tris≤ 360164
Bake texelssmallest UV cell ≥ 12 px at the baked resolution17.45 px at 1024 px
Exportwritten, size > 0, removed after measuring402904 / 402904 / 402900 bytes (4.5.11 / 5.1.2 / 5.2.1)

Hygiene, supports and joints#

Recomputed from the generated mesh on all three binaries, identical on each.

AxisDeclaredMeasured
Loose V/E, non-manifold, zero-area, doubles @1e-5, n-gonsall 0all 0
Z-fightingcoplanar cross-shell face pairs = 00
Groundedbbox min Z within 1e-4 of 00.0000
Named supports2 legs found; each tyre and leg zmin within 1e-4 of the floor2 legs; all four 0.000000
Material-island gapmetal↔wood min distance ≤ 0.008 m0.00023
Wall boards2 boards per side wall, seams 0.0015–0.005 m(2, 2), seams 0.00300
Tyre seat0.0030–0.0055 m interference, per angular station[0.00400, 0.00400] over 48 stations
One assemblythe shells' BVH-overlap graph is 1 component1 component, 59 shells
Wheel mirrorthe two wheels match in X, Z and extent within 5e-5 m0.00000 mm
Edge treatmentmanifold edges within 5° of 90° = 00 wood, 0 iron

DECIMATE COLLAPSE triangle counts are not identical across series. 5.2.1 is more aggressive on LOD2, so the gate is a ratio band, not an exact count. Bake pixels are stochastic; the gate is has_data plus operator FINISHED plus the texel floor, not byte-identity. Per-board tone comes from random.Random(TONE_SEED), so it is identical run to run. Export byte counts differ by a few bytes across series (glTF serializer). The gate is "written and non-empty", not a byte count, and the file is removed once measured.

The bake cage is 0.01 m: it only has to cover the chamfer difference between the 3-segment high and the 1-segment low. At 0.08 m it reached past the 74 mm between a side wall and its wheel, so rays from the wall hit the high-poly felloe. The wheel's rim baked onto the board as a black staircase.

Falsifiers#

Each flag breaks one stage so a named budget fails and the piece exits that code. Magnitudes are sized so no earlier gate can steal the failure. The wheel, leg and bed moves stay inside BBOX_TOL, so the AABB gate (exit 8) still passes, and no flag changes the triangle count by more than the band allows.

FlagTarget budgetExit
--skip-decimateLOD1 ratio band (ratio becomes 1.0)9
--flush-tyreCoplanar cross-shell pairs: sets the tyre's inner radius equal to the felloe's outer radius, which is the construction bug this piece was rebuilt to remove (0 → 144 pairs)15
--lift-zAABB grounded zmin (whole mesh up 0.05 m)16
--float-wheelNamed supports: lifts one wheel 3 mm while the other still grounds the AABB16
--short-propsNamed supports: stops both prop legs 3 mm above the floor while the tyres still ground the AABB16
--wide-seamsWall board seams: opens every seam to 10 mm, same triangle count17
--sink-tyreTyre seat band: buries the hoop 9 mm into the felloe so it reads as one body18
--lift-bedOne assembly: raises the box (planks, walls, straps) 7 mm off its rails, so the contact graph splits in two18
--skew-wheelWheel mirror: pushes one wheel 6 mm out along the track19
--sharp-barEdge treatment: leaves the pull bar's rims unchamfered (24 right-angle edges, 48 triangles short)20
--low-bakeBake texel density: bakes at 256 px (4.36 px per cell)21

--lift-z, --float-wheel and --short-props share exit 16 and fail different budgets. --lift-z fails the AABB gate, which fires first. The other two leave the AABB grounded, so only the per-support check can catch them. --sharp-bar replaced a flag that skipped the whole iron chamfer pass. That flag dropped 1200 triangles and tripped the triangle floor (exit 4) instead of the edge budget.

Run#

blender --background --python cart.py --
blender --background --python cart.py -- --skip-decimate
blender --background --python cart.py -- --flush-tyre
blender --background --python cart.py -- --lift-z
blender --background --python cart.py -- --float-wheel
blender --background --python cart.py -- --short-props
blender --background --python cart.py -- --wide-seams
blender --background --python cart.py -- --sink-tyre
blender --background --python cart.py -- --lift-bed
blender --background --python cart.py -- --skew-wheel
blender --background --python cart.py -- --sharp-bar
blender --background --python cart.py -- --low-bake
blender --background --python cart.py -- --output cart.png

Smoke passes none of the falsifier flags and no --output.

Exit codes#

File-local. 9 is a valid check code. 10 is reserved for gallery_framing.check_framing on the --output path.

CodeMeaning
0Success
1Uncaught exception (FATAL wrapper)
2argparse / usage
3Mesh did not build / no UV layer / wheels not found
4Base triangle count outside range
5Material count ≠ 2 distinct slots, or a face-count floor missed
6UVs outside 0..1
7UV AABB overlap above tolerance
8World AABB off declared outer size
9LOD ratio band (--skip-decimate lands here)
10Framing gate (render path only)
11Collider triangle count above ceiling
12Bake did not finish or image has no data
13Export file missing or empty
14--output produced no file
15Hygiene: loose geometry, non-manifold, zero-area, doubles, n-gons, or coplanar cross-shell face pairs (--flush-tyre lands here)
16Bbox min Z not grounded (--lift-z), or a named support off the floor (--float-wheel, --short-props)
17Material-island gap above tolerance, or wall boards miscounted or their seams out of band (--wide-seams)
18Tyre seat depth outside its band (--sink-tyre), or the shells not one connected assembly (--lift-bed)
19Wheel mirror deviation above epsilon (--skew-wheel lands here)
20A right-angle edge survived the chamfer passes (--sharp-bar lands here)
21Bake texel density below the floor (--low-bake lands here)
22Gallery asset-quality violation (render path; the floors' 11 is remapped here)

Source

showcase/cart/cart.py View the script on GitHub →
A wooden handcart with a planked box bed and iron corner straps on two spoked wheels, standing level on two prop legs with its shafts joined by a pull bar.