complete voxel octtree
This commit is contained in:
parent
463e41ac56
commit
984a9768d2
176
src/oct_tree.rs
176
src/oct_tree.rs
|
@ -26,40 +26,51 @@ struct Path {
|
|||
length: usize,
|
||||
}
|
||||
|
||||
fn to_vec3(path: &Path, center: Vec3, size: usize) -> Vec3 {
|
||||
let mut iter = (center, size);
|
||||
for i in 0..path.length {
|
||||
iter = sub_region(
|
||||
iter.0,
|
||||
iter.1,
|
||||
get_pindex(&path, i.try_into().unwrap()).try_into().unwrap(),
|
||||
);
|
||||
impl Path {
|
||||
pub fn pop(&mut self) -> usize {
|
||||
self.length -= 1;
|
||||
return self.get_index(self.length);
|
||||
}
|
||||
pub fn parent(&self) -> Path {
|
||||
let mut duplicate = self.clone();
|
||||
duplicate.set_index(self.length - 1, 0);
|
||||
duplicate.length = duplicate.length - 1;
|
||||
return duplicate;
|
||||
}
|
||||
pub fn get_index(&self, index: usize) -> usize {
|
||||
if self.length < index {
|
||||
panic!("in too deep!");
|
||||
}
|
||||
let shift_amount = index as u64 * 3;
|
||||
let unshifted_result = self.packed >> shift_amount;
|
||||
(unshifted_result & 7) as usize
|
||||
}
|
||||
pub fn set_index(&mut self, index: usize, value: usize) {
|
||||
if value > 7 {
|
||||
panic!("cannot set to more than 7!");
|
||||
}
|
||||
if index + 1 > self.length {
|
||||
self.length = index + 1;
|
||||
}
|
||||
let shift_amount = index as u64 * 3;
|
||||
let shifted_value = (value as u64) << shift_amount;
|
||||
let shift_mask = 7_u64 << shift_amount;
|
||||
let shift_mask = !shift_mask;
|
||||
self.packed = self.packed & shift_mask;
|
||||
self.packed = self.packed | shifted_value;
|
||||
}
|
||||
return iter.0;
|
||||
}
|
||||
|
||||
fn get_pindex(path: &Path, index: usize) -> usize {
|
||||
if path.length < index {
|
||||
panic!("in too deep!");
|
||||
pub fn to_vec3(&self, center: Vec3, size: usize) -> Vec3 {
|
||||
let mut iter = (center, size);
|
||||
for i in 0..self.length {
|
||||
iter = sub_region(
|
||||
iter.0,
|
||||
iter.1,
|
||||
self.get_index(i.try_into().unwrap()).try_into().unwrap(),
|
||||
);
|
||||
}
|
||||
return iter.0;
|
||||
}
|
||||
let shift_amount = index as u64 * 3;
|
||||
let unshifted_result = path.packed >> shift_amount;
|
||||
(unshifted_result & 7) as usize
|
||||
}
|
||||
|
||||
fn set_pindex(path: &mut Path, index: usize, value: usize) {
|
||||
if value > 7 {
|
||||
panic!("cannot set to more than 7!");
|
||||
}
|
||||
if index + 1 > path.length {
|
||||
path.length = index + 1;
|
||||
}
|
||||
let shift_amount = index as u64 * 3;
|
||||
let shifted_value = (value as u64) << shift_amount;
|
||||
let shift_mask = 7_u64 << shift_amount;
|
||||
let shift_mask = !shift_mask;
|
||||
path.packed = path.packed & shift_mask;
|
||||
path.packed = path.packed | shifted_value;
|
||||
}
|
||||
|
||||
impl<T: Clone> OctTree<T> {
|
||||
|
@ -71,7 +82,78 @@ impl<T: Clone> OctTree<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn remove_voxel(&mut self, location: Vec3) {}
|
||||
pub fn remove_voxel(&mut self, location: Vec3) -> usize {
|
||||
let result = self.voxel_at_location(location);
|
||||
if result.is_some() {
|
||||
let mut count: usize = 0;
|
||||
Self::prune(&mut self.root, result.unwrap().1, &mut count);
|
||||
self.trim(&mut count);
|
||||
return count;
|
||||
} else {
|
||||
return 0; // no culled leaves
|
||||
}
|
||||
}
|
||||
fn has_only_one_element(subject: &mut [TreeNode<T>; 8]) -> Option<usize> {
|
||||
// returns target location of the element
|
||||
let mut res = Option::<usize>::None;
|
||||
for element in subject.iter().enumerate() {
|
||||
match element.1 {
|
||||
TreeNode::Branch(_) | TreeNode::Leaf(_) => {
|
||||
if res.is_none() {
|
||||
res = Some(element.0);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
fn trim(&mut self, removal_count: &mut usize) {
|
||||
let count;
|
||||
let mut extracted: &mut TreeNode<T> = &mut TreeNode::None;
|
||||
match &mut self.root {
|
||||
TreeNode::Branch(a) => {
|
||||
let contents = a.as_mut();
|
||||
count = Self::has_only_one_element(contents);
|
||||
if count.is_some() {
|
||||
extracted = &mut contents[count.unwrap()];
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
if count.is_some() {
|
||||
self.root = extracted.clone();
|
||||
let next_region =
|
||||
constants::sub_region(self.center, self.size, count.unwrap().try_into().unwrap());
|
||||
self.center = next_region.0;
|
||||
self.size = next_region.1;
|
||||
*removal_count += 1;
|
||||
self.trim(removal_count);
|
||||
}
|
||||
}
|
||||
fn prune(element: &mut TreeNode<T>, mut target: Path, count: &mut usize) {
|
||||
match element {
|
||||
TreeNode::Branch(a) => {
|
||||
let i = target.pop();
|
||||
let ar: &mut [TreeNode<T>; 8] = a.as_mut();
|
||||
Self::prune(&mut ar[i], target, count);
|
||||
|
||||
if ar.iter().all(|x| matches!(x, TreeNode::None)) {
|
||||
*element = TreeNode::None;
|
||||
*count += 1;
|
||||
}
|
||||
}
|
||||
TreeNode::Leaf(_) => {
|
||||
if target.length == 0 {
|
||||
*element = TreeNode::None;
|
||||
*count += 1;
|
||||
}
|
||||
}
|
||||
TreeNode::None => return,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_voxel_at_path(&mut self, path: &Path, value: T) -> bool {
|
||||
// return value is whether it was successful
|
||||
|
@ -88,7 +170,7 @@ impl<T: Clone> OctTree<T> {
|
|||
}
|
||||
}
|
||||
for i in 0..path.length {
|
||||
let region = get_pindex(path, i) as usize;
|
||||
let region = path.get_index(i) as usize;
|
||||
match iter {
|
||||
TreeNode::Branch(branch) => {
|
||||
let arr = branch.as_mut();
|
||||
|
@ -178,7 +260,7 @@ impl<T: Clone> OctTree<T> {
|
|||
while rc_size > 0 {
|
||||
if search_direction != -1 {
|
||||
let pindex = path.length;
|
||||
set_pindex(&mut path, pindex, search_direction as usize);
|
||||
path.set_index(pindex, search_direction as usize);
|
||||
}
|
||||
println!("{rc_center}, size {rc_size}, region {search_direction}");
|
||||
match rc_loc {
|
||||
|
@ -317,7 +399,7 @@ impl<T: Clone> OctTree<T> {
|
|||
for (index, node) in branch.iter().enumerate() {
|
||||
let (subpos, subsize) = sub_region(location, size, index as i32);
|
||||
let mut path_next = path.clone();
|
||||
set_pindex(&mut path_next, path.length, index);
|
||||
path_next.set_index(path.length, index);
|
||||
Self::visitor(node, subpos, subsize, result, path_next);
|
||||
}
|
||||
}
|
||||
|
@ -344,7 +426,7 @@ impl<T: Clone> OctTree<T> {
|
|||
}
|
||||
}
|
||||
for i in 0..path.length {
|
||||
let region = get_pindex(path, i) as usize;
|
||||
let region = path.get_index(i) as usize;
|
||||
match iter {
|
||||
TreeNode::Branch(branch) => {
|
||||
let arr = branch.as_ref();
|
||||
|
@ -378,7 +460,7 @@ impl<T: Clone> OctTree<T> {
|
|||
while rc_size > 1 {
|
||||
if search_direction != -1 {
|
||||
let pindex = path_result.length;
|
||||
set_pindex(&mut path_result, pindex, search_direction as usize);
|
||||
path_result.set_index(pindex, search_direction as usize);
|
||||
}
|
||||
println!("{rc_center}, size {rc_size}, region {search_direction}");
|
||||
match rc_loc {
|
||||
|
@ -537,11 +619,11 @@ pub fn test_octtree() {
|
|||
#[test]
|
||||
pub fn test_path() {
|
||||
let mut path_test: Path = Default::default();
|
||||
set_pindex(&mut path_test, 0, 6);
|
||||
set_pindex(&mut path_test, 7, 4);
|
||||
assert_eq!(get_pindex(&path_test, 7), 4);
|
||||
path_test.set_index(0, 6);
|
||||
path_test.set_index(7, 4);
|
||||
assert_eq!(path_test.get_index(7), 4);
|
||||
println!("{:#?}", dbg!(path_test.clone()));
|
||||
assert_eq!(get_pindex(&path_test, 0), 6);
|
||||
assert_eq!(path_test.get_index(0), 6);
|
||||
println!("{:#?}", dbg!(path_test.clone()));
|
||||
}
|
||||
#[test]
|
||||
|
@ -554,7 +636,7 @@ pub fn test_path_return() {
|
|||
println!("{:#?}", dbg!(res0.clone()));
|
||||
println!("{:064b}", res0.packed.clone());
|
||||
for i in 0..res0.length {
|
||||
println!("{}", get_pindex(&res0, i));
|
||||
println!("{}", res0.get_index(i));
|
||||
}
|
||||
let res1 = octtwee.voxel_at_location(Vec3::new(190., 15., -100.));
|
||||
match res1.clone() {
|
||||
|
@ -562,7 +644,7 @@ pub fn test_path_return() {
|
|||
assert_eq!(res0.packed, res1.clone().unwrap().1.packed); //internal path consistency with both functions
|
||||
assert_eq!(
|
||||
Vec3::new(190., 15., -100.),
|
||||
to_vec3(&c, octtwee.center, octtwee.size)
|
||||
c.to_vec3(octtwee.center, octtwee.size)
|
||||
);
|
||||
assert_eq!(res1.clone().unwrap().0, "test".to_string());
|
||||
}
|
||||
|
@ -628,6 +710,14 @@ pub fn test_collect() {
|
|||
)
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
pub fn test_removal() {
|
||||
let mut test_tree = OctTree::new(Vec3::ZERO, 0);
|
||||
test_tree.set_voxel_at_location(Vec3::splat(10.), 5);
|
||||
test_tree.remove_voxel(Vec3::ZERO);
|
||||
assert_eq!(test_tree.size, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
use rand::Rng;
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue