feat(terrain): inspect packed material tags
This commit is contained in:
@@ -26,8 +26,8 @@ use fparkan_assets::{
|
|||||||
};
|
};
|
||||||
use fparkan_corpus::{discover, render_report_json, report, DiscoverOptions};
|
use fparkan_corpus::{discover, render_report_json, report, DiscoverOptions};
|
||||||
use fparkan_inspection::{
|
use fparkan_inspection::{
|
||||||
inspect_archive_file, inspect_land_msh_bounds_file, inspect_model_from_root, ArchiveInspection,
|
inspect_archive_file, inspect_land_msh_bounds_file, inspect_model_from_root,
|
||||||
ModelInspection,
|
load_land_msh_from_path, ArchiveInspection, ModelInspection,
|
||||||
};
|
};
|
||||||
use fparkan_path::{normalize_relative, PathPolicy};
|
use fparkan_path::{normalize_relative, PathPolicy};
|
||||||
use fparkan_prototype::build_prototype_graph_report;
|
use fparkan_prototype::build_prototype_graph_report;
|
||||||
@@ -125,6 +125,15 @@ struct TerrainInspectOutput {
|
|||||||
positions: usize,
|
positions: usize,
|
||||||
min: [f32; 3],
|
min: [f32; 3],
|
||||||
max: [f32; 3],
|
max: [f32; 3],
|
||||||
|
faces: usize,
|
||||||
|
slots: usize,
|
||||||
|
material_tags: Vec<TerrainMaterialTagCount>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct TerrainMaterialTagCount {
|
||||||
|
tag: u16,
|
||||||
|
faces: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@@ -452,6 +461,18 @@ fn inspect_archive(args: &[String]) -> Result<(), String> {
|
|||||||
fn inspect_terrain(args: &[String]) -> Result<(), String> {
|
fn inspect_terrain(args: &[String]) -> Result<(), String> {
|
||||||
let path = parse_file_path(args, "terrain inspect")?;
|
let path = parse_file_path(args, "terrain inspect")?;
|
||||||
let bounds = inspect_land_msh_bounds_file(&path)?;
|
let bounds = inspect_land_msh_bounds_file(&path)?;
|
||||||
|
let terrain = load_land_msh_from_path(&path)?;
|
||||||
|
let mut material_tags = terrain
|
||||||
|
.faces
|
||||||
|
.iter()
|
||||||
|
.fold(std::collections::BTreeMap::new(), |mut counts, face| {
|
||||||
|
*counts.entry(face.material_tag).or_insert(0usize) += 1;
|
||||||
|
counts
|
||||||
|
})
|
||||||
|
.into_iter()
|
||||||
|
.map(|(tag, faces)| TerrainMaterialTagCount { tag, faces })
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
material_tags.sort_unstable_by_key(|entry| entry.tag);
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
serialize_json(&TerrainInspectOutput {
|
serialize_json(&TerrainInspectOutput {
|
||||||
@@ -460,6 +481,9 @@ fn inspect_terrain(args: &[String]) -> Result<(), String> {
|
|||||||
positions: bounds.positions,
|
positions: bounds.positions,
|
||||||
min: bounds.min,
|
min: bounds.min,
|
||||||
max: bounds.max,
|
max: bounds.max,
|
||||||
|
faces: terrain.faces.len(),
|
||||||
|
slots: terrain.slots.slots_raw.len(),
|
||||||
|
material_tags,
|
||||||
})?
|
})?
|
||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -703,12 +727,18 @@ mod tests {
|
|||||||
positions: 3,
|
positions: 3,
|
||||||
min: [-1.0, -2.0, -3.0],
|
min: [-1.0, -2.0, -3.0],
|
||||||
max: [4.0, 5.0, 6.0],
|
max: [4.0, 5.0, 6.0],
|
||||||
|
faces: 2,
|
||||||
|
slots: 4,
|
||||||
|
material_tags: vec![
|
||||||
|
TerrainMaterialTagCount { tag: 0, faces: 1 },
|
||||||
|
TerrainMaterialTagCount { tag: 3, faces: 1 },
|
||||||
|
],
|
||||||
})
|
})
|
||||||
.expect("serialize terrain inspection");
|
.expect("serialize terrain inspection");
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
json,
|
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]}"
|
"{\"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],\"faces\":2,\"slots\":4,\"material_tags\":[{\"tag\":0,\"faces\":1},{\"tag\":3,\"faces\":1}]}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1538,6 +1538,23 @@ temporary vertex buffers или заменять render representation. UI/shell
|
|||||||
диагностики полезно уметь сохранять world-only command list и финальный
|
диагностики полезно уметь сохранять world-only command list и финальный
|
||||||
framebuffer отдельно.
|
framebuffer отдельно.
|
||||||
|
|
||||||
|
Terrain material discovery is now reproducible instead of inferred from the
|
||||||
|
mesh shape. The original AutoDemo map places two textual sidecar WEAR tables,
|
||||||
|
`Land1.wea` and `Land2.wea`, beside `Land.msh`; `Terrain.dll` contains the
|
||||||
|
corresponding `1.wea` and `2.wea` loading suffixes. The new terrain inspector
|
||||||
|
reports all packed face tags. For `DATA/MAPS/AutoMAP/Land.msh`, its 3,174 faces
|
||||||
|
use `0x0102` (592), `0x0203` (386), `0xff01` (918), `0xff02` (970), and
|
||||||
|
`0xff03` (308). The low byte is always a valid positional selector 1..3 in
|
||||||
|
`Land2.wea`; the high byte is a `Land1.wea` selector or sentinel `0xff`.
|
||||||
|
This is evidence for a two-layer terrain-material contract, but not yet for
|
||||||
|
its blend equation, so the Vulkan bridge intentionally remains texture-agnostic
|
||||||
|
until the base/overlay composition is recovered.
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
cargo run -q -p fparkan-cli -- terrain inspect `
|
||||||
|
'C:\GOG Games\Parkan - Iron Strategy\DATA\MAPS\AutoMAP\Land.msh' --format json
|
||||||
|
```
|
||||||
|
|
||||||
## Проверки паритета
|
## Проверки паритета
|
||||||
|
|
||||||
Главные риски совпадения кадра:
|
Главные риски совпадения кадра:
|
||||||
|
|||||||
Reference in New Issue
Block a user