125 lines
3.1 KiB
Rust
125 lines
3.1 KiB
Rust
use std::collections::HashMap;
|
|
use crate::models::Material;
|
|
|
|
use super::Vertex;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Mesh {
|
|
pub vertices: Vec<Vertex>,
|
|
pub material_name: String,
|
|
}
|
|
|
|
const NEW_MATERIAL_DELIMITER: &str = "newmtl ";
|
|
|
|
fn parse_rgb(values: &str) -> Result<[f32; 3], Box<dyn std::error::Error>> {
|
|
let mut rgb = [0.0; 3];
|
|
let mut i = 0;
|
|
|
|
let values = values.split_whitespace();
|
|
|
|
for v in values {
|
|
let parsed = v.parse::<f32>()?;
|
|
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<dyn std::error::Error>> {
|
|
let content = std::fs::read_to_string(path)?;
|
|
|
|
for line in content.lines() {
|
|
if line.starts_with("v ") {
|
|
let coords: Result<Vec<f32>, _> = line
|
|
.split_whitespace()
|
|
.skip(1)
|
|
.take(3)
|
|
.map(|s| s.parse::<f32>())
|
|
.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<dyn std::error::Error>> {
|
|
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(())
|
|
}
|
|
}
|