2018-02-23 12:04:26 +01:00
|
|
|
//! Module containing the parser for material files from Wavefront OBJ (mtl files).
|
|
|
|
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
use parser::{Element, ParserError, LineParser};
|
2018-06-15 17:36:51 +02:00
|
|
|
use parser::obj::parse_values;
|
|
|
|
|
|
|
|
use math::vector::Vector3;
|
2018-02-23 12:04:26 +01:00
|
|
|
|
|
|
|
/// Wavefront material file format parser.
|
|
|
|
pub struct MtlParser {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MtlParser {
|
|
|
|
|
|
|
|
/// Creates a MtlParser.
|
|
|
|
pub fn new() -> MtlParser {
|
|
|
|
MtlParser {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LineParser for MtlParser {
|
2018-06-15 17:36:51 +02:00
|
|
|
fn parse_line(&mut self, line_number: usize, line: &str, path: &str) -> Result<Element, ParserError> {
|
2018-02-23 12:04:26 +01:00
|
|
|
|
|
|
|
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())),
|
|
|
|
|
2018-06-15 17:36:51 +02:00
|
|
|
"Kd" => {
|
|
|
|
let values = parse_values(line_number, line, path, 3)?;
|
|
|
|
Ok(Element::Diffuse(Vector3::new(
|
2018-07-23 10:12:37 +02:00
|
|
|
values[0] as f64,
|
|
|
|
values[1] as f64,
|
|
|
|
values[2] as f64,
|
2018-06-15 17:36:51 +02:00
|
|
|
)))
|
|
|
|
},
|
|
|
|
|
2018-02-23 12:04:26 +01:00
|
|
|
map if map.starts_with("map_") => {
|
|
|
|
|
2018-06-20 17:24:33 +02:00
|
|
|
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(
|
2018-07-23 10:12:37 +02:00
|
|
|
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())); },
|
2018-06-20 17:24:33 +02:00
|
|
|
);
|
|
|
|
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()))
|
|
|
|
}
|
2018-02-23 12:04:26 +01:00
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|