From 61bb142869e64d9bd33881be0ce4f08e35ef8716 Mon Sep 17 00:00:00 2001 From: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Date: Fri, 2 Oct 2026 06:54:15 -0400 Subject: [PATCH] feat(examples): add ray-cast-space and lattice-deform ray-cast-space: Object.ray_cast takes object-local coordinates; Scene.ray_cast takes world coordinates. The script casts five closed-form rays at a block that is translated, rotated about Z and scaled unevenly. - Scene.ray_cast hits every world point and normal exactly (exit 3). - Object.ray_cast, given matrix_world.inverted() origins and directions mapped through the 3x3 only, hits the same polygons and maps back within 5e-7 m (exit 4). - World coordinates passed straight to Object.ray_cast land at least 0.287 m from the true hits (exit 5). - --world-to-object exits 4 with a 1.125 m error. lattice-deform: a 2x2x2 KEY_LINEAR lattice with two corners moved through co_deform puts all 602 evaluated vertices on the trilinear closed form, max error 5.6e-7, through a translated and unevenly scaled lattice. - An unmoved lattice is the identity (exit 3). - The mesh really does move (exit 5). - --bspline, the default interpolation, misses by 0.2145 and exits 4. Both pass the default check on Blender 4.5.11, 5.1.2 and 5.2.1, and each falsifier is proven on 4.5.11 and 5.2.1. Contact sheets are committed under docs/gallery/contact-sheets/. Counts are updated in README, AGENTS, CLAUDE and new-example-prompt; the AGENTS and CLAUDE showcase counts are corrected from 67 to 72 as well. Co-Authored-By: Claude Opus 5.5 Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> --- .cursor-plugin/plugin.json | 4 +- AGENTS.md | 6 +- CLAUDE.md | 8 +- README.md | 39 +- ROADMAP.md | 5 +- docs/gallery/armature-bend/index.html | 4 +- .../assets/lattice-deform-hero-640.webp | Bin 0 -> 20662 bytes docs/gallery/assets/lattice-deform-hero.webp | Bin 0 -> 64020 bytes .../assets/ray-cast-space-hero-640.webp | Bin 0 -> 9966 bytes docs/gallery/assets/ray-cast-space-hero.webp | Bin 0 -> 30404 bytes .../gallery/attribute-domain-shear/index.html | 4 +- .../bake-normal-high-to-low/index.html | 4 +- docs/gallery/bmesh-gear/index.html | 4 +- docs/gallery/car-mirror-symmetry/index.html | 22 +- docs/gallery/collision-hull-proxy/index.html | 4 +- docs/gallery/color-attribute-wheel/index.html | 4 +- docs/gallery/compositor-glare/index.html | 4 +- .../lattice-deform-contact-sheet.webp | Bin 0 -> 74148 bytes .../ray-cast-space-contact-sheet.webp | Bin 0 -> 61014 bytes .../cross-version-property-delete/index.html | 4 +- docs/gallery/curve-bevel-arc/index.html | 4 +- docs/gallery/custom-normals-shade/index.html | 4 +- docs/gallery/damped-track-aim/index.html | 4 +- docs/gallery/degenerate-bevel-weld/index.html | 4 +- docs/gallery/depsgraph-export/index.html | 4 +- docs/gallery/driver-wave/index.html | 4 +- docs/gallery/export-preset-axis/index.html | 4 +- docs/gallery/gltf-export-roundtrip/index.html | 4 +- docs/gallery/gltf-skin-roundtrip/index.html | 4 +- docs/gallery/gn-instance-grid/index.html | 4 +- docs/gallery/gn-modifier-inputs/index.html | 4 +- docs/gallery/gn-sdf-remesh/index.html | 4 +- docs/gallery/gn-sim-fountain/index.html | 4 +- docs/gallery/gn-socket-rename/index.html | 4 +- docs/gallery/gn-zone-iterate/index.html | 4 +- docs/gallery/gp-lineart-contour/index.html | 4 +- docs/gallery/grease-pencil-rosette/index.html | 4 +- docs/gallery/image-pixels-testcard/index.html | 4 +- docs/gallery/index.html | 28 +- docs/gallery/lattice-deform/index.html | 1229 ++++++++++++++++ docs/gallery/light-link-studio/index.html | 4 +- docs/gallery/lightmap-uv-channel/index.html | 4 +- docs/gallery/lod-decimate-chain/index.html | 22 +- docs/gallery/mesh-hygiene-audit/index.html | 4 +- docs/gallery/modular-kit-snap/index.html | 4 +- docs/gallery/parent-inverse-orrery/index.html | 22 +- docs/gallery/png-exr-alpha/index.html | 4 +- docs/gallery/prop-origin-transform/index.html | 4 +- docs/gallery/ray-cast-space/index.html | 1262 +++++++++++++++++ docs/gallery/shader-node-group/index.html | 4 +- docs/gallery/shape-key-blend/index.html | 4 +- .../sky-texture-sun-elevation/index.html | 4 +- docs/gallery/soccer-ball-goldberg/index.html | 4 +- docs/gallery/socket-attach-points/index.html | 4 +- docs/gallery/swatch-grid/index.html | 4 +- docs/gallery/temp-override-join/index.html | 4 +- docs/gallery/text-version-stamp/index.html | 4 +- docs/gallery/triangulate-tangents/index.html | 4 +- docs/gallery/turntable/index.html | 4 +- .../usd-export-evaluation-mode/index.html | 4 +- docs/gallery/uv-layer-grid/index.html | 4 +- docs/gallery/vertex-color-ao/index.html | 4 +- docs/gallery/vertex-weight-limit/index.html | 4 +- docs/gallery/vse-cut-list/index.html | 4 +- docs/gallery/vse-gamma-cross/index.html | 4 +- docs/gallery/wave-displace/index.html | 4 +- docs/new-example-prompt.md | 2 +- examples/gallery.json | 28 + examples/lattice-deform/README.md | 73 + examples/lattice-deform/lattice_deform.py | 460 ++++++ examples/lattice-deform/preview.webp | Bin 0 -> 59220 bytes examples/ray-cast-space/README.md | 72 + examples/ray-cast-space/preview.webp | Bin 0 -> 28124 bytes examples/ray-cast-space/ray_cast_space.py | 476 +++++++ tests/smoke/catalog.json | 2 + 75 files changed, 3808 insertions(+), 148 deletions(-) create mode 100644 docs/gallery/assets/lattice-deform-hero-640.webp create mode 100644 docs/gallery/assets/lattice-deform-hero.webp create mode 100644 docs/gallery/assets/ray-cast-space-hero-640.webp create mode 100644 docs/gallery/assets/ray-cast-space-hero.webp create mode 100644 docs/gallery/contact-sheets/lattice-deform-contact-sheet.webp create mode 100644 docs/gallery/contact-sheets/ray-cast-space-contact-sheet.webp create mode 100644 docs/gallery/lattice-deform/index.html create mode 100644 docs/gallery/ray-cast-space/index.html create mode 100644 examples/lattice-deform/README.md create mode 100644 examples/lattice-deform/lattice_deform.py create mode 100644 examples/lattice-deform/preview.webp create mode 100644 examples/ray-cast-space/README.md create mode 100644 examples/ray-cast-space/preview.webp create mode 100644 examples/ray-cast-space/ray_cast_space.py diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index 7e5ee501..0229f8ae 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -136,7 +136,9 @@ "examples/vse-cut-list", "examples/vse-gamma-cross", "examples/vse-linear-modifiers", - "examples/wave-displace" + "examples/wave-displace", + "examples/ray-cast-space", + "examples/lattice-deform" ], "showcase": [ "showcase/shipping-crate", diff --git a/AGENTS.md b/AGENTS.md index 5cda6954..4069700f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,8 +20,8 @@ a `.cursor-plugin/plugin.json` manifest so the ecosystem drift checker classifies it as a `cursor-plugin`. This is content the AI loads when the user asks Blender questions or works on Blender add-ons in Cursor or Claude Code. -The content base is 16 skills, 9 rules, 3 templates, 27 snippets, 60 -examples, and 67 showcase pieces (counts are CI-enforced against README.md) +The content base is 16 skills, 9 rules, 3 templates, 27 snippets, 62 +examples, and 72 showcase pieces (counts are CI-enforced against README.md) and the manifest). The full inventory tables and per-item purposes live in `CLAUDE.md`. Example anatomy and authoring rules: copy `examples/bmesh-gear/`; showcase conventions: `showcase/README.md`. The render look is specified @@ -36,7 +36,7 @@ Blender-Developer-Tools/ rules/.mdc # 9 rule files templates// # 3 starter templates snippets/.py # 27 standalone Python snippets - examples// # 60 runnable smoke-gated examples (+ gallery.json) + examples// # 62 runnable smoke-gated examples (+ gallery.json) examples/gallery_framing.py # shared Layer 1 framing measurement (render path only) showcase// # budget-conformance props (sibling of examples/) showcase/gallery.json # this tree's gallery index; merged into docs/gallery/ diff --git a/CLAUDE.md b/CLAUDE.md index 118707c0..48c7a44f 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -21,8 +21,8 @@ skills//SKILL.md - AI workflow definitions, 16 total rules/.mdc - Anti-pattern rules, 9 total templates// - Starter projects, 3 total snippets/.py - Standalone code patterns, 27 total -examples// - Runnable smoke-gated examples, 60 total (+ gallery.json) -showcase// - Budget-conformance props, 67 pieces, each with a gallery `category` (sibling of examples/; see showcase/README.md § Categories) +examples// - Runnable smoke-gated examples, 62 total (+ gallery.json) +showcase// - Budget-conformance props, 72 pieces, each with a gallery `category` (sibling of examples/; see showcase/README.md § Categories) scripts/build_gallery.py - Regenerates docs/gallery/ from examples/gallery.json + showcase/gallery.json scripts/site/ - Vendored landing-page build (Jinja2); tokens.css is the shared palette tests/check_site_links.py - Internal link/anchor/alt gate over the built site (docs/) @@ -105,12 +105,12 @@ v0.2.0: Principled BSDF material, driver-with-custom-function via `driver_namesp AI asset pipeline track: `decimate_to_budget.py`, `convex_hull_collider.py`, `lod_chain.py` (helper duplicated, not imported), `gltf_draco_export.py`, `export_preset_unity.py`, `export_preset_godot.py`, `export_preset_unreal.py`, `setup_bake_target_image.py`, `bake_normal_high_to_low.py`, `save_baked_image.py`. -## Examples (60) +## Examples (62) Runnable scripts at `examples//`, each asserting a real API contract with deterministic checks (exit non-zero on failure) and optionally rendering a still via `--output`. All of them run headless on Blender 5.2 LTS and 4.5 LTS in `blender-smoke.yml` (5.1 on the weekly cron, the `needs-5.1` PR label, or manual dispatch); -**52 of the 60 ship a render in the site gallery** at `docs/gallery/`. The other +**54 of the 62 ship a render in the site gallery** at `docs/gallery/`. The other eight are **check-only**: they carry no `--output` path, no gallery entry, and no hero asset. The criterion is whether the contract is expressible in pixels. An example is check-only when its witness is a data or state fact that no scene diff --git a/README.md b/README.md index 7876e01b..3acd3cbd 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@

- 16 skills  •  9 rules  •  3 templates  •  27 snippets  •  60 examples  •  72 showcase pieces + 16 skills  •  9 rules  •  3 templates  •  27 snippets  •  62 examples  •  72 showcase pieces

@@ -37,7 +37,7 @@ ## Overview -This repository ships **16 skills, 9 rules, 3 templates, 27 snippets, 60 examples, and 72 showcase pieces** for Blender Python development targeting Blender 5.2 LTS (current stable) with Blender 4.5 LTS fallback support. Blender 5.1 is prior stable. +This repository ships **16 skills, 9 rules, 3 templates, 27 snippets, 62 examples, and 72 showcase pieces** for Blender Python development targeting Blender 5.2 LTS (current stable) with Blender 4.5 LTS fallback support. Blender 5.1 is prior stable. The content is consumed by AI coding agents reading these files directly from a checkout — **there is no MCP server in this repository, and none is required**. Cursor applies `rules/*.mdc` automatically wherever their scope globs match and takes skills by name in chat; Claude Code reads `skills/` and `rules/` from the project workspace, or from this repo kept as a referenced checkout. Any agent that can read files in a workspace can use it the same way. There is no build step for the content — edit the Markdown and Python files directly. @@ -75,7 +75,7 @@ blender --background --python examples/bmesh-gear/bmesh_gear.py -- ## Falsifiers -Every one of the 60 examples carries a **falsifier**: a flag that changes the +Every one of the 62 examples carries a **falsifier**: a flag that changes the input so a real assertion fails. It never disables the assertion, skips the check, or short-circuits to an error — it feeds the script something the contract says must not pass, and the same check that guards the happy path @@ -451,7 +451,7 @@ Gallery still is a sky-lit obelisk diptych (8° dusk | 55° midday) so the contr

-Mesh, curves & text — 13 examples +Mesh, curves & text — 15 examples @@ -648,6 +648,37 @@ check-only, no gallery still — no geometry getattr is `AttributeError` on 5.2.1. Version-guarded `hasattr` then read exits 0 on all three. `--assume-present` is red only on 5.2. + + + + + + + + +
+Ray cast space: a teal-checkered block turned and stretched on a walnut plinth, five orange rays from brass emitter balls ending in orange hit rings on three of its faces, and one red ray from the world-coordinate trap striking it from somewhere else, on a dark studio floor + + +### [ray-cast-space](examples/ray-cast-space/) + +`Object.ray_cast` vs `Scene.ray_cast` — five closed-form rays on a translated, Z-rotated, +non-uniformly scaled block. `Scene.ray_cast` hits each world point and normal exactly. +`Object.ray_cast`, fed `matrix_world.inverted()` origins and 3×3-only directions, hits the +same polygons and maps back within 5e-7 m. Raw world coordinates handed to `Object.ray_cast` +land 0.287 m or more away (`--world-to-object` exits 4). + +
+Lattice deform: two checker-glazed columns on a walnut plinth, each in a steel-rod cage - the left upright in its rest cage, the right sheared and tapered where two orange cage corners have been pulled out + + +### [lattice-deform](examples/lattice-deform/) + +A 2×2×2 Lattice modifier set to `'KEY_LINEAR'`, with two corners moved through +`LatticePoint.co_deform`. Witnesses that every evaluated vert lands on the trilinear +blend of the eight deformed corners, and that the default `'KEY_BSPLINE'` misses it +(`--bspline` exits 4). +
diff --git a/ROADMAP.md b/ROADMAP.md index 6ac6b529..26688729 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -163,13 +163,14 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo - `persistent` app-handler witness — handlers registered without `@bpy.app.handlers.persistent` are dropped by `wm.read_homefile`/file load while persistent ones survive; assert the registered-handler set before and after a reload (silent loss AI code hits) - Link vs append witness — `bpy.data.libraries.load(link=True)` yields a linked, non-editable datablock (`library` set, `is_editable` False) while append yields a local copy; write a temp .blend with `bpy.data.libraries.write`, then assert both paths - Orphan purge witness — `bpy.data.orphans_purge(do_recursive=...)` removes exactly the zero-user datablocks computed independently beforehand, and `bpy.data.batch_remove` removes a given set in one call (counts closed-form) -- Local vs world ray-cast witness — `Object.ray_cast` takes object-local origin/direction while `Scene.ray_cast` takes world space; a transformed target hit at closed-form points both ways, and passing world coords to `Object.ray_cast` misses (the trap) +- ~~Local vs world ray-cast witness~~ **SHIPPED** as `examples/ray-cast-space/` — five closed-form rays on a translated, Z-rotated, non-uniformly scaled block: `Scene.ray_cast` exact in world space, `Object.ray_cast` exact through `matrix_world.inverted()` (3×3-only directions, inverse-transpose normals, same polygon index); world coords fed to `Object.ray_cast` land ≥ 0.287 m off; `--world-to-object` exits 4 - `mathutils.bvhtree` witness — `BVHTree.FromObject` on evaluated geometry: `find_nearest` distances and `overlap` pairs match closed forms on a known arrangement - Curves datablock witness — the modern `bpy.types.Curves` hair API (`add_curves`, `position` attribute, `curve_offset_data`) vs legacy particle hair: point and curve counts closed-form, every root on the emitter surface - Non-Color normal-map witness — an image used as a normal map must be `colorspace_settings.name = 'Non-Color'`; a baked/sampled value round-trips only then, and sRGB shifts it by the transfer curve (a silent shading error AI code ships) - Solidify even-thickness witness — `use_even_offset` keeps shell thickness constant at sharp corners, while without it the corner thins by 1/cos(θ/2): measured thickness at a known angle matches both closed forms - Boolean solver witness — EXACT solver union/difference volumes match closed forms on overlapping primitives, and the result is manifold; FAST on coplanar faces is the documented failure case -- Lattice deform witness — a 2×2×2 lattice with one displaced point deforms interior verts by exact trilinear weights (`interpolation_type_u/v/w = 'KEY_LINEAR'`) +- ~~Lattice deform witness — a 2×2×2 lattice with one displaced point deforms interior verts by exact trilinear weights (`interpolation_type_u/v/w = 'KEY_LINEAR'`)~~ **SHIPPED** as `examples/lattice-deform/` — 602 evaluated verts on the trilinear closed form (5.6e-7) through a translated, non-uniformly scaled lattice; `--bspline` (the default interpolation) exits 4 at 0.2145 +- Lattice `use_outside` / outside-vertex witness — verts outside a KEY_LINEAR lattice's volume: assert the documented clamp or extrapolation closed form, and `use_outside` (deform only the outer points) against an interior-only control move - FBX unit-scale witness — `export_scene.fbx` with `apply_unit_scale` / `apply_scale_options` changes exported coordinates by the closed-form ×100 cm factor; re-import restores metres only on the matching option - Collection-instance witness — `instance_type = 'COLLECTION'` instances appear only in `depsgraph.object_instances` (never in `scene.objects`); instance world matrices match the closed-form offsets - Asset-marking witness — `ID.asset_mark()`, `asset_data.tags` and catalog UUIDs written to `blender_assets.cats.txt`, re-read from a saved library file (check-only if no legible still) diff --git a/docs/gallery/armature-bend/index.html b/docs/gallery/armature-bend/index.html index 7b928953..6166426e 100644 --- a/docs/gallery/armature-bend/index.html +++ b/docs/gallery/armature-bend/index.html @@ -45,7 +45,7 @@

Armature Bend

Rigging end to end in the data API — edit_bones chain construction, name-bound vertex groups with smoothstep blend zones, posing, and depsgraph evaluation — bending a ribbed bellows hose through rest, half, and full curl.

- + @@ -1050,7 +1050,7 @@

LOD Decimate Chain

- +
diff --git a/docs/gallery/assets/lattice-deform-hero-640.webp b/docs/gallery/assets/lattice-deform-hero-640.webp new file mode 100644 index 0000000000000000000000000000000000000000..3581f6323e8dffcb38d969ae9fd844cf7af210a1 GIT binary patch literal 20662 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

