Better Fill type

This commit is contained in:
Joshua Barretto 2021-03-05 13:08:50 +00:00
parent 97141d12a6
commit 173a127d5e
3 changed files with 69 additions and 74 deletions

View File

@ -18,9 +18,8 @@ pub enum Primitive {
Xor(Id<Primitive>, Id<Primitive>),
}
pub struct Fill {
pub prim: Id<Primitive>,
pub block: Block,
pub enum Fill {
Block(Block),
}
impl Fill {
@ -63,8 +62,19 @@ impl Fill {
}
}
pub fn sample_at(&self, tree: &Store<Primitive>, pos: Vec3<i32>) -> Option<Block> {
Some(self.block).filter(|_| self.contains_at(tree, self.prim, pos))
pub fn sample_at(
&self,
tree: &Store<Primitive>,
prim: Id<Primitive>,
pos: Vec3<i32>,
) -> Option<Block> {
if self.contains_at(tree, prim, pos) {
match self {
Fill::Block(block) => Some(*block),
}
} else {
None
}
}
fn get_bounds_inner(&self, tree: &Store<Primitive>, prim: Id<Primitive>) -> Option<Aabb<i32>> {
@ -93,26 +103,25 @@ impl Fill {
})
}
pub fn get_bounds(&self, tree: &Store<Primitive>) -> Aabb<i32> {
self.get_bounds_inner(tree, self.prim)
pub fn get_bounds(&self, tree: &Store<Primitive>, prim: Id<Primitive>) -> Aabb<i32> {
self.get_bounds_inner(tree, prim)
.unwrap_or_else(|| Aabb::new_empty(Vec3::zero()))
}
}
pub trait Structure {
fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Fill)>(
fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Id<Primitive>, Fill)>(
&self,
site: &Site,
prim: F,
fill: G,
) {
}
);
// Generate a primitive tree and fills for this structure
fn render_collect(&self, site: &Site) -> (Store<Primitive>, Vec<Fill>) {
fn render_collect(&self, site: &Site) -> (Store<Primitive>, Vec<(Id<Primitive>, Fill)>) {
let mut tree = Store::default();
let mut fills = Vec::new();
let root = self.render(site, |p| tree.insert(p), |f| fills.push(f));
let root = self.render(site, |p| tree.insert(p), |p, f| fills.push((p, f)));
(tree, fills)
}
}

View File

