diff --git a/crates/engine/tests/world_real.rs b/crates/engine/tests/world_real.rs index 671b7ea..d3f48b5 100644 --- a/crates/engine/tests/world_real.rs +++ b/crates/engine/tests/world_real.rs @@ -537,6 +537,80 @@ fn real_weapon_model_structure() { } } +/// Заголовки VVD моделей оружия: версия, смещения, размеры. +#[test] +fn real_weapon_vvd_headers() { + let Some(root) = assets_root() else { + eprintln!("пропуск: ассеты не найдены"); + return; + }; + let vfs = mount_game(&root); + for name in [ + "models/weapons/v_pistol", + "models/weapons/w_pistol", + "models/props_c17/oildrum001", + ] { + let Ok(data) = vfs.read(&format!("{name}.vvd")) else { + continue; + }; + let vvd = formats::vvd::Vvd::parse(&data).expect("разбор vvd"); + let h = &vvd.header; + eprintln!( + "{name}.vvd: байт {}, версия {}, лодов {}, вершин по LOD {:?}, фиксов {}, \ + vertex_data_start {}, tangent_data_start {}", + data.len(), + h.version, + h.num_lods, + &h.num_lod_vertexes[..h.num_lods.clamp(0, 8) as usize], + h.num_fixups, + h.vertex_data_start, + h.tangent_data_start + ); + let verts = vvd.vertices(0).expect("вершины"); + let mut min = [f32::MAX; 3]; + let mut max = [f32::MIN; 3]; + for v in &verts { + for j in 0..3 { + min[j] = min[j].min(v.position[j]); + max[j] = max[j].max(v.position[j]); + } + } + eprintln!(" габарит вершин: min {min:?}, max {max:?}"); + } +} + +/// Габарит модели из заголовка MDL: должен совпадать с вершинами VVD. +#[test] +fn real_weapon_mdl_hull() { + let Some(root) = assets_root() else { + eprintln!("пропуск: ассеты не найдены"); + return; + }; + let vfs = mount_game(&root); + for name in ["models/weapons/v_pistol", "models/weapons/w_pistol"] { + let Ok(data) = vfs.read(&format!("{name}.mdl")) else { + continue; + }; + // studiohdr_t: hull_min — 104, hull_max — 116. + let f = |o: usize| f32::from_le_bytes([data[o], data[o + 1], data[o + 2], data[o + 3]]); + eprintln!( + "{name}: hull_min [{:.1} {:.1} {:.1}], hull_max [{:.1} {:.1} {:.1}], view_bb [{:.1} {:.1} {:.1}]..[{:.1} {:.1} {:.1}]", + f(104), + f(108), + f(112), + f(116), + f(120), + f(124), + f(128), + f(132), + f(136), + f(140), + f(144), + f(148) + ); + } +} + /// Позиции вершин экземпляра модели. fn instance_positions(world: &engine::World, index: usize) -> Vec<[f32; 3]> { let instance = &world.model_instances[index];