Refactored triangle meshes in preparation for custom normals.

This commit is contained in:
Nathan Vegdahl 2017-07-30 16:56:28 -07:00
parent c75c154e46
commit e77d5b7576
2 changed files with 91 additions and 53 deletions

View File

@ -25,7 +25,7 @@ pub fn parse_mesh_surface<'a>(
arena: &'a MemArena, arena: &'a MemArena,
tree: &'a DataTree, tree: &'a DataTree,
) -> Result<TriangleMesh<'a>, PsyParseError> { ) -> Result<TriangleMesh<'a>, PsyParseError> {
let mut verts = Vec::new(); let mut verts = Vec::new(); // Vec of vecs, one for each time sample
let mut face_vert_counts = Vec::new(); let mut face_vert_counts = Vec::new();
let mut face_vert_indices = Vec::new(); let mut face_vert_indices = Vec::new();
@ -33,30 +33,25 @@ pub fn parse_mesh_surface<'a>(
// and other validation. // and other validation.
// Get verts // Get verts
let mut time_samples = 0;
let mut first_vert_count = None;
for (_, text, _) in tree.iter_leaf_children_with_type("Vertices") { for (_, text, _) in tree.iter_leaf_children_with_type("Vertices") {
let mut raw_text = text.trim().as_bytes(); let mut raw_text = text.trim().as_bytes();
// Collect verts for this time sample // Collect verts for this time sample
let mut vert_count = 0; let mut tverts = Vec::new();
while let IResult::Done(remaining, vert) = while let IResult::Done(remaining, vert) =
closure!(tuple!(ws_f32, ws_f32, ws_f32))(raw_text) closure!(tuple!(ws_f32, ws_f32, ws_f32))(raw_text)
{ {
raw_text = remaining; raw_text = remaining;
verts.push(Point::new(vert.0, vert.1, vert.2)); tverts.push(Point::new(vert.0, vert.1, vert.2));
vert_count += 1;
} }
verts.push(tverts);
}
// Make sure all time samples have same vert count // Make sure all time samples have same vert count
if let Some(fvc) = first_vert_count { let vert_count = verts[0].len();
assert_eq!(vert_count, fvc); for vs in &verts {
} else { assert_eq!(vert_count, vs.len());
first_vert_count = Some(vert_count);
}
time_samples += 1;
} }
// Get face vert counts // Get face vert counts
@ -82,23 +77,18 @@ pub fn parse_mesh_surface<'a>(
} }
// Build triangle mesh // Build triangle mesh
let mut triangles = Vec::new(); let mut tri_vert_indices = Vec::new();
let vert_count = first_vert_count.unwrap();
let mut ii = 0; let mut ii = 0;
for fvc in &face_vert_counts { for fvc in &face_vert_counts {
if *fvc >= 3 { if *fvc >= 3 {
// Store the polygon, split up into triangles if >3 verts // Store the polygon, split up into triangles if >3 verts
let v1 = ii; let v1 = ii;
for vi in 0..(fvc - 2) { for vi in 0..(fvc - 2) {
// Store all the time samples of each triangle contiguously tri_vert_indices.push((
for time_sample in 0..time_samples { face_vert_indices[v1],
let start_vi = vert_count * time_sample; face_vert_indices[v1 + vi + 1],
triangles.push(( face_vert_indices[v1 + vi + 2],
verts[start_vi + face_vert_indices[v1]], ));
verts[start_vi + face_vert_indices[v1 + vi + 1]],
verts[start_vi + face_vert_indices[v1 + vi + 2]],
));
}
} }
} else { } else {
// TODO: proper error // TODO: proper error
@ -108,5 +98,9 @@ pub fn parse_mesh_surface<'a>(
ii += *fvc; ii += *fvc;
} }
Ok(TriangleMesh::from_triangles(arena, time_samples, triangles)) Ok(TriangleMesh::from_verts_and_indices(
arena,
verts,
tri_vert_indices,
))
} }

View File

