Skip to content

fix(examples): redesign shape-key-blend as a ceramic vase morphing jar to trumpet - #275

Merged
TMHSDigital merged 1 commit into
mainfrom
fix/hero-shape-key-blend
Sep 26, 2026
Merged

TMHSDigital merged 1 commit into
mainfrom
fix/hero-shape-key-blend

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

What changed and why

The gallery review judged the shape-key-blend hero weak: three bare purple boxes of increasing height with a thin wire cage. It was programmer art, and the only thing that changed between the copies was their height.

The subject is now a lathe-turned ceramic vase. It has four materials: a cobalt glaze with noise mottling, a raised ochre band, a bisque foot and a cream interior. Its relative Tall key does three things:

  • lifts the rim, which stretches the neck
  • flares the lip into a trumpet
  • slims the belly

The hero shows the same vase at Tall.value 0 / 0.5 / 1, left to right: squat jar, amphora, trumpet vase. The middle vase is the checked object. The ochre band is part of the lathe profile, so it moves with the key: it sits thin on the jar's shoulder and ends up taller and higher on the full key. Around the full-key vase, three thin pale rings are read straight from the Basis key block. They trace the jar's belly that the blend started from. If the blend broke, the render would show three identical jars. There are no text labels.

Check (contract kept, codes 3–9 unchanged in meaning)

  • 3 there are no shape keys; 4 the key names are not [Basis, Tall]; 5 Tall.value is not 0.5 (--zero-blend)
  • 6 the undeformed mesh.vertices are not at Basis. This check is now stronger: it compares every vertex against the Basis key block, and also the Basis rim ring (z = 1.0, r = 0.335).
  • 7 an evaluated vertex is off basis + value × (key − basis)
  • 8 the evaluated Z span is not [0, 1.0 + 0.5 × 1.5]. The foot stays on the floor and the rim is lifted.
  • 9 the rim-ring radius is not 0.335 + 0.5 × 0.38 (the flare). This replaces the old top-face half-extent check.
  • The key is now authored with bulk key_blocks["Tall"].data.foreach_get/foreach_set("co"), and the check reads with foreach_get. The mesh has 7426 verts.
  • The render path now runs gallery_framing (exit 10) and gallery_asset_quality (exit 11). "No file" moved from 10 to 12, and the README exit table is updated to match.
  • Found and fixed along the way: calling Mesh.materials.clear() before appending slots drops the per-face material_index attribute. Every face then rendered as slot 0. The render path no longer calls clear(), and a comment in the code explains why.

Gate numbers (5.2.1)

  • Framing: fill x=0.844, y=0.750 (band 0.70–0.90). Margins: left 0.103, right 0.053, bottom 0.178, top 0.072. Nothing touches or crosses an edge. The hero is the three vases; the elements are the vases plus the ghost rings.
  • Asset quality: default names none; materials 4; edge90 0.004 (64/15168); compactness 17.0 (informational); aq_ok.
  • Hero drift (measure_hero_drift.py --only shape-key-blend): mean_abs 0.00333, luma 0.2181/0.2178 → matches.
  • Hero webp is 29 940 B; preview webp is 27 540 B.

Contact sheet

docs/gallery/contact-sheets/shape-key-blend-contact-sheet.webp

tile luma stage warmth sat
shape-key-blend 0.2181 0.1838 +0.0967 0.1844
armature-bend 0.2787 0.2132 −0.4279 0.1436
damped-track-aim 0.1511 0.1448 +0.2772 0.2305
bmesh-gear 0.2358 0.1772 +0.3027 0.2495
  • Stage darkness: pass. 0.184 falls between damped-track-aim (0.145) and armature-bend (0.213).
  • Wedge warmth: pass, but weaker. +0.10 is warm, but below damped-track-aim and bmesh-gear (about +0.28–0.30) and above armature-bend.
  • Subject fill: pass. 0.84 in x.
  • Saturation: pass. 0.18 falls between the calibration images (0.14–0.25).
  • Thumbnail legibility: pass. At 427×240 the jar → amphora → trumpet progression and the traveling ochre band read at a glance.
  • Mean luminance: 0.218, against a calibration range of 0.151–0.279.

Asset sheet

