re: calibrate the connectivity cap -- +612 resources against 18 consistency regressions
XBG7_EDGE_CAP / XBG7_SMALL_TRIS make the threshold sweepable (defaults unchanged, full suite green). Above 0.417 the capture-proven eng_02_l anchors exactly right and no e106 part regresses, and nothing that decoded at 0.28 is lost -- but ~250 existing anchors move silently and 18 shared resources lose cross-container consistency. Not changed: the movers have no oracle yet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
80
crates/sylpheed-formats/examples/edge_cap_sweep.rs
Normal file
80
crates/sylpheed-formats/examples/edge_cap_sweep.rs
Normal file
@@ -0,0 +1,80 @@
|
||||
//! Calibrate the connectivity cap against the whole disc.
|
||||
//!
|
||||
//! `XBG7_EDGE_CAP` sets the cap; this reports, for one setting, how much
|
||||
//! geometry decodes and how self-consistent it is across containers — the two
|
||||
//! numbers any change to the cap has to trade off. Run it once per cap value.
|
||||
use sylpheed_formats::mesh::Xbg7Model;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
fn main() {
|
||||
let dir = std::env::args().nth(1).expect("resource3d dir");
|
||||
let mut files: Vec<_> = std::fs::read_dir(&dir)
|
||||
.unwrap()
|
||||
.flatten()
|
||||
.map(|e| e.path())
|
||||
.filter(|p| p.extension().and_then(|s| s.to_str()) == Some("xpr"))
|
||||
.collect();
|
||||
files.sort();
|
||||
|
||||
// name -> (verts, tris) -> spans seen, exactly as mesh_consistency_disc.rs.
|
||||
let mut seen: BTreeMap<String, Vec<([i64; 3], usize, usize)>> = BTreeMap::new();
|
||||
let (mut models, mut verts) = (0usize, 0usize);
|
||||
for f in &files {
|
||||
let Ok(bytes) = std::fs::read(f) else { continue };
|
||||
for m in Xbg7Model::anchor_models_cancellable(&bytes, 0.0, &|| 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if lo[0] == f32::MAX {
|
||||
continue;
|
||||
}
|
||||
let v: usize = m.meshes.iter().map(|s| s.positions.len()).sum();
|
||||
let t: usize = m.meshes.iter().map(|s| s.indices.len() / 3).sum();
|
||||
models += 1;
|
||||
verts += v;
|
||||
if std::env::var("DUMP").is_ok() {
|
||||
// Per-resource signature, so two cap settings can be diffed:
|
||||
// a cap change that silently MOVES an existing anchor is the
|
||||
// risk a coverage count cannot see.
|
||||
println!(
|
||||
"{}|{}|{v}|{t}|{}|{}|{}|{}",
|
||||
f.file_name().unwrap().to_string_lossy(),
|
||||
m.name,
|
||||
m.meshes[0].vbuf_offset.unwrap_or(0),
|
||||
(hi[0] - lo[0]).round() as i64,
|
||||
(hi[1] - lo[1]).round() as i64,
|
||||
(hi[2] - lo[2]).round() as i64
|
||||
);
|
||||
}
|
||||
seen.entry(m.name.clone()).or_default().push((
|
||||
[
|
||||
(hi[0] - lo[0]).round() as i64,
|
||||
(hi[1] - lo[1]).round() as i64,
|
||||
(hi[2] - lo[2]).round() as i64,
|
||||
],
|
||||
v,
|
||||
t,
|
||||
));
|
||||
}
|
||||
}
|
||||
let (mut shared, mut inconsistent) = (0usize, 0usize);
|
||||
for (_, list) in &seen {
|
||||
if list.len() < 2 || !list.iter().all(|e| e.1 == list[0].1 && e.2 == list[0].2) {
|
||||
continue;
|
||||
}
|
||||
shared += 1;
|
||||
if list.iter().any(|e| e.0 != list[0].0) {
|
||||
inconsistent += 1;
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"cap={} models={models} verts={verts} shared={shared} inconsistent={inconsistent}",
|
||||
std::env::var("XBG7_EDGE_CAP").unwrap_or_else(|_| "0.28 (default)".into())
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user