//! Does a resource's DESCRIPTOR carry its bounding box? //! //! The last cross-container disagreements are 24-vertex bound boxes swapping //! identities; no anchoring rule can pin them (see docs). If the descriptor //! states the box, that is the missing information. This decodes the resource, //! takes the box its geometry actually spans, and searches the descriptor for //! those float values. //! //! Usage: bounds_in_descriptor ... use sylpheed_formats::mesh::{xbg7_descriptor_range, Xbg7Model}; use std::collections::HashSet; fn main() { let a: Vec = std::env::args().collect(); let bytes = std::fs::read(&a[1]).expect("container"); let want: HashSet = a[2..].iter().cloned().collect(); for m in Xbg7Model::models_named(&bytes, &want, &|| false) { let (mut lo, mut hi) = ([f32::MAX; 3], [f32::MIN; 3]); for s in &m.meshes { for q in &s.positions { for k in 0..3 { lo[k] = lo[k].min(q[k]); hi[k] = hi[k].max(q[k]); } } } let Some((d0, d1)) = xbg7_descriptor_range(&bytes, &m.name) else { continue }; println!( "{} descriptor 0x{d0:x}..0x{d1:x} ({} bytes), box lo{:?} hi{:?}", m.name, d1 - d0, lo.map(|v| v.round()), hi.map(|v| v.round()) ); // Where in the descriptor does each bound value appear (±0.01)? let targets: Vec<(&str, f32)> = vec![ ("lo.x", lo[0]), ("lo.y", lo[1]), ("lo.z", lo[2]), ("hi.x", hi[0]), ("hi.y", hi[1]), ("hi.z", hi[2]), ]; for (label, v) in targets { let mut at: Vec = Vec::new(); let mut o = d0; while o + 4 <= d1 { let f = f32::from_be_bytes(bytes[o..o + 4].try_into().unwrap()); if (f - v).abs() <= 0.01 * (1.0 + v.abs()) { at.push(o - d0); } o += 4; } println!(" {label:5} {v:10.3} at descriptor offsets {:x?}", &at[..at.len().min(6)]); } } }