Skip to content

Commit d1caf5b

Browse files
TMHSDigitalclaude
andauthored
fix: cart, grindstone and attribute-domain-shear quality pass (#242)
* fix(showcase): rebuild the cart as a handcart that stands on its own legs The shaft tips hovered 0.30 m off the floor with the centre of mass ahead of the axle, slat ends poked out under the front board as a row of teeth, the hub was a 46 mm disc and every edge was razor sharp. The chassis is now stacked from the axle by named bites (bolster, rails that run on as shafts, floor, board walls), two prop legs stand it level, and the wheels get long banded naves. New budgets: prop legs as named supports (16), wall board seams (17), one BVH-contact assembly (18), edge treatment (20) and bake texel density (21), each with a falsifier. A 0.08 m bake cage was baking the wheel rim onto the side wall; it is 0.01 m now. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> * fix(showcase): cup the grindstone shoes, carry its trough, chamfer the frame Iron shoes exactly as wide as the sill shared three planes with it, which a centre-coincidence z-fight test never saw; the trough hovered 6 mm over its stretchers; both diagonals met at one apex; only the trough was chamfered and the stone was a flat-shaded chalk-white 32-gon. Shoes are now cups with a 6 mm reveal, the coplanar budget is cross-shell, the stretchers carry the trough (bite asserted, exit 18), diagonals tenon into the king post, every edge is chamfered (exit 20), and the stone is 48 smooth segments in a sandstone material with a texel-floored bake (21). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> * fix(examples): part the attribute-domain-shear pinwheels and root their sticks Render path only. The two canopies met tip to tip at the centre of the frame, and each dark steel stick stopped 0.6 m under its hub. The stands now sit 2.72 m apart and a wooden stick runs from the floor into each hub. Check, assertions and exit codes unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> * docs(showcase): conventions for contact graphs, cups, n-gon caps and bake cages Also refreshes the gallery cards and alts for the rebuilt cart and grindstone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> --------- Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 0a02b3a commit d1caf5b

22 files changed

Lines changed: 3387 additions & 1335 deletions
4.32 KB
Loading

‎docs/gallery/assets/cart-hero.webp‎

6.35 KB
Loading
1.22 KB
Loading

‎docs/gallery/attribute-domain-shear/index.html‎

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
<meta property="og:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/attribute-domain-shear-hero.webp" />
1717
<meta property="og:image:width" content="1280" />
1818
<meta property="og:image:height" content="720" />
19-
<meta property="og:image:alt" content="Two octagonal rainbow-coloured caps labelled CORNER and POINT, last write wins, showing different colour blending." />
19+
<meta property="og:image:alt" content="Two rainbow pinwheels on wooden sticks, well apart: CORNER on the left with crisp coloured petals, POINT, last write wins, on the right with colours smeared across the hub." />
2020
<meta property="og:site_name" content="Blender Developer Tools" />
2121
<meta name="twitter:card" content="summary_large_image" />
2222
<meta name="twitter:title" content="attribute-domain-shear — Examples — Blender Developer Tools" />
2323
<meta name="twitter:description" content="POINT vs CORNER color-attribute domains on a shared-vertex pinwheel: CORNER stays exact per face while a naive per-wedge POINT loop shears to the last write at the hub. Crisp petals versus a smeared swirl in one frame; the measured shear equals the palette closed form." />
2424
<meta name="twitter:image" content="https://tmhsdigital.github.io/Blender-Developer-Tools/gallery/assets/attribute-domain-shear-hero.webp" />
25-
<meta name="twitter:image:alt" content="Two octagonal rainbow-coloured caps labelled CORNER and POINT, last write wins, showing different colour blending." />
25+
<meta name="twitter:image:alt" content="Two rainbow pinwheels on wooden sticks, well apart: CORNER on the left with crisp coloured petals, POINT, last write wins, on the right with colours smeared across the hub." />
2626
<style>
2727
/* fonts are deployed by the landing build (docs/fonts/) */
2828
@font-face { font-family: 'Barlow Condensed'; font-weight: 600; font-display: swap;
@@ -268,8 +268,8 @@ <h1>attribute-domain-shear</h1>
268268
<p>POINT vs CORNER color-attribute domains on a shared-vertex pinwheel: CORNER stays exact per face while a naive per-wedge POINT loop shears to the last write at the hub. Crisp petals versus a smeared swirl in one frame; the measured shear equals the palette closed form.</p>
269269
</header>
270270
<main id="main">
271-
<button class="detail-hero" id="heroZoom" type="button" aria-label="View full size: Two octagonal rainbow-coloured caps labelled CORNER and POINT, last write wins, showing different colour blending.">
272-
<img src="../assets/attribute-domain-shear-hero.webp" alt="Two octagonal rainbow-coloured caps labelled CORNER and POINT, last write wins, showing different colour blending." width="1280" height="720" />
271+
<button class="detail-hero" id="heroZoom" type="button" aria-label="View full size: Two rainbow pinwheels on wooden sticks, well apart: CORNER on the left with crisp coloured petals, POINT, last write wins, on the right with colours smeared across the hub.">
272+
<img src="../assets/attribute-domain-shear-hero.webp" alt="Two rainbow pinwheels on wooden sticks, well apart: CORNER on the left with crisp coloured petals, POINT, last write wins, on the right with colours smeared across the hub." width="1280" height="720" />
273273
</button>
274274
<p class="zoom-hint">Rendered headless by the example itself — click to zoom.</p>
275275
<div class="callout"><span class="tag">witnesses</span> Authoring per-face colors into a POINT-domain attribute overwrites shared vertices once per neighbor; the last write wins and intended colors shear across every shared vertex.</div>
@@ -285,6 +285,7 @@ <h1>attribute-domain-shear</h1>
285285
<p><strong>What each check catches on failure:</strong> wedge 3 miscolored in the CORNER pass (exit 4); naive writes reversed, so the hub reads palette[0] (exit 5); a ring vert corrupted, breaking the overwrite-ordering witness (exit 6); a constant palette, collapsing the shear so the probe cannot distinguish naive from correct (exit 7). Sizes wrong for the declared domain (exit 3).</p>
286286
<p><strong>Version witness:</strong> output is byte-identical on Blender 4.5.11 LTS and 5.1.2 — the <code>color_attributes</code> domain API is stable across both.</p>
287287
<p><strong>Render as proof:</strong> dual pinwheel from the same closed-form palette the check asserts. CORNER (left) holds eight crisp petals to the hub; naive POINT (right) smears — petal colors bleed across the shared hub and ring verts into a swirl. The broken state is in-frame by design: the right fan <em>is</em> the falsification variant. Fully matte petal materials (<code>Specular IOR Level = 0</code>) so the flat color data carries no specular line, per <code>docs/VISUAL-STYLE.md</code>.</p>
288+
<p>The staging is render-only and does not touch the checked mesh. The two stands are 2.72 m apart so their canopies read as two objects; at 2.30 m the petal tips met at the centre of the frame. Each stand&#x27;s wooden stick runs from just below the floor into the hub it carries, both ends derived from the stand&#x27;s tilt. The old dark steel stick stopped 0.6 m short of the hub, under the canopy, and disappeared into the stage.</p>
288289
<h2>Run</h2>
289290
<pre><code>blender --background --python attribute_domain_shear.py --
290291
blender --background --python attribute_domain_shear.py -- --no-overwrite
@@ -519,26 +520,37 @@ <h2>Source</h2>
519520
<span class="k">return</span> mat
520521

521522

523+
STAND_TILT = math.radians(<span class="n">12</span>)
524+
STEM_BURY = <span class="n">0.02</span>
525+
526+
522527
<span class="k">def</span> _pinwheel_obj(sc, name, me, loc, rot_z):
523528
ob = bpy.data.objects.new(name, me)
524529
ob.location = loc
525-
ob.rotation_euler = (math.radians(<span class="n">12</span>), <span class="n">0.0</span>, rot_z)
530+
ob.rotation_euler = (STAND_TILT, <span class="n">0.0</span>, rot_z)
526531
sc.collection.objects.link(ob)
527-
<span class="c"># stem + hub cap: a garden pinwheel on a stick, not a floating disc</span>
532+
<span class="c"># stem + hub cap: a garden pinwheel on a stick, not a floating disc. The</span>
533+
<span class="c"># stick runs from just under the floor to the hub it carries, both ends</span>
534+
<span class="c"># derived from the stand&#x27;s own tilt; it used to stop 0.6 below the hub,</span>
535+
<span class="c"># hidden under the canopy, holding nothing.</span>
536+
stem_lo = -(loc[<span class="n">2</span>] / math.cos(STAND_TILT)) - STEM_BURY
537+
stem_hi = HUB_Z
528538
stem_me = bpy.data.meshes.new(name + <span class="s">&quot;Stem&quot;</span>)
529539
bm = bmesh.new()
530540
<span class="k">try</span>:
531-
bmesh.ops.create_cone(bm, cap_ends=<span class="k">True</span>, segments=<span class="n">10</span>, radius1=<span class="n">0.05</span>,
532-
radius2=<span class="n">0.06</span>, depth=<span class="n">1.35</span>)
533-
bmesh.ops.translate(bm, vec=(<span class="n">0.0</span>, <span class="n">0.0</span>, -<span class="n">0.72</span>), verts=bm.verts)
541+
bmesh.ops.create_cone(bm, cap_ends=<span class="k">True</span>, segments=<span class="n">10</span>, radius1=<span class="n">0.045</span>,
542+
radius2=<span class="n">0.035</span>, depth=stem_hi - stem_lo)
543+
bmesh.ops.translate(bm, vec=(<span class="n">0.0</span>, <span class="n">0.0</span>, <span class="n">0.5</span> * (stem_lo + stem_hi)),
544+
verts=bm.verts)
534545
bm.to_mesh(stem_me)
535546
<span class="k">finally</span>:
536547
bm.free()
537-
stem_me.materials.append(make_material(<span class="s">&quot;StemMetal&quot;</span>, (<span class="n">0.16</span>, <span class="n">0.17</span>, <span class="n">0.18</span>),
538-
rough=<span class="n">0.4</span>, metallic=<span class="n">0.8</span>))
548+
<span class="c"># a painted wooden dowel: near-black steel vanished into the dark stage</span>
549+
stem_me.materials.append(make_material(<span class="s">&quot;StemDowel&quot;</span>, (<span class="n">0.46</span>, <span class="n">0.30</span>, <span class="n">0.16</span>),
550+
rough=<span class="n">0.55</span>, metallic=<span class="n">0.0</span>))
539551
stem = bpy.data.objects.new(name + <span class="s">&quot;Stem&quot;</span>, stem_me)
540552
stem.location = loc
541-
stem.rotation_euler = (math.radians(<span class="n">12</span>), <span class="n">0.0</span>, rot_z)
553+
stem.rotation_euler = (STAND_TILT, <span class="n">0.0</span>, rot_z)
542554
sc.collection.objects.link(stem)
543555
cap_me = bpy.data.meshes.new(name + <span class="s">&quot;Cap&quot;</span>)
544556
bm = bmesh.new()
@@ -552,7 +564,7 @@ <h2>Source</h2>
552564
rough=<span class="n">0.35</span>, metallic=<span class="n">0.85</span>))
553565
cap = bpy.data.objects.new(name + <span class="s">&quot;Cap&quot;</span>, cap_me)
554566
cap.location = loc
555-
cap.rotation_euler = (math.radians(<span class="n">12</span>), <span class="n">0.0</span>, rot_z)
567+
cap.rotation_euler = (STAND_TILT, <span class="n">0.0</span>, rot_z)
556568
sc.collection.objects.link(cap)
557569
<span class="k">return</span> ob
558570

