Skip to content

Commit c5c0043

Browse files
feat: add prop-origin-transform example (#102)
Ship base-center origin bake, data-API scale apply, and MPI accessory parenting as a dual-panel gallery example so prop pipelines can prove ingest transforms without teleporting children. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 94253cd commit c5c0043

12 files changed

Lines changed: 1469 additions & 4 deletions

File tree

.cursor-plugin/plugin.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
"examples/mesh-hygiene-audit",
8282
"examples/parent-inverse-orrery",
8383
"examples/png-exr-alpha",
84+
"examples/prop-origin-transform",
8485
"examples/shader-node-group",
8586
"examples/shape-key-blend",
8687
"examples/sky-texture-sun-elevation",

.github/workflows/blender-smoke.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,3 +505,14 @@ jobs:
505505
# positive signed volume, Euler V-E+F == 2. Exits non-zero on failure.
506506
xvfb-run -a "$BLENDER" --background \
507507
--python examples/mesh-hygiene-audit/mesh_hygiene_audit.py --
508+
509+
- name: Shipped example - prop origin transform (base origin + scale + MPI)
510+
run: |
511+
set -euo pipefail
512+
# Check only (no render): street pedestal; asserts scale (1,1,1) after
513+
# data-API apply, local bbox min.z == 0, world AABB unchanged, bare
514+
# parent jumps accessory, matrix_parent_inverse restores world location,
515+
# and matrix_world stays stale until view_layer.update(). Exits non-zero
516+
# on failure.
517+
xvfb-run -a "$BLENDER" --background \
518+
--python examples/prop-origin-transform/prop_origin_transform.py --

README.md

Lines changed: 20 additions & 3 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>35 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>36 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 35 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 36 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

@@ -537,7 +537,7 @@ portable path is `radius`.
537537
</details>
538538

539539
<details>
540-
<summary><strong>Game asset pipeline</strong> — 8 examples</summary>
540+
<summary><strong>Game asset pipeline</strong> — 9 examples</summary>
541541

542542
<table>
543543
<tr>
@@ -682,6 +682,23 @@ closed solid (measured 24/44/22, volume 0.989248). Companion to
682682
and [`bmesh-gear`](examples/bmesh-gear/) (parametric closed solids). Dual-panel
683683
still: DIRTY (injected boundary + loose vert) vs CLEAN.
684684

685+
</td>
686+
</tr>
687+
<tr>
688+
<td width="46%" valign="middle">
689+
<a href="examples/prop-origin-transform/"><img src="examples/prop-origin-transform/preview.webp" alt="Prop origin transform: dual-panel TRAP vs MPI KEEP street pedestals — left bare-parent accessory teleports with expected-seat ghost, right accessory stays put, emissive origin markers at base — proving scale apply, base origin, and matrix_parent_inverse" /></a>
690+
</td>
691+
<td valign="middle">
692+
693+
### [prop-origin-transform](examples/prop-origin-transform/)
694+
695+
The origin / scale-apply / MPI contract a prop pipeline relies on before
696+
engine ingest: data-API scale bake to exactly `(1,1,1)`, local bbox
697+
`min.z == 0` (origin at base), world AABB unchanged across the bake, and
698+
`matrix_parent_inverse` so a bolted accessory does not teleport. Extends
699+
[`parent-inverse-orrery`](examples/parent-inverse-orrery/) without retreading
700+
orbits. Dual-panel still: TRAP (bare parent) vs MPI KEEP.
701+
685702
</td>
686703
</tr>
687704
</table>

ROADMAP.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,10 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
119119
- Camera DOF + focus_distance witness: `cam.dof.use_dof`, focus plane vs defocus variance on high-freq cards (Stage deviation — depth needs background content)
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)
122-
- prop-origin-transform witness — origin to base center, `transform_apply` through the data API, delta transforms, `matrix_parent_inverse` so parented children do not teleport; closed forms: post-apply scale exactly (1,1,1), local bbox min Z == 0, world bbox unchanged (builds on `parent-inverse-orrery`, does not duplicate it)
122+
- ~~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
123123
- ~~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
124124
- 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)
125+
- 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`
125126

126127
## Future (uncommitted)
127128

908 KB
Loading
35.7 KB
Loading

docs/gallery/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,14 @@ <h1>Examples Gallery</h1>
199199
<button class="chip" data-tag="node-groups" type="button">node-groups</button>
200200
<button class="chip" data-tag="objects" type="button">objects</button>
201201
<button class="chip" data-tag="operators" type="button">operators</button>
202+
<button class="chip" data-tag="parenting" type="button">parenting</button>
202203
<button class="chip" data-tag="performance" type="button">performance</button>
203204
<button class="chip" data-tag="render" type="button">render</button>
204205
<button class="chip" data-tag="rendering" type="button">rendering</button>
205206
<button class="chip" data-tag="sequencer" type="button">sequencer</button>
206207
<button class="chip" data-tag="shape-keys" type="button">shape-keys</button>
207208
<button class="chip" data-tag="sky" type="button">sky</button>
209+
<button class="chip" data-tag="transform" type="button">transform</button>
208210
<button class="chip" data-tag="transforms" type="button">transforms</button>
209211
<button class="chip" data-tag="uv" type="button">uv</button>
210212
<button class="chip" data-tag="world" type="button">world</button>
@@ -596,6 +598,17 @@ <h2><a href="mesh-hygiene-audit/">mesh-hygiene-audit</a></h2>
596598
<a class="card-link" href="mesh-hygiene-audit/">View example <span aria-hidden="true">&rarr;</span></a>
597599
</div>
598600
</article>
601+
<article class="card" data-tags="transform parenting game-pipeline">
602+
<a class="card-media" href="prop-origin-transform/" aria-label="prop-origin-transform example detail page">
603+
<img src="assets/prop-origin-transform-hero.webp" alt="prop-origin-transform — Street pedestal origin-to-base-center + data-API scale apply + matrix_parent_inverse for a bolted accessory." loading="lazy" decoding="async" />
604+
</a>
605+
<div class="card-body">
606+
<h2><a href="prop-origin-transform/">prop-origin-transform</a></h2>
607+
<p class="teaches">Street pedestal origin-to-base-center + data-API scale apply + matrix_parent_inverse for a bolted accessory. After bake: scale exactly (1,1,1), local min.z==0, world AABB delta 0. Bare parent jumps the accessory (~0.43 m); MPI restores world location (~3e-8). view_layer.update() before reading matrix_world.</p>
608+
<p class="witnesses"><span class="tag">witnesses</span> AI code parents with child.parent = parent alone (accessory teleports), skips view_layer.update() before matrix_world, or leaves non-uniform scale / centered origin for engine ingest. Skipping apply, origin bake, or MPI each fails a closed-form gate.</p>
609+
<a class="card-link" href="prop-origin-transform/">View example <span aria-hidden="true">&rarr;</span></a>
610+
</div>
611+
</article>
599612
</div>
600613
</main>
601614
<footer>

0 commit comments

Comments
 (0)