mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Automatically use right-recursion instead of left-recursion for union/intersection of CSG primitives via measuring the depth of the trees when unioning/intersecting them.
This commit is contained in:
parent
a0d43cb21d
commit
4f962df7c8
@ -509,6 +509,53 @@ pub struct Painter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Painter {
|
impl Painter {
|
||||||
|
/// Computes the depth of the tree rooted at `prim`
|
||||||
|
pub fn depth(&self, prim: Id<Primitive>) -> usize {
|
||||||
|
fn aux(prims: &Store<Primitive>, prim: Id<Primitive>, prev_depth: usize) -> usize {
|
||||||
|
match prims[prim] {
|
||||||
|
Primitive::Empty
|
||||||
|
| Primitive::Aabb(_)
|
||||||
|
| Primitive::Pyramid { .. }
|
||||||
|
| Primitive::Ramp { .. }
|
||||||
|
| Primitive::Gable { .. }
|
||||||
|
| Primitive::Cylinder(_)
|
||||||
|
| Primitive::Cone(_)
|
||||||
|
| Primitive::Sphere(_)
|
||||||
|
| Primitive::Superquadric { .. }
|
||||||
|
| Primitive::Plane(_, _, _)
|
||||||
|
| Primitive::Segment { .. }
|
||||||
|
| Primitive::SegmentPrism { .. }
|
||||||
|
| Primitive::Prefab(_) => prev_depth,
|
||||||
|
Primitive::Sampling(a, _)
|
||||||
|
| Primitive::Rotate(a, _)
|
||||||
|
| Primitive::Translate(a, _)
|
||||||
|
| Primitive::Scale(a, _)
|
||||||
|
| Primitive::Repeat(a, _, _) => aux(prims, a, 1 + prev_depth),
|
||||||
|
|
||||||
|
Primitive::Intersect(a, b) | Primitive::Union(a, b) | Primitive::Without(a, b) => {
|
||||||
|
aux(prims, a, 1 + prev_depth).max(aux(prims, b, 1 + prev_depth))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let prims = self.prims.borrow();
|
||||||
|
aux(&prims, prim, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Orders two primitives by depth, since (A && (B && C)) is cheaper to
|
||||||
|
/// evaluate than ((A && B) && C) due to short-circuiting.
|
||||||
|
pub fn order_by_depth(
|
||||||
|
&self,
|
||||||
|
a: impl Into<Id<Primitive>>,
|
||||||
|
b: impl Into<Id<Primitive>>,
|
||||||
|
) -> (Id<Primitive>, Id<Primitive>) {
|
||||||
|
let (a, b) = (a.into(), b.into());
|
||||||
|
if self.depth(a) < self.depth(b) {
|
||||||
|
(a, b)
|
||||||
|
} else {
|
||||||
|
(b, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a `PrimitiveRef` of an axis aligned bounding box. The geometric
|
/// Returns a `PrimitiveRef` of an axis aligned bounding box. The geometric
|
||||||
/// name of this shape is a "right rectangular prism."
|
/// name of this shape is a "right rectangular prism."
|
||||||
pub fn aabb(&self, aabb: Aabb<i32>) -> PrimitiveRef {
|
pub fn aabb(&self, aabb: Aabb<i32>) -> PrimitiveRef {
|
||||||
@ -838,13 +885,15 @@ impl<'a> PrimitiveRef<'a> {
|
|||||||
/// Joins two primitives together by returning the total of the blocks of
|
/// Joins two primitives together by returning the total of the blocks of
|
||||||
/// both primitives. In boolean logic this is an `OR` operation.
|
/// both primitives. In boolean logic this is an `OR` operation.
|
||||||
pub fn union(self, other: impl Into<Id<Primitive>>) -> PrimitiveRef<'a> {
|
pub fn union(self, other: impl Into<Id<Primitive>>) -> PrimitiveRef<'a> {
|
||||||
self.painter.prim(Primitive::union(self, other))
|
let (a, b) = self.painter.order_by_depth(self, other);
|
||||||
|
self.painter.prim(Primitive::union(a, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Joins two primitives together by returning only overlapping blocks. In
|
/// Joins two primitives together by returning only overlapping blocks. In
|
||||||
/// boolean logic this is an `AND` operation.
|
/// boolean logic this is an `AND` operation.
|
||||||
pub fn intersect(self, other: impl Into<Id<Primitive>>) -> PrimitiveRef<'a> {
|
pub fn intersect(self, other: impl Into<Id<Primitive>>) -> PrimitiveRef<'a> {
|
||||||
self.painter.prim(Primitive::intersect(self, other))
|
let (a, b) = self.painter.order_by_depth(self, other);
|
||||||
|
self.painter.prim(Primitive::intersect(a, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Subtracts the blocks of the `other` primitive from `self`. In boolean
|
/// Subtracts the blocks of the `other` primitive from `self`. In boolean
|
||||||
|
Loading…
x
Reference in New Issue
Block a user