Fixed path irregularities, better bridges

This commit is contained in:
Joshua Barretto 2020-04-13 21:37:47 +01:00
parent e352858c03
commit a51d214c21
7 changed files with 65 additions and 33 deletions

View File

@ -66,6 +66,7 @@ impl<'a> BlockGen<'a> {
// Conservative range of radius: [8, 47] // Conservative range of radius: [8, 47]
let radius = RandomField::new(seed + 2).get(cliff_pos3d) % 48 + 8; let radius = RandomField::new(seed + 2).get(cliff_pos3d) % 48 + 8;
if cliff_sample.water_dist.map(|d| d > radius as f32).unwrap_or(true) {
max_height.max( max_height.max(
if cliff_pos.map(|e| e as f32).distance_squared(wpos) if cliff_pos.map(|e| e as f32).distance_squared(wpos)
< (radius as f32 + tolerance).powf(2.0) < (radius as f32 + tolerance).powf(2.0)
@ -75,6 +76,9 @@ impl<'a> BlockGen<'a> {
0.0 0.0
}, },
) )
} else {
max_height
}
}, },
_ => max_height, _ => max_height,
}, },

View File

@ -28,6 +28,7 @@ pub fn structure_gen<'a>(
if (st_sample.tree_density as f64) < random_seed if (st_sample.tree_density as f64) < random_seed
|| st_sample.alt < st_sample.water_level || st_sample.alt < st_sample.water_level
|| st_sample.spawn_rate < 0.5 || st_sample.spawn_rate < 0.5
|| st_sample.water_dist.map(|d| d < 8.0).unwrap_or(false)
{ {
return None; return None;
} }

View File

@ -95,9 +95,11 @@ impl Civs {
let wpos = site.center * Vec2::from(TerrainChunkSize::RECT_SIZE).map(|e: u32| e as i32); let wpos = site.center * Vec2::from(TerrainChunkSize::RECT_SIZE).map(|e: u32| e as i32);
// Flatten ground // Flatten ground
let flatten_radius = 12.0; let flatten_radius = 10.0;
if let Some(center_alt) = ctx.sim.get_alt_approx(wpos) { if let Some(center_alt) = ctx.sim.get_alt_approx(wpos) {
for pos in Spiral2d::new().map(|offs| site.center + offs).take(radius.pow(2) as usize) { for offs in Spiral2d::new().take(radius.pow(2) as usize) {
let center_alt = center_alt + if offs.magnitude_squared() <= 6i32.pow(2) { 16.0 } else { 0.0 }; // Raise the town centre up a little
let pos = site.center + offs;
let factor = (1.0 - (site.center - pos).map(|e| e as f32).magnitude() / flatten_radius) * 1.15; let factor = (1.0 - (site.center - pos).map(|e| e as f32).magnitude() / flatten_radius) * 1.15;
ctx.sim ctx.sim
.get_mut(pos) .get_mut(pos)

View File

@ -679,7 +679,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
Some((river_dist - river_width * 0.5) as f32), Some((river_dist - river_width * 0.5) as f32),
alt_for_river.min(lake_water_alt - 1.0 - river_gouge), alt_for_river.min(lake_water_alt - 1.0 - river_gouge),
lake_water_alt - river_gouge, lake_water_alt - river_gouge,
alt_for_river.min(lake_water_alt - 1.0), alt_for_river.max(lake_water_alt),
0.0, 0.0,
)); ));
} }
@ -753,7 +753,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
Some(lake_dist as f32), Some(lake_dist as f32),
alt_for_river.min(lake_water_alt - 1.0 - river_gouge), alt_for_river.min(lake_water_alt - 1.0 - river_gouge),
lake_water_alt - river_gouge, lake_water_alt - river_gouge,
alt_for_river.min(lake_water_alt - 1.0), alt_for_river.max(lake_water_alt),
0.0, 0.0,
)); ));
} }
@ -774,7 +774,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
alt.min(lake_water_alt - 1.0 - river_gouge), alt.min(lake_water_alt - 1.0 - river_gouge),
downhill_water_alt.max(lake_water_alt) downhill_water_alt.max(lake_water_alt)
- river_gouge, - river_gouge,
alt.min(lake_water_alt - 1.0), alt.max(lake_water_alt),
0.0, 0.0,
)); ));
} else { } else {

View File

@ -1867,7 +1867,8 @@ impl SimChunk {
) )
}; };
let cliff = gen_ctx.cliff_nz.get((wposf.div(2048.0)).into_array()) as f32 + chaos * 0.2; //let cliff = gen_ctx.cliff_nz.get((wposf.div(2048.0)).into_array()) as f32 + chaos * 0.2;
let cliff = 0.0; // Disable cliffs
// Logistic regression. Make sure x ∈ (0, 1). // Logistic regression. Make sure x ∈ (0, 1).
let logit = |x: f64| x.ln() - x.neg().ln_1p(); let logit = |x: f64| x.ln() - x.neg().ln_1p();

