diff --git a/apps/fparkan-game/src/main.rs b/apps/fparkan-game/src/main.rs index 3549b11..b199805 100644 --- a/apps/fparkan-game/src/main.rs +++ b/apps/fparkan-game/src/main.rs @@ -35,6 +35,8 @@ use fparkan_runtime::{ MissionAssets, MissionObjectDraft, MissionRequest, }; use fparkan_vfs::DirectoryVfs; +#[cfg(test)] +use fparkan_world::OriginalObjectId; use fparkan_world::WorldSnapshot; use std::path::PathBuf; use std::sync::Arc; @@ -167,7 +169,9 @@ fn render_snapshot_with_assets( draws.push(RenderSnapshotDraw { id: DrawId(draw_id), phase: RenderPhase::Opaque, - object_id: None, + object_id: mission_drafts + .and_then(|drafts| drafts.get(index)) + .and_then(|draft| draft.original_id), mesh, material_slots: vec![material], material_index: 0, @@ -428,6 +432,36 @@ mod tests { ); } + #[test] + fn render_snapshot_preserves_mission_original_object_id() -> Result<(), String> { + let snapshot = WorldSnapshot { + tick: Tick(1), + objects: vec![ObjectHandle { + generation: 1, + slot: 0, + }], + events: Vec::new(), + hash: StateHash([0; 32]), + }; + let drafts = vec![MissionObjectDraft { + original_id: Some(OriginalObjectId(42)), + resource_name_raw: Vec::new(), + identity_or_clan_raw: 0, + position: [0.0; 3], + orientation_raw: [0.0; 3], + scale: [1.0; 3], + visual_ids: Vec::new(), + properties: Vec::new(), + }]; + + let commands = render_snapshot_commands_with_assets(&snapshot, None, Some(&drafts))?; + let RenderCommand::Draw(draw) = &commands.commands[1] else { + return Err("expected draw".to_string()); + }; + assert_eq!(draw.object_id, Some(OriginalObjectId(42))); + Ok(()) + } + fn prepared_visual(id: u64, material: u64) -> PreparedVisual { PreparedVisual { id: AssetId::new(id), diff --git a/docs/tomes/05-render.md b/docs/tomes/05-render.md index 85fc231..44ffac7 100644 --- a/docs/tomes/05-render.md +++ b/docs/tomes/05-render.md @@ -925,6 +925,15 @@ matrix convention are not yet proven. This preserves authored values without inventing transform math; the app still uses planning backend and triangle ranges, so it is not a full renderer claim. +### Mission original-ID render provenance + +Each backend-neutral draw now retains the `OriginalObjectId` preserved by the +TMA loader for its source mission object. This gives capture and diagnostics a +stable link from a draw back to its original object record, including every +visual component emitted for that object. The bridge deliberately leaves the +value absent when no mission draft exists; it does not infer an original ID +from a runtime slot or draw order. + `Land.msh` использует отдельный geometry-only bridge: validated `TerrainFace28` сохраняет source triangle order, а его positions и packed UV0 попадают в тот же static vertex/index upload path. Для текущего диагностического viewer XZ bounds