Move multiple-object logic out of BVH4.
This allows each part of Psychopath tp handle the logic in the best way, instead of a one-size-fits-all approach.
This commit is contained in:
parent
874b07df02
commit
4ef376dc89
|
@ -96,14 +96,9 @@ impl<'a> BVH4<'a> {
|
|||
self.depth
|
||||
}
|
||||
|
||||
pub fn traverse<T, F>(
|
||||
&self,
|
||||
rays: &mut RayBatch,
|
||||
ray_stack: &mut RayStack,
|
||||
objects: &[T],
|
||||
mut obj_ray_test: F,
|
||||
) where
|
||||
F: FnMut(&T, &mut RayBatch, &mut RayStack),
|
||||
pub fn traverse<F>(&self, rays: &mut RayBatch, ray_stack: &mut RayStack, mut obj_ray_test: F)
|
||||
where
|
||||
F: FnMut(std::ops::Range<usize>, &mut RayBatch, &mut RayStack),
|
||||
{
|
||||
if self.root.is_none() {
|
||||
return;
|
||||
|
@ -170,16 +165,8 @@ impl<'a> BVH4<'a> {
|
|||
&BVH4Node::Leaf { object_range } => {
|
||||
trav_time += timer.tick() as f64;
|
||||
|
||||
// Set up the tasks for each object.
|
||||
let obj_count = object_range.1 - object_range.0;
|
||||
for _ in 0..(obj_count - 1) {
|
||||
ray_stack.duplicate_next_task();
|
||||
}
|
||||
|
||||
// Do the ray tests.
|
||||
for obj in &objects[object_range.0..object_range.1] {
|
||||
obj_ray_test(obj, rays, ray_stack);
|
||||
}
|
||||
obj_ray_test(object_range.0..object_range.1, rays, ray_stack);
|
||||
|
||||
timer.tick();
|
||||
|
||||
|
|
27
src/ray.rs
27
src/ray.rs
|
@ -292,24 +292,37 @@ impl RayStack {
|
|||
self.lanes[l].end_len = self.lanes[l].idxs.len();
|
||||
}
|
||||
|
||||
/// Pops the next task off the stack, and executes the provided closure for
|
||||
/// each ray index in the task.
|
||||
pub fn pop_do_next_task<F>(&mut self, mut handle_ray: F)
|
||||
// Pops the next task off the stack.
|
||||
pub fn pop_task(&mut self) {
|
||||
let task = self.tasks.pop().unwrap();
|
||||
self.lanes[task.lane].end_len = task.start_idx;
|
||||
self.lanes[task.lane].idxs.truncate(task.start_idx);
|
||||
}
|
||||
|
||||
// Executes a task without popping it from the task stack.
|
||||
pub fn do_next_task<F>(&mut self, mut handle_ray: F)
|
||||
where
|
||||
F: FnMut(usize),
|
||||
{
|
||||
// Pop the task and do necessary bookkeeping.
|
||||
let task = self.tasks.pop().unwrap();
|
||||
let task = self.tasks.last().unwrap();
|
||||
let task_range = (task.start_idx, self.lanes[task.lane].end_len);
|
||||
self.lanes[task.lane].end_len = task.start_idx;
|
||||
|
||||
// Execute task.
|
||||
for i in task_range.0..task_range.1 {
|
||||
let ray_idx = self.lanes[task.lane].idxs[i];
|
||||
handle_ray(ray_idx as usize);
|
||||
}
|
||||
}
|
||||
|
||||
self.lanes[task.lane].idxs.truncate(task_range.0);
|
||||
/// Pops the next task off the stack, and executes the provided closure for
|
||||
/// each ray index in the task.
|
||||
#[inline(always)]
|
||||
pub fn pop_do_next_task<F>(&mut self, handle_ray: F)
|
||||
where
|
||||
F: FnMut(usize),
|
||||
{
|
||||
self.do_next_task(handle_ray);
|
||||
self.pop_task();
|
||||
}
|
||||
|
||||
/// Pops the next task off the stack, executes the provided closure for
|
||||
|
|
|
@ -130,11 +130,11 @@ impl<'a> Surface for TriangleMesh<'a> {
|
|||
Matrix4x4::new()
|
||||
};
|
||||
|
||||
self.accel.traverse(
|
||||
rays,
|
||||
ray_stack,
|
||||
self.indices,
|
||||
|tri_indices, rays, ray_stack| {
|
||||
self.accel
|
||||
.traverse(rays, ray_stack, |idx_range, rays, ray_stack| {
|
||||
for tri_idx in idx_range {
|
||||
let tri_indices = self.indices[tri_idx];
|
||||
|
||||
// For static triangles with static transforms, cache them.
|
||||
let is_cached = self.time_sample_count == 1 && space.len() <= 1;
|
||||
let mut tri = if is_cached {
|
||||
|
@ -157,7 +157,7 @@ impl<'a> Surface for TriangleMesh<'a> {
|
|||
};
|
||||
|
||||
// Test each ray against the current triangle.
|
||||
ray_stack.pop_do_next_task(|ray_idx| {
|
||||
ray_stack.do_next_task(|ray_idx| {
|
||||
let ray_idx = ray_idx as usize;
|
||||
let ray_time = rays.time(ray_idx);
|
||||
|
||||
|
@ -276,7 +276,8 @@ impl<'a> Surface for TriangleMesh<'a> {
|
|||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
ray_stack.pop_task();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,11 +85,11 @@ impl<'a> TracerInner<'a> {
|
|||
rays: &mut RayBatch,
|
||||
ray_stack: &mut RayStack,
|
||||
) {
|
||||
assembly.object_accel.traverse(
|
||||
rays,
|
||||
ray_stack,
|
||||
&assembly.instances[..],
|
||||
|inst, rays, ray_stack| {
|
||||
assembly
|
||||
.object_accel
|
||||
.traverse(rays, ray_stack, |idx_range, rays, ray_stack| {
|
||||
let inst = &assembly.instances[idx_range.start];
|
||||
|
||||
// Transform rays if needed
|
||||
if let Some((xstart, xend)) = inst.transform_indices {
|
||||
// Push transforms to stack
|
||||
|
@ -98,12 +98,11 @@ impl<'a> TracerInner<'a> {
|
|||
// Do transforms
|
||||
// TODO: re-divide rays based on direction (maybe?).
|
||||
let xforms = self.xform_stack.top();
|
||||
ray_stack.pop_do_next_task_and_push_rays(2, |ray_idx| {
|
||||
ray_stack.do_next_task(|ray_idx| {
|
||||
let t = rays.time(ray_idx);
|
||||
rays.update_local(ray_idx, &lerp_slice(xforms, t));
|
||||
(Bool4::new(true, true, false, false), 2)
|
||||
});
|
||||
ray_stack.push_lanes_to_tasks(&[0, 1]);
|
||||
ray_stack.duplicate_next_task();
|
||||
}
|
||||
|
||||
// Trace rays
|
||||
|
@ -142,8 +141,7 @@ impl<'a> TracerInner<'a> {
|
|||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn trace_object<'b>(
|
||||
|
|
Loading…
Reference in New Issue
Block a user