Skip to content

fix: terrain-scatter, export-preset-axis and mesh-automasking-settings quality pass - #230

Merged
TMHSDigital merged 4 commits into
mainfrom
fix/quality-pass-terrain-axis-automasking
Sep 23, 2026
Merged

TMHSDigital merged 4 commits into
mainfrom
fix/quality-pass-terrain-axis-automasking

Conversation

@TMHSDigital

Copy link
Copy Markdown
Owner

Quality pass: three items, one per track. 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.

A — showcase/terrain-scatter

Took 3 inspection rounds. Each round covered six orthos, two three-quarters, clay, wireframe, 4 stone-seat close-ups, slab edge and corner, and ground contact.

Defects

  1. The stones read as white eggs. They were smooth-shaded, near-white ellipsoids with a gentle sine bump (three-quarters, hero).
  2. Two stone pairs interpenetrated (stone-seat 0 and 3 close-ups, back ortho). The GN jitter reaches ±0.22 m on a 0.575 m grid, and no budget compared stone to stone.
  3. The dirt was a flat pale tan, so the tile read as a clay slab (three-quarters, hero).
  4. Once cleaved, the stones read as pebbles on the tile (r1 hero).
  5. The temp .glb export leaked into the working directory.

Fixes, and why each is structural

  • 1: each ellipsoid is cleaved by N_CLEAVES planes. Normals and depths come from the stone's own centre, closed form, and every vertex beyond a plane is projected onto it. Stones are flat-shaded.
  • 2: relax_centres pushes centres apart to 2 × STONE_R_BOUND + STONE_CLEAR (fixed iteration count, symmetric, clamped on the tile). STONE_R_BOUND is derived from ROCK_SCALE, the largest semi-axis, the bump and the tilt, so it tracks any size change. Stated honestly: with today's cleaved sizes the unrelaxed scatter would also clear; the relaxation is what guarantees it.
  • 3: mottled dark soil and grey stone, with roughness and bump from fine object-space noise.
  • 4: ROCK_SCALE = 1.35 on every semi-axis and the bump.
  • 5: the export is removed after it is measured.

New budget. Measured identically on 4.5.11, 5.1.2 and 5.2.1.

Budget Band Measured
Interpenetrating stone pairs (exit 20) BVH overlap between any two stone shells: 0 0

The declared outer AABB z was re-fitted to the measurement, 0.552 → 0.584 (tolerance unchanged). The existing hygiene set stays all zero.

Triangles: 1758 → 1758 (same icospheres, cleaved in place). Collider 81 → 72. LOD ratios are unchanged. Same-binary determinism: two runs on 5.2.1 match on every measured line.

Falsifier: --pile-rocks skips relaxation and draws the scatter in to 40%. 6 pairs interpenetrate → 20 on all three binaries. Skipping relaxation alone was tried first and exited 8, not 20: the cleaved stones miss each other unrelaxed, so it would have witnessed nothing. tests/check_falsifier_targets.py passes (186 falsifiers).

Existing exit codes, before → after, identical on all three binaries: default 0→0, --skip-decimate 9→9, --stray-vert 15→15, --lift-z 16→16, --poke-rock 17→17, --float-rocks 18→18, --box-rocks 19→19.

Hero re-rendered on 5.2.1 through scripts/render_hero.py. check_framing runs without deviation=: fill y 0.706, min margin 0.033. Contact sheet: docs/gallery/contact-sheets/terrain-scatter-contact-sheet.webp.

  • Luma: 0.200, inside the calibration band.
  • Stage: 0.192.
  • Warmth: +0.130.
  • Saturation: 0.141.
  • Thumbnail: reads as a rocky earth tile.

Still weak: the relaxed layout keeps a visible 3×3 grid rhythm (top ortho). It is inherited from the GN point grid, which this pass left alone.

B — examples/export-preset-axis

Presentation changes (render path only):

  • Spacing: the reimports are placed at ±1.35 m instead of −2.15 / +1.95, which had left an empty metre of floor between them.
  • Camera: oblique, from (4.9, −5.1, 2.2) instead of (3.12, −8.15, 2.45). Looking straight along +Y foreshortened the Godot reimport's mast to a stub in front of its base plate, so the one thing the check proves, that it lies, barely read. Now the mast, lamp head and cyan tip show in profile.

The lying beacon is the contract and stays lying. The clay pass showed no scaffolding defects. The reframe went through two framing failures (fill 0.656, then top margin 0) before landing at fill y 0.828, min margin 0.061. Contact sheet: docs/gallery/contact-sheets/export-preset-axis-contact-sheet.webp, luma 0.157, inside the band.

Contract unchanged. build(), check(), the assertions and the exit codes are untouched. Before → after, identical on 4.5.11, 5.1.2 and 5.2.1: default 0 → 0, --same-axis 9 → 9.

C — examples/mesh-automasking-settings

README improvements:

  • Who hits this: sculpt add-ons and preset importers, with the exact AttributeError.
  • The two traps: the non-uniform prefix rule, and brushes.new(name) without mode="SCULPT" leaving mesh_automasking_settings as None on 5.2.
  • The version-safe reader: states it, and that writes round-trip through the struct (verified on 5.2.1).
  • Full attribute map: all 18 old Brush attributes against their 5.2 names. The 10 use_automasking_* keep their names, the 8 automasking_* drop the prefix, and the new struct adds cavity_curve_op. This replaces the vague "18+".
  • Re-verified table: includes the note that the falsifier exiting 0 on 4.5.11 and 5.1.2 is correct by design.
  • API links: current, plus 4.5 Brush.

Re-verification (live probe):

Measurement 4.5.11 5.1.2 5.2.1
MeshAutomaskingSettings type absent absent present
automasking properties on Brush 18 18 1 (pointer)
settings struct, mode="SCULPT" / default mode n/a n/a struct / None
default / --assume-brush-attrs exit 0 / 0 0 / 0 0 / 5

Documented behaviour is correct. No code change.

Also

  • showcase/README.md conventions:
    • Scatter: scattered parts do not interpenetrate (BVH pair test, relaxation to a derived radius bound, a falsifier that guarantees collisions).
    • Rock: broken rock is cleaved and flat-shaded, not a smooth ellipsoid.
  • gn-sdf-remesh's missing framing gate (reported in fix: water-trough, gn-sdf-remesh and eval-mesh-datablock-name quality pass #229) is still open; it adds an exit code, so it doesn't belong in a quality-pass PR.

🤖 Generated with Claude Code

TMHSDigital and others added 4 commits September 23, 2026 11:48
…hat never interpenetrate

The stones were smooth near-white ellipsoids on pale clay, and two pairs
interpenetrated. Stones are now cleaved by closed-form planes, flat-shaded
and scaled 1.35x; centres relax apart to twice a radius bound derived from
the same constants. A stone-overlap budget BVH-tests every pair (exit 20,
--pile-rocks). Dark mottled soil and grey stone materials. The temp glTF
export is removed after measuring.

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

Render path only: props moved together and the camera made oblique so the
Godot reimport's mast reads along its length. The check, its assertions
and exit codes are unchanged.

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

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

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 23, 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 23, 2026
@TMHSDigital
TMHSDigital merged commit 223b1ee into main Sep 23, 2026
14 checks passed
@TMHSDigital
TMHSDigital deleted the fix/quality-pass-terrain-axis-automasking branch September 23, 2026 15:55
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