//! Module containing the logic for Wavefront OBJ serialization. use std::io::Write; use model; use exporter::ExportError; use exporter::ElementSerializer; use parser::Element; use parser::Element::{Vertex, TextureCoordinate, Normal, UseMaterial, Face}; /// Serializer for elements using the wavefront obj format. pub struct ObjElementSerializer { } impl ObjElementSerializer { /// Create an obj element serializer. pub fn new() -> ObjElementSerializer { ObjElementSerializer { } } /// Writes a face to a writable output. pub fn write_face(&self, f: model::Face, output: &mut W) -> Result<(), ExportError> { if f.a.texture_coordinate.is_none() && f.a.normal.is_none() { // Only vertices writeln!(output, "f {} {} {}", f.a.vertex + 1, f.b.vertex + 1, f.c.vertex + 1)?; } else if f.a.normal.is_none() { // Vertices + tex coords writeln!(output, "f {}/{} {}/{} {}/{}", f.a.vertex + 1, f.a.texture_coordinate.unwrap() + 1, f.b.vertex + 1, f.b.texture_coordinate.unwrap() + 1, f.c.vertex + 1, f.c.texture_coordinate.unwrap() + 1)?; } else if f.a.texture_coordinate.is_none() { // Vertices + normals writeln!(output, "f {}//{} {}//{} {}//{}", f.a.vertex + 1, f.a.normal.unwrap() + 1, f.b.vertex + 1, f.b.normal.unwrap() + 1, f.c.vertex + 1, f.c.normal.unwrap() + 1)?; } else { // All writeln!(output, "f {}/{}/{} {}/{}/{} {}/{}/{}", f.a.vertex + 1, f.a.texture_coordinate.unwrap() + 1, f.a.normal.unwrap() + 1, f.b.vertex + 1, f.b.texture_coordinate.unwrap() + 1, f.b.normal.unwrap() + 1, f.c.vertex + 1, f.c.texture_coordinate.unwrap() + 1, f.c.normal.unwrap() + 1)?; } Ok(()) } } impl ElementSerializer for ObjElementSerializer { /// Serializes an element using the wavefront obj format. /// /// ``` /// # use model_converter::math::vector::Vector3; /// # use model_converter::parser::Element::Vertex; /// # use model_converter::exporter::obj::ObjElementSerializer; /// use model_converter::exporter::ElementSerializer; /// let s = ObjElementSerializer::new(); /// let vertex = Vertex(Vector3::new(1.0, 2.0, 3.0)); /// let mut output = vec![]; /// let serialized = s.serialize(vertex, &mut output).ok().unwrap(); /// let result = String::from_utf8(output).unwrap(); /// assert_eq!(result, "v 1 2 3\n"); /// ``` fn serialize(&self, element: Element, output: &mut W) -> Result<(), ExportError> { match element { Vertex(v) => writeln!(output, "v {} {} {}", v.x(), v.y(), v.z())?, TextureCoordinate(vt) => writeln!(output, "vt {} {}", vt.x(), vt.y())?, Normal(n) => writeln!(output, "vn {} {} {}", n.x(), n.y(), n.z())?, Face(f) => self.write_face(f, output)?, UseMaterial(ref n) => writeln!(output, "usemtl {}", n)?, _ => (), } Ok(()) } }