@@ -611,6 +623,9 @@ <h2>Source</h2>
611623
<span class="k">return</span> floor, wall
612624

613625

626+
PAIR_X = <span class="n">1.36</span>
627+
628+
614629
<span class="k">def</span> render_still(path, engine):
615630
<span class="s">&quot;&quot;&quot;Dual pinwheel: CORNER (crisp petals to the hub) vs naive POINT (last
616631
write smears the shared hub + ring verts). Colors come from the same
@@ -622,20 +637,22 @@ <h2>Source</h2>
622637
me_c = build_fan()
623638
assign_corner(me_c, pal)
624639
me_c.materials.append(make_attr_material(<span class="s">&quot;MatCorner&quot;</span>, ATTR_C))
625-
left = _pinwheel_obj(sc, <span class="s">&quot;Corner&quot;</span>, me_c, (-<span class="n">1.15</span>, <span class="n">0.0</span>, <span class="n">1.35</span>), math.radians(-<span class="n">8</span>))
640+
<span class="c"># Spread so the two canopies read as two objects: at +/-1.15 their</span>
641+
<span class="c"># tips met at x=0 and the pair read as one shape.</span>
642+
left = _pinwheel_obj(sc, <span class="s">&quot;Corner&quot;</span>, me_c, (-PAIR_X, <span class="n">0.0</span>, <span class="n">1.35</span>), math.radians(-<span class="n">8</span>))
626643

