mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
WIP fixes: more pleasing uplift generation.
Uses the exponential distribution now.
This commit is contained in:
parent
1b864887e7
commit
825ba1b4f4
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3305,6 +3305,7 @@ dependencies = [
|
||||
"noise 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -21,6 +21,7 @@ rayon = "1.2.0"
|
||||
roots = "0.0.5"
|
||||
serde = "1.0.102"
|
||||
ron = "0.5.1"
|
||||
pretty_env_logger = "0.3.0"
|
||||
|
||||
[dev-dependencies]
|
||||
minifb = { git = "https://github.com/emoon/rust_minifb.git" }
|
||||
|
@ -1,3 +1,5 @@
|
||||
use common::{terrain::TerrainChunkSize, vol::RectVolSize};
|
||||
use std::f32;
|
||||
use vek::*;
|
||||
use veloren_world::{
|
||||
sim::{RiverKind, WORLD_SIZE},
|
||||
@ -8,6 +10,8 @@ const W: usize = 1024;
|
||||
const H: usize = 1024;
|
||||
|
||||
fn main() {
|
||||
pretty_env_logger::init();
|
||||
|
||||
let world = World::generate(1337);
|
||||
|
||||
let sampler = world.sim();
|
||||
@ -16,12 +20,15 @@ fn main() {
|
||||
minifb::Window::new("World Viewer", W, H, minifb::WindowOptions::default()).unwrap();
|
||||
|
||||
let mut focus = Vec2::zero();
|
||||
let mut _gain = 1.0;
|
||||
let mut gain = CONFIG.mountain_scale;
|
||||
let mut scale = (WORLD_SIZE.x / W) as i32;
|
||||
|
||||
let light_direction = Vec3::new(-0.8, -1.0, 0.3).normalized();
|
||||
let light_res = 3;
|
||||
|
||||
while win.is_open() {
|
||||
let mut buf = vec![0; W * H];
|
||||
const QUADRANTS : usize = 4;
|
||||
const QUADRANTS: usize = 4;
|
||||
let mut quads = [[0u32; QUADRANTS]; QUADRANTS];
|
||||
let mut rivers = 0u32;
|
||||
let mut lakes = 0u32;
|
||||
@ -30,39 +37,86 @@ fn main() {
|
||||
for i in 0..W {
|
||||
for j in 0..H {
|
||||
let pos = focus + Vec2::new(i as i32, j as i32) * scale;
|
||||
/* let top_left = pos;
|
||||
let top_right = focus + Vec2::new(i as i32 + light_res, j as i32) * scale;
|
||||
let bottom_left = focus + Vec2::new(i as i32, j as i32 + light_res) * scale; */
|
||||
|
||||
let (alt, water_alt, humidity, temperature, river_kind) = sampler
|
||||
let (alt, water_alt, humidity, temperature, downhill, river_kind) = sampler
|
||||
.get(pos)
|
||||
.map(|sample| (sample.alt, sample.water_alt, sample.humidity, sample.temp, sample.river.river_kind))
|
||||
.unwrap_or((CONFIG.sea_level, CONFIG.sea_level, 0.0, 0.0, None));
|
||||
let humidity = humidity
|
||||
.map(|sample| {
|
||||
(
|
||||
sample.alt,
|
||||
sample.water_alt,
|
||||
sample.humidity,
|
||||
sample.temp,
|
||||
sample.downhill,
|
||||
sample.river.river_kind,
|
||||
)
|
||||
})
|
||||
.unwrap_or((CONFIG.sea_level, CONFIG.sea_level, 0.0, 0.0, None, None));
|
||||
let humidity = humidity.min(1.0).max(0.0);
|
||||
let temperature = temperature.min(1.0).max(-1.0) * 0.5 + 0.5;
|
||||
let downhill_pos = (downhill
|
||||
.map(|downhill_pos| downhill_pos.map2(TerrainChunkSize::RECT_SIZE, |e, sz: u32| e / sz as i32))
|
||||
.unwrap_or(pos)
|
||||
- pos)/* * scale*/
|
||||
+ pos;
|
||||
let downhill_alt = sampler
|
||||
.get(downhill_pos)
|
||||
.map(|s| s.alt)
|
||||
.unwrap_or(CONFIG.sea_level);
|
||||
/* let alt_tl = sampler.get(top_left).map(|s| s.alt)
|
||||
.unwrap_or(CONFIG.sea_level);
|
||||
let alt_tr = sampler.get(top_right).map(|s| s.alt)
|
||||
.unwrap_or(CONFIG.sea_level);
|
||||
let alt_bl = sampler.get(bottom_left).map(|s| s.alt)
|
||||
.unwrap_or(CONFIG.sea_level); */
|
||||
let cross_pos = pos
|
||||
+ ((downhill_pos - pos)
|
||||
.map(|e| e as f32)
|
||||
.rotated_z(f32::consts::FRAC_PI_2)
|
||||
.map(|e| e as i32));
|
||||
let cross_alt = sampler
|
||||
.get(cross_pos)
|
||||
.map(|s| s.alt)
|
||||
.unwrap_or(CONFIG.sea_level);
|
||||
let forward_vec = Vec3::new(
|
||||
(downhill_pos.x - pos.x) as f64,
|
||||
(downhill_pos.y - pos.y) as f64,
|
||||
(downhill_alt - alt) as f64,
|
||||
);
|
||||
let up_vec = Vec3::new(
|
||||
(cross_pos.x - pos.x) as f64,
|
||||
(cross_pos.y - pos.y) as f64,
|
||||
(cross_alt - alt) as f64,
|
||||
);
|
||||
let surface_normal = forward_vec.cross(up_vec).normalized();
|
||||
// let surface_normal = Vec3::new((alt_tl - alt_tr) as f64, 1.0, (alt_tl - alt_bl) as f64).normalized();
|
||||
let light = (surface_normal.dot(light_direction) + 1.0) / 2.0;
|
||||
let light = (light * 0.8) + 0.2;
|
||||
|
||||
let water_alt = ((alt.max(water_alt) - CONFIG.sea_level) as f64 / gain as f64)
|
||||
.min(1.0)
|
||||
.max(0.0);
|
||||
let temperature = temperature
|
||||
.min(1.0)
|
||||
.max(-1.0)
|
||||
* 0.5 + 0.5;
|
||||
let water_alt = ((alt.max(water_alt) - CONFIG.sea_level) / CONFIG.mountain_scale)
|
||||
let alt = ((alt - CONFIG.sea_level) as f64 / gain as f64)
|
||||
.min(1.0)
|
||||
.max(0.0);
|
||||
let alt = ((alt - CONFIG.sea_level) / CONFIG.mountain_scale)
|
||||
.min(1.0)
|
||||
.max(0.0);
|
||||
let quad = |x: f32| ((x as f64 * QUADRANTS as f64).floor() as usize).min(QUADRANTS - 1);
|
||||
let quad =
|
||||
|x: f32| ((x as f64 * QUADRANTS as f64).floor() as usize).min(QUADRANTS - 1);
|
||||
if river_kind.is_none() || humidity != 0.0 {
|
||||
quads[quad(humidity)][quad(temperature)] += 1;
|
||||
}
|
||||
match river_kind {
|
||||
Some(RiverKind::River { .. }) => {
|
||||
rivers += 1;
|
||||
},
|
||||
}
|
||||
Some(RiverKind::Lake { .. }) => {
|
||||
lakes += 1;
|
||||
},
|
||||
}
|
||||
Some(RiverKind::Ocean { .. }) => {
|
||||
oceans += 1;
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
buf[j * W + i] = match river_kind {
|
||||
@ -79,30 +133,56 @@ fn main() {
|
||||
0,
|
||||
255,
|
||||
]),
|
||||
None => u32::from_le_bytes([
|
||||
(/*alt * *//*(1.0 - humidity)*/(alt * humidity).sqrt()/*temperature*/ * 255.0) as u8,
|
||||
(/*alt*//*alt*//* * humidity*//*alt * 255.0*//*humidity*/alt * 255.0) as u8,
|
||||
(/*alt*//*alt * *//*(1.0 - humidity)*/(alt * temperature).sqrt() * 255.0) as u8,
|
||||
255,
|
||||
]),
|
||||
None => {
|
||||
let (r, g, b) = (
|
||||
(alt * humidity/*alt*/ as f64).sqrt(),
|
||||
0.2 + (alt * 0.8),
|
||||
(alt * temperature/*alt*/ as f64).sqrt(),
|
||||
);
|
||||
u32::from_le_bytes([
|
||||
(b * light * 255.0) as u8,
|
||||
(g * light * 255.0) as u8,
|
||||
(r * light * 255.0) as u8,
|
||||
255,
|
||||
])
|
||||
/* u32::from_le_bytes([
|
||||
(/*alt * *//*(1.0 - humidity)*/(alt * humidity).sqrt()/*temperature*/ * 255.0) as u8,
|
||||
(/*alt*//*alt*//* * humidity*//*alt * 255.0*//*humidity*/alt * 255.0) as u8,
|
||||
(/*alt*//*alt * *//*(1.0 - humidity)*/(alt * temperature).sqrt() * 255.0) as u8,
|
||||
255,
|
||||
]) */
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let spd = 32;
|
||||
if win.is_key_down(minifb::Key::P) {
|
||||
println!("\
|
||||
Land(adjacent): (X = temp, Y = humidity): {:?}\n\
|
||||
Rivers: {:?}\n\
|
||||
Lakes: {:?}\n\
|
||||
Oceans: {:?}\n\
|
||||
Total water: {:?}\n\
|
||||
Total land(adjacent): {:?}",
|
||||
quads, rivers, lakes, oceans,
|
||||
println!(
|
||||
"\
|
||||
Land(adjacent): (X = temp, Y = humidity): {:?}\n\
|
||||
Rivers: {:?}\n\
|
||||
Lakes: {:?}\n\
|
||||
Oceans: {:?}\n\
|
||||
Total water: {:?}\n\
|
||||
Total land(adjacent): {:?}",
|
||||
quads,
|
||||
rivers,
|
||||
lakes,
|
||||
oceans,
|
||||
rivers + lakes + oceans,
|
||||
quads.iter().map( |x| x.iter().sum::<u32>() ).sum::<u32>()
|
||||
quads.iter().map(|x| x.iter().sum::<u32>()).sum::<u32>()
|
||||
);
|
||||
}
|
||||
if win.get_mouse_down(minifb::MouseButton::Left) {
|
||||
if let Some((mx, my)) = win.get_mouse_pos(minifb::MouseMode::Clamp) {
|
||||
let pos = focus + Vec2::new(mx as i32, my as i32) * scale;
|
||||
println!(
|
||||
"Chunk position: {:?}",
|
||||
pos.map2(TerrainChunkSize::RECT_SIZE, |e, f| e * f as i32)
|
||||
);
|
||||
}
|
||||
}
|
||||
if win.is_key_down(minifb::Key::W) {
|
||||
focus.y -= spd * scale;
|
||||
}
|
||||
@ -116,10 +196,10 @@ fn main() {
|
||||
focus.x += spd * scale;
|
||||
}
|
||||
if win.is_key_down(minifb::Key::Q) {
|
||||
_gain += 10.0;
|
||||
gain += 64.0;
|
||||
}
|
||||
if win.is_key_down(minifb::Key::E) {
|
||||
_gain -= 10.0;
|
||||
gain = (gain - 64.0).max(64.0);
|
||||
}
|
||||
if win.is_key_down(minifb::Key::R) {
|
||||
scale += 1;
|
||||
|
@ -168,7 +168,7 @@ impl<'a> BlockGen<'a> {
|
||||
temp,
|
||||
humidity,
|
||||
chunk,
|
||||
stone_col,
|
||||
stone_col,
|
||||
..
|
||||
} = sample;
|
||||
|
||||
@ -253,7 +253,6 @@ impl<'a> BlockGen<'a> {
|
||||
saturate_srgb(sub_surface_color, 0.45).map(|e| (e * 255.0) as u8),
|
||||
stone_col,
|
||||
(height - grass_depth - wposf.z as f32) * 0.15,
|
||||
|
||||
);
|
||||
|
||||
// Underground
|
||||
|
@ -232,8 +232,6 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
let rockiness = sim.get_interpolated(wpos, |chunk| chunk.rockiness)?;
|
||||
let tree_density = sim.get_interpolated(wpos, |chunk| chunk.tree_density)?;
|
||||
let spawn_rate = sim.get_interpolated(wpos, |chunk| chunk.spawn_rate)?;
|
||||
let alt = sim.get_interpolated_monotone(wpos, |chunk| chunk.alt)?;
|
||||
|
||||
let sim_chunk = sim.get(chunk_pos)?;
|
||||
let neighbor_coef = TerrainChunkSize::RECT_SIZE.map(|e| e as f64);
|
||||
let my_chunk_idx = vec2_as_uniform_idx(chunk_pos);
|
||||
@ -408,6 +406,41 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
)
|
||||
});
|
||||
|
||||
let downhill = sim_chunk.downhill;
|
||||
let downhill_pos = downhill.and_then(|downhill_pos| sim.get(downhill_pos));
|
||||
debug_assert!(sim_chunk.water_alt >= CONFIG.sea_level);
|
||||
|
||||
let downhill_water_alt = downhill_pos
|
||||
.map(|downhill_chunk| {
|
||||
downhill_chunk
|
||||
.water_alt
|
||||
.min(sim_chunk.water_alt)
|
||||
.max(sim_chunk.alt.min(sim_chunk.water_alt))
|
||||
})
|
||||
.unwrap_or(CONFIG.sea_level);
|
||||
|
||||
let is_cliffs = sim_chunk.is_cliffs;
|
||||
let near_cliffs = sim_chunk.near_cliffs;
|
||||
|
||||
let is_rocky = sim_chunk.humidity < CONFIG.desert_hum
|
||||
&& (/*sim_chunk.temp < CONFIG.snow_temp || */sim_chunk.alt.sub(CONFIG.sea_level) >= CONFIG.mountain_scale * 0.25);
|
||||
/* let downhill_alt_rocky = downhill_pos
|
||||
.map(|downhill_chunk| {
|
||||
downhill_chunk.humidity < CONFIG.forest_hum &&
|
||||
(downhill_chunk.temperature < CONFIG.|| downhill_chunk.alt.sub(CONFIG.sea_level) >= CONFIG.mountain_scale * 0.25)
|
||||
})
|
||||
.unwrap_or(CONFIG.sea_level); */
|
||||
|
||||
let alt = if
|
||||
/*humidity < CONFIG.desert_hum &&
|
||||
(temp < CONFIG.snow_temp ||
|
||||
downhill_alt.sub(CONFIG.sea_level) >= CONFIG.mountain_scale * 0.25)*/
|
||||
is_rocky {
|
||||
sim.get_interpolated_bilinear(wpos, |chunk| chunk.alt)?
|
||||
} else {
|
||||
sim.get_interpolated_monotone(wpos, |chunk| chunk.alt)?
|
||||
};
|
||||
|
||||
// Find the average distance to each neighboring body of water.
|
||||
let mut river_count = 0.0f64;
|
||||
let mut overlap_count = 0.0f64;
|
||||
@ -542,13 +575,6 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
}
|
||||
};
|
||||
|
||||
let alt_for_river = alt
|
||||
+ if overlap_count == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
river_overlap_distance_product / overlap_count
|
||||
} as f32;
|
||||
|
||||
let cliff_hill = (sim
|
||||
.gen_ctx
|
||||
.small_nz
|
||||
@ -558,34 +584,26 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
let riverless_alt_delta = (sim
|
||||
.gen_ctx
|
||||
.small_nz
|
||||
.get((wposf_turb.div(200.0)).into_array()) as f32)
|
||||
.get((wposf_turb.div(/*200.0*//*50.0*//*24.0*//*56.0 / (chaos as f64).max(0.05)*/50.0)).into_array()) as f32)
|
||||
.abs()
|
||||
.mul(chaos.max(0.05))
|
||||
.mul(27.0)
|
||||
+ (sim
|
||||
.mul(3.0)
|
||||
/* .mul(chaos.max(0.05))
|
||||
.mul(27.0) */
|
||||
/* + (sim
|
||||
.gen_ctx
|
||||
.small_nz
|
||||
.get((wposf_turb.div(400.0)).into_array()) as f32)
|
||||
.abs()
|
||||
.mul((1.0 - chaos).max(0.3))
|
||||
.mul(1.0 - humidity)
|
||||
.mul(32.0);
|
||||
.mul(32.0) */;
|
||||
|
||||
let downhill = sim_chunk.downhill;
|
||||
let downhill_pos = downhill.and_then(|downhill_pos| sim.get(downhill_pos));
|
||||
debug_assert!(sim_chunk.water_alt >= CONFIG.sea_level);
|
||||
|
||||
let downhill_water_alt = downhill_pos
|
||||
.map(|downhill_chunk| {
|
||||
downhill_chunk
|
||||
.water_alt
|
||||
.min(sim_chunk.water_alt)
|
||||
.max(sim_chunk.alt.min(sim_chunk.water_alt))
|
||||
})
|
||||
.unwrap_or(CONFIG.sea_level);
|
||||
|
||||
let is_cliffs = sim_chunk.is_cliffs;
|
||||
let near_cliffs = sim_chunk.near_cliffs;
|
||||
let alt_for_river = alt
|
||||
+ if overlap_count == 0.0 {
|
||||
0.0
|
||||
} else {
|
||||
river_overlap_distance_product / overlap_count
|
||||
} as f32;
|
||||
|
||||
let river_gouge = 0.5;
|
||||
let (in_water, alt_, water_level, warp_factor) = if let Some((
|
||||
@ -848,9 +866,9 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
let snow = Rgb::new(0.8, 0.85, 1.0);
|
||||
// let snow = Rgb::new(0.0, 0.0, 0.1);
|
||||
|
||||
// let stone_col = Rgb::new(152, 98, 16);
|
||||
let stone_col = Rgb::new(195, 187, 201);
|
||||
/*let dirt = Lerp::lerp(
|
||||
// let stone_col = Rgb::new(152, 98, 16);
|
||||
let stone_col = Rgb::new(195, 187, 201);
|
||||
/*let dirt = Lerp::lerp(
|
||||
Rgb::new(0.4, 0.4, 0.4),
|
||||
Rgb::new(0.4, 0.4, 0.4),
|
||||
marble,
|
||||
@ -896,10 +914,11 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
sand,
|
||||
temp.sub(CONFIG.snow_temp)
|
||||
.div(CONFIG.desert_temp.sub(CONFIG.snow_temp))
|
||||
.mul(/*4.5*/0.5),
|
||||
.mul(/*4.5*/ 0.5),
|
||||
),
|
||||
cliff,
|
||||
alt.sub(CONFIG.mountain_scale * 0.25)
|
||||
alt.sub(CONFIG.sea_level)
|
||||
.sub(CONFIG.mountain_scale * 0.25)
|
||||
.div(CONFIG.mountain_scale * 0.125),
|
||||
);
|
||||
// From desert to forest humidity, we go from tundra to dirt to grass to moss to sand,
|
||||
@ -918,7 +937,7 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
/*.sub((marble - 0.5) * 0.05)
|
||||
.mul(256.0)*/
|
||||
.mul(1.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
),
|
||||
// 0 to tropical_temp
|
||||
grass,
|
||||
@ -929,20 +948,20 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
temp.sub(CONFIG.tropical_temp)
|
||||
.div(CONFIG.desert_temp.sub(CONFIG.tropical_temp))
|
||||
.mul(1.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
),
|
||||
// above desert_temp
|
||||
sand,
|
||||
temp.sub(CONFIG.desert_temp)
|
||||
.div(1.0 - CONFIG.desert_temp)
|
||||
.mul(4.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
),
|
||||
humidity
|
||||
.sub(CONFIG.desert_hum)
|
||||
.div(CONFIG.forest_hum.sub(CONFIG.desert_hum))
|
||||
.mul(1.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
);
|
||||
// From forest to jungle humidity, we go from snow to dark grass to grass to tropics to sand
|
||||
// depending on temperature.
|
||||
@ -961,20 +980,20 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
temp.sub(CONFIG.tropical_temp)
|
||||
.div(CONFIG.desert_temp.sub(CONFIG.tropical_temp))
|
||||
.mul(1.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
),
|
||||
// above desert_temp
|
||||
sand,
|
||||
temp.sub(CONFIG.desert_temp)
|
||||
.div(1.0 - CONFIG.desert_temp)
|
||||
.mul(4.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
),
|
||||
humidity
|
||||
.sub(CONFIG.forest_hum)
|
||||
.div(CONFIG.jungle_hum.sub(CONFIG.forest_hum))
|
||||
.mul(1.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
);
|
||||
// From jungle humidity upwards, we go from snow to grass to rainforest to tropics to sand.
|
||||
let ground = Rgb::lerp(
|
||||
@ -992,14 +1011,14 @@ impl<'a> Sampler<'a> for ColumnGen<'a> {
|
||||
temp.sub(CONFIG.tropical_temp)
|
||||
.div(CONFIG.desert_temp.sub(CONFIG.tropical_temp))
|
||||
.mul(4.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
),
|
||||
// above desert_temp
|
||||
sand,
|
||||
temp.sub(CONFIG.desert_temp)
|
||||
.div(1.0 - CONFIG.desert_temp)
|
||||
.mul(4.0),
|
||||
// .mul(2.0),
|
||||
// .mul(2.0),
|
||||
),
|
||||
humidity.sub(CONFIG.jungle_hum).mul(1.0),
|
||||
);
|
||||
|
@ -485,7 +485,11 @@ fn get_max_slope(h: &[f32], rock_strength_nz: &(impl NoiseFn<Point3<f64>> + Sync
|
||||
// Normalized to be between 6 and and 54 degrees.
|
||||
let div_factor = 32.0;
|
||||
let rock_strength = rock_strength_nz
|
||||
.get([wposf.x / div_factor, wposf.y / div_factor, wposz])
|
||||
.get([
|
||||
wposf.x, /* / div_factor*/
|
||||
wposf.y, /* / div_factor*/
|
||||
wposz,
|
||||
])
|
||||
.max(-1.0)
|
||||
.min(1.0)
|
||||
* 0.5
|
||||
@ -581,6 +585,9 @@ fn erode(
|
||||
) {
|
||||
log::debug!("Done draining...");
|
||||
let mmaxh = 1.0;
|
||||
// Landslide constant: ideally scaled to 10 m^-2 / y^-1
|
||||
let l = 200.0 * max_uplift as f64;
|
||||
// Erosion constant.
|
||||
let k = erosion_base as f64 + 2.244 / mmaxh as f64 * max_uplift as f64;
|
||||
let ((dh, indirection, newh, area), max_slope) = rayon::join(
|
||||
|| {
|
||||
@ -640,8 +647,8 @@ fn erode(
|
||||
let is_lake_bottom = indirection_idx < 0;
|
||||
// Test the slope.
|
||||
let max_slope = max_slope[posi] as f64;
|
||||
let dz = (new_h_i - h_j) * CONFIG.mountain_scale as f64;
|
||||
let mag_slope = dz.abs() / neighbor_distance;
|
||||
let dz = (new_h_i - h_j).max(0.0) * CONFIG.mountain_scale as f64;
|
||||
let mag_slope = dz/*.abs()*/ / neighbor_distance;
|
||||
let _fake_neighbor = is_lake_bottom && dxy.x.abs() > 1.0 && dxy.y.abs() > 1.0;
|
||||
// If you're on the lake bottom and not right next to your neighbor, don't compute a
|
||||
// slope.
|
||||
@ -656,9 +663,14 @@ fn erode(
|
||||
// exactly max_slope.
|
||||
// max_slope = (old_h_i + dh - h_j) * CONFIG.mountain_scale / NEIGHBOR_DISTANCE
|
||||
// dh = max_slope * NEIGHBOR_DISTANCE / CONFIG.mountain_scale + h_j - old_h_i.
|
||||
let slope = dz.signum() * max_slope;
|
||||
sums += max_slope;
|
||||
new_h_i = slope * neighbor_distance / CONFIG.mountain_scale as f64 + h_j;
|
||||
let dh = max_slope * neighbor_distance / CONFIG.mountain_scale as f64;
|
||||
new_h_i = (h_j + dh).max(new_h_i - l * (mag_slope - max_slope));
|
||||
let dz = (new_h_i - h_j).max(0.0) * CONFIG.mountain_scale as f64;
|
||||
let slope = dz/*.abs()*/ / neighbor_distance;
|
||||
sums += slope;
|
||||
// let slope = dz.signum() * max_slope;
|
||||
// new_h_i = slope * neighbor_distance / CONFIG.mountain_scale as f64 + h_j;
|
||||
// sums += max_slope;
|
||||
} else {
|
||||
sums += mag_slope;
|
||||
// Just use the computed rate.
|
||||
|
@ -47,7 +47,10 @@ use vek::*;
|
||||
// cleanly representable in f32 (that stops around 1024 * 4 * 1024 * 4, for signed floats anyway)
|
||||
// but I think that is probably less important since I don't think we actually cast a chunk id to
|
||||
// float, just coordinates... could be wrong though!
|
||||
pub const WORLD_SIZE: Vec2<usize> = Vec2 { x: 1024, y: 1024 };
|
||||
pub const WORLD_SIZE: Vec2<usize> = Vec2 {
|
||||
x: 1024 * 2,
|
||||
y: 1024 * 2,
|
||||
};
|
||||
|
||||
/// A structure that holds cached noise values and cumulative distribution functions for the input
|
||||
/// that led to those values. See the definition of InverseCdf for a description of how to
|
||||
@ -67,7 +70,7 @@ struct GenCdf {
|
||||
rivers: Box<[RiverData]>,
|
||||
}
|
||||
|
||||
pub(crate) struct GenCtx {
|
||||
pub(crate) struct GenCtx {
|
||||
pub turb_x_nz: SuperSimplex,
|
||||
pub turb_y_nz: SuperSimplex,
|
||||
pub chaos_nz: RidgedMulti,
|
||||
@ -108,26 +111,43 @@ pub struct WorldSim {
|
||||
impl WorldSim {
|
||||
pub fn generate(seed: u32) -> Self {
|
||||
let mut rng = ChaChaRng::from_seed(seed_expan::rng_state(seed));
|
||||
let continent_scale = 5_000.0/*32768.0*/;
|
||||
|
||||
let gen_ctx = GenCtx {
|
||||
turb_x_nz: SuperSimplex::new().set_seed(rng.gen()),
|
||||
turb_y_nz: SuperSimplex::new().set_seed(rng.gen()),
|
||||
chaos_nz: RidgedMulti::new().set_octaves(7).set_seed(rng.gen()),
|
||||
chaos_nz: RidgedMulti::new()
|
||||
.set_octaves(/*7*//*3*/ 7)
|
||||
.set_frequency(
|
||||
/*RidgedMulti::DEFAULT_FREQUENCY **/ 3_000.0 * 8.0 / continent_scale,
|
||||
)
|
||||
.set_seed(rng.gen()),
|
||||
hill_nz: SuperSimplex::new().set_seed(rng.gen()),
|
||||
alt_nz: HybridMulti::new()
|
||||
.set_octaves(8)
|
||||
.set_persistence(0.1)
|
||||
.set_octaves(/*3*//*2*/ 8)
|
||||
// 1/2048*32*1024 = 16
|
||||
.set_frequency(
|
||||
/*HybridMulti::DEFAULT_FREQUENCY*/
|
||||
(10_000.0/* * 2.0*/ / continent_scale) as f64,
|
||||
)
|
||||
// .set_frequency(1.0 / ((1 << 0) as f64))
|
||||
// .set_lacunarity(1.0)
|
||||
.set_persistence(/*0.5*//*0.5*/ 0.5)
|
||||
.set_seed(rng.gen()),
|
||||
//temp_nz: SuperSimplex::new().set_seed(rng.gen()),
|
||||
|
||||
temp_nz: Fbm::new()
|
||||
.set_octaves(6)
|
||||
.set_persistence(0.5)
|
||||
.set_frequency(/*4.0 / /*(1024.0 * 4.0/* * 8.0*/)*//*32.0*/((1 << 6) * (WORLD_SIZE.x)) as f64*/1.0 / (((1 << 6) * 64) as f64))
|
||||
// .set_frequency(1.0 / 1024.0)
|
||||
// .set_frequency(1.0 / (1024.0 * 8.0))
|
||||
.set_lacunarity(2.0)
|
||||
.set_seed(rng.gen()),
|
||||
temp_nz: Fbm::new()
|
||||
.set_octaves(6)
|
||||
.set_persistence(0.5)
|
||||
// 1/2^14*1024*32 = 2
|
||||
// 1/(2^14-2^12)*1024*32 = 8/3 ~= 3
|
||||
.set_frequency(
|
||||
/*4.0 / /*(1024.0 * 4.0/* * 8.0*/)*//*32.0*/((1 << 6) * (WORLD_SIZE.x)) as f64*/
|
||||
1.0 / (((1 << 6) * 64) as f64),
|
||||
)
|
||||
// .set_frequency(1.0 / 1024.0)
|
||||
// .set_frequency(1.0 / (1024.0 * 8.0))
|
||||
.set_lacunarity(2.0)
|
||||
.set_seed(rng.gen()),
|
||||
|
||||
small_nz: BasicMulti::new().set_octaves(2).set_seed(rng.gen()),
|
||||
rock_nz: HybridMulti::new().set_persistence(0.3).set_seed(rng.gen()),
|
||||
@ -160,9 +180,16 @@ impl WorldSim {
|
||||
let river_seed = RandomField::new(rng.gen());
|
||||
let rock_strength_nz = Fbm::new()
|
||||
.set_octaves(8)
|
||||
.set_persistence(0.9)
|
||||
.set_persistence(/*0.9*/ 2.0)
|
||||
.set_frequency(/*0.9*/ Fbm::DEFAULT_FREQUENCY / (64.0 * 32.0))
|
||||
.set_seed(rng.gen());
|
||||
|
||||
let max_erosion_per_delta_t = 32.0 / CONFIG.mountain_scale as f64;
|
||||
let erosion_pow_low = /*0.25*//*1.5*//*2.0*//*0.5*//*4.0*//*0.25*//*1.0*//*2.0*//*1.5*//*1.5*//*0.35*//*0.43*//*0.5*//*0.45*//*0.37*/1.002;
|
||||
let erosion_pow_high = /*1.5*//*1.0*//*0.55*//*0.51*//*2.0*/1.002;
|
||||
let erosion_center = /*0.45*//*0.75*//*0.75*//*0.5*//*0.75*/0.5;
|
||||
let n_steps = 150; //150;//200;
|
||||
|
||||
// No NaNs in these uniform vectors, since the original noise value always returns Some.
|
||||
let ((alt_base, _), (chaos, _)) = rayon::join(
|
||||
|| {
|
||||
@ -177,15 +204,17 @@ impl WorldSim {
|
||||
.min(1.0)
|
||||
.max(-1.0))
|
||||
.sub(0.05)
|
||||
.mul(0.35),
|
||||
.mul(0.35), /*-0.0175*/
|
||||
)
|
||||
})
|
||||
},
|
||||
|| {
|
||||
uniform_noise(|_, 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
|
||||
// From 0 to 1.6, but the distribution before the max is from -1 and 1.6, so there is
|
||||
// a 50% chance that hill will end up at 0.3 or lower, and probably a very high
|
||||
// change it will be exactly 0.
|
||||
let hill = (0.0f64
|
||||
//.add(0.0)
|
||||
+ gen_ctx
|
||||
.hill_nz
|
||||
.get((wposf.div(1_500.0)).into_array())
|
||||
@ -213,6 +242,7 @@ impl WorldSim {
|
||||
.add(1.0)
|
||||
.mul(0.5)
|
||||
// [0, 1] * [0.4, 1] = [0, 1] (but probably towards the lower end)
|
||||
//.mul(1.0)
|
||||
.mul(
|
||||
(gen_ctx
|
||||
.chaos_nz
|
||||
@ -224,7 +254,7 @@ impl WorldSim {
|
||||
.min(1.0),
|
||||
)
|
||||
// Chaos is always increased by a little when we're on a hill (but remember
|
||||
// that hill is 0 about 50% of the time).
|
||||
// that hill is 0.3 or less about 50% of the time).
|
||||
// [0, 1] + 0.15 * [0, 1.6] = [0, 1.24]
|
||||
.add(0.2 * hill)
|
||||
// We can't have *no* chaos!
|
||||
@ -239,7 +269,7 @@ impl WorldSim {
|
||||
// calculation. Note that this is using the "unadjusted" temperature.
|
||||
//
|
||||
// No NaNs in these uniform vectors, since the original noise value always returns Some.
|
||||
let (alt_old, alt_old_inverse) = uniform_noise(|posi, wposf| {
|
||||
let (alt_old, /*alt_old_inverse*/ _) = uniform_noise(|posi, wposf| {
|
||||
// This is the extension upwards from the base added to some extra noise from -1 to
|
||||
// 1.
|
||||
//
|
||||
@ -272,7 +302,7 @@ impl WorldSim {
|
||||
x.abs().powf(pow) * x.signum()
|
||||
}
|
||||
|
||||
(0.0 + alt_main
|
||||
(0.0 + alt_main/*0.4*/
|
||||
+ (gen_ctx
|
||||
.small_nz
|
||||
.get((wposf.div(300.0)).into_array())
|
||||
@ -282,6 +312,7 @@ impl WorldSim {
|
||||
.mul(0.3)
|
||||
.add(1.0)
|
||||
.mul(0.4)
|
||||
/*0.52*/
|
||||
+ spring(alt_main.abs().powf(0.5).min(0.75).mul(60.0).sin(), 4.0).mul(0.045))
|
||||
};
|
||||
|
||||
@ -296,7 +327,24 @@ impl WorldSim {
|
||||
// = [-.3675, .3325] + ([-0.5785, 0.7345])
|
||||
// = [-0.946, 1.067]
|
||||
Some(
|
||||
((alt_base[posi].1 + alt_main.mul((chaos[posi].1 as f64).powf(1.2)/*0.25*/))
|
||||
((alt_base[posi].1
|
||||
+ alt_main /*1.0*/
|
||||
.mul(
|
||||
(chaos[posi].1 as f64) /*.mul(2.0).sub(1.0).max(0.0)*/
|
||||
.powf(1.2), /*0.25)*//*0.285*/
|
||||
)/*0.1425*/)
|
||||
.mul(map_edge_factor(posi) as f64)
|
||||
.add(
|
||||
(CONFIG.sea_level as f64)
|
||||
.div(CONFIG.mountain_scale as f64)
|
||||
.mul(map_edge_factor(posi) as f64),
|
||||
)
|
||||
.sub((CONFIG.sea_level as f64).div(CONFIG.mountain_scale as f64)))
|
||||
as f32,
|
||||
)
|
||||
/* Some(
|
||||
// FIXME: May fail on big-endian platforms.
|
||||
((alt_base[posi].1 as f64 + 0.5 + (/*alt_main./*to_le_bytes()[7]*/to_bits() & 1) as f64 * ((1.0 / CONFIG.mountain_scale as f64).powf(1.0 / erosion_pow_low)) + */alt_main / CONFIG.mountain_scale as f64 * 128.0).mul(0.1).powf(1.2))
|
||||
.mul(map_edge_factor(posi) as f64)
|
||||
.add(
|
||||
(CONFIG.sea_level as f64)
|
||||
@ -305,7 +353,7 @@ impl WorldSim {
|
||||
)
|
||||
.sub((CONFIG.sea_level as f64).div(CONFIG.mountain_scale as f64)))
|
||||
as f32,
|
||||
)
|
||||
) */
|
||||
});
|
||||
|
||||
// Calculate oceans.
|
||||
@ -313,20 +361,28 @@ impl WorldSim {
|
||||
let is_ocean = get_oceans(old_height);
|
||||
let is_ocean_fn = |posi: usize| is_ocean[posi];
|
||||
|
||||
/* // Recalculate altitudes without oceans.
|
||||
// Recalculate altitudes without oceans.
|
||||
// NaNs in these uniform vectors wherever pure_water() returns true.
|
||||
let (alt_old_no_ocean, /*alt_old_inverse*/_) = uniform_noise(|posi, _| {
|
||||
let (alt_old_no_ocean, alt_old_inverse) = uniform_noise(|posi, _| {
|
||||
if is_ocean_fn(posi) {
|
||||
None
|
||||
} else {
|
||||
Some(old_height(posi)/*.abs()*/)
|
||||
Some(old_height(posi) /*.abs()*/)
|
||||
}
|
||||
});
|
||||
|
||||
let old_height_uniform = |posi: usize| alt_old_no_ocean[posi].0;
|
||||
let alt_old_min_uniform = 0.0;
|
||||
let alt_old_max_uniform = 1.0; */
|
||||
// Find the minimum and maximum original altitudes.
|
||||
let alt_old_max_uniform = 1.0;
|
||||
let alt_old_center_uniform = erosion_center;
|
||||
let (_alt_old_min_index, alt_old_min) = alt_old_inverse.first().unwrap();
|
||||
let (_alt_old_max_index, alt_old_max) = alt_old_inverse.last().unwrap();
|
||||
let (_alt_old_mid_index, alt_old_mid) =
|
||||
alt_old_inverse[(alt_old_inverse.len() as f64 * erosion_center) as usize];
|
||||
let alt_old_center =
|
||||
((alt_old_mid - alt_old_min) as f64 / (alt_old_max - alt_old_min) as f64);
|
||||
|
||||
/* // Find the minimum and maximum original altitudes.
|
||||
// NOTE: Will panic if there is no land, and will not work properly if the minimum and
|
||||
// maximum land altitude are identical (will most likely panic later).
|
||||
let old_height_uniform = |posi: usize| alt_old[posi].0;
|
||||
@ -337,21 +393,52 @@ impl WorldSim {
|
||||
.unwrap();
|
||||
let &(alt_old_max_index, _alt_old_max) = alt_old_inverse.last().unwrap();
|
||||
let alt_old_min_uniform = alt_old[alt_old_min_index].0;
|
||||
let alt_old_max_uniform = alt_old[alt_old_max_index].0;
|
||||
let alt_old_max_uniform = alt_old[alt_old_max_index].0; */
|
||||
|
||||
// Perform some erosion.
|
||||
let max_erosion_per_delta_t = 32.0 / CONFIG.mountain_scale as f64;
|
||||
|
||||
// Logistic regression. Make sure x ∈ (0, 1).
|
||||
let logit = |x: f64| x.ln() - (-x).ln_1p();
|
||||
// 0.5 + 0.5 * tanh(ln(1 / (1 - 0.1) - 1) / (2 * (sqrt(3)/pi)))
|
||||
let logistic_2_base = 3.0f64.sqrt() * f64::consts::FRAC_2_PI;
|
||||
let logistic_base = /*3.0f64.sqrt() * f64::consts::FRAC_1_PI*/1.0f64;
|
||||
// Assumes μ = 0, σ = 1
|
||||
let logistic_cdf = |x: f64| (x / logistic_2_base).tanh() * 0.5 + 0.5;
|
||||
|
||||
let erosion_pow = 2.0;
|
||||
let n_steps = 100;
|
||||
let erosion_factor = |x: f64| logistic_cdf(erosion_pow * logit(x));
|
||||
let exp_inverse_cdf = |x: f64/*, pow: f64*/| -(-x).ln_1p()/* / ln(pow)*/;
|
||||
// 2^((2^10-2)/256) = 15.91...
|
||||
// -ln(1-(1-(2^(-22)*0.5)))
|
||||
// -ln(1-(1-(2^(-53)*0.5)))
|
||||
// ((-ln(1-((1-2^(-53)*0.5))))/ln(e))/((-ln(1-((2^(-53)*0.5))))/ln(e))
|
||||
// ((-ln(1-((0.5))))/ln(2))/((-ln(1-((1 - 2^(-53)*0.5))))/ln(2))
|
||||
// ((-ln(1-((0.5))))/ln(e))/((-ln(1-((1 - 2^(-53)*0.5))))/ln(e))
|
||||
// ((-ln(1-((0.5))))/ln(e))/((-ln(1-((2^(-53)*0.5))))/ln(e))
|
||||
// ((-ln(1-((1-2^(-53)))))/ln(1.002))/((-ln(1-((1 - 2^(-53)*0.5))))/ln(1+2^(-10*2)*0.5))
|
||||
// ((-ln(1-((0.9999999999999999))))/ln(e))/((-ln(1-((1 - 2^(-53)*0.5))))/ln(1+2^(-53)*0.5))
|
||||
//
|
||||
// ((-ln(1-((1-2^(-10*2)))))/ln(1.002))/((-ln(1-((1 - 2^(-10*2)))))/ln(1+2^(-9)))
|
||||
// ((-ln(1-((2^(-10*2)))))/ln(1.002))/((-ln(1-((1 - 2^(-10*2)))))/ln(1+2^(-9)))
|
||||
// ((-ln(1-((1-2^(-10*2)))))/ln(1.002))/((-ln(1-((1 - 2^(-10*2)))))/ln(1.002))
|
||||
let min_epsilon =
|
||||
1.0 / (WORLD_SIZE.x as f64 * WORLD_SIZE.y as f64).max(f64::EPSILON as f64 * 0.5);
|
||||
let max_epsilon = (1.0 - 1.0 / (WORLD_SIZE.x as f64 * WORLD_SIZE.y as f64))
|
||||
.min(1.0 - f64::EPSILON as f64 * 0.5);
|
||||
let alt_exp_min_uniform = exp_inverse_cdf(min_epsilon);
|
||||
let alt_exp_max_uniform = exp_inverse_cdf(max_epsilon);
|
||||
|
||||
// let erosion_pow = 2.0;
|
||||
// let n_steps = 100;//150;
|
||||
// let erosion_factor = |x: f64| logistic_cdf(erosion_pow * logit(x));
|
||||
let log_odds = |x: f64| {
|
||||
logit(x)
|
||||
- logit(
|
||||
/*erosion_center*/ alt_old_center_uniform, /*alt_old_center*/
|
||||
)
|
||||
};
|
||||
/* let erosion_factor = |x: f64| logistic_cdf(logistic_base * if x <= /*erosion_center*/alt_old_center_uniform/*alt_old_center*/ { erosion_pow_low.ln() } else { erosion_pow_high.ln() } * log_odds(x))/*0.5 + (x - 0.5).signum() * ((x - 0.5).mul(2.0).abs(
|
||||
).powf(erosion_pow).mul(0.5))*/; */
|
||||
let erosion_factor = |x: f64| (/*if x <= /*erosion_center*/alt_old_center_uniform/*alt_old_center*/ { erosion_pow_low.ln() } else { erosion_pow_high.ln() } * */(exp_inverse_cdf(x) - alt_exp_min_uniform) / (alt_exp_max_uniform - alt_exp_min_uniform))/*0.5 + (x - 0.5).signum() * ((x - 0.5).mul(2.0).abs(
|
||||
).powf(erosion_pow).mul(0.5))*/;
|
||||
let alt = do_erosion(
|
||||
0.0,
|
||||
max_erosion_per_delta_t as f32,
|
||||
@ -362,22 +449,141 @@ impl WorldSim {
|
||||
if is_ocean_fn(posi) {
|
||||
old_height(posi)
|
||||
} else {
|
||||
5.0 / CONFIG.mountain_scale
|
||||
let wposf = (uniform_idx_as_vec2(posi)
|
||||
* TerrainChunkSize::RECT_SIZE.map(|e| e as i32))
|
||||
.map(|e| e as f64);
|
||||
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())
|
||||
.min(1.0)
|
||||
.max(-1.0))
|
||||
.abs()
|
||||
.powf(1.35);
|
||||
|
||||
fn spring(x: f64, pow: f64) -> f64 {
|
||||
x.abs().powf(pow) * x.signum()
|
||||
}
|
||||
|
||||
(0.0 + alt_main
|
||||
+ (gen_ctx
|
||||
.small_nz
|
||||
.get((wposf.div(300.0)).into_array())
|
||||
.min(1.0)
|
||||
.max(-1.0))
|
||||
.mul(alt_main.powf(0.8).max(/*0.25*/ 0.15))
|
||||
.mul(0.3)
|
||||
.add(1.0)
|
||||
.mul(0.4)
|
||||
+ spring(alt_main.abs().powf(0.5).min(0.75).mul(60.0).sin(), 4.0)
|
||||
.mul(0.045))
|
||||
};
|
||||
// old_height_uniform(posi) *
|
||||
(/*((old_height(posi) - alt_old_min) as f64 / (alt_old_max - alt_old_min) as f64) **/(((6.0 / 360.0 * 2.0 * f64::consts::PI).tan()
|
||||
* TerrainChunkSize::RECT_SIZE.reduce_partial_min() as f64)
|
||||
.floor()
|
||||
/ CONFIG.mountain_scale as f64)) as f32
|
||||
// 5.0 / CONFIG.mountain_scale
|
||||
}
|
||||
},
|
||||
is_ocean_fn,
|
||||
|posi| {
|
||||
let height = ((old_height_uniform(posi) - alt_old_min_uniform) as f64
|
||||
if is_ocean_fn(posi) {
|
||||
return 0.0;
|
||||
}
|
||||
let wposf = (uniform_idx_as_vec2(posi)
|
||||
* TerrainChunkSize::RECT_SIZE.map(|e| e as i32))
|
||||
.map(|e| e as f64);
|
||||
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())
|
||||
.min(1.0)
|
||||
.max(-1.0))
|
||||
.abs()
|
||||
.powf(1.35);
|
||||
|
||||
fn spring(x: f64, pow: f64) -> f64 {
|
||||
x.abs().powf(pow) * x.signum()
|
||||
}
|
||||
|
||||
(0.0 + alt_main
|
||||
+ (gen_ctx
|
||||
.small_nz
|
||||
.get((wposf.div(300.0)).into_array())
|
||||
.min(1.0)
|
||||
.max(-1.0))
|
||||
.mul(alt_main.powf(0.8).max(/*0.25*/ 0.15))
|
||||
.mul(0.3)
|
||||
.add(1.0)
|
||||
.mul(0.4)
|
||||
+ spring(alt_main.abs().powf(0.5).min(0.75).mul(60.0).sin(), 4.0)
|
||||
.mul(0.045))
|
||||
};
|
||||
let height =
|
||||
((old_height_uniform(posi) - alt_old_min_uniform) as f64
|
||||
/ (alt_old_max_uniform - alt_old_min_uniform) as f64)
|
||||
/*.mul(1.0 - f64::EPSILON * 0.5)
|
||||
.add(f64::EPSILON * 0.5);*/
|
||||
.max(1e-7 / CONFIG.mountain_scale as f64)
|
||||
.min(1.0f64 - 1e-7);
|
||||
/*((old_height(posi) - alt_old_min) as f64
|
||||
/ (alt_old_max - alt_old_min) as f64)*/
|
||||
;
|
||||
|
||||
let height = height.mul(max_epsilon - min_epsilon).add(min_epsilon);
|
||||
/*.max(1e-7 / CONFIG.mountain_scale as f64)
|
||||
.min(1.0f64 - 1e-7);*/
|
||||
/* 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())
|
||||
.min(1.0)
|
||||
.max(-1.0))
|
||||
.abs()
|
||||
.powf(1.35);
|
||||
|
||||
fn spring(x: f64, pow: f64) -> f64 {
|
||||
x.abs().powf(pow) * x.signum()
|
||||
}
|
||||
|
||||
(0.0 + alt_main
|
||||
+ (gen_ctx
|
||||
.small_nz
|
||||
.get((wposf.div(300.0)).into_array())
|
||||
.min(1.0)
|
||||
.max(-1.0))
|
||||
.mul(alt_main.powf(0.8).max(/*0.25*/ 0.15))
|
||||
.mul(0.3)
|
||||
.add(1.0)
|
||||
.mul(0.4)
|
||||
+ spring(alt_main.abs().powf(0.5).min(0.75).mul(60.0).sin(), 4.0).mul(0.045))
|
||||
}; */
|
||||
// let height = height + (alt_main./*to_le_bytes()[7]*/to_bits() & 1) as f64 * ((1.0 / CONFIG.mountain_scale as f64).powf(1.0 / erosion_pow_low));
|
||||
let height = erosion_factor(height);
|
||||
assert!(height >= 0.0);
|
||||
assert!(height <= 1.0);
|
||||
// assert!(alt_main >= 0.0);
|
||||
let (bump_factor, bump_max) = if
|
||||
/*height < f32::EPSILON as f64 * 0.5/*false*/*/
|
||||
false {
|
||||
(
|
||||
/*(alt_main./*to_le_bytes()[7]*/to_bits() & 1) as f64*/
|
||||
(alt_main / CONFIG.mountain_scale as f64 * 128.0).mul(0.1).powf(1.2) * /*(1.0 / CONFIG.mountain_scale as f64)*/(f32::EPSILON * 0.5) as f64,
|
||||
(f32::EPSILON * 0.5) as f64,
|
||||
)
|
||||
} else {
|
||||
(0.0, 0.0)
|
||||
};
|
||||
let height = height
|
||||
.mul(max_erosion_per_delta_t * 7.0 / 8.0)
|
||||
.add(max_erosion_per_delta_t / 8.0);
|
||||
.add(max_erosion_per_delta_t / 8.0)
|
||||
.sub(/*1.0 / CONFIG.mountain_scale as f64*/ bump_max)
|
||||
.add(bump_factor);
|
||||
/* .sub(/*1.0 / CONFIG.mountain_scale as f64*/(f32::EPSILON * 0.5) as f64)
|
||||
.add(bump_factor); */
|
||||
height as f32
|
||||
},
|
||||
);
|
||||
@ -530,7 +736,8 @@ impl WorldSim {
|
||||
None
|
||||
} else {
|
||||
// -1 to 1.
|
||||
Some(gen_ctx.temp_nz.get((wposf/*.div(12000.0)*/).into_array()) as f32)
|
||||
Some(gen_ctx.temp_nz.get((wposf/*.div(12000.0)*/).into_array())
|
||||
as f32)
|
||||
}
|
||||
})
|
||||
},
|
||||
@ -1044,7 +1251,7 @@ impl SimChunk {
|
||||
|
||||
// Can have NaNs in non-uniform part where pure_water returned true. We just test one of
|
||||
// the four in order to find out whether this is the case.
|
||||
let (flux_uniform, /*flux_non_uniform*/_) = gen_cdf.pure_flux[posi];
|
||||
let (flux_uniform, /*flux_non_uniform*/ _) = gen_cdf.pure_flux[posi];
|
||||
let (alt_uniform, _) = gen_cdf.alt_no_water[posi];
|
||||
let (temp_uniform, _) = gen_cdf.temp_base[posi];
|
||||
let (humid_uniform, _) = gen_cdf.humid_base[posi];
|
||||
@ -1074,7 +1281,7 @@ impl SimChunk {
|
||||
|
||||
// We also correlate temperature negatively with altitude and absolute latitude, using
|
||||
// different weighting than we use for humidity.
|
||||
const TEMP_WEIGHTS: [f32; 2] = [/*1.5, */1.0, 2.0];
|
||||
const TEMP_WEIGHTS: [f32; 2] = [/*1.5, */ 1.0, 2.0];
|
||||
let temp = /*if flux_non_uniform.is_nan() {
|
||||
0.0
|
||||
} else */{
|
||||
|
@ -179,7 +179,8 @@ pub fn uniform_noise<F: Float + Send>(
|
||||
// position of the noise in the sorted vector (divided by the vector length).
|
||||
// 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, F::nan()/*zero()*/); WORLD_SIZE.x * WORLD_SIZE.y].into_boxed_slice();
|
||||
let mut uniform_noise =
|
||||
vec![(0.0, F::nan() /*zero()*/); WORLD_SIZE.x * WORLD_SIZE.y].into_boxed_slice();
|
||||
// NOTE: Consider using try_into here and elsewhere in this function, since i32::MAX
|
||||
// technically doesn't fit in an f32 (even if we should never reach that limit).
|
||||
let total = noise.len() as f32;
|
||||
|
Loading…
Reference in New Issue
Block a user