327 lines
9.0 KiB
Rust
327 lines
9.0 KiB
Rust
use std::array;
|
|
|
|
use pumpkin_data::noise_router::{InterpolatedNoiseSamplerData, NoiseData, ShiftedNoiseData};
|
|
use pumpkin_util::{
|
|
math::{clamped_lerp, vector3::Vector3},
|
|
noise::perlin::OctavePerlinNoiseSampler,
|
|
random::RandomGenerator,
|
|
};
|
|
|
|
use crate::generation::{
|
|
noise::perlin::DoublePerlinNoiseSampler,
|
|
noise::router::{
|
|
chunk_density_function::ChunkNoiseFunctionSampleOptions,
|
|
chunk_noise_router::{ChunkNoiseFunctionComponent, StaticChunkNoiseFunctionComponentImpl},
|
|
},
|
|
};
|
|
|
|
use super::{NoiseFunctionComponentRange, StaticIndependentChunkNoiseFunctionComponentImpl};
|
|
|
|
pub struct Noise {
|
|
sampler: DoublePerlinNoiseSampler,
|
|
data: &'static NoiseData,
|
|
}
|
|
|
|
impl Noise {
|
|
pub const fn new(sampler: DoublePerlinNoiseSampler, data: &'static NoiseData) -> Self {
|
|
Self { sampler, data }
|
|
}
|
|
}
|
|
|
|
impl NoiseFunctionComponentRange for Noise {
|
|
#[inline]
|
|
fn min(&self) -> f64 {
|
|
-self.max()
|
|
}
|
|
|
|
#[inline]
|
|
fn max(&self) -> f64 {
|
|
self.sampler.max_value()
|
|
}
|
|
}
|
|
|
|
impl StaticIndependentChunkNoiseFunctionComponentImpl for Noise {
|
|
fn sample(&self, pos: &Vector3<i32>) -> f64 {
|
|
self.sampler.sample(
|
|
pos.x as f64 * self.data.xz_scale,
|
|
pos.y as f64 * self.data.y_scale,
|
|
pos.z as f64 * self.data.xz_scale,
|
|
)
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
fn shift_sample_3d(sampler: &DoublePerlinNoiseSampler, x: f64, y: f64, z: f64) -> f64 {
|
|
sampler.sample(x * 0.25f64, y * 0.25f64, z * 0.25f64) * 4f64
|
|
}
|
|
|
|
pub struct ShiftA {
|
|
sampler: DoublePerlinNoiseSampler,
|
|
}
|
|
|
|
impl ShiftA {
|
|
pub const fn new(sampler: DoublePerlinNoiseSampler) -> Self {
|
|
Self { sampler }
|
|
}
|
|
}
|
|
|
|
impl NoiseFunctionComponentRange for ShiftA {
|
|
#[inline]
|
|
fn min(&self) -> f64 {
|
|
-self.max()
|
|
}
|
|
|
|
#[inline]
|
|
fn max(&self) -> f64 {
|
|
self.sampler.max_value() * 4.0
|
|
}
|
|
}
|
|
|
|
impl StaticIndependentChunkNoiseFunctionComponentImpl for ShiftA {
|
|
fn sample(&self, pos: &Vector3<i32>) -> f64 {
|
|
shift_sample_3d(&self.sampler, pos.x as f64, 0.0, pos.z as f64)
|
|
}
|
|
}
|
|
|
|
pub struct ShiftB {
|
|
sampler: DoublePerlinNoiseSampler,
|
|
}
|
|
|
|
impl ShiftB {
|
|
pub const fn new(sampler: DoublePerlinNoiseSampler) -> Self {
|
|
Self { sampler }
|
|
}
|
|
}
|
|
|
|
impl NoiseFunctionComponentRange for ShiftB {
|
|
#[inline]
|
|
fn min(&self) -> f64 {
|
|
-self.max()
|
|
}
|
|
|
|
#[inline]
|
|
fn max(&self) -> f64 {
|
|
self.sampler.max_value() * 4.0
|
|
}
|
|
}
|
|
|
|
impl StaticIndependentChunkNoiseFunctionComponentImpl for ShiftB {
|
|
fn sample(&self, pos: &Vector3<i32>) -> f64 {
|
|
shift_sample_3d(&self.sampler, pos.z as f64, pos.x as f64, 0.0)
|
|
}
|
|
}
|
|
|
|
pub struct ShiftedNoise {
|
|
input_x_index: usize,
|
|
input_y_index: usize,
|
|
input_z_index: usize,
|
|
sampler: DoublePerlinNoiseSampler,
|
|
data: &'static ShiftedNoiseData,
|
|
}
|
|
|
|
impl NoiseFunctionComponentRange for ShiftedNoise {
|
|
#[inline]
|
|
fn min(&self) -> f64 {
|
|
-self.max()
|
|
}
|
|
|
|
#[inline]
|
|
fn max(&self) -> f64 {
|
|
self.sampler.max_value()
|
|
}
|
|
}
|
|
|
|
impl StaticChunkNoiseFunctionComponentImpl for ShiftedNoise {
|
|
fn sample(
|
|
&self,
|
|
component_stack: &mut [ChunkNoiseFunctionComponent],
|
|
pos: &Vector3<i32>,
|
|
sample_options: &ChunkNoiseFunctionSampleOptions,
|
|
) -> f64 {
|
|
let translated_x = pos.x as f64 * self.data.xz_scale
|
|
+ ChunkNoiseFunctionComponent::sample_from_stack(
|
|
&mut component_stack[..=self.input_x_index],
|
|
pos,
|
|
sample_options,
|
|
);
|
|
let translated_y = pos.y as f64 * self.data.y_scale
|
|
+ ChunkNoiseFunctionComponent::sample_from_stack(
|
|
&mut component_stack[..=self.input_y_index],
|
|
pos,
|
|
sample_options,
|
|
);
|
|
let translated_z = pos.z as f64 * self.data.xz_scale
|
|
+ ChunkNoiseFunctionComponent::sample_from_stack(
|
|
&mut component_stack[..=self.input_z_index],
|
|
pos,
|
|
sample_options,
|
|
);
|
|
|
|
self.sampler
|
|
.sample(translated_x, translated_y, translated_z)
|
|
}
|
|
}
|
|
|
|
impl ShiftedNoise {
|
|
pub const fn new(
|
|
input_x_index: usize,
|
|
input_y_index: usize,
|
|
input_z_index: usize,
|
|
sampler: DoublePerlinNoiseSampler,
|
|
data: &'static ShiftedNoiseData,
|
|
) -> Self {
|
|
Self {
|
|
input_x_index,
|
|
input_y_index,
|
|
input_z_index,
|
|
sampler,
|
|
data,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct InterpolatedNoiseSampler {
|
|
lower_noise: OctavePerlinNoiseSampler,
|
|
upper_noise: OctavePerlinNoiseSampler,
|
|
noise: OctavePerlinNoiseSampler,
|
|
data: &'static InterpolatedNoiseSamplerData,
|
|
fractions: [f64; 16],
|
|
max_value: f64,
|
|
}
|
|
|
|
impl InterpolatedNoiseSampler {
|
|
pub fn new(data: &'static InterpolatedNoiseSamplerData, random: &mut RandomGenerator) -> Self {
|
|
let big_start = -15;
|
|
let big_amplitudes = [1.0; 16];
|
|
|
|
let little_start = -7;
|
|
let little_amplitudes = [1.0; 8];
|
|
|
|
let lower_noise = OctavePerlinNoiseSampler::new(random, big_start, &big_amplitudes, true);
|
|
let upper_noise = OctavePerlinNoiseSampler::new(random, big_start, &big_amplitudes, true);
|
|
let noise = OctavePerlinNoiseSampler::new(random, little_start, &little_amplitudes, true);
|
|
|
|
let max_value = lower_noise.get_total_amplitude(data.scaled_y_scale + 2.0);
|
|
|
|
let fractions = array::from_fn(|index| {
|
|
let mut o = 1.0;
|
|
for _ in 0..index {
|
|
o /= 2.0;
|
|
}
|
|
o
|
|
});
|
|
|
|
Self {
|
|
lower_noise,
|
|
upper_noise,
|
|
noise,
|
|
data,
|
|
fractions,
|
|
max_value,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl NoiseFunctionComponentRange for InterpolatedNoiseSampler {
|
|
#[inline]
|
|
fn min(&self) -> f64 {
|
|
-self.max()
|
|
}
|
|
|
|
#[inline]
|
|
fn max(&self) -> f64 {
|
|
self.max_value
|
|
}
|
|
}
|
|
|
|
impl StaticIndependentChunkNoiseFunctionComponentImpl for InterpolatedNoiseSampler {
|
|
fn sample(&self, pos: &Vector3<i32>) -> f64 {
|
|
let d = pos.x as f64 * self.data.scaled_xz_scale;
|
|
let e = pos.y as f64 * self.data.scaled_y_scale;
|
|
let f = pos.z as f64 * self.data.scaled_xz_scale;
|
|
|
|
let g = d / self.data.xz_factor;
|
|
let h = e / self.data.y_factor;
|
|
let i = f / self.data.xz_factor;
|
|
|
|
let j = self.data.scaled_y_scale * self.data.smear_scale_multiplier;
|
|
let k = j / self.data.y_factor;
|
|
|
|
// It's ok the the fractions are more than this; zip will cut it short
|
|
let n: f64 = self
|
|
.noise
|
|
.samplers
|
|
.iter()
|
|
.rev()
|
|
.zip(self.fractions)
|
|
.map(|(data, fraction)| {
|
|
let mapped_x = OctavePerlinNoiseSampler::maintain_precision(g * fraction);
|
|
let mapped_y = OctavePerlinNoiseSampler::maintain_precision(h * fraction);
|
|
let mapped_z = OctavePerlinNoiseSampler::maintain_precision(i * fraction);
|
|
|
|
data.sampler.sample_no_fade(
|
|
mapped_x,
|
|
mapped_y,
|
|
mapped_z,
|
|
k * fraction,
|
|
h * fraction,
|
|
) / fraction
|
|
})
|
|
.sum();
|
|
|
|
let q = f64::midpoint(n / 10f64, 1f64);
|
|
let bl2 = q >= 1f64;
|
|
let bl3 = q <= 0f64;
|
|
|
|
let l = if bl2 {
|
|
0.0
|
|
} else {
|
|
self.lower_noise
|
|
.samplers
|
|
.iter()
|
|
.rev()
|
|
.zip(self.fractions)
|
|
.map(|(data, fraction)| {
|
|
let mapped_x = OctavePerlinNoiseSampler::maintain_precision(d * fraction);
|
|
let mapped_y = OctavePerlinNoiseSampler::maintain_precision(e * fraction);
|
|
let mapped_z = OctavePerlinNoiseSampler::maintain_precision(f * fraction);
|
|
|
|
data.sampler.sample_no_fade(
|
|
mapped_x,
|
|
mapped_y,
|
|
mapped_z,
|
|
j * fraction,
|
|
e * fraction,
|
|
) / fraction
|
|
})
|
|
.sum()
|
|
};
|
|
|
|
let m = if bl3 {
|
|
0.0
|
|
} else {
|
|
self.upper_noise
|
|
.samplers
|
|
.iter()
|
|
.rev()
|
|
.zip(self.fractions)
|
|
.map(|(data, fraction)| {
|
|
let mapped_x = OctavePerlinNoiseSampler::maintain_precision(d * fraction);
|
|
let mapped_y = OctavePerlinNoiseSampler::maintain_precision(e * fraction);
|
|
let mapped_z = OctavePerlinNoiseSampler::maintain_precision(f * fraction);
|
|
|
|
data.sampler.sample_no_fade(
|
|
mapped_x,
|
|
mapped_y,
|
|
mapped_z,
|
|
j * fraction,
|
|
e * fraction,
|
|
) / fraction
|
|
})
|
|
.sum()
|
|
};
|
|
|
|
clamped_lerp(l / 512f64, m / 512f64, q) / 128f64
|
|
}
|
|
}
|