Skip to content

feat: add soccer-ball-goldberg example#104

Merged
TMHSDigital merged 1 commit into
mainfrom
feat/example-soccer-ball-goldberg
Jul 22, 2026
Merged

feat: add soccer-ball-goldberg example#104
TMHSDigital merged 1 commit into
mainfrom
feat/example-soccer-ball-goldberg

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

Summary

Adds examples/soccer-ball-goldberg/ — a soccer ball built as a Goldberg
polyhedron
: a bmesh icosphere truncated at exactly 1/3 of every edge (12
pentagons, 20 hexagons), with faces ordered by walking the source mesh's link
topology (fan walk per vertex, loop order per triangle) — nothing hand-listed.
The recognizable object is the contract: the truncated icosahedron is an
Archimedean solid, so its topology is entirely closed-form.

Sibling, not twin, to bmesh-gear: that one witnesses parametric extrusion
ownership; this witnesses polyhedral topology invariants plus
per-face-class material binding (panels bound by face vertex count, never
enumeration order).

Contract witnessed

Truncation at 1/3 makes every new edge a/3, which puts all 60 vertices on
one sphere. The check asserts, exit non-zero on failure, tolerances printed
on success: counts 60/90/32 + Euler 2 · 12×5 + 20×6 census · uniform degree
3 · watertight · edge-length uniformity · face planarity vs an independent
Newell normal
(not Blender's polygon normal) · centroid-at-origin
circumsphere · panel binding by vertex count.

Measured check values (live runs, both binaries)

Binaries: .scratch/blender-5.1.2-windows-x64/blender.exe (reports Blender 5.1.2) and .scratch/blender-4.5.11-windows-x64/blender.exe (reports
Blender 4.5.11 LTS). Output byte-identical on both:

  • edge_len mean 0.464080, max_dev 6.471e-06 (tol 3.0e-05)
  • planarity max 1.888e-06 (tol 3.0e-05)
  • circumradius mean 1.150000, max_dev 8.956e-06 (tol 3.0e-05); centroid_off 0.000e+00
  • V=60 E=90 F=32, euler=2, census 12x5+20x6, degree 3..3, watertight

Tolerance basis: float32 mesh storage + create_icosphere trig put the
invariants at a deterministic ~9e-6 noise floor (identical on both versions);
the 3e-5 gates sit ~3x above it, while any real break is ≥1e-2.

Falsification evidence (live runs)

Probe harness breaks the built mesh, then runs the shipped check():

Probe Exit Measured
one vertex shifted +0.05 X 8 edge dev 4.726e-02 (tol 3e-05) — 5.1.2 and 4.5.11 identical
panels bound "last 12 faces black" (enumeration order) 13 24 misbound faces
panel classes inverted 13 32 misbound faces
one face deleted 3 topology (60, 90, 31)

Note: "first 12 faces black" passes by luck — construction enumerates
pentagons first. That coincidence is exactly why the check reads vertex
counts, and the README says so.

Render / visual-pass log

Hero: white leather hexagons + black pentagons, unapplied Subsurf over the
Goldberg cage (panel materials carry through Catmull-Clark), default stage
per docs/VISUAL-STYLE.md (no deviation). 2 draft iterations: draft 1
floated the ball (cage circumradius ≠ smoothed surface radius — grounded by
the depsgraph-evaluated lowest vertex instead, ~5 cm sink) and reframed;
draft 2 shipped. Pass 1 crops: no clipped highlights, contact shadow
grounded, seam in shadow only. Pass 2 falsification pair: material-inverted
variant renders white pentagons on a black ball — the named visible
difference; it fails on sight. Pass 3: card-size webp reads as a soccer ball
in under a second.

Contact sheet:
docs/gallery/contact-sheets/soccer-ball-goldberg-contact-sheet.webp
(candidate TL; armature-bend TR; damped-track-aim BL; bmesh-gear BR).
Verdicts: stage darkness match ✓ · wedge warmth subtle, within family range
(armature-bend is similarly cool) ✓ · subject fill comparable ✓ · saturation
monochrome by subject nature, designed leather finishes ✓ · thumbnail
legibility highest-contrast of the four ✓. Mean luminance 0.2377 vs set
0.2787 / 0.1722 / 0.3048 — inside the set's range. Not sortable as the odd
one out.

Pass 4 (Playwright, live local server)

Card captured in situ at desktop (1280px) and ~390px mobile widths, plus the
detail page: image fills card media at both widths, teaches/WITNESSES copy
complete (no truncation), ball recognizable at both sizes. Generated HTML
read character-by-character: initial teaches was 166 chars and the card alt
truncated at the generator's 160-char cap — trimmed, rebuilt, alt now
complete; no dotted-path truncation (assert_alts_survive_dotted_paths
passes); single-asterisk italics removed from the README so the detail page
carries no literal * artifacts.

Hazards found while authoring (in code comments + README)

  • Object.to_mesh_clear() takes no argument on current Blender —
    passing the mesh raises TypeError (both 5.1.2 and 4.5.11).
  • Center-at-circumradius floats the ball: the Subsurf surface sinks toward
    the face inradii, so grounding uses the evaluated lowest vertex.
  • The repo's documented img.save(filepath=..., quality=85) webp recipe
    silently writes PNG bytes on these builds (the two newest shipped heroes
    are PNG-magic). Hero/preview here are true RIFF WebP via
    save_render with WEBP image settings, matching the bulk of the gallery
    (verified magic bytes; max channel deviation 0.067 at panel edges, q85
    ringing only).

Integration

Example dir + README + preview webp (1200×675) · hero webp (1280×720, true
RIFF) · examples/gallery.json · .cursor-plugin/plugin.json ·
blender-smoke.yml step · README counts 36→37 + gallery row · ROADMAP pool
drained (soccer-ball) and restocked (mirror-symmetry, chess-lathe, dice-pair,
bicycle-wheel directions) · gallery regenerated (37 detail pages).

Test plan

  • Check-only, both binaries above: blender --background --python examples/soccer-ball-goldberg/soccer_ball_goldberg.py -- → exit 0
    (live-run locally on both, values above).
  • Render path: exercised locally on 5.1.2 and 4.5.11 (EEVEE stills,
    sbg_draft2*.png).
  • CI: both blender-smoke matrix jobs (4.5, 5.1) must pass on this PR head.

Live-run vs inspection-only

  • Live run: all checks (both binaries), all four falsification probes,
    both renders, webp conversion + magic-byte verification, gallery build,
    Playwright captures, contact-sheet luminance.
  • Inspection only: CI runner behavior of the new smoke step (same
    invocation shape as 23 merged siblings); GitHub Pages deploy (path-filtered,
    post-merge).

Witness the Goldberg polyhedron as a bmesh contract: a soccer ball built by
truncating a bmesh icosphere at 1/3 per edge, faces ordered by link-topology
walks. Closed-form invariants asserted with printed tolerances: 60/90/32 +
Euler 2, 12-pentagon/20-hexagon census, uniform degree 3, edge-length and
circumsphere uniformity at the float32 noise floor, face planarity against an
independent Newell normal, and panel materials bound by face vertex count
rather than enumeration order. Distinct from bmesh-gear (parametric
extrusion): this carries polyhedral invariants plus per-face-class material
binding, and the smoothed render inverts on sight if the binding does.

Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation ci labels Jul 22, 2026
@TMHSDigital
TMHSDigital merged commit 05d96d9 into main Jul 22, 2026
9 checks passed
@TMHSDigital
TMHSDigital deleted the feat/example-soccer-ball-goldberg branch July 22, 2026 18:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant