From c0c34fba7df20afbfcf4c432614c3498df4e1c9e Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Tue, 7 Apr 2020 20:16:53 +0200 Subject: [PATCH] library: scene: mesh: use unknown_param for Ke tobj actually has an `unknown_param` map with everything that's not in the official MTL spec, so let's use that instead of forking tobj --- pathtracer/Cargo.toml | 5 +--- pathtracer/src/scene/mesh.rs | 48 +++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/pathtracer/Cargo.toml b/pathtracer/Cargo.toml index 2673431..f80ec3b 100644 --- a/pathtracer/Cargo.toml +++ b/pathtracer/Cargo.toml @@ -28,6 +28,7 @@ rand = "0.7" rayon = "1.3.0" serde_yaml = "0.8" structopt = "0.3" +tobj = "1.0" [dependencies.nalgebra] version = "0.20.0" @@ -36,7 +37,3 @@ features = ["serde-serialize"] [dependencies.serde] version = "1.0" features = ["derive"] - -[dependencies.tobj] -git = "https://github.com/alarsyo/tobj" # forked for Ke support -rev = "82b5c2ca" diff --git a/pathtracer/src/scene/mesh.rs b/pathtracer/src/scene/mesh.rs index 974680c..7895029 100644 --- a/pathtracer/src/scene/mesh.rs +++ b/pathtracer/src/scene/mesh.rs @@ -35,6 +35,26 @@ pub(crate) struct Wavefront { scale: f32, } +fn parse_float3(s: &str) -> Result<[f32; 3], tobj::LoadError> { + let mut res = [0.0, 0.0, 0.0]; + let mut count = 0; + + for (i, s) in s.split_whitespace().enumerate() { + if count == 3 { + return Err(tobj::LoadError::MaterialParseError); + } + + res[i] = s.parse().map_err(|_| tobj::LoadError::MaterialParseError)?; + count += 1; + } + + if count < 3 { + return Err(tobj::LoadError::MaterialParseError); + } + + Ok(res) +} + impl TryFrom for Mesh { type Error = tobj::LoadError; @@ -97,7 +117,15 @@ impl TryFrom for Mesh { let diffuse = LinearColor::from_slice(&mesh_mat.ambient[..]); let specular = LinearColor::from_slice(&mesh_mat.ambient[..]); - let emitted = LinearColor::from_slice(&mesh_mat.emission[..]); + let emitted = mesh_mat + .unknown_param + .get("Ke") + // we want a default if "Ke" isn't provided, but we + // want an error if it is provided but its value + // doesn't parse + .map_or(Ok(LinearColor::black()), |ke| { + parse_float3(ke).map(|vals| LinearColor::from_slice(&vals)) + })?; let material = UniformMaterial::new(LightProperties::new( diffuse.clone(), @@ -134,3 +162,21 @@ impl TryFrom for Mesh { Ok(Mesh { shapes }) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn parse_float3_works() { + assert_eq!(parse_float3("1 1 1"), Ok([1., 1., 1.])); + assert_eq!( + parse_float3("1 1"), + Err(tobj::LoadError::MaterialParseError) + ); + assert_eq!( + parse_float3("1 1 1 1"), + Err(tobj::LoadError::MaterialParseError) + ); + } +}