mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added CSG house roofs
This commit is contained in:
parent
aedfd65721
commit
7749b67d67
@ -6,7 +6,12 @@ use vek::*;
|
|||||||
|
|
||||||
pub enum Primitive {
|
pub enum Primitive {
|
||||||
Empty, // Placeholder
|
Empty, // Placeholder
|
||||||
|
|
||||||
|
// Shapes
|
||||||
Aabb(Aabb<i32>),
|
Aabb(Aabb<i32>),
|
||||||
|
Pyramid { aabb: Aabb<i32>, inset: i32 },
|
||||||
|
|
||||||
|
// Combinators
|
||||||
And(Id<Primitive>, Id<Primitive>),
|
And(Id<Primitive>, Id<Primitive>),
|
||||||
Or(Id<Primitive>, Id<Primitive>),
|
Or(Id<Primitive>, Id<Primitive>),
|
||||||
Xor(Id<Primitive>, Id<Primitive>),
|
Xor(Id<Primitive>, Id<Primitive>),
|
||||||
@ -19,9 +24,21 @@ pub struct Fill {
|
|||||||
|
|
||||||
impl Fill {
|
impl Fill {
|
||||||
fn contains_at(&self, tree: &Store<Primitive>, prim: Id<Primitive>, pos: Vec3<i32>) -> bool {
|
fn contains_at(&self, tree: &Store<Primitive>, prim: Id<Primitive>, pos: Vec3<i32>) -> bool {
|
||||||
|
// Custom closure because vek's impl of `contains_point` is inclusive :(
|
||||||
|
let aabb_contains = |aabb: Aabb<i32>, pos: Vec3<i32>| (aabb.min.x..aabb.max.x).contains(&pos.x)
|
||||||
|
&& (aabb.min.y..aabb.max.y).contains(&pos.y);
|
||||||
|
|
||||||
match &tree[prim] {
|
match &tree[prim] {
|
||||||
Primitive::Empty => false,
|
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::Aabb(aabb) => aabb_contains(*aabb, pos),
|
||||||
|
Primitive::Pyramid { aabb, inset } => {
|
||||||
|
let inner = Aabr { min: aabb.min.xy() + *inset, max: aabb.max.xy() - *inset };
|
||||||
|
aabb_contains(*aabb, pos) && (inner.projected_point(pos.xy()) - pos.xy())
|
||||||
|
.map(|e| e.abs())
|
||||||
|
.reduce_max() as f32 / (*inset as f32) < 1.0 - (pos.z - aabb.min.z) as f32 / (aabb.max.z - aabb.min.z) as f32
|
||||||
|
},
|
||||||
|
|
||||||
Primitive::And(a, b) => self.contains_at(tree, *a, pos) & self.contains_at(tree, *b, pos),
|
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::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),
|
Primitive::Xor(a, b) => self.contains_at(tree, *a, pos) ^ self.contains_at(tree, *b, pos),
|
||||||
@ -36,6 +53,7 @@ impl Fill {
|
|||||||
match &tree[prim] {
|
match &tree[prim] {
|
||||||
Primitive::Empty => Aabb::new_empty(Vec3::zero()),
|
Primitive::Empty => Aabb::new_empty(Vec3::zero()),
|
||||||
Primitive::Aabb(aabb) => *aabb,
|
Primitive::Aabb(aabb) => *aabb,
|
||||||
|
Primitive::Pyramid { aabb, .. } => *aabb,
|
||||||
Primitive::And(a, b) => self.get_bounds_inner(tree, *a).intersection(self.get_bounds_inner(tree, *b)),
|
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)),
|
Primitive::Or(a, b) | Primitive::Xor(a, b) => self.get_bounds_inner(tree, *a).union(self.get_bounds_inner(tree, *b)),
|
||||||
}
|
}
|
||||||
|
@ -444,9 +444,9 @@ impl Site {
|
|||||||
for fill in fills {
|
for fill in fills {
|
||||||
let aabb = fill.get_bounds(&prim_tree);
|
let aabb = fill.get_bounds(&prim_tree);
|
||||||
|
|
||||||
for x in aabb.min.x..aabb.max.x + 1 {
|
for x in aabb.min.x..aabb.max.x {
|
||||||
for y in aabb.min.y..aabb.max.y + 1 {
|
for y in aabb.min.y..aabb.max.y {
|
||||||
for z in aabb.min.z..aabb.max.z + 1 {
|
for z in aabb.min.z..aabb.max.z {
|
||||||
let pos = Vec3::new(x, y, z);
|
let pos = Vec3::new(x, y, z);
|
||||||
|
|
||||||
if let Some(block) = fill.sample_at(&prim_tree, pos) {
|
if let Some(block) = fill.sample_at(&prim_tree, pos) {
|
||||||
|
@ -27,17 +27,36 @@ impl Structure for House {
|
|||||||
mut emit_prim: F,
|
mut emit_prim: F,
|
||||||
mut emit_fill: G,
|
mut emit_fill: G,
|
||||||
) {
|
) {
|
||||||
|
let ceiling = 12;
|
||||||
|
|
||||||
|
// Walls
|
||||||
let wall = emit_prim(Primitive::Aabb(Aabb {
|
let wall = emit_prim(Primitive::Aabb(Aabb {
|
||||||
min: Vec3::new(self.bounds.min.x, self.bounds.min.y, self.alt - 8),
|
min: Vec3::new(self.bounds.min.x, self.bounds.min.y, self.alt - 8),
|
||||||
max: Vec3::new(self.bounds.max.x, self.bounds.max.y, self.alt + 16),
|
max: Vec3::new(self.bounds.max.x, self.bounds.max.y, self.alt + ceiling),
|
||||||
}));
|
}));
|
||||||
let inner = emit_prim(Primitive::Aabb(Aabb {
|
let inner = emit_prim(Primitive::Aabb(Aabb {
|
||||||
min: Vec3::new(self.bounds.min.x + 1, self.bounds.min.y + 1, self.alt - 8),
|
min: Vec3::new(self.bounds.min.x + 1, self.bounds.min.y + 1, self.alt - 8),
|
||||||
max: Vec3::new(self.bounds.max.x - 1, self.bounds.max.y - 1, self.alt + 16),
|
max: Vec3::new(self.bounds.max.x - 1, self.bounds.max.y - 1, self.alt + ceiling),
|
||||||
}));
|
}));
|
||||||
emit_fill(Fill {
|
emit_fill(Fill {
|
||||||
prim: emit_prim(Primitive::Xor(wall, inner)),
|
prim: emit_prim(Primitive::Xor(wall, inner)),
|
||||||
block: Block::new(BlockKind::Rock, Rgb::new(150, 50, 10)),
|
block: Block::new(BlockKind::Rock, Rgb::new(150, 50, 10)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let roof_lip = 3;
|
||||||
|
let roof_height = self.bounds.size().reduce_min() / 2 + roof_lip;
|
||||||
|
|
||||||
|
// Roof
|
||||||
|
emit_fill(Fill {
|
||||||
|
prim: emit_prim(Primitive::Pyramid {
|
||||||
|
aabb: Aabb {
|
||||||
|
min: Vec3::new(self.bounds.min.x - roof_lip, self.bounds.min.y - roof_lip, self.alt + ceiling),
|
||||||
|
max: Vec3::new(self.bounds.max.x + roof_lip, self.bounds.max.y + roof_lip, self.alt + ceiling + roof_height),
|
||||||
|
},
|
||||||
|
inset: roof_height,
|
||||||
|
}),
|
||||||
|
block: Block::new(BlockKind::Wood, Rgb::new(100, 80, 100)),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user