627644
me_p = build_fan()
628645
assign_point_naive(me_p, pal)
629646
me_p.materials.append(make_attr_material(<span class="s">&quot;MatPoint&quot;</span>, ATTR_P))
630-
right = _pinwheel_obj(sc, <span class="s">&quot;Point&quot;</span>, me_p, (<span class="n">1.15</span>, <span class="n">0.0</span>, <span class="n">1.35</span>), math.radians(<span class="n">8</span>))
647+
right = _pinwheel_obj(sc, <span class="s">&quot;Point&quot;</span>, me_p, (PAIR_X, <span class="n">0.0</span>, <span class="n">1.35</span>), math.radians(<span class="n">8</span>))
631648

632-
p_corner = placard(sc, <span class="s">&quot;CORNER&quot;</span>, (-<span class="n">1.15</span>, -<span class="n">1.05</span>, <span class="n">0.02</span>), size=<span class="n">0.13</span>)
633-
p_point = placard(sc, <span class="s">&quot;POINT — last write wins&quot;</span>, (<span class="n">1.15</span>, -<span class="n">1.05</span>, <span class="n">0.02</span>), size=<span class="n">0.10</span>)
649+
p_corner = placard(sc, <span class="s">&quot;CORNER&quot;</span>, (-PAIR_X, -<span class="n">1.05</span>, <span class="n">0.02</span>), size=<span class="n">0.13</span>)
650+
p_point = placard(sc, <span class="s">&quot;POINT — last write wins&quot;</span>, (PAIR_X, -<span class="n">1.05</span>, <span class="n">0.02</span>), size=<span class="n">0.10</span>)
634651

