implement overworld noises

This commit is contained in:
kralverde
2024-09-19 10:44:09 -04:00
parent 81a263180c
commit 7c946bb23f
7 changed files with 474 additions and 12 deletions

View File

@@ -54,7 +54,13 @@ impl GenerationShapeConfig {
}
}
lazy_static! {
pub static ref surface_config: GenerationShapeConfig =
GenerationShapeConfig::new(-64, 384, 1, 2);
pub mod shape_configs {
use super::GenerationShapeConfig;
pub const surface_config: GenerationShapeConfig = GenerationShapeConfig {
y_min: -64,
height: 384,
horizontal: 1,
vertical: 2,
};
}

View File

@@ -4,6 +4,7 @@ mod generator;
mod generic_generator;
mod implementation;
mod noise;
mod sampler;
mod seed;
pub use generator::WorldGenerator;

View File

@@ -57,6 +57,12 @@ pub struct BlendDensityFunction<'a> {
function: Arc<DensityFunction<'a>>,
}
impl<'a> BlendDensityFunction<'a> {
pub fn new(density: Arc<DensityFunction<'a>>) -> Self {
Self { function: density }
}
}
impl<'a> BlendDensityFunction<'a> {
fn apply_density(&self, pos: &impl NoisePos, density: f64) -> f64 {
pos.get_blender().apply_blend_density(pos, density)

View File

@@ -16,7 +16,7 @@ use super::{clamped_map, perlin::DoublePerlinNoiseParameters};
mod blend;
mod end;
mod math;
mod noise;
pub mod noise;
mod offset;
pub mod spline;
mod unary;
@@ -48,11 +48,11 @@ pub mod built_in_noises {
};
pub struct SlopedCheeseResult<'a> {
offset: DensityFunction<'a>,
factor: DensityFunction<'a>,
depth: DensityFunction<'a>,
jaggedness: DensityFunction<'a>,
sloped_cheese: DensityFunction<'a>,
pub(crate) offset: DensityFunction<'a>,
pub(crate) factor: DensityFunction<'a>,
pub(crate) depth: DensityFunction<'a>,
pub(crate) jaggedness: DensityFunction<'a>,
pub(crate) sloped_cheese: DensityFunction<'a>,
}
type BuiltInNoise = LazyLock<DensityFunction<'static>>;
@@ -600,7 +600,7 @@ pub fn peaks_valleys_noise(variance: f32) -> f32 {
-((variance.abs() - 0.6666667f32).abs() - 0.33333334f32) * 3f32
}
fn veritcal_range_choice<'a>(
pub fn veritcal_range_choice<'a>(
input: DensityFunction<'a>,
in_range: DensityFunction<'a>,
min: i32,
@@ -619,6 +619,16 @@ fn veritcal_range_choice<'a>(
))
}
pub fn apply_blend_density(density: DensityFunction) -> DensityFunction {
let function = DensityFunction::BlendDensity(BlendDensityFunction::new(Arc::new(density)));
DensityFunction::Wrapper(WrapperFunction::new(
Arc::new(function),
WrapperType::Interpolated,
))
.mul_const(0.64f64)
.squeeze()
}
fn apply_blending<'a>(
function: DensityFunction<'a>,
blend: DensityFunction<'a>,
@@ -1011,6 +1021,24 @@ pub struct RangeFunction<'a> {
out_range: Arc<DensityFunction<'a>>,
}
impl<'a> RangeFunction<'a> {
pub fn new(
input: Arc<DensityFunction<'a>>,
min: f64,
max: f64,
in_range: Arc<DensityFunction<'a>>,
out_range: Arc<DensityFunction<'a>>,
) -> Self {
Self {
input,
min,
max,
in_range,
out_range,
}
}
}
impl<'a> DensityFunctionImpl<'a> for RangeFunction<'a> {
fn sample(&self, pos: &impl NoisePos) -> f64 {
let d = self.input.sample(pos);
@@ -1063,6 +1091,17 @@ pub struct YClampedFunction {
to_val: f64,
}
impl YClampedFunction {
pub fn new(from: i32, to: i32, from_val: f64, to_val: f64) -> Self {
Self {
from,
to,
from_val,
to_val,
}
}
}
impl<'a> DensityFunctionImpl<'a> for YClampedFunction {
fn sample(&self, pos: &impl NoisePos) -> f64 {
clamped_map(
@@ -1112,6 +1151,22 @@ pub fn lerp_density<'a>(
start: DensityFunction<'a>,
end: DensityFunction<'a>,
) -> DensityFunction<'a> {
let func_2 = delta.mul_const(-1f64).add_const(1f64);
start.mul(func_2.clone()).add(end.mul(func_2))
if let DensityFunction::Constant(function) = start {
lerp_density_static_start(delta, function.value, end)
} else {
let function = DensityFunction::Wrapper(WrapperFunction::new(
Arc::new(delta),
WrapperType::CacheOnce,
));
let function2 = function.mul_const(-1f64).add_const(1f64);
start.mul(function2).add(end.mul(function))
}
}
pub fn lerp_density_static_start<'a>(
delta: DensityFunction<'a>,
start: f64,
end: DensityFunction<'a>,
) -> DensityFunction<'a> {
delta.mul(end.add_const(-start)).add_const(start)
}

