//! 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 face_to_string(&self, f: model::face::Face) -> String { if f.a.texture_coordinate.is_none() && f.a.normal.is_none() { // Only vertices format!("f {} {} {}", f.a.vertex + 1, f.b.vertex + 1, f.c.vertex + 1) } else if f.a.normal.is_none() { // Vertices + tex coords format!("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 format!("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 format!("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) } } } 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 { let string = match element { Vertex(v) => format!("v {} {} {}", v.x(), v.y(), v.z()), TextureCoordinate(vt) => format!("vt {} {}", vt.x(), vt.y()), Normal(n) => format!("vn {} {} {}", n.x(), n.y(), n.z()), Face(f) => self.face_to_string(f), UseMaterial(ref n) => format!("usemtl {}", n), _ => return Ok(0), }; writeln!(output, "{}", string)?; Ok(string.len() + 1) } }