diff --git a/docs/re/captures/shipcap-stage02-launch.png b/docs/re/captures/shipcap-stage02-launch.png new file mode 100644 index 0000000..e304bbf Binary files /dev/null and b/docs/re/captures/shipcap-stage02-launch.png differ diff --git a/docs/re/ship-placement-capture-generalisation.md b/docs/re/ship-placement-capture-generalisation.md new file mode 100644 index 0000000..ce7d422 --- /dev/null +++ b/docs/re/ship-placement-capture-generalisation.md @@ -0,0 +1,100 @@ +# 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. + +## 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 did **not** reproduce on a second ship class yet. The capture + pipeline works end-to-end (boot → F10 → logs); the correlation step is where it + stops. **NEEDS-HUMAN / next session**, do not assume the `e106` rules generalise. diff --git a/tools/re-capture/ship_capture_session.sh b/tools/re-capture/ship_capture_session.sh new file mode 100755 index 0000000..438d5b7 --- /dev/null +++ b/tools/re-capture/ship_capture_session.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# ONE blocking session: boot -> Stage 02 in flight -> sweep the view and press +# F10 several times, so each press dumps xenia_ship_capture_NN.log with whatever +# capital ships are on screen at that moment. +# +# Why a sweep and not a single press: the 2026-07-26 e106 capture missed the +# bridge because it was culled at that camera angle. Several presses at +# different headings cost nothing (the capture is a one-frame draw dump) and +# each one is independently correlatable. +# +# Usage: ship_capture_session.sh [presses] [out_dir] +set -u +export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98 +SD="$(cd "$(dirname "$0")" && pwd)" +PRESSES="${1:-6}" +OUT="${2:-/sylph-home/re/shipcap}" +BINDIR="/home/fabi/RE - Project Sylpheed/xenia-canary-native/build/bin/Linux/Release" +SHOTS=/sylph-home/re/shots +mkdir -p "$OUT" "$SHOTS" + +rm -f "$BINDIR"/xenia_ship_capture_*.log + +"$SD/launch_mission.sh" fly || { echo "BOOT FAILED"; exit 1; } + +# F10 goes to the emulator window through XTEST; the window must be focused. +win="$(xdotool search --class -- xenia | tail -1)" +[ -z "$win" ] && win="$(xdotool search --name -- Xenia | tail -1)" +echo "WINDOW=$win" +[ -n "$win" ] && { xdotool windowactivate "$win" 2>/dev/null; xdotool windowfocus "$win" 2>/dev/null; } + +for i in $(seq 1 "$PRESSES"); do + screenshot "$SHOTS/shipcap-$i.png" >/dev/null 2>&1 + if [ -n "$win" ]; then xdotool key --window "$win" F10; else xdotool key F10; fi + sleep 3 + # Yaw a little between presses so a culled part gets another chance, and the + # craft keeps closing on the friendly formation (the capital ships). + vgamepad axis LX 0.45; sleep 1.2; vgamepad axis LX 0.0 + sleep 3 +done + +sleep 2 +cp -v "$BINDIR"/xenia_ship_capture_*.log "$OUT"/ 2>/dev/null +cp -v "$SHOTS"/shipcap-*.png "$OUT"/ 2>/dev/null +grep -c '^DRAW' "$OUT"/xenia_ship_capture_*.log 2>/dev/null +echo "CAPTURE SESSION DONE"