Got BVH4 working. Woo hoo!

This commit is contained in:
Nathan Vegdahl 2017-04-13 22:44:34 -07:00
parent 53a14996c9
commit 573c5da5ab
5 changed files with 53 additions and 61 deletions

View File

@ -98,47 +98,41 @@ impl<'a> BVH4<'a> {
TRAVERSAL_TABLE[ray_code as usize][traversal_code as usize]
};
let mut all_hits = 0; // Accumulate
// Ray testing
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| {
if (!r.is_done()) && (first_loop || r.trav_stack.pop()) {
let hits = lerp_slice(bounds, r.time)
.intersect_accel_ray(r)
.to_bitmask();
all_hits |= hits;
if hits != 0 {
// Push hit bits onto ray's traversal stack
let mut shuffled_hits = 0;
for i in 0..3 {
for i in 0..children.len() {
let ii = (node_order_code >> (i * 2)) & 3;
shuffled_hits |= ((hits >> ii) & 1) << i;
}
r.trav_stack.push_3(shuffled_hits);
r.trav_stack.push_n(shuffled_hits, children.len() as u8);
true
} else {
false
}
} else {
false
}
});
if part > 0 {
node_stack[stack_ptr] = {
Some(&children[(node_order_code & 3) as usize])
};
node_stack[stack_ptr + 1] = {
Some(&children[((node_order_code >> 2) & 3) as usize])
};
node_stack[stack_ptr + 2] = if children.len() > 2 {
Some(&children[((node_order_code >> 4) & 3) as usize])
} else {
None
};
node_stack[stack_ptr + 3] = if children.len() > 3 {
Some(&children[((node_order_code >> 6) & 3) as usize])
} else {
None
};
ray_i_stack[stack_ptr] = part;
ray_i_stack[stack_ptr + 1] = part;
// Update stack based on ray testing results
if part > 0 {
for i in 0..children.len() {
let inv_i = (children.len() - 1) - i;
node_stack[stack_ptr + i] =
Some(&children[((node_order_code >> (inv_i * 2)) & 3) as
usize]);
ray_i_stack[stack_ptr + i] = part;
}
stack_ptr += children.len() - 1;
} else {
stack_ptr -= 1;
@ -298,7 +292,11 @@ impl<'a> BVH4<'a> {
};
calc_traversal_code(split_axis,
split_axis_l.unwrap_or(split_axis_r.unwrap_or(0)),
split_axis_r.unwrap_or(0),
if child_count == 4 {
split_axis_r.unwrap()
} else {
0
},
topology_code)
};
*fill_node = BVH4Node::Internal {

View File

@ -24,20 +24,24 @@ impl BitStack128 {
self.data.0 |= value as u64;
}
/// Push 3 bits onto the top of the stack. The input
/// Push n bits onto the top of the stack. The input
/// bits are passed as an integer, with the bit that
/// will be on top in the least significant digit, and
/// the rest following in order from there.
///
/// Note that unless you are running a debug build, no
/// effort is made to verify that only the first three
/// effort is made to verify that only the first n
/// bits of the passed value are used. So if other
/// bits are non-zero this will produce incorrect results.
pub fn push_3(&mut self, value: u8) {
debug_assert!((self.data.1 >> (size_of::<u64>() - 3)) == 0); // Verify no stack overflow
debug_assert!(value & (!((1 << 3) - 1)) == 0); // Verify no bits outside of the 3-bit range
self.data.1 = (self.data.1 << 3) | (self.data.0 >> (size_of::<u64>() - 3));
self.data.0 <<= 3;
pub fn push_n(&mut self, value: u8, count: u8) {
// Verify no bitstack overflow
debug_assert!((self.data.1 >> (size_of::<u64>() - count as usize)) == 0);
// Verify no bits outside of the n-bit range
debug_assert!(value & (!((1 << count) - 1)) == 0);
self.data.1 = (self.data.1 << count as usize) |
(self.data.0 >> (size_of::<u64>() - count as usize));
self.data.0 <<= count as u64;
self.data.0 |= value as u64;
}
@ -61,16 +65,6 @@ impl BitStack128 {
return b;
}
/// Pop the top n bits off the stack, returning only the first
/// one.
pub fn pop_1_remove_n(&mut self, n: usize) -> bool {
debug_assert!(n < size_of::<BitStack128>()); // Can't pop more than we have
let b = (self.data.0 & 1) != 0;
self.data.0 = (self.data.0 >> n) | (self.data.1 << (size_of::<u64>() - n));
self.data.1 >>= n;
return b;
}
/// Read the top bit of the stack without popping it.
pub fn peek(&self) -> bool {
(self.data.0 & 1) != 0

View File

@ -520,7 +520,7 @@ impl Bool4 {
}
pub fn to_bitmask(&self) -> u8 {
(self.get_0() as u8) & ((self.get_1() as u8) << 1) & ((self.get_2() as u8) << 2) &
(self.get_0() as u8) | ((self.get_1() as u8) << 1) | ((self.get_2() as u8) << 2) |
((self.get_3() as u8) << 3)
}
}

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use mem_arena::MemArena;
use accel::{LightAccel, LightTree};
use accel::BVH;
use accel::BVH4;
use bbox::{BBox, transform_bbox_slice_from};
use boundable::Boundable;
use color::SpectralSample;
@ -28,7 +28,7 @@ pub struct Assembly<'a> {
pub assemblies: &'a [Assembly<'a>],
// Object accel
pub object_accel: BVH<'a>,
pub object_accel: BVH4<'a>,
// Light accel
pub light_accel: LightTree<'a>,
@ -231,7 +231,7 @@ impl<'a> AssemblyBuilder<'a> {
let (bis, bbs) = self.instance_bounds();
// Build object accel
let object_accel = BVH::from_objects(self.arena,
let object_accel = BVH4::from_objects(self.arena,
&mut self.instances[..],
1,
|inst| &bbs[bis[inst.id]..bis[inst.id + 1]]);
@ -288,7 +288,7 @@ impl<'a> AssemblyBuilder<'a> {
/// Returns a pair of vectors with the bounds of all instances.
/// This is used for building the assembly's BVH.
/// This is used for building the assembly's BVH4.
fn instance_bounds(&self) -> (Vec<usize>, Vec<BBox>) {
let mut indices = vec![0];
let mut bounds = Vec::new();

View File

@ -2,7 +2,7 @@
use mem_arena::MemArena;
use accel::BVH;
use accel::BVH4;
use bbox::BBox;
use boundable::Boundable;
use color::XYZ;
@ -20,7 +20,7 @@ pub struct TriangleMesh<'a> {
time_samples: usize,
geo: &'a [(Point, Point, Point)],
indices: &'a [usize],
accel: BVH<'a>,
accel: BVH4<'a>,
}
impl<'a> TriangleMesh<'a> {
@ -44,7 +44,7 @@ impl<'a> TriangleMesh<'a> {
bounds
};
let accel = BVH::from_objects(arena,
let accel = BVH4::from_objects(arena,
&mut indices[..],
3,
|tri_i| &bounds[*tri_i..(*tri_i + time_samples)]);