From e49c46df322195c306fa232fe7befc8ebd192b3d Mon Sep 17 00:00:00 2001 From: kralverde Date: Wed, 11 Sep 2024 17:37:12 -0400 Subject: [PATCH] split code up --- pumpkin-world/src/world_gen/mod.rs | 4 - pumpkin-world/src/world_gen/noise/mod.rs | 63 ++ pumpkin-world/src/world_gen/noise/perlin.rs | 571 +++++++++++++++ .../world_gen/{noise.rs => noise/simplex.rs} | 651 +----------------- 4 files changed, 643 insertions(+), 646 deletions(-) create mode 100644 pumpkin-world/src/world_gen/noise/mod.rs create mode 100644 pumpkin-world/src/world_gen/noise/perlin.rs rename pumpkin-world/src/world_gen/{noise.rs => noise/simplex.rs} (52%) diff --git a/pumpkin-world/src/world_gen/mod.rs b/pumpkin-world/src/world_gen/mod.rs index 693132f5c..4712a36f3 100644 --- a/pumpkin-world/src/world_gen/mod.rs +++ b/pumpkin-world/src/world_gen/mod.rs @@ -14,7 +14,3 @@ pub fn get_world_gen(seed: Seed) -> Box { // TODO decide which WorldGenerator to pick based on config. Box::new(PlainsGenerator::new(seed)) } - -pub struct ChunkRandom { - sample_count: i32, -} diff --git a/pumpkin-world/src/world_gen/noise/mod.rs b/pumpkin-world/src/world_gen/noise/mod.rs new file mode 100644 index 000000000..206a47a30 --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/mod.rs @@ -0,0 +1,63 @@ +mod perlin; +mod simplex; + +pub fn lerp(delta: f64, start: f64, end: f64) -> f64 { + start + delta * (end - start) +} + +pub fn lerp2(delta_x: f64, delta_y: f64, x0y0: f64, x1y0: f64, x0y1: f64, x1y1: f64) -> f64 { + lerp( + delta_y, + lerp(delta_x, x0y0, x1y0), + lerp(delta_x, x0y1, x1y1), + ) +} + +pub fn lerp3( + delta_x: f64, + delta_y: f64, + delta_z: f64, + x0y0z0: f64, + x1y0z0: f64, + x0y1z0: f64, + x1y1z0: f64, + x0y0z1: f64, + x1y0z1: f64, + x0y1z1: f64, + x1y1z1: f64, +) -> f64 { + lerp( + delta_z, + lerp2(delta_x, delta_y, x0y0z0, x1y0z0, x0y1z0, x1y1z0), + lerp2(delta_x, delta_y, x0y0z1, x1y0z1, x0y1z1, x1y1z1), + ) +} + +struct Gradient { + x: i32, + y: i32, + z: i32, +} + +const GRADIENTS: [Gradient; 16] = [ + Gradient { x: 1, y: 1, z: 0 }, + Gradient { x: -1, y: 1, z: 0 }, + Gradient { x: 1, y: -1, z: 0 }, + Gradient { x: -1, y: -1, z: 0 }, + Gradient { x: 1, y: 0, z: 1 }, + Gradient { x: -1, y: 0, z: 1 }, + Gradient { x: 1, y: 0, z: -1 }, + Gradient { x: -1, y: 0, z: -1 }, + Gradient { x: 0, y: 1, z: 1 }, + Gradient { x: 0, y: -1, z: 1 }, + Gradient { x: 0, y: 1, z: -1 }, + Gradient { x: 0, y: -1, z: -1 }, + Gradient { x: 1, y: 1, z: 0 }, + Gradient { x: 0, y: -1, z: 1 }, + Gradient { x: -1, y: 1, z: 0 }, + Gradient { x: 0, y: -1, z: -1 }, +]; + +fn dot(gradient: &Gradient, x: f64, y: f64, z: f64) -> f64 { + gradient.x as f64 * x + gradient.y as f64 * y + gradient.z as f64 * z +} diff --git a/pumpkin-world/src/world_gen/noise/perlin.rs b/pumpkin-world/src/world_gen/noise/perlin.rs new file mode 100644 index 000000000..a39caa6bc --- /dev/null +++ b/pumpkin-world/src/world_gen/noise/perlin.rs @@ -0,0 +1,571 @@ +use pumpkin_core::random::Random; + +use super::{dot, lerp3, GRADIENTS}; + +pub struct PerlinNoiseSampler { + permutation: Box<[u8]>, + x_origin: f64, + y_origin: f64, + z_origin: f64, +} + +impl PerlinNoiseSampler { + pub fn new(random: &mut impl Random) -> Self { + let x_origin = random.next_f64() * 256f64; + let y_origin = random.next_f64() * 256f64; + let z_origin = random.next_f64() * 256f64; + + let mut permutation = [0u8; 256]; + + permutation + .iter_mut() + .enumerate() + .for_each(|(i, x)| *x = i as u8); + + for i in 0..256 { + let j = random.next_bounded_i32((256 - i) as i32) as usize; + permutation.swap(i, i + j); + } + + Self { + permutation: Box::new(permutation), + x_origin, + y_origin, + z_origin, + } + } + + pub fn sample_flat_y(&self, x: f64, y: f64, z: f64) -> f64 { + self.sample_no_fade(x, y, z, 0f64, 0f64) + } + + pub fn sample_no_fade(&self, x: f64, y: f64, z: f64, y_scale: f64, y_max: f64) -> f64 { + let trans_x = x + self.x_origin; + let trans_y = y + self.y_origin; + let trans_z = z + self.z_origin; + + let x_int = trans_x.floor() as i32; + let y_int = trans_y.floor() as i32; + let z_int = trans_z.floor() as i32; + + let x_dec = trans_x - x_int as f64; + let y_dec = trans_y - y_int as f64; + let z_dec = trans_z - z_int as f64; + + let y_noise = if y_scale != 0f64 { + let raw_y_dec = if y_max >= 0f64 && y_max < y_dec { + y_max + } else { + y_dec + }; + (raw_y_dec / y_scale + 1.0E-7f32 as f64).floor() * y_scale + } else { + 0f64 + }; + + self.sample(x_int, y_int, z_int, x_dec, y_dec - y_noise, z_dec, y_dec) + } + + fn grad(hash: i32, x: f64, y: f64, z: f64) -> f64 { + dot(&GRADIENTS[(hash & 15) as usize], x, y, z) + } + + fn perlin_fade(value: f64) -> f64 { + value * value * value * (value * (value * 6f64 - 15f64) + 10f64) + } + + fn map(&self, input: i32) -> i32 { + (self.permutation[(input & 0xFF) as usize] & 0xFF) as i32 + } + + #[allow(clippy::too_many_arguments)] + fn sample( + &self, + x: i32, + y: i32, + z: i32, + local_x: f64, + local_y: f64, + local_z: f64, + fade_local_y: f64, + ) -> f64 { + let i = self.map(x); + let j = self.map(x.wrapping_add(1)); + let k = self.map(i.wrapping_add(y)); + + let l = self.map(i.wrapping_add(y).wrapping_add(1)); + let m = self.map(j.wrapping_add(y)); + let n = self.map(j.wrapping_add(y).wrapping_add(1)); + + let d = Self::grad(self.map(k.wrapping_add(z)), local_x, local_y, local_z); + let e = Self::grad( + self.map(m.wrapping_add(z)), + local_x - 1f64, + local_y, + local_z, + ); + let f = Self::grad( + self.map(l.wrapping_add(z)), + local_x, + local_y - 1f64, + local_z, + ); + let g = Self::grad( + self.map(n.wrapping_add(z)), + local_x - 1f64, + local_y - 1f64, + local_z, + ); + let h = Self::grad( + self.map(k.wrapping_add(z).wrapping_add(1)), + local_x, + local_y, + local_z - 1f64, + ); + let o = Self::grad( + self.map(m.wrapping_add(z).wrapping_add(1)), + local_x - 1f64, + local_y, + local_z - 1f64, + ); + let p = Self::grad( + self.map(l.wrapping_add(z).wrapping_add(1)), + local_x, + local_y - 1f64, + local_z - 1f64, + ); + let q = Self::grad( + self.map(n.wrapping_add(z).wrapping_add(1)), + local_x - 1f64, + local_y - 1f64, + local_z - 1f64, + ); + let r = Self::perlin_fade(local_x); + let s = Self::perlin_fade(fade_local_y); + let t = Self::perlin_fade(local_z); + + lerp3(r, s, t, d, e, f, g, h, o, p, q) + } +} + +#[cfg(test)] +mod perlin_noise_sampler_test { + use std::ops::Deref; + + use pumpkin_core::random::{xoroshiro128::Xoroshiro, Random}; + + use crate::world_gen::noise::perlin::PerlinNoiseSampler; + + #[test] + fn test_create() { + let mut rand = Xoroshiro::from_seed(111); + assert_eq!(rand.next_i32(), -1467508761); + + let sampler = PerlinNoiseSampler::new(&mut rand); + assert_eq!(sampler.x_origin, 48.58072036717974); + assert_eq!(sampler.y_origin, 110.73235882678037); + assert_eq!(sampler.z_origin, 65.26438852860176); + + let permutation: [u8; 256] = [ + 159, 113, 41, 143, 203, 123, 95, 177, 25, 79, 229, 219, 194, 60, 130, 14, 83, 99, 24, + 202, 207, 232, 167, 152, 220, 201, 29, 235, 87, 147, 74, 160, 155, 97, 111, 31, 85, + 205, 115, 50, 13, 171, 77, 237, 149, 116, 209, 174, 169, 109, 221, 9, 166, 84, 54, 216, + 121, 106, 211, 16, 69, 244, 65, 192, 183, 146, 124, 37, 56, 45, 193, 158, 126, 217, 36, + 255, 162, 163, 230, 103, 63, 90, 191, 214, 20, 138, 32, 39, 238, 67, 64, 105, 250, 140, + 148, 114, 68, 75, 200, 161, 239, 125, 227, 199, 101, 61, 175, 107, 129, 240, 170, 51, + 139, 86, 186, 145, 212, 178, 30, 251, 89, 226, 120, 153, 47, 141, 233, 2, 179, 236, 1, + 19, 98, 21, 164, 108, 11, 23, 91, 204, 119, 88, 165, 195, 168, 26, 48, 206, 128, 6, 52, + 118, 110, 180, 197, 231, 117, 7, 3, 135, 224, 58, 82, 78, 4, 59, 222, 18, 72, 57, 150, + 43, 246, 100, 122, 112, 53, 133, 93, 17, 27, 210, 142, 234, 245, 80, 22, 46, 185, 172, + 71, 248, 33, 173, 76, 35, 40, 92, 228, 127, 254, 70, 42, 208, 73, 104, 187, 62, 154, + 243, 189, 241, 34, 66, 249, 94, 8, 12, 134, 132, 102, 242, 196, 218, 181, 28, 38, 15, + 151, 157, 247, 223, 198, 55, 188, 96, 0, 182, 49, 190, 156, 10, 215, 252, 131, 137, + 184, 176, 136, 81, 44, 213, 253, 144, 225, 5, + ]; + assert_eq!(sampler.permutation.deref(), permutation); + } + + #[test] + fn test_no_y() { + let mut rand = Xoroshiro::from_seed(111); + assert_eq!(rand.next_i32(), -1467508761); + let sampler = PerlinNoiseSampler::new(&mut rand); + + let values = [ + ( + ( + -3.134738528791615E8, + 5.676610095659718E7, + 2.011711832498507E8, + ), + 0.38582139614602945, + ), + ( + (-1369026.560586418, 3.957311252810864E8, 6.797037355570006E8), + 0.15777501333157193, + ), + ( + ( + 6.439373693833767E8, + -3.36218773041759E8, + -3.265494249695775E8, + ), + -0.2806135912409497, + ), + ( + ( + 1.353820060118252E8, + -3.204701624793043E8, + -4.612474746056331E8, + ), + -0.15052865500837787, + ), + ( + ( + -6906850.625560562, + 1.0153663948838013E8, + 2.4923185478305575E8, + ), + -0.3079300694558318, + ), + ( + ( + -7.108376621385525E7, + -2.029413580824217E8, + 2.5164602748045415E8, + ), + 0.03051312670440398, + ), + ( + ( + 1.0591429119126628E8, + -4.7911044364543396E8, + -2918719.2277242197, + ), + -0.11775123159138573, + ), + ( + ( + 4.04615501401398E7, + -3.074409286586152E8, + 5.089118769334092E7, + ), + 0.08763639340713025, + ), + ( + ( + -4.8645283544246924E8, + -3.922570151180015E8, + 2.3741632952563038E8, + ), + 0.08857245482456311, + ), + ( + ( + 2.861710031285905E8, + -1.8973201372718483E8, + -3.2653143323982143E8, + ), + -0.2378339698793312, + ), + ( + ( + 2.885407603819252E8, + -3.358708100884505E7, + -1.4480399660676318E8, + ), + -0.46661747461279457, + ), + ( + ( + 3.6548491156354237E8, + 7.995429702025633E7, + 2.509991661702412E8, + ), + 0.1671543972176835, + ), + ( + ( + 1.3298684552869435E8, + 3.6743804723880893E8, + 5.791092458225288E7, + ), + -0.2704070746642889, + ), + ( + ( + -1.3123184148036437E8, + -2.722300890805201E8, + 2.1601883778132245E7, + ), + 0.05049887915906969, + ), + ( + ( + -5.56047682304707E8, + 3.554803693060646E8, + 3.1647392358159083E8, + ), + -0.21178547899422662, + ), + ( + ( + 5.638216625134594E8, + -2.236907346192737E8, + -5.0562852022285646E8, + ), + 0.03351245780858128, + ), + ( + ( + -5.436956979127073E7, + -1.129261611506945E8, + -1.7909512156895646E8, + ), + 0.31670010349494726, + ), + ( + ( + 1.0915760091641709E8, + 1.932642099859593E7, + -3.405060533753616E8, + ), + -0.13987439655026918, + ), + ( + ( + -6.73911758014991E8, + -2.2147483413687566E8, + -4.531457195005102E7, + ), + 0.07824440437151846, + ), + ( + ( + -2.4827386778136212E8, + -2.6640208832089204E8, + -3.354675096522197E8, + ), + -0.2989735599541437, + ), + ]; + + for ((x, y, z), sample) in values { + assert_eq!(sampler.sample_flat_y(x, y, z), sample); + } + } + + #[test] + fn test_no_fade() { + let mut rand = Xoroshiro::from_seed(111); + assert_eq!(rand.next_i32(), -1467508761); + let sampler = PerlinNoiseSampler::new(&mut rand); + + let values = [ + ( + ( + -3.134738528791615E8, + 5.676610095659718E7, + 2.011711832498507E8, + -1369026.560586418, + 3.957311252810864E8, + ), + 23234.47859421248, + ), + ( + ( + 6.797037355570006E8, + 6.439373693833767E8, + -3.36218773041759E8, + -3.265494249695775E8, + 1.353820060118252E8, + ), + -0.016403984198221984, + ), + ( + ( + -3.204701624793043E8, + -4.612474746056331E8, + -6906850.625560562, + 1.0153663948838013E8, + 2.4923185478305575E8, + ), + 0.3444286491766397, + ), + ( + ( + -7.108376621385525E7, + -2.029413580824217E8, + 2.5164602748045415E8, + 1.0591429119126628E8, + -4.7911044364543396E8, + ), + 0.03051312670440398, + ), + ( + ( + -2918719.2277242197, + 4.04615501401398E7, + -3.074409286586152E8, + 5.089118769334092E7, + -4.8645283544246924E8, + ), + 0.3434020232968479, + ), + ( + ( + -3.922570151180015E8, + 2.3741632952563038E8, + 2.861710031285905E8, + -1.8973201372718483E8, + -3.2653143323982143E8, + ), + -0.07935517045771859, + ), + ( + ( + 2.885407603819252E8, + -3.358708100884505E7, + -1.4480399660676318E8, + 3.6548491156354237E8, + 7.995429702025633E7, + ), + -0.46661747461279457, + ), + ( + ( + 2.509991661702412E8, + 1.3298684552869435E8, + 3.6743804723880893E8, + 5.791092458225288E7, + -1.3123184148036437E8, + ), + 0.0723439870279631, + ), + ( + ( + -2.722300890805201E8, + 2.1601883778132245E7, + -5.56047682304707E8, + 3.554803693060646E8, + 3.1647392358159083E8, + ), + -0.656560662515624, + ), + ( + ( + 5.638216625134594E8, + -2.236907346192737E8, + -5.0562852022285646E8, + -5.436956979127073E7, + -1.129261611506945E8, + ), + 0.03351245780858128, + ), + ( + ( + -1.7909512156895646E8, + 1.0915760091641709E8, + 1.932642099859593E7, + -3.405060533753616E8, + -6.73911758014991E8, + ), + -0.2089142558681482, + ), + ( + ( + -2.2147483413687566E8, + -4.531457195005102E7, + -2.4827386778136212E8, + -2.6640208832089204E8, + -3.354675096522197E8, + ), + 0.38250837565598395, + ), + ( + ( + 3.618095500266467E8, + -1.785261966631494E8, + 8.855575989580283E7, + -1.3702508894700047E8, + -3.564818414428105E8, + ), + 0.00883370523171791, + ), + ( + ( + 3.585592594479808E7, + 1.8822208340571395E8, + -386327.524558296, + -2.613548000006699E8, + 1995562.4304017993, + ), + -0.27653878487738676, + ), + ( + ( + 3.0800276873619422E7, + 1.166750302259058E7, + 8.502636255675305E7, + 4.347409652503064E8, + 1.0678086363325526E8, + ), + -0.13800758751097497, + ), + ( + ( + -2.797805968820768E8, + 9.446376468140173E7, + 2.2821543438325477E8, + -4.8176550369786626E8, + 7.316871126959312E7, + ), + 0.05505478945301634, + ), + ( + ( + -2.236596113898912E7, + 1.5296478602495643E8, + 3.903966235164034E8, + 9.40479475527148E7, + 1.0948229366673347E8, + ), + 0.1158678618158655, + ), + ( + ( + 3.5342596632385695E8, + 3.1584773170834744E8, + -2.1860087172846535E8, + -1.8126626716239208E8, + -2.5263456116162892E7, + ), + -0.354953975313882, + ), + ( + ( + -1.2711958434031656E8, + -4.541988855460623E7, + -1.375878074907788E8, + 6.72693784001799E7, + 6815739.665531283, + ), + -0.23849179316215247, + ), + ( + ( + 1.2660906027019228E8, + -3.3769609799741164E7, + -3.4331505330046E8, + -6.663866659430536E7, + -1.6603843763414428E8, + ), + 0.07974650858448407, + ), + ]; + + for ((x, y, z, y_scale, y_max), sample) in values { + assert_eq!(sampler.sample_no_fade(x, y, z, y_scale, y_max), sample); + } + } +} diff --git a/pumpkin-world/src/world_gen/noise.rs b/pumpkin-world/src/world_gen/noise/simplex.rs similarity index 52% rename from pumpkin-world/src/world_gen/noise.rs rename to pumpkin-world/src/world_gen/noise/simplex.rs index 0f9fc0f33..6c4567007 100644 --- a/pumpkin-world/src/world_gen/noise.rs +++ b/pumpkin-world/src/world_gen/noise/simplex.rs @@ -1,43 +1,7 @@ use num_traits::Pow; use pumpkin_core::random::{legacy_rand::LegacyRand, Random}; -pub fn lerp(delta: f64, start: f64, end: f64) -> f64 { - start + delta * (end - start) -} - -pub fn lerp2(delta_x: f64, delta_y: f64, x0y0: f64, x1y0: f64, x0y1: f64, x1y1: f64) -> f64 { - lerp( - delta_y, - lerp(delta_x, x0y0, x1y0), - lerp(delta_x, x0y1, x1y1), - ) -} - -pub fn lerp3( - delta_x: f64, - delta_y: f64, - delta_z: f64, - x0y0z0: f64, - x1y0z0: f64, - x0y1z0: f64, - x1y1z0: f64, - x0y0z1: f64, - x1y0z1: f64, - x0y1z1: f64, - x1y1z1: f64, -) -> f64 { - lerp( - delta_z, - lerp2(delta_x, delta_y, x0y0z0, x1y0z0, x0y1z0, x1y1z0), - lerp2(delta_x, delta_y, x0y0z1, x1y0z1, x0y1z1, x1y1z1), - ) -} - -struct Gradient { - x: i32, - y: i32, - z: i32, -} +use super::{dot, GRADIENTS}; pub struct SimplexNoiseSampler { permutation: Box<[u8]>, @@ -47,25 +11,6 @@ pub struct SimplexNoiseSampler { } impl SimplexNoiseSampler { - const GRADIENTS: [Gradient; 16] = [ - Gradient { x: 1, y: 1, z: 0 }, - Gradient { x: -1, y: 1, z: 0 }, - Gradient { x: 1, y: -1, z: 0 }, - Gradient { x: -1, y: -1, z: 0 }, - Gradient { x: 1, y: 0, z: 1 }, - Gradient { x: -1, y: 0, z: 1 }, - Gradient { x: 1, y: 0, z: -1 }, - Gradient { x: -1, y: 0, z: -1 }, - Gradient { x: 0, y: 1, z: 1 }, - Gradient { x: 0, y: -1, z: 1 }, - Gradient { x: 0, y: 1, z: -1 }, - Gradient { x: 0, y: -1, z: -1 }, - Gradient { x: 1, y: 1, z: 0 }, - Gradient { x: 0, y: -1, z: 1 }, - Gradient { x: -1, y: 1, z: 0 }, - Gradient { x: 0, y: -1, z: -1 }, - ]; - const SQRT_3: f64 = 1.7320508075688772f64; const SKEW_FACTOR_2D: f64 = 0.5f64 * (Self::SQRT_3 - 1f64); const UNSKEW_FACTOR_2D: f64 = (3f64 - Self::SQRT_3) / 6f64; @@ -99,17 +44,13 @@ impl SimplexNoiseSampler { self.permutation[(input & 0xFF) as usize] as i32 } - fn dot(gradient: &Gradient, x: f64, y: f64, z: f64) -> f64 { - gradient.x as f64 * x + gradient.y as f64 * y + gradient.z as f64 * z - } - fn grad(gradient_index: usize, x: f64, y: f64, z: f64, distance: f64) -> f64 { let d = distance - x * x - y * y - z * z; if d < 0f64 { 0f64 } else { let d = d * d; - d * d * Self::dot(&Self::GRADIENTS[gradient_index], x, y, z) + d * d * dot(&GRADIENTS[gradient_index], x, y, z) } } @@ -229,164 +170,13 @@ impl SimplexNoiseSampler { } } -pub struct PerlinNoiseSampler { - permutation: Box<[u8]>, - x_origin: f64, - y_origin: f64, - z_origin: f64, -} - -impl PerlinNoiseSampler { - pub fn new(random: &mut impl Random) -> Self { - let x_origin = random.next_f64() * 256f64; - let y_origin = random.next_f64() * 256f64; - let z_origin = random.next_f64() * 256f64; - - let mut permutation = [0u8; 256]; - - permutation - .iter_mut() - .enumerate() - .for_each(|(i, x)| *x = i as u8); - - for i in 0..256 { - let j = random.next_bounded_i32((256 - i) as i32) as usize; - permutation.swap(i, i + j); - } - - Self { - permutation: Box::new(permutation), - x_origin, - y_origin, - z_origin, - } - } - - pub fn sample_flat_y(&self, x: f64, y: f64, z: f64) -> f64 { - self.sample_no_fade(x, y, z, 0f64, 0f64) - } - - pub fn sample_no_fade(&self, x: f64, y: f64, z: f64, y_scale: f64, y_max: f64) -> f64 { - let trans_x = x + self.x_origin; - let trans_y = y + self.y_origin; - let trans_z = z + self.z_origin; - - let x_int = trans_x.floor() as i32; - let y_int = trans_y.floor() as i32; - let z_int = trans_z.floor() as i32; - - let x_dec = trans_x - x_int as f64; - let y_dec = trans_y - y_int as f64; - let z_dec = trans_z - z_int as f64; - - let y_noise = if y_scale != 0f64 { - let raw_y_dec = if y_max >= 0f64 && y_max < y_dec { - y_max - } else { - y_dec - }; - (raw_y_dec / y_scale + 1.0E-7f32 as f64).floor() * y_scale - } else { - 0f64 - }; - - self.sample(x_int, y_int, z_int, x_dec, y_dec - y_noise, z_dec, y_dec) - } - - fn grad(hash: i32, x: f64, y: f64, z: f64) -> f64 { - SimplexNoiseSampler::dot( - &SimplexNoiseSampler::GRADIENTS[(hash & 15) as usize], - x, - y, - z, - ) - } - - fn perlin_fade(value: f64) -> f64 { - value * value * value * (value * (value * 6f64 - 15f64) + 10f64) - } - - fn map(&self, input: i32) -> i32 { - (self.permutation[(input & 0xFF) as usize] & 0xFF) as i32 - } - - #[allow(clippy::too_many_arguments)] - fn sample( - &self, - x: i32, - y: i32, - z: i32, - local_x: f64, - local_y: f64, - local_z: f64, - fade_local_y: f64, - ) -> f64 { - let i = self.map(x); - let j = self.map(x.wrapping_add(1)); - let k = self.map(i.wrapping_add(y)); - - let l = self.map(i.wrapping_add(y).wrapping_add(1)); - let m = self.map(j.wrapping_add(y)); - let n = self.map(j.wrapping_add(y).wrapping_add(1)); - - let d = Self::grad(self.map(k.wrapping_add(z)), local_x, local_y, local_z); - let e = Self::grad( - self.map(m.wrapping_add(z)), - local_x - 1f64, - local_y, - local_z, - ); - let f = Self::grad( - self.map(l.wrapping_add(z)), - local_x, - local_y - 1f64, - local_z, - ); - let g = Self::grad( - self.map(n.wrapping_add(z)), - local_x - 1f64, - local_y - 1f64, - local_z, - ); - let h = Self::grad( - self.map(k.wrapping_add(z).wrapping_add(1)), - local_x, - local_y, - local_z - 1f64, - ); - let o = Self::grad( - self.map(m.wrapping_add(z).wrapping_add(1)), - local_x - 1f64, - local_y, - local_z - 1f64, - ); - let p = Self::grad( - self.map(l.wrapping_add(z).wrapping_add(1)), - local_x, - local_y - 1f64, - local_z - 1f64, - ); - let q = Self::grad( - self.map(n.wrapping_add(z).wrapping_add(1)), - local_x - 1f64, - local_y - 1f64, - local_z - 1f64, - ); - let r = Self::perlin_fade(local_x); - let s = Self::perlin_fade(fade_local_y); - let t = Self::perlin_fade(local_z); - - lerp3(r, s, t, d, e, f, g, h, o, p, q) - } -} - -struct OctavePerlinNoiseSampler { +pub struct OctaveSimplexNoiseSampler { octave_samplers: Vec>, persistence: f64, lacunarity: f64, } -impl OctavePerlinNoiseSampler { +impl OctaveSimplexNoiseSampler { pub fn new(random: &mut impl Random, octaves: &[i32]) -> Self { let mut octaves = Vec::from_iter(octaves); octaves.sort(); @@ -459,16 +249,16 @@ impl OctavePerlinNoiseSampler { } #[cfg(test)] -mod octave_perlin_noise_sampler_test { +mod octave_simplex_noise_sampler_test { use pumpkin_core::random::{xoroshiro128::Xoroshiro, Random}; - use crate::world_gen::noise::OctavePerlinNoiseSampler; + use crate::world_gen::noise::simplex::OctaveSimplexNoiseSampler; #[test] fn test_new() { let mut rand = Xoroshiro::from_seed(450); assert_eq!(rand.next_i32(), 1394613419); - let sampler = OctavePerlinNoiseSampler::new(&mut rand, &[-1, 1, 0]); + let sampler = OctaveSimplexNoiseSampler::new(&mut rand, &[-1, 1, 0]); assert_eq!(sampler.lacunarity, 2f64); assert_eq!(sampler.persistence, 0.14285714285714285); @@ -496,7 +286,7 @@ mod octave_perlin_noise_sampler_test { fn test_sample() { let mut rand = Xoroshiro::from_seed(450); assert_eq!(rand.next_i32(), 1394613419); - let sampler = OctavePerlinNoiseSampler::new(&mut rand, &[-1, 1, 0]); + let sampler = OctaveSimplexNoiseSampler::new(&mut rand, &[-1, 1, 0]); let values_1 = [ ( @@ -593,14 +383,13 @@ mod octave_perlin_noise_sampler_test { } } } - #[cfg(test)] mod simplex_noise_sampler_test { use std::ops::Deref; use pumpkin_core::random::{xoroshiro128::Xoroshiro, Random}; - use crate::world_gen::noise::SimplexNoiseSampler; + use crate::world_gen::noise::simplex::SimplexNoiseSampler; #[test] fn test_create() { @@ -911,425 +700,3 @@ mod simplex_noise_sampler_test { } } } - -#[cfg(test)] -mod perlin_noise_sampler_test { - use std::ops::Deref; - - use pumpkin_core::random::{xoroshiro128::Xoroshiro, Random}; - - use crate::world_gen::noise::PerlinNoiseSampler; - - #[test] - fn test_create() { - let mut rand = Xoroshiro::from_seed(111); - assert_eq!(rand.next_i32(), -1467508761); - - let sampler = PerlinNoiseSampler::new(&mut rand); - assert_eq!(sampler.x_origin, 48.58072036717974); - assert_eq!(sampler.y_origin, 110.73235882678037); - assert_eq!(sampler.z_origin, 65.26438852860176); - - let permutation: [u8; 256] = [ - 159, 113, 41, 143, 203, 123, 95, 177, 25, 79, 229, 219, 194, 60, 130, 14, 83, 99, 24, - 202, 207, 232, 167, 152, 220, 201, 29, 235, 87, 147, 74, 160, 155, 97, 111, 31, 85, - 205, 115, 50, 13, 171, 77, 237, 149, 116, 209, 174, 169, 109, 221, 9, 166, 84, 54, 216, - 121, 106, 211, 16, 69, 244, 65, 192, 183, 146, 124, 37, 56, 45, 193, 158, 126, 217, 36, - 255, 162, 163, 230, 103, 63, 90, 191, 214, 20, 138, 32, 39, 238, 67, 64, 105, 250, 140, - 148, 114, 68, 75, 200, 161, 239, 125, 227, 199, 101, 61, 175, 107, 129, 240, 170, 51, - 139, 86, 186, 145, 212, 178, 30, 251, 89, 226, 120, 153, 47, 141, 233, 2, 179, 236, 1, - 19, 98, 21, 164, 108, 11, 23, 91, 204, 119, 88, 165, 195, 168, 26, 48, 206, 128, 6, 52, - 118, 110, 180, 197, 231, 117, 7, 3, 135, 224, 58, 82, 78, 4, 59, 222, 18, 72, 57, 150, - 43, 246, 100, 122, 112, 53, 133, 93, 17, 27, 210, 142, 234, 245, 80, 22, 46, 185, 172, - 71, 248, 33, 173, 76, 35, 40, 92, 228, 127, 254, 70, 42, 208, 73, 104, 187, 62, 154, - 243, 189, 241, 34, 66, 249, 94, 8, 12, 134, 132, 102, 242, 196, 218, 181, 28, 38, 15, - 151, 157, 247, 223, 198, 55, 188, 96, 0, 182, 49, 190, 156, 10, 215, 252, 131, 137, - 184, 176, 136, 81, 44, 213, 253, 144, 225, 5, - ]; - assert_eq!(sampler.permutation.deref(), permutation); - } - - #[test] - fn test_no_y() { - let mut rand = Xoroshiro::from_seed(111); - assert_eq!(rand.next_i32(), -1467508761); - let sampler = PerlinNoiseSampler::new(&mut rand); - - let values = [ - ( - ( - -3.134738528791615E8, - 5.676610095659718E7, - 2.011711832498507E8, - ), - 0.38582139614602945, - ), - ( - (-1369026.560586418, 3.957311252810864E8, 6.797037355570006E8), - 0.15777501333157193, - ), - ( - ( - 6.439373693833767E8, - -3.36218773041759E8, - -3.265494249695775E8, - ), - -0.2806135912409497, - ), - ( - ( - 1.353820060118252E8, - -3.204701624793043E8, - -4.612474746056331E8, - ), - -0.15052865500837787, - ), - ( - ( - -6906850.625560562, - 1.0153663948838013E8, - 2.4923185478305575E8, - ), - -0.3079300694558318, - ), - ( - ( - -7.108376621385525E7, - -2.029413580824217E8, - 2.5164602748045415E8, - ), - 0.03051312670440398, - ), - ( - ( - 1.0591429119126628E8, - -4.7911044364543396E8, - -2918719.2277242197, - ), - -0.11775123159138573, - ), - ( - ( - 4.04615501401398E7, - -3.074409286586152E8, - 5.089118769334092E7, - ), - 0.08763639340713025, - ), - ( - ( - -4.8645283544246924E8, - -3.922570151180015E8, - 2.3741632952563038E8, - ), - 0.08857245482456311, - ), - ( - ( - 2.861710031285905E8, - -1.8973201372718483E8, - -3.2653143323982143E8, - ), - -0.2378339698793312, - ), - ( - ( - 2.885407603819252E8, - -3.358708100884505E7, - -1.4480399660676318E8, - ), - -0.46661747461279457, - ), - ( - ( - 3.6548491156354237E8, - 7.995429702025633E7, - 2.509991661702412E8, - ), - 0.1671543972176835, - ), - ( - ( - 1.3298684552869435E8, - 3.6743804723880893E8, - 5.791092458225288E7, - ), - -0.2704070746642889, - ), - ( - ( - -1.3123184148036437E8, - -2.722300890805201E8, - 2.1601883778132245E7, - ), - 0.05049887915906969, - ), - ( - ( - -5.56047682304707E8, - 3.554803693060646E8, - 3.1647392358159083E8, - ), - -0.21178547899422662, - ), - ( - ( - 5.638216625134594E8, - -2.236907346192737E8, - -5.0562852022285646E8, - ), - 0.03351245780858128, - ), - ( - ( - -5.436956979127073E7, - -1.129261611506945E8, - -1.7909512156895646E8, - ), - 0.31670010349494726, - ), - ( - ( - 1.0915760091641709E8, - 1.932642099859593E7, - -3.405060533753616E8, - ), - -0.13987439655026918, - ), - ( - ( - -6.73911758014991E8, - -2.2147483413687566E8, - -4.531457195005102E7, - ), - 0.07824440437151846, - ), - ( - ( - -2.4827386778136212E8, - -2.6640208832089204E8, - -3.354675096522197E8, - ), - -0.2989735599541437, - ), - ]; - - for ((x, y, z), sample) in values { - assert_eq!(sampler.sample_flat_y(x, y, z), sample); - } - } - - #[test] - fn test_no_fade() { - let mut rand = Xoroshiro::from_seed(111); - assert_eq!(rand.next_i32(), -1467508761); - let sampler = PerlinNoiseSampler::new(&mut rand); - - let values = [ - ( - ( - -3.134738528791615E8, - 5.676610095659718E7, - 2.011711832498507E8, - -1369026.560586418, - 3.957311252810864E8, - ), - 23234.47859421248, - ), - ( - ( - 6.797037355570006E8, - 6.439373693833767E8, - -3.36218773041759E8, - -3.265494249695775E8, - 1.353820060118252E8, - ), - -0.016403984198221984, - ), - ( - ( - -3.204701624793043E8, - -4.612474746056331E8, - -6906850.625560562, - 1.0153663948838013E8, - 2.4923185478305575E8, - ), - 0.3444286491766397, - ), - ( - ( - -7.108376621385525E7, - -2.029413580824217E8, - 2.5164602748045415E8, - 1.0591429119126628E8, - -4.7911044364543396E8, - ), - 0.03051312670440398, - ), - ( - ( - -2918719.2277242197, - 4.04615501401398E7, - -3.074409286586152E8, - 5.089118769334092E7, - -4.8645283544246924E8, - ), - 0.3434020232968479, - ), - ( - ( - -3.922570151180015E8, - 2.3741632952563038E8, - 2.861710031285905E8, - -1.8973201372718483E8, - -3.2653143323982143E8, - ), - -0.07935517045771859, - ), - ( - ( - 2.885407603819252E8, - -3.358708100884505E7, - -1.4480399660676318E8, - 3.6548491156354237E8, - 7.995429702025633E7, - ), - -0.46661747461279457, - ), - ( - ( - 2.509991661702412E8, - 1.3298684552869435E8, - 3.6743804723880893E8, - 5.791092458225288E7, - -1.3123184148036437E8, - ), - 0.0723439870279631, - ), - ( - ( - -2.722300890805201E8, - 2.1601883778132245E7, - -5.56047682304707E8, - 3.554803693060646E8, - 3.1647392358159083E8, - ), - -0.656560662515624, - ), - ( - ( - 5.638216625134594E8, - -2.236907346192737E8, - -5.0562852022285646E8, - -5.436956979127073E7, - -1.129261611506945E8, - ), - 0.03351245780858128, - ), - ( - ( - -1.7909512156895646E8, - 1.0915760091641709E8, - 1.932642099859593E7, - -3.405060533753616E8, - -6.73911758014991E8, - ), - -0.2089142558681482, - ), - ( - ( - -2.2147483413687566E8, - -4.531457195005102E7, - -2.4827386778136212E8, - -2.6640208832089204E8, - -3.354675096522197E8, - ), - 0.38250837565598395, - ), - ( - ( - 3.618095500266467E8, - -1.785261966631494E8, - 8.855575989580283E7, - -1.3702508894700047E8, - -3.564818414428105E8, - ), - 0.00883370523171791, - ), - ( - ( - 3.585592594479808E7, - 1.8822208340571395E8, - -386327.524558296, - -2.613548000006699E8, - 1995562.4304017993, - ), - -0.27653878487738676, - ), - ( - ( - 3.0800276873619422E7, - 1.166750302259058E7, - 8.502636255675305E7, - 4.347409652503064E8, - 1.0678086363325526E8, - ), - -0.13800758751097497, - ), - ( - ( - -2.797805968820768E8, - 9.446376468140173E7, - 2.2821543438325477E8, - -4.8176550369786626E8, - 7.316871126959312E7, - ), - 0.05505478945301634, - ), - ( - ( - -2.236596113898912E7, - 1.5296478602495643E8, - 3.903966235164034E8, - 9.40479475527148E7, - 1.0948229366673347E8, - ), - 0.1158678618158655, - ), - ( - ( - 3.5342596632385695E8, - 3.1584773170834744E8, - -2.1860087172846535E8, - -1.8126626716239208E8, - -2.5263456116162892E7, - ), - -0.354953975313882, - ), - ( - ( - -1.2711958434031656E8, - -4.541988855460623E7, - -1.375878074907788E8, - 6.72693784001799E7, - 6815739.665531283, - ), - -0.23849179316215247, - ), - ( - ( - 1.2660906027019228E8, - -3.3769609799741164E7, - -3.4331505330046E8, - -6.663866659430536E7, - -1.6603843763414428E8, - ), - 0.07974650858448407, - ), - ]; - - for ((x, y, z, y_scale, y_max), sample) in values { - assert_eq!(sampler.sample_no_fade(x, y, z, y_scale, y_max), sample); - } - } -}