635652
floor, wall = build_studio(sc)
636653

637654
cam_data = bpy.data.cameras.new(<span class="s">&quot;Cam&quot;</span>)
638-
cam_data.lens = <span class="n">48.0</span>
655+
cam_data.lens = <span class="n">44.0</span>
639656
cam = bpy.data.objects.new(<span class="s">&quot;Cam&quot;</span>, cam_data)
640657
cam.location = (<span class="n">0.0</span>, -<span class="n">6.4</span>, <span class="n">4.6</span>)
641658
sc.collection.objects.link(cam)
@@ -722,7 +739,7 @@ <h2>Source</h2>
722739
</main>
723740
<dialog class="lightbox" id="lightbox" aria-label="Full-size render">
724741
<button class="lightbox-close" type="button" autofocus>Close</button>
725-
<img src="../assets/attribute-domain-shear-hero.webp" alt="Two octagonal rainbow-coloured caps labelled CORNER and POINT, last write wins, showing different colour blending." />
742+
<img src="../assets/attribute-domain-shear-hero.webp" alt="Two rainbow pinwheels on wooden sticks, well apart: CORNER on the left with crisp coloured petals, POINT, last write wins, on the right with colours smeared across the hub." />
726743
</dialog>
727744
<footer>
728745
<div class="statusbar">

0 commit comments

Comments
 (0)