diff --git a/README.md b/README.md index 5d350cb1..e6ca9946 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Budget-conformance props. Not examples. Conventions: [`showcase/README.md`](show Grindstone: a stone wheel on a timber A-frame with an iron axle, hubs, crank, and tray on a dark studio floor Hand pump: a cast-iron village pump on a wooden plinth with a spout and handle on a dark studio floor Signpost: a timber post with two painted fingerboards, iron straps, and a pyramidal cap on a dark studio floor - Chopping block: a hooped timber stump with an embedded axe on a dark studio floor + Chopping block: a bark-sided log round with growth rings and drying checks on its sawn top, a riveted iron hoop, and a felling axe buried in the top, on a dark studio floor Wooden bucket: a coopered pail with a round rope bail through ear rings and chord-lofted iron hoops on a dark studio floor Wall torch: a dressed stone plaque with an iron sconce, wooden haft, and flame on a dark studio floor Tavern stool: a round wooden seat on turned splayed legs with stretchers and iron ferrules on a dark studio floor @@ -592,7 +592,7 @@ passthrough. -GN socket rename: a copper jo-block column on a steel plinth in a dark studio, the column switched in by Compare and tagged by Random Value, warm wedge on the back wall +GN socket rename: a brushed copper gauge column on a steel plinth in a dark studio, graduated every 0.1 m from its stored gauge_h attribute, warm wedge on the back wall diff --git a/docs/gallery/assets/chopping-block-hero.webp b/docs/gallery/assets/chopping-block-hero.webp index 7cda9bc9..a1327ed4 100644 Binary files a/docs/gallery/assets/chopping-block-hero.webp and b/docs/gallery/assets/chopping-block-hero.webp differ diff --git a/docs/gallery/assets/gn-socket-rename-hero.webp b/docs/gallery/assets/gn-socket-rename-hero.webp index c92db7eb..1969b4c7 100644 Binary files a/docs/gallery/assets/gn-socket-rename-hero.webp and b/docs/gallery/assets/gn-socket-rename-hero.webp differ diff --git a/docs/gallery/cart/index.html b/docs/gallery/cart/index.html index 9fcd5c90..3a93f29d 100644 --- a/docs/gallery/cart/index.html +++ b/docs/gallery/cart/index.html @@ -264,8 +264,8 @@

cart

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.

-

| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) | | --- | --- | --- | | Base triangles | 2760–2960 | 2856 / 2856 / 2856 | | LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 | | LOD2 ratio | 0.10–0.35 of base | 0.2200 / 0.2200 / 0.2154 | | Materials | exactly 2 distinct, metal ≥ 24, wood ≥ 800 faces | 2 slots, floors met | | UVs | in 0..1, AABB overlap ≤ 1e-5 | in range, overlap 0 | | Outer AABB | (1.539, 0.749, 0.640) m ± 0.01 | (1.5393, 0.7486, 0.6400) | | Grounded | bbox min Z within 1e-4 of 0 | 0.0000 / 0.0000 / 0.0000 | | Named supports | each tyre's own zmin within 1e-4 of the floor | +Y 0.000000, −Y 0.000000 | | Hygiene | loose V/E, non-manifold, zero-area, doubles @1e-5, n-gons: all 0 | 0 / 0 / 0 on every axis | | Z-fighting | coplanar cross-shell face pairs = 0 | 0 / 0 / 0 | | Tyre seat | 0.0030–0.0055 m interference, per angular station | [0.00400, 0.00400] over 48 stations | | Wheel mirror | the two wheels match in X, Z and extent within 5e-5 m | 0.00000 mm | | Material-island gap | metal↔wood min distance ≤ 0.008 m | 0.00000 / 0.00000 / 0.00000 | | Collider tris | ≤ 360 | 122 | | Export | written, size > 0 | 201048 / 201048 / 201032 bytes |

-

DECIMATE COLLAPSE triangle counts are not identical across series — 5.2.1 is more aggressive on LOD2. The gate is a ratio band, not an exact count. Bake pixels are stochastic; the gate is has_data plus operator FINISHED, not byte-identity. Construction uses no RNG. Export byte counts differ by 8 B on 5.2.1 (glTF serializer), not a gated axis.

+