View File

@ -11,6 +11,20 @@ use super::{
super::skeleton::*, super::skeleton::*,
}; };
const COLOR_THEMES: [Rgb<u8>; 11] = [
Rgb::new(0x1D, 0x4D, 0x45),
Rgb::new(0xB3, 0x7D, 0x60),
Rgb::new(0xAC, 0x5D, 0x26),
Rgb::new(0x32, 0x46, 0x6B),
Rgb::new(0x2B, 0x19, 0x0F),
Rgb::new(0x93, 0x78, 0x51),
Rgb::new(0x92, 0x57, 0x24),
Rgb::new(0x4A, 0x4E, 0x4E),
Rgb::new(0x2F, 0x32, 0x47),
Rgb::new(0x8F, 0x35, 0x43),
Rgb::new(0x6D, 0x1E, 0x3A),
];
pub struct House { pub struct House {
roof_color: Rgb<u8>, roof_color: Rgb<u8>,
noise: RandomField, noise: RandomField,
@ -116,11 +130,10 @@ impl Archetype for House {
}; };
let this = Self { let this = Self {
roof_color: Rgb::new( roof_color: COLOR_THEMES
rng.gen_range(50, 200), .choose(rng)
rng.gen_range(50, 200), .unwrap()
rng.gen_range(50, 200), .map(|e| e.saturating_add(rng.gen_range(0, 20)) - 10),
),
noise: RandomField::new(rng.gen()), noise: RandomField::new(rng.gen()),
roof_ribbing: rng.gen(), roof_ribbing: rng.gen(),
roof_ribbing_diagonal: rng.gen(), roof_ribbing_diagonal: rng.gen(),
@ -141,7 +154,7 @@ impl Archetype for House {
let make_block = |r, g, b| { let make_block = |r, g, b| {
let nz = self.noise.get(Vec3::new(center_offset.x, center_offset.y, z * 8)); let nz = self.noise.get(Vec3::new(center_offset.x, center_offset.y, z * 8));
BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b) + (nz & 0x0F) as u8 - 8), 2) BlockMask::new(Block::new(BlockKind::Normal, Rgb::new(r, g, b).map(|e: u8| e.saturating_add((nz & 0x0F) as u8).saturating_sub(8))), 2)
}; };
let facade_layer = 3; let facade_layer = 3;

View File

@ -251,7 +251,7 @@ impl Settlement {
} }
pub fn place_town(&mut self, ctx: &mut GenCtx<impl Rng>) { pub fn place_town(&mut self, ctx: &mut GenCtx<impl Rng>) {
const PLOT_COUNT: usize = 2; const PLOT_COUNT: usize = 3;
let mut origin = Vec2::new(ctx.rng.gen_range(-2, 3), ctx.rng.gen_range(-2, 3)); let mut origin = Vec2::new(ctx.rng.gen_range(-2, 3), ctx.rng.gen_range(-2, 3));
@ -273,6 +273,7 @@ impl Settlement {
} }
// Boundary wall // Boundary wall
/*
let spokes = CARDINALS let spokes = CARDINALS
.iter() .iter()
.filter_map(|dir| { .filter_map(|dir| {
@ -316,6 +317,7 @@ impl Settlement {
} }
self.land self.land
.write_path(&wall_path, WayKind::Wall, buildable, true); .write_path(&wall_path, WayKind::Wall, buildable, true);
*/
} }
pub fn place_buildings(&mut self, ctx: &mut GenCtx<impl Rng>) { pub fn place_buildings(&mut self, ctx: &mut GenCtx<impl Rng>) {
@ -326,10 +328,11 @@ impl Settlement {
}; };
for tile in Spiral2d::new().map(|offs| town_center + offs).take(16usize.pow(2)) { for tile in Spiral2d::new().map(|offs| town_center + offs).take(16usize.pow(2)) {
for _ in 0..ctx.rng.gen_range(1, 5) { // This is a stupid way to decide how to place buildings
for _ in 0..10 { for _ in 0..ctx.rng.gen_range(2, 5) {
for _ in 0..25 {
let house_pos = tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2) let house_pos = tile.map(|e| e * AREA_SIZE as i32 + AREA_SIZE as i32 / 2)
+ Vec2::<i32>::zero().map(|_| ctx.rng.gen_range(-(AREA_SIZE as i32) / 2, AREA_SIZE as i32) / 2); + Vec2::<i32>::zero().map(|_| ctx.rng.gen_range(-(AREA_SIZE as i32) / 2, AREA_SIZE as i32 / 2));
let tile_pos = house_pos.map(|e| e.div_euclid(AREA_SIZE as i32)); let tile_pos = house_pos.map(|e| e.div_euclid(AREA_SIZE as i32));
if !matches!(self.land.plot_at(tile_pos), Some(Plot::Town)) if !matches!(self.land.plot_at(tile_pos), Some(Plot::Town))
@ -481,20 +484,23 @@ impl Settlement {
// Try to use the column at the centre of the path for sampling to make them flatter // Try to use the column at the centre of the path for sampling to make them flatter
let col = get_column(offs + (nearest.floor().map(|e| e as i32) - rpos)).unwrap_or(col_sample); let col = get_column(offs + (nearest.floor().map(|e| e as i32) - rpos)).unwrap_or(col_sample);
let bridge_offset = if let Some(water_dist) = col.water_dist { let (bridge_offset, depth) = if let Some(water_dist) = col.water_dist {
((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0 (
((water_dist.max(0.0) * 0.2).min(f32::consts::PI).cos() + 1.0) * 5.0,
((1.0 - ((water_dist + 2.0) * 0.3).min(0.0).cos().abs()) * (col.riverless_alt + 5.0 - col.alt).max(0.0) * 1.75 + 3.0) as i32,
)
} else { } else {
0.0 (0.0, 3)
}; };
let surface_z = (col.riverless_alt + bridge_offset).floor() as i32; let surface_z = (col.riverless_alt + bridge_offset).floor() as i32;
for z in inset - 3..inset { for z in inset - depth..inset {
vol.set( vol.set(
Vec3::new(offs.x, offs.y, surface_z + z), Vec3::new(offs.x, offs.y, surface_z + z),
if bridge_offset >= 2.0 { if bridge_offset >= 2.0 && dist >= 2.5 || z < inset - 1 {
Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8)) Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 80, 100), 8))
} else { } else {
Block::new(BlockKind::Normal, noisy_color(Rgb::new(90, 70, 50), 8)) Block::new(BlockKind::Normal, noisy_color(Rgb::new(80, 50, 30), 8))
}, },
); );
} }
@ -622,7 +628,10 @@ impl Settlement {
Some(Plot::Dirt) => return Some(Rgb::new(90, 70, 50)), Some(Plot::Dirt) => return Some(Rgb::new(90, 70, 50)),
Some(Plot::Grass) => return Some(Rgb::new(100, 200, 0)), Some(Plot::Grass) => return Some(Rgb::new(100, 200, 0)),
Some(Plot::Water) => return Some(Rgb::new(100, 150, 250)), Some(Plot::Water) => return Some(Rgb::new(100, 150, 250)),
Some(Plot::Town) => return Some(Rgb::new(130, 120, 80)), Some(Plot::Town) => return Some(Rgb::new(150, 110, 60)
.map2(Rgb::iota(), |e: u8, i: i32| e
.saturating_add((self.noise.get(Vec3::new(pos.x, pos.y, i * 5)) % 16) as u8)
.saturating_sub(8))),
Some(Plot::Field { seed, .. }) => { Some(Plot::Field { seed, .. }) => {
let furrow_dirs = [ let furrow_dirs = [
Vec2::new(1, 0), Vec2::new(1, 0),
@ -760,7 +769,9 @@ impl Land {
let proj_point = line.projected_point(pos.map(|e| e as f32)); let proj_point = line.projected_point(pos.map(|e| e as f32));
let dist = proj_point.distance(pos.map(|e| e as f32)); let dist = proj_point.distance(pos.map(|e| e as f32));
if dist < way.width() { if dist < way.width() {
sample.way = Some((way, dist, proj_point)); sample.way = sample.way
.filter(|(_, d, _)| *d < dist)
.or(Some((way, dist, proj_point)));
} }
} }
} }