model-converter/src/parser/mtl.rs

98 lines
3.4 KiB
Rust

//! Module containing the parser for material files from Wavefront OBJ (mtl files).
use std::path::PathBuf;
use parser::{Element, ParserError, LineParser};
use parser::obj::parse_values;
use math::vector::Vector3;
/// Wavefront material file format parser.
pub struct MtlParser {
}
impl MtlParser {
/// Creates a MtlParser.
pub fn new() -> MtlParser {
MtlParser {
}
}
}
impl LineParser for MtlParser {
fn parse_line(&mut self, line_number: usize, line: &str, path: &str) -> Result<Element, ParserError> {
let mut root = PathBuf::from(path);
root.pop();
let mut split = line.split_whitespace();
if let Some(first) = split.nth(0) {
let first = first.trim();
match first {
// Ignore comments
"#" => Ok(Element::None),
// Starts a new material
"newmtl" => Ok(Element::NewMaterial(split.nth(0).unwrap().to_owned())),
"Kd" => {
let values = parse_values(line_number, line, path, 3)?;
Ok(Element::Diffuse(Vector3::new(
values[0] as f64,
values[1] as f64,
values[2] as f64,
)))
},
map if map.starts_with("map_") => {
let split = split.collect::<Vec<_>>();
if split.len() == 0 {
Err(ParserError::NoPathAfterMap(path.to_owned(), line_number))
} else if split.len() == 1 {
let mut full_path = root.clone();
full_path.push(split[0].to_owned());
Ok(Element::Texture(first.to_owned(), full_path.to_str().unwrap().to_owned(), Vector3::new(1.0, 1.0, 1.0)))
} else if split[0] == "-s" {
let size = Vector3::new(
if let Ok(f) = split[1].parse::<f64>() { f } else { return Err(ParserError::ParseNumberError(path.to_owned(), line_number, split[1].to_owned())); },
if let Ok(f) = split[2].parse::<f64>() { f } else { return Err(ParserError::ParseNumberError(path.to_owned(), line_number, split[2].to_owned())); },
if let Ok(f) = split[3].parse::<f64>() { f } else { return Err(ParserError::ParseNumberError(path.to_owned(), line_number, split[3].to_owned())); },
);
let mut full_path = root.clone();
full_path.push(split[4].to_owned());
Ok(Element::Texture(first.to_owned(), full_path.to_str().unwrap().to_owned(), size))
} else {
Err(ParserError::UnexpectedKeyword(path.to_owned(), line_number, split[1].to_owned()))
}
},
// The keyword is not empty and unexpected
// We don't do this : we simply return an unknown material instruction
// key if key.len() != 0 => {
// Err(ParserError::UnexpectedKeyword(path.to_owned(), line_number, key.to_owned()))
// },
// Empty string
"" => Ok(Element::None),
// Unknown instruction
_ => Ok(Element::UnknownMaterialInstruction(line.to_owned())),
}
} else {
Ok(Element::None)
}
}
}