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("%d " % v, False)
|
||||||
self.w.write("]\n", False)
|
self.w.write("]\n", False)
|
||||||
|
|
||||||
# SubdivisionSurface section end
|
# MeshSurface/SubdivisionSurface section end
|
||||||
self.w.unindent()
|
self.w.unindent()
|
||||||
self.w.write("}\n")
|
self.w.write("}\n")
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
use std;
|
use std;
|
||||||
|
|
||||||
|
use lerp::{Lerp, lerp_slice};
|
||||||
|
|
||||||
/// Partitions a slice in-place with the given unary predicate, returning
|
/// Partitions a slice in-place with the given unary predicate, returning
|
||||||
/// the index of the first element for which the predicate evaluates
|
/// the index of the first element for which the predicate evaluates
|
||||||
/// false.
|
/// 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 bbox::BBox;
|
||||||
use boundable::Boundable;
|
use boundable::Boundable;
|
||||||
use ray::AccelRay;
|
use ray::AccelRay;
|
||||||
use algorithm::partition;
|
use algorithm::{partition, merge_slices_append};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct BVH {
|
pub struct BVH {
|
||||||
|
@ -158,12 +158,14 @@ impl BVH {
|
||||||
bounder);
|
bounder);
|
||||||
|
|
||||||
// Determine bounds
|
// Determine bounds
|
||||||
// TODO: merging of different length bounds
|
// TODO: do merging without the temporary vec.
|
||||||
let bi = self.bounds.len();
|
let bi = self.bounds.len();
|
||||||
for (i1, i2) in Iterator::zip(c1_bounds.0..c1_bounds.1, c2_bounds.0..c2_bounds.1) {
|
let mut merged = Vec::new();
|
||||||
let bb = self.bounds[i1] | self.bounds[i2];
|
merge_slices_append(&self.bounds[c1_bounds.0..c1_bounds.1],
|
||||||
self.bounds.push(bb);
|
&self.bounds[c2_bounds.0..c2_bounds.1],
|
||||||
}
|
&mut merged,
|
||||||
|
|b1, b2| *b1 | *b2);
|
||||||
|
self.bounds.extend(merged.drain(0..));
|
||||||
|
|
||||||
// Set node
|
// Set node
|
||||||
self.nodes[me] = BVHNode::Internal {
|
self.nodes[me] = BVHNode::Internal {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std;
|
||||||
use std::ops::{Index, IndexMut, Mul};
|
use std::ops::{Index, IndexMut, Mul};
|
||||||
|
|
||||||
use float4::Float4;
|
use float4::Float4;
|
||||||
use lerp::{Lerp, lerp_slice};
|
use lerp::Lerp;
|
||||||
|
|
||||||
use super::Point;
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -8,7 +8,7 @@ mod matrix;
|
||||||
pub use self::vector::Vector;
|
pub use self::vector::Vector;
|
||||||
pub use self::normal::Normal;
|
pub use self::normal::Normal;
|
||||||
pub use self::point::Point;
|
pub use self::point::Point;
|
||||||
pub use self::matrix::{Matrix4x4, multiply_matrix_slices};
|
pub use self::matrix::Matrix4x4;
|
||||||
|
|
||||||
/// Trait for calculating dot products.
|
/// Trait for calculating dot products.
|
||||||
pub trait DotProduct {
|
pub trait DotProduct {
|
||||||
|
|
|
@ -27,18 +27,27 @@ pub fn parse_mesh_surface(tree: &DataTree) -> Result<TriangleMesh, PsyParseError
|
||||||
// and other validation.
|
// and other validation.
|
||||||
|
|
||||||
// Get verts
|
// 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 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
|
||||||
|
let mut vert_count = 0;
|
||||||
while let IResult::Done(remaining, vert) = closure!(tuple!(ws_f32,
|
while let IResult::Done(remaining, vert) = closure!(tuple!(ws_f32,
|
||||||
ws_f32,
|
ws_f32,
|
||||||
ws_f32))(raw_text) {
|
ws_f32))(raw_text) {
|
||||||
raw_text = remaining;
|
raw_text = remaining;
|
||||||
|
|
||||||
verts.push(Point::new(vert.0, vert.1, vert.2));
|
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;
|
time_samples += 1;
|
||||||
|
@ -67,20 +76,25 @@ pub fn parse_mesh_surface(tree: &DataTree) -> Result<TriangleMesh, PsyParseError
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build triangle mesh
|
// Build triangle mesh
|
||||||
// TODO: time samples
|
|
||||||
let mut triangles = Vec::new();
|
let mut triangles = Vec::new();
|
||||||
|
let vert_count = first_vert_count.unwrap();
|
||||||
let mut ii = 0;
|
let mut ii = 0;
|
||||||
for fvc in face_vert_counts.iter() {
|
for fvc in face_vert_counts.iter() {
|
||||||
if *fvc >= 3 {
|
if *fvc >= 3 {
|
||||||
|
// 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) {
|
||||||
triangles.push((verts[face_vert_indices[v1]],
|
// Store all the time samples of each triangle contiguously
|
||||||
verts[face_vert_indices[v1 + vi + 1]],
|
for time_sample in 0..time_samples {
|
||||||
verts[face_vert_indices[v1 + vi + 2]]));
|
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 {
|
} else {
|
||||||
// TODO: proper error
|
// TODO: proper error
|
||||||
panic!();
|
panic!("Cannot handle polygons with less than three vertices.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ii += *fvc;
|
ii += *fvc;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
|
|
||||||
use algorithm::partition;
|
use algorithm::{partition, merge_slices_append};
|
||||||
use math::{Matrix4x4, multiply_matrix_slices};
|
use math::Matrix4x4;
|
||||||
use lerp::lerp_slice;
|
use lerp::lerp_slice;
|
||||||
use assembly::{Assembly, Object, InstanceType};
|
use assembly::{Assembly, Object, InstanceType};
|
||||||
use ray::{Ray, AccelRay};
|
use ray::{Ray, AccelRay};
|
||||||
|
@ -213,7 +213,10 @@ impl TransformStack {
|
||||||
let i2 = self.stack_indices[sil - 1];
|
let i2 = self.stack_indices[sil - 1];
|
||||||
|
|
||||||
self.scratch_space.clear();
|
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);
|
self.stack.extend(&self.scratch_space);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user