use super::*;
use crate::tracer::Color;
pub struct MtlConfig {
pub diffuse_color: Color,
pub specular_color: Color,
pub emission_color: Color,
pub transmission_filter: Vec3,
pub refraction_idx: Float,
pub roughness: Float,
pub illumination_model: usize,
pub map_kd: Option<Image>,
}
impl Default for MtlConfig {
fn default() -> Self {
Self {
diffuse_color: Color::BLACK,
specular_color: Color::BLACK,
emission_color: Color::BLACK,
transmission_filter: Vec3::ZERO,
refraction_idx: 1.5,
roughness: 1.0,
illumination_model: 0,
map_kd: None,
}
}
}
impl MtlConfig {
pub fn build_material(&self) -> Material {
if !self.emission_color.is_black() {
Material::Light(Texture::Solid(self.emission_color))
} else {
let texture = if let Some(img) = &self.map_kd {
Texture::Image(img.clone())
} else {
Texture::Solid(self.diffuse_color + self.specular_color)
};
let metallicity = if self.illumination_model == 5 { 1.0 } else { 0.0 };
let is_transparent = self.illumination_model == 6
|| self.illumination_model == 7;
Material::microfacet(
texture,
self.roughness,
self.refraction_idx,
metallicity,
is_transparent,
)
}
}
}
pub fn load_file(
file: File,
zip_file: Option<Vec<u8>>,
materials: &mut HashMap<String, MtlConfig>,
) -> Result<()> {
let reader = BufReader::new(file);
let mut mtl = MtlConfig::default();
let mut mtl_name = String::default();
for line in reader.lines() {
let line = line?.trim().to_string();
if line.starts_with('#') || line.is_empty() {
continue;
}
let tokens: Vec<&str> = line.split_ascii_whitespace().collect();
match tokens[0] {
"newmtl" => {
if !mtl_name.is_empty() {
materials.insert(mtl_name, mtl);
}
mtl = MtlConfig::default();
mtl_name = tokens[1].to_string();
}
"Kd" => {
let kd = parse_vec3(&tokens)?;
mtl.diffuse_color = Color::from(kd);
}
"map_Kd" => {
if let Some(ref zip) = zip_file {
let tex_name = tokens[1].replace("\\", "/");
let img = super::_img_from_zip(zip.clone(), &tex_name)?;
mtl.map_kd = Some(img);
}
}
"Ke" => {
let ke = parse_vec3(&tokens)?;
mtl.emission_color = Color::from(ke);
}
"Ks" => {
let ks = parse_vec3(&tokens)?;
mtl.specular_color = Color::from(ks);
}
"Tf" => {
let tf = parse_vec3(&tokens)?;
mtl.transmission_filter = tf;
}
"Ni" => {
let ni = parse_double(tokens[1])?;
mtl.refraction_idx = ni;
}
"Ns" => {
let ns = parse_double(tokens[1])?;
let roughness = 1.0 - ns.min(900.0).sqrt() / 30.0;
mtl.roughness = roughness;
}
"illum" => {
let illum = parse_double(tokens[1])?;
mtl.illumination_model = illum as usize;
}
_ => (),
}
}
materials.insert(mtl_name, mtl);
Ok(())
}