Skip to content

feat(showcase): add butter-churn - #256

Merged
TMHSDigital merged 1 commit into
mainfrom
feat/showcase-butter-churn
Sep 25, 2026
Merged

TMHSDigital merged 1 commit into
mainfrom
feat/showcase-butter-churn

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

Adds showcase/butter-churn: a plunge churn with a maple cross dasher whose handle rises through the lid. The body is sixteen tapered oak staves that narrow toward the top, bound by three iron hoops. It has a three-board bottom set in a croze and a two-board lid with a hole for the handle.

Selection: the first entry in the pool was the ox-cart tongue I added as a restock in #255. I moved it behind the bookshelf rather than building it now:

  • it is a hitch pair, meaningful only beside the yoke;
  • a bare tongue or plough cannot stand on its own;
  • as a restock it should never have been placed ahead of the older candidates.

The churn is the next unclaimed standalone prop. There were no open PRs, and the only feat/showcase-* ref is already-merged work.

Binaries (all local, .scratch/):

  • blender-4.5.11-windows-x64 reports Blender 4.5.11 LTS
  • blender-5.1.2-windows-x64 reports Blender 5.1.2
  • blender-5.2.1-windows-x64 reports Blender 5.2.1 LTS

The budget that matters: plunge stroke (exit 20)

The body narrows toward the top, so a plunger that clears the staves at rest can jam partway up. It still sits inside the body without touching it, the handle still clears the lid and the envelope does not move.

The piece reads the inner wall off the staves ring by ring and the plunger's reach off the slats. It then finds how far the plunger can rise before it comes within 10 mm of the wall, or reaches the lid, and asserts a 400 mm floor.

reach stroke
default 100.6 mm 513.8 mm
--wide-dasher 125 mm slats 140.4 mm → exit 20

Under --wide-dasher the plunger still clears the staves at rest, and every other budget passes. live-run-proven

Falsifiers: exit codes per binary (live-run-proven)

default --skip-decimate --stray-vert --lift-z --short-stave --one-piece-bottom --short-handle --float-hoops --float-lid --tight-hole --wide-dasher --output
4.5.11 0 9 15 16 16 17 17 18 18 18 20 —
5.1.2 0 9 15 16 16 17 17 18 18 18 20 —
5.2.1 0 9 15 16 16 17 17 18 18 18 20 0
Flag Target budget Measured Exit
--skip-decimate LOD1 ratio 1.0000 9
--stray-vert hygiene loose_v 1 15
--lift-z grounded zmin 0.050 16
--short-stave named staves one foot 6 mm up 16
--one-piece-bottom bottom boards 1 of 3 17
--short-handle handle bite −5.0 mm 17
--float-hoops hoop seat −3.5 mm 18
--float-lid lid seat −3.6 to −3.0 mm 18
--tight-hole handle clearance −2.0 mm 18
--wide-dasher plunge stroke 140.4 mm (floor 400) 20

Envelope: every falsifier leaves the AABB unchanged. live-run-proven

Checks run locally

  • tests/check_falsifier_targets.py: the static check passes. --run <BLENDER> --only butter-churn passes all 10 falsifiers on each of the three binaries. live-run-proven

  • tests/smoke/run_example.py --forbid-skip: [PASS] butter-churn on 4.5.11, 5.1.2 and 5.2.1. live-run-proven

  • Other local checks:

    • check_exit_code_readme, check_import_export_rules, check_engine_id, check_gallery_images, test_harness
    • the inline validate-manifest, validate-counts and referenced-paths steps, plus the gallery-drift logic, all in a clean worktree (34 showcase pieces, no drift)

    All pass. live-run-proven

  • Determinism: every budget value is byte-identical across the three binaries. The only difference is the glTF byte count: 239796 on 5.2.1 against 239804 on the others, which is exporter metadata. There is no RNG. Check-only wall-clock is about 1.8 s. live-run-proven

  • Remote-only checks: the ecosystem drift check and the 4.5 / 5.1 / 5.2 smoke jobs are CI-proven on this PR.