U`nF9#D<+|7Y9E~ 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 literal 0 HcmV?d00001 diff --git a/docs/gallery/assets/lattice-deform-hero.webp b/docs/gallery/assets/lattice-deform-hero.webp new file mode 100644 index 0000000000000000000000000000000000000000..0bb76764067c3057ab0afb5eddce16e04c6d938e GIT binary patch literal 64020 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

YSkmHSpU*E)dJk97 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 literal 0 HcmV?d00001 diff --git a/docs/gallery/assets/ray-cast-space-hero-640.webp b/docs/gallery/assets/ray-cast-space-hero-640.webp new file mode 100644 index 0000000000000000000000000000000000000000..eb5ac803f0d9098b823fd13e390f2cac4aad2fcb GIT binary patch literal 9966 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 literal 0 HcmV?d00001 diff --git a/docs/gallery/assets/ray-cast-space-hero.webp b/docs/gallery/assets/ray-cast-space-hero.webp new file mode 100644 index 0000000000000000000000000000000000000000..f4f7320cad9a53a6040705a580bf787da9de5864 GIT binary patch literal 30404 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

Fu8QL71LE0Z)kdp}N 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 literal 0 HcmV?d00001 diff --git a/docs/gallery/attribute-domain-shear/index.html b/docs/gallery/attribute-domain-shear/index.html index 823bd7f2..196440db 100644 --- a/docs/gallery/attribute-domain-shear/index.html +++ b/docs/gallery/attribute-domain-shear/index.html @@ -45,7 +45,7 @@

Attribute Domain Shear

POINT vs CORNER color-attribute domains on a shared-vertex fan: CORNER stays exact per face while a naive per-wedge POINT loop shears to the last write at the hub. A striped parasol keeps crisp stripes under CORNER and smears, with one panel turned the wrong color, under POINT; the measured shear equals the palette closed form.

- + @@ -1507,7 +1507,7 @@

Custom Normals Shade< - +

diff --git a/docs/gallery/bake-normal-high-to-low/index.html b/docs/gallery/bake-normal-high-to-low/index.html index 4734231a..e199dcd5 100644 --- a/docs/gallery/bake-normal-high-to-low/index.html +++ b/docs/gallery/bake-normal-high-to-low/index.html @@ -45,7 +45,7 @@

Bake Normal High To Low

A collapse-decimated hatch plate receiving a Cycles cage-baked tangent normal map from a ribbed high-poly source

- + @@ -1409,7 +1409,7 @@

Shape Key Blend

- +
diff --git a/docs/gallery/bmesh-gear/index.html b/docs/gallery/bmesh-gear/index.html index 18d8dc31..d756b011 100644 --- a/docs/gallery/bmesh-gear/index.html +++ b/docs/gallery/bmesh-gear/index.html @@ -45,7 +45,7 @@

BMesh Gear

A 14-tooth gear built entirely with bmesh — profile ring, face, extrude — with bm.free() in a try/finally, exactly as the ownership contract demands.

- + @@ -1229,7 +1229,7 @@

Mesh Hygiene Audit

- +
diff --git a/docs/gallery/car-mirror-symmetry/index.html b/docs/gallery/car-mirror-symmetry/index.html index 6a5ab59b..3084e15b 100644 --- a/docs/gallery/car-mirror-symmetry/index.html +++ b/docs/gallery/car-mirror-symmetry/index.html @@ -45,7 +45,7 @@

Car Mirror Symmetry

A stylized hatchback lofted as one half (52 stations, 13-point rings) and completed by the Mirror modifier, evaluated through the depsgraph. Wheels, lamps, grille, door mirrors and handles mirror about object origins parked on the symmetry plane; the grille is authored as a half and welded on it.

- + @@ -1883,34 +1883,34 @@ - +
diff --git a/docs/gallery/collision-hull-proxy/index.html b/docs/gallery/collision-hull-proxy/index.html index 0f5eef1b..45db1ffd 100644 --- a/docs/gallery/collision-hull-proxy/index.html +++ b/docs/gallery/collision-hull-proxy/index.html @@ -45,7 +45,7 @@

Collision Hull Proxy

A fire hydrant street prop inside its compound collision shell: four convex pieces hulled by bmesh.ops.convex_hull from a coarse inflated cage. The dense render mesh is never hulled - its hull would measure 380 faces, over the 255-face per-piece engine budget. Closed-form plane tests prove containment, convexity, watertightness, outward winding, and Euler characteristic 2 per piece.

- + @@ -1169,7 +1169,7 @@

Mesh Hygiene Audit

- +
diff --git a/docs/gallery/color-attribute-wheel/index.html b/docs/gallery/color-attribute-wheel/index.html index 6a4365d1..14b5bb2d 100644 --- a/docs/gallery/color-attribute-wheel/index.html +++ b/docs/gallery/color-attribute-wheel/index.html @@ -45,7 +45,7 @@

Color Attribute Wheel

The modern color-attributes API — mesh.color_attributes.new() on the CORNER domain, filled by expanding per-vertex HSV across face corners with foreach_get/foreach_set, then wired into a shader Attribute node.

- + @@ -1039,7 +1039,7 @@

Attribute Domain Shear< - +

diff --git a/docs/gallery/compositor-glare/index.html b/docs/gallery/compositor-glare/index.html index 55034ea5..73ad9cf9 100644 --- a/docs/gallery/compositor-glare/index.html +++ b/docs/gallery/compositor-glare/index.html @@ -45,7 +45,7 @@

Compositor Glare

Bloom where it actually lives — a compositor Glare (Fog Glow) node fed by Render Layers, wired via scene.compositing_node_group on 5.x and scene.node_tree on 4.x, with the Glare node's legacy properties vs 5.x menu sockets.

- + @@ -874,7 +874,7 @@

Image Pixels Testcard - +

diff --git a/docs/gallery/contact-sheets/lattice-deform-contact-sheet.webp b/docs/gallery/contact-sheets/lattice-deform-contact-sheet.webp new file mode 100644 index 0000000000000000000000000000000000000000..7d0d971b6de8b549b09171e6a0330dd21a2ae02e GIT binary patch literal 74148 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%0DijxlO#@$a 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 literal 0 HcmV?d00001 diff --git a/docs/gallery/cross-version-property-delete/index.html b/docs/gallery/cross-version-property-delete/index.html index 5a746e3b..bba5b652 100644 --- a/docs/gallery/cross-version-property-delete/index.html +++ b/docs/gallery/cross-version-property-delete/index.html @@ -45,7 +45,7 @@

Cross Version Property Delete

Custom ID properties are removed with del, not property_unset. The IDs are built through bpy.data.objects.new so the check does not depend on active_object.

- + @@ -1009,7 +1009,7 @@

Temp Override Join

- +
diff --git a/docs/gallery/curve-bevel-arc/index.html b/docs/gallery/curve-bevel-arc/index.html index 8f8f53c9..54eaee86 100644 --- a/docs/gallery/curve-bevel-arc/index.html +++ b/docs/gallery/curve-bevel-arc/index.html @@ -45,7 +45,7 @@

Curve Bevel Arc

A beveled Bezier semicircle authored on bpy.types.Curve — splines.new('BEZIER'), bezier_points, bevel_depth, use_fill_caps — so the curve renders as a solid tube without a prior mesh conversion.

- + @@ -1194,7 +1194,7 @@

Text Version Stamp

- +
diff --git a/docs/gallery/custom-normals-shade/index.html b/docs/gallery/custom-normals-shade/index.html index 6c832456..f77388c3 100644 --- a/docs/gallery/custom-normals-shade/index.html +++ b/docs/gallery/custom-normals-shade/index.html @@ -45,7 +45,7 @@

Custom Normals Shade

A jerry can prop shaded three ways to prove the post-4.1 shading contract: hard edges are mesh data, landing exactly where the dihedral crosses. Face smooth flags plus a sharp_edge attribute, verified against an independently recomputed dihedral test, and per-loop custom normals surviving depsgraph evaluation within their int16 storage quantization (3.904e-05 over 8196 loops, not float-exact).

- + @@ -2033,7 +2033,7 @@

Vertex Color AO

- +
diff --git a/docs/gallery/damped-track-aim/index.html b/docs/gallery/damped-track-aim/index.html index 709e2474..0e2f2624 100644 --- a/docs/gallery/damped-track-aim/index.html +++ b/docs/gallery/damped-track-aim/index.html @@ -45,7 +45,7 @@

Damped Track Aim

Aim constraints via the data API — Object.constraints.new('DAMPED_TRACK') with target and TRACK_Z, not bpy.ops.object.constraint_add in a headless loop. Gallery still: twelve spotlight heads on stands, all swung onto one glowing orb.

- + @@ -1030,7 +1030,7 @@

Driver Wave

- +
diff --git a/docs/gallery/degenerate-bevel-weld/index.html b/docs/gallery/degenerate-bevel-weld/index.html index cad2dd91..a1e89370 100644 --- a/docs/gallery/degenerate-bevel-weld/index.html +++ b/docs/gallery/degenerate-bevel-weld/index.html @@ -45,7 +45,7 @@

Degenerate Bevel Weld

Bevel offset >= half the min box dimension collapses the band into zero-area faces — and they ship: a stdlib GLB re-parse counts the degenerate triangles crossing the export boundary. Two rugged cases whose shells are the check's meshes: flat end panel versus a rolled knife ridge, the collapsed seam traced hot from live mesh data.

- + @@ -1369,7 +1369,7 @@

BMesh Gear

- +
diff --git a/docs/gallery/depsgraph-export/index.html b/docs/gallery/depsgraph-export/index.html index 35eb6d14..e9f64cb5 100644 --- a/docs/gallery/depsgraph-export/index.html +++ b/docs/gallery/depsgraph-export/index.html @@ -45,7 +45,7 @@

Depsgraph Export

The depsgraph lifetime contract — evaluated_get().to_mesh() paired with to_mesh_clear() — measured against an OBJ export of the same object.

- + @@ -1416,7 +1416,7 @@

Text Version Stamp

- +
diff --git a/docs/gallery/driver-wave/index.html b/docs/gallery/driver-wave/index.html index 4802b898..c39c17a5 100644 --- a/docs/gallery/driver-wave/index.html +++ b/docs/gallery/driver-wave/index.html @@ -45,7 +45,7 @@

Driver Wave

A driver_namespace function driving sixteen organ-pipe heights through SCRIPTED drivers — the sine skyline of the pipe tops is entirely driver-evaluated.

- + @@ -901,7 +901,7 @@

Damped Track Aim

- +
diff --git a/docs/gallery/export-preset-axis/index.html b/docs/gallery/export-preset-axis/index.html index 595f1538..a740570b 100644 --- a/docs/gallery/export-preset-axis/index.html +++ b/docs/gallery/export-preset-axis/index.html @@ -45,7 +45,7 @@

Export Preset Axis

A radio mast exported under Unity and Godot glTF presets and re-imported, proving the two files have different vertex orientation

- + @@ -1635,7 +1635,7 @@

glTF Skin Roundtrip - +

diff --git a/docs/gallery/gltf-export-roundtrip/index.html b/docs/gallery/gltf-export-roundtrip/index.html index e6e0a8e9..126cc03a 100644 --- a/docs/gallery/gltf-export-roundtrip/index.html +++ b/docs/gallery/gltf-export-roundtrip/index.html @@ -45,7 +45,7 @@

glTF Export Roundtrip

A sci-fi supply crate exported to glTF and re-imported, verifying the round-trip against the depsgraph-evaluated mesh within float tolerances. Positions, loop normals, box-mapped UVs, and per-triangle material bindings must all survive; the on-disk JSON proves the +Y-up conversion and the V-flipped UV layout.

- + @@ -1602,7 +1602,7 @@

Export Preset Axis

- +
diff --git a/docs/gallery/gltf-skin-roundtrip/index.html b/docs/gallery/gltf-skin-roundtrip/index.html index ed1c7e1d..e605d06f 100644 --- a/docs/gallery/gltf-skin-roundtrip/index.html +++ b/docs/gallery/gltf-skin-roundtrip/index.html @@ -45,7 +45,7 @@

glTF Skin Roundtrip

A rigged mech scorpion exported to glTF with skins and re-imported, verifying the skinning contract the geometry round-trip left uncovered. Skeleton, weights, and deformation must all survive the format.

- + @@ -2071,7 +2071,7 @@

glTF Export Roundtrip - +

diff --git a/docs/gallery/gn-instance-grid/index.html b/docs/gallery/gn-instance-grid/index.html index d86d53a5..0c997956 100644 --- a/docs/gallery/gn-instance-grid/index.html +++ b/docs/gallery/gn-instance-grid/index.html @@ -45,7 +45,7 @@

GN Instance Grid

A generative Geometry Nodes tree — Mesh Grid → Instance on Points (a modeled keycap via Object Info) → Realize Instances → Set Shade Smooth → Set Material — attached as a NODES modifier with no Group Input geometry.

- + @@ -1450,7 +1450,7 @@

Modular Kit Snap

- +
diff --git a/docs/gallery/gn-modifier-inputs/index.html b/docs/gallery/gn-modifier-inputs/index.html index 856fcecb..7b92c356 100644 --- a/docs/gallery/gn-modifier-inputs/index.html +++ b/docs/gallery/gn-modifier-inputs/index.html @@ -45,7 +45,7 @@

GN Modifier Inputs

Per-modifier Geometry Nodes Float inputs on a shared tree — 4.5/5.1 write mod[identifier], 5.2 writes mod.properties.inputs.Socket_1.value.

- + @@ -1329,7 +1329,7 @@

GP Lineart Contour

- +
diff --git a/docs/gallery/gn-sdf-remesh/index.html b/docs/gallery/gn-sdf-remesh/index.html index 72060819..62e38586 100644 --- a/docs/gallery/gn-sdf-remesh/index.html +++ b/docs/gallery/gn-sdf-remesh/index.html @@ -45,7 +45,7 @@

GN SDF Remesh

A Geometry Nodes SDF remesh (MeshToSDFGrid → GridToMesh at the SDF zero-level), with a Set Material node carrying the material through the remesh.

- + @@ -716,7 +716,7 @@

GN Instance Grid

- +
diff --git a/docs/gallery/gn-sim-fountain/index.html b/docs/gallery/gn-sim-fountain/index.html index b0a560f0..a3a3f64a 100644 --- a/docs/gallery/gn-sim-fountain/index.html +++ b/docs/gallery/gn-sim-fountain/index.html @@ -45,7 +45,7 @@

GN Sim Fountain

A Simulation Zone only advances one step per consecutive frame_set. A direct jump to frame N runs a single step, and only a bake gives random access to the stepped state.

- + @@ -1437,7 +1437,7 @@

GN Modifier Inputs

- +
diff --git a/docs/gallery/gn-socket-rename/index.html b/docs/gallery/gn-socket-rename/index.html index 237494d7..5bb60233 100644 --- a/docs/gallery/gn-socket-rename/index.html +++ b/docs/gallery/gn-socket-rename/index.html @@ -45,7 +45,7 @@

GN Socket Rename

Compare and Random Value socket identifiers collapsed onto reused names in 5.2; enabled-name lookup wires on 4.5, 5.1, and 5.2

- + @@ -1487,7 +1487,7 @@

GN Modifier Inputs

- +
diff --git a/docs/gallery/gn-zone-iterate/index.html b/docs/gallery/gn-zone-iterate/index.html index f2593237..0c1a34b5 100644 --- a/docs/gallery/gn-zone-iterate/index.html +++ b/docs/gallery/gn-zone-iterate/index.html @@ -45,7 +45,7 @@

GN Zone Iterate

Repeat Zone and For Each Element only iterate after pair_with_output. Evaluated cube counts follow 8 times (1+N) and 8 times P, not tree structure.

- + @@ -1184,7 +1184,7 @@

GN Modifier Inputs

- +
diff --git a/docs/gallery/gp-lineart-contour/index.html b/docs/gallery/gp-lineart-contour/index.html index 9a784e56..96cb86e8 100644 --- a/docs/gallery/gp-lineart-contour/index.html +++ b/docs/gallery/gp-lineart-contour/index.html @@ -45,7 +45,7 @@

GP Lineart Contour

Grease Pencil LINEART modifier ink via the depsgraph on a cel-shaded lighthouse diorama. source_object is load-bearing (clear yields 0 strokes); every edge type off yields 0; the drawing is 255 strokes / 1393 points on 4.5.11, 5.1.2 and 5.2.1, gated above the count left when any one of contour, crease, material-border or intersection edges is dropped. Stroke width: thickness exists on 4.5, AttributeError on 5.1 — portable path is radius.

- + @@ -1576,7 +1576,7 @@

Car Mirror Symmetry - +

diff --git a/docs/gallery/grease-pencil-rosette/index.html b/docs/gallery/grease-pencil-rosette/index.html index 98899a1f..cff343c8 100644 --- a/docs/gallery/grease-pencil-rosette/index.html +++ b/docs/gallery/grease-pencil-rosette/index.html @@ -45,7 +45,7 @@

Grease Pencil Rosette

Grease Pencil v3's attribute-based API — layer → frames.new(1).drawing → add_strokes → per-point position/radius/opacity/vertex_color — drawing five nested neon rose curves.

- + @@ -933,7 +933,7 @@

GP Lineart Contour

- +
diff --git a/docs/gallery/image-pixels-testcard/index.html b/docs/gallery/image-pixels-testcard/index.html index 8d6d8c34..bd7fc27e 100644 --- a/docs/gallery/image-pixels-testcard/index.html +++ b/docs/gallery/image-pixels-testcard/index.html @@ -45,7 +45,7 @@

Image Pixels Testcard

The Image pixel-buffer contract — a procedural broadcast test card written into bpy.data.images.new() with one pixels.foreach_set (589,824 floats), byte vs float_buffer storage, scale() reallocation, and the save() vs save_render() lifecycle.

- + @@ -1041,7 +1041,7 @@

Wave Displace

- +
diff --git a/docs/gallery/index.html b/docs/gallery/index.html index a2b356eb..f306eff7 100644 --- a/docs/gallery/index.html +++ b/docs/gallery/index.html @@ -67,7 +67,7 @@

Examples and Showcase

autocomplete="off" spellcheck="false" aria-label="Search examples and showcase pieces" /> - 52 examples, 72 showcase pieces + 54 examples, 72 showcase pieces
@@ -766,6 +766,30 @@

GN Socket Rename

+
+
+ A teal-checkered block turned and stretched on a walnut plinth, five orange rays from brass balls ending in orange rings on three faces, and one red ray striking it from elsewhere. +
+
+

Ray Cast Space

+

ray-cast-space

+

Object.ray_cast is object-local while Scene.ray_cast is world space: rays mapped through matrix_world.inverted() (directions by its 3x3 only) hit the same points both ways, and raw world coords handed to Object.ray_cast miss.

+

witnesses Five closed-form rays on a translated, Z-rotated, non-uniformly scaled block: Scene.ray_cast hits each world point and normal exactly; Object.ray_cast fed matrix_world.inverted() coordinates hits the same polygons, and mapped back lands within 5e-7 m; world coords fed to Object.ray_cast land 0.287 m or more off. --world-to-object exits 4 (1.125 m error).

+ +
+
+
+
+ Two checker-glazed columns on a walnut plinth, each in a steel-rod cage: the left upright in its rest cage, the right sheared and tapered where two orange cage corners have been pulled out. +
+
+

Lattice Deform

+

lattice-deform

+

A 2x2x2 Lattice modifier set to KEY_LINEAR on all three axes, with two top control points moved through LatticePoint.co_deform, read back through the depsgraph (evaluated_get, to_mesh, to_mesh_clear).

+

witnesses Linear lattice deform is exact trilinear interpolation: all 602 evaluated verts land on the closed-form blend of the eight co_deform corners (max error 5.6e-7 through a translated, non-uniformly scaled lattice), the undeformed lattice is the identity, and --bspline (the default interpolation) misses by 0.2145 and exits 4.

+ +
+
A grained wooden shipping crate in three-quarter view, PORT ROYAL and NO 17 stencilled along its side slats, with nailed iron corner straps and a bail handle on one end. @@ -1688,7 +1712,7 @@

Sundial

var filtersToggle = document.getElementById('filtersToggle'); var toTop = document.getElementById('toTop'); var total = cards.length; - var COUNT_LABEL = '52 examples, 72 showcase pieces'; + var COUNT_LABEL = '54 examples, 72 showcase pieces'; var LS_KEY = 'bdt-gallery-density'; // Read by detail pages: the Gallery crumb returns here, and the pager // walks the reader's filtered order instead of the full gallery. diff --git a/docs/gallery/lattice-deform/index.html b/docs/gallery/lattice-deform/index.html new file mode 100644 index 00000000..035712aa --- /dev/null +++ b/docs/gallery/lattice-deform/index.html @@ -0,0 +1,1229 @@ + + + + + + Lattice Deform (lattice-deform) — Examples — Blender Developer Tools + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

Lattice Deform

+

examples/lattice-deform/

+

A 2x2x2 Lattice modifier set to KEY_LINEAR on all three axes, with two top control points moved through LatticePoint.co_deform, read back through the depsgraph (evaluated_get, to_mesh, to_mesh_clear).

+
+
+ + +

Rendered headless by the example itself. Select it to enlarge.

+
witnesses Linear lattice deform is exact trilinear interpolation: all 602 evaluated verts land on the closed-form blend of the eight co_deform corners (max error 5.6e-7 through a translated, non-uniformly scaled lattice), the undeformed lattice is the identity, and --bspline (the default interpolation) misses by 0.2145 and exits 4.
+

tags mesh modifiers depsgraph

+
+
blender --background --python examples/lattice-deform/lattice_deform.py --
+ +
+
+

A runnable example that deforms a subdivided column with a 2×2×2 lattice set to 'KEY_LINEAR' interpolation on all three axes, then proves, vertex by vertex, that the Lattice modifier's output is exactly the trilinear interpolation of the eight deformed control points. The deformed mesh is read through the depsgraph lifetime contract from depsgraph-and-evaluated-data (evaluated_get → to_mesh → to_mesh_clear), and the lattice points are edited the way mesh-editing-and-bmesh recommends for data-level work: through bpy.data, never bpy.ops.

+

What it witnesses: LatticePoint.co is the read-only rest position and LatticePoint.co_deform is the one you move. With linear interpolation a vertex at normalized rest coordinates (u, v, w) inside the lattice lands on Σ wᵢ · co_deformᵢ with wᵢ = (u or 1−u)(v or 1−v)(w or 1−w), mapped through the lattice object's matrix. The check computes that closed form independently for all 602 vertices, through a lattice object that is translated and non-uniformly scaled (1.7 × 1.7 × 2.4), and requires agreement to 1e-5 in world space (measured: 5.6e-7). It also asserts the undeformed lattice is the identity and that the deformation is not trivially small (max displacement 0.53).

+

The trap it exposes: a new lattice defaults to 'KEY_BSPLINE'. B-spline weights smooth over the control points instead of interpolating them, so a script that moves a corner and expects the mesh to follow it linearly gets a softer, smaller pull. On a 2×2×2 lattice the rest state is still the identity, so nothing looks wrong until a point moves. --bspline keeps the default and fails check 4 with the measured error.

+

The still shows the rule as a before-and-after on a walnut plinth: on the left a render-only twin of the column, undeformed, inside its rest cage; on the right the checked column inside the deformed cage, with the two moved corners in selection orange and a short orange rod from each back to its rest position. The column carries a glazed two-tone checker in Generated (rest) coordinates, so the squares are square before the lattice acts, and their shear and taper in the still are the deformation. Lattices do not render, so both cages are drawn as thin steel rods built from the corner positions after the check has run.

+

Run#

+
# Cheap correctness check (no render) — the CI check:
+blender --background --python lattice_deform.py --
+
+# Falsifier: keep the default KEY_BSPLINE interpolation. Must exit 4.
+blender --background --python lattice_deform.py -- --bspline
+
+# Also render a still (EEVEE on a GPU host; use --engine cycles on GPU-less hosts):
+blender --background --python lattice_deform.py -- --output lattice.png --engine cycles
+

Version notes#

+

The Lattice datablock API (points_u/v/w, interpolation_type_u/v/w, points[i].co / co_deform, point order u fastest, then v, then w) and the 'LATTICE' modifier are the same on 4.5 LTS, 5.1 and 5.2 LTS. Measured identically on 4.5.11, 5.1.2 and 5.2.1: 602 vertices, trilinear max error 5.6e-7, max displacement 0.5311; --bspline max error 0.2145.

+

Exit codes#

+
CodeMeaning
0Success
1Uncaught exception (FATAL wrapper)
2argparse / usage
3Undeformed lattice moved the mesh (identity check)
4A vertex is off the trilinear closed form, or the vertex count changed (--bspline lands here)
5Max displacement below the floor (the witness would pass vacuously)
6--output produced no file
10--output framing violation (Layer 1 fill / margin gate, gallery_framing)
+

The blender-smoke workflow runs the check on Blender 5.2 LTS and 4.5 LTS (5.1 on the weekly cron, the needs-5.1 PR label, or manual dispatch). Smoke does not pass --output or --bspline.

+
+
+

Source

+
+ examples/lattice-deform/lattice_deform.py + 460 lines · View on GitHub → +
+
+
"""Lattice deform with linear interpolation is exact trilinear interpolation — a runnable example.
+
+Witnesses the Lattice modifier contract on a 2x2x2 lattice (``points_u``,
+``points_v`` and ``points_w`` all 2). With ``interpolation_type_u/v/w`` set
+to ``'KEY_LINEAR'`` a mesh vertex inside the lattice moves to the trilinear
+interpolation of the eight *deformed* control points (``LatticePoint.co_deform``)
+at the vertex's normalized rest coordinates (u, v, w) in lattice space.
+The check computes that closed form independently in Python for every
+evaluated vertex (``evaluated_get`` + ``to_mesh`` / ``to_mesh_clear``) and
+requires agreement to 1e-5 in world space, through a lattice object that is
+itself translated and non-uniformly scaled.
+
+Three checks, in run order:
+
+- 3: with no control point moved, the modifier is the identity;
+- 4: with two top corners moved, every vertex lands on the trilinear point;
+- 5: the deformation is not trivially small (the witness cannot pass vacuously).
+
+``--bspline`` leaves the lattice on its default ``'KEY_BSPLINE'``
+interpolation, which smooths over the control points instead of
+interpolating them, so the evaluated mesh no longer matches the trilinear
+closed form and check 4 fails with the measured error. That is the
+falsifier — and the trap: a script that sets ``co_deform`` and expects the
+corner to "pull" the mesh linearly gets a softer, smaller motion.
+
+By default it runs only the correctness check (no render) — the CI smoke
+check. Pass --output to also render a still:
+
+    blender --background --python lattice_deform.py --                 # check only
+    blender --background --python lattice_deform.py -- --bspline       # must fail
+    blender --background --python lattice_deform.py -- --output l.png  # + render
+"""
+import bpy, bmesh, sys, os, math, argparse
+from mathutils import Vector
+
+# Shared Layer 1 framing measurement (render path only) — see gallery_framing.py
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir))
+sys.dont_write_bytecode = True  # keep examples/__pycache__ out of the repo tree
+import gallery_framing
+
+# The lattice: a box in world space, as a translated, non-uniformly scaled
+# 2x2x2 lattice object (its points sit at +-0.5 in lattice-local space).
+LAT_LOC = Vector((0.0, 0.0, 1.30))
+LAT_SCALE = Vector((1.70, 1.70, 2.40))
+# The deformed column, inside the lattice on every axis (lattice-local units);
+# its base lies on the lattice's bottom face (w = 0), so it sits on the plinth
+COLUMN_HALF = (0.40, 0.40, 0.50)
+COLUMN_CUTS = 9          # subdivisions per cube edge
+# Two top corners moved (lattice-local offsets): (u, v, w) index -> offset
+MOVES = {
+    (1, 1, 1): Vector((0.30, 0.18, 0.12)),
+    (0, 0, 1): Vector((-0.10, -0.26, -0.08)),
+}
+TOL = 1e-5
+MIN_DISPLACEMENT = 0.05  # world units; check 5's floor
+TWIN_GAP = 2.9           # render only: the undeformed twin's offset to the left
+
+
+def corner_index(u, v, w, n=2):
+    """LatticePoint order: u fastest, then v, then w."""
+    return u + n * (v + n * w)
+
+
+def build_scene(bspline=False):
+    bpy.ops.wm.read_factory_settings(use_empty=True)
+    scene = bpy.context.scene
+
+    lat = bpy.data.lattices.new("Cage")
+    lat.points_u = lat.points_v = lat.points_w = 2
+    if not bspline:
+        lat.interpolation_type_u = 'KEY_LINEAR'
+        lat.interpolation_type_v = 'KEY_LINEAR'
+        lat.interpolation_type_w = 'KEY_LINEAR'
+    lat_obj = bpy.data.objects.new("Cage", lat)
+    lat_obj.location = LAT_LOC
+    lat_obj.scale = LAT_SCALE
+    scene.collection.objects.link(lat_obj)
+
+    me = bpy.data.meshes.new("Column")
+    bm = bmesh.new()
+    try:
+        bmesh.ops.create_cube(bm, size=1.0)
+        bmesh.ops.subdivide_edges(bm, edges=bm.edges[:], cuts=COLUMN_CUTS, use_grid_fill=True)
+        # cube [-0.5, 0.5]^3 -> the column's box in lattice-local units -> world
+        for vert in bm.verts:
+            local = Vector(tuple(vert.co[k] * 2.0 * COLUMN_HALF[k] for k in range(3)))
+            vert.co = LAT_LOC + Vector(tuple(local[k] * LAT_SCALE[k] for k in range(3)))
+        bm.to_mesh(me)
+    finally:
+        bm.free()
+    obj = bpy.data.objects.new("Column", me)
+    scene.collection.objects.link(obj)
+    mod = obj.modifiers.new("Lattice", 'LATTICE')
+    mod.object = lat_obj
+    return obj, lat_obj
+
+
+def evaluated_world_coords(obj):
+    deps = bpy.context.evaluated_depsgraph_get()
+    ev = obj.evaluated_get(deps)
+    me = ev.to_mesh()
+    try:
+        mw = ev.matrix_world
+        return [mw @ v.co for v in me.vertices]
+    finally:
+        ev.to_mesh_clear()
+
+
+def trilinear(lat_obj, corners, world_rest):
+    """Closed form, independent of Blender's deform code: normalized rest
+    coordinates in lattice space, then the trilinear blend of the deformed
+    corners, mapped back to world."""
+    local = lat_obj.matrix_world.inverted() @ world_rest
+    u, v, w = (local[k] + 0.5 for k in range(3))
+    out = Vector((0.0, 0.0, 0.0))
+    for (i, j, k), co in corners.items():
+        weight = (u if i else 1 - u) * (v if j else 1 - v) * (w if k else 1 - w)
+        out += weight * co
+    return lat_obj.matrix_world @ out
+
+
+def check(obj, lat_obj):
+    bpy.context.view_layer.update()
+    rest = [obj.matrix_world @ v.co for v in obj.data.vertices]
+
+    # 3: an undeformed lattice is the identity
+    ident = evaluated_world_coords(obj)
+    err0 = max((a - b).length for a, b in zip(ident, rest))
+    if err0 > TOL:
+        print(f"ERROR: undeformed lattice moved the mesh (max {err0:.3e} > {TOL:.0e})",
+              file=sys.stderr)
+        return 3
+
+    lat = lat_obj.data
+    for (i, j, k), off in MOVES.items():
+        pt = lat.points[corner_index(i, j, k)]
+        pt.co_deform = Vector(pt.co) + off
+    corners = {(i, j, k): Vector(lat.points[corner_index(i, j, k)].co_deform)
+               for i in (0, 1) for j in (0, 1) for k in (0, 1)}
+    lat.update_tag()
+    obj.update_tag()
+    bpy.context.view_layer.update()
+
+    # 4: every vertex on the trilinear closed form
+    got = evaluated_world_coords(obj)
+    if len(got) != len(rest):
+        print(f"ERROR: vertex count changed {len(rest)} -> {len(got)}", file=sys.stderr)
+        return 4
+    errs = [(g - trilinear(lat_obj, corners, r)).length for g, r in zip(got, rest)]
+    worst = max(range(len(errs)), key=errs.__getitem__)
+    interp = (lat.interpolation_type_u, lat.interpolation_type_v, lat.interpolation_type_w)
+    if errs[worst] > TOL:
+        print(f"ERROR: {sum(e > TOL for e in errs)}/{len(errs)} verts off the trilinear "
+              f"closed form; max {errs[worst]:.4f} at vert {worst} (interpolation {interp})",
+              file=sys.stderr)
+        return 4
+
+    # 5: the witness moved the mesh by a real amount
+    disp = max((g - r).length for g, r in zip(got, rest))
+    if disp < MIN_DISPLACEMENT:
+        print(f"ERROR: max displacement {disp:.4f} < {MIN_DISPLACEMENT}", file=sys.stderr)
+        return 5
+
+    print(f"lattice 2x2x2 {interp}: identity max {err0:.2e}; {len(errs)} verts on the "
+          f"trilinear closed form, max err {errs[worst]:.2e}; max displacement {disp:.4f}")
+    return 0
+
+
+def eevee_engine_id():
+    return 'BLENDER_EEVEE' if bpy.app.version >= (5, 0, 0) else 'BLENDER_EEVEE_NEXT'
+
+
+# ---------------------------------------------------------------------------
+# Render staging only (runs after the check; never part of it)
+# ---------------------------------------------------------------------------
+
+def principled(name, base, rough, metal=0.0, noise=None, coat=0.0, emit=None):
+    mat = bpy.data.materials.new(name)
+    mat.use_nodes = True
+    nt = mat.node_tree
+    b = nt.nodes["Principled BSDF"]
+    b.inputs["Base Color"].default_value = (*base, 1.0)
+    b.inputs["Roughness"].default_value = rough
+    b.inputs["Metallic"].default_value = metal
+    if coat:
+        b.inputs["Coat Weight"].default_value = coat
+    if emit:
+        b.inputs["Emission Color"].default_value = (*emit[0], 1.0)
+        b.inputs["Emission Strength"].default_value = emit[1]
+    if noise:
+        tex = nt.nodes.new("ShaderNodeTexNoise")
+        tex.inputs["Scale"].default_value = noise
+        tex.inputs["Detail"].default_value = 8.0
+        mr = nt.nodes.new("ShaderNodeMapRange")
+        mr.inputs["To Min"].default_value = max(rough - 0.08, 0.0)
+        mr.inputs["To Max"].default_value = rough + 0.14
+        nt.links.new(tex.outputs["Fac"], mr.inputs["Value"])
+        nt.links.new(mr.outputs["Result"], b.inputs["Roughness"])
+    return mat
+
+
+def checker_ceramic():
+    """A glazed two-tone checker on the column, in Generated (rest) coordinates:
+    the squares are square before the lattice acts, so their shear and
+    stretch in the still is the deformation itself."""
+    mat = bpy.data.materials.new("CheckerGlaze")
+    mat.use_nodes = True
+    nt = mat.node_tree
+    b = nt.nodes["Principled BSDF"]
+    b.inputs["Roughness"].default_value = 0.32
+    b.inputs["Coat Weight"].default_value = 0.5
+    tc = nt.nodes.new("ShaderNodeTexCoord")
+    chk = nt.nodes.new("ShaderNodeTexChecker")
+    chk.inputs["Scale"].default_value = float(COLUMN_CUTS + 1)
+    chk.inputs["Color1"].default_value = (0.60, 0.56, 0.49, 1.0)
+    chk.inputs["Color2"].default_value = (0.10, 0.22, 0.30, 1.0)
+    nt.links.new(tc.outputs["Generated"], chk.inputs["Vector"])
+    nt.links.new(chk.outputs["Color"], b.inputs["Base Color"])
+    return mat
+
+
+def tube_mesh(name, segments, radius, sides=10):
+    """Render-only rods along line segments (lattices do not render)."""
+    me = bpy.data.meshes.new(name)
+    bm = bmesh.new()
+    try:
+        for a, b in segments:
+            axis = b - a
+            res = bmesh.ops.create_cone(bm, cap_ends=True, segments=sides,
+                                        radius1=radius, radius2=radius, depth=axis.length)
+            rot = Vector((0, 0, 1)).rotation_difference(axis.normalized()).to_matrix()
+            mid = (a + b) / 2
+            for vert in res["verts"]:
+                vert.co = rot @ vert.co + mid
+        bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
+        bm.to_mesh(me)
+    finally:
+        bm.free()
+    for p in me.polygons:
+        p.use_smooth = True
+    return me
+
+
+def sphere_mesh(name, centers, radius):
+    me = bpy.data.meshes.new(name)
+    bm = bmesh.new()
+    try:
+        for c in centers:
+            res = bmesh.ops.create_uvsphere(bm, u_segments=24, v_segments=14, radius=radius)
+            for vert in res["verts"]:
+                vert.co += c
+        bm.to_mesh(me)
+    finally:
+        bm.free()
+    for p in me.polygons:
+        p.use_smooth = True
+    return me
+
+
+def box_mesh(name, lo, hi):
+    me = bpy.data.meshes.new(name)
+    bm = bmesh.new()
+    try:
+        res = bmesh.ops.create_cube(bm, size=1.0)
+        for vert in res["verts"]:
+            vert.co = Vector(tuple(lo[k] + (vert.co[k] + 0.5) * (hi[k] - lo[k]) for k in range(3)))
+        bm.to_mesh(me)
+    finally:
+        bm.free()
+    return me
+
+
+def cage_edges(points):
+    """The 12 edges of a 2x2x2 cage given corner positions keyed (i, j, k)."""
+    edges = []
+    for i in (0, 1):
+        for j in (0, 1):
+            edges.append((points[(i, j, 0)], points[(i, j, 1)]))
+            edges.append((points[(i, 0, j)], points[(i, 1, j)]))
+            edges.append((points[(0, i, j)], points[(1, i, j)]))
+    return edges
+
+
+def render_still(obj, lat_obj, path, engine):
+    scene = bpy.context.scene
+    mw = lat_obj.matrix_world
+    lat = lat_obj.data
+    rest = {(i, j, k): mw @ Vector(lat.points[corner_index(i, j, k)].co)
+            for i in (0, 1) for j in (0, 1) for k in (0, 1)}
+    moved = {(i, j, k): mw @ Vector(lat.points[corner_index(i, j, k)].co_deform)
+             for i in (0, 1) for j in (0, 1) for k in (0, 1)}
+
+    obj.data.materials.append(checker_ceramic())
+    for p in obj.data.polygons:
+        p.use_smooth = False
+
+    steel = principled("CageSteel", (0.58, 0.60, 0.64), 0.22, metal=1.0)
+    ghost = principled("RestCage", (0.16, 0.17, 0.19), 0.6, metal=0.3)
+    orange = principled("MovedCorner", (1.0, 0.42, 0.04), 0.3,
+                        emit=((1.0, 0.45, 0.06), 1.5))
+    joint = principled("CageJoint", (0.30, 0.31, 0.34), 0.3, metal=1.0)
+    walnut = principled("Walnut", (0.13, 0.055, 0.025), 0.45, noise=40.0, coat=0.4)
+
+    parts = []
+
+    def add(name, me, mat):
+        me.materials.append(mat)
+        ob = bpy.data.objects.new(name, me)
+        scene.collection.objects.link(ob)
+        parts.append(ob)
+        return ob
+
+    add("DeformedCage", tube_mesh("DeformedCage", cage_edges(moved), 0.022), steel)
+    # the rest cage, thin and dark: what the two corners were moved away from
+    rest_only = [(a, b) for a, b in cage_edges(rest)]
+    add("RestCage", tube_mesh("RestCage", rest_only, 0.009), ghost)
+    still = [moved[key] for key in moved if key not in MOVES]
+    add("CageJoints", sphere_mesh("CageJoints", still, 0.05), joint)
+    add("MovedCorners", sphere_mesh("MovedCorners", [moved[key] for key in MOVES], 0.075),
+        orange)
+    # a travel rod from each moved corner back to its rest position
+    add("Travel", tube_mesh("Travel", [(rest[key], moved[key]) for key in MOVES], 0.012),
+        orange)
+
+    # Render-only "before" twin: the same column, unmodified, in its rest cage,
+    # one cage-width to the left, so the still reads rest -> deformed.
+    shift = Vector((-TWIN_GAP, 0.0, 0.0))
+    twin_me = obj.data.copy()
+    twin = bpy.data.objects.new("RestColumn", twin_me)
+    twin.location = shift
+    scene.collection.objects.link(twin)
+    parts.append(twin)
+    rest_twin = {key: co + shift for key, co in rest.items()}
+    add("TwinCage", tube_mesh("TwinCage", cage_edges(rest_twin), 0.022), steel)
+    add("TwinJoints", sphere_mesh("TwinJoints", list(rest_twin.values()), 0.05), joint)
+
+    lo_z = LAT_LOC.z - LAT_SCALE.z / 2
+    half_x = LAT_SCALE.x / 2 + 0.45
+    plinth = add("Plinth", box_mesh("Plinth", (-TWIN_GAP - half_x, -1.3, 0.0),
+                                    (half_x, 1.3, lo_z - 0.002)), walnut)
+    bev = plinth.modifiers.new("Chamfer", 'BEVEL')
+    bev.width = 0.03
+    bev.segments = 2
+
+    floor_me = bpy.data.meshes.new("Floor")
+    bm = bmesh.new()
+    try:
+        bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=30.0)
+        bm.to_mesh(floor_me)
+    finally:
+        bm.free()
+    fmat = bpy.data.materials.new("Studio")
+    fmat.use_nodes = True
+    fb = fmat.node_tree.nodes["Principled BSDF"]
+    fb.inputs["Base Color"].default_value = (0.03, 0.032, 0.037, 1.0)
+    fb.inputs["Roughness"].default_value = 0.7
+    floor_me.materials.append(fmat)
+    floor = bpy.data.objects.new("Floor", floor_me)
+    scene.collection.objects.link(floor)
+    wall = bpy.data.objects.new("Wall", floor_me.copy())
+    wall.location = (0.0, 7.5, 0.0)
+    wall.rotation_euler = (math.radians(90), 0.0, 0.0)
+    scene.collection.objects.link(wall)
+
+    world = bpy.data.worlds.new("World")
+    world.use_nodes = True
+    world.node_tree.nodes["Background"].inputs["Color"].default_value = (0.02, 0.021, 0.025, 1.0)
+    scene.world = world
+
+    centre = Vector((-TWIN_GAP / 2, 0.0, LAT_LOC.z))
+
+    def light(name, loc, energy, size, col, aim):
+        ld = bpy.data.lights.new(name, 'AREA')
+        ld.energy = energy; ld.size = size; ld.color = col
+        ob = bpy.data.objects.new(name, ld)
+        ob.location = loc
+        ob.rotation_euler = (Vector(aim) - Vector(loc)).to_track_quat('-Z', 'Y').to_euler()
+        scene.collection.objects.link(ob)
+
+    light("Key", (-4.5, -5.0, 6.5), 520.0, 4.0, (1.0, 0.96, 0.9), centre)
+    light("Fill", (5.5, -4.5, 2.5), 110.0, 7.0, (0.75, 0.85, 1.0), centre)
+    light("Rim", (1.5, 4.0, 6.0), 380.0, 3.0, (0.6, 0.78, 1.0), centre)
+    light("Wedge", (2.5, 4.5, 3.0), 420.0, 5.0, (1.0, 0.76, 0.5), (4.5, 7.5, 1.0))
+
+    cam_data = bpy.data.cameras.new("Cam")
+    cam_data.lens = 50.0
+    cam = bpy.data.objects.new("Cam", cam_data)
+    cam.location = (centre.x + 3.6, -9.6, 3.9)
+    scene.collection.objects.link(cam)
+    aim = bpy.data.objects.new("Aim", None)
+    aim.location = centre + Vector((0.05, 0.0, -0.15))
+    scene.collection.objects.link(aim)
+    tr = cam.constraints.new('TRACK_TO')
+    tr.target = aim
+    tr.track_axis = 'TRACK_NEGATIVE_Z'
+    tr.up_axis = 'UP_Y'
+    scene.camera = cam
+
+    scene.render.engine = 'CYCLES' if engine == 'cycles' else eevee_engine_id()
+    if engine == 'cycles':
+        scene.cycles.samples = 48
+    else:
+        try:
+            scene.eevee.taa_render_samples = 64
+        except AttributeError:
+            pass
+    scene.render.resolution_x = 1280
+    scene.render.resolution_y = 720
+    scene.render.image_settings.file_format = 'PNG'
+    scene.render.filepath = path
+    # AgX would wash the glaze and the orange accent toward pastel (docs/VISUAL-STYLE.md)
+    scene.view_settings.view_transform = 'Standard'
+    bpy.context.view_layer.update()
+    # Layer 1 framing gate (silhouette matte) — exit 10 on violation, before
+    # the beauty render so a defective composition ships no artifact
+    fcode = gallery_framing.check_framing(
+        scene, cam,
+        hero=[obj] + parts,
+        elements=[obj] + parts,
+        stage=[floor, wall],
+    )
+    if fcode:
+        return fcode
+    bpy.ops.render.render(write_still=True)
+    if not (os.path.exists(path) and os.path.getsize(path) > 0):
+        print("ERROR: render produced no file", file=sys.stderr)
+        return 6
+    return 0
+
+
+def main():
+    argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+    p = argparse.ArgumentParser()
+    p.add_argument("--output", default=None, help="optional: render a still PNG here")
+    p.add_argument("--engine", default="eevee", choices=("eevee", "cycles"),
+                   help="render engine for --output (cycles for GPU-less hosts)")
+    p.add_argument("--bspline", action="store_true",
+                   help="keep the default KEY_BSPLINE interpolation (must fail)")
+    args = p.parse_args(argv)
+
+    obj, lat_obj = build_scene(bspline=args.bspline)
+    code = check(obj, lat_obj)
+    if code:
+        return code
+
+    if args.output:
+        rcode = render_still(obj, lat_obj, os.path.abspath(args.output), args.engine)
+        if rcode:
+            return rcode
+        print(f"rendered still {args.output}")
+
+    print("lattice-deform OK")
+    return 0
+
+
+if __name__ == "__main__":
+    try:
+        sys.exit(main())
+    except Exception as e:
+        import traceback; traceback.print_exc(); print(f"FATAL: {e}", file=sys.stderr); sys.exit(1)
+
+
+
+ + +
+ + + Two checker-glazed columns on a walnut plinth, each in a steel-rod cage: the left upright in its rest cage, the right sheared and tapered where two orange cage corners have been pulled out. + + +

+ + + diff --git a/docs/gallery/light-link-studio/index.html b/docs/gallery/light-link-studio/index.html index 7d24c34f..4ece87b2 100644 --- a/docs/gallery/light-link-studio/index.html +++ b/docs/gallery/light-link-studio/index.html @@ -45,7 +45,7 @@

Light Link Studio

One key, one hero: a light linked to a receiver collection lights only the hero, proven by two pixel renders in one pass. Linked: 3.6x luminance ratio; unlinked in the same check: the decoy rises 233% while the hero holds at 0.3% drift.

- + @@ -1170,7 +1170,7 @@

Parent Inverse Orrery

- + diff --git a/docs/gallery/lightmap-uv-channel/index.html b/docs/gallery/lightmap-uv-channel/index.html index 0d096e76..c566d8a2 100644 --- a/docs/gallery/lightmap-uv-channel/index.html +++ b/docs/gallery/lightmap-uv-channel/index.html @@ -45,7 +45,7 @@

Lightmap UV Channel

A market cart carrying the two-channel UV contract for baked lighting: UV0 untouched, UVLight packed with no overlaps and a respected margin.

- + @@ -2154,7 +2154,7 @@

Compositor Glare

- + diff --git a/docs/gallery/lod-decimate-chain/index.html b/docs/gallery/lod-decimate-chain/index.html index f61afe37..6c984dd3 100644 --- a/docs/gallery/lod-decimate-chain/index.html +++ b/docs/gallery/lod-decimate-chain/index.html @@ -45,7 +45,7 @@

LOD Decimate Chain

A retro rocket at LOD0/1/2 via the Decimate modifier evaluated through the depsgraph, with a wireframe of each evaluated mesh. The check proves the reduction is non-destructive, the triangle count hits ratio x base within bounds, and silhouette-critical dimensions survive.

- + @@ -1364,34 +1364,34 @@ - +
diff --git a/docs/gallery/mesh-hygiene-audit/index.html b/docs/gallery/mesh-hygiene-audit/index.html index 70119bce..d1cce2ef 100644 --- a/docs/gallery/mesh-hygiene-audit/index.html +++ b/docs/gallery/mesh-hygiene-audit/index.html @@ -45,7 +45,7 @@

Mesh Hygiene Audit

Engine-ingest mesh hygiene on every part of a flanged street valve: no ngons, no loose verts, manifold edges, no zero-area faces, contiguous and outward winding, Euler V-E+F==2 on the body casting. A dirty copy carries a hole, a flipped patch, an ngon and loose verts, each marked from live audit incidence; the paint glows red wherever the renderer sees a back face.

- + @@ -1584,7 +1584,7 @@

BMesh Gear

- +
diff --git a/docs/gallery/modular-kit-snap/index.html b/docs/gallery/modular-kit-snap/index.html index 8cbd0bff..4c22e1ec 100644 --- a/docs/gallery/modular-kit-snap/index.html +++ b/docs/gallery/modular-kit-snap/index.html @@ -45,7 +45,7 @@

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.

- + @@ -1675,7 +1675,7 @@

Socket Attach Points< - +

diff --git a/docs/gallery/parent-inverse-orrery/index.html b/docs/gallery/parent-inverse-orrery/index.html index 8a958bc4..d86178e7 100644 --- a/docs/gallery/parent-inverse-orrery/index.html +++ b/docs/gallery/parent-inverse-orrery/index.html @@ -45,7 +45,7 @@

Parent Inverse Orrery

Data-API parenting for a brass orrery — the keep-world idiom (child.parent = pivot; child.matrix_parent_inverse = pivot.matrix_world.inverted()) carrying arms, planets, and a two-level moon through spinning pivots.

- + @@ -1006,34 +1006,34 @@ - +
diff --git a/docs/gallery/png-exr-alpha/index.html b/docs/gallery/png-exr-alpha/index.html index 08b38b43..3a1e0ec7 100644 --- a/docs/gallery/png-exr-alpha/index.html +++ b/docs/gallery/png-exr-alpha/index.html @@ -45,7 +45,7 @@

PNG EXR Alpha

Float-image PNG save trap — float_buffer=True Image.save() writes RGBA16 and unpremultiplies as if associated-alpha, clamping straight-authored dark values at low alpha to white (closed-form err 0.98 at RGB 0.02 / a=1/255).

- + @@ -1579,7 +1579,7 @@

Compositor Glare

- +
diff --git a/docs/gallery/prop-origin-transform/index.html b/docs/gallery/prop-origin-transform/index.html index 183911f0..a863af4b 100644 --- a/docs/gallery/prop-origin-transform/index.html +++ b/docs/gallery/prop-origin-transform/index.html @@ -45,7 +45,7 @@

Prop Origin Transform

Street pedestal origin-to-base-center + data-API scale apply + matrix_parent_inverse for a flanged conduit elbow. After bake: scale (1,1,1), local min.z==0, world AABB unchanged. Bare parent throws the elbow off its mount; MPI keeps it seated.

- + @@ -1715,7 +1715,7 @@

Mesh Hygiene Audit

- +
diff --git a/docs/gallery/ray-cast-space/index.html b/docs/gallery/ray-cast-space/index.html new file mode 100644 index 00000000..9cc5238b --- /dev/null +++ b/docs/gallery/ray-cast-space/index.html @@ -0,0 +1,1262 @@ + + + + + + Ray Cast Space (ray-cast-space) — Examples — Blender Developer Tools + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +

Ray Cast Space

+

examples/ray-cast-space/

+

Object.ray_cast is object-local while Scene.ray_cast is world space: rays mapped through matrix_world.inverted() (directions by its 3x3 only) hit the same points both ways, and raw world coords handed to Object.ray_cast miss.

+
+
+ + +

Rendered headless by the example itself. Select it to enlarge.

+
witnesses Five closed-form rays on a translated, Z-rotated, non-uniformly scaled block: Scene.ray_cast hits each world point and normal exactly; Object.ray_cast fed matrix_world.inverted() coordinates hits the same polygons, and mapped back lands within 5e-7 m; world coords fed to Object.ray_cast land 0.287 m or more off. --world-to-object exits 4 (1.125 m error).
+

tags objects transforms depsgraph

+
+
blender --background --python examples/ray-cast-space/ray_cast_space.py --
+ +
+
+

A runnable example of the coordinate-space contract behind Blender's two ray casts, the one AI-written code gets wrong most often. Scene.ray_cast(depsgraph, origin, direction) takes and returns world space. Object.ray_cast(origin, direction) takes and returns the object's local space. Feed world coordinates to Object.ray_cast and nothing raises: it quietly misses, or hits the wrong spot.

+

What it witnesses: a target block carries a transform with every ingredient that separates the two spaces: a translation, a 32° turn about Z, and non-uniform scale (1.55 × 0.62 × 0.62). The example casts five rays at closed-form points on three of its faces, arriving obliquely, and checks each one three ways:

+
  1. Scene.ray_cast hits the closed-form world point (to 1e-4 m). Its normal matches the face's world normal, which comes from the inverse-transpose of matrix_world.
  2. Object.ray_cast is fed the origin through matrix_world.inverted() and the direction through that matrix's 3×3 part only, because directions do not translate. It must hit the same polygon. Its local hit point, mapped back through matrix_world (and its normal through the inverse-transpose), must land on the same world point and normal.
  3. The trap must bite on this setup. The same world origin and direction handed straight to Object.ray_cast either misses or lands at least 0.25 m from the true hit. Without this, the check could pass by coincidence.
+

Both 5.2 LTS and 4.5 LTS give identical results: every hit exact to under 1e-6 m, and the world-coordinate trap's closest landing 0.287 m away.

+

The still shows the block glazed in a teal checker laid out in object coordinates. The cells are square in local space, so the non-uniform scale stretches them into the block's own grid. The block stands on a walnut plinth. Five orange rays run from brass emitter balls to orange hit rings that sit exactly on three faces: the correct casts. One red ray is the first front-face ray's world origin and direction read by Object.ray_cast as if local. In the world that is the ray matrix_world @ origin along matrix_world.to_3x3() @ direction. It starts somewhere else entirely and strikes the far side of the block. A render-only Bevel modifier rounds the block's edges after the check has run.

+

Run#

+
# Cheap correctness check (no render) — the CI check:
+blender --background --python ray_cast_space.py --
+
+# Falsifier: feed WORLD coords to Object.ray_cast in the checked path. Must exit 4.
+blender --background --python ray_cast_space.py -- --world-to-object
+
+# Also render a still (EEVEE on a GPU host; use --engine cycles on GPU-less hosts):
+blender --background --python ray_cast_space.py -- --output ray.png
+blender --background --python ray_cast_space.py -- --output ray.png --engine cycles
+

--world-to-object measured on 5.2.1 and 4.5.11: Object.ray_cast ray 0 mapped back to (1.5668, 1.22769, 1.38161), error 1.1253 m (normal error 1.0000, polygon 2 vs Scene 3). The cast hit a different face of the block, a metre from the true point.

+

Exit codes#

+
CodeMeaning
0Success
1Uncaught exception (FATAL wrapper)
2argparse / usage
3Scene.ray_cast missed, hit another object, or hit off the closed-form world point or normal
4Object.ray_cast missed, or its local hit mapped back by matrix_world disagrees with the world point, normal or polygon (--world-to-object lands here)
5The world-coordinate trap did not bite: world coords fed to Object.ray_cast landed within TRAP_MIN of a true hit
6--output produced no file
10--output framing violation (Layer 1 fill / margin gate, gallery_framing)
+

The blender-smoke workflow runs the check on Blender 5.2 LTS and 4.5 LTS (5.1 on the weekly cron, the needs-5.1 PR label, or manual dispatch). Smoke does not pass --output or --world-to-object.

+
+
+

Source

+
+ examples/ray-cast-space/ray_cast_space.py + 476 lines · View on GitHub → +
+
+
"""Object.ray_cast is object-local, Scene.ray_cast is world space — a runnable example.
+
+Witnesses the coordinate-space contract of the two ray casts, the one AI code
+gets wrong most often: ``Scene.ray_cast(depsgraph, origin, direction)`` takes
+and returns WORLD space, while ``Object.ray_cast(origin, direction)`` takes
+and returns the object's LOCAL space. A target block carries a non-trivial
+transform (translation, a turn about Z, non-uniform scale). Five rays aimed at
+closed-form points on three of its faces are cast both ways:
+
+- ``Scene.ray_cast`` must hit each closed-form world point, with the face's
+  world normal (inverse-transpose of the object matrix) and the target object;
+- ``Object.ray_cast``, fed the origin through ``matrix_world.inverted()`` and
+  the direction through its 3x3 part only (directions do not translate), must
+  hit the same polygon, and its local hit point mapped back by
+  ``matrix_world`` (normal by the inverse-transpose) must land on the same
+  world point and normal;
+- the trap: the same WORLD origin/direction handed straight to
+  ``Object.ray_cast`` must NOT reproduce the hit — every such cast misses or
+  lands at least ``TRAP_MIN`` away, so the check proves the transform matters
+  on this setup rather than passing by coincidence.
+
+``--world-to-object`` feeds world coordinates to ``Object.ray_cast`` in the
+checked path (the bug); the local-hit check catches it (exit 4) and prints
+the measured error.
+
+By default it runs only the correctness check (no render) — the CI smoke
+check. Pass --output to also render a still:
+
+    blender --background --python ray_cast_space.py --                       # check only
+    blender --background --python ray_cast_space.py -- --world-to-object     # must fail
+    blender --background --python ray_cast_space.py -- --output r.png        # + render
+"""
+import bpy, bmesh, sys, os, math, argparse
+from mathutils import Vector, Matrix
+
+# Shared Layer 1 framing measurement (render path only) — see gallery_framing.py
+sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir))
+sys.dont_write_bytecode = True  # keep examples/__pycache__ out of the repo tree
+import gallery_framing
+
+# The target: a unit-half-size cube (local coords in [-1, 1]^3) under a
+# transform with every ingredient that separates local from world space.
+TARGET_LOC = (0.35, 0.25, 0.80)
+TARGET_ROT_Z = math.radians(32.0)
+TARGET_SCALE = (1.55, 0.62, 0.62)
+
+# Closed-form hit points, authored in LOCAL face coordinates, plus a tangent
+# tilt so the rays arrive obliquely rather than straight down each normal.
+# (face axis, face sign, local point on that face, tilt in local tangent space)
+RAYS = (
+    ("y", -1, (0.55, -1.0, 0.35), (0.35, 0.0, 0.25)),
+    ("y", -1, (-0.45, -1.0, -0.30), (-0.30, 0.0, 0.20)),
+    ("z", +1, (0.40, 0.30, 1.0), (0.25, -0.35, 0.0)),
+    ("z", +1, (-0.60, -0.40, 1.0), (-0.20, -0.30, 0.0)),
+    ("x", -1, (-1.0, -0.35, 0.30), (0.0, -0.30, 0.25)),
+)
+RAY_LEN = 1.7        # world distance from each ray origin to its hit
+POS_TOL = 1e-4       # world-space hit tolerance
+NRM_TOL = 1e-4       # 1 - dot(normal, expected)
+TRAP_MIN = 0.25      # a world-coord Object.ray_cast must miss or land this far off
+
+
+def build_target():
+    bpy.ops.wm.read_factory_settings(use_empty=True)
+    me = bpy.data.meshes.new("TargetBlock")
+    bm = bmesh.new()
+    try:
+        bmesh.ops.create_cube(bm, size=2.0)
+        bm.to_mesh(me)
+    finally:
+        bm.free()
+    obj = bpy.data.objects.new("TargetBlock", me)
+    bpy.context.collection.objects.link(obj)
+    obj.location = TARGET_LOC
+    obj.rotation_euler = (0.0, 0.0, TARGET_ROT_Z)
+    obj.scale = TARGET_SCALE
+    bpy.context.view_layer.update()
+    return obj
+
+
+def world_rays(obj):
+    """Closed-form world rays: (origin, direction, hit point, face normal).
+
+    The hit point is the local face point through matrix_world; the world
+    normal is the local face normal through the inverse-transpose 3x3. The
+    origin sits RAY_LEN back along the (tilted) incoming direction, in the
+    face's outer half-space, so on this convex block the first surface the
+    ray meets is that face at that point.
+    """
+    mw = obj.matrix_world
+    n_mat = mw.to_3x3().inverted().transposed()
+    out = []
+    for axis, sign, p_local, tilt in RAYS:
+        n_local = Vector((0.0, 0.0, 0.0))
+        n_local["xyz".index(axis)] = sign
+        p = mw @ Vector(p_local)
+        n = (n_mat @ n_local).normalized()
+        incoming = (n_local + Vector(tilt))       # outward-ish, in local space
+        d = -(mw.to_3x3() @ incoming).normalized()
+        if d.dot(n) >= 0.0:
+            raise ValueError(f"ray at {p_local} does not approach its face from outside")
+        out.append((p - RAY_LEN * d, d, p, n))
+    return out
+
+
+def object_space(obj, origin, direction):
+    """World ray -> the object's local space: the origin through the full
+    inverse matrix, the direction through its 3x3 only (no translation)."""
+    inv = obj.matrix_world.inverted()
+    return inv @ origin, (inv.to_3x3() @ direction).normalized()
+
+
+def check(obj, world_to_object=False):
+    dg = bpy.context.evaluated_depsgraph_get()
+    scene = bpy.context.scene
+    mw = obj.matrix_world
+    n_mat = mw.to_3x3().inverted().transposed()
+    rays = world_rays(obj)
+
+    # 1. Scene.ray_cast: world in, world out
+    scene_hits = []
+    for k, (o, d, p, n) in enumerate(rays):
+        ok, loc, nrm, idx, hit_ob, _m = scene.ray_cast(dg, o, d)
+        if not ok or hit_ob is None or hit_ob.name != obj.name:
+            print(f"ERROR: Scene.ray_cast ray {k} missed the target", file=sys.stderr)
+            return 3
+        err, nerr = (loc - p).length, 1.0 - nrm.normalized().dot(n)
+        if err > POS_TOL or nerr > NRM_TOL:
+            print(f"ERROR: Scene.ray_cast ray {k} hit {tuple(round(c, 5) for c in loc)} "
+                  f"(error {err:.6f} m, normal error {nerr:.6f}) vs closed form "
+                  f"{tuple(round(c, 5) for c in p)}", file=sys.stderr)
+            return 3
+        scene_hits.append(idx)
+
+    # 2. Object.ray_cast: local in, local out — map both ways
+    worst = 0.0
+    for k, (o, d, p, n) in enumerate(rays):
+        if world_to_object:
+            lo, ld = o, d                      # the bug: world coords as if local
+        else:
+            lo, ld = object_space(obj, o, d)
+        ok, loc, nrm, idx = obj.ray_cast(lo, ld, depsgraph=dg)
+        if not ok:
+            print(f"ERROR: Object.ray_cast ray {k} missed (origin/direction not in "
+                  f"object space?)", file=sys.stderr)
+            return 4
+        p_back = mw @ loc
+        n_back = (n_mat @ nrm).normalized()
+        err, nerr = (p_back - p).length, 1.0 - n_back.dot(n)
+        worst = max(worst, err)
+        if err > POS_TOL or nerr > NRM_TOL or idx != scene_hits[k]:
+            print(f"ERROR: Object.ray_cast ray {k} mapped back to "
+                  f"{tuple(round(c, 5) for c in p_back)}, error {err:.4f} m "
+                  f"(normal error {nerr:.4f}, polygon {idx} vs Scene {scene_hits[k]})",
+                  file=sys.stderr)
+            return 4
+
+    # 3. The trap must actually bite on this setup
+    trap_min = math.inf
+    for k, (o, d, p, n) in enumerate(rays):
+        ok, loc, _nrm, _idx = obj.ray_cast(o, d, depsgraph=dg)
+        dev = (mw @ loc - p).length if ok else math.inf
+        trap_min = min(trap_min, dev)
+    if trap_min < TRAP_MIN:
+        print(f"ERROR: world coords fed to Object.ray_cast landed only {trap_min:.4f} m "
+              f"from a true hit (< {TRAP_MIN}); the transform does not separate the "
+              f"spaces", file=sys.stderr)
+        return 5
+
+    trap_txt = "all miss" if trap_min == math.inf else f"closest {trap_min:.3f} m off"
+    print(f"rays={len(rays)} scene_hits=exact object_local_hits=exact "
+          f"max_mapped_error={worst:.2e} m world_coords_trap={trap_txt}")
+    return 0
+
+
+def eevee_engine_id():
+    return 'BLENDER_EEVEE' if bpy.app.version >= (5, 0, 0) else 'BLENDER_EEVEE_NEXT'
+
+
+# --------------------------------------------------------------------------
+# Render staging only (not part of the check)
+# --------------------------------------------------------------------------
+
+def principled(name, base, rough, metal=0.0, emit=None, strength=0.0, alpha=1.0):
+    mat = bpy.data.materials.new(name)
+    mat.use_nodes = True
+    b = mat.node_tree.nodes["Principled BSDF"]
+    b.inputs["Base Color"].default_value = (*base, 1.0)
+    b.inputs["Roughness"].default_value = rough
+    b.inputs["Metallic"].default_value = metal
+    if emit is not None:
+        b.inputs["Emission Color"].default_value = (*emit, 1.0)
+        b.inputs["Emission Strength"].default_value = strength
+    if alpha < 1.0:
+        b.inputs["Alpha"].default_value = alpha
+        try:
+            mat.surface_render_method = 'BLENDED'
+        except AttributeError:
+            pass
+    return mat
+
+
+def block_material():
+    """Glazed teal ceramic with an OBJECT-space checker: the cells are square
+    in local space, so the non-uniform scale stretches them into the
+    rectangles the eye reads as 'this object has its own coordinates'. Teal
+    sits opposite the orange rays, so every hit marker reads at thumbnail size."""
+    mat = bpy.data.materials.new("LocalSpaceCeramic")
+    mat.use_nodes = True
+    nt = mat.node_tree
+    b = nt.nodes["Principled BSDF"]
+    b.inputs["Roughness"].default_value = 0.32
+    b.inputs["Coat Weight"].default_value = 0.35
+    coords = nt.nodes.new("ShaderNodeTexCoord")
+    chk = nt.nodes.new("ShaderNodeTexChecker")
+    chk.inputs["Scale"].default_value = 4.0
+    chk.inputs["Color1"].default_value = (0.09, 0.36, 0.40, 1.0)
+    chk.inputs["Color2"].default_value = (0.035, 0.15, 0.18, 1.0)
+    # Object coords span -1..1; shift to 0..2 so cells line up with face edges
+    add = nt.nodes.new("ShaderNodeVectorMath")
+    add.operation = 'ADD'
+    add.inputs[1].default_value = (1.0, 1.0, 1.0)
+    nt.links.new(coords.outputs["Object"], add.inputs[0])
+    nt.links.new(add.outputs["Vector"], chk.inputs["Vector"])
+    nt.links.new(chk.outputs["Color"], b.inputs["Base Color"])
+    return mat
+
+
+def rod(name, a, b, radius, mat, segs=16):
+    """A thin cylinder from a to b (render-only ray segment)."""
+    me = bpy.data.meshes.new(name)
+    bm = bmesh.new()
+    try:
+        length = (b - a).length
+        bmesh.ops.create_cone(bm, cap_ends=True, segments=segs, radius1=radius,
+                              radius2=radius, depth=length)
+        bm.to_mesh(me)
+    finally:
+        bm.free()
+    me.materials.append(mat)
+    for poly in me.polygons:
+        poly.use_smooth = True
+    ob = bpy.data.objects.new(name, me)
+    bpy.context.scene.collection.objects.link(ob)
+    ob.location = (a + b) / 2
+    ob.rotation_euler = (b - a).to_track_quat('Z', 'Y').to_euler()
+    return ob
+
+
+def sphere(name, at, radius, mat):
+    me = bpy.data.meshes.new(name)
+    bm = bmesh.new()
+    try:
+        bmesh.ops.create_uvsphere(bm, u_segments=24, v_segments=12, radius=radius)
+        bm.to_mesh(me)
+    finally:
+        bm.free()
+    me.materials.append(mat)
+    for poly in me.polygons:
+        poly.use_smooth = True
+    ob = bpy.data.objects.new(name, me)
+    bpy.context.scene.collection.objects.link(ob)
+    ob.location = at
+    return ob
+
+
+def ring(name, at, normal, r_out, r_in, mat):
+    """A flat hit-marker annulus lying on the surface, facing out along normal."""
+    me = bpy.data.meshes.new(name)
+    bm = bmesh.new()
+    try:
+        segs = 32
+        outer = [bm.verts.new((r_out * math.cos(2 * math.pi * i / segs),
+                               r_out * math.sin(2 * math.pi * i / segs), 0.0))
+                 for i in range(segs)]
+        inner = [bm.verts.new((r_in * math.cos(2 * math.pi * i / segs),
+                               r_in * math.sin(2 * math.pi * i / segs), 0.0))
+                 for i in range(segs)]
+        for i in range(segs):
+            j = (i + 1) % segs
+            bm.faces.new((outer[i], outer[j], inner[j], inner[i]))
+        ext = bmesh.ops.extrude_face_region(bm, geom=list(bm.faces))
+        top = [e for e in ext["geom"] if isinstance(e, bmesh.types.BMVert)]
+        bmesh.ops.translate(bm, verts=top, vec=(0.0, 0.0, 0.006))
+        bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
+        bm.to_mesh(me)
+    finally:
+        bm.free()
+    me.materials.append(mat)
+    ob = bpy.data.objects.new(name, me)
+    bpy.context.scene.collection.objects.link(ob)
+    ob.location = at + normal * 0.002
+    ob.rotation_euler = normal.to_track_quat('Z', 'Y').to_euler()
+    return ob
+
+
+def render_still(obj, path, engine):
+    scene = bpy.context.scene
+    dg = bpy.context.evaluated_depsgraph_get()
+    rays = world_rays(obj)
+    # one ghosted trap ray: the first front-face ray's WORLD origin/direction
+    # read by Object.ray_cast as if local. In the world that is the ray
+    # matrix_world @ o along matrix_world.to_3x3() @ d; cast it before any
+    # render-only modifier changes the evaluated mesh.
+    mw = obj.matrix_world
+    o, d, p, n = rays[0]
+    t_o = mw @ o
+    t_d = (mw.to_3x3() @ d).normalized()
+    t_ok, t_loc, _n, _i = obj.ray_cast(o, d, depsgraph=dg)
+    t_end = (mw @ t_loc) if t_ok else (t_o + 3.0 * t_d)
+    obj.data.materials.append(block_material())
+    bev = obj.modifiers.new("Chamfer", 'BEVEL')   # render-only, after the check
+    bev.width = 0.025
+    bev.segments = 3
+    bev.affect = 'EDGES'
+
+    # emission kept under clipping in Standard view, so the beams stay orange
+    beam = principled("RayBeam", (1.0, 0.26, 0.02), 0.3, emit=(1.0, 0.26, 0.02), strength=1.4)
+    hit_mat = principled("HitMarker", (1.0, 0.36, 0.04), 0.25, emit=(1.0, 0.36, 0.04),
+                         strength=1.8)
+    emitter = principled("RayEmitter", (0.85, 0.58, 0.24), 0.38, metal=1.0)
+    trap_beam = principled("TrapBeam", (0.9, 0.12, 0.18), 0.4, emit=(1.0, 0.1, 0.16),
+                           strength=1.2)
+    trap_end = principled("TrapEnd", (0.9, 0.12, 0.18), 0.35, emit=(1.0, 0.1, 0.16),
+                          strength=1.5)
+    plinth_mat = principled("PlinthWalnut", (0.13, 0.055, 0.025), 0.45)
+
+    shown = [obj]
+    for k, (o, d, p, n) in enumerate(rays):
+        shown.append(rod(f"Ray{k}", o, p, 0.022, beam))
+        shown.append(sphere(f"Emitter{k}", o, 0.07, emitter))
+        shown.append(ring(f"Hit{k}", p, n, 0.10, 0.045, hit_mat))
+
+    trap = [rod("TrapRay", t_o, t_end, 0.016, trap_beam),
+            sphere("TrapEmitter", t_o, 0.06, trap_end)]
+    if not t_ok:
+        trap.append(sphere("TrapMissEnd", t_end, 0.03, trap_end))
+
+    # a low walnut plinth the block stands on (block bottom at z = loc - scale)
+    base_z = TARGET_LOC[2] - TARGET_SCALE[2]
+    pme = bpy.data.meshes.new("Plinth")
+    bm = bmesh.new()
+    try:
+        res = bmesh.ops.create_cone(bm, cap_ends=True, segments=64, radius1=1.9,
+                                    radius2=1.9, depth=base_z)
+        for v in res["verts"]:
+            v.co.z += base_z / 2
+        bm.to_mesh(pme)
+    finally:
+        bm.free()
+    pme.materials.append(plinth_mat)
+    for poly in pme.polygons:
+        poly.use_smooth = True
+    plinth = bpy.data.objects.new("Plinth", pme)
+    scene.collection.objects.link(plinth)
+    plinth.location = (TARGET_LOC[0], TARGET_LOC[1], 0.0)
+    pb = plinth.modifiers.new("Chamfer", 'BEVEL')
+    pb.width = 0.02
+    pb.segments = 3
+    pb.limit_method = 'ANGLE'
+
+    floor_me = bpy.data.meshes.new("Floor")
+    bm = bmesh.new()
+    try:
+        bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=30.0)
+        bm.to_mesh(floor_me)
+    finally:
+        bm.free()
+    fmat = bpy.data.materials.new("Studio")
+    fmat.use_nodes = True
+    fb = fmat.node_tree.nodes["Principled BSDF"]
+    fb.inputs["Base Color"].default_value = (0.03, 0.032, 0.037, 1.0)
+    fb.inputs["Roughness"].default_value = 0.7
+    floor_me.materials.append(fmat)
+    floor = bpy.data.objects.new("Floor", floor_me)
+    scene.collection.objects.link(floor)
+    wall = bpy.data.objects.new("Wall", floor_me.copy())
+    wall.location = (0.0, 7.5, 0.0)
+    wall.rotation_euler = (math.radians(90), 0.0, 0.0)
+    scene.collection.objects.link(wall)
+
+    world = bpy.data.worlds.new("World")
+    world.use_nodes = True
+    world.node_tree.nodes["Background"].inputs["Color"].default_value = (0.02, 0.021, 0.025, 1.0)
+    scene.world = world
+
+    centre = Vector((TARGET_LOC[0], TARGET_LOC[1], 1.05))
+
+    def light(name, loc, energy, size, col, aim):
+        ld = bpy.data.lights.new(name, 'AREA')
+        ld.energy = energy; ld.size = size; ld.color = col
+        ob = bpy.data.objects.new(name, ld)
+        ob.location = loc
+        ob.rotation_euler = (Vector(aim) - Vector(loc)).to_track_quat('-Z', 'Y').to_euler()
+        scene.collection.objects.link(ob)
+
+    light("Key", (-4.0, -5.0, 6.0), 520.0, 4.0, (1.0, 0.96, 0.9), centre)
+    light("Fill", (5.5, -4.0, 2.5), 110.0, 6.0, (0.75, 0.85, 1.0), centre)
+    light("Rim", (-1.0, 5.0, 6.0), 320.0, 3.0, (0.6, 0.78, 1.0), centre)
+    light("Wedge", (2.5, 4.0, 3.0), 420.0, 5.0, (1.0, 0.76, 0.5), (4.0, 7.5, 1.0))
+
+    cam_data = bpy.data.cameras.new("Cam")
+    cam_data.lens = 50.0
+    cam = bpy.data.objects.new("Cam", cam_data)
+    cam.location = centre + 1.15 * Vector((-5.2, -8.6, 4.4))
+    scene.collection.objects.link(cam)
+    aim = bpy.data.objects.new("Aim", None)
+    aim.location = centre
+    scene.collection.objects.link(aim)
+    tr = cam.constraints.new('TRACK_TO')
+    tr.target = aim
+    tr.track_axis = 'TRACK_NEGATIVE_Z'
+    tr.up_axis = 'UP_Y'
+    scene.camera = cam
+
+    scene.render.engine = 'CYCLES' if engine == 'cycles' else eevee_engine_id()
+    if engine == 'cycles':
+        scene.cycles.samples = 48
+    else:
+        try:
+            scene.eevee.taa_render_samples = 64
+        except AttributeError:
+            pass
+    scene.render.resolution_x = 1280
+    scene.render.resolution_y = 720
+    scene.render.image_settings.file_format = 'PNG'
+    scene.render.filepath = path
+    # AgX would wash the emissive orange rays toward pastel (docs/VISUAL-STYLE.md)
+    scene.view_settings.view_transform = 'Standard'
+    bpy.context.view_layer.update()
+    # Layer 1 framing gate (silhouette matte) — exit 10 on violation
+    fcode = gallery_framing.check_framing(
+        scene, cam,
+        hero=shown + [plinth],
+        elements=shown + trap + [plinth],
+        stage=[floor, wall],
+    )
+    if fcode:
+        return fcode
+    bpy.ops.render.render(write_still=True)
+    if not (os.path.exists(path) and os.path.getsize(path) > 0):
+        print("ERROR: render produced no file", file=sys.stderr)
+        return 6
+    return 0
+
+
+def main():
+    argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
+    p = argparse.ArgumentParser()
+    p.add_argument("--output", default=None, help="optional: render a still PNG here")
+    p.add_argument("--engine", default="eevee", choices=("eevee", "cycles"),
+                   help="render engine for --output (cycles for GPU-less hosts)")
+    p.add_argument("--world-to-object", action="store_true",
+                   help="feed world coords to Object.ray_cast in the checked path (must fail)")
+    args = p.parse_args(argv)
+
+    obj = build_target()
+    code = check(obj, world_to_object=args.world_to_object)
+    if code:
+        return code
+
+    if args.output:
+        rcode = render_still(obj, os.path.abspath(args.output), args.engine)
+        if rcode:
+            return rcode
+        print(f"rendered still {args.output}")
+
+    print("ray-cast-space OK")
+    return 0
+
+
+if __name__ == "__main__":
+    try:
+        sys.exit(main())
+    except Exception as e:
+        import traceback; traceback.print_exc(); print(f"FATAL: {e}", file=sys.stderr); sys.exit(1)
+
+
+
+ + +
+ + + A teal-checkered block turned and stretched on a walnut plinth, five orange rays from brass balls ending in orange rings on three faces, and one red ray striking it from elsewhere. + + +

+ + + diff --git a/docs/gallery/shader-node-group/index.html b/docs/gallery/shader-node-group/index.html index b8cc14fe..22af579a 100644 --- a/docs/gallery/shader-node-group/index.html +++ b/docs/gallery/shader-node-group/index.html @@ -45,7 +45,7 @@

Shader Node Group

One reusable shader group declared via tree.interface.new_socket, instanced in five materials with different Tint values — one dipped-glaze group, five stoneware mugs, five colors.

- + @@ -946,7 +946,7 @@

Color Attribute Wheel - +

diff --git a/docs/gallery/shape-key-blend/index.html b/docs/gallery/shape-key-blend/index.html index 86b11db3..94bd28ab 100644 --- a/docs/gallery/shape-key-blend/index.html +++ b/docs/gallery/shape-key-blend/index.html @@ -45,7 +45,7 @@

Shape Key Blend

A relative Tall shape key that turns a squat ceramic jar into a trumpet vase — lifting and flaring the rim — authored via shape_key_add / key_blocks / .value and read back from the depsgraph-evaluated mesh.

- + @@ -1057,7 +1057,7 @@

Color Attribute Wheel - +

diff --git a/docs/gallery/sky-texture-sun-elevation/index.html b/docs/gallery/sky-texture-sun-elevation/index.html index 4f92c0ef..c28379e6 100644 --- a/docs/gallery/sky-texture-sun-elevation/index.html +++ b/docs/gallery/sky-texture-sun-elevation/index.html @@ -45,7 +45,7 @@

Sky Texture Sun Elevation

World ShaderNodeTexSky driving Background Color — the sky contract across 4.5 LTS and 5.1. sky_type is NISHITA on 4.5 and MULTIPLE_SCATTERING on 5.1 (NISHITA gone); dust_density exists only on 4.5 (aerosol_density on 5.1). Two tiny Cycles OPEN_EXR zenith probes prove sun_elevation 8 deg to 55 deg brightens zenith (rise 2.25x on 5.1.2, 1.50x on 4.5.11, gate >= 1.25).

- + @@ -1700,7 +1700,7 @@

Text Version Stamp

- +
diff --git a/docs/gallery/soccer-ball-goldberg/index.html b/docs/gallery/soccer-ball-goldberg/index.html index fb16a7ac..f7b83348 100644 --- a/docs/gallery/soccer-ball-goldberg/index.html +++ b/docs/gallery/soccer-ball-goldberg/index.html @@ -45,7 +45,7 @@

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.

- + @@ -1347,7 +1347,7 @@

Collision Hull Proxy< - +

diff --git a/docs/gallery/socket-attach-points/index.html b/docs/gallery/socket-attach-points/index.html index 0165142c..87de4649 100644 --- a/docs/gallery/socket-attach-points/index.html +++ b/docs/gallery/socket-attach-points/index.html @@ -45,7 +45,7 @@

Socket Attach Points

A survey drone whose named SKT_ empties are the spawn contract: modules parented with an identity local transform seat exactly on their mount pads.

- + @@ -2477,7 +2477,7 @@

Prop Origin Transform - +

diff --git a/docs/gallery/swatch-grid/index.html b/docs/gallery/swatch-grid/index.html index 84c21029..e66fec56 100644 --- a/docs/gallery/swatch-grid/index.html +++ b/docs/gallery/swatch-grid/index.html @@ -45,7 +45,7 @@

Swatch Grid

Procedural Principled materials — metal and dielectric, the emission pattern, and the cross-version set_specular shim.

- + @@ -1229,7 +1229,7 @@

Compositor Glare

- +
diff --git a/docs/gallery/temp-override-join/index.html b/docs/gallery/temp-override-join/index.html index 08c9a8a0..ce0c1849 100644 --- a/docs/gallery/temp-override-join/index.html +++ b/docs/gallery/temp-override-join/index.html @@ -45,7 +45,7 @@

Temp Override Join

Join seven lantern parts into one object under bpy.context.temp_override — the supported replacement for the removed context.copy() dict-pass form.

- + @@ -1247,7 +1247,7 @@

Cross Version Pr - +

diff --git a/docs/gallery/text-version-stamp/index.html b/docs/gallery/text-version-stamp/index.html index c2f30edf..6ec9ad32 100644 --- a/docs/gallery/text-version-stamp/index.html +++ b/docs/gallery/text-version-stamp/index.html @@ -45,7 +45,7 @@

Text Version Stamp

The TextCurve data API — curves.new(type='FONT'), live body text from bpy.app.version_string, extrude and bevel_depth solids, and evaluated-mesh conversion — so every render self-documents which Blender produced it.

- + @@ -934,7 +934,7 @@

Curve Bevel Arc

- +
diff --git a/docs/gallery/triangulate-tangents/index.html b/docs/gallery/triangulate-tangents/index.html index da49650d..99dac989 100644 --- a/docs/gallery/triangulate-tangents/index.html +++ b/docs/gallery/triangulate-tangents/index.html @@ -45,7 +45,7 @@

Triangulate Tangents

A machined buckler verifying the tangent-space contract a game engine's normal mapping depends on. Deterministic triangulation, unit orthogonal tangent frames, and the edge/UV-delta formula matching mikktspace within welding tolerance.

- + @@ -1376,7 +1376,7 @@

BMesh Gear

- +
diff --git a/docs/gallery/turntable/index.html b/docs/gallery/turntable/index.html index 57f4ee93..8984040a 100644 --- a/docs/gallery/turntable/index.html +++ b/docs/gallery/turntable/index.html @@ -45,7 +45,7 @@

Turntable

A slotted-actions Z-rotation turntable keyed through the cross-version channelbag path (get_channelbag_for_slot).

- + @@ -844,7 +844,7 @@

Damped Track Aim

- +
diff --git a/docs/gallery/usd-export-evaluation-mode/index.html b/docs/gallery/usd-export-evaluation-mode/index.html index 6dd772c8..ff5318ad 100644 --- a/docs/gallery/usd-export-evaluation-mode/index.html +++ b/docs/gallery/usd-export-evaluation-mode/index.html @@ -45,7 +45,7 @@

USD Export Evaluation Mode

The USD exporter evaluation_mode chooses viewport versus render modifier quality. TESSELLATE makes the split observable; BEST_MATCH writes the cage and the mode is silent.

- + @@ -1185,7 +1185,7 @@

Text Version Stamp

- +
diff --git a/docs/gallery/uv-layer-grid/index.html b/docs/gallery/uv-layer-grid/index.html index 3055c4e6..2266ee7f 100644 --- a/docs/gallery/uv-layer-grid/index.html +++ b/docs/gallery/uv-layer-grid/index.html @@ -45,7 +45,7 @@

UV Layer Grid

The UV-layer authoring hazard — bmesh.ops.create_grid(..., calc_uvs=True) is a silent no-op unless a UV layer already exists; without one an Image Texture samples texel (0,0) everywhere.

- + @@ -1305,7 +1305,7 @@

Triangulate Tangents< - +

diff --git a/docs/gallery/vertex-color-ao/index.html b/docs/gallery/vertex-color-ao/index.html index 4ca1dcfa..b2cc1d3c 100644 --- a/docs/gallery/vertex-color-ao/index.html +++ b/docs/gallery/vertex-color-ao/index.html @@ -45,7 +45,7 @@

Vertex Color AO

A stone well carrying baked ambient occlusion in a colour attribute, with the bake held to the closed-form hemisphere integral rather than to a captured value.

- + @@ -2235,7 +2235,7 @@

Custom Normals Shade< - +

diff --git a/docs/gallery/vertex-weight-limit/index.html b/docs/gallery/vertex-weight-limit/index.html index fa710c97..36e64d9f 100644 --- a/docs/gallery/vertex-weight-limit/index.html +++ b/docs/gallery/vertex-weight-limit/index.html @@ -45,7 +45,7 @@

Vertex Weight Limit

A rigged industrial robot arm pruned to the game-engine cap of four bone influences per vertex, through the data API. The check proves no vertex exceeds the cap, weights still sum to one, the pose survives pruning, and the modifier is still exact linear blend skinning.

- + @@ -1674,7 +1674,7 @@

Shape Key Blend

- +
diff --git a/docs/gallery/vse-cut-list/index.html b/docs/gallery/vse-cut-list/index.html index 915be219..ee720ee1 100644 --- a/docs/gallery/vse-cut-list/index.html +++ b/docs/gallery/vse-cut-list/index.html @@ -45,7 +45,7 @@

VSE Cut List

The sequencer API rename from 4.5 LTS to 5.x — strips (never .sequences), new_effect ending in length= vs frame_end=, and left_handle/right_handle/duration replacing the deprecated frame_final_*. A deterministic cut list — color programs, a clamped GAMMA_CROSS, a scene strip, a text strip — asserted before and after save/reload.

- + @@ -1833,7 +1833,7 @@

Compositor Glare

- +
diff --git a/docs/gallery/vse-gamma-cross/index.html b/docs/gallery/vse-gamma-cross/index.html index 09023063..dc936ed7 100644 --- a/docs/gallery/vse-gamma-cross/index.html +++ b/docs/gallery/vse-gamma-cross/index.html @@ -45,7 +45,7 @@

VSE Gamma Cross

The GAMMA_CROSS fade is not the naive linear mix: it blends in a gamma-0.5 space, so the mid-cross dips below the sRGB lerp. Tiny per-frame renders are asserted against the closed form per frame.

- + @@ -1420,7 +1420,7 @@

Compositor Glare

- +
diff --git a/docs/gallery/wave-displace/index.html b/docs/gallery/wave-displace/index.html index 41ca9adf..c69c3aa4 100644 --- a/docs/gallery/wave-displace/index.html +++ b/docs/gallery/wave-displace/index.html @@ -45,7 +45,7 @@

Wave Displace

Bulk vertex IO at real scale — 9,409 vertices displaced into a standing wave with one foreach_get and one foreach_set, no per-vertex access.

- + @@ -808,7 +808,7 @@

Color Attribute Wheel - +

diff --git a/docs/new-example-prompt.md b/docs/new-example-prompt.md index 08e80f04..b048786f 100644 --- a/docs/new-example-prompt.md +++ b/docs/new-example-prompt.md @@ -59,7 +59,7 @@ metadata — so the render would be identical whether the API held or broke. The "redesign the scene until failure would be visible" instruction above is the test: attempt it first, and only when it cannot succeed in principle does the example become check-only. The exception is for contracts that are invisible, not for -renders that are hard. Eight of the 60 examples currently qualify, and `CLAUDE.md` +renders that are hard. Eight of the 62 examples currently qualify, and `CLAUDE.md` carries the same rule. A check-only example is otherwise a full example: it still asserts a real contract, still exits non-zero on failure, still carries a falsifier, and still takes a `tests/smoke/catalog.json` row so it runs on every PR. diff --git a/examples/gallery.json b/examples/gallery.json index 2989cdaa..a482e23e 100644 --- a/examples/gallery.json +++ b/examples/gallery.json @@ -701,6 +701,34 @@ "tags": [ "geometry-nodes" ] + }, + { + "name": "ray-cast-space", + "dir": "examples/ray-cast-space", + "teaches": "Object.ray_cast is object-local while Scene.ray_cast is world space: rays mapped through matrix_world.inverted() (directions by its 3x3 only) hit the same points both ways, and raw world coords handed to Object.ray_cast miss.", + "alt": "A teal-checkered block turned and stretched on a walnut plinth, five orange rays from brass balls ending in orange rings on three faces, and one red ray striking it from elsewhere.", + "witnessesFix": "Five closed-form rays on a translated, Z-rotated, non-uniformly scaled block: Scene.ray_cast hits each world point and normal exactly; Object.ray_cast fed matrix_world.inverted() coordinates hits the same polygons, and mapped back lands within 5e-7 m; world coords fed to Object.ray_cast land 0.287 m or more off. --world-to-object exits 4 (1.125 m error).", + "hero": "docs/gallery/assets/ray-cast-space-hero.webp", + "preview": "examples/ray-cast-space/preview.webp", + "tags": [ + "objects", + "transforms", + "depsgraph" + ] + }, + { + "name": "lattice-deform", + "dir": "examples/lattice-deform", + "teaches": "A 2x2x2 Lattice modifier set to KEY_LINEAR on all three axes, with two top control points moved through LatticePoint.co_deform, read back through the depsgraph (evaluated_get, to_mesh, to_mesh_clear).", + "alt": "Two checker-glazed columns on a walnut plinth, each in a steel-rod cage: the left upright in its rest cage, the right sheared and tapered where two orange cage corners have been pulled out.", + "witnessesFix": "Linear lattice deform is exact trilinear interpolation: all 602 evaluated verts land on the closed-form blend of the eight co_deform corners (max error 5.6e-7 through a translated, non-uniformly scaled lattice), the undeformed lattice is the identity, and --bspline (the default interpolation) misses by 0.2145 and exits 4.", + "hero": "docs/gallery/assets/lattice-deform-hero.webp", + "preview": "examples/lattice-deform/preview.webp", + "tags": [ + "mesh", + "modifiers", + "depsgraph" + ] } ] } diff --git a/examples/lattice-deform/README.md b/examples/lattice-deform/README.md new file mode 100644 index 00000000..572c3c19 --- /dev/null +++ b/examples/lattice-deform/README.md @@ -0,0 +1,73 @@ +# Lattice Deform + +A runnable example that deforms a subdivided column with a **2×2×2 lattice** set to +`'KEY_LINEAR'` interpolation on all three axes, then proves, vertex by vertex, that the +Lattice modifier's output is exactly the **trilinear interpolation** of the eight deformed +control points. The deformed mesh is read through the depsgraph lifetime contract from +[`depsgraph-and-evaluated-data`](../../skills/depsgraph-and-evaluated-data/SKILL.md) +(`evaluated_get` → `to_mesh` → `to_mesh_clear`), and the lattice points are edited the way +[`mesh-editing-and-bmesh`](../../skills/mesh-editing-and-bmesh/SKILL.md) recommends for +data-level work: through `bpy.data`, never `bpy.ops`. + +**What it witnesses:** `LatticePoint.co` is the read-only rest position and +`LatticePoint.co_deform` is the one you move. With linear interpolation a vertex at +normalized rest coordinates (u, v, w) inside the lattice lands on +Σ wᵢ · `co_deform`ᵢ with wᵢ = (u or 1−u)(v or 1−v)(w or 1−w), mapped through the lattice +object's matrix. The check computes that closed form independently for all 602 vertices, +through a lattice object that is translated and non-uniformly scaled (1.7 × 1.7 × 2.4), +and requires agreement to 1e-5 in world space (measured: 5.6e-7). It also asserts the +undeformed lattice is the identity and that the deformation is not trivially small +(max displacement 0.53). + +**The trap it exposes:** a new lattice defaults to `'KEY_BSPLINE'`. B-spline weights +smooth over the control points instead of interpolating them, so a script that moves a +corner and expects the mesh to follow it linearly gets a softer, smaller pull. On a +2×2×2 lattice the rest state is still the identity, so nothing looks wrong until a +point moves. `--bspline` keeps the default and fails check 4 with the measured error. + +The still shows the rule as a before-and-after on a walnut plinth: on the left a +render-only twin of the column, undeformed, inside its rest cage; on the right the +checked column inside the deformed cage, with the two moved corners in selection orange +and a short orange rod from each back to its rest position. The column carries a glazed +two-tone checker in Generated (rest) coordinates, so the squares are square before the +lattice acts, and their shear and taper in the still are the deformation. Lattices do +not render, so both cages are drawn as thin steel rods built from the corner positions +after the check has run. + +## Run + +```bash +# Cheap correctness check (no render) — the CI check: +blender --background --python lattice_deform.py -- + +# Falsifier: keep the default KEY_BSPLINE interpolation. Must exit 4. +blender --background --python lattice_deform.py -- --bspline + +# Also render a still (EEVEE on a GPU host; use --engine cycles on GPU-less hosts): +blender --background --python lattice_deform.py -- --output lattice.png --engine cycles +``` + +## Version notes + +The Lattice datablock API (`points_u/v/w`, `interpolation_type_u/v/w`, `points[i].co` / +`co_deform`, point order u fastest, then v, then w) and the `'LATTICE'` modifier are the +same on 4.5 LTS, 5.1 and 5.2 LTS. Measured identically on 4.5.11, 5.1.2 and 5.2.1: +602 vertices, trilinear max error 5.6e-7, max displacement 0.5311; `--bspline` max error +0.2145. + +## Exit codes + +| Code | Meaning | +| --- | --- | +| 0 | Success | +| 1 | Uncaught exception (FATAL wrapper) | +| 2 | argparse / usage | +| 3 | Undeformed lattice moved the mesh (identity check) | +| 4 | A vertex is off the trilinear closed form, or the vertex count changed (`--bspline` lands here) | +| 5 | Max displacement below the floor (the witness would pass vacuously) | +| 6 | `--output` produced no file | +| 10 | `--output` framing violation (Layer 1 fill / margin gate, `gallery_framing`) | + +The `blender-smoke` workflow runs the check on Blender 5.2 LTS and 4.5 LTS +(5.1 on the weekly cron, the `needs-5.1` PR label, or manual dispatch). +Smoke does not pass `--output` or `--bspline`. diff --git a/examples/lattice-deform/lattice_deform.py b/examples/lattice-deform/lattice_deform.py new file mode 100644 index 00000000..b33a7ddd --- /dev/null +++ b/examples/lattice-deform/lattice_deform.py @@ -0,0 +1,460 @@ +"""Lattice deform with linear interpolation is exact trilinear interpolation — a runnable example. + +Witnesses the Lattice modifier contract on a 2x2x2 lattice (``points_u``, +``points_v`` and ``points_w`` all 2). With ``interpolation_type_u/v/w`` set +to ``'KEY_LINEAR'`` a mesh vertex inside the lattice moves to the trilinear +interpolation of the eight *deformed* control points (``LatticePoint.co_deform``) +at the vertex's normalized rest coordinates (u, v, w) in lattice space. +The check computes that closed form independently in Python for every +evaluated vertex (``evaluated_get`` + ``to_mesh`` / ``to_mesh_clear``) and +requires agreement to 1e-5 in world space, through a lattice object that is +itself translated and non-uniformly scaled. + +Three checks, in run order: + +- 3: with no control point moved, the modifier is the identity; +- 4: with two top corners moved, every vertex lands on the trilinear point; +- 5: the deformation is not trivially small (the witness cannot pass vacuously). + +``--bspline`` leaves the lattice on its default ``'KEY_BSPLINE'`` +interpolation, which smooths over the control points instead of +interpolating them, so the evaluated mesh no longer matches the trilinear +closed form and check 4 fails with the measured error. That is the +falsifier — and the trap: a script that sets ``co_deform`` and expects the +corner to "pull" the mesh linearly gets a softer, smaller motion. + +By default it runs only the correctness check (no render) — the CI smoke +check. Pass --output to also render a still: + + blender --background --python lattice_deform.py -- # check only + blender --background --python lattice_deform.py -- --bspline # must fail + blender --background --python lattice_deform.py -- --output l.png # + render +""" +import bpy, bmesh, sys, os, math, argparse +from mathutils import Vector + +# Shared Layer 1 framing measurement (render path only) — see gallery_framing.py +sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)) +sys.dont_write_bytecode = True # keep examples/__pycache__ out of the repo tree +import gallery_framing + +# The lattice: a box in world space, as a translated, non-uniformly scaled +# 2x2x2 lattice object (its points sit at +-0.5 in lattice-local space). +LAT_LOC = Vector((0.0, 0.0, 1.30)) +LAT_SCALE = Vector((1.70, 1.70, 2.40)) +# The deformed column, inside the lattice on every axis (lattice-local units); +# its base lies on the lattice's bottom face (w = 0), so it sits on the plinth +COLUMN_HALF = (0.40, 0.40, 0.50) +COLUMN_CUTS = 9 # subdivisions per cube edge +# Two top corners moved (lattice-local offsets): (u, v, w) index -> offset +MOVES = { + (1, 1, 1): Vector((0.30, 0.18, 0.12)), + (0, 0, 1): Vector((-0.10, -0.26, -0.08)), +} +TOL = 1e-5 +MIN_DISPLACEMENT = 0.05 # world units; check 5's floor +TWIN_GAP = 2.9 # render only: the undeformed twin's offset to the left + + +def corner_index(u, v, w, n=2): + """LatticePoint order: u fastest, then v, then w.""" + return u + n * (v + n * w) + + +def build_scene(bspline=False): + bpy.ops.wm.read_factory_settings(use_empty=True) + scene = bpy.context.scene + + lat = bpy.data.lattices.new("Cage") + lat.points_u = lat.points_v = lat.points_w = 2 + if not bspline: + lat.interpolation_type_u = 'KEY_LINEAR' + lat.interpolation_type_v = 'KEY_LINEAR' + lat.interpolation_type_w = 'KEY_LINEAR' + lat_obj = bpy.data.objects.new("Cage", lat) + lat_obj.location = LAT_LOC + lat_obj.scale = LAT_SCALE + scene.collection.objects.link(lat_obj) + + me = bpy.data.meshes.new("Column") + bm = bmesh.new() + try: + bmesh.ops.create_cube(bm, size=1.0) + bmesh.ops.subdivide_edges(bm, edges=bm.edges[:], cuts=COLUMN_CUTS, use_grid_fill=True) + # cube [-0.5, 0.5]^3 -> the column's box in lattice-local units -> world + for vert in bm.verts: + local = Vector(tuple(vert.co[k] * 2.0 * COLUMN_HALF[k] for k in range(3))) + vert.co = LAT_LOC + Vector(tuple(local[k] * LAT_SCALE[k] for k in range(3))) + bm.to_mesh(me) + finally: + bm.free() + obj = bpy.data.objects.new("Column", me) + scene.collection.objects.link(obj) + mod = obj.modifiers.new("Lattice", 'LATTICE') + mod.object = lat_obj + return obj, lat_obj + + +def evaluated_world_coords(obj): + deps = bpy.context.evaluated_depsgraph_get() + ev = obj.evaluated_get(deps) + me = ev.to_mesh() + try: + mw = ev.matrix_world + return [mw @ v.co for v in me.vertices] + finally: + ev.to_mesh_clear() + + +def trilinear(lat_obj, corners, world_rest): + """Closed form, independent of Blender's deform code: normalized rest + coordinates in lattice space, then the trilinear blend of the deformed + corners, mapped back to world.""" + local = lat_obj.matrix_world.inverted() @ world_rest + u, v, w = (local[k] + 0.5 for k in range(3)) + out = Vector((0.0, 0.0, 0.0)) + for (i, j, k), co in corners.items(): + weight = (u if i else 1 - u) * (v if j else 1 - v) * (w if k else 1 - w) + out += weight * co + return lat_obj.matrix_world @ out + + +def check(obj, lat_obj): + bpy.context.view_layer.update() + rest = [obj.matrix_world @ v.co for v in obj.data.vertices] + + # 3: an undeformed lattice is the identity + ident = evaluated_world_coords(obj) + err0 = max((a - b).length for a, b in zip(ident, rest)) + if err0 > TOL: + print(f"ERROR: undeformed lattice moved the mesh (max {err0:.3e} > {TOL:.0e})", + file=sys.stderr) + return 3 + + lat = lat_obj.data + for (i, j, k), off in MOVES.items(): + pt = lat.points[corner_index(i, j, k)] + pt.co_deform = Vector(pt.co) + off + corners = {(i, j, k): Vector(lat.points[corner_index(i, j, k)].co_deform) + for i in (0, 1) for j in (0, 1) for k in (0, 1)} + lat.update_tag() + obj.update_tag() + bpy.context.view_layer.update() + + # 4: every vertex on the trilinear closed form + got = evaluated_world_coords(obj) + if len(got) != len(rest): + print(f"ERROR: vertex count changed {len(rest)} -> {len(got)}", file=sys.stderr) + return 4 + errs = [(g - trilinear(lat_obj, corners, r)).length for g, r in zip(got, rest)] + worst = max(range(len(errs)), key=errs.__getitem__) + interp = (lat.interpolation_type_u, lat.interpolation_type_v, lat.interpolation_type_w) + if errs[worst] > TOL: + print(f"ERROR: {sum(e > TOL for e in errs)}/{len(errs)} verts off the trilinear " + f"closed form; max {errs[worst]:.4f} at vert {worst} (interpolation {interp})", + file=sys.stderr) + return 4 + + # 5: the witness moved the mesh by a real amount + disp = max((g - r).length for g, r in zip(got, rest)) + if disp < MIN_DISPLACEMENT: + print(f"ERROR: max displacement {disp:.4f} < {MIN_DISPLACEMENT}", file=sys.stderr) + return 5 + + print(f"lattice 2x2x2 {interp}: identity max {err0:.2e}; {len(errs)} verts on the " + f"trilinear closed form, max err {errs[worst]:.2e}; max displacement {disp:.4f}") + return 0 + + +def eevee_engine_id(): + return 'BLENDER_EEVEE' if bpy.app.version >= (5, 0, 0) else 'BLENDER_EEVEE_NEXT' + + +# --------------------------------------------------------------------------- +# Render staging only (runs after the check; never part of it) +# --------------------------------------------------------------------------- + +def principled(name, base, rough, metal=0.0, noise=None, coat=0.0, emit=None): + mat = bpy.data.materials.new(name) + mat.use_nodes = True + nt = mat.node_tree + b = nt.nodes["Principled BSDF"] + b.inputs["Base Color"].default_value = (*base, 1.0) + b.inputs["Roughness"].default_value = rough + b.inputs["Metallic"].default_value = metal + if coat: + b.inputs["Coat Weight"].default_value = coat + if emit: + b.inputs["Emission Color"].default_value = (*emit[0], 1.0) + b.inputs["Emission Strength"].default_value = emit[1] + if noise: + tex = nt.nodes.new("ShaderNodeTexNoise") + tex.inputs["Scale"].default_value = noise + tex.inputs["Detail"].default_value = 8.0 + mr = nt.nodes.new("ShaderNodeMapRange") + mr.inputs["To Min"].default_value = max(rough - 0.08, 0.0) + mr.inputs["To Max"].default_value = rough + 0.14 + nt.links.new(tex.outputs["Fac"], mr.inputs["Value"]) + nt.links.new(mr.outputs["Result"], b.inputs["Roughness"]) + return mat + + +def checker_ceramic(): + """A glazed two-tone checker on the column, in Generated (rest) coordinates: + the squares are square before the lattice acts, so their shear and + stretch in the still is the deformation itself.""" + mat = bpy.data.materials.new("CheckerGlaze") + mat.use_nodes = True + nt = mat.node_tree + b = nt.nodes["Principled BSDF"] + b.inputs["Roughness"].default_value = 0.32 + b.inputs["Coat Weight"].default_value = 0.5 + tc = nt.nodes.new("ShaderNodeTexCoord") + chk = nt.nodes.new("ShaderNodeTexChecker") + chk.inputs["Scale"].default_value = float(COLUMN_CUTS + 1) + chk.inputs["Color1"].default_value = (0.60, 0.56, 0.49, 1.0) + chk.inputs["Color2"].default_value = (0.10, 0.22, 0.30, 1.0) + nt.links.new(tc.outputs["Generated"], chk.inputs["Vector"]) + nt.links.new(chk.outputs["Color"], b.inputs["Base Color"]) + return mat + + +def tube_mesh(name, segments, radius, sides=10): + """Render-only rods along line segments (lattices do not render).""" + me = bpy.data.meshes.new(name) + bm = bmesh.new() + try: + for a, b in segments: + axis = b - a + res = bmesh.ops.create_cone(bm, cap_ends=True, segments=sides, + radius1=radius, radius2=radius, depth=axis.length) + rot = Vector((0, 0, 1)).rotation_difference(axis.normalized()).to_matrix() + mid = (a + b) / 2 + for vert in res["verts"]: + vert.co = rot @ vert.co + mid + bmesh.ops.recalc_face_normals(bm, faces=bm.faces) + bm.to_mesh(me) + finally: + bm.free() + for p in me.polygons: + p.use_smooth = True + return me + + +def sphere_mesh(name, centers, radius): + me = bpy.data.meshes.new(name) + bm = bmesh.new() + try: + for c in centers: + res = bmesh.ops.create_uvsphere(bm, u_segments=24, v_segments=14, radius=radius) + for vert in res["verts"]: + vert.co += c + bm.to_mesh(me) + finally: + bm.free() + for p in me.polygons: + p.use_smooth = True + return me + + +def box_mesh(name, lo, hi): + me = bpy.data.meshes.new(name) + bm = bmesh.new() + try: + res = bmesh.ops.create_cube(bm, size=1.0) + for vert in res["verts"]: + vert.co = Vector(tuple(lo[k] + (vert.co[k] + 0.5) * (hi[k] - lo[k]) for k in range(3))) + bm.to_mesh(me) + finally: + bm.free() + return me + + +def cage_edges(points): + """The 12 edges of a 2x2x2 cage given corner positions keyed (i, j, k).""" + edges = [] + for i in (0, 1): + for j in (0, 1): + edges.append((points[(i, j, 0)], points[(i, j, 1)])) + edges.append((points[(i, 0, j)], points[(i, 1, j)])) + edges.append((points[(0, i, j)], points[(1, i, j)])) + return edges + + +def render_still(obj, lat_obj, path, engine): + scene = bpy.context.scene + mw = lat_obj.matrix_world + lat = lat_obj.data + rest = {(i, j, k): mw @ Vector(lat.points[corner_index(i, j, k)].co) + for i in (0, 1) for j in (0, 1) for k in (0, 1)} + moved = {(i, j, k): mw @ Vector(lat.points[corner_index(i, j, k)].co_deform) + for i in (0, 1) for j in (0, 1) for k in (0, 1)} + + obj.data.materials.append(checker_ceramic()) + for p in obj.data.polygons: + p.use_smooth = False + + steel = principled("CageSteel", (0.58, 0.60, 0.64), 0.22, metal=1.0) + ghost = principled("RestCage", (0.16, 0.17, 0.19), 0.6, metal=0.3) + orange = principled("MovedCorner", (1.0, 0.42, 0.04), 0.3, + emit=((1.0, 0.45, 0.06), 1.5)) + joint = principled("CageJoint", (0.30, 0.31, 0.34), 0.3, metal=1.0) + walnut = principled("Walnut", (0.13, 0.055, 0.025), 0.45, noise=40.0, coat=0.4) + + parts = [] + + def add(name, me, mat): + me.materials.append(mat) + ob = bpy.data.objects.new(name, me) + scene.collection.objects.link(ob) + parts.append(ob) + return ob + + add("DeformedCage", tube_mesh("DeformedCage", cage_edges(moved), 0.022), steel) + # the rest cage, thin and dark: what the two corners were moved away from + rest_only = [(a, b) for a, b in cage_edges(rest)] + add("RestCage", tube_mesh("RestCage", rest_only, 0.009), ghost) + still = [moved[key] for key in moved if key not in MOVES] + add("CageJoints", sphere_mesh("CageJoints", still, 0.05), joint) + add("MovedCorners", sphere_mesh("MovedCorners", [moved[key] for key in MOVES], 0.075), + orange) + # a travel rod from each moved corner back to its rest position + add("Travel", tube_mesh("Travel", [(rest[key], moved[key]) for key in MOVES], 0.012), + orange) + + # Render-only "before" twin: the same column, unmodified, in its rest cage, + # one cage-width to the left, so the still reads rest -> deformed. + shift = Vector((-TWIN_GAP, 0.0, 0.0)) + twin_me = obj.data.copy() + twin = bpy.data.objects.new("RestColumn", twin_me) + twin.location = shift + scene.collection.objects.link(twin) + parts.append(twin) + rest_twin = {key: co + shift for key, co in rest.items()} + add("TwinCage", tube_mesh("TwinCage", cage_edges(rest_twin), 0.022), steel) + add("TwinJoints", sphere_mesh("TwinJoints", list(rest_twin.values()), 0.05), joint) + + lo_z = LAT_LOC.z - LAT_SCALE.z / 2 + half_x = LAT_SCALE.x / 2 + 0.45 + plinth = add("Plinth", box_mesh("Plinth", (-TWIN_GAP - half_x, -1.3, 0.0), + (half_x, 1.3, lo_z - 0.002)), walnut) + bev = plinth.modifiers.new("Chamfer", 'BEVEL') + bev.width = 0.03 + bev.segments = 2 + + floor_me = bpy.data.meshes.new("Floor") + bm = bmesh.new() + try: + bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=30.0) + bm.to_mesh(floor_me) + finally: + bm.free() + fmat = bpy.data.materials.new("Studio") + fmat.use_nodes = True + fb = fmat.node_tree.nodes["Principled BSDF"] + fb.inputs["Base Color"].default_value = (0.03, 0.032, 0.037, 1.0) + fb.inputs["Roughness"].default_value = 0.7 + floor_me.materials.append(fmat) + floor = bpy.data.objects.new("Floor", floor_me) + scene.collection.objects.link(floor) + wall = bpy.data.objects.new("Wall", floor_me.copy()) + wall.location = (0.0, 7.5, 0.0) + wall.rotation_euler = (math.radians(90), 0.0, 0.0) + scene.collection.objects.link(wall) + + world = bpy.data.worlds.new("World") + world.use_nodes = True + world.node_tree.nodes["Background"].inputs["Color"].default_value = (0.02, 0.021, 0.025, 1.0) + scene.world = world + + centre = Vector((-TWIN_GAP / 2, 0.0, LAT_LOC.z)) + + def light(name, loc, energy, size, col, aim): + ld = bpy.data.lights.new(name, 'AREA') + ld.energy = energy; ld.size = size; ld.color = col + ob = bpy.data.objects.new(name, ld) + ob.location = loc + ob.rotation_euler = (Vector(aim) - Vector(loc)).to_track_quat('-Z', 'Y').to_euler() + scene.collection.objects.link(ob) + + light("Key", (-4.5, -5.0, 6.5), 520.0, 4.0, (1.0, 0.96, 0.9), centre) + light("Fill", (5.5, -4.5, 2.5), 110.0, 7.0, (0.75, 0.85, 1.0), centre) + light("Rim", (1.5, 4.0, 6.0), 380.0, 3.0, (0.6, 0.78, 1.0), centre) + light("Wedge", (2.5, 4.5, 3.0), 420.0, 5.0, (1.0, 0.76, 0.5), (4.5, 7.5, 1.0)) + + cam_data = bpy.data.cameras.new("Cam") + cam_data.lens = 50.0 + cam = bpy.data.objects.new("Cam", cam_data) + cam.location = (centre.x + 3.6, -9.6, 3.9) + scene.collection.objects.link(cam) + aim = bpy.data.objects.new("Aim", None) + aim.location = centre + Vector((0.05, 0.0, -0.15)) + scene.collection.objects.link(aim) + tr = cam.constraints.new('TRACK_TO') + tr.target = aim + tr.track_axis = 'TRACK_NEGATIVE_Z' + tr.up_axis = 'UP_Y' + scene.camera = cam + + scene.render.engine = 'CYCLES' if engine == 'cycles' else eevee_engine_id() + if engine == 'cycles': + scene.cycles.samples = 48 + else: + try: + scene.eevee.taa_render_samples = 64 + except AttributeError: + pass + scene.render.resolution_x = 1280 + scene.render.resolution_y = 720 + scene.render.image_settings.file_format = 'PNG' + scene.render.filepath = path + # AgX would wash the glaze and the orange accent toward pastel (docs/VISUAL-STYLE.md) + scene.view_settings.view_transform = 'Standard' + bpy.context.view_layer.update() + # Layer 1 framing gate (silhouette matte) — exit 10 on violation, before + # the beauty render so a defective composition ships no artifact + fcode = gallery_framing.check_framing( + scene, cam, + hero=[obj] + parts, + elements=[obj] + parts, + stage=[floor, wall], + ) + if fcode: + return fcode + bpy.ops.render.render(write_still=True) + if not (os.path.exists(path) and os.path.getsize(path) > 0): + print("ERROR: render produced no file", file=sys.stderr) + return 6 + return 0 + + +def main(): + argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [] + p = argparse.ArgumentParser() + p.add_argument("--output", default=None, help="optional: render a still PNG here") + p.add_argument("--engine", default="eevee", choices=("eevee", "cycles"), + help="render engine for --output (cycles for GPU-less hosts)") + p.add_argument("--bspline", action="store_true", + help="keep the default KEY_BSPLINE interpolation (must fail)") + args = p.parse_args(argv) + + obj, lat_obj = build_scene(bspline=args.bspline) + code = check(obj, lat_obj) + if code: + return code + + if args.output: + rcode = render_still(obj, lat_obj, os.path.abspath(args.output), args.engine) + if rcode: + return rcode + print(f"rendered still {args.output}") + + print("lattice-deform OK") + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except Exception as e: + import traceback; traceback.print_exc(); print(f"FATAL: {e}", file=sys.stderr); sys.exit(1) diff --git a/examples/lattice-deform/preview.webp b/examples/lattice-deform/preview.webp new file mode 100644 index 0000000000000000000000000000000000000000..caadf9fbf1fc04e6805e2287c4b6b6c6ab5609c8 GIT binary patch literal 59220 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%0DDHvCiurXRz!^&bKS030By7XZpYF{* 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 R!4fbeN2vGyDOUU+Z~y~`##R6T literal 0 HcmV?d00001 diff --git a/examples/ray-cast-space/README.md b/examples/ray-cast-space/README.md new file mode 100644 index 00000000..b34ad838 --- /dev/null +++ b/examples/ray-cast-space/README.md @@ -0,0 +1,72 @@ +# Ray Cast Space + +A runnable example of the coordinate-space contract behind Blender's two ray casts, the +one AI-written code gets wrong most often. `Scene.ray_cast(depsgraph, origin, direction)` +takes and returns **world** space. `Object.ray_cast(origin, direction)` takes and returns +the object's **local** space. Feed world coordinates to `Object.ray_cast` and nothing +raises: it quietly misses, or hits the wrong spot. + +**What it witnesses:** a target block carries a transform with every ingredient that +separates the two spaces: a translation, a 32° turn about Z, and non-uniform scale +(1.55 × 0.62 × 0.62). The example casts five rays at closed-form points on three of its +faces, arriving obliquely, and checks each one three ways: + +1. **`Scene.ray_cast`** hits the closed-form world point (to 1e-4 m). Its normal matches + the face's world normal, which comes from the inverse-transpose of `matrix_world`. +2. **`Object.ray_cast`** is fed the origin through `matrix_world.inverted()` and the + direction through that matrix's 3×3 part only, because directions do not translate. + It must hit the same polygon. Its local hit point, mapped back through `matrix_world` + (and its normal through the inverse-transpose), must land on the same world point and + normal. +3. **The trap must bite on this setup.** The same world origin and direction handed + straight to `Object.ray_cast` either misses or lands at least 0.25 m from the true + hit. Without this, the check could pass by coincidence. + +Both 5.2 LTS and 4.5 LTS give identical results: every hit exact to under 1e-6 m, and +the world-coordinate trap's closest landing 0.287 m away. + +The still shows the block glazed in a teal checker laid out in **object** coordinates. +The cells are square in local space, so the non-uniform scale stretches them into the +block's own grid. The block stands on a walnut plinth. Five orange rays run from brass +emitter balls to orange hit rings that sit exactly on three faces: the correct casts. +One red ray is the first front-face ray's world origin and direction read by +`Object.ray_cast` as if local. In the world that is the ray `matrix_world @ origin` +along `matrix_world.to_3x3() @ direction`. It starts somewhere else entirely and +strikes the far side of the block. A render-only Bevel modifier rounds the block's +edges after the check has run. + +## Run + +```bash +# Cheap correctness check (no render) — the CI check: +blender --background --python ray_cast_space.py -- + +# Falsifier: feed WORLD coords to Object.ray_cast in the checked path. Must exit 4. +blender --background --python ray_cast_space.py -- --world-to-object + +# Also render a still (EEVEE on a GPU host; use --engine cycles on GPU-less hosts): +blender --background --python ray_cast_space.py -- --output ray.png +blender --background --python ray_cast_space.py -- --output ray.png --engine cycles +``` + +`--world-to-object` measured on 5.2.1 and 4.5.11: +`Object.ray_cast ray 0 mapped back to (1.5668, 1.22769, 1.38161), error 1.1253 m +(normal error 1.0000, polygon 2 vs Scene 3)`. The cast hit a different face of the +block, a metre from the true point. + +## Exit codes + +| Code | Meaning | +| --- | --- | +| 0 | Success | +| 1 | Uncaught exception (FATAL wrapper) | +| 2 | argparse / usage | +| 3 | `Scene.ray_cast` missed, hit another object, or hit off the closed-form world point or normal | +| 4 | `Object.ray_cast` missed, or its local hit mapped back by `matrix_world` disagrees with the world point, normal or polygon (`--world-to-object` lands here) | +| 5 | The world-coordinate trap did not bite: world coords fed to `Object.ray_cast` landed within `TRAP_MIN` of a true hit | +| 6 | `--output` produced no file | +| 10 | `--output` framing violation (Layer 1 fill / margin gate, `gallery_framing`) | + +The `blender-smoke` workflow runs the check on Blender 5.2 LTS and 4.5 LTS +(5.1 on the weekly cron, the `needs-5.1` PR label, or manual dispatch). +Smoke does not pass `--output` or `--world-to-object`. diff --git a/examples/ray-cast-space/preview.webp b/examples/ray-cast-space/preview.webp new file mode 100644 index 0000000000000000000000000000000000000000..007458f6e853f4d24ee917cb59d1a8758afda278 GIT binary patch literal 28124 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

