Completed first attempt at implementing BVH4.
Completely untested, so almost certainly non-functional. But it compiles!
This commit is contained in:
parent
e0c6dfbd76
commit
53a14996c9
|
@ -21,6 +21,309 @@ use super::bvh_base::{BVHBase, BVHBaseNode, BVH_MAX_DEPTH};
|
||||||
// TRAVERSAL_TABLE
|
// TRAVERSAL_TABLE
|
||||||
include!("bvh4_table.inc");
|
include!("bvh4_table.inc");
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct BVH4<'a> {
|
||||||
|
root: Option<&'a BVH4Node<'a>>,
|
||||||
|
depth: usize,
|
||||||
|
_bounds: Option<&'a [BBox]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
enum BVH4Node<'a> {
|
||||||
|
Internal {
|
||||||
|
bounds: &'a [BBox4],
|
||||||
|
children: &'a [BVH4Node<'a>],
|
||||||
|
traversal_code: u8,
|
||||||
|
},
|
||||||
|
|
||||||
|
Leaf { object_range: (usize, usize) },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BVH4<'a> {
|
||||||
|
pub fn from_objects<'b, T, F>(arena: &'a MemArena,
|
||||||
|
objects: &mut [T],
|
||||||
|
objects_per_leaf: usize,
|
||||||
|
bounder: F)
|
||||||
|
-> BVH4<'a>
|
||||||
|
where F: 'b + Fn(&T) -> &'b [BBox]
|
||||||
|
{
|
||||||
|
if objects.len() == 0 {
|
||||||
|
BVH4 {
|
||||||
|
root: None,
|
||||||
|
depth: 0,
|
||||||
|
_bounds: None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let base = BVHBase::from_objects(objects, objects_per_leaf, bounder);
|
||||||
|
|
||||||
|
let mut fill_node = unsafe { arena.alloc_uninitialized::<BVH4Node>() };
|
||||||
|
BVH4::construct_from_base(arena, &base, &base.nodes[base.root_node_index()], fill_node);
|
||||||
|
|
||||||
|
BVH4 {
|
||||||
|
root: Some(fill_node),
|
||||||
|
depth: (base.depth / 2) + 1,
|
||||||
|
_bounds: {
|
||||||
|
let range = base.nodes[base.root_node_index()].bounds_range();
|
||||||
|
Some(arena.copy_slice(&base.bounds[range.0..range.1]))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tree_depth(&self) -> usize {
|
||||||
|
self.depth
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn traverse<T, F>(&self, rays: &mut [AccelRay], objects: &[T], mut obj_ray_test: F)
|
||||||
|
where F: FnMut(&T, &mut [AccelRay])
|
||||||
|
{
|
||||||
|
match self.root {
|
||||||
|
None => {}
|
||||||
|
|
||||||
|
Some(root) => {
|
||||||
|
// +2 of max depth for root and last child
|
||||||
|
let mut node_stack = [Some(root); BVH_MAX_DEPTH + 2];
|
||||||
|
let mut ray_i_stack = [rays.len(); BVH_MAX_DEPTH + 2];
|
||||||
|
let mut stack_ptr = 1;
|
||||||
|
let mut first_loop = true;
|
||||||
|
|
||||||
|
let ray_code = (rays[0].dir_inv.x().is_sign_negative() as u8) |
|
||||||
|
((rays[0].dir_inv.y().is_sign_negative() as u8) << 1) |
|
||||||
|
((rays[0].dir_inv.z().is_sign_negative() as u8) << 2);
|
||||||
|
|
||||||
|
while stack_ptr > 0 {
|
||||||
|
match node_stack[stack_ptr] {
|
||||||
|
Some(&BVH4Node::Internal { bounds, children, traversal_code }) => {
|
||||||
|
let node_order_code = {
|
||||||
|
TRAVERSAL_TABLE[ray_code as usize][traversal_code as usize]
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut all_hits = 0; // Accumulate
|
||||||
|
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;
|
||||||
|
|
||||||
|
// Push hit bits onto ray's traversal stack
|
||||||
|
let mut shuffled_hits = 0;
|
||||||
|
for i in 0..3 {
|
||||||
|
let ii = (node_order_code >> (i * 2)) & 3;
|
||||||
|
shuffled_hits |= ((hits >> ii) & 1) << i;
|
||||||
|
}
|
||||||
|
r.trav_stack.push_3(shuffled_hits);
|
||||||
|
|
||||||
|
true
|
||||||
|
} 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;
|
||||||
|
stack_ptr += children.len() - 1;
|
||||||
|
} else {
|
||||||
|
stack_ptr -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(&BVH4Node::Leaf { object_range }) => {
|
||||||
|
let part = if !first_loop {
|
||||||
|
partition(&mut rays[..ray_i_stack[stack_ptr]],
|
||||||
|
|r| r.trav_stack.pop())
|
||||||
|
} else {
|
||||||
|
ray_i_stack[stack_ptr]
|
||||||
|
};
|
||||||
|
|
||||||
|
for obj in &objects[object_range.0..object_range.1] {
|
||||||
|
obj_ray_test(obj, &mut rays[..part]);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_ptr -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
None => {
|
||||||
|
if !first_loop {
|
||||||
|
for r in (&mut rays[..ray_i_stack[stack_ptr]]).iter_mut() {
|
||||||
|
r.trav_stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack_ptr -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
first_loop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn construct_from_base(arena: &'a MemArena,
|
||||||
|
base: &BVHBase,
|
||||||
|
node: &BVHBaseNode,
|
||||||
|
fill_node: &mut BVH4Node<'a>) {
|
||||||
|
match node {
|
||||||
|
// Create internal node
|
||||||
|
&BVHBaseNode::Internal { bounds_range: _, children_indices, split_axis } => {
|
||||||
|
let child_l = &base.nodes[children_indices.0];
|
||||||
|
let child_r = &base.nodes[children_indices.1];
|
||||||
|
|
||||||
|
// Prepare convenient access to the stuff we need.
|
||||||
|
let child_count;
|
||||||
|
let children; // [Optional, Optional, Optional, Optional]
|
||||||
|
let split_axis_l; // Optional
|
||||||
|
let split_axis_r; // Optional
|
||||||
|
match child_l {
|
||||||
|
&BVHBaseNode::Internal { children_indices: i_l, split_axis: s_l, .. } => {
|
||||||
|
match child_r {
|
||||||
|
&BVHBaseNode::Internal { children_indices: i_r,
|
||||||
|
split_axis: s_r,
|
||||||
|
.. } => {
|
||||||
|
// Four nodes
|
||||||
|
child_count = 4;
|
||||||
|
children = [Some(&base.nodes[i_l.0]),
|
||||||
|
Some(&base.nodes[i_l.1]),
|
||||||
|
Some(&base.nodes[i_r.0]),
|
||||||
|
Some(&base.nodes[i_r.1])];
|
||||||
|
split_axis_l = Some(s_l);
|
||||||
|
split_axis_r = Some(s_r);
|
||||||
|
}
|
||||||
|
&BVHBaseNode::Leaf { .. } => {
|
||||||
|
// Three nodes with left split
|
||||||
|
child_count = 3;
|
||||||
|
children = [Some(&base.nodes[i_l.0]),
|
||||||
|
Some(&base.nodes[i_l.1]),
|
||||||
|
Some(child_r),
|
||||||
|
None];
|
||||||
|
split_axis_l = Some(s_l);
|
||||||
|
split_axis_r = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&BVHBaseNode::Leaf { .. } => {
|
||||||
|
match child_r {
|
||||||
|
&BVHBaseNode::Internal { children_indices: i_r,
|
||||||
|
split_axis: s_r,
|
||||||
|
.. } => {
|
||||||
|
// Three nodes with right split
|
||||||
|
child_count = 3;
|
||||||
|
children = [Some(child_l),
|
||||||
|
Some(&base.nodes[i_r.0]),
|
||||||
|
Some(&base.nodes[i_r.1]),
|
||||||
|
None];
|
||||||
|
split_axis_l = None;
|
||||||
|
split_axis_r = Some(s_r);
|
||||||
|
}
|
||||||
|
&BVHBaseNode::Leaf { .. } => {
|
||||||
|
// Two nodes
|
||||||
|
child_count = 2;
|
||||||
|
children = [Some(child_l), Some(child_r), None, None];
|
||||||
|
split_axis_l = None;
|
||||||
|
split_axis_r = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct bounds
|
||||||
|
let bounds = {
|
||||||
|
let bounds_len = children.iter()
|
||||||
|
.map(|c| if let &Some(n) = c {
|
||||||
|
n.bounds_range().1 - n.bounds_range().0
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
})
|
||||||
|
.max()
|
||||||
|
.unwrap();
|
||||||
|
let mut bounds = unsafe { arena.alloc_array_uninitialized(bounds_len) };
|
||||||
|
for (i, b) in bounds.iter_mut().enumerate() {
|
||||||
|
let time = i as f32 / (bounds_len - 1) as f32;
|
||||||
|
|
||||||
|
let b1 = children[0].map_or(BBox::new(), |c| {
|
||||||
|
let (x, y) = c.bounds_range();
|
||||||
|
lerp_slice(&base.bounds[x..y], time)
|
||||||
|
});
|
||||||
|
let b2 = children[1].map_or(BBox::new(), |c| {
|
||||||
|
let (x, y) = c.bounds_range();
|
||||||
|
lerp_slice(&base.bounds[x..y], time)
|
||||||
|
});
|
||||||
|
let b3 = children[2].map_or(BBox::new(), |c| {
|
||||||
|
let (x, y) = c.bounds_range();
|
||||||
|
lerp_slice(&base.bounds[x..y], time)
|
||||||
|
});
|
||||||
|
let b4 = children[3].map_or(BBox::new(), |c| {
|
||||||
|
let (x, y) = c.bounds_range();
|
||||||
|
lerp_slice(&base.bounds[x..y], time)
|
||||||
|
});
|
||||||
|
*b = BBox4::from_bboxes(b1, b2, b3, b4);
|
||||||
|
}
|
||||||
|
bounds
|
||||||
|
};
|
||||||
|
|
||||||
|
// Construct child nodes
|
||||||
|
let mut child_nodes =
|
||||||
|
unsafe { arena.alloc_array_uninitialized::<BVH4Node>(child_count) };
|
||||||
|
for (i, c) in children[0..child_count].iter().enumerate() {
|
||||||
|
BVH4::construct_from_base(arena, base, c.unwrap(), &mut child_nodes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build this node
|
||||||
|
let traversal_code = {
|
||||||
|
let topology_code = if child_count == 4 {
|
||||||
|
0
|
||||||
|
} else if child_count == 2 {
|
||||||
|
3
|
||||||
|
} else if split_axis_l.is_some() {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
};
|
||||||
|
calc_traversal_code(split_axis,
|
||||||
|
split_axis_l.unwrap_or(split_axis_r.unwrap_or(0)),
|
||||||
|
split_axis_r.unwrap_or(0),
|
||||||
|
topology_code)
|
||||||
|
};
|
||||||
|
*fill_node = BVH4Node::Internal {
|
||||||
|
bounds: bounds,
|
||||||
|
children: child_nodes,
|
||||||
|
traversal_code: traversal_code,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create internal node
|
||||||
|
&BVHBaseNode::Leaf { object_range, .. } => {
|
||||||
|
*fill_node = BVH4Node::Leaf { object_range: object_range };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<'a> Boundable for BVH4<'a> {
|
||||||
|
fn bounds<'b>(&'b self) -> &'b [BBox] {
|
||||||
|
self._bounds.unwrap_or(&[])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Calculates the traversal code for a BVH4 node based on the splits and topology
|
// Calculates the traversal code for a BVH4 node based on the splits and topology
|
||||||
// of its children.
|
// of its children.
|
||||||
//
|
//
|
||||||
|
@ -44,161 +347,3 @@ fn calc_traversal_code(split_1: u8, split_2: u8, split_3: u8, topology: u8) -> u
|
||||||
static T_TABLE: [u8; 4] = [0, 27, 27 + 9, 27 + 9 + 9];
|
static T_TABLE: [u8; 4] = [0, 27, 27 + 9, 27 + 9 + 9];
|
||||||
split_1 + (split_2 * 3) + (split_3 * 9) + T_TABLE[topology as usize]
|
split_1 + (split_2 * 3) + (split_3 * 9) + T_TABLE[topology as usize]
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub struct BVH4<'a> {
|
|
||||||
root: Option<&'a BVH4Node<'a>>,
|
|
||||||
depth: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
enum BVH4Node<'a> {
|
|
||||||
// Internal {
|
|
||||||
// bounds: &'a [BBox4],
|
|
||||||
// children: [&'a BVH4Node<'a>; 4],
|
|
||||||
// children_count: u8,
|
|
||||||
// traversal_code: u8,
|
|
||||||
// },
|
|
||||||
Internal {
|
|
||||||
bounds: &'a [BBox],
|
|
||||||
children: (&'a BVH4Node<'a>, &'a BVH4Node<'a>),
|
|
||||||
split_axis: u8,
|
|
||||||
},
|
|
||||||
|
|
||||||
Leaf {
|
|
||||||
bounds: &'a [BBox],
|
|
||||||
object_range: (usize, usize),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> BVH4<'a> {
|
|
||||||
pub fn from_objects<'b, T, F>(arena: &'a MemArena,
|
|
||||||
objects: &mut [T],
|
|
||||||
objects_per_leaf: usize,
|
|
||||||
bounder: F)
|
|
||||||
-> BVH4<'a>
|
|
||||||
where F: 'b + Fn(&T) -> &'b [BBox]
|
|
||||||
{
|
|
||||||
if objects.len() == 0 {
|
|
||||||
BVH4 {
|
|
||||||
root: None,
|
|
||||||
depth: 0,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let base = BVHBase::from_objects(objects, objects_per_leaf, bounder);
|
|
||||||
|
|
||||||
BVH4 {
|
|
||||||
root: Some(BVH4::construct_from_base(arena, &base, base.root_node_index())),
|
|
||||||
depth: base.depth,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn tree_depth(&self) -> usize {
|
|
||||||
self.depth
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn traverse<T, F>(&self, rays: &mut [AccelRay], objects: &[T], mut obj_ray_test: F)
|
|
||||||
where F: FnMut(&T, &mut [AccelRay])
|
|
||||||
{
|
|
||||||
match self.root {
|
|
||||||
None => {}
|
|
||||||
|
|
||||||
Some(root) => {
|
|
||||||
// +2 of max depth for root and last child
|
|
||||||
let mut node_stack = [root; BVH_MAX_DEPTH + 2];
|
|
||||||
let mut ray_i_stack = [rays.len(); BVH_MAX_DEPTH + 2];
|
|
||||||
let mut stack_ptr = 1;
|
|
||||||
|
|
||||||
while stack_ptr > 0 {
|
|
||||||
match node_stack[stack_ptr] {
|
|
||||||
&BVH4Node::Internal { bounds, children, split_axis } => {
|
|
||||||
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| {
|
|
||||||
(!r.is_done()) && lerp_slice(bounds, r.time).intersect_accel_ray(r)
|
|
||||||
});
|
|
||||||
if part > 0 {
|
|
||||||
node_stack[stack_ptr] = children.0;
|
|
||||||
node_stack[stack_ptr + 1] = children.1;
|
|
||||||
ray_i_stack[stack_ptr] = part;
|
|
||||||
ray_i_stack[stack_ptr + 1] = part;
|
|
||||||
if rays[0].dir_inv.get_n(split_axis as usize).is_sign_positive() {
|
|
||||||
node_stack.swap(stack_ptr, stack_ptr + 1);
|
|
||||||
}
|
|
||||||
stack_ptr += 1;
|
|
||||||
} else {
|
|
||||||
stack_ptr -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&BVH4Node::Leaf { bounds, object_range } => {
|
|
||||||
let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| {
|
|
||||||
(!r.is_done()) && lerp_slice(bounds, r.time).intersect_accel_ray(r)
|
|
||||||
});
|
|
||||||
if part > 0 {
|
|
||||||
for obj in &objects[object_range.0..object_range.1] {
|
|
||||||
obj_ray_test(obj, &mut rays[..part]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stack_ptr -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn construct_from_base(arena: &'a MemArena,
|
|
||||||
base: &BVHBase,
|
|
||||||
node_index: usize)
|
|
||||||
-> &'a mut BVH4Node<'a> {
|
|
||||||
match &base.nodes[node_index] {
|
|
||||||
&BVHBaseNode::Internal { bounds_range, children_indices, split_axis } => {
|
|
||||||
let mut node = unsafe { arena.alloc_uninitialized::<BVH4Node>() };
|
|
||||||
|
|
||||||
let bounds = arena.copy_slice(&base.bounds[bounds_range.0..bounds_range.1]);
|
|
||||||
let child1 = BVH4::construct_from_base(arena, base, children_indices.0);
|
|
||||||
let child2 = BVH4::construct_from_base(arena, base, children_indices.1);
|
|
||||||
|
|
||||||
*node = BVH4Node::Internal {
|
|
||||||
bounds: bounds,
|
|
||||||
children: (child1, child2),
|
|
||||||
split_axis: split_axis,
|
|
||||||
};
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
&BVHBaseNode::Leaf { bounds_range, object_range } => {
|
|
||||||
let mut node = unsafe { arena.alloc_uninitialized::<BVH4Node>() };
|
|
||||||
let bounds = arena.copy_slice(&base.bounds[bounds_range.0..bounds_range.1]);
|
|
||||||
|
|
||||||
*node = BVH4Node::Leaf {
|
|
||||||
bounds: bounds,
|
|
||||||
object_range: object_range,
|
|
||||||
};
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
static ref DEGENERATE_BOUNDS: [BBox; 1] = [BBox::new()];
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Boundable for BVH4<'a> {
|
|
||||||
fn bounds<'b>(&'b self) -> &'b [BBox] {
|
|
||||||
match self.root {
|
|
||||||
None => &DEGENERATE_BOUNDS[..],
|
|
||||||
Some(root) => {
|
|
||||||
match root {
|
|
||||||
&BVH4Node::Internal { bounds, .. } => bounds,
|
|
||||||
|
|
||||||
&BVH4Node::Leaf { bounds, .. } => bounds,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -33,6 +33,15 @@ pub enum BVHBaseNode {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BVHBaseNode {
|
||||||
|
pub fn bounds_range(&self) -> (usize, usize) {
|
||||||
|
match self {
|
||||||
|
&BVHBaseNode::Internal { bounds_range, .. } => bounds_range,
|
||||||
|
&BVHBaseNode::Leaf { bounds_range, .. } => bounds_range,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl BVHBase {
|
impl BVHBase {
|
||||||
fn new() -> BVHBase {
|
fn new() -> BVHBase {
|
||||||
BVHBase {
|
BVHBase {
|
||||||
|
|
|
@ -12,6 +12,10 @@ impl BitStack128 {
|
||||||
BitStack128 { data: (0, 0) }
|
BitStack128 { data: (0, 0) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_with_1() -> BitStack128 {
|
||||||
|
BitStack128 { data: (1, 0) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Push a bit onto the top of the stack.
|
/// Push a bit onto the top of the stack.
|
||||||
pub fn push(&mut self, value: bool) {
|
pub fn push(&mut self, value: bool) {
|
||||||
debug_assert!((self.data.1 >> (size_of::<u64>() - 1)) == 0); // Verify no stack overflow
|
debug_assert!((self.data.1 >> (size_of::<u64>() - 1)) == 0); // Verify no stack overflow
|
||||||
|
@ -57,6 +61,16 @@ impl BitStack128 {
|
||||||
return b;
|
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.
|
/// Read the top bit of the stack without popping it.
|
||||||
pub fn peek(&self) -> bool {
|
pub fn peek(&self) -> bool {
|
||||||
(self.data.0 & 1) != 0
|
(self.data.0 & 1) != 0
|
||||||
|
|
|
@ -17,7 +17,6 @@ pub struct Ray {
|
||||||
pub max_t: f32,
|
pub max_t: f32,
|
||||||
pub time: f32,
|
pub time: f32,
|
||||||
pub flags: u32,
|
pub flags: u32,
|
||||||
pub trav_stack: BitStack128,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ray {
|
impl Ray {
|
||||||
|
@ -29,7 +28,6 @@ impl Ray {
|
||||||
max_t: std::f32::INFINITY,
|
max_t: std::f32::INFINITY,
|
||||||
time: time,
|
time: time,
|
||||||
flags: 0,
|
flags: 0,
|
||||||
trav_stack: BitStack128::new(),
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ray {
|
Ray {
|
||||||
|
@ -38,7 +36,6 @@ impl Ray {
|
||||||
max_t: 1.0,
|
max_t: 1.0,
|
||||||
time: time,
|
time: time,
|
||||||
flags: OCCLUSION_FLAG,
|
flags: OCCLUSION_FLAG,
|
||||||
trav_stack: BitStack128::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +59,7 @@ pub struct AccelRay {
|
||||||
pub time: f32,
|
pub time: f32,
|
||||||
pub flags: u32,
|
pub flags: u32,
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
|
pub trav_stack: BitStack128,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AccelRay {
|
impl AccelRay {
|
||||||
|
@ -73,6 +71,7 @@ impl AccelRay {
|
||||||
time: ray.time,
|
time: ray.time,
|
||||||
flags: ray.flags,
|
flags: ray.flags,
|
||||||
id: id,
|
id: id,
|
||||||
|
trav_stack: BitStack128::new_with_1(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user