Skip to content

Commit 916160d

Browse files
authored
feat: add modular-kit-snap example (#115)
* docs: reconcile ROADMAP candidate pool against shipped examples Two drift cases found by diffing the pool against examples/gallery.json: - Removed the 'Gallery coverage follow-ups from the GPv3 review' line: every example it names (grease-pencil-rosette, armature-bend, text-version-stamp, image-pixels-testcard, vse-cut-list) has shipped, and its light-linking subject duplicates the dedicated shipped line for light-link-studio. - Struck through the glTF skinned-mesh export witness entry per the pool's convention: it shipped as gltf-skin-roundtrip but was left unstruck, so it read as an active candidate. Every remaining unstruck entry verified genuinely unbuilt (camera DOF, volumetric scatter, freestyle, chess lathe, dice pair, bicycle wheel, UV atlas pack, and the two snippet ideas have no matching examples/ directory). Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * feat: add modular-kit-snap example A tiling corridor kit where the snap is the contract: 16 boundary verts on x in {0, 4} within 1e-6 m, end rings coincident under the tile offset (nearest-key match), a linked duplicate's joint positions deviating 0.0, shell bbox equal to the declared tile, manifold except the two open ends, and 12 detail parts contained inside the tile. Built for reuse: pivot at the start-edge connection point, identity transforms, Kit.CorridorSeg.* datablocks. Falsification: an unsnapped variant (3 mm skew, 2 mm nudge) fails at exits 3/4 with measured errors; a --falsify render exaggerates the same failure class to visible floor gaps and broken trim rails. Byte-identical check output on 4.5.11 LTS and 5.1.2. Also takes the featured_rank 8 slot on the landing page from color-attribute-wheel: the corridor is the only interior/envelope composition in the set and the stronger card. Authoring hazard recorded in ROADMAP: sorted-zip ring matching mispairs displaced verts and reports bogus cascade errors - match by nearest key. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> --------- Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
1 parent dcdc1cd commit 916160d

12 files changed

Lines changed: 1691 additions & 6 deletions

File tree

‎.cursor-plugin/plugin.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
"examples/light-link-studio",
8383
"examples/lod-decimate-chain",
8484
"examples/mesh-hygiene-audit",
85+
"examples/modular-kit-snap",
8586
"examples/parent-inverse-orrery",
8687
"examples/png-exr-alpha",
8788
"examples/prop-origin-transform",

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,3 +566,16 @@ jobs:
566566
# Exits non-zero on failure.
567567
xvfb-run -a "$BLENDER" --background \
568568
--python examples/degenerate-bevel-weld/degenerate_bevel_weld.py --
569+
570+
- name: Shipped example - modular kit snap (tile boundary contract)
571+
run: |
572+
set -euo pipefail
573+
# Check only (no render): a 4x3x3 corridor segment; asserts 16
574+
# boundary verts on x in {0, TILE} within 1e-6, end-ring coincidence
575+
# within 1e-6, a linked duplicate's joint positions matching within
576+
# 1e-6, shell bbox == declared tile (dev 0), manifold shell except
577+
# the 16 open-end edges, watertight detail parts contained inside
578+
# the tile, and reuse hygiene (identity scales, kit names, pivot
579+
# origins). Exits non-zero on failure.
580+
xvfb-run -a "$BLENDER" --background \
581+
--python examples/modular-kit-snap/modular_kit_snap.py --

‎README.md‎

Lines changed: 21 additions & 1 deletion
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>40 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>41 examples</strong>
2222
</p>
2323

2424
<p align="center">
@@ -780,6 +780,26 @@ welds their loops. Companion to
780780
check first caught the weld) and [`mesh-hygiene-audit`](examples/mesh-hygiene-audit/)
781781
(topology gates). Seam markers are placed from live mesh data.
782782

783+
</td>
784+
</tr>
785+
<tr>
786+
<td width="46%" valign="middle">
787+
<a href="examples/modular-kit-snap/"><img src="examples/modular-kit-snap/preview.webp" alt="Modular kit snap: a corridor run of four tiling segments — dark steel walls with blue-gray panels, orange trim rails, and ceiling light strips converging on a glowing amber doorway, with every joint seamless because the boundary verts snap exactly to the tile grid" /></a>
788+
</td>
789+
<td valign="middle">
790+
791+
### [modular-kit-snap](examples/modular-kit-snap/)
792+
793+
A tiling corridor kit where the snap is the contract. **16 boundary verts**
794+
on `x ∈ {0, 4}` within **1e-6 m**, opposing end loops coincident under the
795+
tile offset, and a linked duplicate's joint positions matching within 1e-6 —
796+
zero gap, zero overlap. Shell bbox equals the declared tile exactly, the
797+
tube is manifold except its two open ends, and all twelve detail parts are
798+
contained inside the tile. The unsnapped probe (3 mm skew) fails with the
799+
measured error printed. Companion to
800+
[`prop-origin-transform`](examples/prop-origin-transform/) (pivot discipline)
801+
and [`mesh-hygiene-audit`](examples/mesh-hygiene-audit/) (topology gates).
802+
783803
</td>
784804
</tr>
785805
</table>

