Skip to content

Commit

Permalink
Use OctantMap in Alloctree.
Browse files Browse the repository at this point in the history
  • Loading branch information
kpreid committed Jun 16, 2024
1 parent 8ab9ebb commit 690a683
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 36 deletions.
36 changes: 35 additions & 1 deletion all-is-cubes-base/src/math/octant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,22 @@ impl Octant {
}
}

/// Given a cube in the volume (0..2)³, return which octant of that volume it is.
#[inline]
pub fn try_from_positive_cube(cube: Cube) -> Option<Self> {
match <[i32; 3]>::from(cube) {
[0, 0, 0] => Some(Self::Nnn),
[0, 0, 1] => Some(Self::Nnp),
[0, 1, 0] => Some(Self::Npn),
[0, 1, 1] => Some(Self::Npp),
[1, 0, 0] => Some(Self::Pnn),
[1, 0, 1] => Some(Self::Pnp),
[1, 1, 0] => Some(Self::Ppn),
[1, 1, 1] => Some(Self::Ppp),
_ => None,
}
}

const fn to_zmaj_index(self) -> u8 {
self as u8
}
Expand Down Expand Up @@ -327,6 +343,24 @@ impl<T> OctantMap<T> {
}))
}

/// Constructs an [`OctantMap`] by cloning the provided value.
#[inline]
#[must_use]
pub fn repeat(value: T) -> Self
where
T: Clone,
{
Self([
value.clone(),
value.clone(),
value.clone(),
value.clone(),
value.clone(),
value.clone(),
value.clone(),
value,
])
}
/// Returns an [`OctantMask`] constructed by applying the given `predicate` to each octant
/// of the data in `self`.
#[inline]
Expand Down Expand Up @@ -356,7 +390,7 @@ impl<T> OctantMap<T> {

/// Returns an iterator over all elements by reference, and their octants.
///
/// The order of iteration is not guarateed.
/// The order of iteration is not currently guarateed.
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (Octant, &T)> + '_ {
Octant::ALL.into_iter().zip(self.0.iter())
Expand Down
55 changes: 20 additions & 35 deletions all-is-cubes-gpu/src/common/octree_alloc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use all_is_cubes::euclid::default::Translation3D;
use all_is_cubes::math::{self, Cube, GridAab, GridCoordinate, GridPoint};
use all_is_cubes::math::{self, Cube, GridAab, GridCoordinate, GridPoint, Octant, OctantMap};

/// An octree that knows how to allocate box regions of itself. It stores no other data.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -162,22 +162,15 @@ enum AlloctreeNode {
Full,

/// Subdivided into parts with `size_exponent` decremented by one.
Oct(Box<[AlloctreeNode; 8]>),
Oct(Box<OctantMap<AlloctreeNode>>),
}

impl AlloctreeNode {
/// Construct a node with this child in the low corner.
fn wrap_in_oct(self) -> Self {
AlloctreeNode::Oct(Box::new([
self,
AlloctreeNode::Empty,
AlloctreeNode::Empty,
AlloctreeNode::Empty,
AlloctreeNode::Empty,
AlloctreeNode::Empty,
AlloctreeNode::Empty,
AlloctreeNode::Empty,
]))
let mut oct = Box::new(OctantMap::repeat(AlloctreeNode::Empty));
oct[Octant::Nnn] = self;
AlloctreeNode::Oct(oct)
}

fn allocate(
Expand Down Expand Up @@ -239,16 +232,14 @@ impl AlloctreeNode {
}
let child_size = expsize(size_exponent - 1);

children
.iter_mut()
.zip(linearization().iter_cubes())
.find_map(|(child, child_position)| {
child.allocate(
size_exponent - 1,
low_corner + child_position.lower_bounds().to_vector() * child_size,
request,
)
})
children.iter_mut().find_map(|(octant, child)| {
child.allocate(
size_exponent - 1,
low_corner
+ octant.to_positive_cube().lower_bounds().to_vector() * child_size,
request,
)
})
}
}
}
Expand All @@ -265,26 +256,20 @@ impl AlloctreeNode {
AlloctreeNode::Oct(children) => {
debug_assert!(size_exponent > 0, "tree is deeper than size");
let child_size = expsize(size_exponent - 1);
let which_child = relative_low_corner.map(|c| c.div_euclid(child_size));
let child_index = linearization()
.index(Cube::from(which_child))
.expect("Alloctree::free: out of bounds");
children[child_index].free(
let octant = Octant::try_from_positive_cube(Cube::from(
relative_low_corner.map(|c| c.div_euclid(child_size)),
))
.expect("Alloctree::free: out of bounds");
children[octant].free(
size_exponent - 1,
relative_low_corner - which_child.to_vector() * child_size,
relative_low_corner
- octant.to_positive_cube().lower_bounds().to_vector() * child_size,
);
}
}
}
}

// TODO: ideally this would be a constant
fn linearization() -> math::Vol<(), math::ZMaj> {
GridAab::from_lower_size([0, 0, 0], [2, 2, 2])
.to_vol()
.unwrap()
}

/// Description of an allocated region in an [`Alloctree`].
///
/// This **does not deallocate on drop**, because the tree does not implement interior
Expand Down

0 comments on commit 690a683

Please sign in to comment.