docs/gallery/asset-sheets/shape-key-blend.webp. It was built with scripts/asset_sheet.py, and I added a SELECT row for ^Vase$, the checked vase alone. The references come from CLAUDE.md: collision-hull-proxy, socket-attach-points, vertex-color-ao, wheelbarrow, apothecary-shelf.

Verdict: borderline pass. The vase is a single lathe object. Its silhouette is simpler than the drone, well, barrow and shelf, and roughly on par with the hydrant. Its finish (reactive glaze, raised band, bisque foot, glazed interior) keeps it from reading as placeholder. A reviewer could reasonably rank it lowest in the lineup on part count, but not on surface design. This is a technique example rather than a game-asset example, so the sheet is supplied as evidence rather than as a hard ship gate.

Check runs (check-only README command, --factory-startup)

binary (reported version) check --zero-blend --output render + gates
E:\Blender-Developer-Tools\.scratch\blender-5.2.1-windows-x64\blender.exe (Blender 5.2.1 LTS) exit 0 exit 5 exit 0, framing_ok, aq_ok
E:\Blender-Developer-Tools\.scratch\blender-5.1.2-windows-x64\blender.exe (Blender 5.1.2) exit 0 exit 5 exit 0, framing_ok, aq_ok
E:\Blender-Developer-Tools\.scratch\blender-4.5.11-windows-x64\blender.exe (Blender 4.5.11 LTS) exit 0 exit 5 exit 0, framing_ok, aq_ok

All three print keys=['Basis', 'Tall'] value=0.5 verts=7426 eval_z=0.000..1.750 rim_r=0.525 undeformed_rim=1.000/0.335.

Falsifiers (5.2.1, scratch probe wrapper that imports the module and breaks one thing)

probe exit measured error
shape_key_clear() 3 no shape keys on mesh
rename Tall → Taller 4 key names ['Basis', 'Taller']
--zero-blend 5 Tall.value 0.0 != 0.5
write the Tall coords into mesh.vertices (the trap) 6 off by 1.54738, rim z=2.5000 r=0.7150
Tall.relative_key = Tall 7 vert 385 evaluated x 0.32369 vs blend 0.32346
uniform ×1.3 key instead of lift+flare 8 eval z [0, 1.15] != [0, 1.75]
lift-only key (no flare) 9 rim radius 0.3350 != 0.5250

Proven by live run vs established by inspection

Proven by live run:

  • the check, --zero-blend and render+gates on 5.2.1, 5.1.2 and 4.5.11
  • all seven falsifiers on 5.2.1
  • render_hero.py, contact_sheet.py, asset_sheet.py and measure_hero_drift.py on 5.2.1
  • build_gallery.py after rebasing on main. I read the regenerated <img alt> and the witnesses callout in docs/gallery/index.html and docs/gallery/shape-key-blend/index.html.

Established by inspection only:

  • the falsifiers on 5.1.2 and 4.5.11 (same data-API code path)
  • CI smoke on the floating 4.5.x and 5.2.x point releases

🤖 Generated with Claude Code

…r to trumpet

The committed hero was three bare purple boxes with a thin wire cage:
programmer art whose only difference between copies was height. The
subject is now a lathe-turned ceramic vase (cobalt glaze, ochre band,
bisque foot, cream interior) whose relative Tall key lifts the rim,
flares the lip and slims the belly, shown at values 0, 0.5 (the checked
object) and 1. The ochre band rides the key, and three thin rings read
from the Basis key block trace the jar's belly around the full key.

The check keeps its contract and codes 3-9: every raw vertex must equal
Basis, every evaluated vertex must match basis + value * (key - basis),
the foot stays at z=0, and the rim ring is lifted and flared in closed
form. The render path now runs the shared framing (10) and asset-quality
(11) gates; no-file moves to 12.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Signed-off-by: TMHSDigital <[email protected]>
@github-actions github-actions Bot added examples Runnable smoke-gated examples under examples/ documentation Improvements or additions to documentation labels Sep 26, 2026
@TMHSDigital
TMHSDigital merged commit dda157b into main Sep 26, 2026
11 checks passed
@TMHSDigital
TMHSDigital deleted the fix/hero-shape-key-blend branch September 26, 2026 23:06
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 examples Runnable smoke-gated examples under examples/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant