Skip to content

fix: seat the ladder rungs and stop the iron chamfers reading as wood - #172

Merged
TMHSDigital merged 2 commits into
mainfrom
fix/wooden-ladder-quality-pass
Sep 16, 2026
Merged

TMHSDigital merged 2 commits into
mainfrom
fix/wooden-ladder-quality-pass

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

Visual quality pass on showcase/wooden-ladder. Four inspection rounds. Everything below was proven by live run on three local binaries unless labelled otherwise.

Binaries, versions as the binaries report them:

  • .scratch/blender-4.5.11-windows-x64/blender.exeBlender 4.5.11 LTS
  • .scratch/blender-5.1.2-windows-x64/blender.exeBlender 5.1.2
  • .scratch/blender-5.2.1-windows-x64/blender.exeBlender 5.2.1 LTS

Defect list

Inspection sheet: six orthos, two three-quarters, clay, wireframe, twelve rung-joint close-ups, two top-joint, two foot-joint, one ground-contact, 1024², rendered to .scratch/ladder-inspection/round-{0..4}/ and never committed.

Rounds 0 and 1 landed in the prior session; rounds 2 to 4 are this one.

# Part Defect Revealed by
1 Stile top A second wood block sat on top of each stile as a stub, reading as a broken-off extension joint_top_*, three_quarter_a
2 Iron fittings Four fittings per stile (base collar, two side straps, top band) clustered into an unreadable mass and protruded past the silhouette as loose tabs ortho_front, committed hero
3 Feet No shoe: the raked stile met the floor on a bare angled end, so contact was a line, not a pad ground_contact
4 Whole piece zmin was forced to 0 by clamping stray vertices upward, deforming the foot instead of grounding the piece ortho_left, ground_contact
5 Rungs All six rungs identical in radius and perfectly even in spacing, reading as CG ortho_front
6 Stiles Bevel applied via every wood vertex, so the rung cap rims were beveled too and shaded broad faces as faceted clay pass
7 Rungs / stiles Rung diameter equalled the full 34 mm stile depth, so each dowel broke through the stile's front and back chamfer as a thin spike joint_rung_* close-ups, rounds 1 and 2
8 Iron fittings Every chamfer face on the caps and shoes rendered as wood, framing each black fitting in tan joint_top_left, joint_foot_left, ground_contact, round 2
9 Whole piece The piece failed its own gates at exit 4 — round 1 removed geometry without re-fitting the triangle band or outer AABB default run, round 2
10 Hero set The wall's left edge sat in frame as a bright vertical band in the corner committed hero and re-render
11 Falsifier --lift-z exited 0 — the grounded budget could not fail falsifier matrix, round 3

Defects 1 to 6 were fixed in the prior session's round 1. Defects 7 to 11 are this PR.

What changed in the generator, and why it is structural

7 — rung diameter. RUNG_R 0.017 → 0.013, a 26 mm dowel in a 34 mm stile. Structural because it corrects a proportion that was wrong: the dowel was as deep as the member it passes through, so no material, camera angle, or chamfer tweak could stop it erupting. The clearance is now 3.61 mm against a 2.5 mm chamfer, so the dowel lands on the stile's flat face with margin rather than grazing the chamfer.

8 — chamfer material. bmesh.ops.bevel does not inherit material_index onto the faces it creates, and the piece claimed its metal faces from a face-set snapshot taken before the bevel. Every chamfer therefore fell back to slot 0. Now claimed from the bevel op's own return["faces"]. Structural because it derives the face set from the operation that created it, rather than from a snapshot that is correct only if bevel never adds faces.

9 — stale fitted constants. BASE_TRIS 2100–2280 → 900–975 and OUTER_SIZE (0.474, 0.361, 1.482) → (0.472, 0.365, 1.460), both re-fitted to the measured result. Not a loosened assertion: the band is the same ±4% relative width, and the triangle count fell because geometry was removed, not because a gate was widened.

10 — set edge. Floor and wall grid 14 → 60. Structural because it removes the class (no edge of the set can enter frame at any framing) rather than nudging the wall out of this one shot.

11 — vacuous falsifier. world_bbox reads matrix_world, which is evaluated data; the object was moved with no view-layer update, so the cached matrix hid the lift. Added bpy.context.view_layer.update() before measuring.

Also replaced the bevel's wood_verts[:16] slice with an explicit stile_verts list. Identical geometry — the slice happened to be the two stiles — but it no longer depends on the stiles being constructed first and contributing exactly sixteen vertices.

New budgets, measured on all three binaries

All three agree exactly except glTF byte count.

