1use std::mem;
11use std::fmt;
12
13use glam::{DVec3, DVec2, IVec3};
14
15use crate::rand::JavaRandom;
16
17
18#[repr(transparent)]
20#[derive(Clone, PartialEq)]
21pub struct NoiseCube<const X: usize, const Y: usize, const Z: usize> {
22 inner: [[[f64; Y]; Z]; X],
23}
24
25impl<const X: usize, const Y: usize, const Z: usize> NoiseCube<X, Y, Z> {
26
27 #[inline]
28 pub fn new() -> Self {
29 Self {
30 inner: [[[0.0; Y]; Z]; X],
31 }
32 }
33
34 #[inline]
35 pub fn fill(&mut self, value: f64) {
36 self.inner = [[[value; Y]; Z]; X];
37 }
38
39 #[inline]
40 pub fn get(&self, x: usize, y: usize, z: usize) -> f64 {
41 self.inner[x][z][y]
42 }
43
44 #[inline]
45 pub fn set(&mut self, x: usize, y: usize, z: usize, value: f64) {
46 self.inner[x][z][y] = value;
47 }
48
49 #[inline]
50 pub fn add(&mut self, x: usize, y: usize, z: usize, value: f64) {
51 self.inner[x][z][y] += value;
52 }
53
54}
55
56impl<const X: usize, const Y: usize, const Z: usize> Default for NoiseCube<X, Y, Z> {
57 #[inline]
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63impl<const X: usize, const Y: usize, const Z: usize> fmt::Debug for NoiseCube<X, Y, Z> {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 f.debug_tuple("NoiseCube").field(&self.inner).finish()
66 }
67}
68
69
70impl NoiseCube<1, 1, 1> {
71
72 #[inline(always)]
74 pub fn from_ref(value: &f64) -> &Self {
75 const __ASSERT: () = assert!(mem::size_of::<NoiseCube<1, 1, 1>>() == mem::size_of::<f64>());
77 unsafe { &*(value as *const f64 as *const Self) }
82 }
83
84 #[inline(always)]
87 pub fn from_mut(value: &mut f64) -> &mut Self {
88 unsafe { &mut *(value as *mut f64 as *mut Self) }
90 }
91
92}
93
94
95#[derive(Debug, Clone)]
97pub struct PerlinNoise {
98 offset: DVec3,
100 permutations: Box<[u16; 512]>,
102}
103
104impl PerlinNoise {
105
106 pub fn new(rand: &mut JavaRandom) -> Self {
108
109 let offset = rand.next_double_vec() * 256.0;
113
114 let mut permutations = Box::new(std::array::from_fn::<u16, 512, _>(|i| {
115 if i <= 256 {
116 i as u16
117 } else {
118 0
119 }
120 }));
121
122 for index in 0usize..256 {
123 let permutation_index = rand.next_int_bounded(256 - index as i32) as usize + index;
124 permutations.swap(index, permutation_index);
125 permutations[index + 256] = permutations[index];
126 }
127
128 Self {
129 offset,
130 permutations,
131 }
132
133 }
134
135 pub fn gen_3d_point(&self, pos: DVec3) -> f64 {
137
138 let mut pos = pos + self.offset;
139 let pos_floor = pos.floor();
140 pos -= pos_floor;
141 let factor = pos * pos * pos * (pos * (pos * 6.0 - 15.0) + 10.0);
142
143 let pos_int = pos_floor.as_ivec3();
144 let x_index = (pos_int.x & 255) as usize;
145 let y_index = (pos_int.y & 255) as usize;
146 let z_index = (pos_int.z & 255) as usize;
147
148 let a = self.permutations[x_index] as usize + y_index;
149 let a0 = self.permutations[a] as usize + z_index;
150 let a1 = self.permutations[a + 1] as usize + z_index;
151 let b = self.permutations[x_index + 1] as usize + y_index;
152 let b0 = self.permutations[b] as usize + z_index;
153 let b1 = self.permutations[b + 1] as usize + z_index;
154
155 let DVec3 { x, y, z } = pos;
156
157 lerp(factor.z,
158 lerp(factor.y,
159 lerp(factor.x,
160 grad3(self.permutations[a0], x , y, z),
161 grad3(self.permutations[b0], x - 1.0, y, z)),
162 lerp(factor.x,
163 grad3(self.permutations[a1], x , y - 1.0, z),
164 grad3(self.permutations[b1], x - 1.0, y - 1.0, z))),
165 lerp(factor.y,
166 lerp(factor.x,
167 grad3(self.permutations[a0 + 1], x , y, z - 1.0),
168 grad3(self.permutations[b0 + 1], x - 1.0, y, z - 1.0)),
169 lerp(factor.x,
170 grad3(self.permutations[a1 + 1], x , y - 1.0, z - 1.0),
171 grad3(self.permutations[b1 + 1], x - 1.0, y - 1.0, z - 1.0))))
172
173 }
174
175 pub fn gen_2d_point(&self, pos: DVec2) -> f64 {
177 self.gen_3d_point(pos.extend(0.0))
178 }
179
180 pub fn gen_3d<const X: usize, const Y: usize, const Z: usize>(&self,
182 cube: &mut NoiseCube<X, Y, Z>,
183 offset: DVec3,
184 scale: DVec3,
185 amplitude: f64
186 ) {
187
188 let mut last_y_index = usize::MAX;
189
190 let mut x0 = 0.0;
191 let mut x1 = 0.0;
192 let mut x2 = 0.0;
193 let mut x3 = 0.0;
194
195 for x_cube in 0..X {
196 let (x, x_factor, x_index) = calc_pos((offset.x + x_cube as f64) * scale.x + self.offset.x);
197 for z_cube in 0..Z {
198 let (z, z_factor, z_index) = calc_pos((offset.z + z_cube as f64) * scale.z + self.offset.z);
199 for y_cube in 0..Y {
200 let (y, y_factor, y_index) = calc_pos((offset.y + y_cube as f64) * scale.y + self.offset.y);
201
202 if y_cube == 0 || y_index != last_y_index {
203
204 last_y_index = y_index;
205
206 let a = self.permutations[x_index] as usize + y_index;
207 let a0 = self.permutations[a] as usize + z_index;
208 let a1 = self.permutations[a + 1] as usize + z_index;
209 let b = self.permutations[x_index + 1] as usize + y_index;
210 let b0 = self.permutations[b] as usize + z_index;
211 let b1 = self.permutations[b + 1] as usize + z_index;
212
213 x0 = lerp(x_factor,
214 grad3(self.permutations[a0], x , y, z),
215 grad3(self.permutations[b0], x - 1.0, y, z));
216 x1 = lerp(x_factor,
217 grad3(self.permutations[a1], x , y - 1.0, z),
218 grad3(self.permutations[b1], x - 1.0, y - 1.0, z));
219 x2 = lerp(x_factor,
220 grad3(self.permutations[a0 + 1], x , y, z - 1.0),
221 grad3(self.permutations[b0 + 1], x - 1.0, y, z - 1.0));
222 x3 = lerp(x_factor,
223 grad3(self.permutations[a1 + 1], x , y - 1.0, z - 1.0),
224 grad3(self.permutations[b1 + 1], x - 1.0, y - 1.0, z - 1.0));
225
226 }
227
228 let noise = lerp(z_factor, lerp(y_factor, x0, x1), lerp(y_factor, x2, x3));
229 cube.add(x_cube, y_cube, z_cube, noise * amplitude);
230
231 }
232 }
233 }
234
235 }
236
237 pub fn gen_2d<const X: usize, const Z: usize>(&self,
239 cube: &mut NoiseCube<X, 1, Z>,
240 offset: DVec2,
241 scale: DVec2,
242 amplitude: f64
243 ) {
244
245 for x_cube in 0..X {
246 let (x, x_factor, x_index) = calc_pos((offset.x + x_cube as f64) * scale.x + self.offset.x);
247 for z_cube in 0..Z {
248 let (z, z_factor, z_index) = calc_pos((offset.y + z_cube as f64) * scale.y + self.offset.z);
249
250 let a = self.permutations[x_index] as usize + 0;
251 let a0 = self.permutations[a] as usize + z_index;
252 let b = self.permutations[x_index + 1] as usize + 0;
253 let b0 = self.permutations[b] as usize + z_index;
254
255 let noise = lerp(z_factor,
256 lerp(x_factor,
257 grad2(self.permutations[a0], x, z),
258 grad3(self.permutations[b0], x - 1.0, 0.0, z)),
259 lerp(x_factor,
260 grad3(self.permutations[a0 + 1], x, 0.0, z - 1.0),
261 grad3(self.permutations[b0 + 1], x - 1.0, 0.0, z - 1.0)));
262
263 cube.add(x_cube, 0, z_cube, noise * amplitude);
264
265 }
266 }
267
268 }
269
270 pub fn gen_weird_2d<const X: usize, const Z: usize>(&self,
276 cube: &mut NoiseCube<X, 1, Z>,
277 offset: DVec2,
278 scale: DVec2,
279 amplitude: f64
280 ) {
281
282 let const_a: f64 = 0.5 * (f64::sqrt(3.0) - 1.0);
283 let const_b: f64 = (3.0 - f64::sqrt(3.0)) / 6.0;
284
285 for x_noise in 0..X {
286 let x = (offset.x + x_noise as f64) * scale.x + self.offset.x;
287 for z_noise in 0..Z {
288 let z = (offset.y + z_noise as f64) * scale.y + self.offset.y;
290
291 let a = (x + z) * const_a;
292 let x_wrap = wrap(x + a);
293 let z_wrap = wrap(z + a);
294
295 let b = i32::wrapping_add(x_wrap, z_wrap) as f64 * const_b;
296 let x_wrap_b = x_wrap as f64 - b;
297 let z_wrap_b = z_wrap as f64 - b;
298
299 let x_delta = x - x_wrap_b;
300 let z_delta = z - z_wrap_b;
301
302 let (
303 x_offset,
304 z_offset
305 ) = if x_delta > z_delta { (1, 0) } else { (0, 1) };
306
307 let x_delta0 = x_delta - x_offset as f64 + const_b;
308 let z_delta0 = z_delta - z_offset as f64 + const_b;
309 let x_delta1 = x_delta - 1.0 + 2.0 * const_b;
310 let z_delta1 = z_delta - 1.0 + 2.0 * const_b;
311
312 let x_index = (x_wrap & 255) as usize;
313 let z_index = (z_wrap & 255) as usize;
314
315 let v0_index = self.permutations[x_index + self.permutations[z_index] as usize] % 12;
316 let v1_index = self.permutations[x_index + x_offset + self.permutations[z_index + z_offset] as usize] % 12;
317 let v2_index = self.permutations[x_index + 1 + self.permutations[z_index + 1] as usize] % 12;
318
319 let v0 = calc_weird_noise(x_delta, z_delta, v0_index as usize);
320 let v1 = calc_weird_noise(x_delta0, z_delta0, v1_index as usize);
321 let v2 = calc_weird_noise(x_delta1, z_delta1, v2_index as usize);
322
323 cube.add(x_noise, 0, z_noise, 70.0 * (v0 + v1 + v2) * amplitude);
324
325 }
326 }
327
328 }
329
330}
331
332
333#[derive(Debug, Clone)]
335pub struct PerlinOctaveNoise {
336 generators: Box<[PerlinNoise]>
338}
339
340impl PerlinOctaveNoise {
341
342 pub fn new(rand: &mut JavaRandom, octaves: usize) -> Self {
344 Self {
345 generators: (0..octaves)
346 .map(move |_| PerlinNoise::new(rand))
347 .collect::<Vec<_>>()
348 .into_boxed_slice(),
349 }
350 }
351
352 pub fn gen_3d_point(&self, pos: DVec3) -> f64 {
354 let mut ret = 0.0;
355 let mut freq = 1.0;
356 for gen in &self.generators[..] {
357 ret += gen.gen_3d_point(pos * freq) / freq;
358 freq /= 2.0;
359 }
360 ret
361 }
362
363 pub fn gen_2d_point(&self, pos: DVec2) -> f64 {
365 let mut ret = 0.0;
366 let mut freq = 1.0;
367 for gen in &self.generators[..] {
368 ret += gen.gen_2d_point(pos * freq) / freq;
369 freq /= 2.0;
370 }
371 ret
372 }
373
374 pub fn gen_3d<const X: usize, const Y: usize, const Z: usize>(&self,
376 cube: &mut NoiseCube<X, Y, Z>,
377 offset: DVec3,
378 scale: DVec3
379 ) {
380 cube.fill(0.0);
381 let mut freq = 1.0;
382 for gen in &self.generators[..] {
383 gen.gen_3d(cube, offset, scale * freq, 1.0 / freq);
384 freq /= 2.0;
385 }
386 }
387
388 pub fn gen_2d<const X: usize, const Z: usize>(&self,
390 cube: &mut NoiseCube<X, 1, Z>,
391 offset: DVec2,
392 scale: DVec2,
393 ) {
394 cube.fill(0.0);
395 let mut freq = 1.0;
396 for gen in &self.generators[..] {
397 gen.gen_2d(cube, offset, scale * freq, 1.0 / freq);
398 freq /= 2.0;
399 }
400 }
401
402 pub fn gen_weird_2d<const X: usize, const Z: usize>(&self,
408 cube: &mut NoiseCube<X, 1, Z>,
409 offset: DVec2,
410 scale: DVec2,
411 freq_factor: f64,
412 ) {
413 cube.fill(0.0);
414 let scale = scale / 1.5;
415 let mut freq = 1.0;
416 let mut amplitude = 0.55;
417 for gen in &self.generators[..] {
418 gen.gen_weird_2d(cube, offset, scale * freq, amplitude);
419 freq *= freq_factor;
420 amplitude *= 2.0;
421 }
422 }
423
424}
425
426
427#[inline]
428fn lerp(factor: f64, from: f64, to: f64) -> f64 {
429 from + factor * (to - from)
430}
431
432#[inline]
433fn grad3(value: u16, x: f64, y: f64, z: f64) -> f64 {
434 let value = value & 15;
435 let a = if value < 8 { x } else { y };
436 let b = if value < 4 { y } else if value != 12 && value != 14 { z } else { x };
437 (if value & 1 == 0 { a } else { -a }) + (if value & 2 == 0 { b } else { -b })
438}
439
440#[inline]
441fn grad2(value: u16, x: f64, z: f64) -> f64 {
442 let value = value & 15;
443 let a = (1 - ((value & 8) >> 3)) as f64 * x;
444 let b = if value < 4 { 0.0 } else if value != 12 && value != 14 { z } else { x };
445 (if value & 1 == 0 { a } else { -a }) + (if value & 2 == 0 { b } else { -b })
446}
447
448#[inline]
449fn calc_pos(mut pos: f64) -> (f64, f64, usize) {
450
451 let mut floor = pos as i32;
457 if pos < floor as f64 {
458 floor = floor.wrapping_sub(1);
459 }
460
461 pos -= floor as f64;
462 let factor = pos * pos * pos * (pos * (pos * 6.0 - 15.0) + 10.0);
463 let index = (floor & 255) as usize;
464
465 (pos, factor, index)
466
467}
468
469#[inline]
470fn wrap(value: f64) -> i32 {
471 let ret = value as i32;
472 if value > 0.0 { ret } else { ret.wrapping_sub(1) }
473}
474
475#[inline]
476fn calc_weird_noise(x_delta: f64, z_delta: f64, index: usize) -> f64 {
477
478 static WEIRD_TABLE: [IVec3; 12] = [
479 IVec3::new(1, 1, 0),
480 IVec3::new(-1, 1, 0),
481 IVec3::new(1, -1, 0),
482 IVec3::new(-1, -1, 0),
483 IVec3::new(1, 0, 1),
484 IVec3::new(-1, 0, 1),
485 IVec3::new(1, 0, -1),
486 IVec3::new(-1, 0, -1),
487 IVec3::new(0, 1, 1),
488 IVec3::new(0, -1, 1),
489 IVec3::new(0, 1, -1),
490 IVec3::new(0, -1, -1),
491 ];
492
493 let tmp = 0.5 - x_delta * x_delta - z_delta * z_delta;
494 if tmp < 0.0 {
495 0.0
496 } else {
497 let tmp = tmp * tmp;
498 let weird = WEIRD_TABLE[index];
499 tmp * tmp * (weird.x as f64 * x_delta + weird.y as f64 * z_delta)
500 }
501
502}