@ -7,7 +7,7 @@ use bbox::BBox;
use boundable::Boundable; use boundable::Boundable;
use color::XYZ; use color::XYZ;
use fp_utils::fp_gamma; use fp_utils::fp_gamma;
use lerp::{lerp, lerp_slice, lerp_slice_with}; use lerp::lerp_slice;
use math::{Point, Matrix4x4, cross}; use math::{Point, Matrix4x4, cross};
use ray::{Ray, AccelRay}; use ray::{Ray, AccelRay};
use shading::surface_closure::{SurfaceClosureUnion, GTRClosure, LambertClosure}; use shading::surface_closure::{SurfaceClosureUnion, GTRClosure, LambertClosure};
@ -18,42 +18,71 @@ use super::triangle;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub struct TriangleMesh<'a> { pub struct TriangleMesh<'a> {
time_samples: usize, time_sample_count: usize,
geo: &'a [(Point, Point, Point)], vertices: &'a [Point], // Vertices, with the time samples for each vertex stored contiguously
indices: &'a [usize], indices: &'a [(u32, u32, u32, u32)], // (v0_idx, v1_idx, v2_idx, original_tri_idx)
accel: BVH4<'a>, accel: BVH4<'a>,
} }
impl<'a> TriangleMesh<'a> { impl<'a> TriangleMesh<'a> {
pub fn from_triangles<'b>( pub fn from_verts_and_indices<'b>(
arena: &'b MemArena, arena: &'b MemArena,
time_samples: usize, verts: Vec<Vec<Point>>,
triangles: Vec<(Point, Point, Point)>, tri_indices: Vec<(usize, usize, usize)>,
) -> TriangleMesh<'b> { ) -> TriangleMesh<'b> {
assert_eq!(triangles.len() % time_samples, 0); let vert_count = verts[0].len();
let time_sample_count = verts.len();
let mut indices: Vec<usize> = (0..(triangles.len() / time_samples)) // Copy verts over to a contiguous area of memory, reorganizing them
.map(|n| n * time_samples) // so that each vertices' time samples are contiguous in memory.
.collect(); let vertices = {
let mut vertices =
unsafe { arena.alloc_array_uninitialized(vert_count * time_sample_count) };
for vi in 0..vert_count {
for ti in 0..time_sample_count {
vertices[(vi * time_sample_count) + ti] = verts[ti][vi];
}
}
vertices
};
// Copy triangle vertex indices over, appending the triangle index itself to the tuple
let mut indices = {
let mut indices = unsafe { arena.alloc_array_uninitialized(tri_indices.len()) };
for (i, tri_i) in tri_indices.iter().enumerate() {
indices[i] = (tri_i.0 as u32, tri_i.2 as u32, tri_i.1 as u32, i as u32);
}
indices
};
// Create bounds array for use during BVH construction
let bounds = { let bounds = {
let mut bounds = Vec::new(); let mut bounds = Vec::with_capacity(indices.len() * time_sample_count);
for tri in &triangles { for tri in &tri_indices {
let minimum = tri.0.min(tri.1.min(tri.2)); for ti in 0..time_sample_count {
let maximum = tri.0.max(tri.1.max(tri.2)); let p0 = verts[ti][tri.0];
bounds.push(BBox::from_points(minimum, maximum)); let p1 = verts[ti][tri.1];
let p2 = verts[ti][tri.2];
let minimum = p0.min(p1.min(p2));
let maximum = p0.max(p1.max(p2));
bounds.push(BBox::from_points(minimum, maximum));
}
} }
bounds bounds
}; };
let accel = BVH4::from_objects(arena, &mut indices[..], 3, |tri_i| { // Build BVH
&bounds[*tri_i..(*tri_i + time_samples)] let accel = BVH4::from_objects(arena, &mut indices[..], 3, |tri| {
&bounds[(tri.3 as usize * time_sample_count)..
((tri.3 as usize + 1) * time_sample_count)]
}); });
TriangleMesh { TriangleMesh {
time_samples: time_samples, time_sample_count: time_sample_count,
geo: arena.copy_slice(&triangles), vertices: vertices,
indices: arena.copy_slice(&indices), indices: indices,
accel: accel, accel: accel,
} }
} }
@ -83,16 +112,31 @@ impl<'a> Surface for TriangleMesh<'a> {
self.accel self.accel
.traverse( .traverse(
&mut accel_rays[..], self.indices, |tri_i, rs| { &mut accel_rays[..], self.indices, |tri_indices, rs| {
for r in rs { for r in rs {
let wr = &wrays[r.id as usize]; let wr = &wrays[r.id as usize];
// Get triangle // Get triangle
let tri = lerp_slice_with( let tri = {
&self.geo[*tri_i..(*tri_i + self.time_samples)], let p0_slice = &self.vertices[
wr.time, (tri_indices.0 as usize * self.time_sample_count)..
|a, b, t| (lerp(a.0, b.0, t), lerp(a.1, b.1, t), lerp(a.2, b.2, t)), ((tri_indices.0 as usize + 1) * self.time_sample_count)
); ];
let p1_slice = &self.vertices[
(tri_indices.1 as usize * self.time_sample_count)..
((tri_indices.1 as usize + 1) * self.time_sample_count)
];
let p2_slice = &self.vertices[
(tri_indices.2 as usize * self.time_sample_count)..
((tri_indices.2 as usize + 1) * self.time_sample_count)
];
let p0 = lerp_slice(p0_slice, wr.time);
let p1 = lerp_slice(p1_slice, wr.time);
let p2 = lerp_slice(p2_slice, wr.time);
(p0, p1, p2)
};
// Transform triangle as necessary, and get transform // Transform triangle as necessary, and get transform
// space. // space.