Skip to main content

oxideav_obj/
encoder.rs

1//! [`Mesh3DEncoder`] adaptors for OBJ + standalone MTL outputs.
2//!
3//! These wrap the [`crate::obj::serialize_obj`] /
4//! [`crate::mtl::serialize_mtl`] free functions in the
5//! `oxideav-mesh3d` encoder trait shape, with optional configuration
6//! captured on the wrapper itself.
7
8use oxideav_mesh3d::{Mesh3DEncoder, Result, Scene3D};
9
10use crate::{mtl, obj};
11
12/// Wavefront OBJ encoder.
13///
14/// By default the encoder emits a standalone OBJ (no `mtllib`
15/// directive). Call [`ObjEncoder::with_mtl_basename`] to embed an
16/// `mtllib <basename>.mtl` line at the top, in which case the caller
17/// is responsible for writing the companion MTL file alongside (use
18/// [`crate::mtl::serialize_mtl`] for that).
19///
20/// The encoder is loss-tolerant — it preserves the OBJ-specific
21/// extras (`obj:groups`, `obj:smoothing_group`, `obj:original_face_arities`,
22/// `obj:usemtl`, `obj:mtllibs`) populated by the decoder, so a
23/// decode → encode → decode round-trip is structurally stable.
24#[derive(Debug, Default)]
25pub struct ObjEncoder {
26    mtl_basename: Option<String>,
27}
28
29impl ObjEncoder {
30    pub fn new() -> Self {
31        Self::default()
32    }
33
34    /// Emit `mtllib <basename>.mtl` at the top of the output. The
35    /// basename is used verbatim (no `.mtl` extension is appended
36    /// twice; if you supply `"foo"` the directive becomes `mtllib foo.mtl`).
37    pub fn with_mtl_basename(mut self, basename: impl Into<String>) -> Self {
38        self.mtl_basename = Some(basename.into());
39        self
40    }
41}
42
43impl Mesh3DEncoder for ObjEncoder {
44    fn encode(&mut self, scene: &Scene3D) -> Result<Vec<u8>> {
45        obj::serialize_obj(scene, self.mtl_basename.as_deref())
46    }
47}
48
49/// Standalone MTL encoder — serialises only the [`Scene3D::materials`]
50/// vector (and any [`oxideav_mesh3d::Texture`]s referenced by them).
51#[derive(Debug, Default)]
52pub struct MtlEncoder {
53    _private: (),
54}
55
56impl MtlEncoder {
57    pub fn new() -> Self {
58        Self::default()
59    }
60}
61
62impl Mesh3DEncoder for MtlEncoder {
63    fn encode(&mut self, scene: &Scene3D) -> Result<Vec<u8>> {
64        mtl::serialize_mtl(&scene.materials, &scene.textures)
65    }
66}