//! 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 { 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 f32, values[1] as f32, values[2] as f32, ))) }, map if map.starts_with("map_") => { let split = split.collect::>(); 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::() { f } else { return Err(ParserError::ParseNumberError(path.to_owned(), line_number, split[1].to_owned())); }, if let Ok(f) = split[2].parse::() { f } else { return Err(ParserError::ParseNumberError(path.to_owned(), line_number, split[2].to_owned())); }, if let Ok(f) = split[3].parse::() { 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[2].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) } } }