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
fix(site): correct landing-page claims and render README tables on gallery pages (#208)
A review of the live Pages site found the landing page naming Blender 5.1
as the primary target and calling every render a CI artifact, when CI
checks 5.2 LTS and 4.5 LTS and renders only swatch-grid. The Rules table's
Scope column was empty because the parser stopped at `description`, and
render cards showed no keyboard focus ring. On the gallery, the README
converter had no table, emphasis, ordered-list or image support, so all
182 budget tables printed as raw pipe text.
- template: 5.2 LTS / 4.5 LTS wording, accurate render claim, visible
focus on render cards, showcase CTA links to #tag=showcase, rules and
templates copy match the repo, stats rendered server-side
- build_site: parse `globs` YAML lists for the rule scope column; HUD
example count includes check-only examples (plugin.json)
- build_gallery: pipe tables, *emphasis*, ordered lists, inline images;
drop the README's own preview image, which duplicates the hero
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
<p>Base triangles dropped from <strong>6616 to 2988</strong> in the quality pass: overlapping face boxes and a beveled superellipse horn became one slotted slab plus a circular oval loft. Hidden coincident faces were the waste.</p>
270
275
<p>DECIMATE COLLAPSE triangle counts are <strong>not</strong> identical across series — the gate is a ratio band, not an exact count. Bake pixels are stochastic; the gate is <code>has_data</code> plus operator <code>FINISHED</code>, not byte-identity. Stave-width jitter uses fixed seed 17. Export byte counts differ by 16 B on 5.2.1 (glTF serializer), not a gated axis.</p>
271
276
<h3>Hygiene</h3>
272
277
<p>Recomputed from the generated mesh, not asserted about the script.</p>
273
-
<p>| Axis | Declared | Measured (all three) | | --- | --- | --- | | Non-manifold edges | 0 | 0 | | Loose verts / edges | 0 / 0 | 0 / 0 | | Doubles merged at 1e-5 | 0 | 0 | | Zero-area faces | 0 | 0 | | N-gons | 0 | 0 | | Coplanar disjoint face pairs | 0 | 0 | | Grounded: <code>zmin</code> | within 1e-4 of 0 | 0.0000 | | Named supports: 16 staves | each <code>zmin</code> ≤ 0.001 | 16, stave_z 0.00000 | | Body plan | 0.621 m long × 0.180 m high ± 0.05 | 0.6210 × 0.1800 |</p>
278
+
<divclass="table-wrap"><table><thead><tr><thscope="col">Axis</th><thscope="col">Declared</th><thscope="col">Measured (all three)</th></tr></thead><tbody><tr><td>Non-manifold edges</td><td>0</td><td>0</td></tr><tr><td>Loose verts / edges</td><td>0 / 0</td><td>0 / 0</td></tr><tr><td>Doubles merged at 1e-5</td><td>0</td><td>0</td></tr><tr><td>Zero-area faces</td><td>0</td><td>0</td></tr><tr><td>N-gons</td><td>0</td><td>0</td></tr><tr><td>Coplanar disjoint face pairs</td><td>0</td><td>0</td></tr><tr><td>Grounded: <code>zmin</code></td><td>within 1e-4 of 0</td><td>0.0000</td></tr><tr><td>Named supports: 16 staves</td><td>each <code>zmin</code> ≤ 0.001</td><td>16, stave_z 0.00000</td></tr><tr><td>Body plan</td><td>0.621 m long × 0.180 m high ± 0.05</td><td>0.6210 × 0.1800</td></tr></tbody></table></div>
<p>Each violates one named budget. All six were run on 4.5.11, 5.1.2 and 5.2.1 and returned the same code on each.</p>
278
-
<p>| Flag | Budget violated | Exit | | --- | --- | --- | | <code>--skip-decimate</code> | LOD1 ratio band | 9 | | <code>--stray-vert</code> | loose vertex count is 0 | 15 | | <code>--lift-z</code> | bounding box <code>zmin</code> is 0 | 16 | | <code>--short-staves</code> | named stave supports at Z=0 | 16 | | <code>--float-anvil</code> | foot-on-head gap | 17 | | <code>--round-band</code> | hoop bite band | 18 |</p>
283
+
<divclass="table-wrap"><table><thead><tr><thscope="col">Flag</th><thscope="col">Budget violated</th><thscope="col">Exit</th></tr></thead><tbody><tr><td><code>--skip-decimate</code></td><td>LOD1 ratio band</td><td>9</td></tr><tr><td><code>--stray-vert</code></td><td>loose vertex count is 0</td><td>15</td></tr><tr><td><code>--lift-z</code></td><td>bounding box <code>zmin</code> is 0</td><td>16</td></tr><tr><td><code>--short-staves</code></td><td>named stave supports at Z=0</td><td>16</td></tr><tr><td><code>--float-anvil</code></td><td>foot-on-head gap</td><td>17</td></tr><tr><td><code>--round-band</code></td><td>hoop bite band</td><td>18</td></tr></tbody></table></div>
<p>File-local. <code>9</code> is a valid check code. <code>10</code> is reserved for <code>gallery_framing.check_framing</code> on the <code>--output</code> path. <code>15</code>–<code>19</code> are the hygiene and joint-fit family.</p>
291
-
<p>| Code | Meaning | | --- | --- | | 0 | Success | | 1 | Uncaught exception (FATAL wrapper) | | 2 | argparse / usage | | 3 | Mesh did not build / no UV layer | | 4 | Base triangle count outside range | | 5 | Material count ≠ 2 distinct slots, or a face-count floor missed | | 6 | UVs outside 0..1 | | 7 | UV AABB overlap above tolerance | | 8 | World AABB off declared outer size | | 9 | LOD ratio band (<code>--skip-decimate</code> lands here) | | 10 | Framing gate (render path only) | | 11 | Collider triangle count above ceiling | | 12 | Bake did not finish or image has no data | | 13 | Export file missing or empty | | 14 | <code>--output</code> produced no file | | 15 | Mesh hygiene: loose, non-manifold, zero-area, doubles, n-gons, z-fight | | 16 | Not grounded: bounding box <code>zmin</code> off 0, or a named stave floats | | 17 | Joint fit: foot-on-head gap (<code>--float-anvil</code>) | | 18 | Seat: hoop bite band (<code>--round-band</code>) | | 19 | Body length or height off the stated real-world size |</p>
296
+
<divclass="table-wrap"><table><thead><tr><thscope="col">Code</th><thscope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td>Mesh did not build / no UV layer</td></tr><tr><td>4</td><td>Base triangle count outside range</td></tr><tr><td>5</td><td>Material count ≠ 2 distinct slots, or a face-count floor missed</td></tr><tr><td>6</td><td>UVs outside 0..1</td></tr><tr><td>7</td><td>UV AABB overlap above tolerance</td></tr><tr><td>8</td><td>World AABB off declared outer size</td></tr><tr><td>9</td><td>LOD ratio band (<code>--skip-decimate</code> lands here)</td></tr><tr><td>10</td><td>Framing gate (render path only)</td></tr><tr><td>11</td><td>Collider triangle count above ceiling</td></tr><tr><td>12</td><td>Bake did not finish or image has no data</td></tr><tr><td>13</td><td>Export file missing or empty</td></tr><tr><td>14</td><td><code>--output</code> produced no file</td></tr><tr><td>15</td><td>Mesh hygiene: loose, non-manifold, zero-area, doubles, n-gons, z-fight</td></tr><tr><td>16</td><td>Not grounded: bounding box <code>zmin</code> off 0, or a named stave floats</td></tr><tr><td>17</td><td>Joint fit: foot-on-head gap (<code>--float-anvil</code>)</td></tr><tr><td>18</td><td>Seat: hoop bite band (<code>--round-band</code>)</td></tr><tr><td>19</td><td>Body length or height off the stated real-world size</td></tr></tbody></table></div>
<p>A runnable example that rigs a tapered, segmented tube with a four-bone armature chain — <code>edit_bones</code> construction, name-bound vertex groups with smoothstep blend zones, a posed curl — and checks the depsgraph-evaluated result against closed-form linear blend skinning, following <ahref="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/mesh-editing-and-bmesh/SKILL.md"><code>mesh-editing-and-bmesh</code></a> and <ahref="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/depsgraph-and-evaluated-data/SKILL.md"><code>depsgraph-and-evaluated-data</code></a>.</p>
263
268
<p><strong>What it witnesses:</strong> the three contracts AI-generated rigging code most often gets wrong.</p>
264
-
<p>1. <code>edit_bones</code> only exists in edit mode — the collection is asserted empty in object mode and holding the full chain (heads/tails at closed-form positions) inside <code>mode_set(mode='EDIT')</code>. Outside edit mode, reads silently return nothing. 2. Vertex groups bind to bones <strong>by name</strong>; a typo deforms nothing without erroring. Every group here is named after its bone and the deform proves the binding. 3. The armature modifier is exactly linear blend skinning: for *every* vertex, <code>evaluated == Σ wᵢ · (pose_bone.matrix @ bone.matrix_local.inverted()) @ rest</code>. The check re-implements LBS from the pose matrices and compares the whole evaluated mesh (max error ~5e-7). The root ring must stay pinned and the tip must deflect — a straight tube is a failure.</p>
269
+
<ol><li><code>edit_bones</code> only exists in edit mode — the collection is asserted empty in object mode and holding the full chain (heads/tails at closed-form positions) inside <code>mode_set(mode='EDIT')</code>. Outside edit mode, reads silently return nothing.</li><li>Vertex groups bind to bones <strong>by name</strong>; a typo deforms nothing without erroring. Every group here is named after its bone and the deform proves the binding.</li><li>The armature modifier is exactly linear blend skinning: for <em>every</em> vertex, <code>evaluated == Σ wᵢ · (pose_bone.matrix @ bone.matrix_local.inverted()) @ rest</code>. The check re-implements LBS from the pose matrices and compares the whole evaluated mesh (max error ~5e-7). The root ring must stay pinned and the tip must deflect — a straight tube is a failure.</li></ol>
265
270
<p>The armature API is identical on Blender 4.5 LTS and 5.1 — no version gate needed. One portability hazard is baked in as a comment: interleaving <code>color_attributes</code> writes with <code>VertexGroup.add()</code> dangles the attribute reference when the deform layer is allocated (hard crash on 4.5, silent luck on 5.1), so the script finishes all weight writes before creating the color attribute.</p>
266
271
<p>The render shows rest → half curl → full curl left to right, with per-bone weight bands visualized through a <code>BoneTint</code> color attribute — the smooth color blends at the joints are the same weights the LBS check asserts.</p>
<p>Per-script sequential checks. <code>9</code> is a valid check code; there is no rule against it.</p>
279
-
<p>| Code | Meaning | | --- | --- | | 0 | Success | | 1 | Uncaught exception (FATAL wrapper) | | 2 | argparse / usage | | 3 | <code>edit_bones</code> populated in object mode | | 4 | Edit-mode bone chain off closed form | | 5 | Evaluated vertex count changed | | 6 | Evaluated mesh off closed-form LBS | | 7 | Root ring moved | | 8 | Tip did not deflect (<code>--zero-curl</code> lands here) | | 9 | <code>--output</code> produced no file |</p>
284
+
<divclass="table-wrap"><table><thead><tr><thscope="col">Code</th><thscope="col">Meaning</th></tr></thead><tbody><tr><td>0</td><td>Success</td></tr><tr><td>1</td><td>Uncaught exception (FATAL wrapper)</td></tr><tr><td>2</td><td>argparse / usage</td></tr><tr><td>3</td><td><code>edit_bones</code> populated in object mode</td></tr><tr><td>4</td><td>Edit-mode bone chain off closed form</td></tr><tr><td>5</td><td>Evaluated vertex count changed</td></tr><tr><td>6</td><td>Evaluated mesh off closed-form LBS</td></tr><tr><td>7</td><td>Root ring moved</td></tr><tr><td>8</td><td>Tip did not deflect (<code>--zero-curl</code> lands here)</td></tr><tr><td>9</td><td><code>--output</code> produced no file</td></tr></tbody></table></div>
280
285
<p>The <code>blender-smoke</code> workflow runs the check on Blender 5.2 LTS and 4.5 LTS (5.1 on the weekly cron, the <code>needs-5.1</code> PR label, or manual dispatch). Smoke does not pass <code>--output</code> or <code>--zero-curl</code>.</p>
0 commit comments