467 lines
13 KiB
Rust
467 lines
13 KiB
Rust
use pumpkin_data::chunk::DoublePerlinNoiseParameters;
|
|
use pumpkin_util::{noise::perlin::OctavePerlinNoiseSampler, random::RandomImpl};
|
|
|
|
#[derive(Clone)]
|
|
pub struct DoublePerlinNoiseSampler {
|
|
first_sampler: OctavePerlinNoiseSampler,
|
|
second_sampler: OctavePerlinNoiseSampler,
|
|
amplitude: f64,
|
|
max_value: f64,
|
|
}
|
|
|
|
impl DoublePerlinNoiseSampler {
|
|
const fn create_amplitude(octaves: i32) -> f64 {
|
|
0.1f64 * (1f64 + 1f64 / (octaves + 1) as f64)
|
|
}
|
|
|
|
#[must_use]
|
|
pub const fn max_value(&self) -> f64 {
|
|
self.max_value
|
|
}
|
|
|
|
pub fn from_params(
|
|
rand: &mut impl RandomImpl,
|
|
parameters: &DoublePerlinNoiseParameters,
|
|
legacy: bool,
|
|
) -> Self {
|
|
Self::new(
|
|
rand,
|
|
parameters.first_octave,
|
|
parameters.amplitudes,
|
|
parameters.amplitude,
|
|
legacy,
|
|
)
|
|
}
|
|
|
|
pub fn get_amplitude(amplitudes: &[f64]) -> f64 {
|
|
let mut j = i32::MAX;
|
|
let mut k = i32::MIN;
|
|
|
|
for (index, amplitude) in amplitudes.iter().enumerate() {
|
|
if *amplitude != 0f64 {
|
|
j = i32::min(j, index as i32);
|
|
k = i32::max(k, index as i32);
|
|
}
|
|
}
|
|
|
|
0.16666666666666666f64 / Self::create_amplitude(k - j)
|
|
}
|
|
|
|
pub fn new(
|
|
rand: &mut impl RandomImpl,
|
|
first_octave: i32,
|
|
amplitudes: &[f64],
|
|
amplitude: f64,
|
|
legacy: bool,
|
|
) -> Self {
|
|
let first_sampler = OctavePerlinNoiseSampler::new(rand, first_octave, amplitudes, legacy);
|
|
let second_sampler = OctavePerlinNoiseSampler::new(rand, first_octave, amplitudes, legacy);
|
|
|
|
let max_value = (first_sampler.max_value() + second_sampler.max_value()) * amplitude;
|
|
|
|
Self {
|
|
first_sampler,
|
|
second_sampler,
|
|
amplitude,
|
|
max_value,
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn sample(&self, x: f64, y: f64, z: f64) -> f64 {
|
|
let d = x * 1.0181268882175227f64;
|
|
let e = y * 1.0181268882175227f64;
|
|
let f = z * 1.0181268882175227f64;
|
|
|
|
(self.first_sampler.sample(x, y, z) + self.second_sampler.sample(d, e, f)) * self.amplitude
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod double_perlin_noise_sampler_test {
|
|
use crate::generation::noise::perlin::DoublePerlinNoiseSampler;
|
|
use pumpkin_data::chunk::DoublePerlinNoiseParameters;
|
|
use pumpkin_util::random::{
|
|
RandomGenerator, RandomImpl, legacy_rand::LegacyRand, xoroshiro128::Xoroshiro,
|
|
};
|
|
|
|
#[test]
|
|
fn sample_legacy() {
|
|
let mut rand = LegacyRand::from_seed(513513513);
|
|
assert_eq!(rand.next_i32(), -1302745855);
|
|
|
|
let mut rand_gen = RandomGenerator::Legacy(rand);
|
|
let params = DoublePerlinNoiseParameters::new(
|
|
0,
|
|
0,
|
|
&[4f64],
|
|
0,
|
|
0,
|
|
DoublePerlinNoiseSampler::get_amplitude(&[4f64]),
|
|
);
|
|
let sampler = DoublePerlinNoiseSampler::from_params(&mut rand_gen, ¶ms, true);
|
|
|
|
let values = [
|
|
(
|
|
(
|
|
3.7329617139221236E7,
|
|
2.847228022372606E8,
|
|
-1.8244299064688918E8,
|
|
),
|
|
-0.5044027150385925,
|
|
),
|
|
(
|
|
(
|
|
8.936597679535551E7,
|
|
1.491954533221004E8,
|
|
3.457494216166344E8,
|
|
),
|
|
-1.0004671438756043,
|
|
),
|
|
(
|
|
(
|
|
-2.2479845046034336E8,
|
|
-4.085449163378981E7,
|
|
1.343082907470065E8,
|
|
),
|
|
2.1781128778536973,
|
|
),
|
|
(
|
|
(
|
|
-1.9094944979652843E8,
|
|
3.695081561625232E8,
|
|
2.1566424798360935E8,
|
|
),
|
|
-1.2571847948126453,
|
|
),
|
|
(
|
|
(
|
|
1.8486356004931596E8,
|
|
-4.148713734284534E8,
|
|
4.8687219454012525E8,
|
|
),
|
|
-0.550285244015363,
|
|
),
|
|
(
|
|
(
|
|
1.7115351141710258E8,
|
|
-1.8835885697652313E8,
|
|
1.7031060329927653E8,
|
|
),
|
|
-0.6953327750604766,
|
|
),
|
|
(
|
|
(
|
|
8.952317194270046E7,
|
|
-5.420942524023042E7,
|
|
-2.5987559023045145E7,
|
|
),
|
|
2.7361630914824393,
|
|
),
|
|
(
|
|
(
|
|
-8.36195975247282E8,
|
|
-1.2167090318484206E8,
|
|
2.1237199673286602E8,
|
|
),
|
|
-1.5518675789351004,
|
|
),
|
|
(
|
|
(
|
|
3.333103540906928E8,
|
|
5.088236187007203E8,
|
|
-3.521137809477999E8,
|
|
),
|
|
0.6928720433082317,
|
|
),
|
|
(
|
|
(
|
|
7.82760234776598E7,
|
|
-2.5204361464037597E7,
|
|
-1.6615974590937865E8,
|
|
),
|
|
-0.5102124930620466,
|
|
),
|
|
];
|
|
|
|
for ((x, y, z), sample) in values {
|
|
assert_eq!(sampler.sample(x, y, z), sample);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn sample_xoroshiro() {
|
|
let mut rand = Xoroshiro::from_seed(5);
|
|
assert_eq!(rand.next_i32(), -1678727252);
|
|
|
|
let mut rand_gen = RandomGenerator::Xoroshiro(rand);
|
|
|
|
let params = DoublePerlinNoiseParameters::new(
|
|
0,
|
|
1,
|
|
&[2f64, 4f64],
|
|
0,
|
|
0,
|
|
DoublePerlinNoiseSampler::get_amplitude(&[2f64, 4f64]),
|
|
);
|
|
|
|
let sampler = DoublePerlinNoiseSampler::from_params(&mut rand_gen, ¶ms, false);
|
|
|
|
let values = [
|
|
(
|
|
(
|
|
-2.4823401687190732E8,
|
|
1.6909869132832196E8,
|
|
1.0510057123823991E8,
|
|
),
|
|
-0.09627881756376819,
|
|
),
|
|
(
|
|
(
|
|
1.2971355215791291E8,
|
|
-3.614855223614046E8,
|
|
1.9997149869463342E8,
|
|
),
|
|
0.4412466810560897,
|
|
),
|
|
(
|
|
(
|
|
-1.9858224577678584E7,
|
|
2.5103843334053648E8,
|
|
2.253841390457064E8,
|
|
),
|
|
-1.3086196098510068,
|
|
),
|
|
(
|
|
(
|
|
1.4243878295159304E8,
|
|
-1.9185612600051942E8,
|
|
4.7736284830701286E8,
|
|
),
|
|
1.727683424808049,
|
|
),
|
|
(
|
|
(
|
|
-9.411241394159131E7,
|
|
4.4052130232611096E8,
|
|
5.1042225596740514E8,
|
|
),
|
|
-0.4651812519989636,
|
|
),
|
|
(
|
|
(
|
|
3.007670445405074E8,
|
|
1.4630490674448165E8,
|
|
-1.681994537227527E8,
|
|
),
|
|
-0.8607587886441551,
|
|
),
|
|
(
|
|
(
|
|
-2.290369962944646E8,
|
|
-4.9627750061129004E8,
|
|
9.751744069476394E7,
|
|
),
|
|
-0.3592693708849225,
|
|
),
|
|
(
|
|
(
|
|
-5.380825223911383E7,
|
|
6.317706682942032E7,
|
|
-3.0105795661690116E8,
|
|
),
|
|
0.7372424991843702,
|
|
),
|
|
(
|
|
(
|
|
-1.4261684559190175E8,
|
|
9.987839104129419E7,
|
|
3.3290027416415906E8,
|
|
),
|
|
0.27706980571082485,
|
|
),
|
|
(
|
|
(
|
|
-8.881637146904664E7,
|
|
1.1033687270820947E8,
|
|
-1.0014482192140123E8,
|
|
),
|
|
-0.4602443245357103,
|
|
),
|
|
];
|
|
|
|
for ((x, y, z), sample) in values {
|
|
assert_eq!(sampler.sample(x, y, z), sample);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod octave_perline_noise_sampler_test {
|
|
use pumpkin_util::random::{RandomGenerator, RandomImpl, xoroshiro128::Xoroshiro};
|
|
|
|
use super::OctavePerlinNoiseSampler;
|
|
|
|
#[test]
|
|
fn sample() {
|
|
let mut rand = Xoroshiro::from_seed(513513513);
|
|
assert_eq!(rand.next_i32(), 404174895);
|
|
|
|
let (start, amplitudes) = OctavePerlinNoiseSampler::calculate_amplitudes(&[1, 2, 3]);
|
|
let mut rand_gen = RandomGenerator::Xoroshiro(rand);
|
|
let sampler = OctavePerlinNoiseSampler::new(&mut rand_gen, start, &litudes, false);
|
|
|
|
let values = [
|
|
(
|
|
(
|
|
1.4633897801218182E8,
|
|
3.360929121402108E8,
|
|
-1.7376184515043163E8,
|
|
),
|
|
-0.16510137639683028,
|
|
),
|
|
(
|
|
(
|
|
-3.952093942501234E8,
|
|
-8.149682915016855E7,
|
|
2.0761709535397574E8,
|
|
),
|
|
-0.19865227457826365,
|
|
),
|
|
(
|
|
(
|
|
1.0603518812861493E8,
|
|
-1.6028050039630303E8,
|
|
9.621510690305333E7,
|
|
),
|
|
-0.16157548492944798,
|
|
),
|
|
(
|
|
(
|
|
-2.2789281609860754E8,
|
|
1.2416505757723756E8,
|
|
-3.047619296454517E8,
|
|
),
|
|
-0.05762575118540847,
|
|
),
|
|
(
|
|
(
|
|
-1.6361322604690066E8,
|
|
-1.862652364900794E8,
|
|
9.03458926538596E7,
|
|
),
|
|
0.21589404036742288,
|
|
),
|
|
(
|
|
(
|
|
-1.6074718857061076E8,
|
|
-4.816551924254624E8,
|
|
-9.930236785759543E7,
|
|
),
|
|
0.1888188057014473,
|
|
),
|
|
(
|
|
(
|
|
-1.6848478115907547E8,
|
|
1.9495247771890038E8,
|
|
1.3780564333313772E8,
|
|
),
|
|
0.23114508298896774,
|
|
),
|
|
(
|
|
(
|
|
2.5355640846261957E8,
|
|
-2.5973376726076955E8,
|
|
3.7834594620459855E7,
|
|
),
|
|
-0.23703473310230702,
|
|
),
|
|
(
|
|
(
|
|
-8.636649828254433E7,
|
|
1.7017680431584623E8,
|
|
2.941033134334743E8,
|
|
),
|
|
-0.14050102207739693,
|
|
),
|
|
(
|
|
(
|
|
-4.573784466442647E8,
|
|
1.789046617664721E8,
|
|
-5.515223967099891E8,
|
|
),
|
|
-0.1422470544720957,
|
|
),
|
|
];
|
|
|
|
for ((x, y, z), sample) in values {
|
|
assert_eq!(sampler.sample(x, y, z), sample);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod perlin_noise_sampler_test {
|
|
|
|
use pumpkin_util::noise::perlin::OctavePerlinNoiseSampler;
|
|
|
|
#[test]
|
|
fn precision() {
|
|
let values = [
|
|
2.5E-4,
|
|
1.25E-4,
|
|
6.25E-5,
|
|
3.125E-5,
|
|
1.5625E-5,
|
|
7.8125E-6,
|
|
3.90625E-6,
|
|
1.953125E-6,
|
|
9.765625E-7,
|
|
4.8828125E-7,
|
|
2.44140625E-7,
|
|
1.220703125E-7,
|
|
6.103515625E-8,
|
|
3.0517578125E-8,
|
|
1.52587890625E-8,
|
|
7.62939453125E-9,
|
|
3.814697265625E-9,
|
|
1.9073486328125E-9,
|
|
9.5367431640625E-10,
|
|
4.76837158203125E-10,
|
|
2.384185791015625E-10,
|
|
1.1920928955078125E-10,
|
|
5.960464477539063E-11,
|
|
2.980232238769531E-11,
|
|
1.4901161193847657E-11,
|
|
7.450580596923828E-12,
|
|
3.725290298461914E-12,
|
|
1.862645149230957E-12,
|
|
9.313225746154785E-13,
|
|
];
|
|
let mut value_iter = values.iter();
|
|
|
|
for x in 1..20 {
|
|
let mut f = 0.0005f64;
|
|
for _ in 0..x {
|
|
f /= 2f64;
|
|
}
|
|
let value = OctavePerlinNoiseSampler::maintain_precision(f);
|
|
assert_eq!(value, *value_iter.next().unwrap());
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn calculate_amplitudes() {
|
|
let (first, amplitudes) =
|
|
OctavePerlinNoiseSampler::calculate_amplitudes(&(-15..=0).collect::<Vec<i32>>());
|
|
|
|
assert_eq!(first, -15);
|
|
assert_eq!(
|
|
amplitudes,
|
|
[
|
|
1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0
|
|
]
|
|
);
|
|
}
|
|
}
|