use mercs2_engine::{game_world, model::Model, wad};
fn main() {
let args: Vec<String> = std::env::args().collect();
let mhash = args
.get(1)
.and_then(|a| a.strip_prefix("0x"))
.and_then(|h| u32::from_str_radix(h, 16).ok())
.unwrap_or(0xA3C1_FABC); let mut w = wad::registry_vz_wad().and_then(|p| wad::open(&p).ok()).expect("open vz.wad");
let m = Model::load(&mut w, mhash).expect("load model");
let (verts, _indices, draws, stats) = m.flatten();
println!("model 0x{mhash:08X}: {} rung(s), {} draws, {} verts, {} bones in rig",
m.rungs.len(), draws.len(), verts.len(), stats.rig.len());
let skinned = verts.iter().filter(|v| v.weights.iter().any(|&x| x > 0)).count();
let max_joint = verts.iter().flat_map(|v| v.joints).max().unwrap_or(0);
println!("\n-- skinning --");
println!("verts with a nonzero BLENDWEIGHT: {skinned}/{} ({:.1}%) max joint index: {max_joint}",
verts.len(), 100.0 * skinned as f32 / verts.len().max(1) as f32);
let sk_groups = draws.iter().filter(|d| d.skinned).count();
let sk_tris: u32 = draws.iter().filter(|d| d.skinned).map(|d| d.index_count / 3).sum();
let all_tris: u32 = draws.iter().map(|d| d.index_count / 3).sum();
println!(
"DEFORMING draw groups: {sk_groups}/{} ({sk_tris}/{all_tris} tris = {:.1}%) -> exporter picks the {} path",
draws.len(),
100.0 * sk_tris as f32 / all_tris.max(1) as f32,
if sk_groups > 0 { "SKIN" } else { "rigid node-parented" }
);
let mut by_node: std::collections::BTreeMap<i16, (usize, usize)> = std::collections::BTreeMap::new();
for d in &draws {
let e = by_node.entry(d.node).or_insert((0, 0));
e.0 += 1;
e.1 += (d.index_count / 3) as usize;
}
println!("draw groups by SEGM node (node -1 = no mount):");
for (node, (n, tris)) in by_node.iter().take(12) {
println!(" node {node:>4}: {n:>3} groups, {tris:>6} tris");
}
if by_node.len() > 12 {
println!(" ... {} more nodes", by_node.len() - 12);
}
println!("\n-- clips (game_world::load_clips_for_model, rig-matched) --");
let clips = game_world::load_clips_for_model(&mut w, &stats.rig);
println!("{} clip(s) resolve against this rig", clips.len());
let (mut decoded, mut neutral) = (0u32, 0u32);
for c in &clips {
if c.clip.decoded { decoded += 1 } else { neutral += 1 }
}
println!("decoded: {decoded} NOT decoded (would export as neutral pose): {neutral}");
for c in clips.iter().take(8) {
let bound = c.track_to_hier.iter().take(c.num_transform_tracks).filter(|x| x.is_some()).count();
println!(
" 0x{:08X} {:>6.2}s {:>4} frames {:>3} tracks ({bound} bound to HIER) decoded={}",
c.name_hash, c.clip.duration, c.clip.num_frames, c.num_transform_tracks, c.clip.decoded
);
}
if clips.len() > 8 {
println!(" ... {} more", clips.len() - 8);
}
}