Wall, in progress

This commit is contained in:
Sam 2022-04-05 15:21:34 -04:00
parent c90159840c
commit dd1d5d1c29
10 changed files with 168 additions and 187 deletions

View File

@ -1442,7 +1442,7 @@ pub trait Structure {
},
};
self.render(site, &canvas.land(), &painter);
self.render(site, &canvas.land(), &painter, &canvas);
(
painter.prims.into_inner(),
painter.fills.into_inner(),

View File

@ -480,21 +480,21 @@ impl Site {
site.demarcate_obstacles(land);
let adlet_stronghold = plot::AdletStronghold::generate(origin, land, &mut rng);
site.name = adlet_stronghold.name().to_string();
// TODO: Update this to also blit tiles near entrance when entrance has stuff
let size = adlet_stronghold.radius() / tile::TILE_SIZE as i32;
let offset = (adlet_stronghold.origin() - origin) / tile::TILE_SIZE as i32;
let aabr = Aabr {
min: Vec2::broadcast(-size) + offset,
max: Vec2::broadcast(size) + offset,
};
let (cavern_aabr, wall_aabr) = adlet_stronghold.plot_tiles(origin);
let plot = site.create_plot(Plot {
kind: PlotKind::Adlet(adlet_stronghold),
root_tile: aabr.center(),
tiles: aabr_tiles(aabr).collect(),
root_tile: cavern_aabr.center(),
tiles: aabr_tiles(cavern_aabr)
.chain(aabr_tiles(wall_aabr))
.collect(),
seed: rng.gen(),
});
site.blit_aabr(aabr, Tile {
site.blit_aabr(cavern_aabr, Tile {
kind: TileKind::AdletStronghold,
plot: Some(plot),
hard_alt: None,
});
site.blit_aabr(wall_aabr, Tile {
kind: TileKind::AdletStronghold,
plot: Some(plot),
hard_alt: None,

View File

@ -3,7 +3,7 @@ use crate::{
assets::AssetHandle,
site2::{gen::PrimitiveTransform, util::Dir},
util::{attempt, sampler::Sampler, FastNoise, RandomField},
Land,
Land, CanvasInfo,
};
use common::{
generation::{ChunkSupplement, EntityInfo},
@ -11,17 +11,27 @@ use common::{
};
use lazy_static::lazy_static;
use rand::prelude::*;
use std::{collections::HashMap, f32::consts::TAU};
use std::{
collections::HashMap,
f32::consts::TAU,
ops::{Add, Div, Mul, Sub},
};
use vek::*;
const ANGLE_SAMPLES: usize = 360;
pub struct AdletStronghold {
name: String,
seed: u32,
origin: Vec2<i32>,
entrance: Vec2<i32>,
wall_center: Vec2<i32>,
wall_radius: i32,
wall_alt: f32,
wall_alt_sample_positions: [[Vec2<i32>; 3]; ANGLE_SAMPLES],
tunnel_length: i32,
cavern_center: Vec2<i32>,
cavern_alt: f32,
cavern_radius: i32,
entrance: Vec2<i32>,
tunnel_length: i32,
}
enum AdletStructure {
@ -49,6 +59,32 @@ impl AdletStronghold {
let seed = rng.gen();
let entrance = wpos;
let wall_radius = {
let unit_size = rng.gen_range(8..11);
let num_units = rng.gen_range(6..9);
let variation = rng.gen_range(0..10);
unit_size * num_units + variation
};
let wall_center = entrance.map(|x| x + rng.gen_range(-wall_radius / 4..wall_radius / 4));
let wall_alt = land.get_alt_approx(wall_center) + 10.0;
let mut wall_alt_sample_positions = [[Vec2::zero(); 3]; ANGLE_SAMPLES];
for i in 0..ANGLE_SAMPLES {
let theta = i as f32 / ANGLE_SAMPLES as f32 * TAU;
// let sample_rpos = Vec2::new(
// theta.cos() * wall_radius as f32,
// theta.sin() * wall_radius as f32,
// );
// wall_alt_sample_positions[i] = sample_rpos.as_() + wall_center;
for j in 0..3 {
let sample_rpos = Vec2::new(
theta.cos() * (wall_radius as f32 + j as f32 - 1.0),
theta.sin() * (wall_radius as f32 + j as f32 - 1.0),
);
wall_alt_sample_positions[i][j] = sample_rpos.as_() + wall_center;
}
}
// Find direction that allows for deep enough site
let angle_samples = (0..64).into_iter().map(|x| x as f32 / 64.0 * TAU);
// Sample blocks 40-50 away, use angle where these positions are highest
@ -78,33 +114,56 @@ impl AdletStronghold {
let tunnel_length = rng.gen_range(35_i32..50);
let origin = entrance
let cavern_center = entrance
+ (Vec2::new(angle.cos(), angle.sin()) * (tunnel_length as f32 + cavern_radius as f32))
.as_();
let cavern_alt =
(land.get_alt_approx(origin) - cavern_radius as f32).min(land.get_alt_approx(entrance));
let cavern_alt = (land.get_alt_approx(cavern_center) - cavern_radius as f32)
.min(land.get_alt_approx(entrance));
Self {
name,
seed,
origin,
entrance,
wall_center,
wall_radius,
wall_alt,
wall_alt_sample_positions,
tunnel_length,
cavern_center,
cavern_radius,
cavern_alt,
entrance,
tunnel_length,
}
}
pub fn name(&self) -> &str { &self.name }
pub fn origin(&self) -> Vec2<i32> { self.origin }
// pub fn origin(&self) -> Vec2<i32> { self.cavern_center }
pub fn radius(&self) -> i32 { self.cavern_radius + self.tunnel_length + 5 }
pub fn plot_tiles(&self, origin: Vec2<i32>) -> (Aabr<i32>, Aabr<i32>) {
// Cavern
let size = self.cavern_radius / tile::TILE_SIZE as i32;
let offset = (self.cavern_center - origin) / tile::TILE_SIZE as i32;
let cavern_aabr = Aabr {
min: Vec2::broadcast(-size) + offset,
max: Vec2::broadcast(size) + offset,
};
// Wall
let size = (self.wall_radius * 5 / 4) / tile::TILE_SIZE as i32;
let offset = (self.wall_center - origin) / tile::TILE_SIZE as i32;
let wall_aabr = Aabr {
min: Vec2::broadcast(-size) + offset,
max: Vec2::broadcast(size) + offset,
};
(cavern_aabr, wall_aabr)
}
pub fn spawn_rules(&self, wpos: Vec2<i32>) -> SpawnRules {
SpawnRules {
waypoints: false,
trees: wpos.distance_squared(self.entrance) > (self.wall_radius * 5 / 4).pow(2),
..SpawnRules::default()
}
}
@ -117,7 +176,7 @@ impl AdletStronghold {
wpos2d: Vec2<i32>,
supplement: &mut ChunkSupplement,
) {
let rpos = wpos2d - self.origin;
let rpos = wpos2d - self.cavern_center;
let area = Aabr {
min: rpos,
max: rpos + TerrainChunkSize::RECT_SIZE.map(|e| e as i32),
@ -131,41 +190,108 @@ impl Structure for AdletStronghold {
#[cfg_attr(feature = "be-dyn-lib", export_name = "render_adletstronghold")]
fn render_inner(&self, _site: &Site, land: &Land, painter: &Painter) {
let wall_mat = Fill::Brick(BlockKind::Snow, Rgb::new(175, 175, 175), 25);
const WALL_DELTA: f32 = 4.0;
// let mut wall_alt_samples = self.wall_alt_sample_positions.map(|pos| canvas.col(pos).map_or(land.get_alt_approx(pos), |col| col.alt));
let mut wall_alt_samples = self.wall_alt_sample_positions.map(|poses| {
let mut average = 0.0;
for pos in poses.iter() {
average += canvas.col(*pos).map_or(land.get_alt_approx(*pos), |col| col.alt);
}
average / 3.0
});
loop {
let mut changed = false;
for i in 0..wall_alt_samples.len() {
let tmp = (wall_alt_samples[(i + 1) % ANGLE_SAMPLES] - WALL_DELTA).max(wall_alt_samples[(i + ANGLE_SAMPLES - 1) % ANGLE_SAMPLES] - WALL_DELTA);
if tmp > wall_alt_samples[i] {
wall_alt_samples[i] = tmp;
changed = true;
}
}
if !changed {
break;
}
}
// Wall
painter
.cylinder_with_radius(
self.wall_center
.with_z(self.wall_alt as i32 - self.wall_radius * 2),
self.wall_radius as f32 + 3.0,
self.wall_radius as f32 * 2.5,
)
.without(
painter.cylinder_with_radius(
self.wall_center
.with_z(self.wall_alt as i32 - self.wall_radius * 2),
self.wall_radius as f32,
self.wall_radius as f32 * 2.5,
),
)
.sample_with_column({
let wall_center = self.wall_center;
let theta = move |pos: Vec2<i32>| {
let rpos: Vec2<f32> = (pos - wall_center).as_();
let theta = rpos.y.atan2(rpos.x);
if theta > 0.0 {
theta
} else {
theta + TAU
}
};
move |pos, col| {
let index = (theta(pos.xy()) * ANGLE_SAMPLES as f32 / TAU).floor().max(0.0) as usize % ANGLE_SAMPLES;
(col.alt.sub(10.0)..wall_alt_samples[index].add(10.0).div(WALL_DELTA).floor().mul(WALL_DELTA))
.contains(&(pos.z as f32))
}
})
.fill(wall_mat);
// Tunnel
let dist: f32 = self.origin.as_().distance(self.entrance.as_());
let dist: f32 = self.cavern_center.as_().distance(self.entrance.as_());
let tunnel_radius = 5.0;
let tunnel_start = self
.entrance
.as_()
.with_z(land.get_alt_approx(self.entrance));
// Adds cavern radius to ensure that tunnel fully bores into cavern
let tunnel_end = ((self.origin.as_() - self.entrance.as_()) * self.tunnel_length as f32
/ dist)
.with_z(self.cavern_alt + tunnel_radius - 1.0)
+ self.entrance.as_();
let tunnel_end =
((self.cavern_center.as_() - self.entrance.as_()) * self.tunnel_length as f32 / dist)
.with_z(self.cavern_alt + tunnel_radius - 1.0)
+ self.entrance.as_();
painter
.line(tunnel_start, tunnel_end, tunnel_radius)
.clear();
painter
.line(
tunnel_end,
self.origin.as_().with_z(self.cavern_alt + tunnel_radius),
self.cavern_center
.as_()
.with_z(self.cavern_alt + tunnel_radius),
tunnel_radius,
)
.clear();
painter
.sphere_with_radius(
self.entrance
.with_z(land.get_alt_approx(self.entrance) as i32 + 4),
8.0,
)
.clear();
// Cavern
painter
.sphere_with_radius(
self.origin.with_z(self.cavern_alt as i32),
self.cavern_center.with_z(self.cavern_alt as i32),
self.cavern_radius as f32,
)
.intersect(painter.aabb(Aabb {
min: (self.origin - self.cavern_radius).with_z(self.cavern_alt as i32),
max: self.origin.with_z(self.cavern_alt as i32) + self.cavern_radius,
min: (self.cavern_center - self.cavern_radius).with_z(self.cavern_alt as i32),
max: self.cavern_center.with_z(self.cavern_alt as i32) + self.cavern_radius,
}))
.sample_with_column({
let origin = self.origin.with_z(self.cavern_alt as i32);
let origin = self.cavern_center.with_z(self.cavern_alt as i32);
let radius_sqr = self.cavern_radius.pow(2);
move |pos, col| {
let alt = col.basement - col.cliff_offset;
@ -190,151 +316,6 @@ impl Structure for AdletStronghold {
}
})
.clear();
// Create outer wall
// for (point, next_point) in self.wall_segments.iter() {
// // This adds additional points for the wall on the line between
// two points, // allowing the wall to better handle slopes
// const SECTIONS_PER_WALL_SEGMENT: usize = 3;
// (0..(SECTIONS_PER_WALL_SEGMENT as i32))
// .into_iter()
// .map(move |a| {
// let get_point =
// |a| point + (next_point - point) * a /
// (SECTIONS_PER_WALL_SEGMENT as i32);
// (get_point(a), get_point(a + 1)) })
// .for_each(|(point, next_point)| {
// // 2d world positions of each point in wall segment
// let point = point;
// let start_wpos = point + self.origin;
// let end_wpos = next_point + self.origin;
// let lightstone = Fill::Brick(BlockKind::Wood,
// Rgb::new(107, 107, 107), 18); let midstone =
// Fill::Brick(BlockKind::Wood, Rgb::new(70, 70, 70), 18);
// let darkstone = Fill::Brick(BlockKind::Wood, Rgb::new(42,
// 42, 42), 18); let darkpelt =
// Fill::Brick(BlockKind::Wood, Rgb::new(80, 47, 13), 35);
// let lightpelt = Fill::Brick(BlockKind::Wood, Rgb::new(54,
// 25, 1), 25);
// let start = (start_wpos + 2)
// .as_()
// .with_z(land.get_alt_approx(start_wpos) + 0.0);
// let end = (end_wpos + 2)
// .as_()
// .with_z(land.get_alt_approx(end_wpos) + 0.0);
// let randstart = start % 10.0 - 5.;
// let randend = end % 10.0 - 5.0;
// let mid = (start + end) / 2.0;
// let start =
// start_wpos.as_().with_z(land.get_alt_approx(start_wpos));
// let end =
// end_wpos.as_().with_z(land.get_alt_approx(end_wpos));
// let wall_base_height = 3.0;
// let wall_mid_thickness = 2.0;
// let wall_mid_height = 15.0 + wall_base_height;
// let highwall =
// painter.segment_prism(start, end, wall_mid_thickness,
// wall_mid_height); painter.fill(highwall,
// lightstone.clone());
// painter
// .segment_prism(start, end, wall_mid_thickness + 1.0,
// wall_mid_height - 8.0)
// .fill(midstone.clone()); let wallexterior =
// painter .segment_prism(start, end,
// wall_mid_thickness + 2.0, wall_mid_height - 15.0)
// .translate(Vec3::new(0, 0, 8)); let wallstrut =
// painter .segment_prism(start, end,
// wall_mid_thickness - 1.0, wall_mid_height)
// .translate(Vec3::new(0, 0, 8)); let
// wallexteriorlow = wallexterior.translate(Vec3::new(0, 0, -2));
// painter.fill(wallexterior, darkpelt.clone());
// painter.fill(wallexteriorlow, lightpelt.clone());
// let exclusion = painter.line(
// Vec3::new(
// start.x as i32,
// start.y as i32,
// start.z as i32 + wall_mid_height as i32 + 2,
// ),
// Vec3::new(
// end.x as i32,
// end.y as i32,
// end.z as i32 + wall_mid_height as i32 + 2,
// ),
// 5.0,
// );
// let top = painter
// .line(
// Vec3::new(
// start.x as i32,
// start.y as i32,
// start.z as i32 + wall_mid_height as i32 + 5,
// ),
// Vec3::new(
// end.x as i32,
// end.y as i32,
// end.z as i32 + wall_mid_height as i32 + 5,
// ),
// 4.0,
// )
// .without(exclusion);
// let overtop = top.translate(Vec3::new(0, 0, 1));
// let cyl = painter.cylinder_with_radius(
// Vec3::new(start.x as i32, start.y as i32, start.z as
// i32), 5.0,
// wall_mid_height - 8.0,
// );
// painter.fill(cyl, darkstone.clone());
// let cylsupport = painter.cylinder_with_radius(
// Vec3::new(start.x as i32, start.y as i32, start.z as
// i32), 5.0,
// wall_mid_height + 20.0,
// );
// let cylsub = painter.cylinder_with_radius(
// Vec3::new(start.x as i32, start.y as i32, start.z as
// i32), 4.0,
// wall_mid_height + 20.0,
// );
// let hollowcyl = cylsupport.without(cylsub);
// let roofpoles = wallstrut.intersect(hollowcyl);
// painter.fill(roofpoles, midstone.clone());
// painter.fill(top, darkpelt.clone());
// let startshift =
// Vec3::new(randstart.x * 3.0, randstart.y * 3.0,
// randstart.z * 1.0); let endshift =
// Vec3::new(randend.x * 3.0, randend.y * 3.0, randend.z * 1.0);
// painter
// .cubic_bezier(start, mid + startshift, mid +
// endshift, end, 2.5) .translate(Vec3::new(0,
// 0, 27)) .intersect(overtop)
// .fill(lightpelt.clone());
// painter
// .sphere_with_radius(
// Vec3::new(
// start.x as i32,
// start.y as i32,
// start.z as i32 + wall_mid_height as i32 - 8,
// ),
// 5.0,
// )
// .without(cyl)
// .clear();
// })
// }
}
}

View File

@ -1,5 +1,5 @@
use super::*;
use crate::{util::SQUARE_4, Land};
use crate::{util::SQUARE_4, Land, CanvasInfo};
use common::terrain::{Block, BlockKind};
use num::Integer;
use rand::prelude::*;

View File

@ -1,7 +1,7 @@
use super::*;
use crate::{
util::{RandomField, Sampler, LOCALITY},
Land,
Land, CanvasInfo,
};
use common::{
generation::EntityInfo,

View File

@ -3,7 +3,7 @@ use crate::{
site::namegen::NameGen,
site2::{aabr_with_z, Fill, Primitive, Structure as SiteStructure},
util::{attempt, Grid, RandomField, Sampler, CARDINALS, DIRS},
Land,
Land, CanvasInfo,
};
use common::{

View File

@ -3,7 +3,7 @@ use crate::{
site::namegen::NameGen,
site2::{Fill, Painter, Site, Structure},
util::FastNoise,
Land, Sampler,
Land, Sampler, CanvasInfo,
};
use common::{
generation::EntityInfo,

View File

@ -3,7 +3,7 @@ use crate::{
assets::AssetHandle,
site2::{gen::PrimitiveTransform, util::Dir},
util::{attempt, sampler::Sampler, RandomField},
Land,
Land, CanvasInfo,
};
use common::{
generation::{ChunkSupplement, EntityInfo},

View File

@ -2,7 +2,7 @@ use super::*;
use crate::{
site2::util::Dir,
util::{RandomField, Sampler, DIRS},
Land,
Land, CanvasInfo,
};
use common::terrain::{Block, BlockKind, SpriteKind};
use rand::prelude::*;

View File

@ -1,7 +1,7 @@
use super::*;
use crate::{
util::{RandomField, Sampler},
Land,
Land, CanvasInfo,
};
use common::{
generation::EntityInfo,