Speed up ray/mesh intersection for cases with no transform motion blur.

This commit is contained in:
Nathan Vegdahl 2017-07-12 01:32:44 -07:00
parent 972c2a90a7
commit 2dcba3aca4

View File

@ -8,7 +8,7 @@ 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, lerp_slice, lerp_slice_with};
use math::{Point, Vector, 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};
@ -74,25 +74,51 @@ impl<'a> Surface for TriangleMesh<'a> {
isects: &mut [SurfaceIntersection], isects: &mut [SurfaceIntersection],
space: &[Matrix4x4], space: &[Matrix4x4],
) { ) {
// Precalculate transform for non-motion blur cases
let static_mat_space = if space.len() == 1 {
lerp_slice(space, 0.0).inverse()
} else {
Matrix4x4::new()
};
self.accel self.accel
.traverse( .traverse(
&mut accel_rays[..], &self.indices, |tri_i, rs| { &mut accel_rays[..], &self.indices, |tri_i, 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
let tri = lerp_slice_with( let tri = lerp_slice_with(
&self.geo[*tri_i..(*tri_i + self.time_samples)], &self.geo[*tri_i..(*tri_i + self.time_samples)],
wr.time, wr.time,
|a, b, t| (lerp(a.0, b.0, t), lerp(a.1, b.1, t), lerp(a.2, b.2, t)), |a, b, t| (lerp(a.0, b.0, t), lerp(a.1, b.1, t), lerp(a.2, b.2, t)),
); );
// TODO: when there's no transforms, we don't have to
// transform the triangles at all. // Transform triangle as necessary, and get transform
let mat_space = if space.len() > 0 { // space.
lerp_slice(space, wr.time) let (mat_space, tri) = if space.len() > 0 {
if space.len() > 1 {
// Per-ray transform, for motion blur
let mat_space = lerp_slice(space, wr.time).inverse();
(mat_space,
(tri.0 * mat_space,
tri.1 * mat_space,
tri.2 * mat_space)
)
} else { } else {
Matrix4x4::new() // Same transform for all rays
(static_mat_space,
(tri.0 * static_mat_space,
tri.1 * static_mat_space,
tri.2 * static_mat_space)
)
}
} else {
// No transforms
(Matrix4x4::new(), tri)
}; };
let mat_inv = mat_space.inverse();
let tri = (tri.0 * mat_inv, tri.1 * mat_inv, tri.2 * mat_inv); // Test ray against triangle
if let Some((t, b0, b1, b2)) = triangle::intersect_ray(wr, tri) { if let Some((t, b0, b1, b2)) = triangle::intersect_ray(wr, tri) {
if t < r.max_t { if t < r.max_t {
if r.is_occlusion() { if r.is_occlusion() {