Files
benilla-octo/crates/benilla-formats/tests/blob_shadow_box.rs
T
SamandClaude Fable 5 2ad0043523 benilla: initial public release
A from-scratch World of Warcraft 1.12.1 client in Rust + Bevy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 14:27:01 +07:00

60 lines
2.6 KiB
Rust

//! Pins the unit blob shadow's box source against real build-5875 assets: the shadow sizes from
//! the **current animation's** `M2Sequence` CAaBox (wow-re `unit-blob-shadow.md`, `0x711a20` — the
//! same sequence-record box the pick volume and the ring's Stand-footprint read), so
//! `ModelAnimation::bounds_min/max` must round-trip the raw record. The Stand-box horizontal
//! extents of the four reference-traced creatures are already pinned by
//! `selection_ring_radius.rs` *through* the nested-sqrt footprint; this asserts the **box itself**
//! (the shadow consumes it raw: clamp ±5, scale, AA-bound — no compression). Skips when the
//! gitignored client data isn't present.
use benilla_formats::{open_chain, parse_m2_animations};
#[test]
fn stand_box_extents_match_reference() {
let data = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../WoW/Data");
if !data.is_dir() {
eprintln!("skipping: vanilla client not present at {}", data.display());
return;
}
let mut chain = open_chain(&data).expect("open chain");
// (model, Stand-box horizontal extents (dx, dy) — the wow-re selection-ring RE's measured
// table, read straight off the real sequence records).
let cases = [
("Creature\\Chicken\\Chicken.m2", 0.532_f32, 0.382_f32),
("Character\\Human\\Male\\HumanMale.m2", 0.913, 1.080),
];
for (path, dx, dy) in cases {
let bytes = chain.read_file(path).expect(path);
let anims = parse_m2_animations(&bytes);
// Stand (anim id 0)'s head variation — the box the idle shadow projects.
let stand = anims
.iter()
.find(|a| a.anim_id == 0)
.unwrap_or_else(|| panic!("{path}: no Stand sequence"));
let (bmin, bmax) = (stand.bounds_min, stand.bounds_max);
assert!(
(bmax[0] - bmin[0] - dx).abs() < 0.01,
"{path}: Stand box dx {:.3} != reference {dx}",
bmax[0] - bmin[0]
);
assert!(
(bmax[1] - bmin[1] - dy).abs() < 0.01,
"{path}: Stand box dy {:.3} != reference {dy}",
bmax[1] - bmin[1]
);
// The box is a real volume: a degenerate Z extent would zero the shadow's vertical reach.
assert!(
bmax[2] > bmin[2],
"{path}: Stand box has no vertical extent"
);
// And the centre derives from the same corners (the sphere fields already shipped).
for i in 0..3 {
assert!(
((bmin[i] + bmax[i]) * 0.5 - stand.bounds_center[i]).abs() < 1e-4,
"{path}: bounds_center[{i}] must be the box midpoint"
);
}
}
}