From e2ef44f666febf0f7c011d51400e659aae8ff37d Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sun, 10 Jul 2016 19:20:37 -0700 Subject: [PATCH] Finished implementing motion blur. --- psychoblend/psy_export.py | 2 +- src/algorithm.rs | 31 +++++++++++++++++++++++++++++++ src/bvh.rs | 14 ++++++++------ src/math/matrix.rs | 29 +---------------------------- src/math/mod.rs | 2 +- src/parse/psy_mesh_surface.rs | 28 +++++++++++++++++++++------- src/tracer.rs | 9 ++++++--- 7 files changed, 69 insertions(+), 46 deletions(-) diff --git a/psychoblend/psy_export.py b/psychoblend/psy_export.py index c4b4af4..1a001ff 100644 --- a/psychoblend/psy_export.py +++ b/psychoblend/psy_export.py @@ -348,7 +348,7 @@ class PsychoExporter: self.w.write("%d " % v, False) self.w.write("]\n", False) - # SubdivisionSurface section end + # MeshSurface/SubdivisionSurface section end self.w.unindent() self.w.write("}\n") diff --git a/src/algorithm.rs b/src/algorithm.rs index 1fe19e1..ed784fa 100644 --- a/src/algorithm.rs +++ b/src/algorithm.rs @@ -2,6 +2,8 @@ use std; +use lerp::{Lerp, lerp_slice}; + /// Partitions a slice in-place with the given unary predicate, returning /// the index of the first element for which the predicate evaluates /// false. @@ -109,3 +111,32 @@ pub fn partition_pair(slc1: &mut [A], slc2: &mut [B], mut pred: F) -> u } } } + +/// Merges two slices of things, appending the result to vec_out +pub fn merge_slices_append(slice1: &[T], + slice2: &[T], + vec_out: &mut Vec, + merge: F) + where F: Fn(&T, &T) -> T +{ + // Transform the bounding boxes + if slice1.len() == 0 || slice2.len() == 0 { + return; + } else if slice1.len() == slice2.len() { + for (xf1, xf2) in Iterator::zip(slice1.iter(), slice2.iter()) { + vec_out.push(merge(xf1, xf2)); + } + } else if slice1.len() > slice2.len() { + let s = (slice1.len() - 1) as f32; + for (i, xf1) in slice1.iter().enumerate() { + let xf2 = lerp_slice(slice2, i as f32 / s); + vec_out.push(merge(xf1, &xf2)); + } + } else if slice1.len() < slice2.len() { + let s = (slice2.len() - 1) as f32; + for (i, xf2) in slice2.iter().enumerate() { + let xf1 = lerp_slice(slice1, i as f32 / s); + vec_out.push(merge(&xf1, xf2)); + } + } +} diff --git a/src/bvh.rs b/src/bvh.rs index e4947bf..bc03b93 100644 --- a/src/bvh.rs +++ b/src/bvh.rs @@ -4,7 +4,7 @@ use lerp::lerp_slice; use bbox::BBox; use boundable::Boundable; use ray::AccelRay; -use algorithm::partition; +use algorithm::{partition, merge_slices_append}; #[derive(Debug)] pub struct BVH { @@ -158,12 +158,14 @@ impl BVH { bounder); // Determine bounds - // TODO: merging of different length bounds + // TODO: do merging without the temporary vec. let bi = self.bounds.len(); - for (i1, i2) in Iterator::zip(c1_bounds.0..c1_bounds.1, c2_bounds.0..c2_bounds.1) { - let bb = self.bounds[i1] | self.bounds[i2]; - self.bounds.push(bb); - } + let mut merged = Vec::new(); + merge_slices_append(&self.bounds[c1_bounds.0..c1_bounds.1], + &self.bounds[c2_bounds.0..c2_bounds.1], + &mut merged, + |b1, b2| *b1 | *b2); + self.bounds.extend(merged.drain(0..)); // Set node self.nodes[me] = BVHNode::Internal { diff --git a/src/math/matrix.rs b/src/math/matrix.rs index 79e84aa..ae9fd61 100644 --- a/src/math/matrix.rs +++ b/src/math/matrix.rs @@ -4,7 +4,7 @@ use std; use std::ops::{Index, IndexMut, Mul}; use float4::Float4; -use lerp::{Lerp, lerp_slice}; +use lerp::Lerp; use super::Point; @@ -248,33 +248,6 @@ impl Lerp for Matrix4x4 { } -pub fn multiply_matrix_slices(xforms1: &[Matrix4x4], - xforms2: &[Matrix4x4], - xforms_out: &mut Vec) { - xforms_out.clear(); - - // Transform the bounding boxes - if xforms1.len() == 0 || xforms2.len() == 0 { - return; - } else if xforms1.len() == xforms2.len() { - for (xf1, xf2) in Iterator::zip(xforms1.iter(), xforms2.iter()) { - xforms_out.push(*xf1 * *xf2); - } - } else if xforms1.len() > xforms2.len() { - let s = (xforms1.len() - 1) as f32; - for (i, xf) in xforms1.iter().enumerate() { - xforms_out.push(*xf * lerp_slice(xforms2, i as f32 / s)); - } - } else if xforms1.len() < xforms2.len() { - let s = (xforms2.len() - 1) as f32; - for (i, xf) in xforms2.iter().enumerate() { - xforms_out.push(lerp_slice(xforms1, i as f32 / s) * *xf); - } - } -} - - - #[cfg(test)] mod tests { use super::*; diff --git a/src/math/mod.rs b/src/math/mod.rs index c9f8bdc..efd6b44 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -8,7 +8,7 @@ mod matrix; pub use self::vector::Vector; pub use self::normal::Normal; pub use self::point::Point; -pub use self::matrix::{Matrix4x4, multiply_matrix_slices}; +pub use self::matrix::Matrix4x4; /// Trait for calculating dot products. pub trait DotProduct { diff --git a/src/parse/psy_mesh_surface.rs b/src/parse/psy_mesh_surface.rs index f7f5324..052cdcb 100644 --- a/src/parse/psy_mesh_surface.rs +++ b/src/parse/psy_mesh_surface.rs @@ -27,18 +27,27 @@ pub fn parse_mesh_surface(tree: &DataTree) -> Result Result= 3 { + // Store the polygon, split up into triangles if >3 verts let v1 = ii; for vi in 0..(fvc - 2) { - triangles.push((verts[face_vert_indices[v1]], - verts[face_vert_indices[v1 + vi + 1]], - verts[face_vert_indices[v1 + vi + 2]])); + // Store all the time samples of each triangle contiguously + for time_sample in 0..time_samples { + let start_vi = vert_count * time_sample; + triangles.push((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 { // TODO: proper error - panic!(); + panic!("Cannot handle polygons with less than three vertices."); } ii += *fvc; diff --git a/src/tracer.rs b/src/tracer.rs index e43777f..df142a3 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -1,8 +1,8 @@ use std::iter; use std::cell::UnsafeCell; -use algorithm::partition; -use math::{Matrix4x4, multiply_matrix_slices}; +use algorithm::{partition, merge_slices_append}; +use math::Matrix4x4; use lerp::lerp_slice; use assembly::{Assembly, Object, InstanceType}; use ray::{Ray, AccelRay}; @@ -213,7 +213,10 @@ impl TransformStack { let i2 = self.stack_indices[sil - 1]; self.scratch_space.clear(); - multiply_matrix_slices(&self.stack[i1..i2], xforms, &mut self.scratch_space); + merge_slices_append(&self.stack[i1..i2], + xforms, + &mut self.scratch_space, + |xf1, xf2| *xf1 * *xf2); self.stack.extend(&self.scratch_space); }