feat(runtime): use mission placement in render snapshots
This commit is contained in:
@@ -32,7 +32,7 @@ use fparkan_render::{
|
|||||||
use fparkan_render_vulkan::VulkanPlanningBackend;
|
use fparkan_render_vulkan::VulkanPlanningBackend;
|
||||||
use fparkan_runtime::{
|
use fparkan_runtime::{
|
||||||
create, frame, load_mission, loaded_mission_assets, EngineConfig, EngineMode, EngineServices,
|
create, frame, load_mission, loaded_mission_assets, EngineConfig, EngineMode, EngineServices,
|
||||||
MissionAssets, MissionRequest,
|
MissionAssets, MissionObjectDraft, MissionRequest,
|
||||||
};
|
};
|
||||||
use fparkan_vfs::DirectoryVfs;
|
use fparkan_vfs::DirectoryVfs;
|
||||||
use fparkan_world::WorldSnapshot;
|
use fparkan_world::WorldSnapshot;
|
||||||
@@ -85,8 +85,10 @@ fn run(args: &[String]) -> Result<String, String> {
|
|||||||
last_tick = result.snapshot.tick.0;
|
last_tick = result.snapshot.tick.0;
|
||||||
last_hash = result.snapshot.hash.0;
|
last_hash = result.snapshot.hash.0;
|
||||||
let mission_assets = loaded_mission_assets(&engine);
|
let mission_assets = loaded_mission_assets(&engine);
|
||||||
let commands = render_snapshot_commands_with_assets(&result.snapshot, mission_assets)
|
let mission_drafts = fparkan_runtime::loaded_mission_object_drafts(&engine);
|
||||||
.map_err(|err| format!("render snapshot: {err}"))?;
|
let commands =
|
||||||
|
render_snapshot_commands_with_assets(&result.snapshot, mission_assets, mission_drafts)
|
||||||
|
.map_err(|err| format!("render snapshot: {err}"))?;
|
||||||
last_draw_count = commands
|
last_draw_count = commands
|
||||||
.commands
|
.commands
|
||||||
.iter()
|
.iter()
|
||||||
@@ -114,20 +116,22 @@ fn run(args: &[String]) -> Result<String, String> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn render_snapshot_commands(snapshot: &WorldSnapshot) -> Result<RenderCommandList, String> {
|
fn render_snapshot_commands(snapshot: &WorldSnapshot) -> Result<RenderCommandList, String> {
|
||||||
render_snapshot_commands_with_assets(snapshot, None)
|
render_snapshot_commands_with_assets(snapshot, None, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_snapshot_commands_with_assets(
|
fn render_snapshot_commands_with_assets(
|
||||||
snapshot: &WorldSnapshot,
|
snapshot: &WorldSnapshot,
|
||||||
mission_assets: Option<&MissionAssets>,
|
mission_assets: Option<&MissionAssets>,
|
||||||
|
mission_drafts: Option<&[MissionObjectDraft]>,
|
||||||
) -> Result<RenderCommandList, String> {
|
) -> Result<RenderCommandList, String> {
|
||||||
let render_snapshot = render_snapshot_with_assets(snapshot, mission_assets);
|
let render_snapshot = render_snapshot_with_assets(snapshot, mission_assets, mission_drafts);
|
||||||
build_commands(&render_snapshot, RenderProfile::default()).map_err(|err| err.to_string())
|
build_commands(&render_snapshot, RenderProfile::default()).map_err(|err| err.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_snapshot_with_assets(
|
fn render_snapshot_with_assets(
|
||||||
snapshot: &WorldSnapshot,
|
snapshot: &WorldSnapshot,
|
||||||
mission_assets: Option<&MissionAssets>,
|
mission_assets: Option<&MissionAssets>,
|
||||||
|
mission_drafts: Option<&[MissionObjectDraft]>,
|
||||||
) -> RenderSnapshot {
|
) -> RenderSnapshot {
|
||||||
let mut draws = Vec::with_capacity(snapshot.objects.len());
|
let mut draws = Vec::with_capacity(snapshot.objects.len());
|
||||||
for (index, handle) in snapshot.objects.iter().enumerate() {
|
for (index, handle) in snapshot.objects.iter().enumerate() {
|
||||||
@@ -168,7 +172,12 @@ fn render_snapshot_with_assets(
|
|||||||
material_slots: vec![material],
|
material_slots: vec![material],
|
||||||
material_index: 0,
|
material_index: 0,
|
||||||
pipeline_state: fparkan_render::LegacyPipelineState::default(),
|
pipeline_state: fparkan_render::LegacyPipelineState::default(),
|
||||||
transform: identity_transform(index_to_f32(index)),
|
transform: mission_drafts
|
||||||
|
.and_then(|drafts| drafts.get(index))
|
||||||
|
.map_or_else(
|
||||||
|
|| identity_transform(index_to_f32(index)),
|
||||||
|
mission_position_scale_transform,
|
||||||
|
),
|
||||||
range: IndexRange { start: 0, count: 3 },
|
range: IndexRange { start: 0, count: 3 },
|
||||||
stable_order,
|
stable_order,
|
||||||
});
|
});
|
||||||
@@ -180,6 +189,27 @@ fn render_snapshot_with_assets(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mission_position_scale_transform(draft: &MissionObjectDraft) -> [f32; 16] {
|
||||||
|
[
|
||||||
|
draft.scale[0],
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
draft.position[0],
|
||||||
|
0.0,
|
||||||
|
draft.scale[1],
|
||||||
|
0.0,
|
||||||
|
draft.position[1],
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
draft.scale[2],
|
||||||
|
draft.position[2],
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
1.0,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
fn identity_transform(x: f32) -> [f32; 16] {
|
fn identity_transform(x: f32) -> [f32; 16] {
|
||||||
[
|
[
|
||||||
1.0, 0.0, 0.0, x, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
|
1.0, 0.0, 0.0, x, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
|
||||||
@@ -362,7 +392,7 @@ mod tests {
|
|||||||
object_visuals: vec![vec![AssetId::new(101), AssetId::new(102)]],
|
object_visuals: vec![vec![AssetId::new(101), AssetId::new(102)]],
|
||||||
..MissionAssets::default()
|
..MissionAssets::default()
|
||||||
};
|
};
|
||||||
let commands = render_snapshot_commands_with_assets(&snapshot, Some(&assets))?;
|
let commands = render_snapshot_commands_with_assets(&snapshot, Some(&assets), None)?;
|
||||||
let draws: Vec<_> = commands
|
let draws: Vec<_> = commands
|
||||||
.commands
|
.commands
|
||||||
.iter()
|
.iter()
|
||||||
@@ -380,6 +410,24 @@ mod tests {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_snapshot_uses_mission_position_and_scale_without_interpreting_orientation() {
|
||||||
|
let draft = MissionObjectDraft {
|
||||||
|
original_id: None,
|
||||||
|
resource_name_raw: Vec::new(),
|
||||||
|
identity_or_clan_raw: 0,
|
||||||
|
position: [10.0, 20.0, 30.0],
|
||||||
|
orientation_raw: [1.0, 2.0, 3.0],
|
||||||
|
scale: [2.0, 3.0, 4.0],
|
||||||
|
visual_ids: Vec::new(),
|
||||||
|
properties: Vec::new(),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
mission_position_scale_transform(&draft),
|
||||||
|
[2.0, 0.0, 0.0, 10.0, 0.0, 3.0, 0.0, 20.0, 0.0, 0.0, 4.0, 30.0, 0.0, 0.0, 0.0, 1.0,]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn prepared_visual(id: u64, material: u64) -> PreparedVisual {
|
fn prepared_visual(id: u64, material: u64) -> PreparedVisual {
|
||||||
PreparedVisual {
|
PreparedVisual {
|
||||||
id: AssetId::new(id),
|
id: AssetId::new(id),
|
||||||
|
|||||||
@@ -916,6 +916,15 @@ prepared visual сохраняет один compatibility fallback draw. Это
|
|||||||
multi-component prototype graph для будущего real Vulkan renderer, однако
|
multi-component prototype graph для будущего real Vulkan renderer, однако
|
||||||
текущий game app всё ещё использует planning backend и triangle ranges.
|
текущий game app всё ещё использует planning backend и triangle ranges.
|
||||||
|
|
||||||
|
### Mission position/scale render bridge
|
||||||
|
|
||||||
|
`fparkan-game` now maps preserved TMA position and non-uniform scale into each
|
||||||
|
backend-neutral draw matrix instead of diagnostic index placement. Raw
|
||||||
|
orientation deliberately remains uninterpreted: the original Euler order and
|
||||||
|
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.
|
||||||
|
|
||||||
`Land.msh` использует отдельный geometry-only bridge: validated `TerrainFace28`
|
`Land.msh` использует отдельный geometry-only bridge: validated `TerrainFace28`
|
||||||
сохраняет source triangle order, а его positions и packed UV0 попадают в тот же
|
сохраняет source triangle order, а его positions и packed UV0 попадают в тот же
|
||||||
static vertex/index upload path. Для текущего диагностического viewer XZ bounds
|
static vertex/index upload path. Для текущего диагностического viewer XZ bounds
|
||||||
|
|||||||
Reference in New Issue
Block a user