Merge branch 'sharp/humidity_ignores_ocean' into 'master'

Make humidity ignore ocean chunks.

See merge request veloren/veloren!460
This commit is contained in:
Joshua Barretto 2019-08-24 19:47:22 +00:00
commit 47380090fa
2 changed files with 85 additions and 76 deletions

View File

@ -132,75 +132,71 @@ impl WorldSim {
.set_seed(gen_seed()), .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
.hill_nz
.get((wposf.div(1_500.0)).into_array())
.mul(1.0) as f32
+ gen_ctx
.hill_nz
.get((wposf.div(400.0)).into_array())
.mul(0.3) as f32)
.add(0.3)
.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 // "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), // 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). // but value here is from -0.275 to 0.225).
let alt_base = uniform_noise(|_, wposf| { let alt_base = uniform_noise(|_, wposf| {
(gen_ctx.alt_nz.get((wposf.div(12_000.0)).into_array()) as f32) Some(
.sub(0.1) (gen_ctx.alt_nz.get((wposf.div(12_000.0)).into_array()) as f32)
.mul(0.25) .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 // 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. // "chaotic" the region is--how much weird stuff is going on on this terrain.
let chaos = uniform_noise(|posi, wposf| { let chaos = uniform_noise(|posi, wposf| {
(gen_ctx.chaos_nz.get((wposf.div(3_000.0)).into_array()) as f32) // From 0 to 1.6, but the distribution before the max is from -1 and 1, so there is a
.add(1.0) // 50% chance that hill will end up at 0.
.mul(0.5) let hill = (0.0
// [0, 1] * [0.25, 1] = [0, 1] (but probably towards the lower end) + gen_ctx
.mul( .hill_nz
(gen_ctx.chaos_nz.get((wposf.div(6_000.0)).into_array()) as f32) .get((wposf.div(1_500.0)).into_array())
.abs() .mul(1.0) as f32
.max(0.25) + gen_ctx
.min(1.0), .hill_nz
) .get((wposf.div(400.0)).into_array())
// Chaos is always increased by a little when we're on a hill (but remember that .mul(0.3) as f32)
// hill is 0 about 50% of the time). .add(0.3)
// [0, 1] + 0.15 * [0, 1.6] = [0, 1.24] .max(0.0);
.add(0.2 * hill[posi].1)
// [0, 1.24] * [0.35, 1.0] = [0, 1.24]. Some(
// Sharply decreases (towards 0.35) when temperature is near desert_temp (from below), (gen_ctx.chaos_nz.get((wposf.div(3_000.0)).into_array()) as f32)
// then saturates just before it actually becomes desert. Otherwise stays at 1. .add(1.0)
// Note that this is not the *final* temperature, only the initial noise value for .mul(0.5)
// temperature. // [0, 1] * [0.25, 1] = [0, 1] (but probably towards the lower end)
.mul( .mul(
temp_base[posi] (gen_ctx.chaos_nz.get((wposf.div(6_000.0)).into_array()) as f32)
.1 .abs()
.sub(0.45) .max(0.25)
.neg() .min(1.0),
.mul(12.0) )
.max(0.35) // Chaos is always increased by a little when we're on a hill (but remember that
.min(1.0), // hill is 0 about 50% of the time).
) // [0, 1] + 0.15 * [0, 1.6] = [0, 1.24]
// We can't have *no* chaos! .add(0.2 * hill)
.max(0.1) // [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),
)
}); });
// We ignore sea level because we actually want to be relative to sea level here and want // We ignore sea level because we actually want to be relative to sea level here and want
@ -227,9 +223,9 @@ impl WorldSim {
(0.0 + alt_main (0.0 + alt_main
+ (gen_ctx.small_nz.get((wposf.div(300.0)).into_array()) as f32) + (gen_ctx.small_nz.get((wposf.div(300.0)).into_array()) as f32)
.mul(alt_main.max(0.25)) .mul(alt_main.max(0.25))
.mul(0.3)) .mul(0.3)
.add(1.0) .add(1.0)
.mul(0.5) .mul(0.5))
}; };
// Now we can compute the final altitude using chaos. // Now we can compute the final altitude using chaos.
@ -237,7 +233,20 @@ impl WorldSim {
// alt_pre, then multiply by CONFIG.mountain_scale and add to the base and sea level to // 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 // get an adjusted value, then multiply the whole thing by map_edge_factor
// (TODO: compute final bounds). // (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 { let gen_cdf = GenCdf {

View File

@ -123,36 +123,36 @@ pub fn uniform_idx_as_vec2(idx: usize) -> Vec2<i32> {
/// vector returned by uniform_noise, and (for convenience) the float-translated version of those /// vector returned by uniform_noise, and (for convenience) the float-translated version of those
/// coordinates. /// coordinates.
/// f should return a value with no NaNs. If there is a NaN, it will panic. There are no other /// 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 /// 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 /// 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 /// subsequent code that needs the noise value actually uses the same one we were using here
/// easier). /// easier).
pub fn uniform_noise(f: impl Fn(usize, Vec2<f64>) -> f32) -> InverseCdf { pub fn uniform_noise(f: impl Fn(usize, Vec2<f64>) -> Option<f32>) -> InverseCdf {
let mut noise = (0..WORLD_SIZE.x * WORLD_SIZE.y) let mut noise = (0..WORLD_SIZE.x * WORLD_SIZE.y)
.map(|i| { .filter_map(|i| {
( (f(
i, i,
f( (uniform_idx_as_vec2(i) * TerrainChunkSize::SIZE.map(|e| e as i32))
i, .map(|e| e as f64),
(uniform_idx_as_vec2(i) * TerrainChunkSize::SIZE.map(|e| e as i32))
.map(|e| e as f64),
),
) )
.map(|res| (i, res)))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
// 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 // 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). // 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()); 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 // 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). // 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 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() { for (noise_idx, (chunk_idx, noise_val)) in noise.into_iter().enumerate() {
uniform_noise[chunk_idx] = ((1 + noise_idx) as f32 / total, noise_val); uniform_noise[chunk_idx] = ((1 + noise_idx) as f32 / total, noise_val);
} }