134 lines
4.5 KiB
Rust
134 lines
4.5 KiB
Rust
//! Bit-exact gate vs official C++ xatlas (`oracle/gold/*.txt`).
|
|
|
|
use makepad_xatlas::parametrize;
|
|
use std::fs;
|
|
use std::path::PathBuf;
|
|
|
|
fn f32_from_bits(hex: &str) -> f32 {
|
|
f32::from_bits(u32::from_str_radix(hex, 16).expect(hex))
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct Gold {
|
|
width: u32,
|
|
height: u32,
|
|
atlas_count: u32,
|
|
chart_count: u32,
|
|
texels_per_unit: f32,
|
|
vertices: Vec<(u32, i32, i32, f32, f32)>,
|
|
faces: Vec<[u32; 3]>,
|
|
}
|
|
|
|
fn load_gold(name: &str) -> Gold {
|
|
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.join("oracle/gold")
|
|
.join(format!("{name}.txt"));
|
|
let text = fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {}: {e}", path.display()));
|
|
let mut gold = Gold {
|
|
width: 0,
|
|
height: 0,
|
|
atlas_count: 0,
|
|
chart_count: 0,
|
|
texels_per_unit: 0.0,
|
|
vertices: Vec::new(),
|
|
faces: Vec::new(),
|
|
};
|
|
for line in text.lines() {
|
|
let mut it = line.split_whitespace();
|
|
let Some(tag) = it.next() else { continue };
|
|
match tag {
|
|
"width" => gold.width = it.next().unwrap().parse().unwrap(),
|
|
"height" => gold.height = it.next().unwrap().parse().unwrap(),
|
|
"atlasCount" => gold.atlas_count = it.next().unwrap().parse().unwrap(),
|
|
"chartCount" => gold.chart_count = it.next().unwrap().parse().unwrap(),
|
|
"texelsPerUnit" => gold.texels_per_unit = f32_from_bits(it.next().unwrap()),
|
|
"v" => gold.vertices.push((
|
|
it.next().unwrap().parse().unwrap(),
|
|
it.next().unwrap().parse().unwrap(),
|
|
it.next().unwrap().parse().unwrap(),
|
|
f32_from_bits(it.next().unwrap()),
|
|
f32_from_bits(it.next().unwrap()),
|
|
)),
|
|
"f" => gold.faces.push([
|
|
it.next().unwrap().parse().unwrap(),
|
|
it.next().unwrap().parse().unwrap(),
|
|
it.next().unwrap().parse().unwrap(),
|
|
]),
|
|
_ => {}
|
|
}
|
|
}
|
|
gold
|
|
}
|
|
|
|
fn load_mesh(name: &str) -> (Vec<[f32; 3]>, Vec<[u32; 3]>) {
|
|
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.join("oracle/meshes")
|
|
.join(format!("{name}.txt"));
|
|
let text = fs::read_to_string(&path).unwrap();
|
|
let mut toks = text.split_whitespace();
|
|
assert_eq!(toks.next(), Some("v"));
|
|
let nv: usize = toks.next().unwrap().parse().unwrap();
|
|
let mut positions = Vec::with_capacity(nv);
|
|
for _ in 0..nv {
|
|
positions.push([
|
|
toks.next().unwrap().parse().unwrap(),
|
|
toks.next().unwrap().parse().unwrap(),
|
|
toks.next().unwrap().parse().unwrap(),
|
|
]);
|
|
}
|
|
assert_eq!(toks.next(), Some("f"));
|
|
let nf: usize = toks.next().unwrap().parse().unwrap();
|
|
let mut faces = Vec::with_capacity(nf);
|
|
for _ in 0..nf {
|
|
faces.push([
|
|
toks.next().unwrap().parse().unwrap(),
|
|
toks.next().unwrap().parse().unwrap(),
|
|
toks.next().unwrap().parse().unwrap(),
|
|
]);
|
|
}
|
|
(positions, faces)
|
|
}
|
|
|
|
fn assert_exact(name: &str) {
|
|
let (positions, faces) = load_mesh(name);
|
|
let gold = load_gold(name);
|
|
let out = parametrize(&positions, &faces).unwrap_or_else(|e| panic!("{name}: {e}"));
|
|
assert_eq!(out.width, gold.width, "{name} width");
|
|
assert_eq!(out.height, gold.height, "{name} height");
|
|
assert_eq!(out.atlas_count, gold.atlas_count, "{name} atlasCount");
|
|
assert_eq!(out.chart_count, gold.chart_count, "{name} chartCount");
|
|
assert_eq!(
|
|
out.texels_per_unit.to_bits(),
|
|
gold.texels_per_unit.to_bits(),
|
|
"{name} texelsPerUnit"
|
|
);
|
|
assert_eq!(out.vertices.len(), gold.vertices.len(), "{name} vertexCount");
|
|
for (i, (got, exp)) in out.vertices.iter().zip(gold.vertices.iter()).enumerate() {
|
|
assert_eq!(got.xref, exp.0, "{name} v{i} xref");
|
|
assert_eq!(got.atlas_index, exp.1, "{name} v{i} atlasIndex");
|
|
assert_eq!(got.chart_index, exp.2, "{name} v{i} chartIndex");
|
|
assert_eq!(got.uv[0].to_bits(), exp.3.to_bits(), "{name} v{i} uv.x");
|
|
assert_eq!(got.uv[1].to_bits(), exp.4.to_bits(), "{name} v{i} uv.y");
|
|
}
|
|
assert_eq!(out.indices, gold.faces, "{name} indices");
|
|
}
|
|
|
|
#[test]
|
|
fn unit_quad_matches_official_xatlas() {
|
|
assert_exact("unit_quad");
|
|
}
|
|
|
|
#[test]
|
|
fn unit_cube_matches_official_xatlas() {
|
|
assert_exact("unit_cube");
|
|
}
|
|
|
|
#[test]
|
|
fn tetra_matches_official_xatlas() {
|
|
assert_exact("tetra");
|
|
}
|
|
|
|
#[test]
|
|
fn irregular_matches_official_xatlas() {
|
|
assert_exact("irregular");
|
|
}
|