diff options
Diffstat (limited to 'apps')
| -rw-r--r-- | apps/fparkan-cli/src/main.rs | 58 | ||||
| -rw-r--r-- | apps/fparkan-game/src/main.rs | 44 |
2 files changed, 76 insertions, 26 deletions
diff --git a/apps/fparkan-cli/src/main.rs b/apps/fparkan-cli/src/main.rs index 6d5fb3c..e118b2e 100644 --- a/apps/fparkan-cli/src/main.rs +++ b/apps/fparkan-cli/src/main.rs @@ -25,8 +25,7 @@ use fparkan_assets::{ decode_mission_payload, extend_graph_report_with_visual_dependencies, TmaProfile, }; use fparkan_corpus::{discover, render_report_json, report, DiscoverOptions}; -use fparkan_inspection::inspect_archive_file; -use fparkan_inspection::ArchiveInspection; +use fparkan_inspection::{inspect_archive_file, inspect_land_msh_bounds_file, ArchiveInspection}; use fparkan_path::{normalize_relative, PathPolicy}; use fparkan_prototype::build_prototype_graph_report; use fparkan_resource::{resource_name, CachedResourceRepository}; @@ -42,6 +41,7 @@ const ARCHIVE_INSPECT_SCHEMA: &str = "fparkan-archive-inspect-v1"; const PROTOTYPE_INSPECT_SCHEMA: &str = "fparkan-prototype-inspect-v1"; const MISSION_GRAPH_SCHEMA: &str = "fparkan-mission-graph-v1"; const MISSION_INSPECT_SCHEMA: &str = "fparkan-mission-inspect-v1"; +const TERRAIN_INSPECT_SCHEMA: &str = "fparkan-terrain-inspect-v1"; #[derive(Serialize)] struct ArchiveInspectOutput<'a> { @@ -115,6 +115,15 @@ struct MissionObjectInspectOutput { } #[derive(Serialize)] +struct TerrainInspectOutput { + schema_version: &'static str, + path: String, + positions: usize, + min: [f32; 3], + max: [f32; 3], +} + +#[derive(Serialize)] struct GraphFailureOutput { root_index: usize, edge: &'static str, @@ -178,6 +187,10 @@ fn run(args: &[String]) -> Result<(), String> { let rest = strip_format_json(rest)?; inspect_mission(&rest) } + [domain, command, rest @ ..] if domain == "terrain" && command == "inspect" => { + let rest = strip_format_json(rest)?; + inspect_terrain(&rest) + } _ => Err(usage()), } } @@ -400,6 +413,22 @@ fn inspect_archive(args: &[String]) -> Result<(), String> { } } +fn inspect_terrain(args: &[String]) -> Result<(), String> { + let path = parse_file_path(args, "terrain inspect")?; + let bounds = inspect_land_msh_bounds_file(&path)?; + println!( + "{}", + serialize_json(&TerrainInspectOutput { + schema_version: TERRAIN_INSPECT_SCHEMA, + path: path.display().to_string(), + positions: bounds.positions, + min: bounds.min, + max: bounds.max, + })? + ); + Ok(()) +} + fn archive_inspect_json( path: &str, kind: &str, @@ -416,10 +445,14 @@ fn archive_inspect_json( } fn parse_archive_path(args: &[String]) -> Result<PathBuf, String> { + parse_file_path(args, "archive inspect") +} + +fn parse_file_path(args: &[String], command: &str) -> Result<PathBuf, String> { match args { [path] => Ok(PathBuf::from(path)), [flag, path] if flag == "--file" => Ok(PathBuf::from(path)), - _ => Err("archive inspect requires <file> or --file <file>".to_string()), + _ => Err(format!("{command} requires <file> or --file <file>")), } } @@ -472,7 +505,7 @@ fn prototype_graph_requiredness_label( } fn usage() -> String { - "usage: fparkan corpus discover|validate --root <path> [--format json] | archive inspect <file> [--format json] | prototype inspect --root <path> --key <key> [--format json] | mission graph|inspect --root <path> --mission <path> [--format json]".to_string() + "usage: fparkan corpus discover|validate --root <path> [--format json] | archive inspect <file> [--format json] | terrain inspect <Land.msh> [--format json] | prototype inspect --root <path> --key <key> [--format json] | mission graph|inspect --root <path> --mission <path> [--format json]".to_string() } #[cfg(test)] @@ -584,4 +617,21 @@ mod tests { "{\"schema_version\":\"fparkan-mission-inspect-v1\",\"mission\":\"MISSIONS/test/data.tma\",\"objects\":[{\"index\":1,\"resource\":\"unit.dat\",\"position\":[1.0,2.0,3.0],\"orientation_raw\":[4.0,5.0,6.0],\"scale\":[7.0,8.0,9.0]}]}" ); } + + #[test] + fn terrain_inspect_output_retains_axis_bounds() { + let json = serialize_json(&TerrainInspectOutput { + schema_version: TERRAIN_INSPECT_SCHEMA, + path: "DATA/MAPS/AutoMAP/Land.msh".to_string(), + positions: 3, + min: [-1.0, -2.0, -3.0], + max: [4.0, 5.0, 6.0], + }) + .expect("serialize terrain inspection"); + + assert_eq!( + json, + "{\"schema_version\":\"fparkan-terrain-inspect-v1\",\"path\":\"DATA/MAPS/AutoMAP/Land.msh\",\"positions\":3,\"min\":[-1.0,-2.0,-3.0],\"max\":[4.0,5.0,6.0]}" + ); + } } diff --git a/apps/fparkan-game/src/main.rs b/apps/fparkan-game/src/main.rs index b5106ea..86891d7 100644 --- a/apps/fparkan-game/src/main.rs +++ b/apps/fparkan-game/src/main.rs @@ -30,10 +30,10 @@ use fparkan_render::{ RenderSnapshotDraw, }; use fparkan_render_vulkan::{ - project_land_msh_to_static_mesh_in_xz_frame, project_msh_to_static_mesh_in_xz_frame, + project_land_msh_to_static_mesh_in_xy_frame, project_msh_to_static_mesh_in_xy_frame, VulkanPlanningBackend, VulkanSmokeFrameOutcome, VulkanSmokeRenderer, VulkanSmokeRendererCreateInfo, VulkanStaticMaterial, VulkanStaticMesh, VulkanStaticTexture, - VulkanStaticXzFrame, + VulkanStaticXyFrame, }; use fparkan_runtime::{ create, frame, load_mission, load_mission_static_preview, load_mission_static_preview_roots, @@ -206,7 +206,7 @@ struct StaticPreviewScene { } /// Projects the mission terrain plus every MSH component of the explicitly -/// bounded static-preview root into one diagnostic XZ frame. +/// bounded static-preview root into one diagnostic XY frame. /// /// This intentionally takes only the first MAT0 texture request for each MSH /// batch selector. The terrain uses an explicit white diagnostic texture; @@ -220,7 +220,7 @@ fn static_preview_mesh_and_materials( let terrain_mesh = terrain .source_mesh() .ok_or_else(|| "runtime terrain does not retain its validated source mesh".to_string())?; - let frame = static_preview_xz_frame(assets, terrain, roots)?; + let frame = static_preview_xy_frame(assets, terrain, roots)?; let mut mesh = VulkanStaticMesh { vertices: Vec::new(), indices: Vec::new(), @@ -234,7 +234,7 @@ fn static_preview_mesh_and_materials( rgba8: vec![255, 255, 255, 255], }, }]; - let terrain_component = project_land_msh_to_static_mesh_in_xz_frame(terrain_mesh, frame) + let terrain_component = project_land_msh_to_static_mesh_in_xy_frame(terrain_mesh, frame) .map_err(|err| format!("project mission terrain for Vulkan: {err}"))?; append_static_preview_component(&mut mesh, terrain_component, &[(0, 0)])?; let mut mesh_components = 0; @@ -251,7 +251,7 @@ fn static_preview_mesh_and_materials( let model = assets.model_by_id(model_id).ok_or_else(|| { format!("static preview visual {visual_id:?} references unknown model {model_id:?}") })?; - let component = project_msh_to_static_mesh_in_xz_frame( + let component = project_msh_to_static_mesh_in_xy_frame( &model.validated, frame, root.position, @@ -275,20 +275,20 @@ fn static_preview_mesh_and_materials( }) } -fn static_preview_xz_frame( +fn static_preview_xy_frame( assets: &MissionAssets, terrain: &TerrainWorld, roots: &[MissionObjectDraft], -) -> Result<VulkanStaticXzFrame, String> { +) -> Result<VulkanStaticXyFrame, String> { let mut min_x = f32::INFINITY; let mut max_x = f32::NEG_INFINITY; - let mut min_z = f32::INFINITY; - let mut max_z = f32::NEG_INFINITY; + let mut min_y = f32::INFINITY; + let mut max_y = f32::NEG_INFINITY; let terrain_positions = terrain .source_positions() .ok_or_else(|| "runtime terrain does not retain source positions".to_string())?; for position in terrain_positions { - extend_static_preview_xz_bounds(*position, &mut min_x, &mut max_x, &mut min_z, &mut max_z)?; + extend_static_preview_xy_bounds(*position, &mut min_x, &mut max_x, &mut min_y, &mut max_y)?; } for (object_index, root) in roots.iter().enumerate() { if !root @@ -314,7 +314,7 @@ fn static_preview_xz_frame( format!("static preview visual {visual_id:?} references unknown model {model_id:?}") })?; for position in &model.validated.positions { - extend_static_preview_xz_bounds( + extend_static_preview_xy_bounds( [ position[0] * root.scale[0] + root.position[0], position[1] * root.scale[1] + root.position[1], @@ -322,30 +322,30 @@ fn static_preview_xz_frame( ], &mut min_x, &mut max_x, - &mut min_z, - &mut max_z, + &mut min_y, + &mut max_y, )?; } } } - VulkanStaticXzFrame::from_bounds(min_x, max_x, min_z, max_z) - .map_err(|err| format!("build static preview XZ frame: {err}")) + VulkanStaticXyFrame::from_bounds(min_x, max_x, min_y, max_y) + .map_err(|err| format!("build static preview XY frame: {err}")) } -fn extend_static_preview_xz_bounds( +fn extend_static_preview_xy_bounds( position: [f32; 3], min_x: &mut f32, max_x: &mut f32, - min_z: &mut f32, - max_z: &mut f32, + min_y: &mut f32, + max_y: &mut f32, ) -> Result<(), String> { if !position.iter().all(|value| value.is_finite()) { - return Err("static preview contains a non-finite XZ position".to_string()); + return Err("static preview contains a non-finite XY position".to_string()); } *min_x = min_x.min(position[0]); *max_x = max_x.max(position[0]); - *min_z = min_z.min(position[2]); - *max_z = max_z.max(position[2]); + *min_y = min_y.min(position[1]); + *max_y = max_y.max(position[1]); Ok(()) } |
