Skip to content

Commit 704b1e4

Browse files
authored
fix: audit game-pipeline arc heroes and stage vse-cut-list presentation (#78)
* fix: legibilize gltf-export-roundtrip labels at thumbnail scale The AUTHORED and ROUND-TRIP plaques are the render's argument, but the dark metallic text vanished at thumbnail. Diffuse light-grey material and larger type keep the round-trip story readable at 320x180. Render-path only; the check's closed forms and measured values are unchanged and re-verified on 5.1.2 and 4.5.11. README gains the pipeline-arc reference. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: anchor vertex-weight-limit accent glow to the pruned zones The teal ring sat on the forearm armor, reading as decoration while the actual pruned zones (the flex boots) stayed unmarked. The boots now carry the teal accent and the bright ring seals the elbow boot, so the glow marks the five-influence zones the limit prunes. Counts, weights, and measured check values are byte-identical; all three falsification probes re-run on the remodel (exits 4/6/8), check green on 5.1.2 and 4.5.11. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * fix: stage vse-cut-list hero as an editing-bay presentation The raw sequencer frame was stylistically the furthest hero from the house look. The render now makes two passes: the authentic VSE program wall (evidence, untouched) and a dark-studio editing bay whose reference monitor displays exactly that frame (presentation). The check and --check-pixels paths are unchanged and green on 5.1.2 and 4.5.11 with identical measured values; the 4.5 render path is proven locally. Includes the explicit-UV fix: the flat screen quad's Generated coords sampled one frame strip; UVs carry the full frame. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> * docs: cross-reference the pipeline arc and commit the audit contact sheet lod-decimate-chain's README gains the modeling/LOD - weighting - export stage references (the other two arc READMEs carry theirs in their fix commits), and the combined seven-cell audit contact sheet — four audited heroes beside the pinned calibration set — is committed per the contact-sheet gate. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com> --------- Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
1 parent 041f49f commit 704b1e4

18 files changed

Lines changed: 325 additions & 32 deletions

File tree

2.04 KB
Loading
556 Bytes
Loading
-1.11 KB
Loading
55.4 KB
Loading

docs/gallery/gltf-export-roundtrip/index.html

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ <h1>gltf-export-roundtrip</h1>
184184
</div>
185185
<section class="detail-section md">
186186
<p>A runnable example that builds a sci-fi supply crate — 35 beveled box shells with three material slots and box-mapped UVs — exports it with <code>bpy.ops.export_scene.gltf</code>, parses the file on disk, re-imports it, and verifies the whole round-trip against the depsgraph-evaluated mesh, following <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/depsgraph-and-evaluated-data/SKILL.md"><code>depsgraph-and-evaluated-data</code></a> and <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/headless-batch-scripting/SKILL.md"><code>headless-batch-scripting</code></a>.</p>
187+
<p><strong>Pipeline arc:</strong> modeling/LOD in <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/lod-decimate-chain"><code>lod-decimate-chain</code></a>, weighting in <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/vertex-weight-limit"><code>vertex-weight-limit</code></a>, export here.</p>
187188
<p><strong>What it witnesses:</strong> the interchange contracts AI-generated export code most often gets silently wrong.</p>
188189
<p>1. <strong>The +Y-up convention is baked into vertex data.</strong> glTF is +Y-up, Blender is +Z-up, and <code>export_yup=True</code> (the default) writes <code>(x, y, z) -&gt; (x, z, -y)</code> directly into the POSITION buffer — the node carries <strong>no</strong> rotation or scale. The check parses the <code>.gltf</code> JSON and asserts the accessor bounds equal the axis-converted evaluated bounding box, and that the node transform is absent. Exporting with <code>export_yup=False</code> ships raw Z-up data every engine displays lying on its back. 2. <strong><code>export_apply=True</code> ships the evaluated mesh, not the base cage.</strong> The crate&#x27;s bevel modifier lives only in the depsgraph; with flat shading and UV seams the exporter splits exactly one vertex per evaluated loop (7,560), so the on-disk POSITION count is an exact witness. <code>export_apply=False</code> silently writes the 624-vertex cage. 3. <strong>The round-trip is faithful.</strong> Re-imported positions (bit-exact here), loop normals (≤2e-4), box-mapped UVs (≤3e-5), and per-triangle material bindings all match the evaluated mesh. UVs are V-flipped on disk (glTF texture origin is top-left) and flipped back on import — both flips are proven by reading the <code>.bin</code> buffer directly.</p>
189190
<p><strong>Version witness (probed on Blender 4.5.11 LTS and 5.1.2):</strong> the operator signatures are byte-identical — 109 exporter properties, 20 importer properties, same defaults — and the exported JSON differs only in <code>asset.generator</code> (&quot;Khronos glTF Blender I/O v4.5.51&quot; vs &quot;v5.1.20&quot;). The example therefore runs identical kwargs on both versions and guards forward drift explicitly: every kwarg it passes must still exist in the operator&#x27;s RNA, so a future rename fails loudly instead of drifting silently. One genuine 5.x removal surfaced during authoring: <code>Mesh.calc_normals()</code> is gone (loop normals auto-compute on read) — calling it is itself a cross-version hazard, noted in the code.</p>
@@ -680,15 +681,17 @@ <h2>Source</h2>
680681
pm = bpy.data.materials.new(<span class="s">&quot;PlaqueMetal&quot;</span>)
681682
pm.use_nodes = <span class="k">True</span>
682683
pb = pm.node_tree.nodes[<span class="s">&quot;Principled BSDF&quot;</span>]
683-
pb.inputs[<span class="s">&quot;Base Color&quot;</span>].default_value = (<span class="n">0.16</span>, <span class="n">0.17</span>, <span class="n">0.19</span>, <span class="n">1.0</span>)
684-
pb.inputs[<span class="s">&quot;Metallic&quot;</span>].default_value = <span class="n">0.9</span>
685-
pb.inputs[<span class="s">&quot;Roughness&quot;</span>].default_value = <span class="n">0.3</span>
684+
<span class="c"># diffuse light-grey, not metal: the AUTHORED/ROUND-TRIP labels are the</span>
685+
<span class="c"># render&#x27;s argument and must survive thumbnail scale on the dark floor</span>
686+
pb.inputs[<span class="s">&quot;Base Color&quot;</span>].default_value = (<span class="n">0.42</span>, <span class="n">0.44</span>, <span class="n">0.48</span>, <span class="n">1.0</span>)
687+
pb.inputs[<span class="s">&quot;Metallic&quot;</span>].default_value = <span class="n">0.2</span>
688+
pb.inputs[<span class="s">&quot;Roughness&quot;</span>].default_value = <span class="n">0.6</span>
686689

687690
<span class="k">def</span> plaque(text, x):
688691
cu = bpy.data.curves.new(<span class="s">&quot;Plaque&quot;</span>, <span class="s">&#x27;FONT&#x27;</span>)
689692
cu.body = text
690693
cu.align_x = <span class="s">&#x27;CENTER&#x27;</span>
691-
cu.size = <span class="n">0.24</span>
694+
cu.size = <span class="n">0.30</span>
692695
cu.extrude = <span class="n">0.008</span>
693696
ob = bpy.data.objects.new(<span class="s">&quot;Plaque&quot;</span>, cu)
694697
ob.location = (x, -<span class="n">1.55</span>, <span class="n">0.01</span>)

docs/gallery/lod-decimate-chain/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ <h1>lod-decimate-chain</h1>
184184
</div>
185185
<section class="detail-section md">
186186
<p>A runnable example that builds a retro toy rocket — a lathed body with an ogive nose, three swept fin plates, a porthole, every dimension a closed form — and evaluates it at LOD0/1/2 through the Decimate modifier via the depsgraph, following <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/depsgraph-and-evaluated-data/SKILL.md"><code>depsgraph-and-evaluated-data</code></a> and <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/mesh-editing-and-bmesh/SKILL.md"><code>mesh-editing-and-bmesh</code></a>.</p>
187+
<p><strong>Pipeline arc:</strong> modeling/LOD here, weighting in <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/vertex-weight-limit"><code>vertex-weight-limit</code></a>, export in <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/gltf-export-roundtrip"><code>gltf-export-roundtrip</code></a>.</p>
187188
<p><strong>What it witnesses:</strong> the modifier-based LOD contract that game asset pipelines rely on.</p>
188189
<p>1. <strong>Decimate is non-destructive and lives in the depsgraph.</strong> The evaluated mesh carries the reduction; the original datablock is byte-identical before and after evaluation. The check proves both — evaluated counts drop while <code>obj.data</code> keeps the closed-form counts (1,147 verts / 2,260 tris) — and every evaluated reference is released with <code>to_mesh_clear()</code>. An LOD chain that bakes the reduction into <code>obj.data</code> destroys the asset&#x27;s LOD0. 2. <strong>The COLLAPSE ratio is a target, not a guarantee.</strong> Each LOD&#x27;s evaluated triangle count must land within 5% of <code>ratio x base_tris</code> — measured 0.00% at ratio 0.5 (1,130 tris) and 0.44% at ratio 0.18 (405 tris). A stacked second Decimate halves the effective ratio (50% excursion, caught); a dropped modifier leaves evaluated == original (caught). 3. <strong>LODs preserve silhouette-critical dimensions.</strong> Height (3.12) and fin span are the rocket&#x27;s readability; the evaluated bbox holds the base bbox within 1e-3 at every level (measured 7.7e-6). Decimate has no vertex pinning, so this is a real risk, not a formality: at an aggressive ratio 0.02 the nose tip collapses (bbox drift 0.0206, caught).</p>
189190
<p>The Decimate modifier API (<code>decimate_type=&#x27;COLLAPSE&#x27;</code>, <code>ratio</code>) is stable between Blender 4.5 LTS and 5.1 — the example runs identically on both, which is itself the version witness (measured values match to the digit).</p>

docs/gallery/vertex-weight-limit/index.html

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,11 @@ <h1>vertex-weight-limit</h1>
184184
</div>
185185
<section class="detail-section md">
186186
<p>A runnable example that rigs a mech arm — pedestal mount and pauldron, orange armor shells, ribbed flex boots, wrist, three claw prongs — with deliberately rich five-bone weight bumps in the boots, then enforces the game-engine <strong>maximum of four bone influences per vertex</strong> through the data API, following <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/skills/mesh-editing-and-bmesh/SKILL.md"><code>mesh-editing-and-bmesh</code></a> and building on the linear-blend-skinning precedent of <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/armature-bend"><code>armature-bend</code></a>.</p>
187+
<p><strong>Pipeline arc:</strong> modeling/LOD in <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/lod-decimate-chain"><code>lod-decimate-chain</code></a>, weighting here, export in <a href="https://github.com/TMHSDigital/Blender-Developer-Tools/tree/main/examples/gltf-export-roundtrip"><code>gltf-export-roundtrip</code></a>.</p>
187188
<p><strong>What it witnesses:</strong> the skinning constraint every game engine enforces and AI-generated rigging code most often violates silently.</p>
188189
<p>1. <strong>The limit is a data-API operation, not a context operator.</strong> Instead of <code>bpy.ops.object.vertex_group_limit_total</code>, the example reads each vertex&#x27;s groups, keeps the top four by weight, <code>VertexGroup.remove</code>s the rest, and renormalizes the survivors. Dropping without renormalizing leaves sums at 0.986 — a mesh that shrinks toward the origin under load (the check&#x27;s measured failure, 1.438e-02 off unit sum). 2. <strong>The armature modifier is still exactly linear blend skinning</strong> after the limit: every depsgraph-evaluated vertex equals <code>Σ wᵢ · (pose.matrix @ bone.matrix_local.inverted()) @ rest</code>, with the weights <strong>read back from the mesh&#x27;s own deform layer</strong> (<code>v.groups</code>) — the weights on the mesh are the contract, not the weights you meant to write. Measured <code>lbs_err = 3.0e-07</code>. 3. <strong>Pruning must not damage the pose.</strong> Evaluated positions before and after the limit are held within 0.05 (measured 3.0e-03), the pedestal mount stays exactly pinned (Root is unposed), and the pre-limit authoring really carries five influences in the boots — otherwise the witness would be vacuous.</p>
189190
<p>The vertex-group API (<code>v.groups</code>, <code>VertexGroup.add</code>/<code>remove</code>) is stable between Blender 4.5 LTS and 5.1 — the example runs identically on both, which is itself the version witness (measured values match to the digit).</p>
190-
<p>The render shows the pruned arm mid-pose: the elbow bellows and wrist boot flex through the bend, the teal accent ring rides the forearm — proof that the limited weights still deform as authored.</p>
191+
<p>The render shows the pruned arm mid-pose: the flex boots carry the teal accent — the five-influence zones the limit prunes glow at the elbow and wrist, sealed by the bright ring on the elbow boot — proof that the limited weights still deform as authored.</p>
191192
<h2>Run</h2>
192193
<pre><code># Cheap correctness check (no render) — the CI check:
193194
blender --background --python vertex_weight_limit.py --
@@ -315,8 +316,9 @@ <h2>Source</h2>
315316
(<span class="n">1.82</span>, <span class="n">0.26</span>), (<span class="n">2.00</span>, <span class="n">0.24</span>), (<span class="n">2.10</span>, <span class="n">0.27</span>),
316317
(<span class="n">2.16</span>, <span class="n">0.27</span>), (<span class="n">2.22</span>, <span class="n">0.24</span>), (<span class="n">2.45</span>, <span class="n">0.22</span>)],
317318
ORANGE), <span class="s">&quot;Elbow&quot;</span>)
318-
<span class="c"># teal accent ring inset on the forearm</span>
319-
tag(lathe_part(bm, [(<span class="n">2.10</span>, <span class="n">0.275</span>), (<span class="n">2.16</span>, <span class="n">0.275</span>)], ACCENT), <span class="s">&quot;Elbow&quot;</span>)
319+
<span class="c"># teal accent ring sealing the elbow boot — the primary</span>
320+
<span class="c"># five-influence zone the limit prunes</span>
321+
tag(lathe_part(bm, [(<span class="n">1.33</span>, <span class="n">0.245</span>), (<span class="n">1.39</span>, <span class="n">0.245</span>)], ACCENT), <span class="s">&quot;Elbow&quot;</span>)
320322
<span class="c"># wrist flex boot + ball (second &gt;4-influence region)</span>
321323
tag(lathe_part(bm, [(<span class="n">2.45</span>, <span class="n">0.21</span>), (<span class="n">2.52</span>, <span class="n">0.17</span>), (<span class="n">2.60</span>, <span class="n">0.20</span>),
322324
(<span class="n">2.68</span>, <span class="n">0.16</span>), (<span class="n">2.76</span>, <span class="n">0.19</span>), (<span class="n">2.84</span>, <span class="n">0.16</span>), (<span class="n">2.95</span>, <span class="n">0.15</span>)], RUBBER), <span class="s">&quot;FLEX&quot;</span>)
@@ -518,7 +520,8 @@ <h2>Source</h2>
518520
<span class="k">return</span> [
519521
pbr(<span class="s">&quot;Gunmetal&quot;</span>, (<span class="n">0.11</span>, <span class="n">0.12</span>, <span class="n">0.14</span>), <span class="n">0.9</span>, <span class="n">0.32</span>),
520522
pbr(<span class="s">&quot;HazardOrange&quot;</span>, (<span class="n">0.82</span>, <span class="n">0.30</span>, <span class="n">0.08</span>), <span class="n">0.10</span>, <span class="n">0.45</span>),
521-
pbr(<span class="s">&quot;FlexRubber&quot;</span>, (<span class="n">0.05</span>, <span class="n">0.05</span>, <span class="n">0.06</span>), <span class="n">0.0</span>, <span class="n">0.85</span>),
523+
pbr(<span class="s">&quot;FlexRubber&quot;</span>, (<span class="n">0.04</span>, <span class="n">0.13</span>, <span class="n">0.17</span>), <span class="n">0.0</span>, <span class="n">0.80</span>,
524+
emission=(<span class="n">0.06</span>, <span class="n">0.30</span>, <span class="n">0.34</span>), strength=<span class="n">0.38</span>),
522525
pbr(<span class="s">&quot;TealAccent&quot;</span>, (<span class="n">0.03</span>, <span class="n">0.22</span>, <span class="n">0.26</span>), <span class="n">0.0</span>, <span class="n">0.35</span>,
523526
emission=(<span class="n">0.10</span>, <span class="n">0.65</span>, <span class="n">0.72</span>), strength=<span class="n">2.2</span>),
524527
]

0 commit comments

Comments
 (0)