Tweak world generation
3396b4a9e53be34ec2fdcc3bd24034e39937f5e0 2e566dc9ad45b80e4c94031b5be78ca6703cba45 66ce82b31d0a61a31a96ba909332069606b700ad 4f133213e787fd7d725ed8147376814b05e9694a a282ae965bf83736f48f47cddc2fc8a799455fda e28eb81541730277e437003005707728669ea859 4947b7be051971432f5569bfbf4e5414f7cd3532
This commit is contained in:
parent
7d3e97da5a
commit
cb935618b0
3 changed files with 163 additions and 109 deletions
|
@ -57,8 +57,8 @@ impl From<BiomeType> for BiomeStats {
|
||||||
color: Color::rgb_u8(167, 177, 84),
|
color: Color::rgb_u8(167, 177, 84),
|
||||||
min_altitude: 0.0,
|
min_altitude: 0.0,
|
||||||
max_altitude: World::MAX_ALTITUDE,
|
max_altitude: World::MAX_ALTITUDE,
|
||||||
min_rainfall: 25.0,
|
min_rainfall: 15.0,
|
||||||
max_rainfall: 1475.0,
|
max_rainfall: 1575.0,
|
||||||
min_temperature: -5.0,
|
min_temperature: -5.0,
|
||||||
max_temperature: World::MAX_TEMPERATURE,
|
max_temperature: World::MAX_TEMPERATURE,
|
||||||
},
|
},
|
||||||
|
@ -68,8 +68,8 @@ impl From<BiomeType> for BiomeStats {
|
||||||
color: Color::rgb_u8(76, 132, 55),
|
color: Color::rgb_u8(76, 132, 55),
|
||||||
min_altitude: 0.0,
|
min_altitude: 0.0,
|
||||||
max_altitude: World::MAX_ALTITUDE,
|
max_altitude: World::MAX_ALTITUDE,
|
||||||
min_rainfall: 975.0,
|
min_rainfall: 1375.0,
|
||||||
max_rainfall: 2475.0,
|
max_rainfall: 2975.0,
|
||||||
min_temperature: -5.0,
|
min_temperature: -5.0,
|
||||||
max_temperature: World::MAX_TEMPERATURE,
|
max_temperature: World::MAX_TEMPERATURE,
|
||||||
},
|
},
|
||||||
|
@ -102,7 +102,7 @@ impl From<BiomeType> for BiomeStats {
|
||||||
min_altitude: 0.0,
|
min_altitude: 0.0,
|
||||||
max_altitude: World::MAX_ALTITUDE,
|
max_altitude: World::MAX_ALTITUDE,
|
||||||
min_rainfall: World::MIN_RAINFALL,
|
min_rainfall: World::MIN_RAINFALL,
|
||||||
max_rainfall: 125.0,
|
max_rainfall: 275.0,
|
||||||
min_temperature: -5.0,
|
min_temperature: -5.0,
|
||||||
max_temperature: World::MAX_TEMPERATURE,
|
max_temperature: World::MAX_TEMPERATURE,
|
||||||
},
|
},
|
||||||
|
@ -112,7 +112,7 @@ impl From<BiomeType> for BiomeStats {
|
||||||
color: Color::rgb_u8(59, 103, 43),
|
color: Color::rgb_u8(59, 103, 43),
|
||||||
min_altitude: 0.0,
|
min_altitude: 0.0,
|
||||||
max_altitude: World::MAX_ALTITUDE,
|
max_altitude: World::MAX_ALTITUDE,
|
||||||
min_rainfall: 1975.0,
|
min_rainfall: 1775.0,
|
||||||
max_rainfall: World::MAX_RAINFALL,
|
max_rainfall: World::MAX_RAINFALL,
|
||||||
min_temperature: -5.0,
|
min_temperature: -5.0,
|
||||||
max_temperature: World::MAX_TEMPERATURE,
|
max_temperature: World::MAX_TEMPERATURE,
|
||||||
|
|
|
@ -107,26 +107,20 @@ pub struct TerrainCell {
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
pub const ALTITUDE_SPAN: f32 = World::MAX_ALTITUDE - World::MIN_ALTITUDE;
|
pub const ALTITUDE_SPAN: f32 = World::MAX_ALTITUDE - World::MIN_ALTITUDE;
|
||||||
pub const CONTINENT_MAX_SIZE_FACTOR: f32 = 6.0;
|
pub const CONTINENT_MAX_SIZE_FACTOR: f32 = 8.0;
|
||||||
pub const CONTINENT_MIN_SIZE_FACTOR: f32 = 2.5;
|
pub const CONTINENT_MIN_SIZE_FACTOR: f32 = 6.0;
|
||||||
pub const MAX_ALTITUDE: f32 = 15000.0;
|
pub const MAX_ALTITUDE: f32 = 15000.0;
|
||||||
pub const MAX_RAINFALL: f32 = 7500.0;
|
pub const MAX_RAINFALL: f32 = 13000.0;
|
||||||
pub const MAX_TEMPERATURE: f32 = 30.0;
|
pub const MAX_TEMPERATURE: f32 = 30.0;
|
||||||
pub const MIN_ALTITUDE: f32 = -15000.0;
|
pub const MIN_ALTITUDE: f32 = -15000.0;
|
||||||
pub const MIN_RAINFALL: f32 = 0.0;
|
pub const MIN_RAINFALL: f32 = 0.0;
|
||||||
pub const MIN_TEMPERATURE: f32 = -35.0;
|
pub const MIN_TEMPERATURE: f32 = -35.0;
|
||||||
pub const MOUNTAIN_RANGE_MIX_FACTOR: f32 = 0.075;
|
pub const NUM_CONTINENTS: u8 = 6;
|
||||||
pub const MOUNTAIN_RANGE_WIDTH_FACTOR: f32 = 25.0;
|
|
||||||
pub const NUM_CONTINENTS: u8 = 7;
|
|
||||||
pub const RAINFALL_DRYNESS_FACTOR: f32 = 0.005;
|
pub const RAINFALL_DRYNESS_FACTOR: f32 = 0.005;
|
||||||
pub const RAINFALL_DRYNESS_OFFSET: f32 = World::RAINFALL_DRYNESS_FACTOR * World::MAX_RAINFALL;
|
pub const RAINFALL_DRYNESS_OFFSET: f32 = World::RAINFALL_DRYNESS_FACTOR * World::MAX_RAINFALL;
|
||||||
pub const RAINFALL_SPAN: f32 = World::MAX_RAINFALL - World::MIN_RAINFALL;
|
pub const RAINFALL_SPAN: f32 = World::MAX_RAINFALL - World::MIN_RAINFALL;
|
||||||
pub const TEMPERATURE_ALTITUDE_FACTOR: f32 = 1.0;
|
pub const TEMPERATURE_ALTITUDE_FACTOR: f32 = 2.05;
|
||||||
pub const TEMPERATURE_SPAN: f32 = World::MAX_TEMPERATURE - World::MIN_TEMPERATURE;
|
pub const TEMPERATURE_SPAN: f32 = World::MAX_TEMPERATURE - World::MIN_TEMPERATURE;
|
||||||
pub const TERRAIN_NOISE_FACTOR_1: f32 = 0.15;
|
|
||||||
pub const TERRAIN_NOISE_FACTOR_2: f32 = 0.15;
|
|
||||||
pub const TERRAIN_NOISE_FACTOR_3: f32 = 0.1;
|
|
||||||
pub const TERRAIN_NOISE_FACTOR_4: f32 = 2.5;
|
|
||||||
|
|
||||||
pub fn new(width: u32, height: u32, seed: u32) -> World {
|
pub fn new(width: u32, height: u32, seed: u32) -> World {
|
||||||
World {
|
World {
|
||||||
|
@ -199,6 +193,8 @@ impl World {
|
||||||
let width = self.width as f32;
|
let width = self.width as f32;
|
||||||
let height = self.height as f32;
|
let height = self.height as f32;
|
||||||
|
|
||||||
|
const LATITUDE_FACTOR: f32 = 6.0;
|
||||||
|
|
||||||
for i in 0..World::NUM_CONTINENTS {
|
for i in 0..World::NUM_CONTINENTS {
|
||||||
// #[cfg(feature = "logging")]
|
// #[cfg(feature = "logging")]
|
||||||
// info!("Continents: {}/{}", i, World::NUM_CONTINENTS);
|
// info!("Continents: {}/{}", i, World::NUM_CONTINENTS);
|
||||||
|
@ -207,8 +203,9 @@ impl World {
|
||||||
.rng
|
.rng
|
||||||
.gen_range(width * i as f32 * 2.0 / 5.0..(width * (i as f32 + 2.0) * 2.0 / 5.0))
|
.gen_range(width * i as f32 * 2.0 / 5.0..(width * (i as f32 + 2.0) * 2.0 / 5.0))
|
||||||
.repeat(width);
|
.repeat(width);
|
||||||
self.continent_offsets[i as usize].y =
|
self.continent_offsets[i as usize].y = self.rng.gen_range(
|
||||||
self.rng.gen_range(height * 1.0 / 6.0..height * 5.0 / 6.0);
|
height * 1.0 / LATITUDE_FACTOR..height * (LATITUDE_FACTOR - 1.0) / LATITUDE_FACTOR,
|
||||||
|
);
|
||||||
|
|
||||||
self.continent_sizes[i as usize] = Vec2 {
|
self.continent_sizes[i as usize] = Vec2 {
|
||||||
x: self
|
x: self
|
||||||
|
@ -216,47 +213,61 @@ impl World {
|
||||||
.gen_range(World::CONTINENT_MIN_SIZE_FACTOR..World::CONTINENT_MAX_SIZE_FACTOR),
|
.gen_range(World::CONTINENT_MIN_SIZE_FACTOR..World::CONTINENT_MAX_SIZE_FACTOR),
|
||||||
y: self
|
y: self
|
||||||
.rng
|
.rng
|
||||||
.gen_range(World::CONTINENT_MIN_SIZE_FACTOR..World::CONTINENT_MAX_SIZE_FACTOR),
|
.gen_range(World::CONTINENT_MIN_SIZE_FACTOR..World::CONTINENT_MAX_SIZE_FACTOR)
|
||||||
|
/ 2.0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
info!("Done generating continents");
|
info!("Done generating continents");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn continent_modifier(&self, x: usize, y: usize) -> f32 {
|
fn continent_distance(&self, continent_num: u8, x: usize, y: usize) -> f32 {
|
||||||
let x = x as f32;
|
let beta_factor = f32::sin(std::f32::consts::PI * y as f32 / self.height as f32);
|
||||||
let y = y as f32;
|
|
||||||
let width = self.width as f32;
|
|
||||||
let height = self.height as f32;
|
|
||||||
|
|
||||||
|
let Vec2 {
|
||||||
|
x: continent_x,
|
||||||
|
y: continent_y,
|
||||||
|
} = self.continent_offsets[usize::from(continent_num)];
|
||||||
|
|
||||||
|
let distance_x = f32::min(
|
||||||
|
f32::abs(continent_x - x as f32),
|
||||||
|
f32::abs(self.width as f32 + continent_x - x as f32),
|
||||||
|
);
|
||||||
|
let distance_x = f32::min(
|
||||||
|
distance_x,
|
||||||
|
f32::abs(continent_x - x as f32 - self.width as f32),
|
||||||
|
);
|
||||||
|
let distance_x = distance_x * beta_factor;
|
||||||
|
|
||||||
|
let distance_y = f32::abs(continent_y - y as f32);
|
||||||
|
|
||||||
|
let Vec2 {
|
||||||
|
x: continent_width,
|
||||||
|
y: continent_height,
|
||||||
|
} = self.continent_sizes[usize::from(continent_num)];
|
||||||
|
|
||||||
|
f32::sqrt(
|
||||||
|
f32::powi(distance_x * continent_width, 2)
|
||||||
|
+ f32::powi(distance_y * continent_height, 2),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn continent_modifier(&self, x: usize, y: usize) -> f32 {
|
||||||
let mut max_value = 0.0;
|
let mut max_value = 0.0;
|
||||||
let beta_factor = f32::sin(PI * y / height);
|
|
||||||
|
|
||||||
for i in 0..World::NUM_CONTINENTS {
|
for i in 0..World::NUM_CONTINENTS {
|
||||||
let idx = i as usize;
|
let distance = self.continent_distance(i, x, y);
|
||||||
let Vec2 {
|
let value = f32::clamp(1.0 - distance / self.width as f32, 0.0, 1.0);
|
||||||
x: offset_x,
|
|
||||||
y: offset_y,
|
|
||||||
} = self.continent_offsets[idx];
|
|
||||||
let Vec2 {
|
|
||||||
x: continent_width,
|
|
||||||
y: continent_height,
|
|
||||||
} = self.continent_sizes[idx];
|
|
||||||
|
|
||||||
let distance_x = f32::min(
|
let mut other_value = value;
|
||||||
f32::min(f32::abs(offset_x - x), f32::abs(width + offset_x - x)),
|
|
||||||
f32::abs(offset_x - x - width),
|
|
||||||
) * beta_factor
|
|
||||||
* continent_width;
|
|
||||||
|
|
||||||
let distance_y = f32::abs(offset_y - y) * continent_height;
|
|
||||||
|
|
||||||
let distance = f32::sqrt((distance_x * distance_x) + (distance_y * distance_y));
|
|
||||||
|
|
||||||
let value = f32::max(0.0, 1.0 - distance / width);
|
|
||||||
|
|
||||||
if value > max_value {
|
if value > max_value {
|
||||||
|
other_value = max_value;
|
||||||
max_value = value;
|
max_value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let value_mod = f32::min(other_value * 2.0, 1.0);
|
||||||
|
|
||||||
|
max_value = mix_values(max_value, other_value, value_mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
max_value
|
max_value
|
||||||
|
@ -270,16 +281,26 @@ impl World {
|
||||||
self.generate_continents();
|
self.generate_continents();
|
||||||
|
|
||||||
const RADIUS_1: f32 = 0.5;
|
const RADIUS_1: f32 = 0.5;
|
||||||
const RADIUS_2: f32 = 4.0;
|
const RADIUS_2: f32 = 8.0;
|
||||||
const RADIUS_3: f32 = 4.0;
|
const RADIUS_3: f32 = 4.0;
|
||||||
const RADIUS_4: f32 = 8.0;
|
const RADIUS_4: f32 = 8.0;
|
||||||
const RADIUS_5: f32 = 16.0;
|
const RADIUS_5: f32 = 16.0;
|
||||||
|
const RADIUS_6: f32 = 64.0;
|
||||||
|
const RADIUS_7: f32 = 128.0;
|
||||||
|
const RADIUS_8: f32 = 1.0;
|
||||||
|
const RADIUS_9: f32 = 1.0;
|
||||||
|
|
||||||
let offset_1 = World::random_offset_vector(&mut self.rng);
|
let offset_1 = World::random_offset_vector(&mut self.rng);
|
||||||
|
let offset_1b = World::random_offset_vector(&mut self.rng);
|
||||||
let offset_2 = World::random_offset_vector(&mut self.rng);
|
let offset_2 = World::random_offset_vector(&mut self.rng);
|
||||||
|
let offset_2b = World::random_offset_vector(&mut self.rng);
|
||||||
let offset_3 = World::random_offset_vector(&mut self.rng);
|
let offset_3 = World::random_offset_vector(&mut self.rng);
|
||||||
let offset_4 = World::random_offset_vector(&mut self.rng);
|
let offset_4 = World::random_offset_vector(&mut self.rng);
|
||||||
let offset_5 = World::random_offset_vector(&mut self.rng);
|
let offset_5 = World::random_offset_vector(&mut self.rng);
|
||||||
|
let offset_6 = World::random_offset_vector(&mut self.rng);
|
||||||
|
let offset_7 = World::random_offset_vector(&mut self.rng);
|
||||||
|
let offset_8 = World::random_offset_vector(&mut self.rng);
|
||||||
|
let offset_9 = World::random_offset_vector(&mut self.rng);
|
||||||
|
|
||||||
let height = self.terrain.len();
|
let height = self.terrain.len();
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
|
@ -299,46 +320,62 @@ impl World {
|
||||||
|
|
||||||
let value_1 =
|
let value_1 =
|
||||||
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_1, offset_1)?;
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_1, offset_1)?;
|
||||||
|
let value_1b =
|
||||||
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_1, offset_1b)?;
|
||||||
let value_2 =
|
let value_2 =
|
||||||
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_2, offset_2)?;
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_2, offset_2)?;
|
||||||
|
let value_2b =
|
||||||
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_2, offset_2b)?;
|
||||||
let value_3 =
|
let value_3 =
|
||||||
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_3, offset_3)?;
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_3, offset_3)?;
|
||||||
let value_4 =
|
let value_4 =
|
||||||
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_4, offset_4)?;
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_4, offset_4)?;
|
||||||
let value_5 =
|
let value_5 =
|
||||||
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_5, offset_5)?;
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_5, offset_5)?;
|
||||||
|
let value_6 =
|
||||||
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_6, offset_6)?;
|
||||||
|
let value_7 =
|
||||||
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_7, offset_7)?;
|
||||||
|
let value_8 = self
|
||||||
|
.random_noise_from_polar_coordinates(alpha, beta, RADIUS_8, offset_8)?
|
||||||
|
* 1.5
|
||||||
|
+ 0.25;
|
||||||
|
let value_9 =
|
||||||
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_9, offset_9)?;
|
||||||
|
|
||||||
let value_a = mix_values(
|
let mut value_a = self.continent_modifier(x, y);
|
||||||
self.continent_modifier(x, y),
|
value_a = mix_values(value_a, value_3, 0.22 * value_8);
|
||||||
value_3,
|
value_a = mix_values(value_a, value_4, 0.15 * value_8);
|
||||||
World::TERRAIN_NOISE_FACTOR_1,
|
value_a = mix_values(value_a, value_5, 0.1 * value_8);
|
||||||
) * mix_values(1.0, value_4, World::TERRAIN_NOISE_FACTOR_2)
|
value_a = mix_values(value_a, value_6, 0.03 * value_8);
|
||||||
* mix_values(1.0, value_5, World::TERRAIN_NOISE_FACTOR_3);
|
value_a = mix_values(value_a, value_7, 0.005 * value_8);
|
||||||
|
|
||||||
let value_b = value_a * 0.04 + 0.48;
|
let mut value_c = mix_values(value_1, value_9, 0.5 * value_8);
|
||||||
|
value_c = mix_values(value_c, value_2, 0.04 * value_8);
|
||||||
|
value_c = self.mountain_range_noise_from_random_noise(value_c, 25.0);
|
||||||
|
|
||||||
let value_c = mix_values(
|
let mut value_cb = mix_values(value_1b, value_9, 0.5 * value_8);
|
||||||
self.mountain_range_noise_from_random_noise(mix_values(
|
value_cb = mix_values(value_cb, value_2b, 0.04 * value_8);
|
||||||
value_1,
|
value_cb = self.mountain_range_noise_from_random_noise(value_cb, 25.0);
|
||||||
value_2,
|
|
||||||
World::MOUNTAIN_RANGE_MIX_FACTOR,
|
value_c = mix_values(value_c, value_cb, 0.5 * value_8);
|
||||||
)),
|
|
||||||
value_3,
|
value_c = mix_values(value_c, value_3, 0.35 * value_8);
|
||||||
World::TERRAIN_NOISE_FACTOR_1 * World::TERRAIN_NOISE_FACTOR_4,
|
value_c = mix_values(value_c, value_4, 0.075);
|
||||||
) * mix_values(
|
value_c = mix_values(value_c, value_5, 0.05);
|
||||||
1.0,
|
value_c = mix_values(value_c, value_6, 0.02);
|
||||||
value_4,
|
value_c = mix_values(value_c, value_7, 0.01);
|
||||||
World::TERRAIN_NOISE_FACTOR_2 * World::TERRAIN_NOISE_FACTOR_4,
|
|
||||||
) * mix_values(
|
let value_b = mix_values(
|
||||||
1.0,
|
value_a,
|
||||||
value_5,
|
value_a * 0.02 + 0.49,
|
||||||
World::TERRAIN_NOISE_FACTOR_3 * World::TERRAIN_NOISE_FACTOR_4,
|
value_a - f32::max(0.0, 2.0 * value_c - 1.0),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut value_d = mix_values(value_a, value_c, 0.25);
|
let value_d = mix_values(value_b, value_c, 0.225 * value_8);
|
||||||
value_d = mix_values(value_d, value_c, 0.1);
|
|
||||||
value_d = mix_values(value_d, value_b, 0.1);
|
|
||||||
|
|
||||||
|
// todo!("Calculate and set altitude");
|
||||||
|
// This is done in a separate method in the original. But why?
|
||||||
let altitude = World::calculate_altitude(value_d);
|
let altitude = World::calculate_altitude(value_d);
|
||||||
self.terrain[y][x].altitude = altitude;
|
self.terrain[y][x].altitude = altitude;
|
||||||
|
|
||||||
|
@ -376,27 +413,13 @@ impl World {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mountain_range_noise_from_random_noise(&self, noise: f32) -> f32 {
|
fn mountain_range_noise_from_random_noise(&self, noise: f32, width_factor: f32) -> f32 {
|
||||||
let noise = noise * 2.0 - 1.0;
|
let noise = noise * 2.0 - 1.0;
|
||||||
|
|
||||||
let value_1 = -f32::exp(-f32::powi(
|
let value_1 = -f32::exp(-f32::powi(noise * width_factor + 1.0, 2));
|
||||||
noise * World::MOUNTAIN_RANGE_WIDTH_FACTOR + 1.0,
|
let value_2 = f32::exp(-f32::powi(noise * width_factor - 1.0, 2));
|
||||||
2,
|
|
||||||
));
|
|
||||||
let value_2 = f32::exp(-f32::powi(
|
|
||||||
noise * World::MOUNTAIN_RANGE_WIDTH_FACTOR - 1.0,
|
|
||||||
2,
|
|
||||||
));
|
|
||||||
let value_3 = -f32::exp(-f32::powi(
|
|
||||||
noise * World::MOUNTAIN_RANGE_WIDTH_FACTOR + World::MOUNTAIN_RANGE_WIDTH_FACTOR / 2.0,
|
|
||||||
2,
|
|
||||||
));
|
|
||||||
let value_4 = f32::exp(-f32::powi(
|
|
||||||
noise * World::MOUNTAIN_RANGE_WIDTH_FACTOR - World::MOUNTAIN_RANGE_WIDTH_FACTOR / 2.0,
|
|
||||||
2,
|
|
||||||
));
|
|
||||||
|
|
||||||
(value_1 + value_2 + value_3 + value_4 + 1.0) / 2.0
|
(value_1 + value_2 + 1.0) / 2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_altitude(raw_altitude: f32) -> f32 {
|
fn calculate_altitude(raw_altitude: f32) -> f32 {
|
||||||
|
@ -408,8 +431,10 @@ impl World {
|
||||||
progress_sender: &Sender<(f32, String)>,
|
progress_sender: &Sender<(f32, String)>,
|
||||||
) -> Result<(), CartesianError> {
|
) -> Result<(), CartesianError> {
|
||||||
info!("Generating rainfall");
|
info!("Generating rainfall");
|
||||||
const RADIUS: f32 = 2.0;
|
const RADIUS_1: f32 = 2.0;
|
||||||
let offset = World::random_offset_vector(&mut self.rng);
|
const RADIUS_2: f32 = 1.0;
|
||||||
|
let offset_1 = World::random_offset_vector(&mut self.rng);
|
||||||
|
let offset_2 = World::random_offset_vector(&mut self.rng);
|
||||||
|
|
||||||
let height = self.terrain.len();
|
let height = self.terrain.len();
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
|
@ -426,35 +451,66 @@ impl World {
|
||||||
);
|
);
|
||||||
let beta = (x as f32 / self.width as f32) * TAU;
|
let beta = (x as f32 / self.width as f32) * TAU;
|
||||||
|
|
||||||
let random_noise =
|
let random_noise_1 =
|
||||||
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS, offset)?;
|
self.random_noise_from_polar_coordinates(alpha, beta, RADIUS_1, offset_1)?;
|
||||||
|
let random_noise_2 = self
|
||||||
|
.random_noise_from_polar_coordinates(alpha, beta, RADIUS_2, offset_2)?
|
||||||
|
* 1.5
|
||||||
|
+ 0.25;
|
||||||
|
|
||||||
let latitude_factor = alpha + (random_noise * 2.0 - 1.0) * PI * 0.1;
|
let latitude_factor = alpha + (random_noise_1 * 2.0 - 1.0) * PI * 0.2;
|
||||||
let latitude_modifier_1 = (1.5 * f32::sin(latitude_factor)) - 0.5;
|
let latitude_modifier_1 = (1.5 * f32::sin(latitude_factor)) - 0.5;
|
||||||
let latitude_modifier_2 = f32::cos(latitude_factor);
|
let latitude_modifier_2 = f32::cos(latitude_factor);
|
||||||
|
|
||||||
let offset_cell_x =
|
let offset_cell_x_1 =
|
||||||
(width + x + f32::floor(latitude_modifier_2 * width as f32 / 20.0) as usize)
|
(width + x + f32::floor(latitude_modifier_2 * width as f32 / 20.0) as usize)
|
||||||
% width;
|
% width;
|
||||||
let offset_cell_2_x =
|
let offset_cell_x_2 =
|
||||||
|
(width + x + f32::floor(latitude_modifier_2 * width as f32 / 15.0) as usize)
|
||||||
|
% width;
|
||||||
|
let offset_cell_x_3 =
|
||||||
(width + x + f32::floor(latitude_modifier_2 * width as f32 / 10.0) as usize)
|
(width + x + f32::floor(latitude_modifier_2 * width as f32 / 10.0) as usize)
|
||||||
% width;
|
% width;
|
||||||
|
let offset_cell_x_4 =
|
||||||
|
(width + x + f32::floor(latitude_modifier_2 * width as f32 / 5.0) as usize)
|
||||||
|
% width;
|
||||||
|
let offset_cell_y =
|
||||||
|
y + f32::floor(latitude_modifier_2 * height as f32 / 10.0) as usize;
|
||||||
|
|
||||||
let offset_cell = &self.terrain[y][offset_cell_x];
|
let offset_cell = &self.terrain[y][offset_cell_x_1];
|
||||||
let offset_altitude = f32::max(0.0, offset_cell.altitude);
|
let offset_altitude = f32::max(0.0, offset_cell.altitude);
|
||||||
|
|
||||||
let offset_cell_2 = &self.terrain[y][offset_cell_2_x];
|
let offset_cell_2 = &self.terrain[y][offset_cell_x_2];
|
||||||
let offset_altitude_2 = f32::max(0.0, offset_cell_2.altitude);
|
let offset_altitude_2 = f32::max(0.0, offset_cell_2.altitude);
|
||||||
|
|
||||||
|
let offset_cell_3 = &self.terrain[y][offset_cell_x_3];
|
||||||
|
let offset_altitude_3 = f32::max(0.0, offset_cell_3.altitude);
|
||||||
|
|
||||||
|
let offset_cell_4 = &self.terrain[y][offset_cell_x_4];
|
||||||
|
let offset_altitude_4 = f32::max(0.0, offset_cell_4.altitude);
|
||||||
|
|
||||||
|
let offset_cell_5 = &self.terrain[offset_cell_y][x];
|
||||||
|
let offset_altitude_5 = f32::max(0.0, offset_cell_5.altitude);
|
||||||
|
|
||||||
let cell = &mut self.terrain[y][x];
|
let cell = &mut self.terrain[y][x];
|
||||||
let altitude_value = f32::max(0.0, cell.altitude);
|
let altitude_value = f32::max(0.0, cell.altitude);
|
||||||
|
|
||||||
let altitude_modifier =
|
let altitude_modifier = (altitude_value
|
||||||
(altitude_value - (offset_altitude * 1.5) - (offset_altitude_2))
|
- (offset_altitude * 0.7)
|
||||||
/ World::MAX_ALTITUDE;
|
- (offset_altitude_2 * 0.6)
|
||||||
|
- (offset_altitude_3 * 0.5)
|
||||||
|
- (offset_altitude_4 * 0.4)
|
||||||
|
- (offset_altitude_5 * 0.5)
|
||||||
|
+ (World::MAX_ALTITUDE * 0.18 * random_noise_2)
|
||||||
|
- (altitude_value * 0.25))
|
||||||
|
/ World::MAX_ALTITUDE;
|
||||||
|
|
||||||
let rainfall_value = mix_values(latitude_modifier_1, altitude_modifier, 0.63);
|
let mut rainfall_value = mix_values(latitude_modifier_1, altitude_modifier, 0.85);
|
||||||
let rainfall_value = mix_values(rainfall_value.powi(2), rainfall_value, 0.85);
|
rainfall_value = mix_values(
|
||||||
|
rainfall_value.powi(2).copysign(rainfall_value),
|
||||||
|
rainfall_value,
|
||||||
|
0.75,
|
||||||
|
);
|
||||||
let rainfall = f32::min(
|
let rainfall = f32::min(
|
||||||
World::MAX_RAINFALL,
|
World::MAX_RAINFALL,
|
||||||
World::calculate_rainfall(rainfall_value),
|
World::calculate_rainfall(rainfall_value),
|
||||||
|
|
|
@ -155,14 +155,12 @@ impl WorldManager {
|
||||||
WorldManager::NEW_WORLD_HEIGHT,
|
WorldManager::NEW_WORLD_HEIGHT,
|
||||||
seed,
|
seed,
|
||||||
);
|
);
|
||||||
if let Err(_) =
|
if let Err(_) = progress_sender.try_send((0.0, String::from("Generating new world...")))
|
||||||
progress_sender.try_send((0.0, String::from("Generating new world...")))
|
|
||||||
{
|
{
|
||||||
// Quietly ignore. It's not critical and logging is slow.
|
// Quietly ignore. It's not critical and logging is slow.
|
||||||
}
|
}
|
||||||
let result = new_world.generate(&progress_sender);
|
let result = new_world.generate(&progress_sender);
|
||||||
if let Err(_) =
|
if let Err(_) = progress_sender.try_send((1.0, String::from("Done generating world!")))
|
||||||
progress_sender.try_send((1.0, String::from("Done generating world!")))
|
|
||||||
{
|
{
|
||||||
// Quietly ignore. See above
|
// Quietly ignore. See above
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue