Move load_obj() into submudule

This commit is contained in:
Matthew Gordon 2019-12-21 10:42:52 -05:00
parent 12e26887c1
commit 08484306fd
1 changed files with 82 additions and 70 deletions

View File

@ -1,19 +1,15 @@
use nalgebra::{convert, Point3, RealField, Vector2, Vector3}; use nalgebra::{Point3, RealField, Vector2, Vector3};
use obj::{IndexTuple, Obj, SimplePolygon};
use super::materials::Material; use super::materials::Material;
use super::raycasting::{Intersect, IntersectionInfo, Ray}; use super::raycasting::{Intersect, IntersectionInfo, Ray};
use alga::general::SupersetOf;
use std::io::Result;
use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
#[derive(Debug)] #[derive(Debug)]
pub struct Triangle<T: RealField> { pub struct Triangle<T: RealField> {
pub vertices: [Point3<T>; 3], pub vertices: [Point3<T>; 3],
pub normals: [Vector3<T>; 3], pub normals: [Vector3<T>; 3],
pub material: Arc<dyn Material<T> >, pub material: Arc<dyn Material<T>>,
} }
impl<T: RealField> Intersect<T> for Triangle<T> { impl<T: RealField> Intersect<T> for Triangle<T> {
@ -81,75 +77,91 @@ impl<T: RealField> Intersect<T> for Triangle<T> {
} }
} }
fn get_vertex_and_normal<T: RealField>( mod wavefront_obj {
index_tuple: &IndexTuple, use crate::materials::Material;
vertex_positions: &Vec<[f32; 3]>,
normal_positions: &Vec<[f32; 3]>,
) -> (Point3<T>, Vector3<T>)
where
T: SupersetOf<f32>,
{
let &IndexTuple(vertex_index, _, maybe_normal_index) = index_tuple;
let vertex: Point3<T> = convert(Point3::from_slice(&vertex_positions[vertex_index]));
let normal = match maybe_normal_index {
Some(normal_index) => convert(Vector3::from_row_slice(&normal_positions[normal_index])),
None => Vector3::zeros(),
};
(vertex, normal)
}
fn get_triangles<T: RealField>( use super::Triangle;
polygon: &SimplePolygon,
vertex_positions: &Vec<[f32; 3]>, use alga::general::SupersetOf;
normal_positions: &Vec<[f32; 3]>, use nalgebra::{convert, Point3, RealField, Vector3};
material: Arc<dyn Material<T>>, use obj::{IndexTuple, Obj, SimplePolygon};
) -> Vec<Triangle<T>>
where use std::io::Result;
T: SupersetOf<f32>, use std::path::Path;
{ use std::sync::Arc;
if let Some(v0_index) = polygon.iter().next() {
let (v0_vertex, v0_normal) = fn get_vertex_and_normal<T: RealField>(
get_vertex_and_normal(v0_index, &vertex_positions, &normal_positions); index_tuple: &IndexTuple,
polygon vertex_positions: &Vec<[f32; 3]>,
normal_positions: &Vec<[f32; 3]>,
) -> (Point3<T>, Vector3<T>)
where
T: SupersetOf<f32>,
{
let &IndexTuple(vertex_index, _, maybe_normal_index) = index_tuple;
let vertex: Point3<T> = convert(Point3::from_slice(&vertex_positions[vertex_index]));
let normal = match maybe_normal_index {
Some(normal_index) => convert(Vector3::from_row_slice(&normal_positions[normal_index])),
None => Vector3::zeros(),
};
(vertex, normal)
}
fn get_triangles<T: RealField>(
polygon: &SimplePolygon,
vertex_positions: &Vec<[f32; 3]>,
normal_positions: &Vec<[f32; 3]>,
material: Arc<dyn Material<T>>,
) -> Vec<Triangle<T>>
where
T: SupersetOf<f32>,
{
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<T: RealField>(
filename: &Path,
material: Arc<dyn Material<T>>,
) -> Result<Vec<Triangle<T>>>
where
T: SupersetOf<f32>,
{
let obj = Obj::<SimplePolygon>::load(filename)?;
Ok(obj
.objects
.iter() .iter()
.skip(1) .flat_map(|object| object.groups.iter())
.zip(polygon.iter().skip(2)) .flat_map(|group| group.polys.iter())
.map(|(v1_index, v2_index)| { .flat_map(|poly| get_triangles(poly, &obj.position, &obj.normal, material.clone()))
let (v1_vertex, v1_normal) = .collect())
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<T: RealField>( pub use wavefront_obj::load_obj;
filename: &Path,
material: Arc<dyn Material<T>>,
) -> Result<Vec<Triangle<T>>>
where
T: SupersetOf<f32>,
{
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()))
.collect())
}
fn indices_with_index_of_largest_element_last<T: RealField>(v: &Vector3<T>) -> [usize; 3] { fn indices_with_index_of_largest_element_last<T: RealField>(v: &Vector3<T>) -> [usize; 3] {
if v.x > v.y { if v.x > v.y {