Budget Declared 4.5.11 5.1.2 5.2.1
Shell count exactly 12 12 12 12
Rung depth clearance ≥ 0.003 m 0.00361 0.00361 0.00361
Tenon engagement ≥ 0.006 m 0.01200 0.01200 0.01200
Tenon breakout margin ≥ 0.005 m 0.04600 0.04600 0.04600
Wood faces ≥ 280 324 324 324
Metal faces ≥ 180 216 216 216
Non-manifold / loose v / loose e / doubles @1e-5 / zero-area / n-gons 0 all 0 all 0 all 0
Grounded abs(zmin) ≤ 1e-4 0.0000 0.0000 0.0000
Base triangles 900–975 936 936 936
Outer AABB (0.472, 0.365, 1.460) ± 0.01 (0.4720, 0.3649, 1.4597) same same
Collider tris ≤ 120 24 24 24
glTF bytes > 0 75140 75140 75128

The joint budgets are measured per rung end against each stile from vertex positions, un-raked into the construction frame so the 12° rake does not inflate the stile's own AABB, and reported as the worst case over all twelve ends.

Exit codes, all three binaries

Invocation Budget violated 4.5.11 5.1.2 5.2.1
default 0 0 0
--skip-decimate LOD1 ratio band 9 9 9
--stray-vert mesh hygiene, loose verts 15 15 15
--lift-z grounded zmin 16 16 16
--fat-rungs rung depth clearance 17 17 17

Measured failures: LOD1 ratio 1.0000, loose_v=1, zmin 0.050000, clearance -0.00051.

--fat-rungs widens the dowels to the full stile depth, reproducing defect 7 exactly, so the assertion is proven against the real defect rather than a synthetic one.

--stray-vert and --fat-rungs are new. --lift-z existed but exited 0 on all three binaries before this PR.

Falsification of the material-face floor

The floor that locks defect 8 in was proven to fire by breaking the fix: dropping metal_faces.update(bevelled["faces"]) gives mat_index_counts={0: 516, 1: 24} and exits 5 with metal faces 24 < 180 on 5.2.1. Restored.

Triangle counts

2184 → 936. Cause is round 1's fitting removal, not hidden-face culling. The rung end rims stay capped and buried inside the stiles — 144 triangles nobody sees — because an open rim is a non-manifold boundary and the hygiene budget forbids it.

Hero still

Re-rendered on 5.2.1. Framing gate passes without deviation=: fill x=0.166 y=0.839 in band 0.70–0.90, margins left 0.419 right 0.416 bottom 0.072 top 0.089 against a 0.020 minimum, no edge touched or crossed.

Conventions

showcase/README.md gains the joint-fit budget class (shell count plus the three named minima, measured in the construction frame) and a named falsifier for every hygiene budget, which previously had none. Every future piece inherits both.

Not done

No contact sheet or asset sheet. Those gates cover examples/; no showcase piece has ever carried one, including the four prior showcase quality passes (#167, #169, #170, #171). Showcase pieces are governed by showcase/README.md instead.

TMHSDigital and others added 2 commits September 15, 2026 23:25
The rung dowels were as deep as the stile they pass through, so each one
erupted through the stile's front and back chamfers as a thin spike in
every joint close-up. Narrowing the dowel to 26 mm corrects the
proportion; a material or camera change would only have hidden it.

Beveling the caps and shoes left every chamfer face in the wood slot.
Bevel does not inherit material_index onto the faces it creates, and the
piece claimed its metal faces from a pre-bevel snapshot, so each iron
fitting rendered as a black block framed in tan. Claim them from the
bevel op's own return instead.

The previous round removed six iron fittings per ladder without
re-fitting the triangle band or the outer AABB, leaving the piece
failing its own gates at exit 4. Both constants are re-fitted to the
measured result: 2184 tris to 936.

Locks all of it in as budgets recomputed from the generated mesh: shell
count, rung-to-stile depth clearance, tenon engagement and breakout
margin, and material face floors that the pre-bevel snapshot would have
failed. --lift-z could never fire, because matrix_world is evaluated
data and the object was moved without a view-layer update; --stray-vert
and --fat-rungs are new, and all four are proven to fire.

Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
A part exactly as thick as its host passes any "do the parts overlap"
check while erupting through the host's chamfer as a spike, which is how
the wooden ladder shipped. Name the three minima that catch it, and the
frame to measure them in, so the next piece inherits them instead of
rediscovering the class.

The hygiene budgets added in the last pass had no named falsifier, so
nothing proved they could fail. Name one per budget and require the exit
code be checked rather than merely non-zero.

Signed-off-by: TMHSDigital <154358121+TMHSDigital@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.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 16, 2026
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 16, 2026
@TMHSDigital
TMHSDigital merged commit dec2f21 into main Sep 16, 2026
13 checks passed
@TMHSDigital
TMHSDigital deleted the fix/wooden-ladder-quality-pass branch September 16, 2026 03:33
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 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant