complete voxel octtree

This commit is contained in:
Lillian Vixe 2024-02-29 11:44:10 -08:00
parent 463e41ac56
commit 984a9768d2

View file

@ -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]