//! A Dynamic Bounding Volume Tree. use std::cell::RefCell; use std::rc::Rc; use std::ptr; use std::mem; use utils::data::owned_allocation_cache::OwnedAllocationCache; use na::Translation; use na; use bounding_volume::BoundingVolume; use partitioning::bvt_visitor::BVTVisitor; use math::{Point, Vector}; #[derive(RustcEncodable, RustcDecodable)] enum UpdateState { NeedsShrink, UpToDate } type Cache
= OwnedAllocationCache {
cache: Cache ,
tree: Option DBVT {
/// Creates a new Dynamic Bounding Volume Tree.
pub fn new() -> DBVT {
DBVT {
cache: OwnedAllocationCache::new(),
tree: None,
len: 0
}
}
}
impl DBVT
where P: Point,
BV: 'static + BoundingVolume< {
Internal(Box {
/// The bounding volume of this node. It always encloses both its children bounding volumes.
bounding_volume: BV,
/// The center of this node bounding volume.
center: P,
/// This node left child.
left: DBVTNode ,
/// This node right child.
right: DBVTNode ,
/// This node parent.
parent: *mut DBVTInternal ,
state: UpdateState
}
impl {
/// Creates a new internal node.
fn new(bounding_volume: BV,
parent: *mut DBVTInternal ,
left: DBVTNode ,
right: DBVTNode )
-> DBVTInternal {
DBVTInternal {
center: na::origin:: () + bounding_volume.translation(),
bounding_volume: bounding_volume,
left: left,
right: right,
parent: parent,
state: UpdateState::UpToDate
}
}
}
#[derive(Clone)]
/// State of a leaf.
enum DBVTLeafState {
/// This leaf is the root of a tree.
Root,
/// This leaf is the right child of another node.
RightChildOf(*mut DBVTInternal ),
/// This leaf is the left child of another node.
LeftChildOf(*mut DBVTInternal ),
/// This leaf is detached from any tree.
Detached
}
impl DBVTLeafState {
/// Indicates whether this leaf is the root.
#[inline]
pub fn is_root(&self) -> bool {
match *self {
DBVTLeafState::Root => true,
_ => false
}
}
/// Indicates whether this leaf is detached.
#[inline]
pub fn is_detached(&self) -> bool {
match *self {
DBVTLeafState::Detached => true,
_ => false
}
}
/// Returns a pointer to this leaf parent and `true` if it is the left child.
#[inline]
fn unwrap(self) -> (bool, *mut DBVTInternal ) {
match self {
DBVTLeafState::RightChildOf(p) => (false, p),
DBVTLeafState::LeftChildOf(p) => (true, p),
_ => panic!("Attempting to unwrap a root or detached node.")
}
}
}
/// Leaf of a Dynamic Bounding Volume Tree.
#[derive(Clone)]
pub struct DBVTLeaf {
/// The bounding volume of this node.
pub bounding_volume: BV,
/// The center of this node bounding volume.
pub center: P,
/// An user-defined object.
pub object: B,
/// This node parent.
parent: DBVTLeafState
}
impl DBVTNode {
fn take_internal(self) -> Box {
let mut res = DBVTNode::Invalid;
mem::swap(&mut res, self);
res
}
}
impl DBVTInternal {
fn is_right_internal_node(&self, r: &mut DBVTInternal ) -> bool
{
match self.right {
DBVTNode::Internal(ref i) => &**i as *const DBVTInternal == &*r as *const DBVTInternal ,
_ => false
}
}
}
impl {
/// Creates a new leaf.
pub fn new(bounding_volume: BV, object: B) -> DBVTLeaf {
DBVTLeaf {
center: na::origin:: () + bounding_volume.translation(),
bounding_volume: bounding_volume,
object: object,
parent: DBVTLeafState::Detached
}
}
/// Tests if this node is the root.
pub fn is_root(&self) -> bool {
self.parent.is_root()
}
/// Tests if this node has no parent.
pub fn is_detached(&self) -> bool {
self.parent.is_detached()
}
/// Removes this leaf from the tree.
///
/// Returns the new root of the tree.
///
/// # Arguments:
/// * `curr_root`: current root of the tree.
fn unlink(&mut self,
cache: &mut Cache ,
curr_root: DBVTNode ) -> Option DBVTNode
where P: Point,
BV: 'static + BoundingVolume< DBVTInternal
where P: Point,
BV: 'static + Translation DBVTNode
where P: Point,
BV: 'static + Translation ,
to_insert: Rc ;
unsafe {
(*parent).bounding_volume.merge(&pto_insert.bounding_volume);
// iteratively go to the leaves
let mut curr;
let mut left;
if (*parent).is_closest_to_left(&pto_insert.center) {
curr = &mut (*parent).left as *mut DBVTNode ;
left = true;
}
else {
curr = &mut (*parent).right as *mut DBVTNode ;
left = false;
}
loop {
match *curr {
DBVTNode::Internal(ref mut ci) => {
// FIXME: we could avoid the systematic merge
ci.bounding_volume.merge(&pto_insert.bounding_volume);
if ci.is_closest_to_left(&pto_insert.center) { // FIXME
curr = &mut ci.left as *mut DBVTNode ;
left = true;
}
else {
curr = &mut ci.right as *mut DBVTNode ;
left = false;
}
parent = &mut **ci as *mut DBVTInternal ;
},
DBVTNode::Leaf(ref l) => {
let mut bl = (**l).borrow_mut();
let pl = &mut *bl;
let mut internal = cache.alloc(DBVTInternal::new(
pl.bounding_volume.merged(&pto_insert.bounding_volume),
parent,
DBVTNode::Leaf(l.clone()),
DBVTNode::Leaf(to_insert.clone())));
pl.parent = DBVTLeafState::LeftChildOf(&mut *internal as *mut DBVTInternal );
pto_insert.parent =
DBVTLeafState::RightChildOf(&mut *internal as *mut DBVTInternal );
if left {
(*parent).left = DBVTNode::Internal(internal)
}
else {
(*parent).right = DBVTNode::Internal(internal)
}
break;
},
DBVTNode::Invalid => unreachable!()
}
}
}
mut_internal
},
DBVTNode::Leaf(l) => {
let cl = l.clone();
let mut bl = (*cl).borrow_mut();
let pl = &mut *bl;
// create the root
let mut root = cache.alloc(DBVTInternal::new(
pl.bounding_volume.merged(&pto_insert.bounding_volume),
ptr::null_mut(),
DBVTNode::Leaf(l),
DBVTNode::Leaf(to_insert.clone())));
pl.parent = DBVTLeafState::LeftChildOf(&mut *root as *mut DBVTInternal );
pto_insert.parent = DBVTLeafState::RightChildOf(&mut *root as *mut DBVTInternal );
root
},
DBVTNode::Invalid => unreachable!()
}
}
fn visit