You may have seen my other post which showed you how expensive this kind of octree would be - 36 bytes per node just to store four bytes of actual data! I recommend dropping the tree structure.
If you still want all the benefits of an octree - namely level-of-detail for rendering - just cache the non-leaf-nodes in separate linear arrays and use math on the pointers.
Example:
pub struct BlockData<'a> { pub name: &'a str }
impl<'a> BlockData<'a>
{
pub fn new(name: &str) -> BlockData
{
BlockData { name }
}
}
#[derive(Clone)]
pub struct Color { pub red: u8, pub green: u8, pub blue: u8, pub alpha: u8 }
impl Color
{
pub fn new(red: u8, green: u8, blue: u8, alpha: u8) -> Color
{
Color { red, green, blue, alpha }
}
}
#[derive(Clone)]
pub enum Node<'a>
{
Internal { color: Color },
Leaf { block_data: &'a BlockData<'a> }
}
pub struct Octree<'a>
{
depth: usize,
forest: Vec<Vec<Node<'a>>>
}
impl<'a> Octree<'a>
{
pub fn new(depth: usize, color: Color, block_data: &'a BlockData) -> Octree<'a>
{
let mut forest: Vec<Vec<Node>> = Vec::with_capacity(depth);
let base_interior = Node::Internal { color };
let base_leaf = Node::Leaf { block_data };
use std::convert::TryInto;
let levels: u32 = depth.try_into().unwrap();
for i in 0..levels
{
let node;
if i == levels - 1
{
node = base_leaf.clone();
}
else
{
node = base_interior.clone();
};
let siblings = std::iter::repeat(node)
.take(8_usize.pow(i))
.collect();
forest.push(siblings);
}
Octree { depth, forest }
}
pub fn root(&self) -> &Node
{
&self.forest[0][0]
}
pub fn depth(&self) -> usize
{
self.depth.clone()
}
pub fn get(&self, depth: usize, index: usize) -> &Node
{
&self.forest[depth][index]
}
}
fn main()
{
let block_air = BlockData::new("air");
let color_clear = Color::new(0, 0, 0, 0);
let tree = Octree::new(3, color_clear, &block_air);
}