‎ROADMAP.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
9797
- Refresh the `slotted-actions-animation` skill against any 5.2 changes
9898
- Bump `blender_version_min` in the templates if 5.2 APIs are used
9999
- Additional snippets for asset library scripting, EXR baking, multi-file extensions
100-
- Gallery coverage follow-ups from the GPv3 review: light-linking (`grease-pencil-rosette`, `armature-bend`, `text-version-stamp`, `image-pixels-testcard`, and `vse-cut-list` shipped first)
101100
- ~~UV-layer authoring witness~~ **SHIPPED** as `examples/uv-layer-grid/` — `create_grid(..., calc_uvs=True)` silent no-op without a pre-existing UV layer; closed-form UV fill + explicit assignment fallback; dual-panel render (flat texel (0,0) vs neon checker)
102101
- ~~Image save-format witness~~ **SHIPPED** as `examples/png-exr-alpha/` — float→PNG is RGBA16 and false-unpremultiplies as if associated-alpha (closed-form err 0.98 at RGB 0.02 / a=1/255); OpenEXR preserves float RGBA; byte→PNG is straight RGBA8; `EXR color_mode='RGB'` drops alpha
103102
- ~~Attribute domain witness~~ **SHIPPED** as `examples/attribute-domain-shear/` — POINT vs CORNER semantics on an 8-wedge pinwheel with one shared hub: CORNER authoring exact (hub corners disagree by face, err ≤ 1e-6), naive per-wedge POINT loop shears to the last write at hub + ring verts, measured deviation == palette closed form (0.751031); byte-identical on 4.5.11 and 5.1.2; crisp-vs-smeared dual pinwheel still — companion to `color-attribute-wheel`
@@ -108,8 +107,9 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
108107
- ~~Vertex weight limit witness~~ **SHIPPED** as `examples/vertex-weight-limit/` — the 4-influence engine cap enforced via the data API (`v.groups` + `VertexGroup.remove` + renormalize); unit sums (measured 3e-8), pose preserved (4.9e-3), exact LBS from the mesh's own deform layer (2.7e-7), Root mount pinned
109108
- ~~Triangulate + tangent-space witness~~ **SHIPPED** as `examples/triangulate-tangents/` — `calc_tangents` aborts on any ngon (back cap must be an explicit fan); mikktspace matches the edge/UV-delta formula within welding tolerance on smooth fields (2.3e-6 measured); planar UVs on a cylindrical wall collapse tangents onto normals (dot 0.998); `MeshUVLoopLayer` handle dangles across `calc_tangents()` on 4.5 (471 phantom flips, silent exit 0) while the mikktspace math is byte-identical on 4.5.11 and 5.1.2
110109
- UV-handle lifetime snippet: re-fetch attribute/UV layers by name after any CustomData-reallocating call (`calc_tangents`, `VertexGroup.add`, modifier edits) — held handles dangle silently on 4.5, survive by luck on 5.1 (found authoring `triangulate-tangents`)
111-
- glTF skinned-mesh export witness: follow-up to `gltf-export-roundtrip` + `vertex-weight-limit` — **SHIPPED** as `examples/gltf-skin-roundtrip/` — `skins[0].joints` names every bone, JOINTS_0/WEIGHTS_0 with unit sums (3e-8), weights bit-exact, rest matrices to 2.4e-07, deformation to 4.8e-07; exporter welds duplicate loops (sorted-multiset comparisons mispair — compare by rest-key); unparented skinned meshes make the exporter bind an armature by name
110+
- ~~glTF skinned-mesh export witness: follow-up to `gltf-export-roundtrip` + `vertex-weight-limit`~~ **SHIPPED** as `examples/gltf-skin-roundtrip/` — `skins[0].joints` names every bone, JOINTS_0/WEIGHTS_0 with unit sums (3e-8), weights bit-exact, rest matrices to 2.4e-07, deformation to 4.8e-07; exporter welds duplicate loops (sorted-multiset comparisons mispair — compare by rest-key); unparented skinned meshes make the exporter bind an armature by name
112111
- ~~Degenerate-bevel weld hazard~~ **SHIPPED** as `examples/degenerate-bevel-weld/` — at `offset == min_dim/2` the bevel band collapses to exactly 12 zero-area faces (4 min-axis edges × 3 segments) with 16 coincident verts (4 × (segments+1)) and min_area down 3.2e5×; a stdlib GLB re-parse counts **32 degenerate triangles crossing the export boundary** (MEASURED regression constant) versus 0 for the safe mesh — the loops an engine merge-by-distance welds; byte-identical on 4.5.11 and 5.1.2
112+
- ~~Modular kit snap witness~~ **SHIPPED** as `examples/modular-kit-snap/` — tiling corridor segment: 16 boundary verts on `x ∈ {0, TILE}` within 1e-6 m, end rings coincident under the tile offset (nearest-key match), linked-duplicate joint deviation 0.0, shell bbox == declared tile (dev 0.0), manifold except the 16 open-end edges, 12 detail parts contained inside the tile; unsnapped probe (3 mm skew, 2 mm nudge) fails at exits 3/4 with measured errors; sorted-zip ring matching mispairs displaced verts — match by nearest key (authoring hazard, fixed); byte-identical on 4.5.11 and 5.1.2
113113
- ~~GAMMA_CROSS blend-curve witness~~ **SHIPPED** as `examples/vse-gamma-cross/` — the cross blends in a gamma-0.5 space: `((1-t)·√A + t·√B)²` with `t = (frame − start)/duration`, never 1 inside the effect; mid-cross dips 0.115 below the sRGB lerp from crimson/teal (closed form (0.341, 0.349, 0.463) confirmed per frame); AgX-default sampling poisons the fit (0.146 red-channel error, `view_transform='Standard'` mandatory); deleting a consumed input orphans-and-deletes the effect — follow-up to `vse-cut-list`
114114
- Falsy `bpy_prop_collection` trap snippet: an empty collection is falsy, so `editor.strips or editor.sequences` silently falls through to the legacy accessor on an empty timeline — always branch on `hasattr`; likely generalizes across the API (found authoring `vse-cut-list`)
115115
- ~~Collision compound witness~~ **SHIPPED** as `examples/collision-hull-proxy/` — game-prop collision as a compound of convex pieces, each a `bmesh.ops.convex_hull` of a coarse `sec(π/n)`-inflated cage (containment 4.4e-08, watertight, positive signed volume, Euler 2, per-piece 255-face budget: body 70, caps 60×3, compound 250); a hull of the dense render mesh measures 380 faces — over budget — which is why pipelines hull cages; proud details cost cage rows, concave grooves are free; byte-identical on 4.5.11 and 5.1.2
1.09 MB
Loading
49.8 KB
Loading

