You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 44cdf87
Browse filesBrowse the repository at this point in the historyBrowse files
feat: add high-to-low tangent normal bake skill, snippets, and example (#140)
Cycles cage-bake is stochastic and CI is CPU-only, so the witness uses
tolerance gates and a --flat-source falsifier rather than byte-identity.
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This repository ships **15 skills, 9 rules, 3 templates, 24 snippets, and 54 examples** for Blender Python development targeting Blender 5.2 LTS (current stable) with Blender 4.5 LTS fallback support. Blender 5.1 is prior stable.
39
+
This repository ships **16 skills, 9 rules, 3 templates, 27 snippets, and 55 examples** for Blender Python development targeting Blender 5.2 LTS (current stable) with Blender 4.5 LTS fallback support. Blender 5.1 is prior stable.
40
40
41
41
The content is consumed by AI coding agents (Cursor, Claude Code, any MCP-capable client) when working on Blender add-ons, geometry nodes scripts, batch pipelines, or animation tooling. There is no build step. Edit the markdown and Python files directly.
42
42
@@ -679,6 +679,22 @@ keeps its closed-form counts), each LOD's evaluated triangle count lands within
679
679
survives within 1e-3 — with the aggressive-ratio nose-tip collapse documented
680
680
as the caught failure mode.
681
681
682
+
</td>
683
+
</tr>
684
+
<tr>
685
+
<tdwidth="46%"valign="middle">
686
+
<ahref="examples/bake-normal-high-to-low/"><imgsrc="examples/bake-normal-high-to-low/preview.webp"alt="Bake normal high to low: an unlit tangent-space normal map card of a six-lobe riveted hatch beside the collapse-decimated bronze plate wearing that map, dark studio" /></a>
@@ -95,7 +96,8 @@ Audit pass on v0.1.0 content: standards-version markers bumped from `1.9.1` to `
95
96
96
97
Provider-agnostic GLB-in / engine-ready-out. This repo does not generate meshes.
97
98
98
-
-**Post-generation cleanup skills.** Import and unit-scale normalization, transform apply and origin, poly-budget decimate, LOD chain, collision mesh. Phase 1 shipped in v0.54.0 as `ai-mesh-cleanup`, four snippets, two rules. Bake/UV/atlas follow on.
99
+
-**Post-generation cleanup skills.** Import and unit-scale normalization, transform apply and origin, poly-budget decimate, LOD chain, collision mesh. Phase 1 shipped in v0.54.0 as `ai-mesh-cleanup`, four snippets, two rules.
100
+
-**High-to-low normal bake.****Delivered.** Skill `bake-high-to-low`, snippets `setup_bake_target_image.py` / `bake_normal_high_to_low.py` / `save_baked_image.py`, witness `examples/bake-normal-high-to-low/`. Cycles CPU cage bake; statistical gates, not byte-identity. UV transfer and atlas packing remain a later phase. Template integration remains a later phase.
99
101
-**Engine export presets.****Delivered.** Unity (Y-up glTF), Godot (Z-up glTF, meters), Unreal (centimeter glTF bake and FBX `global_scale`). Skill `engine-export-presets`, three snippets, rule `use-correct-axis-rna-per-exporter`, witness `examples/export-preset-axis/`. Draco remains opt-in via `gltf_draco_export.py`.
100
102
-**`ai-asset-pipeline-template/`.****Delivered.** Third template. Headless: GLB path in; LOD set, convex or box collider, engine-preset export; explicit CI exit codes. Pattern: `templates/headless-batch-script-template/`.
101
103
-**Live-session agent bridge.** Research spike, not a committed deliverable. MCP server or socket listener so an agent can execute against a running Blender instance instead of blind `--background` scripts. Built on `templates/extension-addon-template/`. Needs its own design pass. Unpinned.
@@ -136,6 +138,7 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
136
138
-~~Lightmap UV channel witness~~**SHIPPED** as `examples/lightmap-uv-channel/` — two-channel UV contract on a market cart: per-part `UVMap`/`UVLight` with `active`/`active_render` re-asserted after the ops (edit-mode UV ops clear both flags; `uv_layers.new()` never moves them), UV0 drift 0.0 (clobber trap measured 2.068), every UV1 loop in [0,1], 0 overlapping islands via independent binned strict-SAT (15 hits when falsified), min island distance 0.00401 vs nominal margin 0.002 (`MARGIN_DIV × 0.01` semantics measured live); held `MeshUVLoopLayer.data` after edit-mode UV ops segfaults 4.5.11 (5/5, EXCEPTION_ACCESS_VIOLATION), silent no-op pack without prior unwrap; byte-identical on 4.5.11 and 5.1.2 (3680 islands)
137
139
- ~~Socket attach-point witness~~ **SHIPPED** as `examples/socket-attach-points/` — named `SKT_` empties as the spawn contract on a survey drone: 7 socket world matrices within 1.788e-07 of the authored transform with orthonormal right-handed bases (Gram 3.576e-07, det err 2.980e-07), socket +Z == the mount pad's Newell normal (1.794e-07) by a quaternion-swing construction independent of the Gram-Schmidt basis, origin on the mount-face centroid (6.687e-08), documented up-axis fallback for the +Z/−Z mounts, module seating offset exactly 0.0 with strictly identity local matrices, rigid invariance under a re-pose (2.384e-07); `transform_apply` on an **Empty** root preserves world matrices (2.235e-07) but clears **7/7** `matrix_parent_inverse` and pushes the root scale down into every child (0.35 for an applied 1.35) — both halves asserted; a child left selected during the apply drifts sockets **2.335 m**; `bm.normal_update()` does not fix inward winding (`recalc_face_normals` does — the lofted fuselage rendered as a flat white panel); no-parent-inverse probe jumps 0.690128 m; byte-identical on 4.5.11 and 5.1.2
138
140
- ~~Vertex-colour AO witness~~ **SHIPPED** as `examples/vertex-color-ao/` — baked occlusion in a colour attribute on a stone village well, checked against a closed form rather than a captured value: the cosine-weighted hemisphere integral for an infinitely wide wall of height H at distance d is `AO = 1 − ½(1 − 1/√(1+k²))`, `k = H/d`, matched to **6.760e-04** across k = 60.0…0.60 (gate 2.5e-03, QMC noise ~1/√n at 4096 samples); unoccluded plate bakes to **exactly 1.0**; strictly monotone 0.508301 → 0.928467; asset values in [0,1] with spread 1.0; **`BYTE_COLOR` is sRGB-encoded 8-bit, not linear** (0.735 → 0.7379107, peak round-trip error 3.782e-03, matching an independent encode/quantise/decode model to 3.189e-07) while `FLOAT_COLOR` is exact; both survive depsgraph evaluation at deviation 0.0; `bmesh.ops.bevel` offsets along **cached** face normals and flips outward past 90° of staleness (12 mm below ground on a ring of boxes, fixed by `normal_update()`); point-domain AO needs subdivision or the crevice gradient never reaches the attribute; `color_attributes` enumeration order differs between 4.5.11 and 5.1.2 — look up by name; byte-identical on 4.5.11 and 5.1.2 (6966 verts)
141
+
-~~High-to-low tangent normal bake~~**SHIPPED** as `examples/bake-normal-high-to-low/` — Cycles CPU `type='NORMAL'` cage bake onto a `DECIMATE COLLAPSE` hatch; statistical gates (detail frac 0.7211 / MAD 0.09356 vs flat 0.0000 / 0.00277); `--flat-source` exits 5; RNA identical on 4.5.11, 5.1.2, 5.2.1; byte-identity is not the contract
139
142
- UV atlas **utilization** witness — coverage/wasted-texel closed forms for a packed lightmap atlas (the non-overlap, unit-square, margin, and active/active_render contracts shipped in `lightmap-uv-channel`; utilization is the remaining unbuilt slice of the old "UV atlas pack" candidate)
140
143
-~~GAMMA_CROSS blend-curve witness~~**SHIPPED** as `examples/vse-gamma-cross/` — the cross blends in a gamma-0.5 space: `((1-t)·√A + t·√B)²` with `t = (frame − start)/duration`, never 1 inside the effect; mid-cross dips 0.115 below the sRGB lerp from crimson/teal (closed form (0.341, 0.349, 0.463) confirmed per frame); AgX-default sampling poisons the fit (0.146 red-channel error, `view_transform='Standard'` mandatory); deleting a consumed input orphans-and-deletes the effect — follow-up to `vse-cut-list`
141
144
- Falsy `bpy_prop_collection` trap snippet: an empty collection is falsy, so `editor.strips or editor.sequences` silently falls through to the legacy accessor on an empty timeline — always branch on `hasattr`; likely generalizes across the API (found authoring `vse-cut-list`)
0 commit comments