Commit Graph

2 Commits

Author SHA1 Message Date
0776beb6f4 fix(xbg7): degenerate index runs 582 -> 1 (grouped path + prefer a clean candidate)
Two follow-ups to the pad-scoring fix, both driven by the same invariant (a
correctly located index run has no degenerate triangles):

- anchor_grouped_meshes picked its pad by first-match too; scoring the pivot run
  the same way cleared every remaining ptc_pack composite (f102/f104/e107).
- anchor_pool_mesh now prefers a degenerate-free candidate over an earlier dirty
  one. examples/better_home.rs showed the last two resources each had exactly one
  degenerate-free, pool-covering block, sitting later in file order than the
  lookalike we took. First-match order is kept for every clean hit, and a dirty
  block is still used if nothing clean exists, so coverage cannot regress.

  degenerate index runs, disc-wide:      582 -> 11 -> 1
  captured index runs identical:         93/93 (unchanged)
  resources decoded / misses:            6 209 / 85 (unchanged)
  index runs changed / anchors moved:    590 / 10 (_rou_f402_dead x8, e201_bdy_03_m x2)

Cross-container minority decodes 89 -> 96, and that is progress: all seven new
rows are _rou_f402_dead, which now has a majority (32x25x8) for the first time, so
its seven wrong copies are named instead of hidden behind "no majority".

The last dirty run (_rou_f402_dead in Stage_S09) is blocked by distinct assignment
— its clean block is claimed by e_rou_f003_Near, both 24-vertex bounding boxes. A
winding-floor escalation for that case was written, measured to fire for nothing,
and reverted; the reasoning is kept as a comment.

Regression threshold tightened to 1. Suite green with --include-ignored apart from
the pre-existing known-failing cross-container consistency test.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NptfmpjdpNCKEez6d2xvA9
2026-08-13 08:52:41 +00:00
41b59faf5f fix(xbg7): the index run was one element late for 575 sub-meshes
Extending the capture comparison from index COUNTS to index VALUES
(`examples/capture_index_bytes.rs`, using the batch offsets the new ib logging
gives) showed 76 of 93 Stage_S02 index runs identical to the GPU's and 17
differing — every difference a shift by exactly one element, on buffers whose
index data sits at pad 2.

`anchor_pool_mesh` returned the FIRST pad that validated, and pad 0 is tried
first with the looser winding gate (0.70 vs 0.85). Read at pad 0, a pad-2 block
yields [true[1], true[2], …, garbage]: every index in range, the pool covered,
the positions right, the winding often just above 0.70 — so it validated, and
every triangle was mis-wired. Nothing count-based could see it.

The signature is decidable without the capture: a shifted run wires arbitrary
vertices, so triangles come out degenerate. 282 of 283 correctly anchored
Stage_S02 blocks have zero degenerate triangles, while the shifted readings carry
1–2 156. So score every validating pad by (degenerate triangles, then winding)
and keep the best. `XBG7_PAD_FIRST_MATCH=1` restores the old behaviour.

  captured index runs identical:            76/93  ->  93/93  (2 025 elements)
  decoded runs with a degenerate triangle:    579  ->     16  (disc-wide)
  sub-meshes whose index run changed:                    575  of 8 850
  resources decoded / vertex anchors / consistency:  unchanged (6 209 / same vb / 89)

Locked in by tests/mesh_disc.rs::decoded_index_runs_have_almost_no_degenerate_triangles.
Suite green with --include-ignored apart from the pre-existing known-failing
cross-container consistency test (the 24-vertex bounding-box class).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NptfmpjdpNCKEez6d2xvA9
2026-08-13 07:26:52 +00:00