From 9e20d7390f94fa42c3303bb6a26d56f0f48e9b9c Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Mon, 1 Mar 2021 21:14:38 +0000 Subject: [PATCH] Better house generation --- world/src/site2/gen.rs | 5 +-- world/src/site2/mod.rs | 4 +-- world/src/site2/plot/house.rs | 65 ++++++++++++++++++++++++++++------- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/world/src/site2/gen.rs b/world/src/site2/gen.rs index 2d8d3d94bb..244e1ff196 100644 --- a/world/src/site2/gen.rs +++ b/world/src/site2/gen.rs @@ -33,10 +33,11 @@ impl Fill { Primitive::Aabb(aabb) => aabb_contains(*aabb, pos), Primitive::Pyramid { aabb, inset } => { - let inner = Aabr { min: aabb.min.xy() + *inset, max: aabb.max.xy() - *inset }; + let inset = (*inset).max(aabb.size().reduce_min()); + let inner = Aabr { min: aabb.min.xy() - 1 + 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 + .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), diff --git a/world/src/site2/mod.rs b/world/src/site2/mod.rs index 7f2d4c7576..2f3dcbac5d 100644 --- a/world/src/site2/mod.rs +++ b/world/src/site2/mod.rs @@ -241,9 +241,9 @@ impl Site { // House 1 => { let size = (2.0 + rng.gen::().powf(8.0) * 3.0).round() as u32; - if let Some((aabr, _)) = attempt(10, || site.find_roadside_aabr(rng, 4..(size + 1).pow(2), Extent2::broadcast(size))) { + if let Some((aabr, door_tile)) = attempt(10, || site.find_roadside_aabr(rng, 4..(size + 1).pow(2), Extent2::broadcast(size))) { let plot = site.create_plot(Plot { - kind: PlotKind::House(plot::House::generate(land, rng, &site, aabr)), + kind: PlotKind::House(plot::House::generate(land, rng, &site, door_tile, aabr)), root_tile: aabr.center(), tiles: aabr_tiles(aabr).collect(), seed: rng.gen(), diff --git a/world/src/site2/plot/house.rs b/world/src/site2/plot/house.rs index 6f8e04b152..dd6e4f0f2d 100644 --- a/world/src/site2/plot/house.rs +++ b/world/src/site2/plot/house.rs @@ -1,22 +1,26 @@ use super::*; -use crate::Land; +use crate::{Land, util::SQUARE_4}; use common::terrain::{Block, BlockKind}; use vek::*; use rand::prelude::*; pub struct House { + door_tile: Vec2, bounds: Aabr, alt: i32, + levels: u32, } impl House { - pub fn generate(land: &Land, rng: &mut impl Rng, site: &Site, tile_aabr: Aabr) -> Self { + pub fn generate(land: &Land, rng: &mut impl Rng, site: &Site, door_tile: Vec2, tile_aabr: Aabr) -> Self { Self { + door_tile, 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(tile_aabr.center())) as i32, + alt: land.get_alt_approx(site.tile_center_wpos(door_tile)) as i32, + levels: rng.gen_range(1..3), } } } @@ -27,36 +31,71 @@ impl Structure for House { mut emit_prim: F, mut emit_fill: G, ) { - let ceiling = 12; + let storey = 8; + let roof = storey * self.levels as i32; + let foundations = 8; // Walls let wall = emit_prim(Primitive::Aabb(Aabb { - 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 + ceiling), + 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), })); let inner = emit_prim(Primitive::Aabb(Aabb { - 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 + ceiling), + 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), })); emit_fill(Fill { prim: emit_prim(Primitive::Xor(wall, inner)), - block: Block::new(BlockKind::Rock, Rgb::new(150, 50, 10)), + block: Block::new(BlockKind::Rock, Rgb::new(181, 170, 148)), }); + // Floor + for i in 0..self.levels + 1 { + let height = storey * i as i32; + emit_fill(Fill { + prim: emit_prim(Primitive::Aabb(Aabb { + min: Vec3::new(self.bounds.min.x, self.bounds.min.y, self.alt + height + 0), + max: Vec3::new(self.bounds.max.x, self.bounds.max.y, self.alt + height + 1), + })), + 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; + emit_fill(Fill { + prim: emit_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 = 3; - let roof_height = self.bounds.size().reduce_min() / 2 + roof_lip; + let roof_height = (self.bounds.min - self.bounds.max).map(|e| e.abs()).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), + min: Vec3::new(self.bounds.min.x - roof_lip, self.bounds.min.y - roof_lip, self.alt + roof), + max: Vec3::new(self.bounds.max.x + roof_lip, self.bounds.max.y + roof_lip, self.alt + roof + roof_height), }, inset: roof_height, }), - block: Block::new(BlockKind::Wood, Rgb::new(100, 80, 100)), + block: Block::new(BlockKind::Wood, Rgb::new(21, 43, 48)), + }); + + // Foundations + emit_fill(Fill { + prim: emit_prim(Primitive::Aabb(Aabb { + min: Vec3::new(self.bounds.min.x - 1, self.bounds.min.y - 1, self.alt - foundations), + max: Vec3::new(self.bounds.max.x + 1, self.bounds.max.y + 1, self.alt + 1), + })), + block: Block::new(BlockKind::Rock, Rgb::new(31, 33, 32)), }); } }