all but remove_voxel done for oct-tree structure handling. remaining: remove_voxel() and rendering code

This commit is contained in:
Lillian Vixe 2024-02-26 13:48:29 -08:00
parent 8567b102a8
commit 463e41ac56

View file

@ -20,7 +20,7 @@ struct OctTree<T> {
root: TreeNode<T>,
}
#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
struct Path {
packed: u64,
length: usize,
@ -71,6 +71,8 @@ impl<T: Clone> OctTree<T> {
}
}
pub fn remove_voxel(&mut self, location: Vec3) {}
pub fn set_voxel_at_path(&mut self, path: &Path, value: T) -> bool {
// return value is whether it was successful
let mut iter = &mut self.root;
@ -239,6 +241,95 @@ impl<T: Clone> OctTree<T> {
return Default::default();
}
pub fn collect_voxels(&self) -> Vec<(Path, Vec3, T)> {
let mut result = Vec::new();
Self::visitor(
&self.root,
self.center,
self.size,
&mut result,
Default::default(),
);
return result;
}
pub fn bounding_box(&self) -> Option<(Vec3, Vec3)> {
//center, size
let contents = self.collect_voxels();
let mut min: Option<Vec3> = None;
let mut max: Option<Vec3> = None;
for each in contents.iter() {
if min.is_none() {
min = Some(each.1);
} else {
let mut cont = min.unwrap();
if cont.x > each.1.x {
cont.x = each.1.x;
min = Some(cont);
}
if cont.y > each.1.y {
cont.y = each.1.y;
min = Some(cont);
}
if cont.z > each.1.z {
cont.z = each.1.z;
min = Some(cont);
}
}
if max.is_none() {
max = Some(each.1);
} else {
let mut cont: Vec3 = max.unwrap();
if cont.x < each.1.x {
cont.x = each.1.x;
max = Some(cont);
}
if cont.y < each.1.y {
cont.y = each.1.y;
max = Some(cont);
}
if cont.z < each.1.z {
cont.z = each.1.z;
max = Some(cont);
}
}
}
if max.is_none() && min.is_none() {
return None;
} else {
let center = min.unwrap() + max.unwrap();
let center = center / 2.;
let size = max.unwrap() - min.unwrap() + Vec3::ONE; // + 1 accounts for size of voxels themself, one half a voxel on each side
return Some((center, size));
}
}
fn visitor(
subject: &TreeNode<T>,
location: Vec3,
size: usize,
result: &mut Vec<(Path, Vec3, T)>,
path: Path,
) {
match subject {
TreeNode::Branch(branch) => {
let branch = branch.as_ref();
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);
Self::visitor(node, subpos, subsize, result, path_next);
}
}
TreeNode::Leaf(value) => {
result.push((path, location, value.clone()));
}
TreeNode::None => {
return;
}
}
}
pub fn voxel_at_path(&self, path: &Path) -> Option<T> {
// return value is whether it was successful
let mut iter = &self.root;
@ -321,8 +412,6 @@ impl<T: Clone> OctTree<T> {
}
None
}
pub fn remove_voxel(&mut self, location: Vec3) {}
}
pub fn bounds_contains(center: Vec3, size: usize, subject: Vec3) -> bool {
@ -469,7 +558,7 @@ pub fn test_path_return() {
}
let res1 = octtwee.voxel_at_location(Vec3::new(190., 15., -100.));
match res1.clone() {
Some((b, c)) => {
Some((_, c)) => {
assert_eq!(res0.packed, res1.clone().unwrap().1.packed); //internal path consistency with both functions
assert_eq!(
Vec3::new(190., 15., -100.),
@ -500,6 +589,45 @@ pub fn test_path_return() {
}
}
}
#[test]
pub fn test_bounding() {
let mut octtree = OctTree::<()>::new(Vec3::ZERO, ());
octtree.set_voxel_at_location(Vec3::splat(10.), ());
assert_eq!(
octtree.bounding_box().unwrap(),
(Vec3::splat(5.), Vec3::splat(11.))
);
}
#[test]
pub fn test_collect() {
let zeropos = Vec3::ZERO;
let otherpos = Vec3::new(10., -5., 1.);
let mut octtree = OctTree::<usize>::new(zeropos, 0);
octtree.set_voxel_at_location(otherpos, 27);
let x = octtree.collect_voxels();
assert_eq!(
x[0],
(
Path {
packed: 1170,
length: 4,
},
Vec3::ZERO,
0
)
);
assert_eq!(
x[1],
(
Path {
packed: 902,
length: 4,
},
otherpos,
27
)
);
}
/*
use rand::Rng;
#[test]