re: eng_02_l's real block is adjacent -- the connectivity heuristic rejects it

debug_find_index_buffer scans the container for an index buffer that validates
against a capture-proven vertex buffer. For eng_02_l nothing validates with the
connectivity test on; with it off the nearest hit is exact pad-0 adjacency
(vb-ib = 144 = 72*2). The block's mean_edge/diag is 0.417 against a 0.28 cap --
the documented false positive for coarse LODs, now caught with ground truth.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 02:31:53 +00:00
parent dde52c02e7
commit 845b63d7dd
3 changed files with 155 additions and 0 deletions

View File

@@ -714,6 +714,40 @@ sub-range, a different unit, or a Xenia-side artifact is unknown — it may matt
for `eng_02_l`, whose block validation is exactly what an index-count mismatch
would break.
**6. Why `eng_02_l`'s real block is rejected: the connectivity heuristic.**
`mesh::debug_find_index_buffer` scans the *whole container* for an index buffer
that validates against a known vertex buffer, instead of assuming adjacency
(`examples/find_ib.rs`). For `e106_eng_02_l` at the capture-proven `0x44a32c`,
with the connectivity test on, **nothing in the container validates**. With it
off (`SOFT_IB=1`) the nearest hit is `ib 0x44a29c``vb ib = 144 = 72 × 2`,
i.e. **exact pad-0 adjacency**. So the index buffer is exactly where the decoder
assumes it is; the block is thrown out by one heuristic.
That heuristic is `mean_edge / bbox_diag > 0.28 → reject`. Measured on the real
blocks:
| block | mean edge | bbox diagonal | ratio | verdict |
|---|---|---|---|---|
| `eng_02_l` (24 tris) `ib 0x44a29c → vb 0x44a32c` | 109.21 | 261.96 | **0.417** | rejected (cap 0.28) |
| `bdy_02_l` (82 tris) `ib 0x3c53ec → vb 0x3c55d8` | 131.70 | 786.66 | 0.167 | passes |
| `bdy_01_l` (82 tris) `ib 0x3b3cfc → vb 0x3b3ee8` | 131.70 | 786.66 | 0.167 | passes |
This is precisely the false positive the check's own comment predicts — "a small
flat sub-mesh legitimately has large edges relative to its own diagonal" — caught
in the wild for the first time, with the runtime naming the block it rejects. A
24-triangle engine LOD is coarse by construction, so its edges *are* a large
fraction of its size.
(The twins' two real blocks having **identical** mean edge and diagonal is a free
corroboration that they are mirror images: reflection preserves lengths.)
So the residual class is not one bug. `eng_02_l` has its vertex start in the
candidate list *and* its index buffer exactly adjacent, and still fails — a
**validator** problem, not a scan or selection one. Raising the cap is not the
fix to reach for blind: the threshold trades against false anchors, and now that
a capture can name true blocks, it can be **calibrated** against them rather than
guessed. Not changed here.
Not settled: `e106_brg_01_b_02``e106_brg_01_l` (51 verts). A second 51-vertex
`vbase` exists in the logs but is **not** from this container, and the container
holds three near-identical 51-vertex runs, so the pair has no oracle yet.