2018-02-23 14:34:25 +01:00
|
|
|
//! 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.
|
2018-04-17 10:45:44 +02:00
|
|
|
pub fn face_to_string(&self, f: model::face::Face) -> String {
|
2018-04-10 13:37:08 +02:00
|
|
|
|
2018-02-23 14:34:25 +01:00
|
|
|
if f.a.texture_coordinate.is_none() && f.a.normal.is_none() {
|
|
|
|
// Only vertices
|
2018-04-10 13:37:08 +02:00
|
|
|
format!("f {} {} {}", f.a.vertex + 1, f.b.vertex + 1, f.c.vertex + 1)
|
2018-02-23 14:34:25 +01:00
|
|
|
} else if f.a.normal.is_none() {
|
|
|
|
// Vertices + tex coords
|
2018-04-10 13:37:08 +02:00
|
|
|
format!("f {}/{} {}/{} {}/{}",
|
2018-02-23 14:34:25 +01:00
|
|
|
f.a.vertex + 1, f.a.texture_coordinate.unwrap() + 1,
|
|
|
|
f.b.vertex + 1, f.b.texture_coordinate.unwrap() + 1,
|
2018-04-10 13:37:08 +02:00
|
|
|
f.c.vertex + 1, f.c.texture_coordinate.unwrap() + 1)
|
2018-02-23 14:34:25 +01:00
|
|
|
} else if f.a.texture_coordinate.is_none() {
|
|
|
|
// Vertices + normals
|
2018-04-10 13:37:08 +02:00
|
|
|
format!("f {}//{} {}//{} {}//{}",
|
2018-02-23 14:34:25 +01:00
|
|
|
f.a.vertex + 1, f.a.normal.unwrap() + 1,
|
|
|
|
f.b.vertex + 1, f.b.normal.unwrap() + 1,
|
2018-04-10 13:37:08 +02:00
|
|
|
f.c.vertex + 1, f.c.normal.unwrap() + 1)
|
2018-02-23 14:34:25 +01:00
|
|
|
} else {
|
|
|
|
// All
|
2018-04-10 13:37:08 +02:00
|
|
|
format!("f {}/{}/{} {}/{}/{} {}/{}/{}",
|
2018-02-23 14:34:25 +01:00
|
|
|
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,
|
2018-04-10 13:37:08 +02:00
|
|
|
f.c.vertex + 1, f.c.texture_coordinate.unwrap() + 1, f.c.normal.unwrap() + 1)
|
2018-02-23 14:34:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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");
|
|
|
|
/// ```
|
2018-04-10 13:37:08 +02:00
|
|
|
fn serialize<W: Write>(&self, element: Element, output: &mut W) -> Result<usize, ExportError> {
|
2018-02-23 14:34:25 +01:00
|
|
|
|
2018-04-10 13:37:08 +02:00
|
|
|
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),
|
|
|
|
};
|
2018-02-23 14:34:25 +01:00
|
|
|
|
2018-04-10 13:37:08 +02:00
|
|
|
writeln!(output, "{}", string)?;
|
|
|
|
Ok(string.len() + 1)
|
2018-02-23 14:34:25 +01:00
|
|
|
}
|
|
|
|
}
|