use std::io;
use std::path::PathBuf;
use draco_gltf::{CompressionOptions, Import, MeshIndex, OutputFormat};
fn decoded_draco_stats(import: &Import) -> Result<(usize, usize), Box<dyn std::error::Error>> {
let mut primitives = 0usize;
let mut faces = 0usize;
for primitive in import.draco_primitives() {
let mesh = import.decode_draco_primitive(primitive)?;
if mesh.num_faces() == 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Draco primitive decoded to zero faces",
)
.into());
}
primitives = primitives.checked_add(1).ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
"decoded primitive count overflow",
)
})?;
faces = faces.checked_add(mesh.num_faces()).ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidData, "decoded face count overflow")
})?;
}
if primitives == 0 || faces == 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"document contains no decodable Draco triangle faces",
)
.into());
}
Ok((primitives, faces))
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut args = std::env::args_os().skip(1);
let input = PathBuf::from(args.next().ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidInput,
"usage: gltf_tool <input.gltf|input.glb> [output.glb]",
)
})?);
let output = args.next().map(PathBuf::from);
if args.next().is_some() {
return Err(io::Error::new(io::ErrorKind::InvalidInput, "too many arguments").into());
}
let mut import = draco_gltf::import(&input)?;
if let Some(output) = output {
let report = import.compress_primitive(MeshIndex(0), 0, CompressionOptions::default())?;
let bytes = import.to_bytes(OutputFormat::GlbV2)?;
std::fs::write(output, bytes)?;
println!("compression_report={report:?}");
} else {
let (primitives, faces) = decoded_draco_stats(&import)?;
println!("decoded_draco_primitives={primitives} decoded_faces={faces}");
}
Ok(())
}