View File

@@ -1,6 +1,7 @@
#![allow(dead_code)]
pub mod density;
mod perlin;
mod router;
mod simplex;
pub mod builtin_noise_params {

View File

@@ -0,0 +1,365 @@
use std::sync::Arc;
use crate::world_gen::sampler::VeinType;
use super::{
builtin_noise_params,
density::{
apply_blend_density, built_in_noises, lerp_density_static_start,
noise::{InternalNoise, NoiseFunction, ShiftedNoiseFunction},
veritcal_range_choice, ConstantFunction, DensityFunction, RangeFunction, Visitor,
WrapperFunction, WrapperType, YClampedFunction,
},
};
pub struct NoiseRouter<'a> {
barrier: DensityFunction<'a>,
fluid_level_floodedness: DensityFunction<'a>,
fluid_level_spread: DensityFunction<'a>,
lava: DensityFunction<'a>,
temperature: DensityFunction<'a>,
vegetation: DensityFunction<'a>,
continents: DensityFunction<'a>,
erosion: DensityFunction<'a>,
depth: DensityFunction<'a>,
ridges: DensityFunction<'a>,
internal_density: DensityFunction<'a>,
final_densitiy: DensityFunction<'a>,
vein_toggle: DensityFunction<'a>,
vein_ridged: DensityFunction<'a>,
vein_gap: DensityFunction<'a>,
}
impl<'a> NoiseRouter<'a> {
pub fn apply(&'a self, visitor: &'a impl Visitor) -> Self {
NoiseRouter {
barrier: self.barrier.apply(visitor),
fluid_level_floodedness: self.fluid_level_floodedness.apply(visitor),
fluid_level_spread: self.fluid_level_spread.apply(visitor),
lava: self.lava.apply(visitor),
temperature: self.temperature.apply(visitor),
vegetation: self.vegetation.apply(visitor),
continents: self.continents.apply(visitor),
erosion: self.erosion.apply(visitor),
depth: self.depth.apply(visitor),
ridges: self.ridges.apply(visitor),
internal_density: self.internal_density.apply(visitor),
final_densitiy: self.final_densitiy.apply(visitor),
vein_toggle: self.vein_toggle.apply(visitor),
vein_ridged: self.vein_ridged.apply(visitor),
vein_gap: self.vein_gap.apply(visitor),
}
}
pub fn create_surface_noise_router(large_biomes: bool, amplified: bool) -> Self {
let function = DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::AQUIFER_BARRIER.clone(),
None,
)),
1f64,
0.5f64,
));
let function2 = DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::AQUIFER_BARRIER_FLOODEDNESS.clone(),
None,
)),
1f64,
0.67f64,
));
let function3 = DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::AQUIFER_FLUID_LEVEL_SPREAD.clone(),
None,
)),
1f64,
0.7142857142857143f64,
));
let function4 = DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::AQUIFER_LAVA.clone(),
None,
)),
1f64,
1f64,
));
let function5 = built_in_noises::SHIFT_X.clone();
let function6 = built_in_noises::SHIFT_Z.clone();
let function7 = DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new(
Arc::new(function5.clone()),
Arc::new(built_in_noises::ZERO.clone()),
Arc::new(function6.clone()),
0.25f64,
0f64,
Arc::new(InternalNoise::new(
if large_biomes {
builtin_noise_params::TEMPERATURE_LARGE.clone()
} else {
builtin_noise_params::TEMPERATURE.clone()
},
None,
)),
));
let function8 = DensityFunction::ShiftedNoise(ShiftedNoiseFunction::new(
Arc::new(function5.clone()),
Arc::new(built_in_noises::ZERO.clone()),
Arc::new(function6.clone()),
0.25f64,
0f64,
Arc::new(InternalNoise::new(
if large_biomes {
builtin_noise_params::VEGETATION_LARGE.clone()
} else {
builtin_noise_params::VEGETATION.clone()
},
None,
)),
));
let function9 = if large_biomes {
built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE
.factor
.clone()
} else if amplified {
built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE
.factor
.clone()
} else {
built_in_noises::OVERWORLD_SLOPED_CHEESE.factor.clone()
};
let function10 = if large_biomes {
built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE.depth.clone()
} else if amplified {
built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE
.depth
.clone()
} else {
built_in_noises::OVERWORLD_SLOPED_CHEESE.depth.clone()
};
let function11 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul(
function10
.mul(DensityFunction::Wrapper(WrapperFunction::new(
Arc::new(function9),
WrapperType::Cache2D,
)))
.quarter_negative(),
);
let function12 = if large_biomes {
built_in_noises::OVERWORLD_LARGE_SLOPED_CHEESE
.sloped_cheese
.clone()
} else if amplified {
built_in_noises::OVERWORLD_AMPLIFIED_SLOPED_CHEESE
.sloped_cheese
.clone()
} else {
built_in_noises::OVERWORLD_SLOPED_CHEESE
.sloped_cheese
.clone()
};
let function13 = function12.binary_min(
DensityFunction::Constant(ConstantFunction::new(5f64))
.mul(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone()),
);
let function14 = DensityFunction::Range(RangeFunction::new(
Arc::new(function12.clone()),
-1000000f64,
1.5625f64,
Arc::new(function13),
Arc::new(create_caves(function12)),
));
let function15 = apply_blend_density(apply_surface_slides(amplified, function14))
.binary_min(built_in_noises::CAVES_NOODLE_OVERWORLD.clone());
let function16 = built_in_noises::Y.clone();
let i = VeinType::overall_min_y();
let j = VeinType::overall_max_y();
let function17 = veritcal_range_choice(
function16.clone(),
DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::ORE_VEININESS.clone(),
None,
)),
1.5f64,
1.5f64,
)),
i,
j,
0,
);
let function18 = veritcal_range_choice(
function16.clone(),
DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::ORE_VEIN_A.clone(),
None,
)),
4f64,
4f64,
)),
i,
j,
0,
)
.abs();
let function19 = veritcal_range_choice(
function16,
DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::ORE_VEIN_B.clone(),
None,
)),
4f64,
4f64,
)),
i,
j,
0,
)
.abs();
let function20 = DensityFunction::Constant(ConstantFunction::new(-0.08f64))
.add(function18.binary_max(function19));
let function21 = DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::ORE_GAP.clone(),
None,
)),
1f64,
1f64,
));
Self {
barrier: function,
fluid_level_floodedness: function2,
fluid_level_spread: function3,
lava: function4,
temperature: function7,
vegetation: function8,
continents: if large_biomes {
built_in_noises::CONTINENTS_OVERWORLD_LARGE_BIOME.clone()
} else {
built_in_noises::CONTINENTS_OVERWORLD.clone()
},
erosion: if large_biomes {
built_in_noises::EROSION_OVERWORLD_LARGE_BIOME.clone()
} else {
built_in_noises::CONTINENTS_OVERWORLD.clone()
},
depth: function10,
ridges: built_in_noises::RIDGES_OVERWORLD.clone(),
internal_density: apply_surface_slides(
amplified,
function11.add_const(-0.703125).clamp(-64f64, 64f64),
),
final_densitiy: function15,
vein_toggle: function17,
vein_ridged: function20,
vein_gap: function21,
}
}
}
fn apply_surface_slides(amplified: bool, density: DensityFunction) -> DensityFunction {
apply_slides(
density,
-64,
384,
if amplified { 16 } else { 80 },
if amplified { 0 } else { 64 },
-0.078125f64,
0,
24,
if amplified { 0.4f64 } else { 0.1171875f64 },
)
}
#[allow(clippy::too_many_arguments)]
fn apply_slides(
density: DensityFunction,
y_min: i32,
y_max: i32,
top_rel_y_min: i32,
top_rel_y_max: i32,
top_density: f64,
bottom_rel_y_min: i32,
bottom_rel_y_max: i32,
bottom_density: f64,
) -> DensityFunction {
let function2 = DensityFunction::ClampedY(YClampedFunction::new(
y_min + y_max - top_rel_y_min,
y_min + y_max + -top_rel_y_max,
1f64,
0f64,
));
let function = lerp_density_static_start(function2, top_density, density);
let function3 = DensityFunction::ClampedY(YClampedFunction::new(
y_min + bottom_rel_y_min,
y_min + bottom_rel_y_max,
0f64,
1f64,
));
lerp_density_static_start(function3, bottom_density, function)
}
fn create_caves(sloped_cheese: DensityFunction) -> DensityFunction {
let function = built_in_noises::CAVES_SPAGHETTI_2D_OVERWORLD.clone();
let function2 = built_in_noises::CAVES_SPAGHETTI_ROUGHNESS_FUNCTION_OVERWORLD.clone();
let function3 = DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::CAVE_LAYER.clone(),
None,
)),
1f64,
8f64,
));
let function4 = DensityFunction::Constant(ConstantFunction::new(4f64)).mul(function3.square());
let function5 = DensityFunction::Noise(NoiseFunction::new(
Arc::new(InternalNoise::new(
builtin_noise_params::CAVE_CHEESE.clone(),
None,
)),
1f64,
0.6666666666666666f64,
));
let function6 = DensityFunction::Constant(ConstantFunction::new(0.27f64))
.add(function5)
.clamp(-1f64, 1f64)
.add(
DensityFunction::Constant(ConstantFunction::new(1.5f64))
.add(DensityFunction::Constant(ConstantFunction::new(-0.64f64)).mul(sloped_cheese))
.clamp(0f64, 0.5f64),
);
let function7 = function4.add(function6);
let function8 = function7
.binary_min(built_in_noises::CAVES_ENTRANCES_OVERWORLD.clone())
.binary_min(function.add(function2));
let function9 = built_in_noises::CAVES_PILLARS_OVERWORLD.clone();
let function10 = DensityFunction::Range(RangeFunction::new(
Arc::new(function9.clone()),
-1000000f64,
0.03f64,
Arc::new(DensityFunction::Constant(ConstantFunction::new(
-1000000f64,
))),
Arc::new(function9),
));
function8.binary_max(function10)
}

View File

@@ -0,0 +1,28 @@
pub enum VeinType {
Copper,
Iron,
}
impl VeinType {
pub fn min_y(&self) -> i32 {
match self {
Self::Copper => 0,
Self::Iron => -60,
}
}
pub fn max_y(&self) -> i32 {
match self {
Self::Copper => 50,
Self::Iron => -8,
}
}
pub fn overall_min_y() -> i32 {
-60
}
pub fn overall_max_y() -> i32 {
60
}
}