use std::collections::HashMap; use crate::models::Material; use super::Vertex; #[derive(Debug)] pub struct Mesh { pub vertices: Vec, pub material_name: String, } const NEW_MATERIAL_DELIMITER: &str = "newmtl "; fn parse_rgb(values: &str) -> Result<[f32; 3], Box> { let mut rgb = [0.0; 3]; let mut i = 0; let values = values.split_whitespace(); for v in values { let parsed = v.parse::()?; rgb[i] = parsed; i += 1; if i > 2 { todo!("Implement custom error handling: too many values"); } }; if i != 3 { todo!("Implement custom error handling: too few values"); } Ok(rgb) } impl Mesh { pub fn new() -> Self { Self { vertices: vec![], material_name: String::new(), } } pub fn load_obj(&mut self, path: &str) -> Result<(), Box> { let content = std::fs::read_to_string(path)?; for line in content.lines() { if line.starts_with("v ") { let coords: Result, _> = line .split_whitespace() .skip(1) .take(3) .map(|s| s.parse::()) .collect(); match coords { Ok(v) if v.len() == 3 => { self.vertices.push(Vertex { x: v[0], y: v[1], z: v[2] }) }, _ => eprintln!("Warning: Invalid vertex line: {}", line) } } } println!("{:#?}", self.vertices); Ok(()) } pub fn load_material(&mut self, path: &str) -> Result<(), Box> { let content = std::fs::read_to_string(path)?; let mut lines = content.lines().peekable(); while let Some(line) = lines.next() { let line = line.trim(); if line.is_empty() { continue ; } if line.starts_with(NEW_MATERIAL_DELIMITER) { let mat_name = line.strip_prefix(NEW_MATERIAL_DELIMITER).unwrap(); while let Some(&next_line) = lines.peek() { let next = next_line.trim(); if next.starts_with(NEW_MATERIAL_DELIMITER) || next.is_empty() { lines.next(); let mut material = Material::new(); if let Some((key, values)) = next.split_once(' ') { match key { "Ka" => { match parse_rgb(values) { Ok(v) => material.ka = v, Err(e) => eprintln!("Error parsing Ka values: {}", e.to_string()) } }, "Kd" => { match parse_rgb(values) { Ok(v) => material.kd = v, Err(e) => eprintln!("Error parsing Kd values: {}", e.to_string()) } } "Ks" => { match parse_rgb(values) { Ok(v) => material.ks = v, Err(e) => eprintln!("Error parsing Ks values: {}", e.to_string()) } } _ => { eprintln!("Unknown key: {key}") } } } self.materials.insert(mat_name.to_string(), material); } } } } println!("{:#?}", self.vertices); Ok(()) } }