ship: engine placement CONFIRMED by 43-instance capture; exhaust markers added
capture_verify example: clusters every part's ship-relative transform across the new multi-snapshot, multi-instance F10 captures (5 snapshots, 43 e106 instances, all angles). Verdict: the dominant clusters match the static assembly to ~1 unit on EVERY part — including BOTH engine nacelles at (+-131, -133, -131) — so the "engines inside the hull" appearance is the game's own placement: the engine geometry sits recessed in the aft hull, and the visible "thrusters" in-game are exhaust FX drawn at the GN_Jet/GN_SJet frames (Z ~ -570, past the stern). To close that perception gap the viewer now draws simple exhaust cones at the game's own jet frames (ship::exhaust_frames; part of the external-parts toggle). The jet frames flip Z, so the cone apex is authored at +Z and lands trailing aft — verified in the offline render. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -376,6 +376,29 @@ pub fn assemble_ship(bytes: &[u8], id: &str, include_external: bool) -> Vec<Scen
|
||||
placed
|
||||
}
|
||||
|
||||
/// The ship's exhaust mount frames (`GN_Jet_*` / `GN_SJet_*`), world-space, from
|
||||
/// the primary composite. These are where the game renders the engine exhaust
|
||||
/// FX — the visible "thrusters". The engine GEOMETRY itself sits recessed in
|
||||
/// the hull (capture-verified across 43 e106 instances: the game draws
|
||||
/// `eng_01`/`eng_02` exactly where [`assemble_ship`] puts them); without the
|
||||
/// FX the assembled ship reads engine-less, so a viewer can draw exhaust
|
||||
/// markers at these frames.
|
||||
pub fn exhaust_frames(bytes: &[u8], id: &str) -> Vec<ScenePart> {
|
||||
let names = xbg7_resource_names(bytes);
|
||||
let scenes: Vec<Vec<ScenePart>> = composites_for(&names, id)
|
||||
.into_iter()
|
||||
.filter(|c| !c.ends_with("_joint"))
|
||||
.map(|c| scene_world_nodes(bytes, c))
|
||||
.collect();
|
||||
let Some(nodes) = scenes.into_iter().max_by_key(|n| n.len()) else {
|
||||
return Vec::new();
|
||||
};
|
||||
nodes
|
||||
.into_iter()
|
||||
.filter(|n| n.resource.starts_with("GN_Jet") || n.resource.starts_with("GN_SJet"))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Detect shared-geometry port/starboard twin RESOURCES placed at ±TX and mark
|
||||
/// the dominant-side instance as an X-reflection (negate the matrix X column).
|
||||
/// Twins are `<stem>_01`/`<stem>_02` pairs with equal vertex data; the reflected
|
||||
|
||||
Reference in New Issue
Block a user