vanrijn/src/mesh.rs

92 lines
3.0 KiB
Rust

/// Load a model from a Wavefront .obj file
mod wavefront_obj {
use crate::materials::Material;
use crate::math::Vec3;
use crate::raycasting::{Primitive, Triangle};
use obj::{IndexTuple, Obj, SimplePolygon};
use std::io::Result;
use std::path::Path;
use std::sync::Arc;
fn get_vertex_and_normal(
index_tuple: &IndexTuple,
vertex_positions: &[[f32; 3]],
normal_positions: &[[f32; 3]],
) -> (Vec3, Vec3) {
let &IndexTuple(vertex_index, _, maybe_normal_index) = index_tuple;
(
{
let vertex_coords = &vertex_positions[vertex_index];
Vec3::new(
vertex_coords[0] as f64,
vertex_coords[1] as f64,
vertex_coords[2] as f64,
)
},
match maybe_normal_index {
Some(normal_index) => {
let normal_coords = &normal_positions[normal_index];
Vec3::new(
normal_coords[0] as f64,
normal_coords[1] as f64,
normal_coords[2] as f64,
)
}
None => Vec3::zeros(),
},
)
}
fn get_triangles(
polygon: &SimplePolygon,
vertex_positions: &[[f32; 3]],
normal_positions: &[[f32; 3]],
material: Arc<dyn Material>,
) -> Vec<Triangle> {
if let Some(v0_index) = polygon.iter().next() {
let (v0_vertex, v0_normal) =
get_vertex_and_normal(v0_index, &vertex_positions, &normal_positions);
polygon
.iter()
.skip(1)
.zip(polygon.iter().skip(2))
.map(|(v1_index, v2_index)| {
let (v1_vertex, v1_normal) =
get_vertex_and_normal(v1_index, &vertex_positions, &normal_positions);
let (v2_vertex, v2_normal) =
get_vertex_and_normal(v2_index, &vertex_positions, &normal_positions);
let vertices = [v0_vertex, v1_vertex, v2_vertex];
let normals = [v0_normal, v1_normal, v2_normal];
Triangle {
vertices,
normals,
material: material.clone(),
}
})
.collect()
} else {
vec![]
}
}
pub fn load_obj(
filename: &Path,
material: Arc<dyn Material>,
) -> Result<Vec<Arc<dyn Primitive>>> {
let obj = Obj::<SimplePolygon>::load(filename)?;
Ok(obj
.objects
.iter()
.flat_map(|object| object.groups.iter())
.flat_map(|group| group.polys.iter())
.flat_map(|poly| get_triangles(poly, &obj.position, &obj.normal, material.clone()))
.map(|triangle| Arc::new(triangle) as Arc<dyn Primitive>)
.collect())
}
}
pub use wavefront_obj::load_obj;