| Axis | Declared | Measured (4.5.11 / 5.1.2 / 5.2.1) | | --- | --- | --- | | Base triangles | 2760–2960 | 2856 / 2856 / 2856 | | LOD1 ratio | 0.32–0.62 of base | 0.5000 / 0.5000 / 0.5000 | | LOD2 ratio | 0.10–0.35 of base | 0.2199 / 0.2199 / 0.2157 | | Materials | exactly 2 distinct, metal ≥ 24, wood ≥ 800 faces | 2 slots, floors met | | UVs | in 0..1, AABB overlap ≤ 1e-5 | in range, overlap 0 | | Outer AABB | (1.539, 0.749, 0.640) m ± 0.01 | (1.5393, 0.7486, 0.6400) | | Grounded | bbox min Z within 1e-4 of 0 | 0.0000 / 0.0000 / 0.0000 | | Named supports | each tyre's own zmin within 1e-4 of the floor | +Y 0.000000, −Y 0.000000 | | Hygiene | loose V/E, non-manifold, zero-area, doubles @1e-5, n-gons: all 0 | 0 / 0 / 0 on every axis | | Z-fighting | coplanar cross-shell face pairs = 0 | 0 / 0 / 0 | | Tyre seat | 0.0030–0.0055 m interference, per angular station | [0.00400, 0.00400] over 48 stations | | Wheel mirror | the two wheels match in X, Z and extent within 5e-5 m | 0.00000 mm | | Material-island gap | metal↔wood min distance ≤ 0.008 m | 0.00000 / 0.00000 / 0.00000 | | Collider tris | ≤ 360 | 154 | | Export | written, size > 0, removed after measuring | 221960 bytes on 5.2.1 |

+

DECIMATE COLLAPSE triangle counts are not identical across series — 5.2.1 is more aggressive on LOD2. The gate is a ratio band, not an exact count. Bake pixels are stochastic; the gate is has_data plus operator FINISHED, not byte-identity. Construction uses no RNG. 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.

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 two wheel moves stay inside BBOX_TOL, so the AABB gate (exit 8) still passes.

| Flag | Target budget | Exit | | --- | --- | --- | | --skip-decimate | LOD1 ratio band (ratio becomes 1.0) | 9 | | --lift-z | AABB grounded zmin (whole mesh up 0.05 m) | 16 | | --flush-tyre | Coplanar 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 → 48 pairs) | 15 | | --sink-tyre | Tyre seat band — buries the hoop 9 mm into the felloe so it reads as one body | 18 | | --float-wheel | Named supports — lifts one wheel 3 mm while the other still grounds the AABB | 16 | | --skew-wheel | Wheel mirror — pushes one wheel 6 mm out along the track | 19 |

@@ -299,9 +299,13 @@

Source

export. Budgets are declared below and recomputed from the generated result. -They are not API-contract witnesses. ``--skip-decimate`` skips the LOD -DECIMATE stage so the LOD-ratio budget fails. ``--lift-z`` raises the -mesh so the grounded-zmin hygiene budget fails. +They are not API-contract witnesses. Each falsifier flag breaks one +stage so a named budget fails and the piece exits that budget's code: +``--skip-decimate`` (LOD ratio, 9), ``--lift-z`` (AABB grounded, 16), +``--float-wheel`` (named supports, 16), ``--flush-tyre`` (coplanar +cross-shell pairs, 15), ``--sink-tyre`` (tyre seat band, 18), +``--skew-wheel`` (wheel mirror, 19). The two wheel moves stay inside +``BBOX_TOL`` so the AABB gate cannot steal the failure. No RNG. Construction is closed-form. DECIMATE COLLAPSE triangle counts are not byte-identical across Blender versions — the LOD gate is a @@ -309,7 +313,7 @@

Source

blender --background --python cart.py -- blender --background --python cart.py -- --skip-decimate - blender --background --python cart.py -- --lift-z + blender --background --python cart.py -- --flush-tyre blender --background --python cart.py -- --output cart.png """ import argparse @@ -1295,6 +1299,15 @@

Source

os.remove(export_path) export_unity(export_path, [low, collider]) export_size = os.path.getsize(export_path) if os.path.isfile(export_path) else 0 + # Blender sets TMPDIR from its own preference, which resolves to the + # working directory on a stock portable build — so gettempdir() is the + # repo root under CI and every run left a .glb behind. The budget only + # needs the byte count, so drop the file once it is measured. + if os.path.isfile(export_path): + try: + os.remove(export_path) + except OSError: + pass print(f"blender={tuple(bpy.app.version)} skip_decimate={skip_decimate}") print( diff --git a/docs/gallery/chopping-block/index.html b/docs/gallery/chopping-block/index.html index 38154266..ed708a66 100644 --- a/docs/gallery/chopping-block/index.html +++ b/docs/gallery/chopping-block/index.html @@ -4,18 +4,18 @@ chopping-block — Showcase — Blender Developer Tools - + - + - +