‎docs/gallery/index.html‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ <h1>Examples Gallery</h1>
272272
autocomplete="off" spellcheck="false" aria-label="Search examples" />
273273
<button class="q-clear" id="qClear" type="button" aria-label="Clear search" hidden>&times;</button>
274274
</div>
275-
<span class="count" id="count" role="status" aria-live="polite">40 examples</span>
275+
<span class="count" id="count" role="status" aria-live="polite">41 examples</span>
276276
<div class="density" role="group" aria-label="Card density">
277277
<button class="density-btn" data-density="compact" type="button" aria-pressed="false">Compact</button>
278278
<button class="density-btn" data-density="detailed" type="button" aria-pressed="false">Detailed</button>
@@ -762,6 +762,17 @@ <h2><a href="degenerate-bevel-weld/">degenerate-bevel-weld</a></h2>
762762
<a class="card-link" href="degenerate-bevel-weld/">View example <span aria-hidden="true">&rarr;</span></a>
763763
</div>
764764
</article>
765+
<article class="card" data-tags="mesh bmesh game-pipeline instancing">
766+
<a class="card-media" href="modular-kit-snap/" aria-label="modular-kit-snap example detail page">
767+
<img src="assets/modular-kit-snap-hero.webp" alt="modular-kit-snap — A tiling corridor kit whose open-end boundary verts snap to the tile grid, so instances at 4 m multiples join with zero gap or overlap." loading="lazy" decoding="async" />
768+
</a>
769+
<div class="card-body">
770+
<h2><a href="modular-kit-snap/">modular-kit-snap</a></h2>
771+
<p class="teaches">A tiling corridor kit whose open-end boundary verts snap to the tile grid, so instances at 4 m multiples join with zero gap or overlap.</p>
772+
<p class="witnesses"><span class="tag">witnesses</span> 16 boundary verts on x∈{0,4} within 1e-6 m, linked-duplicate joint deviation 0.0, bbox == declared tile; unsnapped probe fails at 3e-3 m.</p>
773+
<a class="card-link" href="modular-kit-snap/">View example <span aria-hidden="true">&rarr;</span></a>
774+
</div>
775+
</article>
765776
</div>
766777
<p class="noresults" id="noResults" hidden>No examples match the current filters.
767778
<button class="chip" id="resetFilters" type="button">Clear search and tags</button></p>

0 commit comments

Comments
 (0)