fix(mesh): filtered decode must not depend on the requested subset

models_named pruned to the wanted set BEFORE distinct assignment, so collision
resolution saw a different resource population and returned different offsets:
27 of 356 resources in Stage_S02 decoded differently when asked for alone,
including real geometry (f001_bdy_30, f106_sld_02_l/m/d, f101_wep_01_l). Both the
viewer and assemble_ship decode subsets, so both could disagree with the
container's own answer. This was a regression from distinct assignment itself.

Fixed by filtering the OUTPUT: the assignment always runs over the whole
container. One-name, three-name and full decodes now agree exactly. Cost: a
single-resource query on a 50MB container goes from near-instant to ~15s;
per-container caching is the follow-up. Ten suites green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 18:47:41 +00:00
parent e8434541f2
commit c79c0f6ccf
3 changed files with 85 additions and 5 deletions

View File

@@ -1097,6 +1097,28 @@ that carry it) and `t901_e01_D` is 58×59×3013 (a mast). And `f101_bdy_01` flag
at 6× while being **capture-verified exact** in the truth table — a useful
reminder that a bulky hull is not a bug.
### ✅ Fixed: a filtered decode no longer depends on what you ask for
Distinct assignment resolves collisions against the set of resources being
decoded — and `models_named` was pruning to the requested subset **before** that
pass. So the answer depended on the request: measured on `Stage_S02`, **27 of 356
resources came out at a different offset when asked for alone** than in a full
decode, and not only boxes — `f001_bdy_30`, `f106_sld_02_l/m/d`, `f101_wep_01_l`
among them. Both the viewer and `ship::assemble_ship` decode subsets, so both
could get geometry the container's own answer disagrees with.
This was a regression introduced by distinct assignment itself, and it is fixed
by applying `wanted` to the **output** instead of the input: the assignment
always runs over the whole container, and a subset is now a subset of the
container's own answer. Verified: one-name, three-name and full decodes now
return the identical offset for the same resource.
**Cost, stated plainly:** a single-resource query on a 50 MB container went from
near-instant to **~15 s**, because it now anchors every resource. The viewer
calls this once per ship view (with cancellation), so it is a slow prepare step
rather than a per-frame cost — but caching the per-container decode is the
obvious follow-up and is not done here.
### The consistency figure is mostly bounding boxes — real disagreement is ONE resource
`examples/consensus_check.rs` sharpens the cross-container test: with three or