diff --git a/Cargo.lock b/Cargo.lock index d19626b2d..9973cb062 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1072,6 +1072,7 @@ dependencies = [ "stl", "thiserror", "threemf", + "wavefront_rs", ] [[package]] @@ -3921,6 +3922,12 @@ version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +[[package]] +name = "wavefront_rs" +version = "2.0.0-alpha.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad6ae8f49ee35d8afba6b30d1714f9043bfd2d1ef650897cb6405a600609e9a1" + [[package]] name = "wayland-client" version = "0.29.5" diff --git a/crates/fj-export/Cargo.toml b/crates/fj-export/Cargo.toml index c3ad3f694..16bb848e1 100644 --- a/crates/fj-export/Cargo.toml +++ b/crates/fj-export/Cargo.toml @@ -17,3 +17,4 @@ fj-math.workspace = true thiserror = "1.0.40" threemf = "0.4.0" stl = "0.2.1" +wavefront_rs = "2.0.0-alpha.1" diff --git a/crates/fj-export/src/lib.rs b/crates/fj-export/src/lib.rs index 0129bb833..df7bba312 100644 --- a/crates/fj-export/src/lib.rs +++ b/crates/fj-export/src/lib.rs @@ -14,7 +14,7 @@ #![warn(missing_docs)] -use std::{fs::File, path::Path}; +use std::{fs::File, io::Write, path::Path}; use thiserror::Error; @@ -35,6 +35,9 @@ pub fn export(mesh: &Mesh>, path: &Path) -> Result<(), Error> { Some(extension) if extension.to_ascii_uppercase() == "STL" => { export_stl(mesh, path) } + Some(extension) if extension.to_ascii_uppercase() == "OBJ" => { + export_obj(mesh, path) + } Some(extension) => Err(Error::InvalidExtension( extension.to_string_lossy().into_owned(), )), @@ -119,6 +122,55 @@ fn export_stl(mesh: &Mesh>, path: &Path) -> Result<(), Error> { Ok(()) } +fn export_obj(mesh: &Mesh>, path: &Path) -> Result<(), Error> { + let mut f = File::create(path)?; + + for (cnt, t) in mesh.triangles().enumerate() { + // write each point of the triangle + for v in t.inner.points() { + wavefront_rs::obj::writer::Writer::write( + &mut f, + &wavefront_rs::obj::entity::Entity::Vertex { + x: v.x.into_f64(), + y: v.y.into_f64(), + z: v.z.into_f64(), + w: None, + }, + ) + .or(Err(Error::OBJ))?; + f.write_all(b"\n")?; + } + + // write the triangle + wavefront_rs::obj::writer::Writer::write( + &mut f, + &wavefront_rs::obj::entity::Entity::Face { + vertices: vec![ + wavefront_rs::obj::entity::FaceVertex { + vertex: (cnt * 3 + 1) as i64, + texture: None, + normal: None, + }, + wavefront_rs::obj::entity::FaceVertex { + vertex: (cnt * 3 + 2) as i64, + texture: None, + normal: None, + }, + wavefront_rs::obj::entity::FaceVertex { + vertex: (cnt * 3 + 3) as i64, + texture: None, + normal: None, + }, + ], + }, + ) + .or(Err(Error::OBJ))?; + f.write_all(b"\n")?; + } + + Ok(()) +} + /// An error that can occur while exporting #[derive(Debug, Error)] pub enum Error { @@ -141,4 +193,8 @@ pub enum Error { /// Threemf error whilst exporting to 3MF file #[error("threemf error whilst exporting to 3MF file")] ThreeMF(#[from] threemf::Error), + + /// OBJ exporter error whilst exporting to OBJ file + #[error("obj error whilst exporting to OBJ file")] + OBJ, }