From 5fd93ee5e5e0bd15ae3e6d79c615635505e66a39 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Tue, 2 Mar 2021 14:07:30 +0000 Subject: [PATCH] Fixed stupid generation bugs, made houses more interesting --- world/src/site2/gen.rs | 13 +++--- world/src/site2/mod.rs | 2 +- world/src/site2/plot/house.rs | 76 +++++++++++++++++++++++++++++++---- 3 files changed, 78 insertions(+), 13 deletions(-) diff --git a/world/src/site2/gen.rs b/world/src/site2/gen.rs index c72c02d3f6..7fb17ee45e 100644 --- a/world/src/site2/gen.rs +++ b/world/src/site2/gen.rs @@ -1,3 +1,4 @@ +use super::*; use common::{ terrain::Block, store::{Id, Store}, @@ -26,7 +27,8 @@ impl Fill { fn contains_at(&self, tree: &Store, prim: Id, pos: Vec3) -> bool { // Custom closure because vek's impl of `contains_point` is inclusive :( let aabb_contains = |aabb: Aabb, pos: Vec3| (aabb.min.x..aabb.max.x).contains(&pos.x) - && (aabb.min.y..aabb.max.y).contains(&pos.y); + && (aabb.min.y..aabb.max.y).contains(&pos.y) + && (aabb.min.z..aabb.max.z).contains(&pos.z); match &tree[prim] { Primitive::Empty => false, @@ -40,8 +42,8 @@ impl Fill { .reduce_max() as f32 / (inset as f32) < 1.0 - ((pos.z - aabb.min.z) as f32 + 0.5) / (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::Or(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::Xor(a, b) => self.contains_at(tree, *a, pos) ^ self.contains_at(tree, *b, pos), } } @@ -68,15 +70,16 @@ impl Fill { pub trait Structure { fn render Id, G: FnMut(Fill)>( &self, + site: &Site, prim: F, fill: G, ) {} // Generate a primitive tree and fills for this structure - fn render_collect(&self) -> (Store, Vec) { + fn render_collect(&self, site: &Site) -> (Store, Vec) { let mut tree = Store::default(); let mut fills = Vec::new(); - let root = self.render(|p| tree.insert(p), |f| fills.push(f)); + let root = self.render(site, |p| tree.insert(p), |f| fills.push(f)); (tree, fills) } } diff --git a/world/src/site2/mod.rs b/world/src/site2/mod.rs index 3b11c32a3b..7211734589 100644 --- a/world/src/site2/mod.rs +++ b/world/src/site2/mod.rs @@ -437,7 +437,7 @@ impl Site { for plot in plots_to_render { let (prim_tree, fills) = match &self.plots[plot].kind { - PlotKind::House(house) => house.render_collect(), + PlotKind::House(house) => house.render_collect(self), _ => continue, }; diff --git a/world/src/site2/plot/house.rs b/world/src/site2/plot/house.rs index 6a503c87b0..677a3de3f1 100644 --- a/world/src/site2/plot/house.rs +++ b/world/src/site2/plot/house.rs @@ -1,11 +1,12 @@ use super::*; use crate::{Land, util::SQUARE_4}; -use common::terrain::{Block, BlockKind}; +use common::terrain::{Block, BlockKind, SpriteKind}; use vek::*; use rand::prelude::*; pub struct House { door_tile: Vec2, + tile_aabr: Aabr, bounds: Aabr, alt: i32, levels: u32, @@ -15,11 +16,12 @@ impl House { pub fn generate(land: &Land, rng: &mut impl Rng, site: &Site, door_tile: Vec2, tile_aabr: Aabr) -> Self { Self { door_tile, + tile_aabr, bounds: Aabr { min: site.tile_wpos(tile_aabr.min), max: site.tile_wpos(tile_aabr.max), }, - alt: land.get_alt_approx(site.tile_center_wpos(door_tile)) as i32, + alt: land.get_alt_approx(site.tile_center_wpos(door_tile)) as i32 + 2, levels: rng.gen_range(1..3), } } @@ -28,15 +30,16 @@ impl House { impl Structure for House { fn render Id, G: FnMut(Fill)>( &self, + site: &Site, mut prim: F, mut fill: G, ) { - let storey = 8; + let storey = 6; let roof = storey * self.levels as i32; - let foundations = 8; + let foundations = 12; // Walls - let wall = prim(Primitive::Aabb(Aabb { + let outer = prim(Primitive::Aabb(Aabb { min: Vec3::new(self.bounds.min.x, self.bounds.min.y, self.alt - foundations), max: Vec3::new(self.bounds.max.x, self.bounds.max.y, self.alt + roof), })); @@ -44,14 +47,73 @@ impl Structure for House { min: Vec3::new(self.bounds.min.x + 1, self.bounds.min.y + 1, self.alt + 0), max: Vec3::new(self.bounds.max.x - 1, self.bounds.max.y - 1, self.alt + roof), })); + let walls = prim(Primitive::Xor(outer, inner)); fill(Fill { - prim: prim(Primitive::Xor(wall, inner)), + prim: walls, block: Block::new(BlockKind::Rock, Rgb::new(181, 170, 148)), }); - // Floor + // wall pillars + let mut pillars = prim(Primitive::Empty); + for x in self.tile_aabr.min.x + 1..self.tile_aabr.max.x { + let pillar = prim(Primitive::Aabb(Aabb { + min: Vec3::from(site.tile_wpos(Vec2::new(x, self.tile_aabr.min.y))) + Vec3::unit_z() * self.alt, + max: Vec3::from(site.tile_wpos(Vec2::new(x, self.tile_aabr.max.y)) + Vec2::unit_x()) + Vec3::unit_z() * (self.alt + roof), + })); + pillars = prim(Primitive::Or(pillars, pillar)); + } + for y in self.tile_aabr.min.y + 1..self.tile_aabr.max.y { + let pillar = prim(Primitive::Aabb(Aabb { + min: Vec3::from(site.tile_wpos(Vec2::new(self.tile_aabr.min.x, y))) + Vec3::unit_z() * self.alt, + max: Vec3::from(site.tile_wpos(Vec2::new(self.tile_aabr.max.x, y)) + Vec2::unit_y()) + Vec3::unit_z() * (self.alt + roof), + })); + pillars = prim(Primitive::Or(pillars, pillar)); + } + fill(Fill { + prim: prim(Primitive::And(walls, pillars)), + block: Block::new(BlockKind::Wood, Rgb::new(89, 44, 14)), + }); + + // For each storey... for i in 0..self.levels + 1 { let height = storey * i as i32; + + // Windows x axis + { + let mut windows = prim(Primitive::Empty); + for y in self.tile_aabr.min.y..self.tile_aabr.max.y { + let window = prim(Primitive::Aabb(Aabb { + min: Vec3::from(site.tile_wpos(Vec2::new(self.tile_aabr.min.x, y)) + Vec2::unit_y() * 2) + Vec3::unit_z() * (self.alt + height + 2), + max: Vec3::from(site.tile_wpos(Vec2::new(self.tile_aabr.max.x, y + 1)) - Vec2::unit_y() * 1) + Vec3::unit_z() * (self.alt + height + 5), + })); + windows = prim(Primitive::Or(windows, window)); + } + fill(Fill { + prim: prim(Primitive::And(walls, windows)), + block: Block::air(SpriteKind::Window1) + .with_ori(2) + .unwrap(), + }); + } + // Windows y axis + { + let mut windows = prim(Primitive::Empty); + for x in self.tile_aabr.min.x..self.tile_aabr.max.x { + let window = prim(Primitive::Aabb(Aabb { + min: Vec3::from(site.tile_wpos(Vec2::new(x, self.tile_aabr.min.y)) + Vec2::unit_x() * 2) + Vec3::unit_z() * (self.alt + height + 2), + max: Vec3::from(site.tile_wpos(Vec2::new(x + 1, self.tile_aabr.max.y)) - Vec2::unit_x() * 1) + Vec3::unit_z() * (self.alt + height + 5), + })); + windows = prim(Primitive::Or(windows, window)); + } + fill(Fill { + prim: prim(Primitive::And(walls, windows)), + block: Block::air(SpriteKind::Window1) + .with_ori(0) + .unwrap(), + }); + } + + // Floor fill(Fill { prim: prim(Primitive::Aabb(Aabb { min: Vec3::new(self.bounds.min.x, self.bounds.min.y, self.alt + height + 0),