Skip to content

Commit 1a671b2

Browse files
authored
fix: restage the game-prop pair heroes from deployed-page review (#98)
Second pass after seeing both heroes at gallery scale: collision-hull-proxy: the bonnet gains its overhanging brim (the pawn-like silhouette is gone; the proud brim is paid for with a cage row, exactly the containment trade-off the example teaches — the hull still measures 70 faces because the enlarged nut cage swallows the now-interior top dome ring), the operating nut is enlarged and re-materialized in lighter cast iron so it actually reads inside the shell peak, the barrel groove deepens (free — concave), and Cycles rises to 64 samples against enamel blotch. Measured values shift accordingly and every published number is corrected: body volume 1.022381, containment 4.4e-08, convexity 4.8e-08, dense-mesh hull 380 faces (was 368; ROADMAP still carried the pre-correction 374). Checks re-proven byte-identical on 4.5.11 and 5.1.2; all three falsification probes re-confirmed (exit 3 escape 0.730000, exit 5 volume -1.022381, exit 4 three border edges). custom-normals-shade: render-only — the flat-shaded can lifts (fill 120->150 W), the strip light softens and narrows its energy (460->400 W, size 1.0->1.35) so the by-angle can's highlight band stops short of clipping, the olive deepens, 64 samples. Geometry untouched; check values unchanged, re-verified exit 0 on both binaries. Luminance: hydrant 137.0, cans 144.6 (was 146.3, now inside the calibration band). Contact sheets re-composited in place. Signed-off-by: fOuttaMyPaint <TMhospitalitystrategies@gmail.com>
1 parent c85a935 commit 1a671b2

15 files changed

Lines changed: 49 additions & 41 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,8 +605,8 @@ The compound-collision contract prop pipelines (engines generally,
605605
FiveM/GTA-style prop workflows specifically) ingest: one convex hull piece
606606
per part group, built with `bmesh.ops.convex_hull` from a coarse
607607
`sec(π/n)`-inflated cage — never the dense render mesh, whose hull measures
608-
368 faces, over the 255-face per-piece engine budget. Closed-form plane
609-
tests prove containment (5.9e-08), convexity, watertightness, outward
608+
380 faces, over the 255-face per-piece engine budget. Closed-form plane
609+
tests prove containment (4.4e-08), convexity, watertightness, outward
610610
winding, and Euler characteristic 2 per piece. Proud details cost cage rows;
611611
concave grooves are free.
612612

ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ Not committed; target list for the next content version. (v0.3.0 shipped the smo
112112
- Degenerate-bevel weld hazard (snippet or rule): bevel width ≥ half a box dimension creates zero-area faces whose loops weld on glTF export (found authoring `gltf-export-roundtrip`, where the count check caught a 36-vertex weld)
113113
- ~~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`
114114
- 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`)
115-
- ~~Collision compound witness~~ **SHIPPED** as `examples/collision-hull-proxy/` — game-prop collision as a compound of convex pieces, each a `bmesh.ops.convex_hull` of a coarse `sec(π/n)`-inflated cage (containment 5.9e-08, watertight, positive signed volume, Euler 2, per-piece 255-face budget: body 70, caps 60×3, compound 250); a hull of the dense render mesh measures 374 faces — over budget — which is why pipelines hull cages; proud details cost cage rows, concave grooves are free; byte-identical on 4.5.11 and 5.1.2
115+
- ~~Collision compound witness~~ **SHIPPED** as `examples/collision-hull-proxy/` — game-prop collision as a compound of convex pieces, each a `bmesh.ops.convex_hull` of a coarse `sec(π/n)`-inflated cage (containment 4.4e-08, watertight, positive signed volume, Euler 2, per-piece 255-face budget: body 70, caps 60×3, compound 250); a hull of the dense render mesh measures 380 faces — over budget — which is why pipelines hull cages; proud details cost cage rows, concave grooves are free; byte-identical on 4.5.11 and 5.1.2
116116
- ~~Custom-normals / shade-by-angle witness~~ **SHIPPED** as `examples/custom-normals-shade/` — the post-4.1 shading contract: `use_auto_smooth`/`use_custom_normals`/`calc_normals` are AttributeError on BOTH 4.5.11 and 5.1.2; `set_sharp_from_angle` sharp sets match an independent dihedral recompute exactly (188/388 edges, 3 meshes); evaluated normal welds/splits exact (0.0 dev); custom split normals survive depsgraph evaluation within int16 quantization (1.407e-04, not float-exact); **divergence**: the legacy `shade_auto_smooth` operator CANCELS headless on 4.5 ("Asset loading is unfinished", mesh untouched, no exception) while 5.1 FINISHES with the Smooth-by-Angle NODES modifier — the data API is the portable path
117117
- prop-origin-transform witness — origin to base center, `transform_apply` through the data API, delta transforms, `matrix_parent_inverse` so parented children do not teleport; closed forms: post-apply scale exactly (1,1,1), local bbox min Z == 0, world bbox unchanged (builds on `parent-inverse-orrery`, does not duplicate it)
118118
- mesh-hygiene-audit witness — the engine-ingest checklist as executable contract: no ngons, no loose vertices, no non-manifold edges, no zero-area faces, consistent outward winding; closed forms via Euler characteristic and exact edge-face incidence counts
554 Bytes
Loading
-124 Bytes
Loading

docs/gallery/collision-hull-proxy/index.html

Lines changed: 17 additions & 13 deletions
Large diffs are not rendered by default.
334 Bytes
Loading
-140 Bytes
Loading

docs/gallery/custom-normals-shade/index.html

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ <h2>Source</h2>
659659
<span class="c"># semi-gloss painted steel: rough enough to read as paint, glossy enough</span>
660660
<span class="c"># that a highlight exposes every normal discontinuity — matte would hide</span>
661661
<span class="c"># the very shading differences this render exists to show</span>
662-
steel = make_material(<span class="s">&quot;OliveDrab&quot;</span>, (<span class="n">0.31</span>, <span class="n">0.35</span>, <span class="n">0.15</span>), <span class="n">0.8</span>, <span class="n">0.26</span>)
662+
steel = make_material(<span class="s">&quot;OliveDrab&quot;</span>, (<span class="n">0.30</span>, <span class="n">0.345</span>, <span class="n">0.13</span>), <span class="n">0.8</span>, <span class="n">0.26</span>)
663663
accent = make_material(<span class="s">&quot;FuelMarker&quot;</span>, (<span class="n">0.55</span>, <span class="n">0.06</span>, <span class="n">0.03</span>), <span class="n">0.3</span>, <span class="n">0.30</span>)
664664

665665
<span class="c"># the checked base can IS the by-angle variant; the two failure modes are</span>
@@ -712,16 +712,16 @@ <h2>Source</h2>
712712

713713
<span class="c"># key/fill/rim/wedge per docs/VISUAL-STYLE.md</span>
714714
light(<span class="s">&quot;Key&quot;</span>, (-<span class="n">4.0</span>, -<span class="n">5.0</span>, <span class="n">6.0</span>), <span class="n">520.0</span>, <span class="n">4.5</span>, (<span class="n">1.0</span>, <span class="n">0.96</span>, <span class="n">0.9</span>), (<span class="n">50</span>, <span class="n">0</span>, -<span class="n">38</span>))
715-
light(<span class="s">&quot;Fill&quot;</span>, (<span class="n">5.5</span>, -<span class="n">3.5</span>, <span class="n">2.5</span>), <span class="n">120.0</span>, <span class="n">9.0</span>, (<span class="n">0.75</span>, <span class="n">0.85</span>, <span class="n">1.0</span>), (<span class="n">65</span>, <span class="n">0</span>, <span class="n">55</span>))
715+
light(<span class="s">&quot;Fill&quot;</span>, (<span class="n">5.5</span>, -<span class="n">3.5</span>, <span class="n">2.5</span>), <span class="n">150.0</span>, <span class="n">9.0</span>, (<span class="n">0.75</span>, <span class="n">0.85</span>, <span class="n">1.0</span>), (<span class="n">65</span>, <span class="n">0</span>, <span class="n">55</span>))
716716
light(<span class="s">&quot;Rim&quot;</span>, (<span class="n">1.5</span>, <span class="n">4.5</span>, <span class="n">4.0</span>), <span class="n">340.0</span>, <span class="n">3.0</span>, (<span class="n">0.6</span>, <span class="n">0.78</span>, <span class="n">1.0</span>), (-<span class="n">58</span>, <span class="n">0</span>, <span class="n">170</span>))
717717
light(<span class="s">&quot;Wedge&quot;</span>, (<span class="n">2.5</span>, <span class="n">5.5</span>, <span class="n">4.0</span>), <span class="n">400.0</span>, <span class="n">6.0</span>, (<span class="n">1.0</span>, <span class="n">0.76</span>, <span class="n">0.5</span>), (-<span class="n">68</span>, <span class="n">0</span>, <span class="n">190</span>))
718718
<span class="c"># the shading audit light: a tall strip whose reflection runs down each</span>
719719
<span class="c"># can face — it stair-steps on flat shading, warps at the rim on</span>
720720
<span class="c"># smooth-everything, and stays straight with crisp edges on by-angle</span>
721721
ld = bpy.data.lights.new(<span class="s">&quot;Strip&quot;</span>, <span class="s">&#x27;AREA&#x27;</span>)
722-
ld.energy = <span class="n">460.0</span>
722+
ld.energy = <span class="n">400.0</span>
723723
ld.shape = <span class="s">&#x27;RECTANGLE&#x27;</span>
724-
ld.size = <span class="n">1.0</span>
724+
ld.size = <span class="n">1.35</span>
725725
ld.size_y = <span class="n">8.0</span>
726726
ld.color = (<span class="n">0.9</span>, <span class="n">0.95</span>, <span class="n">1.0</span>)
727727
strip = bpy.data.objects.new(<span class="s">&quot;Strip&quot;</span>, ld)
@@ -743,7 +743,7 @@ <h2>Source</h2>
743743

744744
scene.render.engine = <span class="s">&#x27;CYCLES&#x27;</span> <span class="k">if</span> engine == <span class="s">&#x27;cycles&#x27;</span> <span class="k">else</span> eevee_engine_id()
745745
<span class="k">if</span> engine == <span class="s">&#x27;cycles&#x27;</span>:
746-
scene.cycles.samples = <span class="n">48</span>
746+
scene.cycles.samples = <span class="n">64</span>
747747
<span class="k">else</span>:
748748
<span class="k">try</span>:
749749
scene.eevee.taa_render_samples = <span class="n">64</span>

docs/gallery/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,8 +541,8 @@ <h2><a href="light-link-studio/">light-link-studio</a></h2>
541541
</a>
542542
<div class="card-body">
543543
<h2><a href="collision-hull-proxy/">collision-hull-proxy</a></h2>
544-
<p class="teaches">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 368 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.</p>
545-
<p class="witnesses"><span class="tag">witnesses</span> A hull of the dense render mesh measures 368 faces, over the 255-face per-piece budget - the cage is a coarser lathe with rings inflated by sec(pi/n) so each cage ring circumscribes its render ring exactly (containment 5.9e-08). Proud details cost cage rows; concave grooves are free under the hull. Piece budgets: body 70, caps 60+60+60, compound 250.</p>
544+
<p class="teaches">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.</p>
545+
<p class="witnesses"><span class="tag">witnesses</span> A hull of the dense render mesh measures 380 faces, over the 255-face per-piece budget - the cage is a coarser lathe with rings inflated by sec(pi/n) so each cage ring circumscribes its render ring exactly (containment 4.4e-08). Proud details cost cage rows; concave grooves are free under the hull. Piece budgets: body 70, caps 60+60+60, compound 250.</p>
546546
<a class="card-link" href="collision-hull-proxy/">View example <span aria-hidden="true">&rarr;</span></a>
547547
</div>
548548
</article>

examples/collision-hull-proxy/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,27 @@ per-piece face limit (255 is the common cap). The example builds that
2424
structure and derives every property from closed forms, per piece:
2525

2626
- **Containment.** Every render-mesh vertex lies on the inner side of every
27-
face plane of its piece's hull — max excursion **5.9e-08** (tol 2e-4). This
27+
face plane of its piece's hull — max excursion **4.4e-08** (tol 2e-4). This
2828
holds by construction, not luck: the cage is a coarse lathe whose rings are
2929
inflated by `sec(π/n)`, so each n-gon cage ring *circumscribes* its render
3030
ring exactly. Proud details (a rim, a nut) must be paid for in cage rows;
3131
concave details (the grooves) are free — the hull bridges over them. That
3232
trade-off is the collision-authoring lesson.
3333
- **Convexity.** The same plane test restricted to the hull's own vertices
34-
(5.0e-08) — what a convex solver assumes when it uploads the piece.
34+
(4.8e-08) — what a convex solver assumes when it uploads the piece.
3535
- **Watertight + manifold.** Every hull edge borders exactly two faces, and
3636
V − E + F = 2: a convex hull is a topological sphere.
3737
- **Outward winding.** Positive signed volume by the divergence theorem
38-
(body piece 0.968858) — inverted collision is a physics no-op.
38+
(body piece 1.022381) — inverted collision is a physics no-op.
3939
- **Budget.** Every piece ≤ 255 faces: body 70, pumper 60, side caps 60+60;
4040
the compound totals 250. The naive approach fails this — a hull of the
41-
*dense render mesh* measures **368 faces**, over budget, which is why real
41+
*dense render mesh* measures **380 faces**, over budget, which is why real
4242
pipelines hull a cage, never the render mesh.
4343

4444
**What each check catches on failure:** an artist editing the render mesh
4545
after the hull was generated (probe: pumper lug stretched 2×, exit 3,
4646
measured escape 0.730000); inverted hull winding (probe: polygons flipped,
47-
exit 5, signed volume −0.968858, the exact negation); a non-watertight piece
47+
exit 5, signed volume −1.022381, the exact negation); a non-watertight piece
4848
(probe: one face deleted, exit 4, three border edges).
4949

5050
**Version witness:** output is byte-identical on Blender 4.5.11 LTS and

0 commit comments

Comments
 (0)