path based retrieval and setting

This commit is contained in:
Lillian Vixe 2024-02-25 09:40:16 -08:00
parent 4e9ca044fb
commit 8567b102a8

View file

@ -26,6 +26,18 @@ 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(),
);
}
return iter.0;
}
fn get_pindex(path: &Path, index: usize) -> usize {
if path.length < index {
panic!("in too deep!");
@ -39,7 +51,7 @@ fn set_pindex(path: &mut Path, index: usize, value: usize) {
if value > 7 {
panic!("cannot set to more than 7!");
}
if index > path.length {
if index + 1 > path.length {
path.length = index + 1;
}
let shift_amount = index as u64 * 3;
@ -59,17 +71,55 @@ impl<T: Clone> OctTree<T> {
}
}
pub fn set_voxel(&mut self, location: Vec3, value: T) {
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;
if path.length == 0 {
match &mut self.root {
TreeNode::Leaf(nvalue) => {
*nvalue = value;
return true;
}
_ => {
return false;
}
}
}
for i in 0..path.length {
let region = get_pindex(path, i) as usize;
match iter {
TreeNode::Branch(branch) => {
let arr = branch.as_mut();
iter = &mut arr[region];
}
_ => {
return false;
}
}
}
match &mut iter {
TreeNode::Leaf(nvalue) => {
*nvalue = value;
return true;
}
_ => {
return false;
}
}
}
pub fn set_voxel_at_location(&mut self, location: Vec3, value: T) -> Path {
// if the tree is empty, we want to fall out immediately - no looping needed.
match self.root {
TreeNode::None => {
self.center = location;
self.size = 1;
self.root = TreeNode::Leaf(value);
return;
return Default::default();
}
_ => {} // continue to modify the tree structure - no easy answer yet
}
let mut path: Path = Default::default();
// if we don't already have a big enough non-empty tree, we need to branch upward till our tree contains our subject matter
if !bounds_contains(self.center, self.size, location) {
println!("building up to contain addition {location}");
@ -105,7 +155,7 @@ impl<T: Clone> OctTree<T> {
}
TreeNode::None => {
println!("something went wrong with early fall-out. shouldn't be plausible unless you're using unsafe rust.");
return;
return Default::default();
}
}
}
@ -124,6 +174,10 @@ impl<T: Clone> OctTree<T> {
println!("searching down to set {location}");
while rc_size > 0 {
if search_direction != -1 {
let pindex = path.length;
set_pindex(&mut path, pindex, search_direction as usize);
}
println!("{rc_center}, size {rc_size}, region {search_direction}");
match rc_loc {
TreeNode::Branch(region) => {
@ -138,19 +192,20 @@ impl<T: Clone> OctTree<T> {
);
let end = TreeNode::Leaf(value.clone());
*next_rc_loc = end;
return;
return path;
}
match next_rc_loc {
TreeNode::Branch(_) => {}
TreeNode::Leaf(lvalue) => {
if rc_size != 1 {
println!("tree edited to contain non-unit node size. returning instead of losing data");
return;
return Default::default();
} else {
println!(
"value set {location} within {rc_center}, {rc_size}, index {search_direction}"
);
*lvalue = value.clone();
return path;
}
}
TreeNode::None => {
@ -167,32 +222,73 @@ impl<T: Clone> OctTree<T> {
"value set {location} within {rc_center}, {rc_size}, index {search_direction}"
);
*lvalue = value;
return;
return path;
} else {
println!("tree edited to contain non-unit node size. returning instead of losing data");
return;
return Default::default();
}
}
TreeNode::None => {
println!(
"should be handled automatically before arrival at target node. returning"
);
return;
return Default::default();
}
}
}
return Default::default();
}
pub fn voxel_at_path(&self, path: &Path) -> Option<T> {
// return value is whether it was successful
let mut iter = &self.root;
if path.length == 0 {
match &self.root {
TreeNode::Leaf(nvalue) => {
return Some(nvalue.clone());
}
_ => {
return None;
}
}
}
for i in 0..path.length {
let region = get_pindex(path, i) as usize;
match iter {
TreeNode::Branch(branch) => {
let arr = branch.as_ref();
iter = &arr[region];
}
_ => {
return None;
}
}
}
match &mut iter {
TreeNode::Leaf(nvalue) => {
return Some(nvalue.clone());
}
_ => {
return None;
}
}
}
pub fn voxel_at(&self, location: Vec3) -> Option<(T, Path)> {
pub fn voxel_at_location(&self, location: Vec3) -> Option<(T, Path)> {
if bounds_contains(self.center, self.size, location) {
let mut rc_center = self.center;
let mut rc_size = self.size;
let mut path_result: Path = Default::default();
let mut search_direction = constants::to_region_id(rc_center, location);
println!("searching for {location}");
let mut rc_loc = &self.root;
while rc_size > 1 {
if search_direction != -1 {
let pindex = path_result.length;
set_pindex(&mut path_result, pindex, search_direction as usize);
}
println!("{rc_center}, size {rc_size}, region {search_direction}");
match rc_loc {
TreeNode::Branch(branch) => {
@ -215,7 +311,7 @@ impl<T: Clone> OctTree<T> {
match rc_loc {
TreeNode::Leaf(value) => {
println!("found at {rc_center}, {rc_size}");
return Some((value.clone(), Default::default()));
return Some((value.clone(), path_result));
}
_ => {
println!("Couldn't find it..");
@ -340,14 +436,14 @@ pub fn test_octtree() {
let origin = Vec3::ZERO;
let neighbor = Vec3::new(1., 1., 1.);
let mut test_oct = OctTree::<i32>::new(origin, 1);
test_oct.set_voxel(neighbor, 2);
test_oct.set_voxel_at_location(neighbor, 2);
let far_off_bullshit = Vec3::new(26., 26., 26.);
test_oct.set_voxel(far_off_bullshit, 5);
test_oct.set_voxel_at_location(far_off_bullshit, 5);
dbg!(&test_oct);
assert_eq!(test_oct.voxel_at(neighbor).unwrap().0, 2);
assert_eq!(test_oct.voxel_at(origin).unwrap().0, 1);
assert_eq!(test_oct.voxel_at(far_off_bullshit).unwrap().0, 5);
assert_eq!(test_oct.voxel_at_location(neighbor).unwrap().0, 2);
assert_eq!(test_oct.voxel_at_location(origin).unwrap().0, 1);
assert_eq!(test_oct.voxel_at_location(far_off_bullshit).unwrap().0, 5);
}
#[test]
pub fn test_path() {
@ -359,6 +455,51 @@ pub fn test_path() {
assert_eq!(get_pindex(&path_test, 0), 6);
println!("{:#?}", dbg!(path_test.clone()));
}
#[test]
pub fn test_path_return() {
let mut octtwee = OctTree::<String>::new(Vec3::ZERO, "a".to_string());
octtwee.set_voxel_at_location(Vec3::splat(1.), "test".to_string());
octtwee.set_voxel_at_location(Vec3::splat(19.), "test".to_string());
let res0 = octtwee.set_voxel_at_location(Vec3::new(190., 15., -100.), "test".to_string());
println!("{:#?}", dbg!(res0.clone()));
println!("{:064b}", res0.packed.clone());
for i in 0..res0.length {
println!("{}", get_pindex(&res0, i));
}
let res1 = octtwee.voxel_at_location(Vec3::new(190., 15., -100.));
match res1.clone() {
Some((b, c)) => {
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)
);
assert_eq!(res1.clone().unwrap().0, "test".to_string());
}
_ => {
panic!("should be something there!");
}
}
assert!(octtwee.set_voxel_at_path(&res1.clone().unwrap().1, "test_change".to_string())); //if we cant modify it we get false, a failed test
assert_eq!(
octtwee
.voxel_at_location(Vec3::new(190., 15., -100.))
.unwrap()
.0,
octtwee.voxel_at_path(&res1.clone().unwrap().1).unwrap()
);
let res1 = octtwee.voxel_at_location(Vec3::new(190., 15., -100.));
match &res1 {
Some((a, _)) => {
assert_eq!(*a, "test_change".to_string());
}
None => {
panic!("something should be here");
}
}
}
/*
use rand::Rng;
#[test]