Skip to content

Commit 05d96d9

Browse files
authored
feat: add soccer-ball-goldberg example (#104)
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>
1 parent cf8e76f commit 05d96d9

13 files changed

Lines changed: 1222 additions & 3 deletions

File tree

‎.cursor-plugin/plugin.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
"examples/shader-node-group",
8686
"examples/shape-key-blend",
8787
"examples/sky-texture-sun-elevation",
88+
"examples/soccer-ball-goldberg",
8889
"examples/swatch-grid",
8990
"examples/temp-override-join",
9091
"examples/text-version-stamp",

‎.github/workflows/blender-smoke.yml‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,3 +516,16 @@ jobs:
516516
# on failure.
517517
xvfb-run -a "$BLENDER" --background \
518518
--python examples/prop-origin-transform/prop_origin_transform.py --
519+
520+
- name: Shipped example - soccer ball Goldberg (polyhedron invariants + panel binding)
521+
run: |
522+
set -euo pipefail
523+
# Check only (no render): a bmesh icosphere truncated at 1/3 per edge
524+
# into the Goldberg polyhedron; asserts closed-form counts (60/90/32,
525+
# Euler 2), 12-pentagon/20-hexagon census, uniform degree 3,
526+
# watertightness, edge-length uniformity, face planarity vs an
527+
# independent Newell normal, centroid-at-origin circumsphere, and
528+
# panel materials bound by face vertex count. Exits non-zero on
529+
# failure.
530+
xvfb-run -a "$BLENDER" --background \
531+
--python examples/soccer-ball-goldberg/soccer_ball_goldberg.py --

‎README.md‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
</p>
1919

2020
<p align="center">
21-
<strong>12 skills</strong> &nbsp;&bull;&nbsp; <strong>6 rules</strong> &nbsp;&bull;&nbsp; <strong>2 templates</strong> &nbsp;&bull;&nbsp; <strong>17 snippets</strong> &nbsp;&bull;&nbsp; <strong>36 examples</strong>
21+
<strong>12 skills</strong> &nbsp;&bull;&nbsp; <strong>6 rules</strong> &nbsp;&bull;&nbsp; <strong>2 templates</strong> &nbsp;&bull;&nbsp; <strong>17 snippets</strong> &nbsp;&bull;&nbsp; <strong>37 examples</strong>
2222
</p>
2323

2424
<p align="center">
@@ -36,7 +36,7 @@
3636

3737
## Overview
3838

39-
This repository ships **12 skills, 6 rules, 2 templates, 17 snippets, and 36 runnable examples** for Blender Python development targeting Blender 5.1 (current stable) with Blender 4.5 LTS fallback support.
39+
This repository ships **12 skills, 6 rules, 2 templates, 17 snippets, and 37 runnable examples** for Blender Python development targeting Blender 5.1 (current stable) with Blender 4.5 LTS fallback support.
4040

4141
The content is consumed by AI coding agents (Cursor, Claude Code, any MCP-capable client) when working on Blender add-ons, geometry nodes scripts, batch pipelines, or animation tooling. There is no build step. Edit the markdown and Python files directly.
4242

@@ -700,6 +700,26 @@ Extends [`parent-inverse-orrery`](examples/parent-inverse-orrery/) without
700700
retreading orbits. Dual-panel still: TRAP (bare parent — empty socket +
701701
teleported flange) vs MPI KEEP.
702702

703+
</td>
704+
</tr>
705+
<tr>
706+
<td width="46%" valign="middle">
707+
<a href="examples/soccer-ball-goldberg/"><img src="examples/soccer-ball-goldberg/preview.webp" alt="Soccer ball Goldberg: a white soccer ball with black pentagon panels on a dark studio floor — a bmesh icosphere truncated at one-third per edge into the Goldberg polyhedron, proving closed-form counts, uniform degree, equal edges, planar faces, one circumsphere, and panels bound by face vertex count" /></a>
708+
</td>
709+
<td valign="middle">
710+
711+
### [soccer-ball-goldberg](examples/soccer-ball-goldberg/)
712+
713+
The truncated icosahedron as a bmesh contract: every icosphere edge cut at
714+
exactly `1/3`, faces ordered by link-topology walks (nothing hand-listed),
715+
and every invariant asserted as a closed form — `60/90/32`, Euler 2, uniform
716+
degree 3, edge lengths within 3e-5, planar faces against an independent
717+
Newell normal, one circumsphere, and the black pentagons / white hexagons
718+
bound by face vertex count, never enumeration order. Sibling to
719+
[`bmesh-gear`](examples/bmesh-gear/) (parametric extrusion): this one
720+
witnesses polyhedral invariants plus per-face-class material binding. The
721+
smoothed render inverts on sight if the panel binding does.
722+
703723
</td>
704724
</tr>
705725
</table>

‎ROADMAP.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
120120
- Volumetric scatter optical-depth witness: Volume Scatter density → Beer–Lambert transmittance along a known path (Cycles; Stage deviation)
121121
- Freestyle SVG / line-set witness: Freestyle line set on a silhouette (full render pass; prefer Line Art first)
122122
- ~~prop-origin-transform witness~~ **SHIPPED** as `examples/prop-origin-transform/` — origin to base center + data-API scale apply + `matrix_parent_inverse` for a bolted accessory; scale `(1,1,1)`, local `min.z==0`, world AABB delta 0, bare jump ~0.43 m, MPI err ~3e-8; stale `matrix_world` until `view_layer.update()`; byte-identical on 4.5.11 and 5.1.2
123+
- ~~Goldberg polyhedron topology witness~~ **SHIPPED** as `examples/soccer-ball-goldberg/` — soccer ball as a truncated icosahedron: bmesh icosphere cut at 1/3 per edge, faces ordered by link-topology walks; closed forms 60/90/32 + Euler 2, census 12×5+20×6, uniform degree 3, edge dev 6.5e-06, planarity 1.9e-06 (independent Newell normal), circumsphere dev 9.0e-06, panels bound by face vertex count (enumeration-order probes exit 13); float32 noise floor ~9e-6 → 3e-5 gates; byte-identical on 4.5.11 and 5.1.2
124+
- Mirror-modifier symmetry witness: half-model completed by Mirror evaluated through the depsgraph — evaluated-vs-original counts (2n − welded centerline), exact ±X partner for every evaluated vertex, merge-threshold weld proof, failure dramatically visible (half a subject / split seam). Strongest subject: a generic vehicle body
125+
- Chess-piece lathe witness: a turned piece (rook/pawn) via Screw modifier or bmesh spin from an authored profile — evaluated verts == profile × steps (minus pole merges), ring radii match the profile closed form, axis of revolution exact
126+
- Dice-pair per-face witness: material/attribute assignment driven by face normal direction, opposite-faces-sum-to-7 as an independently computed invariant, pip placement from a closed-form lattice
127+
- Bicycle-wheel radial witness: spokes via radial Array with object offset — exact angular spacing, spoke count, hub/rim concentricity, every evaluated spoke endpoint on its computed rim coordinate
123128
- ~~mesh-hygiene-audit witness~~ **SHIPPED** as `examples/mesh-hygiene-audit/` — engine-ingest topology checklist on a stepped street electrical pedestal: no ngons, no loose verts, manifold edges (exactly 2 faces), no zero-area faces (`min_area` printed), positive signed volume, Euler `V−E+F==2` (24/44/22, volume 0.989248); byte-identical on 4.5.11 and 5.1.2; dual-panel dirty vs clean still
124129
- UV atlas pack witness — lightmap/unique UV island packing with non-overlap + utilization closed forms (deferred behind hygiene/origin; overlaps `uv-layer-grid` / `triangulate-tangents` / `gltf-export-roundtrip` UV arc)
125130
- Attribute domain witness: writing a POINT-domain color attribute and reading it as if it were CORNER (or vice versa) silently shears colors across shared verts — companion to `color-attribute-wheel`
9.51 KB
Loading
41 KB
Loading

‎docs/gallery/index.html‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,17 @@ <h2><a href="prop-origin-transform/">prop-origin-transform</a></h2>
609609
<a class="card-link" href="prop-origin-transform/">View example <span aria-hidden="true">&rarr;</span></a>
610610
</div>
611611
</article>
612+
<article class="card" data-tags="bmesh mesh">
613+
<a class="card-media" href="soccer-ball-goldberg/" aria-label="soccer-ball-goldberg example detail page">
614+
<img src="assets/soccer-ball-goldberg-hero.webp" alt="soccer-ball-goldberg — A soccer ball as a Goldberg polyhedron: a bmesh icosphere truncated at 1/3 per edge, faces ordered by link-topology walks, panels bound by face vertex count." loading="lazy" decoding="async" />
615+
</a>
616+
<div class="card-body">
617+
<h2><a href="soccer-ball-goldberg/">soccer-ball-goldberg</a></h2>
618+
<p class="teaches">A soccer ball as a Goldberg polyhedron: a bmesh icosphere truncated at 1/3 per edge, faces ordered by link-topology walks, panels bound by face vertex count.</p>
619+
<p class="witnesses"><span class="tag">witnesses</span> Goldberg invariants are closed forms — counts, degree 3, uniform edges, planar faces, one circumsphere — and panels bind by vertex count, never enumeration order.</p>
620+
<a class="card-link" href="soccer-ball-goldberg/">View example <span aria-hidden="true">&rarr;</span></a>
621+
</div>
622+
</article>
612623
</div>
613624
</main>
614625
<footer>

‎docs/gallery/prop-origin-transform/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ <h1>prop-origin-transform</h1>
190190
<ul><li><strong>Stale <code>matrix_world</code>.</strong> After a location edit, <code>matrix_world</code> is unchanged until <code>view_layer.update()</code> (same half of the orrery contract).</li><li><strong>Scale apply via data API.</strong> Non-uniform scale baked into verts; <code>obj.scale == (1,1,1)</code> exactly afterward.</li><li><strong>Origin at base center.</strong> Local bbox <code>min.z == 0</code>, XY centered; world AABB delta across the bake is <strong>0</strong> (gate <code>1e-5</code>).</li><li><strong>Bare-parent trap.</strong> Parenting the accessory without MPI jumps it (~0.43 m measured); setting <code>matrix_parent_inverse</code> restores world location (err ~3e-8).</li></ul>
191191
<p><strong>What each check catches on failure:</strong> skipping scale apply leaves non-identity scale; skipping origin bake leaves <code>min.z ≈ -0.756</code>; skipping MPI leaves the accessory teleported.</p>
192192
<p><strong>Version witness:</strong> byte-identical numbers on Blender 4.5.11 LTS and 5.1.2.</p>
193-
<p>The render is a dual panel: left <strong>TRAP</strong> (bare parent — accessory teleports, hazard material) vs right <strong>MPI KEEP</strong> (accessory stays put), with emissive origin markers at each pedestal&#x27;s base.</p>
193+
<p>The render is a dual panel: left <strong>TRAP</strong> (bare parent — flanged conduit teleports off an empty mount socket, hazard material) vs right <strong>MPI KEEP</strong> (flange seated in the socket), with emissive origin markers at each pedestal&#x27;s base. Check closed forms are unchanged; the flange/socket are render form only.</p>
194194
<h2>Run</h2>
195195
<pre><code>blender --background --python prop_origin_transform.py --
196196
blender --background --python prop_origin_transform.py -- --output origin.png

0 commit comments

Comments
 (0)