Re: Game world and implementation

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);
}
3 Likes