@RV4&CbD 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�cF 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 HX>x!7WN=Bg literal 0 HcmV?d00001 diff --git a/examples/ray-cast-space/ray_cast_space.py b/examples/ray-cast-space/ray_cast_space.py new file mode 100644 index 00000000..bea83d8e --- /dev/null +++ b/examples/ray-cast-space/ray_cast_space.py @@ -0,0 +1,476 @@ +"""Object.ray_cast is object-local, Scene.ray_cast is world space — a runnable example. + +Witnesses the coordinate-space contract of the two ray casts, the one AI code +gets wrong most often: ``Scene.ray_cast(depsgraph, origin, direction)`` takes +and returns WORLD space, while ``Object.ray_cast(origin, direction)`` takes +and returns the object's LOCAL space. A target block carries a non-trivial +transform (translation, a turn about Z, non-uniform scale). Five rays aimed at +closed-form points on three of its faces are cast both ways: + +- ``Scene.ray_cast`` must hit each closed-form world point, with the face's + world normal (inverse-transpose of the object matrix) and the target object; +- ``Object.ray_cast``, fed the origin through ``matrix_world.inverted()`` and + the direction through its 3x3 part only (directions do not translate), must + hit the same polygon, and its local hit point mapped back by + ``matrix_world`` (normal by the inverse-transpose) must land on the same + world point and normal; +- the trap: the same WORLD origin/direction handed straight to + ``Object.ray_cast`` must NOT reproduce the hit — every such cast misses or + lands at least ``TRAP_MIN`` away, so the check proves the transform matters + on this setup rather than passing by coincidence. + +``--world-to-object`` feeds world coordinates to ``Object.ray_cast`` in the +checked path (the bug); the local-hit check catches it (exit 4) and prints +the measured error. + +By default it runs only the correctness check (no render) — the CI smoke +check. Pass --output to also render a still: + + blender --background --python ray_cast_space.py -- # check only + blender --background --python ray_cast_space.py -- --world-to-object # must fail + blender --background --python ray_cast_space.py -- --output r.png # + render +""" +import bpy, bmesh, sys, os, math, argparse +from mathutils import Vector, Matrix + +# Shared Layer 1 framing measurement (render path only) — see gallery_framing.py +sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir)) +sys.dont_write_bytecode = True # keep examples/__pycache__ out of the repo tree +import gallery_framing + +# The target: a unit-half-size cube (local coords in [-1, 1]^3) under a +# transform with every ingredient that separates local from world space. +TARGET_LOC = (0.35, 0.25, 0.80) +TARGET_ROT_Z = math.radians(32.0) +TARGET_SCALE = (1.55, 0.62, 0.62) + +# Closed-form hit points, authored in LOCAL face coordinates, plus a tangent +# tilt so the rays arrive obliquely rather than straight down each normal. +# (face axis, face sign, local point on that face, tilt in local tangent space) +RAYS = ( + ("y", -1, (0.55, -1.0, 0.35), (0.35, 0.0, 0.25)), + ("y", -1, (-0.45, -1.0, -0.30), (-0.30, 0.0, 0.20)), + ("z", +1, (0.40, 0.30, 1.0), (0.25, -0.35, 0.0)), + ("z", +1, (-0.60, -0.40, 1.0), (-0.20, -0.30, 0.0)), + ("x", -1, (-1.0, -0.35, 0.30), (0.0, -0.30, 0.25)), +) +RAY_LEN = 1.7 # world distance from each ray origin to its hit +POS_TOL = 1e-4 # world-space hit tolerance +NRM_TOL = 1e-4 # 1 - dot(normal, expected) +TRAP_MIN = 0.25 # a world-coord Object.ray_cast must miss or land this far off + + +def build_target(): + bpy.ops.wm.read_factory_settings(use_empty=True) + me = bpy.data.meshes.new("TargetBlock") + bm = bmesh.new() + try: + bmesh.ops.create_cube(bm, size=2.0) + bm.to_mesh(me) + finally: + bm.free() + obj = bpy.data.objects.new("TargetBlock", me) + bpy.context.collection.objects.link(obj) + obj.location = TARGET_LOC + obj.rotation_euler = (0.0, 0.0, TARGET_ROT_Z) + obj.scale = TARGET_SCALE + bpy.context.view_layer.update() + return obj + + +def world_rays(obj): + """Closed-form world rays: (origin, direction, hit point, face normal). + + The hit point is the local face point through matrix_world; the world + normal is the local face normal through the inverse-transpose 3x3. The + origin sits RAY_LEN back along the (tilted) incoming direction, in the + face's outer half-space, so on this convex block the first surface the + ray meets is that face at that point. + """ + mw = obj.matrix_world + n_mat = mw.to_3x3().inverted().transposed() + out = [] + for axis, sign, p_local, tilt in RAYS: + n_local = Vector((0.0, 0.0, 0.0)) + n_local["xyz".index(axis)] = sign + p = mw @ Vector(p_local) + n = (n_mat @ n_local).normalized() + incoming = (n_local + Vector(tilt)) # outward-ish, in local space + d = -(mw.to_3x3() @ incoming).normalized() + if d.dot(n) >= 0.0: + raise ValueError(f"ray at {p_local} does not approach its face from outside") + out.append((p - RAY_LEN * d, d, p, n)) + return out + + +def object_space(obj, origin, direction): + """World ray -> the object's local space: the origin through the full + inverse matrix, the direction through its 3x3 only (no translation).""" + inv = obj.matrix_world.inverted() + return inv @ origin, (inv.to_3x3() @ direction).normalized() + + +def check(obj, world_to_object=False): + dg = bpy.context.evaluated_depsgraph_get() + scene = bpy.context.scene + mw = obj.matrix_world + n_mat = mw.to_3x3().inverted().transposed() + rays = world_rays(obj) + + # 1. Scene.ray_cast: world in, world out + scene_hits = [] + for k, (o, d, p, n) in enumerate(rays): + ok, loc, nrm, idx, hit_ob, _m = scene.ray_cast(dg, o, d) + if not ok or hit_ob is None or hit_ob.name != obj.name: + print(f"ERROR: Scene.ray_cast ray {k} missed the target", file=sys.stderr) + return 3 + err, nerr = (loc - p).length, 1.0 - nrm.normalized().dot(n) + if err > POS_TOL or nerr > NRM_TOL: + print(f"ERROR: Scene.ray_cast ray {k} hit {tuple(round(c, 5) for c in loc)} " + f"(error {err:.6f} m, normal error {nerr:.6f}) vs closed form " + f"{tuple(round(c, 5) for c in p)}", file=sys.stderr) + return 3 + scene_hits.append(idx) + + # 2. Object.ray_cast: local in, local out — map both ways + worst = 0.0 + for k, (o, d, p, n) in enumerate(rays): + if world_to_object: + lo, ld = o, d # the bug: world coords as if local + else: + lo, ld = object_space(obj, o, d) + ok, loc, nrm, idx = obj.ray_cast(lo, ld, depsgraph=dg) + if not ok: + print(f"ERROR: Object.ray_cast ray {k} missed (origin/direction not in " + f"object space?)", file=sys.stderr) + return 4 + p_back = mw @ loc + n_back = (n_mat @ nrm).normalized() + err, nerr = (p_back - p).length, 1.0 - n_back.dot(n) + worst = max(worst, err) + if err > POS_TOL or nerr > NRM_TOL or idx != scene_hits[k]: + print(f"ERROR: Object.ray_cast ray {k} mapped back to " + f"{tuple(round(c, 5) for c in p_back)}, error {err:.4f} m " + f"(normal error {nerr:.4f}, polygon {idx} vs Scene {scene_hits[k]})", + file=sys.stderr) + return 4 + + # 3. The trap must actually bite on this setup + trap_min = math.inf + for k, (o, d, p, n) in enumerate(rays): + ok, loc, _nrm, _idx = obj.ray_cast(o, d, depsgraph=dg) + dev = (mw @ loc - p).length if ok else math.inf + trap_min = min(trap_min, dev) + if trap_min < TRAP_MIN: + print(f"ERROR: world coords fed to Object.ray_cast landed only {trap_min:.4f} m " + f"from a true hit (< {TRAP_MIN}); the transform does not separate the " + f"spaces", file=sys.stderr) + return 5 + + trap_txt = "all miss" if trap_min == math.inf else f"closest {trap_min:.3f} m off" + print(f"rays={len(rays)} scene_hits=exact object_local_hits=exact " + f"max_mapped_error={worst:.2e} m world_coords_trap={trap_txt}") + return 0 + + +def eevee_engine_id(): + return 'BLENDER_EEVEE' if bpy.app.version >= (5, 0, 0) else 'BLENDER_EEVEE_NEXT' + + +# -------------------------------------------------------------------------- +# Render staging only (not part of the check) +# -------------------------------------------------------------------------- + +def principled(name, base, rough, metal=0.0, emit=None, strength=0.0, alpha=1.0): + mat = bpy.data.materials.new(name) + mat.use_nodes = True + b = mat.node_tree.nodes["Principled BSDF"] + b.inputs["Base Color"].default_value = (*base, 1.0) + b.inputs["Roughness"].default_value = rough + b.inputs["Metallic"].default_value = metal + if emit is not None: + b.inputs["Emission Color"].default_value = (*emit, 1.0) + b.inputs["Emission Strength"].default_value = strength + if alpha < 1.0: + b.inputs["Alpha"].default_value = alpha + try: + mat.surface_render_method = 'BLENDED' + except AttributeError: + pass + return mat + + +def block_material(): + """Glazed teal ceramic with an OBJECT-space checker: the cells are square + in local space, so the non-uniform scale stretches them into the + rectangles the eye reads as 'this object has its own coordinates'. Teal + sits opposite the orange rays, so every hit marker reads at thumbnail size.""" + mat = bpy.data.materials.new("LocalSpaceCeramic") + mat.use_nodes = True + nt = mat.node_tree + b = nt.nodes["Principled BSDF"] + b.inputs["Roughness"].default_value = 0.32 + b.inputs["Coat Weight"].default_value = 0.35 + coords = nt.nodes.new("ShaderNodeTexCoord") + chk = nt.nodes.new("ShaderNodeTexChecker") + chk.inputs["Scale"].default_value = 4.0 + chk.inputs["Color1"].default_value = (0.09, 0.36, 0.40, 1.0) + chk.inputs["Color2"].default_value = (0.035, 0.15, 0.18, 1.0) + # Object coords span -1..1; shift to 0..2 so cells line up with face edges + add = nt.nodes.new("ShaderNodeVectorMath") + add.operation = 'ADD' + add.inputs[1].default_value = (1.0, 1.0, 1.0) + nt.links.new(coords.outputs["Object"], add.inputs[0]) + nt.links.new(add.outputs["Vector"], chk.inputs["Vector"]) + nt.links.new(chk.outputs["Color"], b.inputs["Base Color"]) + return mat + + +def rod(name, a, b, radius, mat, segs=16): + """A thin cylinder from a to b (render-only ray segment).""" + me = bpy.data.meshes.new(name) + bm = bmesh.new() + try: + length = (b - a).length + bmesh.ops.create_cone(bm, cap_ends=True, segments=segs, radius1=radius, + radius2=radius, depth=length) + bm.to_mesh(me) + finally: + bm.free() + me.materials.append(mat) + for poly in me.polygons: + poly.use_smooth = True + ob = bpy.data.objects.new(name, me) + bpy.context.scene.collection.objects.link(ob) + ob.location = (a + b) / 2 + ob.rotation_euler = (b - a).to_track_quat('Z', 'Y').to_euler() + return ob + + +def sphere(name, at, radius, mat): + me = bpy.data.meshes.new(name) + bm = bmesh.new() + try: + bmesh.ops.create_uvsphere(bm, u_segments=24, v_segments=12, radius=radius) + bm.to_mesh(me) + finally: + bm.free() + me.materials.append(mat) + for poly in me.polygons: + poly.use_smooth = True + ob = bpy.data.objects.new(name, me) + bpy.context.scene.collection.objects.link(ob) + ob.location = at + return ob + + +def ring(name, at, normal, r_out, r_in, mat): + """A flat hit-marker annulus lying on the surface, facing out along normal.""" + me = bpy.data.meshes.new(name) + bm = bmesh.new() + try: + segs = 32 + outer = [bm.verts.new((r_out * math.cos(2 * math.pi * i / segs), + r_out * math.sin(2 * math.pi * i / segs), 0.0)) + for i in range(segs)] + inner = [bm.verts.new((r_in * math.cos(2 * math.pi * i / segs), + r_in * math.sin(2 * math.pi * i / segs), 0.0)) + for i in range(segs)] + for i in range(segs): + j = (i + 1) % segs + bm.faces.new((outer[i], outer[j], inner[j], inner[i])) + ext = bmesh.ops.extrude_face_region(bm, geom=list(bm.faces)) + top = [e for e in ext["geom"] if isinstance(e, bmesh.types.BMVert)] + bmesh.ops.translate(bm, verts=top, vec=(0.0, 0.0, 0.006)) + bmesh.ops.recalc_face_normals(bm, faces=bm.faces) + bm.to_mesh(me) + finally: + bm.free() + me.materials.append(mat) + ob = bpy.data.objects.new(name, me) + bpy.context.scene.collection.objects.link(ob) + ob.location = at + normal * 0.002 + ob.rotation_euler = normal.to_track_quat('Z', 'Y').to_euler() + return ob + + +def render_still(obj, path, engine): + scene = bpy.context.scene + dg = bpy.context.evaluated_depsgraph_get() + rays = world_rays(obj) + # one ghosted trap ray: the first front-face ray's WORLD origin/direction + # read by Object.ray_cast as if local. In the world that is the ray + # matrix_world @ o along matrix_world.to_3x3() @ d; cast it before any + # render-only modifier changes the evaluated mesh. + mw = obj.matrix_world + o, d, p, n = rays[0] + t_o = mw @ o + t_d = (mw.to_3x3() @ d).normalized() + t_ok, t_loc, _n, _i = obj.ray_cast(o, d, depsgraph=dg) + t_end = (mw @ t_loc) if t_ok else (t_o + 3.0 * t_d) + obj.data.materials.append(block_material()) + bev = obj.modifiers.new("Chamfer", 'BEVEL') # render-only, after the check + bev.width = 0.025 + bev.segments = 3 + bev.affect = 'EDGES' + + # emission kept under clipping in Standard view, so the beams stay orange + beam = principled("RayBeam", (1.0, 0.26, 0.02), 0.3, emit=(1.0, 0.26, 0.02), strength=1.4) + hit_mat = principled("HitMarker", (1.0, 0.36, 0.04), 0.25, emit=(1.0, 0.36, 0.04), + strength=1.8) + emitter = principled("RayEmitter", (0.85, 0.58, 0.24), 0.38, metal=1.0) + trap_beam = principled("TrapBeam", (0.9, 0.12, 0.18), 0.4, emit=(1.0, 0.1, 0.16), + strength=1.2) + trap_end = principled("TrapEnd", (0.9, 0.12, 0.18), 0.35, emit=(1.0, 0.1, 0.16), + strength=1.5) + plinth_mat = principled("PlinthWalnut", (0.13, 0.055, 0.025), 0.45) + + shown = [obj] + for k, (o, d, p, n) in enumerate(rays): + shown.append(rod(f"Ray{k}", o, p, 0.022, beam)) + shown.append(sphere(f"Emitter{k}", o, 0.07, emitter)) + shown.append(ring(f"Hit{k}", p, n, 0.10, 0.045, hit_mat)) + + trap = [rod("TrapRay", t_o, t_end, 0.016, trap_beam), + sphere("TrapEmitter", t_o, 0.06, trap_end)] + if not t_ok: + trap.append(sphere("TrapMissEnd", t_end, 0.03, trap_end)) + + # a low walnut plinth the block stands on (block bottom at z = loc - scale) + base_z = TARGET_LOC[2] - TARGET_SCALE[2] + pme = bpy.data.meshes.new("Plinth") + bm = bmesh.new() + try: + res = bmesh.ops.create_cone(bm, cap_ends=True, segments=64, radius1=1.9, + radius2=1.9, depth=base_z) + for v in res["verts"]: + v.co.z += base_z / 2 + bm.to_mesh(pme) + finally: + bm.free() + pme.materials.append(plinth_mat) + for poly in pme.polygons: + poly.use_smooth = True + plinth = bpy.data.objects.new("Plinth", pme) + scene.collection.objects.link(plinth) + plinth.location = (TARGET_LOC[0], TARGET_LOC[1], 0.0) + pb = plinth.modifiers.new("Chamfer", 'BEVEL') + pb.width = 0.02 + pb.segments = 3 + pb.limit_method = 'ANGLE' + + floor_me = bpy.data.meshes.new("Floor") + bm = bmesh.new() + try: + bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=30.0) + bm.to_mesh(floor_me) + finally: + bm.free() + fmat = bpy.data.materials.new("Studio") + fmat.use_nodes = True + fb = fmat.node_tree.nodes["Principled BSDF"] + fb.inputs["Base Color"].default_value = (0.03, 0.032, 0.037, 1.0) + fb.inputs["Roughness"].default_value = 0.7 + floor_me.materials.append(fmat) + floor = bpy.data.objects.new("Floor", floor_me) + scene.collection.objects.link(floor) + wall = bpy.data.objects.new("Wall", floor_me.copy()) + wall.location = (0.0, 7.5, 0.0) + wall.rotation_euler = (math.radians(90), 0.0, 0.0) + scene.collection.objects.link(wall) + + world = bpy.data.worlds.new("World") + world.use_nodes = True + world.node_tree.nodes["Background"].inputs["Color"].default_value = (0.02, 0.021, 0.025, 1.0) + scene.world = world + + centre = Vector((TARGET_LOC[0], TARGET_LOC[1], 1.05)) + + def light(name, loc, energy, size, col, aim): + ld = bpy.data.lights.new(name, 'AREA') + ld.energy = energy; ld.size = size; ld.color = col + ob = bpy.data.objects.new(name, ld) + ob.location = loc + ob.rotation_euler = (Vector(aim) - Vector(loc)).to_track_quat('-Z', 'Y').to_euler() + scene.collection.objects.link(ob) + + light("Key", (-4.0, -5.0, 6.0), 520.0, 4.0, (1.0, 0.96, 0.9), centre) + light("Fill", (5.5, -4.0, 2.5), 110.0, 6.0, (0.75, 0.85, 1.0), centre) + light("Rim", (-1.0, 5.0, 6.0), 320.0, 3.0, (0.6, 0.78, 1.0), centre) + light("Wedge", (2.5, 4.0, 3.0), 420.0, 5.0, (1.0, 0.76, 0.5), (4.0, 7.5, 1.0)) + + cam_data = bpy.data.cameras.new("Cam") + cam_data.lens = 50.0 + cam = bpy.data.objects.new("Cam", cam_data) + cam.location = centre + 1.15 * Vector((-5.2, -8.6, 4.4)) + scene.collection.objects.link(cam) + aim = bpy.data.objects.new("Aim", None) + aim.location = centre + scene.collection.objects.link(aim) + tr = cam.constraints.new('TRACK_TO') + tr.target = aim + tr.track_axis = 'TRACK_NEGATIVE_Z' + tr.up_axis = 'UP_Y' + scene.camera = cam + + scene.render.engine = 'CYCLES' if engine == 'cycles' else eevee_engine_id() + if engine == 'cycles': + scene.cycles.samples = 48 + else: + try: + scene.eevee.taa_render_samples = 64 + except AttributeError: + pass + scene.render.resolution_x = 1280 + scene.render.resolution_y = 720 + scene.render.image_settings.file_format = 'PNG' + scene.render.filepath = path + # AgX would wash the emissive orange rays toward pastel (docs/VISUAL-STYLE.md) + scene.view_settings.view_transform = 'Standard' + bpy.context.view_layer.update() + # Layer 1 framing gate (silhouette matte) — exit 10 on violation + fcode = gallery_framing.check_framing( + scene, cam, + hero=shown + [plinth], + elements=shown + trap + [plinth], + stage=[floor, wall], + ) + if fcode: + return fcode + bpy.ops.render.render(write_still=True) + if not (os.path.exists(path) and os.path.getsize(path) > 0): + print("ERROR: render produced no file", file=sys.stderr) + return 6 + return 0 + + +def main(): + argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else [] + p = argparse.ArgumentParser() + p.add_argument("--output", default=None, help="optional: render a still PNG here") + p.add_argument("--engine", default="eevee", choices=("eevee", "cycles"), + help="render engine for --output (cycles for GPU-less hosts)") + p.add_argument("--world-to-object", action="store_true", + help="feed world coords to Object.ray_cast in the checked path (must fail)") + args = p.parse_args(argv) + + obj = build_target() + code = check(obj, world_to_object=args.world_to_object) + if code: + return code + + if args.output: + rcode = render_still(obj, os.path.abspath(args.output), args.engine) + if rcode: + return rcode + print(f"rendered still {args.output}") + + print("ray-cast-space OK") + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except Exception as e: + import traceback; traceback.print_exc(); print(f"FATAL: {e}", file=sys.stderr); sys.exit(1) diff --git a/tests/smoke/catalog.json b/tests/smoke/catalog.json index 4feccabd..48545a62 100644 --- a/tests/smoke/catalog.json +++ b/tests/smoke/catalog.json @@ -75,6 +75,8 @@ {"name": "gn-socket-rename", "script": "examples/gn-socket-rename/gn_socket_rename.py"}, {"name": "eval-mesh-datablock-name", "script": "examples/eval-mesh-datablock-name/eval_mesh_datablock_name.py"}, {"name": "mesh-automasking-settings", "script": "examples/mesh-automasking-settings/mesh_automasking_settings.py"}, + {"name": "ray-cast-space", "script": "examples/ray-cast-space/ray_cast_space.py"}, + {"name": "lattice-deform", "script": "examples/lattice-deform/lattice_deform.py"}, {"name": "shipping-crate", "script": "showcase/shipping-crate/shipping_crate.py"}, {"name": "stone-well", "script": "showcase/stone-well/stone_well.py"}, {"name": "wooden-barrel", "script": "showcase/wooden-barrel/wooden_barrel.py"},