use std::process::exit;
use tmx::{glb, tmxb};
fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() != 3 {
eprintln!("usage: {} <input.3mxb> <output.glb>", args[0]);
exit(2);
}
let input = &args[1];
let output = &args[2];
let data = std::fs::read(input).unwrap_or_else(|e| {
eprintln!("read {input}: {e}");
exit(1);
});
let parsed = tmxb::parse(&data).unwrap_or_else(|e| {
eprintln!("parse: {e}");
exit(1);
});
println!(
"3mxb: {} textures, {} geometries",
parsed.textures.len(),
parsed.geometries.len()
);
let mut prims = Vec::new();
let mut total_v = 0usize;
let mut total_t = 0usize;
for g in &parsed.geometries {
let mesh = match openctm::decode(&g.ctm) {
Ok(m) => m,
Err(e) => {
eprintln!(" CTM decode {} failed: {e}", g.id);
continue;
}
};
total_v += mesh.positions.len();
total_t += mesh.indices.len() / 3;
let jpeg = g
.texture_id
.as_ref()
.and_then(|tid| parsed.textures.get(tid))
.cloned();
println!(
" {}: {} verts, {} tris, normals={}, uvs={}, tex={}",
g.id,
mesh.positions.len(),
mesh.indices.len() / 3,
mesh.normals.is_some(),
mesh.uvs.is_some(),
jpeg.is_some(),
);
let uvs = mesh
.uvs
.map(|uvs| uvs.iter().map(|t| [t[0], 1.0 - t[1]]).collect());
prims.push(glb::Prim {
positions: mesh.positions,
normals: mesh.normals,
uvs,
indices: mesh.indices,
jpeg,
});
}
if prims.is_empty() {
eprintln!("no geometry decoded");
exit(1);
}
let glb = glb::write(&prims);
std::fs::write(output, &glb).unwrap_or_else(|e| {
eprintln!("write {output}: {e}");
exit(1);
});
println!(
"wrote {output}: {} primitives, {total_v} verts, {total_t} tris, {} bytes",
prims.len(),
glb.len()
);
}