mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Addressing concerns, for real.
This commit is contained in:
parent
688563accf
commit
398c18359d
@ -1,5 +1,6 @@
|
||||
#![deny(unsafe_code)]
|
||||
#![feature(
|
||||
box_syntax,
|
||||
const_generics,
|
||||
euclidean_division,
|
||||
bind_by_move_pattern_guards,
|
||||
|
@ -54,8 +54,7 @@ struct GenCdf {
|
||||
temp_base: InverseCdf,
|
||||
alt_base: InverseCdf,
|
||||
chaos: InverseCdf,
|
||||
alt_main: InverseCdf,
|
||||
alt_pre: InverseCdf,
|
||||
alt: InverseCdf,
|
||||
}
|
||||
|
||||
pub(crate) struct GenCtx {
|
||||
@ -191,6 +190,8 @@ impl WorldSim {
|
||||
// [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
|
||||
@ -204,36 +205,41 @@ impl WorldSim {
|
||||
.max(0.1)
|
||||
});
|
||||
|
||||
// This is the extension upwards from the base added to some extra noise from -1 to 1.
|
||||
// The extra noise is multiplied by alt_main (the mountain part of the extension) clamped to
|
||||
// be between 0.25 and 1, and made 60% larger (so the extra noise is between -1.6 and 1.6,
|
||||
// and the final noise is never more than 160% or less than 40% of the original noise,
|
||||
// depending on altitude).
|
||||
// Adding this to alt_main thus yields a value between -0.4 (if alt_main = 0 and
|
||||
// gen_ctx = -1) and 2.6 (if alt_main = 1 and gen_ctx = 1). When the generated small_nz
|
||||
// value hits -0.625 the value crosses 0, so most of the points are above 0.
|
||||
//
|
||||
// Then, we add 1 and divide by 2 to get a value between 0.3 and 1.8.
|
||||
let alt_main = uniform_noise(|_, wposf| {
|
||||
// Extension upwards from the base. A positive number from 0 to 1 curved to be maximal
|
||||
// at 0. Also to be multiplied by CONFIG.mountain_scale.
|
||||
let alt_main = (gen_ctx.alt_nz.get((wposf.div(2_000.0)).into_array()) as f32)
|
||||
.abs()
|
||||
.powf(1.45);
|
||||
|
||||
(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.2))
|
||||
.add(1.0)
|
||||
.mul(0.5)
|
||||
});
|
||||
|
||||
// We ignore sea level because we actually want to be relative to sea level here and want
|
||||
// things in CONFIG.mountain_scale units, and we are using the version of chaos that doesn't
|
||||
// know about temperature. Otherwise, this is a correct altitude calculation.
|
||||
let alt_pre = uniform_noise(|posi, _| {
|
||||
(alt_base[posi].1 + alt_main[posi].1.mul(chaos[posi].1.max(0.1)))
|
||||
// things in CONFIG.mountain_scale units, but otherwise this is a correct altitude
|
||||
// calculation. Note that this is using the "unadjusted" temperature.
|
||||
let alt = uniform_noise(|posi, wposf| {
|
||||
// This is the extension upwards from the base added to some extra noise from -1 to 1.
|
||||
// The extra noise is multiplied by alt_main (the mountain part of the extension)
|
||||
// clamped to [0.25, 1], and made 60% larger (so the extra noise is between [-1.6, 1.6],
|
||||
// and the final noise is never more than 160% or less than 40% of the original noise,
|
||||
// depending on altitude).
|
||||
// Adding this to alt_main thus yields a value between -0.4 (if alt_main = 0 and
|
||||
// gen_ctx = -1) and 2.6 (if alt_main = 1 and gen_ctx = 1). When the generated small_nz
|
||||
// value hits -0.625 the value crosses 0, so most of the points are above 0.
|
||||
//
|
||||
// Then, we add 1 and divide by 2 to get a value between 0.3 and 1.8.
|
||||
let alt_main = {
|
||||
// Extension upwards from the base. A positive number from 0 to 1 curved to be
|
||||
// maximal at 0. Also to be multiplied by CONFIG.mountain_scale.
|
||||
let alt_main = (gen_ctx.alt_nz.get((wposf.div(2_000.0)).into_array()) as f32)
|
||||
.abs()
|
||||
.powf(1.45);
|
||||
|
||||
(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.2))
|
||||
.add(1.0)
|
||||
.mul(0.5)
|
||||
};
|
||||
|
||||
// Now we can compute the final altitude using chaos.
|
||||
// We multiply by chaos clamped to [0.1, 1.24] to get a value between 0.03 and 2.232 for
|
||||
// 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))
|
||||
});
|
||||
|
||||
@ -242,8 +248,7 @@ impl WorldSim {
|
||||
temp_base,
|
||||
alt_base,
|
||||
chaos,
|
||||
alt_main,
|
||||
alt_pre,
|
||||
alt,
|
||||
};
|
||||
|
||||
let mut chunks = Vec::new();
|
||||
@ -508,36 +513,28 @@ impl SimChunk {
|
||||
let (_, alt_base) = gen_cdf.alt_base[posi];
|
||||
let map_edge_factor = map_edge_factor(posi);
|
||||
let (_, chaos) = gen_cdf.chaos[posi];
|
||||
let (_, alt_pre) = gen_cdf.alt_main[posi];
|
||||
let (humid_base, _) = gen_cdf.humid_base[posi];
|
||||
let (alt_uniform, _) = gen_cdf.alt_pre[posi];
|
||||
let (humid_uniform, _) = gen_cdf.humid_base[posi];
|
||||
let (alt_uniform, alt_pre) = gen_cdf.alt[posi];
|
||||
let (temp_uniform, _) = gen_cdf.temp_base[posi];
|
||||
|
||||
// Take the weighted average of our randomly generated base humidity, the scaled
|
||||
// negative altitude, and other random variable (to add some noise) to yield the
|
||||
// final humidity. Note that we are using the "old" version of chaos here.
|
||||
const HUMID_WEIGHTS: [f32; 2] = [1.0, 1.0];
|
||||
let humidity = cdf_irwin_hall(&HUMID_WEIGHTS, [humid_base, 1.0 - alt_uniform]);
|
||||
|
||||
let (temp_base, _) = gen_cdf.temp_base[posi];
|
||||
let humidity = cdf_irwin_hall(&HUMID_WEIGHTS, [humid_uniform, 1.0 - alt_uniform]);
|
||||
|
||||
// We also correlate temperature negatively with altitude using different weighting than we
|
||||
// use for humidity.
|
||||
const TEMP_WEIGHTS: [f32; 2] = [2.0, 1.0];
|
||||
let temp = cdf_irwin_hall(&TEMP_WEIGHTS, [temp_base, 1.0 - alt_uniform])
|
||||
let temp = cdf_irwin_hall(&TEMP_WEIGHTS, [temp_uniform, 1.0 - alt_uniform])
|
||||
// Convert to [-1, 1]
|
||||
.sub(0.5)
|
||||
.mul(2.0);
|
||||
|
||||
// Now we can recompute altitude using the correct verison of chaos.
|
||||
// We multiply by chaos clamped to [0.1, 1.24] to get a value between 0.03 and 2.232 for
|
||||
// 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).
|
||||
let alt_base = alt_base.mul(CONFIG.mountain_scale);
|
||||
let alt = CONFIG
|
||||
.sea_level
|
||||
.add(alt_base)
|
||||
.add(alt_pre.mul(chaos).mul(CONFIG.mountain_scale))
|
||||
.mul(map_edge_factor);
|
||||
.sea_level.mul(map_edge_factor)
|
||||
.add(alt_pre.mul(CONFIG.mountain_scale));
|
||||
|
||||
let cliff = gen_ctx.cliff_nz.get((wposf.div(2048.0)).into_array()) as f32 + chaos * 0.2;
|
||||
|
||||
|
@ -152,7 +152,11 @@ pub fn uniform_noise(f: impl Fn(usize, Vec2<f64>) -> f32) -> InverseCdf {
|
||||
// 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.
|
||||
let mut uniform_noise = Box::new([(0.0, 0.0); WORLD_SIZE.x * WORLD_SIZE.y]);
|
||||
//
|
||||
// NOTE: Currently there doesn't seem to be a way to create a large fixed-size
|
||||
// array on the heap without overflowing the stack unless you use placement box (at least on
|
||||
// debug mode). So I want to keep using this until a better alternative is made available.
|
||||
let mut uniform_noise = box [(0.0, 0.0); WORLD_SIZE.x * WORLD_SIZE.y];
|
||||
let total = (WORLD_SIZE.x * WORLD_SIZE.y) 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);
|
||||
|
Loading…
Reference in New Issue
Block a user