use common::{ terrain::Block, store::{Id, Store}, }; use vek::*; pub enum Primitive { Empty, // Placeholder Aabb(Aabb), And(Id, Id), Or(Id, Id), Xor(Id, Id), } pub struct Fill { pub prim: Id, pub block: Block, } impl Fill { fn contains_at(&self, tree: &Store, prim: Id, pos: Vec3) -> bool { match &tree[prim] { Primitive::Empty => false, Primitive::Aabb(aabb) => (aabb.min.x..aabb.max.x).contains(&pos.x) && (aabb.min.y..aabb.max.y).contains(&pos.y), Primitive::And(a, b) => self.contains_at(tree, *a, pos) & self.contains_at(tree, *b, pos), Primitive::Or(a, b) => self.contains_at(tree, *a, pos) | self.contains_at(tree, *b, pos), Primitive::Xor(a, b) => self.contains_at(tree, *a, pos) ^ self.contains_at(tree, *b, pos), } } pub fn sample_at(&self, tree: &Store, pos: Vec3) -> Option { Some(self.block).filter(|_| self.contains_at(tree, self.prim, pos)) } fn get_bounds_inner(&self, tree: &Store, prim: Id) -> Aabb { match &tree[prim] { Primitive::Empty => Aabb::new_empty(Vec3::zero()), Primitive::Aabb(aabb) => *aabb, Primitive::And(a, b) => self.get_bounds_inner(tree, *a).intersection(self.get_bounds_inner(tree, *b)), Primitive::Or(a, b) | Primitive::Xor(a, b) => self.get_bounds_inner(tree, *a).union(self.get_bounds_inner(tree, *b)), } } pub fn get_bounds(&self, tree: &Store) -> Aabb { self.get_bounds_inner(tree, self.prim) } } pub trait Structure { fn render Id, G: FnMut(Fill)>( &self, emit_prim: F, emit_fill: G, ) {} // Generate a primitive tree and fills for this structure fn render_collect(&self) -> (Store, Vec) { let mut tree = Store::default(); let mut fills = Vec::new(); let root = self.render(|p| tree.insert(p), |f| fills.push(f)); (tree, fills) } }