diff --git a/world/src/site2/gen.rs b/world/src/site2/gen.rs index af81fbec7a..f958b8732a 100644 --- a/world/src/site2/gen.rs +++ b/world/src/site2/gen.rs @@ -6,17 +6,26 @@ use common::{ }; use vek::*; +#[allow(dead_code)] pub enum Primitive { Empty, // Placeholder // Shapes Aabb(Aabb), Pyramid { aabb: Aabb, inset: i32 }, + Cylinder(Aabb), + Cone(Aabb), + Sphere(Aabb), + Plane(Aabr, Vec3, Vec2), // Combinators And(Id, Id), Or(Id, Id), Xor(Id, Id), + // Not commutative + Diff(Id, Id), + // Operators + Rotate(Id, Mat3), } pub enum Fill { @@ -51,7 +60,41 @@ impl Fill { < 1.0 - ((pos.z - aabb.min.z) as f32 + 0.5) / (aabb.max.z - aabb.min.z) as f32 }, - + Primitive::Cylinder(aabb) => { + (aabb.min.z..aabb.max.z).contains(&pos.z) + && (pos + .xy() + .as_() + .distance_squared(aabb.as_().center().xy() - 0.5) + as f32) + < (aabb.size().w.min(aabb.size().h) as f32 / 2.0).powi(2) + }, + Primitive::Cone(aabb) => { + (aabb.min.z..aabb.max.z).contains(&pos.z) + && pos + .xy() + .as_() + .distance_squared(aabb.as_().center().xy() - 0.5) + < (((aabb.max.z - pos.z) as f32 / aabb.size().d as f32) + * (aabb.size().w.min(aabb.size().h) as f32 / 2.0)) + .powi(2) + }, + Primitive::Sphere(aabb) => { + aabb_contains(*aabb, pos) + && pos.as_().distance_squared(aabb.as_().center() - 0.5) + < (aabb.size().w.min(aabb.size().h) as f32 / 2.0).powi(2) + }, + Primitive::Plane(aabr, origin, gradient) => { + // Maybe <= instead of == + (aabr.min.x..aabr.max.x).contains(&pos.x) + && (aabr.min.y..aabr.max.y).contains(&pos.y) + && pos.z + == origin.z + + ((pos.xy() - origin.xy()) + .map(|x| x.abs()) + .as_() + .dot(*gradient) as i32) + }, Primitive::And(a, b) => { self.contains_at(tree, *a, pos) && self.contains_at(tree, *b, pos) }, @@ -61,6 +104,14 @@ impl Fill { Primitive::Xor(a, b) => { self.contains_at(tree, *a, pos) ^ self.contains_at(tree, *b, pos) }, + Primitive::Diff(a, b) => { + self.contains_at(tree, *a, pos) && !self.contains_at(tree, *b, pos) + }, + Primitive::Rotate(prim, mat) => { + let aabb = self.get_bounds(tree, *prim); + let diff = pos - (aabb.min + mat.cols.map(|x| x.reduce_min())); + self.contains_at(tree, *prim, aabb.min + mat.transposed() * diff) + }, } } @@ -98,6 +149,26 @@ impl Fill { Primitive::Empty => return None, Primitive::Aabb(aabb) => *aabb, Primitive::Pyramid { aabb, .. } => *aabb, + Primitive::Cylinder(aabb) => *aabb, + Primitive::Cone(aabb) => *aabb, + Primitive::Sphere(aabb) => *aabb, + Primitive::Plane(aabr, origin, gradient) => { + let half_size = aabr.half_size().reduce_max(); + let longest_dist = ((aabr.center() - origin.xy()).map(|x| x.abs()) + + half_size + + aabr.size().reduce_max() % 2) + .map(|x| x as f32); + let z = if gradient.x.signum() == gradient.y.signum() { + Vec2::new(0, longest_dist.dot(*gradient) as i32) + } else { + (longest_dist * gradient).as_() + }; + let aabb = Aabb { + min: aabr.min.with_z(origin.z + z.reduce_min().min(0)), + max: aabr.max.with_z(origin.z + z.reduce_max().max(0)), + }; + aabb.made_valid() + }, Primitive::And(a, b) => or_zip_with( self.get_bounds_inner(tree, *a), self.get_bounds_inner(tree, *b), @@ -108,6 +179,16 @@ impl Fill { self.get_bounds_inner(tree, *b), |a, b| a.union(b), )?, + Primitive::Diff(a, _) => self.get_bounds_inner(tree, *a)?, + Primitive::Rotate(prim, mat) => { + let aabb = self.get_bounds_inner(tree, *prim)?; + let extent = *mat * Vec3::from(aabb.size()); + let new_aabb: Aabb = Aabb { + min: aabb.min, + max: aabb.min + extent, + }; + new_aabb.made_valid() + }, }) }