diff options
author | HampusM <hampus@hampusmat.com> | 2025-05-24 19:40:41 +0200 |
---|---|---|
committer | HampusM <hampus@hampusmat.com> | 2025-05-24 19:41:02 +0200 |
commit | 66799c1a44d1f4871a42547f1ac3e2dde49d364c (patch) | |
tree | e9e85ceef39aad7a8a0696b598f83bc16c7c8d1e /engine | |
parent | 4ad0f20f90147b663e0b151ffcdb88ca62c60281 (diff) |
refactor(engine): make mtl parser not open texture maps
Diffstat (limited to 'engine')
-rw-r--r-- | engine/src/file_format/wavefront/mtl.rs | 182 |
1 files changed, 95 insertions, 87 deletions
diff --git a/engine/src/file_format/wavefront/mtl.rs b/engine/src/file_format/wavefront/mtl.rs index d90dbcf..7d1c570 100644 --- a/engine/src/file_format/wavefront/mtl.rs +++ b/engine/src/file_format/wavefront/mtl.rs @@ -2,7 +2,7 @@ //! //! File format documentation: <https://paulbourke.net/dataformats/mtl> -use std::path::Path; +use std::path::{Path, PathBuf}; use crate::color::Color; use crate::file_format::wavefront::common::{ @@ -11,8 +11,6 @@ use crate::file_format::wavefront::common::{ ParsingError, Statement, }; -use crate::material::{Builder as MaterialBuilder, Material}; -use crate::texture::{Error as TextureError, Texture}; /// Parses the content of a Wavefront `.mtl`. /// @@ -50,18 +48,41 @@ pub fn parse(obj_content: &str) -> Result<Vec<NamedMaterial>, Error> } #[derive(Debug, Clone)] +#[non_exhaustive] pub struct NamedMaterial { pub name: String, - pub material: Material, + pub ambient: Color<f32>, + pub diffuse: Color<f32>, + pub specular: Color<f32>, + pub ambient_map: Option<TextureMap>, + pub diffuse_map: Option<TextureMap>, + pub specular_map: Option<TextureMap>, + pub shininess: f32, +} + +impl Default for NamedMaterial +{ + fn default() -> Self + { + Self { + name: String::new(), + ambient: Color::WHITE_F32, + diffuse: Color::WHITE_F32, + specular: Color::WHITE_F32, + ambient_map: None, + diffuse_map: None, + specular_map: None, + shininess: 0.0, + } + } } #[derive(Debug, Clone)] -pub struct UnfinishedNamedMaterial +#[non_exhaustive] +pub struct TextureMap { - name: String, - material_builder: MaterialBuilder, - ready: bool, + pub path: PathBuf, } #[derive(Debug, thiserror::Error)] @@ -70,8 +91,14 @@ pub enum Error #[error(transparent)] ParsingError(#[from] ParsingError), - #[error("Failed to open texture")] - TextureError(#[from] TextureError), + #[error( + "A material start statement (newmtl) is expected before statement at line {}", + line_no + )] + ExpectedMaterialStartStmtBeforeStmt + { + line_no: usize + }, #[error( "Unsupported number of arguments ({arg_count}) to {keyword} at line {line_no}" @@ -100,59 +127,52 @@ fn statements_to_materials( { let mut materials = Vec::<NamedMaterial>::with_capacity(material_cnt); - let mut curr_material = UnfinishedNamedMaterial { - name: String::new(), - material_builder: MaterialBuilder::new(), - ready: false, - }; - for (line_no, statement) in statements { if statement.keyword == Keyword::Newmtl { - if curr_material.ready { - tracing::debug!("Building material"); - - let material = curr_material.material_builder.clone().build(); - - materials.push(NamedMaterial { name: curr_material.name, material }); - } - let name = statement.get_text_arg(0, line_no)?; - curr_material.name = name.to_string(); - curr_material.ready = true; + materials.push(NamedMaterial { + name: name.to_string(), + ..Default::default() + }); continue; } - if !curr_material.ready { - // Discard statements not belonging to a material - continue; + let Some(curr_material) = materials.last_mut() else { + return Err(Error::ExpectedMaterialStartStmtBeforeStmt { line_no }); }; match statement.keyword { Keyword::Ka => { let color = get_color_from_statement(&statement, line_no)?; - tracing::debug!("Adding ambient color"); + tracing::debug!( + "Adding ambient color {color:?} to material {}", + curr_material.name + ); - curr_material.material_builder = - curr_material.material_builder.ambient(color); + curr_material.ambient = color; } Keyword::Kd => { let color = get_color_from_statement(&statement, line_no)?; - tracing::debug!("Adding diffuse color"); + tracing::debug!( + "Adding diffuse color {color:?} to material {}", + curr_material.name + ); - curr_material.material_builder = - curr_material.material_builder.diffuse(color); + curr_material.diffuse = color; } Keyword::Ks => { let color = get_color_from_statement(&statement, line_no)?; - tracing::debug!("Adding specular color"); + tracing::debug!( + "Adding specular color {color:?} to material {}", + curr_material.name + ); - curr_material.material_builder = - curr_material.material_builder.specular(color); + curr_material.specular = color; } Keyword::MapKa => { if statement.arguments.len() > 1 { @@ -165,53 +185,59 @@ fn statements_to_materials( let texture_file_path = statement.get_text_arg(0, line_no)?; - let texture = Texture::open(Path::new(texture_file_path))?; + tracing::debug!( + "Adding ambient map {texture_file_path} to material {}", + curr_material.name + ); - tracing::debug!("Adding ambient map"); - - let texture_id = texture.id(); - - curr_material.material_builder = curr_material - .material_builder - .texture(texture) - .ambient_map(texture_id); + curr_material.ambient_map = Some(TextureMap { + path: Path::new(texture_file_path).to_path_buf(), + }); } Keyword::MapKd => { - let texture = get_map_from_texture(&statement, line_no)?; + if statement.arguments.len() > 1 { + return Err(Error::UnsupportedArgumentCount { + keyword: statement.keyword.to_string(), + arg_count: statement.arguments.len(), + line_no, + }); + } - tracing::debug!("Adding diffuse map"); + let texture_file_path = statement.get_text_arg(0, line_no)?; - let texture_id = texture.id(); + tracing::debug!( + "Adding diffuse map {texture_file_path} to material {}", + curr_material.name + ); - curr_material.material_builder = curr_material - .material_builder - .texture(texture) - .diffuse_map(texture_id); + curr_material.diffuse_map = Some(TextureMap { + path: Path::new(texture_file_path).to_path_buf(), + }); } Keyword::MapKs => { - let texture = get_map_from_texture(&statement, line_no)?; + if statement.arguments.len() > 1 { + return Err(Error::UnsupportedArgumentCount { + keyword: statement.keyword.to_string(), + arg_count: statement.arguments.len(), + line_no, + }); + } - tracing::debug!("Adding specular map"); + let texture_file_path = statement.get_text_arg(0, line_no)?; - let texture_id = texture.id(); + tracing::debug!( + "Adding specular map {texture_file_path} to material {}", + curr_material.name + ); - curr_material.material_builder = curr_material - .material_builder - .texture(texture) - .specular_map(texture_id); + curr_material.specular_map = Some(TextureMap { + path: Path::new(texture_file_path).to_path_buf(), + }); } Keyword::Newmtl => {} } } - if curr_material.ready { - tracing::debug!("Building last material"); - - let material = curr_material.material_builder.build(); - - materials.push(NamedMaterial { name: curr_material.name, material }); - } - Ok(materials) } @@ -235,24 +261,6 @@ fn get_color_from_statement( Ok(Color { red, green, blue }) } -fn get_map_from_texture( - statement: &Statement<Keyword>, - line_no: usize, -) -> Result<Texture, Error> -{ - if statement.arguments.len() > 1 { - return Err(Error::UnsupportedArgumentCount { - keyword: statement.keyword.to_string(), - arg_count: statement.arguments.len(), - line_no, - }); - } - - let texture_file_path = statement.get_text_arg(0, line_no)?; - - Ok(Texture::open(Path::new(texture_file_path))?) -} - keyword! { #[derive(Debug, PartialEq, Eq, Clone, Copy)] enum Keyword { |