@ -470,16 +470,16 @@ impl Site {
match &tile.kind {
TileKind::Plaza => {
let near_roads = CARDINALS
.iter()
.filter_map(|rpos| if self.tiles.get(tpos + rpos) == tile {
let near_roads = CARDINALS.iter().filter_map(|rpos| {
if self.tiles.get(tpos + rpos) == tile {
Some(Aabr {
min: self.tile_wpos(tpos).map(|e| e as f32),
max: self.tile_wpos(tpos + 1).map(|e| e as f32),
})
} else {
None
});
}
});
cols.for_each(|(wpos2d, offs)| {
let wpos2df = wpos2d.map(|e| e as f32);
@ -490,18 +490,19 @@ impl Site {
if dist.map_or(false, |d| d <= 3.0) {
let alt = canvas.col(wpos2d).map_or(0, |col| col.alt as i32);
(-8..6).for_each(|z| canvas.map(
Vec3::new(wpos2d.x, wpos2d.y, alt + z),
|b| if z >= 0 {
if b.is_filled() {
Block::empty()
(-8..6).for_each(|z| {
canvas.map(Vec3::new(wpos2d.x, wpos2d.y, alt + z), |b| {
if z >= 0 {
if b.is_filled() {
Block::empty()
} else {
b.with_sprite(SpriteKind::Empty)
}
} else {
b.with_sprite(SpriteKind::Empty)
Block::new(BlockKind::Rock, Rgb::new(55, 45, 50))
}
} else {
Block::new(BlockKind::Rock, Rgb::new(55, 45, 50))
},
));
})
});
}
});
},
@ -625,15 +626,15 @@ impl Site {
_ => continue,
};
for fill in fills {
let aabb = fill.get_bounds(&prim_tree);
for (prim, fill) in fills {
let aabb = fill.get_bounds(&prim_tree, prim);
for x in aabb.min.x..aabb.max.x {
for y in aabb.min.y..aabb.max.y {
for z in aabb.min.z..aabb.max.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, prim, pos) {
canvas.set(pos, block);
}
}

View File

@ -47,7 +47,7 @@ impl House {
}
impl Structure for House {
fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Fill)>(
fn render<F: FnMut(Primitive) -> Id<Primitive>, G: FnMut(Id<Primitive>, Fill)>(
&self,
site: &Site,
mut prim: F,
@ -66,14 +66,11 @@ impl Structure for House {
min: self.bounds.min.with_z(self.alt - foundations),
max: (self.bounds.max + 1).with_z(self.alt + roof),
}));
fill(Fill {
prim: outer,
block: Block::new(BlockKind::Rock, Rgb::new(181, 170, 148)),
});
fill(Fill {
prim: inner,
block: Block::empty(),
});
fill(
outer,
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(181, 170, 148))),
);
fill(inner, Fill::Block(Block::empty()));
let walls = prim(Primitive::Xor(outer, inner));
// wall pillars
@ -100,10 +97,10 @@ impl Structure for House {
pillars_x = prim(Primitive::Or(pillars_x, pillar));
}
let pillars = prim(Primitive::And(pillars_x, pillars_y));
fill(Fill {
prim: pillars,
block: Block::new(BlockKind::Wood, Rgb::new(55, 25, 8)),
});
fill(
pillars,
Fill::Block(Block::new(BlockKind::Wood, Rgb::new(55, 25, 8))),
);
// For each storey...
for i in 0..self.levels + 1 {
@ -124,10 +121,10 @@ impl Structure for House {
}));
windows = prim(Primitive::Or(windows, window));
}
fill(Fill {
prim: prim(Primitive::And(walls, windows)),
block: Block::air(SpriteKind::Window1).with_ori(2).unwrap(),
});
fill(
prim(Primitive::And(walls, windows)),
Fill::Block(Block::air(SpriteKind::Window1).with_ori(2).unwrap()),
);
}
// Windows y axis
{
@ -143,34 +140,22 @@ impl Structure for House {
}));
windows = prim(Primitive::Or(windows, window));
}
fill(Fill {
prim: prim(Primitive::And(walls, windows)),
block: Block::air(SpriteKind::Window1).with_ori(0).unwrap(),
});
fill(
prim(Primitive::And(walls, windows)),
Fill::Block(Block::air(SpriteKind::Window1).with_ori(0).unwrap()),
);
}
// Floor
fill(Fill {
prim: prim(Primitive::Aabb(Aabb {
fill(
prim(Primitive::Aabb(Aabb {
min: self.bounds.min.with_z(self.alt + height),
max: (self.bounds.max + 1).with_z(self.alt + height + 1),
})),
block: Block::new(BlockKind::Rock, Rgb::new(89, 44, 14)),
});
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(89, 44, 14))),
);
}
// Corner pillars
// for &rpos in SQUARE_4.iter() {
// let pos = self.bounds.min + (self.bounds.max - self.bounds.min) * rpos;
// fill(Fill {
// prim: prim(Primitive::Aabb(Aabb {
// min: Vec3::new(pos.x - 1, pos.y - 1, self.alt - foundations),
// max: Vec3::new(pos.x + 1, pos.y + 1, self.alt + roof),
// })),
// block: Block::new(BlockKind::Wood, Rgb::new(89, 44, 14)),
// });
// }
let roof_lip = 2;
let roof_height = (self.bounds.min - self.bounds.max)
.map(|e| e.abs())
@ -180,24 +165,24 @@ impl Structure for House {
+ 1;
// Roof
fill(Fill {
prim: prim(Primitive::Pyramid {
fill(
prim(Primitive::Pyramid {
aabb: Aabb {
min: (self.bounds.min - roof_lip).with_z(self.alt + roof),
max: (self.bounds.max + 1 + roof_lip).with_z(self.alt + roof + roof_height),
},
inset: roof_height,
}),
block: Block::new(BlockKind::Wood, self.roof_color),
});
Fill::Block(Block::new(BlockKind::Wood, self.roof_color)),
);
// Foundations
fill(Fill {
prim: prim(Primitive::Aabb(Aabb {
fill(
prim(Primitive::Aabb(Aabb {
min: (self.bounds.min - 1).with_z(self.alt - foundations),
max: (self.bounds.max + 2).with_z(self.alt + 1),
})),
block: Block::new(BlockKind::Rock, Rgb::new(31, 33, 32)),
});
Fill::Block(Block::new(BlockKind::Rock, Rgb::new(31, 33, 32))),
);
}
}