Finished implementing motion blur.

This commit is contained in:
Nathan Vegdahl 2016-07-10 19:20:37 -07:00
parent c2eb421fd8
commit e2ef44f666
7 changed files with 69 additions and 46 deletions

View File

@ -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")

View File

@ -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<A, B, F>(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<T: Lerp + Copy, F>(slice1: &[T],
slice2: &[T],
vec_out: &mut Vec<T>,
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));
}
}
}

View File

@ -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 {

View File

@ -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<Matrix4x4>) {
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::*;

View File

@ -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 {

View File

@ -27,18 +27,27 @@ pub fn parse_mesh_surface(tree: &DataTree) -> Result<TriangleMesh, PsyParseError
// and other validation.
// Get verts
// TODO: store vert count for a single round and make sure all rounds
// have the same count.
let mut time_samples = 0;
let mut first_vert_count = None;
for (_, text) in tree.iter_leaf_children_with_type("Vertices") {
let mut raw_text = text.trim().as_bytes();
// Collect verts for this time sample
let mut vert_count = 0;
while let IResult::Done(remaining, vert) = closure!(tuple!(ws_f32,
ws_f32,
ws_f32))(raw_text) {
raw_text = remaining;
verts.push(Point::new(vert.0, vert.1, vert.2));
vert_count += 1;
}
// Make sure all time samples have same vert count
if let Some(fvc) = first_vert_count {
assert!(vert_count == fvc);
} else {
first_vert_count = Some(vert_count);
}
time_samples += 1;
@ -67,20 +76,25 @@ pub fn parse_mesh_surface(tree: &DataTree) -> Result<TriangleMesh, PsyParseError
}
// Build triangle mesh
// TODO: time samples
let mut triangles = Vec::new();
let vert_count = first_vert_count.unwrap();
let mut ii = 0;
for fvc in face_vert_counts.iter() {
if *fvc >= 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;

View File

@ -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);
}