Skip to content

fix: park-bench, fence-kit and soccer-ball-goldberg quality pass - #240

Merged
TMHSDigital merged 4 commits into
mainfrom
fix/quality-pass-bench-fence-soccer
Sep 24, 2026
Merged

TMHSDigital merged 4 commits into
mainfrom
fix/quality-pass-bench-fence-soccer

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

Quality pass: three items (two showcase pieces, one gallery example). Everything below comes from live runs on .scratch/blender-{4.5.11,5.1.2,5.2.1}-windows-x64/blender.exe, which report 4.5.11 LTS / 5.1.2 / 5.2.1 LTS, unless it is labelled inspection. Baselines were taken on the pristine tree before any edit.

Picks. Every showcase piece has had some pass. Track A took two that had only the old-era pass (#182/#183), which still had the 14 m stage, set-ordered bevel input, a 2° X tilt in the hero, a leaked temp .glb and single-tone timber: park-bench and fence-kit. Track B took soccer-ball-goldberg, never reviewed and outside both pinned reference sets. Track C: none. Every pathology and sidecar example has been reviewed.

A: showcase/park-bench

Took 2 inspection rounds.

Defects

  1. All four feet floated under their posts (joint_foot_front, joint_foot_back, ortho_left). Each scroll foot was its own arc, started 8% along (t0=0.08), and each post started at the arc's top. That left about 14 mm of daylight at every join. No budget saw it: the toes grounded, and the stretcher gap only measured stretchers.
  2. The back slats straddled the rear posts (joint_back_slats_post, ortho_left). The slats were centred on the post plane, 30 mm thick against 24 mm posts, so each post ran through every slat end. The back was dead vertical.
  3. Square box posts were smooth-shaded (joint_center_stretcher, joint_stretcher_post). They rendered as tapering cylinders, and they met 6-gon round scroll tubes at the feet.
  4. The arm scroll hung off the post top, overlapping the post (joint_arm_scroll). The armrest sat 0.6 mm above its arm bar.
  5. The iron read as chrome (metallic 1.0, roughness 0.32), and the timber was one flat brown (three-quarter views).
  6. Hero: the 14 m back wall's edge showed top-left, and a 2° X tilt sank the front toes about 1 cm into the floor. Temp .glb leak. Set-ordered bevel input.

Fixes, and why each is structural

  • 1–3: Every leg is now one round bar swept along one path with parallel-transported frames: the toe quarter-circle, then the post, then (at the back) a 12° bend into the upright that carries the back slats. The join cannot open because there is no join. All iron is 8-gon round bar, smooth-shaded, with flat caps.
  • 2: The back slats are placed from the upright's own axis and normal: r + SLAT_T/2 − SLAT_BITE in front of it.
  • 4: The armrest sits SLAT_BITE into the arm bar and overhangs the front leg. A quarter-round bracket runs from the leg up into the overhang. The front leg tenons 12 mm into the armrest.
  • Seat slats sit SLAT_BITE into the side rails, computed from the rail's top line.
  • Front and back rails stop half a bar inside the legs. Ending on the leg axis put their end rings on the side rails' end rings (14 doubles on the first try). The top rail is a heavier bar that swallows the upright caps.
  • 5: Per-slat PlankTone/GrainDir wood (the watchtower shader) and dark rusted iron (metallic 0.6, roughness 0.55).
  • 6: 60 m stage, no X tilt. Export deleted after it is measured. Bevel input sorted by edge index.

New budgets, identical on 4.5.11, 5.1.2 and 5.2.1:

Budget Band Measured
Bearing bite (exit 20): 7 seat slats × 2 side rails, 5 back slats × 2 uprights, 2 armrests × (leg + arm bar); overlap depth either way round; member counts asserted 28 bites, each ≥ 0.0015 m 28, min 0.00201
Legs in one piece (exit 21): the shell under each toe station is a leg reaching the seat 4 4
Back recline (exit 19): low and high slab centroids of each upright 9°–16° 12.00° / 12.00°

Triangles: 2520 → 3272 (band re-fitted from 2200–4200 to 2900–3700). Collider 82 → 64. Outer AABB z 0.884 → 0.887 (heavier top rail). Hygiene all zero, z-fight pairs 0. Same-binary deterministic: two full matrix runs printed identical measurements.

Falsifiers, identical on all three binaries:

  • --float-slats lifts the seat slats 6 mm → 20 (−0.00354).
  • --split-feet restores the first build's separate foot arcs → 21 (0 of 4). The toes still ground and every gap budget still passes.
  • --upright-back sets the recline to 0 with the back top kept → 19 (0.00°).

Existing exit codes, before → after, identical on all three: default 0→0, --skip-decimate 9→9, --stray-vert 15→15, --lift-z 16→16, --short-feet 16→16, --float-stretcher 17→17, --gap-slats 18→18, --narrow-seat 19→19.

Hero: check_framing without deviation= passes. Contact sheet: docs/gallery/contact-sheets/park-bench-contact-sheet.webp. Luma 0.181 (band 0.151–0.305), stage 0.167, warmth +0.045, saturation 0.118.

A: showcase/fence-kit

Took 1 inspection round.

Defects

  1. Every iron collar was three or four loose plates with an open slit at each corner (joint_rail0/1/2_post, joint_shoe_left/right).
  2. The brace ran from post centre to post centre (joint_brace_low, joint_brace_high, joint_brace_mid_rail, ortho_top):
    • it passed through the rail bands' front plates at both ends;
    • it sat 6 mm into all three rails;
    • its ends were cut square to its own axis, so one corner was buried and the other stood off.
  3. The section did not fit its tile (ortho_top, ortho_bottom). The AABB was 1.624 m against a 1.60 m tile. The bands stood 12 mm past each end, so copies placed at the pitch interpenetrated 24 mm. The README said the width was the tile.
  4. Flat single-tone timber and near-chrome iron (metallic 1.0, roughness 0.28).
  5. Hero: 14 m stage, 2° X tilt. Temp .glb leak. Set-ordered bevel input.

Fixes

  • 1: add_collar extrudes one mitred profile per band. A shoe is a closed ring. A rail band is a U whose arms stop a quarter-thickness inside the post's inner face, so no arm end lands on that face's plane.
  • 2: The brace is a board with plumb-cut ends:
    • its back face sits BRACE_BITE into the middle rail's front face, derived from that rail's own depth;
    • it is housed 12 mm into both posts;
    • its heights are derived from the bottom and top rails plus a clearance;
    • 22 mm deep, so it stays inside the band arms.
  • 3: The post stations come from the tile: HX = TILE/2 − KIT_CLEAR − band reach. Changing post stock or band thickness moves the posts, not the tile.
  • 4: Per-member wood, dark rusted iron. 5: 60 m stage, no tilt. Export deleted after it is measured. Bevel input sorted.

New budgets, identical on all three binaries:

Budget Band Measured
Brace housing (exit 20): deepest brace vertex inside each post ≥ 0.004 m 0.01200
Brace bearing (exit 20): brace back plane past the middle rail's front plane, where their heights overlap ≥ 0.001 m 0.00200
Tile fit (exit 21): section width along X 1.590–1.600 m 1.5960

The bearing is measured plane to plane. The brace and rail cross mid-span, where neither has a vertex, so a vertex-depth metric reported a false 0.15 m gap on the first try.

Triangles: 1092 → 1012 (band re-fitted from 1000–1400 to 850–1200). Outer AABB 1.624 → 1.596 m. Collider 32 → 24. Hygiene all zero. Same-binary deterministic.

Falsifiers, identical on all three binaries:

  • --float-brace moves the brace 6 mm forward → 20 (−0.00400).
  • --wide-tile restores the first build's post stations, rails moved with them → 21 (1.6240). The tile check runs before the AABB gate so the envelope cannot steal it. On the first try this falsifier landed on 20, because the middle-rail lookup keyed on the constant rail length; the lookup now keys on the rail's station height.

Existing exit codes, before → after, identical on all three: default 0→0, --skip-decimate 9→9, --stray-vert 15→15, --lift-z 16→16, --short-shoes 16→16, --short-brace 17→17, --gap-rails 18→18, --long-rails 19→19.

Hero: framing passes. Contact sheet: docs/gallery/contact-sheets/fence-kit-contact-sheet.webp. Luma 0.183, stage 0.167, warmth +0.203, saturation 0.135.

B: examples/soccer-ball-goldberg

Render path only. build_ball and check are untouched.

Inspection (clay, wireframe, hero, close-up) found three problems:

  1. The clay pass read as a lumpy stone. Level-2 Catmull-Clark on a 60-vertex cage leaves flats over each hexagon.
  2. The 20 white hexagons merged into one white shell. The still showed 12 of the 32 panels the check counts.
  3. The render path had no framing gate.

Presentation changes:

  • Round ball. Subsurf goes to level 3, then an unapplied CAST sphere at the cage's own circumradius.
  • Stitched seams. A render-only copy of the mesh, parented to the ball, with its slot indices set to the dark slot on the copy only. It is wireframed, subdivided and cast 2 mm proud of the ball.
    • First try: a Bevel modifier bound to the dark slot. Subsurf bloated the thin strips into black blobs, visible in round 1. Replaced.
  • Framing gate. check_framing returns 10, and this example already uses 10 for the centroid check, so the call site maps a violation to 14. This adds a render-path-only row to the exit table; no existing code changes meaning.
    • The rounder ball touched the top margin at 55 mm (caught by the gate). The lens is now 50 mm: fill y 0.750, min margin 0.044.
    • Falsified with a scratch copy at a 90 mm lens → 14 (fill 1.000, top and bottom margins 0.000).

Contract unchanged. Before → after, identical on all three binaries: default 0 → 0, --invert-bind 13 → 13. The check output is byte-identical to before: edge max_dev 6.471e-06, planarity 1.888e-06, circumradius max_dev 8.956e-06.

Contact sheet: docs/gallery/contact-sheets/soccer-ball-goldberg-contact-sheet.webp. Luma 0.240, stage 0.178. Saturation is 0.074, low by design: it is a black-and-white subject.

Also

  • showcase/README.md gains four conventions:
    • A bent bar is one sweep
    • A carried member bites its carrier, measured where the vertices are
    • A kit section fits its tile
    • Level on the stage
  • Gallery teaches, alt and witnessesFix text and the root README alts are updated. The gallery is regenerated, and the generated <img alt> and witness callouts were read back.
  • tests/check_falsifier_targets.py: passed, 209 falsifiers across 28 pieces.
  • Not done: asset sheets for these two pieces. No showcase piece has one yet (Backfill contact sheets (26) and asset sheets (28) for existing showcase pieces #202).

🤖 Generated with Claude Code

TMHSDigital and others added 4 commits September 24, 2026 06:37
… carries

The scroll feet were separate arcs stopped 14 mm under square posts, the
back slats straddled vertical posts, and the iron read as chrome. Each leg
is now one swept round bar from toe to reclined back; slats and armrests
bite named bearers (exit 20), legs are asserted whole (exit 21), and the
back recline is a band (exit 19).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
…posts

The iron collars were loose plates with open corners and stood 12 mm past
each tile edge, and the brace ran post centre to post centre through the
bands and 6 mm into every rail. Bands are now one mitred shell each, posts
are placed from the tile (exit 21), and the brace is a plumb-cut board
housed in both posts and bearing on the middle rail (exit 20).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Render path only. The white hexagons merged into one shell and the ball
read lumpy; a render-only seam overlay and a Cast modifier fix both. The
render path now calls check_framing, remapped to exit 14 because 10 is
the centroid check. Contract, assertions and exit codes 0-13 unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
…el stage

Also refreshes the gallery cards and root README alts for the three
restaged stills and regenerates docs/gallery.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
@TMHSDigital TMHSDigital added the needs-5.1 Opt-in Blender 5.1 smoke on this PR. Default matrix stays 4.5 + 5.2. Auto-label will not apply this. label Sep 24, 2026
@github-actions github-actions Bot added examples Runnable smoke-gated examples under examples/ showcase Budget-conformance props under showcase/ documentation Improvements or additions to documentation labels Sep 24, 2026
@TMHSDigital
TMHSDigital merged commit a8f121d into main Sep 24, 2026
13 checks passed
@TMHSDigital
TMHSDigital deleted the fix/quality-pass-bench-fence-soccer branch September 24, 2026 10:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation examples Runnable smoke-gated examples under examples/ needs-5.1 Opt-in Blender 5.1 smoke on this PR. Default matrix stays 4.5 + 5.2. Auto-label will not apply this. showcase Budget-conformance props under showcase/

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant