# Capital-ship placement โ€” does the `e106` result generalise? (WIP, 2026-07-31) **Status:** ๐Ÿšง **WIP, time-boxed session.** Two results so far: a static audit across all 22 stage containers (done, below) and a first in-mission F10 capture run in Stage 02 (done โ€” three capture logs, but **no capital-ship part correlated**; see "Open"). Context: [`BACKLOG.md`](BACKLOG.md) โ€” "Capital ships assemble wrong in the viewer", reported 2026-07-30. The oracle and the correlator already exist ([`ship-placement-runtime-capture.md`](ship-placement-runtime-capture.md)); the open question is whether the rules derived from the one validated ship (`e106`, Stage_S01) hold for other classes. ## 1. Static audit across all stages (offline, reproducible) ``` cargo run --release --example ship_audit -- ../sylph_extract/hidden/resource3d ``` 87 lines of output, of which: - **Only two OUTLIER lines, and they are the same ship twice**: `Stage_S03`/`Stage_S27`, `f002_bdy_05` centroid `[-1398 6251 918]`, `dist=6540` vs a cluster spread of `1071`. Every other assembled ship in every other stage has all parts inside its own cluster. โ†’ **The user-visible breakage is NOT a gross static-placement outlier for most classes.** Whatever is wrong in the viewer is either subtler than "part flung far away" (wrong rotation, wrong mirror, missing part) or lives in the viewer, not in `assemble_ship`. `f002_bdy_05` is a genuine, separate, reproducible static bug. - **MULTIKEY**: joint tracks with more than one keyframe, which `read_trs9`'s single-key read does not model. Recurring rigs: `e_rou_f104` (3), `e_rou_f105` (2), `e_rou_f106` (2), `e_rou_e102` (6), `e_rou_e108_Missile_open` (2), `e_rou_e501` (1), and the `e901` boss with 2โ€“15 tracks per pose. Several of these (`Missile_open`, the `e901_attack*` poses) are obviously *animation* and harmless for a static pose; the plain hull rigs `f104`/`f105`/`f106`/`e102` are **not** obviously animation and are the best hypothesis for a class-specific assembly error. โ” **HYPOTHESIS โ€” not verified.** `e106`, the one validated ship, has **no** multikey tracks, which is exactly how a rule that only works for single-key rigs could have passed unnoticed. Raw audit output is reproducible with the command above (not checked in; it is deterministic from the disc). ## 2. First in-mission capture run (Stage 02) New tool: [`tools/re-capture/ship_capture_session.sh`](../../tools/re-capture/ship_capture_session.sh) โ€” one blocking session (per the session-lifetime rule): boot โ†’ Stage 02 in flight โ†’ Nร— {screenshot, F10, small yaw}. Each F10 writes its own `xenia_ship_capture_NN.log` next to the binary. Run 2026-07-31, 5 presses requested: - **Boot to in-flight took 24 s** (`skip_intro.sh` skipped the movie at 1 s and 6 s, title at 11 s, HUD shield bar at 24 s) โ€” much faster than the ~100 s in the notes. - **3 of 5 F10 presses produced a log** (`_01`โ€ฆ`_03`, 2964 / 3111 / 3668 draws). Logs (8โ€“10 MB each) and the screenshots are at `/sylph-home/re/shipcap/`; not committed for size. One screenshot is checked in as [`captures/shipcap-stage02-launch.png`](captures/shipcap-stage02-launch.png). - The screenshot confirms the capture frames are real in-mission combat frames (HUD live, `REMAINING OB 004`, ACROPOLIS + a Destroyer labelled on screen, a capital-ship hull filling the bottom of the frame). ### Result: no correlation yet โŒ ``` correlate_capture xenia_ship_capture_03.log Stage_S02 bdy_01 ``` for `f101` (ACROPOLIS), `f105`, `f106`, `e105` reports *"no draw matches any LOD (culled/off-screen?)"* for essentially every part โ€” only two speculative LOD tries (`f101_bdy_03` vcount 90 `[l]`, `e105_wep_01` vcount 60 `[l]`) and **zero accepted matches**. That is a **negative result, and it is not yet explained**. Facts collected: - The capture is not empty or degenerate: 3668 draws in `_03`, top shaders `0xDA51B0745ABF85D2` (1258), `0xE0BAFB4F520FE441` (1091), `0xEEA84C59D7F95371` (770). None is the `e106` ship-shader hash from the 2026-07-26 capture; the F10 path does not filter by hash, so this alone is not the cause. - Large vertex counts *are* present (3024, 2772, 1736, 1612, 1240 โ€ฆ), so capital-ship- sized geometry is being drawn. Candidate explanations, **untested**: 1. the Stage-02 capital ships on screen are drawn from LOD/damage variants (`_d00`, `_m`, `_l`) whose vcounts the correlator's variant list does not cover; 2. the position-validation step rejects otherwise-correct vcount hits (the capture dumps โ‰ค64 positions โ€” a set-membership test against the wrong variant fails); 3. the ships in view at launch are drawn by a *different* draw path than `e106` in Stage_S01 (e.g. instanced/batched), so no single draw equals one part. **First step next session:** take the largest few vcounts in the capture and ask which decoded part in `Stage_S02.xpr` has that count (invert the match), instead of asking per-part whether a draw exists. That distinguishes (1)/(2) from (3) immediately. ## 3. The inverted match โ€” the ships were never drawn (2026-08-10) โœ… explained The inversion was run and it settles the negative result. Two new tools: ``` cargo run --release --example invert_capture -- Stage_S02 [top_n] [--ship f101] cargo run --release --example vcount_index -- ../sylph_extract/hidden/resource3d ``` `invert_capture` asks, of the capture's own vertex counts, which resource in one stage container has that count; `vcount_index` asks the same across **all 166 containers** (5480 resources), so a draw whose geometry lives in `Common.xpr`, a `rou_*` weapon pack or a `DeltaSaber_*` player-craft pack is identified instead of coming back "unknown". On `xenia_ship_capture_03.log` (3668 draws, Stage 02): | capture vcount | draws | what it is | |---|---|---| | 10891 | 28 | **`DeltaSaber_T:f001`** โ€” the player's own craft | | 6000 | 14 | `Stage_S02:n006_02` โ€” backdrop | | 1096 / 1008 / 841 / 215 / 127 | 14โ€“112 | `rou_f001_wep_*` โ€” the player's weapons | | 417 / 279 / 201 / 167 | 104โ€“448 | `Base:j00*`, `ptc_pack:*` โ€” HUD/particles | | 8 / 4 / 3 / 1 | 317โ€“590 | particle quads | - **Not one capital-ship hull part appears.** Per ship: `f101` **1 of 15** resources had a drawn vcount (`f101_bdy_03_l`, 90 verts), `e105` 3 of 37, `e106` 3 of 34 โ€” and each of those hits is a 44โ€“225-vertex `_l`/`_b` piece whose count also collides with dozens of unrelated resources, i.e. probably not even the ship. - The 3668 draws span **~14 frames** per F10 press and use only **10 distinct vertex shaders**, and the player's own craft is captured at **full detail with its `c0..c2` WVP rows** โ€” so the capture path itself is healthy and unfiltered. - The screenshot ([`captures/shipcap-stage02-launch.png`](captures/shipcap-stage02-launch.png)) agrees once read carefully: the hull "filling the bottom of the frame" is the **player's own craft** in the chase view. The nearest contact on the HUD is a wingman's engine trail. **So hypothesis (3) is dead, and (1)/(2) never applied.** The correlator's message "no draw matches any LOD (culled/off-screen?)" was literally true: the ships were far enough away that the renderer drew nothing of them. `correlate` additionally cannot anchor without the reference part, and `f101_bdy_01` was never drawn at any LOD. **The variable that was never controlled is RANGE.** New tooling closes that gap: [`tools/re-capture/approach_capture.py`](../../tools/re-capture/approach_capture.py) locks onto a capital ship (definition size-radius โ‰ฅ 150 = not a fighter), flies at it with navigator.py's drift compensation and CPA avoidance, firing disabled, and presses F10 as each range band is crossed (8000 / 6000 / 4500 / 3000 / 2000 / 1400 / 900), stamping every capture with its distance in `approach-bands.jsonl`. Driver: [`ship_capture_close.sh`](../../tools/re-capture/ship_capture_close.sh). Besides giving the correlator a full-detail frame, the stamped bands measure the game's own **LOD ladder** per part, which the reborn renderer needs anyway. ## Honest summary - โœ… Static assembly is **not** grossly broken across stages โ€” 1 outlier ship (`f002_bdy_05`), reproducible. - ๐ŸŸก A concrete, testable hypothesis for class-specific breakage exists (multikey joint tracks on `f104`/`f105`/`f106`/`e102`; `e106` has none). - โŒ The runtime oracle has **not** reproduced on a second ship class yet โ€” but the reason is now known and is not a format or correlator bug: **the captures were taken at ranges where no capital-ship geometry is drawn at all** (ยง3, verified by inverting the match against all 5480 decoded resources). Do not assume the `e106` rules generalise; equally, do not read the zero-match as evidence against them. - โ–ถ Next: run `ship_capture_close.sh` so the capture happens with a hull actually on screen, then re-run `correlate_capture` on the closest band.