Fix cycles (live-run-proven unless marked)

  • 240 coplanar cross-shell pairs. Neighbouring stave feet and tops, the two lid boards, and the bottom boards (faces and a rim chord the seams split) each shared a plane. The fixes:

    • stave ends are canted inward, doubled on alternate staves (at one cant, neighbours 5.6° apart still matched: 32 pairs remained);
    • one lid board stands 0.6 mm proud;
    • the middle bottom board steps up and in by 0.6 mm.

    The count is now 0.

  • Collider steal. --float-hoops first exited 11 (collider 242 against 240) instead of 18. The hoops add nothing to collide with, so they came out of the body hull and the ceiling was not raised. The collider is now 178 triangles, and the falsifier exits 18.

  • Framing (inspection-only for the look, measured by the gate). The first render filled 0.944 tall, over the gate's 0.90 cap, and exited 10. The camera was pulled back 12%, and the fill is now 0.839.

Visual gates

Contact sheet: docs/gallery/contact-sheets/butter-churn-contact-sheet.webp

criterion butter-churn calibration verdict
mean luminance 0.2327 0.151–0.302 in band
stage darkness 0.2031 0.145–0.236 in band
wedge warmth +0.149 −0.43 … +0.37 warm pool on the floor behind the churn
saturation 0.2001 0.144–0.231 in band
subject fill 0.839 tall 0.70–0.90 passes the framing gate, min margin 0.072
thumbnail legibility — — a hooped staved churn with a handle reads at tile size

Asset sheet: docs/gallery/asset-sheets/butter-churn.webp, beside the four re-rendered reference panels. Verdict: passes.

  • Alone under neutral light, it shows per-stave tone, dark iron hoops, a lid overhanging the rim and a turned handle.
  • It sits at the level of the rocket and arm, and is not the least-designed object.

inspection-only

Close-ups (lit and clay: lid, hoop, foot, underside, side, handle, rim):

  • the lid step and the hole's clearance are visible;
  • three bottom boards show from below;
  • the hoops sit on the staves with no speckle;
  • one soft dithered contact shadow shows under a hoop edge at 800 px, which is EEVEE shadow sampling, not geometry.

inspection-only

The hero was rendered on 5.2.1 through scripts/render_hero.py, and build_gallery.py was run last. I read the generated <img alt> and the witnesses callout in docs/gallery/index.html and docs/gallery/butter-churn/index.html. inspection-only

needs-5.1 is applied because the piece runs a normal bake.

🤖 Generated with Claude Code

The butter churn was the first unclaimed standalone showcase candidate.
What an envelope check cannot see on a churn is whether the dasher can
plunge: the body narrows toward the top, so a plunger that clears the
staves at rest can jam a hand's width up the stroke while it still sits
inside the body untouched. The piece reads the inner wall off the
staves and the plunger's reach off the dasher and asserts a 400 mm
stroke floor; --wide-dasher exits 20 at 140 mm while every other budget
and the envelope still pass.

Also asserts every stave on the floor, a three-board bottom, the handle
biting the slats, hoops seated vertex-for-vertex on the staves, the lid
on the stave tops and the handle clearing its hole, each with a
falsifier proven on 4.5.11, 5.1.2 and 5.2.1. The ox-cart tongue entry
moves behind the bookshelf: it was a restock placed ahead of older
candidates, and it needs the yoke as its hitch partner.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
@TMHSDigital TMHSDigital added the needs-5.1 Opt-in Blender 5.1 smoke on this PR. Default matrix stays 4.5 + 5.2. Auto-label will not apply this. label Sep 25, 2026
@github-actions github-actions Bot added showcase Budget-conformance props under showcase/ documentation Improvements or additions to documentation labels Sep 25, 2026
@TMHSDigital
TMHSDigital merged commit a15d36a into main Sep 25, 2026
14 checks passed
@TMHSDigital
TMHSDigital deleted the feat/showcase-butter-churn branch September 25, 2026 23:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation needs-5.1 Opt-in Blender 5.1 smoke on this PR. Default matrix stays 4.5 + 5.2. Auto-label will not apply this. showcase Budget-conformance props under showcase/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant