1use std::io;
4use std::path::PathBuf;
5
6use draco_gltf::{CompressionOptions, Import, MeshIndex, OutputFormat};
7
8fn decoded_draco_stats(import: &Import) -> Result<(usize, usize), Box<dyn std::error::Error>> {
9 let mut primitives = 0usize;
10 let mut faces = 0usize;
11 for primitive in import.draco_primitives() {
12 let mesh = import.decode_draco_primitive(primitive)?;
13 if mesh.num_faces() == 0 {
14 return Err(io::Error::new(
15 io::ErrorKind::InvalidData,
16 "Draco primitive decoded to zero faces",
17 )
18 .into());
19 }
20 primitives = primitives.checked_add(1).ok_or_else(|| {
21 io::Error::new(
22 io::ErrorKind::InvalidData,
23 "decoded primitive count overflow",
24 )
25 })?;
26 faces = faces.checked_add(mesh.num_faces()).ok_or_else(|| {
27 io::Error::new(io::ErrorKind::InvalidData, "decoded face count overflow")
28 })?;
29 }
30 if primitives == 0 || faces == 0 {
31 return Err(io::Error::new(
32 io::ErrorKind::InvalidData,
33 "document contains no decodable Draco triangle faces",
34 )
35 .into());
36 }
37 Ok((primitives, faces))
38}
39
40fn main() -> Result<(), Box<dyn std::error::Error>> {
41 let mut args = std::env::args_os().skip(1);
42 let input = PathBuf::from(args.next().ok_or_else(|| {
43 io::Error::new(
44 io::ErrorKind::InvalidInput,
45 "usage: gltf_tool <input.gltf|input.glb> [output.glb]",
46 )
47 })?);
48 let output = args.next().map(PathBuf::from);
49 if args.next().is_some() {
50 return Err(io::Error::new(io::ErrorKind::InvalidInput, "too many arguments").into());
51 }
52
53 let mut import = draco_gltf::import(&input)?;
54 if let Some(output) = output {
55 let report = import.compress_primitive(MeshIndex(0), 0, CompressionOptions::default())?;
56 let bytes = import.to_bytes(OutputFormat::GlbV2)?;
57 std::fs::write(output, bytes)?;
58 println!("compression_report={report:?}");
59 } else {
60 let (primitives, faces) = decoded_draco_stats(&import)?;
61 println!("decoded_draco_primitives={primitives} decoded_faces={faces}");
62 }
63 Ok(())
64}