oxideav_obj/decoder.rs
1//! [`Mesh3DDecoder`] adaptors for OBJ + standalone MTL inputs.
2//!
3//! These are thin wrappers around [`crate::obj::parse_obj`] /
4//! [`crate::mtl::parse_mtl_with_scene`] that conform to the
5//! `oxideav-mesh3d` decoder trait. Held state is empty for now (the
6//! parsers don't carry options); the wrapper exists so registry-based
7//! lookup gets a uniform `Box<dyn Mesh3DDecoder>` factory.
8
9use oxideav_mesh3d::{Mesh3DDecoder, Result, Scene3D};
10
11use crate::{mtl, obj};
12
13/// Wavefront OBJ decoder.
14///
15/// Decodes a self-contained OBJ document into a [`Scene3D`]. Companion
16/// MTL files referenced by `mtllib` directives are not auto-resolved
17/// (the decoder has no file-system context); the material names land
18/// in `Primitive::extras["obj:usemtl"]` and the library file names
19/// land in `Scene3D::extras["obj:mtllibs"]` so the caller can fetch
20/// them and merge via [`crate::mtl::merge_materials_into_scene`].
21///
22/// Use [`obj::parse_obj_with_resolver`] directly when MTL bytes are
23/// already available.
24#[derive(Debug, Default)]
25pub struct ObjDecoder {
26 _private: (),
27}
28
29impl ObjDecoder {
30 /// Construct a fresh decoder. Equivalent to `ObjDecoder::default()`.
31 pub fn new() -> Self {
32 Self::default()
33 }
34}
35
36impl Mesh3DDecoder for ObjDecoder {
37 fn decode(&mut self, bytes: &[u8]) -> Result<Scene3D> {
38 let text = std::str::from_utf8(bytes)
39 .map_err(|_| oxideav_mesh3d::Error::invalid("OBJ input contained non-UTF-8 bytes"))?;
40 obj::parse_obj(text)
41 }
42}
43
44/// Standalone MTL decoder. Returns a [`Scene3D`] populated with the
45/// MTL's materials and any external textures they reference; no
46/// meshes / nodes / cameras / lights / animations are added.
47#[derive(Debug, Default)]
48pub struct MtlDecoder {
49 _private: (),
50}
51
52impl MtlDecoder {
53 pub fn new() -> Self {
54 Self::default()
55 }
56}
57
58impl Mesh3DDecoder for MtlDecoder {
59 fn decode(&mut self, bytes: &[u8]) -> Result<Scene3D> {
60 let text = std::str::from_utf8(bytes)
61 .map_err(|_| oxideav_mesh3d::Error::invalid("MTL input contained non-UTF-8 bytes"))?;
62 mtl::parse_mtl_with_scene(text)
63 }
64}