From 798e8d7e8f24e8435740c7b53e0a802c5e03e27d Mon Sep 17 00:00:00 2001 From: Joshua Yanovski Date: Sat, 24 Aug 2019 21:13:32 +0200 Subject: [PATCH] Make humidity ignore ocean chunks. --- world/src/sim/mod.rs | 74 ++++++++++++++++++++++--------------------- world/src/sim/util.rs | 17 +++++----- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 50fa320036..f4f66828f9 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -132,10 +132,26 @@ impl WorldSim { .set_seed(gen_seed()), }; - // From 0 to 1.6, but the distribution before the max is from -1 and 1, so there is a 50% - // chance that hill will end up at 0. - let hill = uniform_noise(|_, wposf| { - (0.0 + gen_ctx + // "Base" of the chunk, to be multiplied by CONFIG.mountain_scale (multiplied value is + // from -0.25 * (CONFIG.mountain_scale * 1.1) to 0.25 * (CONFIG.mountain_scale * 0.9), + // but value here is from -0.275 to 0.225). + let alt_base = uniform_noise(|_, wposf| { + Some((gen_ctx.alt_nz.get((wposf.div(12_000.0)).into_array()) as f32) + .sub(0.1) + .mul(0.25)) + }); + + // -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| { + // From 0 to 1.6, but the distribution before the max is from -1 and 1, so there is a + // 50% chance that hill will end up at 0. + let hill = (0.0 + gen_ctx .hill_nz .get((wposf.div(1_500.0)).into_array()) .mul(1.0) as f32 @@ -144,34 +160,9 @@ impl WorldSim { .get((wposf.div(400.0)).into_array()) .mul(0.3) as f32) .add(0.3) - .max(0.0) - }); + .max(0.0); - // 0 to 1, hopefully. - let humid_base = uniform_noise(|_, wposf| { - (gen_ctx.humid_nz.get(wposf.div(1024.0).into_array()) as f32) - .add(1.0) - .mul(0.5) - }); - - // -1 to 1. - let temp_base = uniform_noise(|_, wposf| { - (gen_ctx.temp_nz.get((wposf.div(12000.0)).into_array()) as f32) - }); - - // "Base" of the chunk, to be multiplied by CONFIG.mountain_scale (multiplied value is - // from -0.25 * (CONFIG.mountain_scale * 1.1) to 0.25 * (CONFIG.mountain_scale * 0.9), - // but value here is from -0.275 to 0.225). - let alt_base = uniform_noise(|_, wposf| { - (gen_ctx.alt_nz.get((wposf.div(12_000.0)).into_array()) as f32) - .sub(0.1) - .mul(0.25) - }); - - // 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| { - (gen_ctx.chaos_nz.get((wposf.div(3_000.0)).into_array()) as f32) + Some((gen_ctx.chaos_nz.get((wposf.div(3_000.0)).into_array()) as f32) .add(1.0) .mul(0.5) // [0, 1] * [0.25, 1] = [0, 1] (but probably towards the lower end) @@ -184,7 +175,7 @@ impl WorldSim { // Chaos is always increased by a little when we're on a hill (but remember that // hill is 0 about 50% of the time). // [0, 1] + 0.15 * [0, 1.6] = [0, 1.24] - .add(0.2 * hill[posi].1) + .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. @@ -200,7 +191,7 @@ impl WorldSim { .min(1.0), ) // We can't have *no* chaos! - .max(0.1) + .max(0.1)) }); // We ignore sea level because we actually want to be relative to sea level here and want @@ -227,9 +218,9 @@ impl WorldSim { (0.0 + alt_main + (gen_ctx.small_nz.get((wposf.div(300.0)).into_array()) as f32) .mul(alt_main.max(0.25)) - .mul(0.3)) + .mul(0.3) .add(1.0) - .mul(0.5) + .mul(0.5)) }; // Now we can compute the final altitude using chaos. @@ -237,7 +228,18 @@ impl WorldSim { // alt_pre, then multiply by CONFIG.mountain_scale and add to the base and sea level to // get an adjusted value, then multiply the whole thing by map_edge_factor // (TODO: compute final bounds). - (alt_base[posi].1 + alt_main.mul(chaos[posi].1)).mul(map_edge_factor(posi)) + Some((alt_base[posi].1 + alt_main.mul(chaos[posi].1)).mul(map_edge_factor(posi))) + }); + + // 0 to 1, hopefully. + let humid_base = uniform_noise(|posi, wposf| { + if alt[posi].1 <= 5.0.div(CONFIG.mountain_scale) { + None + } else { + Some((gen_ctx.humid_nz.get(wposf.div(1024.0).into_array()) as f32) + .add(1.0) + .mul(0.5)) + } }); let gen_cdf = GenCdf { diff --git a/world/src/sim/util.rs b/world/src/sim/util.rs index 66a553b8db..5f1b3254b1 100644 --- a/world/src/sim/util.rs +++ b/world/src/sim/util.rs @@ -123,36 +123,37 @@ pub fn uniform_idx_as_vec2(idx: usize) -> Vec2 { /// vector returned by uniform_noise, and (for convenience) the float-translated version of those /// coordinates. /// f should return a value with no NaNs. If there is a NaN, it will panic. There are no other -/// conditions on f. +/// conditions on f. If f returns None, the value will be set to 0.0, and will be ignored for the +/// purposes of computing the uniform range. /// /// Returns a vec of (f32, f32) pairs consisting of the percentage of chunks with a value lower than /// this one, and the actual noise value (we don't need to cache it, but it makes ensuring that /// subsequent code that needs the noise value actually uses the same one we were using here /// easier). -pub fn uniform_noise(f: impl Fn(usize, Vec2) -> f32) -> InverseCdf { +pub fn uniform_noise(f: impl Fn(usize, Vec2) -> Option) -> InverseCdf { let mut noise = (0..WORLD_SIZE.x * WORLD_SIZE.y) - .map(|i| { + .filter_map(|i| { ( - i, f( i, (uniform_idx_as_vec2(i) * TerrainChunkSize::SIZE.map(|e| e as i32)) .map(|e| e as f64), - ), + ).map(|res| (i, res)) ) }) .collect::>(); - // sort_unstable_by is equivalent to sort_by here since we include the index in the + // sort_unstable_by is equivalent to sort_by here since we include a unique index in the // comparison. We could leave out the index, but this might make the order not // reproduce the same way between different versions of Rust (for example). noise.sort_unstable_by(|f, g| (f.1, f.0).partial_cmp(&(g.1, g.0)).unwrap()); // Construct a vector that associates each chunk position with the 1-indexed // position of the noise in the sorted vector (divided by the vector length). - // This guarantees a uniform distribution among the samples. + // This guarantees a uniform distribution among the samples (excluding those that returned + // None, which will remain at zero). let mut uniform_noise = vec![(0.0, 0.0); WORLD_SIZE.x * WORLD_SIZE.y].into_boxed_slice(); - let total = (WORLD_SIZE.x * WORLD_SIZE.y) as f32; + let total = noise.len() as f32; for (noise_idx, (chunk_idx, noise_val)) in noise.into_iter().enumerate() { uniform_noise[chunk_idx] = ((1 + noise_idx) as f32 / total, noise_val); }