Promote the F10 ship-capture correlator from an example into a reusable, unit-
tested library module (ship_capture): parse_capture (log -> per-draw rigid
WorldView from the c0..c2 WVP constants), correlate (match parts to draws by
vertex count, express each in the reference part's frame), and a checked-in
placement-table format (serialize_table/parse_table, embedded via
embedded_placement from data/ship_placements.txt).
build_ship_model now prefers a ship's captured placement over the static
assemble_ship when a table entry exists (empty table -> unchanged fallback).
correlate_capture example refactored onto the module + gains --emit to print a
table block. Doc updated: bake plumbing done; remaining is running real F10
captures to populate the table (needs the emulator).
5 new ship_capture tests (parse/normalize/correlate/table round-trip); 76
formats-lib tests + viewer build green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Static external-part placement (ship::assemble_ship) is only approximate — a GN_*
frame is the mount pivot, and the real offset lives in a runtime detail rig. So
capture ground truth from Canary instead.
Finding: the guest vertex buffer holds LOCAL coords (byte-identical to the .xpr),
so capital-ship parts are placed entirely in the vertex shader. The per-part
transform is in the VS float constants — c0..c2 are the WorldViewProjection rows;
normalising each by its norm (= projection x/y/z scales, sy/sx = 16:9) yields the
rigid WorldView (rows orthonormal, det +1). Expressing every part relative to a
reference part cancels the camera: rel_p = WV_ref⁻¹·WV_p, a pure ship-space rigid
transform.
- examples/correlate_capture.rs: parse xenia_ship_capture.log, decode the ship's
parts, match by vertex count, recover each part's ship-relative placement.
- docs/re/ship-placement-runtime-capture.md: full method + the capture protocol
(Canary branch capture-ship-placement, F10 hotkey) + validated e106 result.
Validated on e106 (ADAN Destroyer, Stage_S01): all 7 drawn parts matched by
vertex count; bdy_01/bdy_02 recovered as a PORT/STARBOARD pair (X = ∓264) that
static had overlapping; engines correctly aft; extent 872×670×2181. Only brg_01
(bridge) missing — culled at that camera angle, needs a bridge-facing capture.
HANDOFF: next = re-capture bridge, bake a per-ship placement table the viewer
prefers over assemble_ship, then capture the cruiser / ACROPOLIS / TCAF ships.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>