Finished implementing motion blur.
This commit is contained in:
parent
c2eb421fd8
commit
e2ef44f666
|
@ -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")
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
14
src/bvh.rs
14
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 {
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user