Add generic BinaryTree struct and use in BoundingVolumeHierarchy

No change in runtime, as expected.
This commit is contained in:
Matthew Gordon 2020-07-04 22:09:44 -04:00
parent 5aad1242b3
commit 231be6a1a5
3 changed files with 33 additions and 36 deletions

View File

@ -2,6 +2,7 @@ use super::{
Aggregate, BoundingBox, HasBoundingBox, Intersect, IntersectP, IntersectionInfo, Primitive, Ray, Aggregate, BoundingBox, HasBoundingBox, Intersect, IntersectP, IntersectionInfo, Primitive, Ray,
}; };
use crate::util::binary_tree::BinaryTree;
use crate::util::morton::morton_order_value_3d; use crate::util::morton::morton_order_value_3d;
use crate::util::normalizer::Point3Normalizer; use crate::util::normalizer::Point3Normalizer;
use crate::Real; use crate::Real;
@ -18,18 +19,8 @@ use std::mem::swap;
/// Each node knows the overall bounds of all it's children, which means that a ray that /// Each node knows the overall bounds of all it's children, which means that a ray that
/// doesn't intersect the [BoundingBox](BoundingBox) of the node doesn't intersect any of /// doesn't intersect the [BoundingBox](BoundingBox) of the node doesn't intersect any of
/// the primitives stored in it's children. /// the primitives stored in it's children.
pub enum BoundingVolumeHierarchy<T: Real> { pub type BoundingVolumeHierarchy<T: Real> =
Node { BinaryTree<BoundingBox<T>, (BoundingBox<T>, Box<dyn Primitive<T>>)>;
bounds: BoundingBox<T>,
left: Box<BoundingVolumeHierarchy<T>>,
right: Box<BoundingVolumeHierarchy<T>>,
},
Leaf {
bounds: BoundingBox<T>,
primitive: Box<dyn Primitive<T>>,
},
None,
}
fn centre<T: Real>(bounds: &BoundingBox<T>) -> Point3<T> { fn centre<T: Real>(bounds: &BoundingBox<T>) -> Point3<T> {
let two = convert(2.0); let two = convert(2.0);
@ -74,8 +65,8 @@ impl<T: Real> BoundingVolumeHierarchy<T> {
let left = Box::new(Self::from_sorted_nodes(&mut nodes[..midpoint])); let left = Box::new(Self::from_sorted_nodes(&mut nodes[..midpoint]));
let right = Box::new(Self::from_sorted_nodes(&mut nodes[midpoint..])); let right = Box::new(Self::from_sorted_nodes(&mut nodes[midpoint..]));
let bounds = left.get_bounds().union(&right.get_bounds()); let bounds = left.get_bounds().union(&right.get_bounds());
BoundingVolumeHierarchy::Node { BoundingVolumeHierarchy::Branch {
bounds, value: bounds,
left, left,
right, right,
} }
@ -84,7 +75,9 @@ impl<T: Real> BoundingVolumeHierarchy<T> {
let mut primitive = None; let mut primitive = None;
swap(primitive_src, &mut primitive); swap(primitive_src, &mut primitive);
let primitive = primitive.unwrap(); let primitive = primitive.unwrap();
BoundingVolumeHierarchy::Leaf { bounds, primitive } BoundingVolumeHierarchy::Leaf {
value: (bounds, primitive),
}
} else { } else {
BoundingVolumeHierarchy::None BoundingVolumeHierarchy::None
} }
@ -92,30 +85,24 @@ impl<T: Real> BoundingVolumeHierarchy<T> {
pub fn get_bounds(&self) -> BoundingBox<T> { pub fn get_bounds(&self) -> BoundingBox<T> {
match self { match self {
BoundingVolumeHierarchy::Node { BoundingVolumeHierarchy::Branch {
bounds, value,
left: _, left: _,
right: _, right: _,
} => *bounds, } => *value,
BoundingVolumeHierarchy::Leaf { BoundingVolumeHierarchy::Leaf { value: (bounds, _) } => *bounds,
bounds,
primitive: _,
} => *bounds,
BoundingVolumeHierarchy::None => BoundingBox::empty(), BoundingVolumeHierarchy::None => BoundingBox::empty(),
} }
} }
pub fn count_leaves(&self) -> usize { pub fn count_leaves(&self) -> usize {
match self { match self {
Self::Node { Self::Branch {
bounds: _, value: _,
left, left,
right, right,
} => right.count_leaves() + left.count_leaves(), } => right.count_leaves() + left.count_leaves(),
Self::Leaf { Self::Leaf { value: _ } => 1,
bounds: _,
primitive: _,
} => 1,
Self::None => 0, Self::None => 0,
} }
} }
@ -142,8 +129,8 @@ fn closest_intersection<T: Real>(
impl<T: Real> Intersect<T> for BoundingVolumeHierarchy<T> { impl<T: Real> Intersect<T> for BoundingVolumeHierarchy<T> {
fn intersect<'a>(&'a self, ray: &Ray<T>) -> Option<IntersectionInfo<T>> { fn intersect<'a>(&'a self, ray: &Ray<T>) -> Option<IntersectionInfo<T>> {
match self { match self {
Self::Node { Self::Branch {
bounds, value: bounds,
left, left,
right, right,
} => { } => {
@ -154,8 +141,7 @@ impl<T: Real> Intersect<T> for BoundingVolumeHierarchy<T> {
} }
} }
Self::Leaf { Self::Leaf {
bounds: _, value: (_, primitive),
primitive,
} => primitive.intersect(ray), } => primitive.intersect(ray),
Self::None => None, Self::None => None,
} }
@ -194,8 +180,8 @@ impl<'a, T: Real> Iterator for FilterIterator<'a, T> {
//let mut result = Option::None; //let mut result = Option::None;
while let Some(next_subtree) = self.unsearched_subtrees.pop() { while let Some(next_subtree) = self.unsearched_subtrees.pop() {
match next_subtree { match next_subtree {
BoundingVolumeHierarchy::Node { BoundingVolumeHierarchy::Branch {
bounds, value: bounds,
left, left,
right, right,
} => { } => {
@ -205,8 +191,7 @@ impl<'a, T: Real> Iterator for FilterIterator<'a, T> {
} }
} }
BoundingVolumeHierarchy::Leaf { BoundingVolumeHierarchy::Leaf {
bounds, value: (bounds, ref primitive),
ref primitive,
} => { } => {
if (self.predicate)(bounds) { if (self.predicate)(bounds) {
return Some(&**primitive); return Some(&**primitive);

11
src/util/binary_tree.rs Normal file
View File

@ -0,0 +1,11 @@
pub enum BinaryTree<BranchValue, LeafValue> {
Branch {
value: BranchValue,
left: Box<Self>,
right: Box<Self>,
},
Leaf {
value: LeafValue,
},
None,
}

View File

@ -3,6 +3,7 @@ pub use interval::Interval;
pub mod algebra_utils; pub mod algebra_utils;
pub mod axis_aligned_bounding_box; pub mod axis_aligned_bounding_box;
pub mod binary_tree;
pub mod morton; pub mod morton;
pub mod normalizer; pub mod normalizer;
mod tile_iterator; mod tile_iterator;