From 6f12a240de04dbd4aef8d486e69929b1f5126f09 Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sun, 25 Aug 2019 17:49:33 +0200 Subject: [PATCH 1/2] Chaos doesn't depend on temperature anymore. Also fix some things to use a consistent coordinate system and bump up tree density and variation around tree density in hopes of creating more aesthetically pleasing jungles. However, this does change worldgen a bit, so please make sure you look through it before merging. --- world/src/block/natural.rs | 2 +- world/src/sim/mod.rs | 62 +++++++++++++++++++++++--------------- world/src/sim/util.rs | 8 ++++- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/world/src/block/natural.rs b/world/src/block/natural.rs index 86ee632ea5..1d12a72cc5 100644 --- a/world/src/block/natural.rs +++ b/world/src/block/natural.rs @@ -25,7 +25,7 @@ pub fn structure_gen<'a>( let st_sample = &structure_samples[idx].as_ref()?; // Assuming it's a tree... figure out when it SHOULDN'T spawn - if st_sample.tree_density < 0.5 + (st_seed as f32 / 1000.0).fract() * 0.2 + if st_sample.tree_density < 0.5 + (st_seed as f32 / 1000.0).fract() * 0.5 || st_sample.alt < st_sample.water_level || st_sample.spawn_rate < 0.5 { diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index df8bfa9332..7ea6bbf283 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -5,7 +5,10 @@ mod util; // Reexports pub use self::location::Location; pub use self::settlement::Settlement; -use self::util::{cdf_irwin_hall, uniform_idx_as_vec2, uniform_noise, InverseCdf}; +use self::util::{ + cdf_irwin_hall, uniform_idx_as_vec2, uniform_noise, vec2_as_uniform_idx, + InverseCdf, +}; use crate::{ all::ForestKind, @@ -143,11 +146,6 @@ impl WorldSim { ) }); - // -1 to 1. - let temp_base = uniform_noise(|_, wposf| { - Some((gen_ctx.temp_nz.get((wposf.div(12000.0)).into_array()) as f32)) - }); - // chaos produces a value in [0.1, 1.24]. It is a meta-level factor intended to reflect how // "chaotic" the region is--how much weird stuff is going on on this terrain. let chaos = uniform_noise(|posi, wposf| { @@ -180,20 +178,6 @@ impl WorldSim { // hill is 0 about 50% of the time). // [0, 1] + 0.15 * [0, 1.6] = [0, 1.24] .add(0.2 * hill) - // [0, 1.24] * [0.35, 1.0] = [0, 1.24]. - // Sharply decreases (towards 0.35) when temperature is near desert_temp (from below), - // then saturates just before it actually becomes desert. Otherwise stays at 1. - // Note that this is not the *final* temperature, only the initial noise value for - // temperature. - .mul( - temp_base[posi] - .1 - .sub(0.45) - .neg() - .mul(12.0) - .max(0.35) - .min(1.0), - ) // We can't have *no* chaos! .max(0.1), ) @@ -236,9 +220,36 @@ impl WorldSim { Some((alt_base[posi].1 + alt_main.mul(chaos[posi].1)).mul(map_edge_factor(posi))) }); + // Check whether any tiles around this tile are not water (since Lerp will ensure that they + // are included). + let pure_water = |posi| { + let pos = uniform_idx_as_vec2(posi); + for x in (pos.x - 1..=pos.x + 1) { + for y in (pos.y - 1..=pos.y + 1) { + if x >= 0 && y >= 0 && x < WORLD_SIZE.x as i32 && y < WORLD_SIZE.y as i32 { + let posi = vec2_as_uniform_idx(Vec2::new(x, y)); + if alt[posi].1.mul(CONFIG.mountain_scale) > 0.0 { + return false + } + } + } + } + true + }; + + // -1 to 1. + let temp_base = uniform_noise(|posi, wposf| { + if pure_water(posi) { + None + } else { + Some((gen_ctx.temp_nz.get((wposf.div(12000.0)).into_array()) as f32)) + } + }); + // 0 to 1, hopefully. let humid_base = uniform_noise(|posi, wposf| { - if alt[posi].1 <= 5.0.div(CONFIG.mountain_scale) { + // Check whether any tiles around this tile are water. + if pure_water(posi) { None } else { Some( @@ -398,7 +409,7 @@ impl WorldSim { .map2(WORLD_SIZE, |e, sz| e >= 0 && e < sz as i32) .reduce_and() { - Some(&self.chunks[chunk_pos.y as usize * WORLD_SIZE.x + chunk_pos.x as usize]) + Some(&self.chunks[vec2_as_uniform_idx(chunk_pos)]) } else { None } @@ -409,7 +420,7 @@ impl WorldSim { .map2(WORLD_SIZE, |e, sz| e >= 0 && e < sz as i32) .reduce_and() { - Some(&mut self.chunks[chunk_pos.y as usize * WORLD_SIZE.x + chunk_pos.x as usize]) + Some(&mut self.chunks[vec2_as_uniform_idx(chunk_pos)]) } else { None } @@ -573,9 +584,9 @@ impl SimChunk { // Weighted logit sum. logistic_cdf(logit(humidity) + 0.5 * logit(tree_density)) } - // rescale to (-0.9, 0.9) + // rescale to (-0.95, 0.95) .sub(0.5) - .mul(0.9) + .mul(0.95) .add(0.5) }; @@ -614,6 +625,7 @@ impl SimChunk { } } else if temp > CONFIG.tropical_temp { if humidity > CONFIG.jungle_hum { + println!("Mangrove: {:?}", wposf); ForestKind::Mangrove } else if humidity > CONFIG.forest_hum { // NOTE: Probably the wrong kind of tree for this climate. diff --git a/world/src/sim/util.rs b/world/src/sim/util.rs index cf30ed11e3..48aa836665 100644 --- a/world/src/sim/util.rs +++ b/world/src/sim/util.rs @@ -96,7 +96,13 @@ pub type InverseCdf = Box<[(f32, f32)]>; /// Computes the position Vec2 of a SimChunk from an index, where the index was generated by /// uniform_noise. pub fn uniform_idx_as_vec2(idx: usize) -> Vec2 { - Vec2::new((idx / WORLD_SIZE.x) as i32, (idx % WORLD_SIZE.x) as i32) + Vec2::new((idx % WORLD_SIZE.x) as i32, (idx / WORLD_SIZE.x) as i32) +} + +/// Computes the index of a Vec2 of a SimChunk from a position, where the index is generated by +/// uniform_noise. NOTE: Both components of idx should be in-bounds! +pub fn vec2_as_uniform_idx(idx: Vec2) -> usize { + (idx.y as usize * WORLD_SIZE.x + idx.x as usize) as usize } /// Compute inverse cumulative distribution function for arbitrary function f, the hard way. We From 958a40b8c0540113a3b3fe14cd475ba7c82f6acd Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sun, 25 Aug 2019 18:17:51 +0200 Subject: [PATCH 2/2] Fix clean code lints. --- world/src/sim/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 7ea6bbf283..a259a98309 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -6,8 +6,7 @@ mod util; pub use self::location::Location; pub use self::settlement::Settlement; use self::util::{ - cdf_irwin_hall, uniform_idx_as_vec2, uniform_noise, vec2_as_uniform_idx, - InverseCdf, + cdf_irwin_hall, uniform_idx_as_vec2, uniform_noise, vec2_as_uniform_idx, InverseCdf, }; use crate::{ @@ -229,7 +228,7 @@ impl WorldSim { if x >= 0 && y >= 0 && x < WORLD_SIZE.x as i32 && y < WORLD_SIZE.y as i32 { let posi = vec2_as_uniform_idx(Vec2::new(x, y)); if alt[posi].1.mul(CONFIG.mountain_scale) > 0.0 { - return false + return false; } } } @@ -625,7 +624,6 @@ impl SimChunk { } } else if temp > CONFIG.tropical_temp { if humidity > CONFIG.jungle_hum { - println!("Mangrove: {:?}", wposf); ForestKind::Mangrove } else if humidity > CONFIG.forest_hum { // NOTE: Probably the wrong kind of tree for this climate.