1#![allow(arithmetic_overflow)]
2
3mod lookup;
4
5fn fast_min(a: f32, b: f32) -> f32 {
6 return if a < b { a } else { b };
7}
8
9fn fast_max(a: f32, b: f32) -> f32 {
10 return if a > b { a } else { b };
11}
12
13fn fast_abs(f: f32) -> f32 {
14 return if f < 0.0 { -f } else { f };
15}
16
17fn fast_sqrt(f: f32) -> f32 {
18 return f.sqrt();
19}
20
21fn fast_floor(f: f32) -> i32 {
22 return if f >= 0.0 { f as i32 } else { f as i32 - 1 };
23}
24
25fn fast_round(f: f32) -> i32 {
26 return if f >= 0.0 {
27 (f + 0.5) as i32
28 } else {
29 (f - 0.5) as i32
30 };
31}
32
33fn lerp(a: f32, b: f32, t: f32) -> f32 {
34 return a + t * (b - a);
35}
36
37fn interp_hermite(t: f32) -> f32 {
38 return t * t * (3.0 - 2.0 * t);
39}
40
41fn interp_quintic(t: f32) -> f32 {
42 return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
43}
44
45fn cubic_lerp(a: f32, b: f32, c: f32, d: f32, t: f32) -> f32 {
46 let p = (d - c) - (a - b);
47 return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b;
48}
49
50fn ping_pong(mut t: f32) -> f32 {
51 t -= ((t * 0.5) as i32 * 2) as f32;
52 return if t < 1.0 { t } else { 2.0 - t };
53}
54
55pub enum NoiseType {
56 OpenSimplex2,
57 OpenSimplex2S,
58 Cellular,
59 Perlin,
60 ValueCubic,
61 Value,
62}
63
64pub enum RotationType3D {
65 None,
66 ImproveXYPlanes,
67 ImproveXZPlanes,
68}
69
70pub enum FractalType {
71 None,
72 FBm,
73 Ridged,
74 PingPong,
75 DomainWarpProgressive,
76 DomainWarpIndependent,
77}
78
79#[derive(PartialEq)]
80pub enum CellularDistanceFunction {
81 Euclidean,
82 EuclideanSq,
83 Manhattan,
84 Hybrid,
85}
86
87#[derive(PartialEq, PartialOrd)]
88pub enum CellularReturnType {
89 CellValue,
90 Distance,
91 Distance2,
92 Distance2Add,
93 Distance2Sub,
94 Distance2Mul,
95 Distance2Div,
96}
97
98pub enum DomainWarpType {
99 OpenSimplex2,
100 OpenSimplex2Reduced,
101 BasicGrid,
102}
103
104pub enum TransformType3D {
105 None,
106 ImproveXYPlanes,
107 ImproveXZPlanes,
108 DefaultOpenSimplex2,
109}
110
111pub struct FastNoiseLite {
112 seed: i32,
113 frequency: f32,
114 noise_type: NoiseType,
115 rotation_type3d: RotationType3D,
116 transform_type3d: TransformType3D,
117
118 fractal_type: FractalType,
119 octaves: usize,
120 lacunarity: f32,
121 gain: f32,
122 weighted_strength: f32,
123 ping_pong_strength: f32,
124
125 fractal_bounding: f32,
126
127 cellular_distance_function: CellularDistanceFunction,
128 cellular_return_type: CellularReturnType,
129 cellular_jitter_modifier: f32,
130
131 domain_warp_type: DomainWarpType,
132 warp_transform_type3d: TransformType3D,
133 domain_warp_amp: f32,
134}
135
136impl FastNoiseLite {
137 pub fn new(seed: i32) -> Self {
138 Self {
139 seed,
140 frequency: 0.01,
141 noise_type: NoiseType::OpenSimplex2,
142 rotation_type3d: RotationType3D::None,
143 transform_type3d: TransformType3D::DefaultOpenSimplex2,
144 fractal_type: FractalType::None,
145 octaves: 3,
146 lacunarity: 2.0,
147 gain: 0.5,
148 weighted_strength: 0.0,
149 ping_pong_strength: 2.0,
150 fractal_bounding: 1.0 / 1.75,
151 cellular_distance_function: CellularDistanceFunction::EuclideanSq,
152 cellular_return_type: CellularReturnType::Distance,
153 cellular_jitter_modifier: 1.0,
154 domain_warp_type: DomainWarpType::OpenSimplex2,
155 warp_transform_type3d: TransformType3D::DefaultOpenSimplex2,
156 domain_warp_amp: 1.0,
157 }
158 }
159 pub fn set_seed(&mut self, seed: i32) {
160 self.seed = seed;
161 }
162 pub fn set_frequency(&mut self, frequency: f32) {
163 self.frequency = frequency;
164 }
165 pub fn set_noise_type(&mut self, noise_type: NoiseType) {
166 self.noise_type = noise_type;
167 self.update_transform_type_3d();
168 }
169 pub fn set_rotation_type_3d(&mut self, rotation_type3d: RotationType3D) {
170 self.rotation_type3d = rotation_type3d;
171 self.update_transform_type_3d();
172 self.update_warp_transform_type_3d();
173 }
174 pub fn set_fractal_type(&mut self, fractal_type: FractalType) {
175 self.fractal_type = fractal_type;
176 }
177 pub fn set_fractal_octaves(&mut self, octaves: usize) {
178 self.octaves = octaves;
179 self.calculate_fractal_bounding();
180 }
181 pub fn set_fractal_lacunarity(&mut self, lacunarity: f32) {
182 self.lacunarity = lacunarity;
183 }
184 pub fn set_fractal_gain(&mut self, gain: f32) {
185 self.gain = gain;
186 self.calculate_fractal_bounding();
187 }
188
189 pub fn set_fractal_weighted_strength(&mut self, weighted_strength: f32) {
190 self.weighted_strength = weighted_strength;
191 }
192
193 pub fn set_fractal_ping_pong_strength(&mut self, ping_pong_strength: f32) {
194 self.ping_pong_strength = ping_pong_strength;
195 }
196
197 pub fn set_cellular_distance_function(
198 &mut self,
199 cellular_distance_function: CellularDistanceFunction,
200 ) {
201 self.cellular_distance_function = cellular_distance_function;
202 }
203
204 pub fn set_cellular_return_type(&mut self, cellular_return_type: CellularReturnType) {
205 self.cellular_return_type = cellular_return_type;
206 }
207
208 pub fn set_cellular_jitter(&mut self, cellular_jitter: f32) {
209 self.cellular_jitter_modifier = cellular_jitter;
210 }
211
212 pub fn set_domain_warp_type(&mut self, domain_warp_type: DomainWarpType) {
213 self.domain_warp_type = domain_warp_type;
214 self.update_warp_transform_type_3d();
215 }
216
217 pub fn set_domain_warp_amp(&mut self, domain_warp_amp: f32) {
218 self.domain_warp_amp = domain_warp_amp;
219 }
220
221 pub fn get_noise_2d(&self, mut x: f32, mut y: f32) -> f32 {
222 self.transform_noise_coordinate_2d(&mut x, &mut y);
223
224 match self.fractal_type {
225 FractalType::FBm => self.gen_fractal_fbm_2d(x, y),
226 FractalType::Ridged => self.gen_fractal_ridged_2d(x, y),
227 FractalType::PingPong => self.gen_fractal_ping_pong_2d(x, y),
228 _ => self.gen_noise_single_2d(self.seed, x, y),
229 }
230 }
231
232 pub fn get_noise_3d(&self, mut x: f32, mut y: f32, mut z: f32) -> f32 {
233 self.transform_noise_coordinate_3d(&mut x, &mut y, &mut z);
234 match self.fractal_type {
235 FractalType::FBm => self.gen_fractal_fbm_3d(x, y, z),
236 FractalType::Ridged => self.gen_fractal_ridged_3d(x, y, z),
237 FractalType::PingPong => self.gen_fractal_ping_pong_3d(x, y, z),
238 _ => self.gen_noise_single_3d(self.seed, x, y, z),
239 }
240 }
241
242 pub fn domain_warp_2d(&self, x: &mut f32, y: &mut f32) {
243 match self.fractal_type {
244 FractalType::DomainWarpProgressive => self.domain_warp_fractal_progressive_2d(x, y),
245 FractalType::DomainWarpIndependent => self.domain_warp_fractal_independent_2d(x, y),
246 _ => self.domain_warp_single_2d(x, y),
247 }
248 }
249 pub fn domain_warp_3d(&self, x: &mut f32, y: &mut f32, z: &mut f32) {
250 match self.fractal_type {
251 FractalType::DomainWarpIndependent => self.domain_warp_fractal_independent_3d(x, y, z),
252 FractalType::DomainWarpProgressive => self.domain_warp_fractal_progressive_3d(x, y, z),
253 _ => self.domain_warp_single_3d(x, y, z),
254 }
255 }
256 fn calculate_fractal_bounding(&mut self) {
257 let gain = fast_abs(self.gain);
258 let mut amp = gain;
259 let mut amp_fractal = 1.0;
260 for _ in 0..self.octaves {
261 amp_fractal += amp;
262 amp *= gain;
263 }
264 self.fractal_bounding = 1.0 / amp_fractal;
265 }
266 const PRIME_X: i32 = 501125321;
267 const PRIME_Y: i32 = 1136930381;
268 const PRIME_Z: i32 = 1720413743;
269
270 fn hash_2d(seed: i32, x_primed: i32, y_primed: i32) -> i32 {
271 let mut hash = seed ^ x_primed ^ y_primed;
272 hash = hash.wrapping_mul(0x27d4eb2d);
273 return hash;
274 }
275
276 fn hash_3d(seed: i32, x_primed: i32, y_primed: i32, z_primed: i32) -> i32 {
277 let mut hash = seed ^ x_primed ^ y_primed ^ z_primed;
278 hash = hash.wrapping_mul(0x27d4eb2d);
279 return hash;
280 }
281
282 fn val_coord_2d(seed: i32, x_primed: i32, y_primed: i32) -> f32 {
283 let mut hash: i32 = Self::hash_2d(seed, x_primed, y_primed);
284
285 hash *= hash;
286 hash ^= hash << 19;
287 return hash as f32 * (1.0 / 2147483648.0);
288 }
289
290 fn val_coord_3d(seed: i32, x_primed: i32, y_primed: i32, z_primed: i32) -> f32 {
291 let mut hash: i32 = Self::hash_3d(seed, x_primed, y_primed, z_primed);
292
293 hash *= hash;
294 hash ^= hash << 19;
295 return hash as f32 * (1.0 / 2147483648.0);
296 }
297
298 fn grad_coord_2d(seed: i32, x_primed: i32, y_primed: i32, xd: f32, yd: f32) -> f32 {
299 let mut hash = Self::hash_2d(seed, x_primed, y_primed);
300 hash ^= hash >> 15;
301 hash &= 127 << 1;
302
303 let xg = lookup::GRADIENTS_2D[hash as usize];
304 let yg = lookup::GRADIENTS_2D[(hash | 1) as usize];
305
306 return xd * xg + yd * yg;
307 }
308
309 fn grad_coord_3d(
310 seed: i32,
311 x_primed: i32,
312 y_primed: i32,
313 z_primed: i32,
314 xd: f32,
315 yd: f32,
316 zd: f32,
317 ) -> f32 {
318 let mut hash: i32 = Self::hash_3d(seed, x_primed, y_primed, z_primed);
319 hash ^= hash >> 15;
320 hash &= 63 << 2;
321
322 let xg: f32 = lookup::GRADIENTS_3D[hash as usize];
323 let yg: f32 = lookup::GRADIENTS_3D[(hash | 1) as usize];
324 let zg: f32 = lookup::GRADIENTS_3D[(hash | 2) as usize];
325
326 return xd * xg + yd * yg + zd * zg;
327 }
328
329 fn grad_coord_out_2d(seed: i32, x_primed: i32, y_primed: i32, xo: &mut f32, yo: &mut f32) {
330 let hash: i32 = Self::hash_2d(seed, x_primed, y_primed) & (255 << 1);
331
332 *xo = lookup::RAND_VECS_2D[hash as usize];
333 *yo = lookup::RAND_VECS_2D[(hash | 1) as usize];
334 }
335
336 fn grad_coord_out_3d(
337 seed: i32,
338 x_primed: i32,
339 y_primed: i32,
340 z_primed: i32,
341 xo: &mut f32,
342 yo: &mut f32,
343 zo: &mut f32,
344 ) {
345 let hash: i32 = Self::hash_3d(seed, x_primed, y_primed, z_primed) & (255 << 2);
346
347 *xo = lookup::RAND_VECS_3D[hash as usize];
348 *yo = lookup::RAND_VECS_3D[(hash | 1) as usize];
349 *zo = lookup::RAND_VECS_3D[(hash | 2) as usize];
350 }
351
352 fn grad_coord_dual_2d(
353 seed: i32,
354 x_primed: i32,
355 y_primed: i32,
356 xd: f32,
357 yd: f32,
358 xo: &mut f32,
359 yo: &mut f32,
360 ) {
361 let hash: i32 = Self::hash_2d(seed, x_primed, y_primed);
362 let index1: i32 = hash & (127 << 1);
363 let index2: i32 = (hash >> 7) & (255 << 1);
364
365 let xg: f32 = lookup::GRADIENTS_2D[index1 as usize];
366 let yg: f32 = lookup::GRADIENTS_2D[(index1 | 1) as usize];
367 let value: f32 = xd * xg + yd * yg;
368
369 let xgo: f32 = lookup::RAND_VECS_2D[index2 as usize];
370 let ygo: f32 = lookup::RAND_VECS_2D[(index2 | 1) as usize];
371
372 *xo = value * xgo;
373 *yo = value * ygo;
374 }
375
376 fn grad_coord_dual_3d(
377 seed: i32,
378 x_primed: i32,
379 y_primed: i32,
380 z_primed: i32,
381 xd: f32,
382 yd: f32,
383 zd: f32,
384 xo: &mut f32,
385 yo: &mut f32,
386 zo: &mut f32,
387 ) {
388 let hash: i32 = Self::hash_3d(seed, x_primed, y_primed, z_primed);
389 let index1: i32 = hash & (63 << 2);
390 let index2: i32 = (hash >> 6) & (255 << 2);
391
392 let xg: f32 = lookup::GRADIENTS_3D[index1 as usize];
393 let yg: f32 = lookup::GRADIENTS_3D[(index1 | 1) as usize];
394 let zg: f32 = lookup::GRADIENTS_3D[(index1 | 2) as usize];
395 let value: f32 = xd * xg + yd * yg + zd * zg;
396
397 let xgo: f32 = lookup::RAND_VECS_3D[index2 as usize];
398 let ygo: f32 = lookup::RAND_VECS_3D[(index2 | 1) as usize];
399 let zgo: f32 = lookup::RAND_VECS_3D[(index2 | 2) as usize];
400
401 *xo = value * xgo;
402 *yo = value * ygo;
403 *zo = value * zgo;
404 }
405 fn gen_noise_single_2d(&self, seed: i32, x: f32, y: f32) -> f32 {
406 match self.noise_type {
407 NoiseType::OpenSimplex2 => self.single_open_simplex_2_2d(seed, x, y),
408 NoiseType::OpenSimplex2S => self.single_open_simplex2s_2d(seed, x, y),
409 NoiseType::Cellular => self.single_cellular_2d(seed, x, y),
410 NoiseType::Perlin => self.single_perlin_2d(seed, x, y),
411 NoiseType::ValueCubic => self.single_value_cubic_2d(seed, x, y),
412 NoiseType::Value => self.single_value_2d(seed, x, y),
413 }
414 }
415
416 fn gen_noise_single_3d(&self, seed: i32, x: f32, y: f32, z: f32) -> f32 {
417 match self.noise_type {
418 NoiseType::OpenSimplex2 => self.single_open_simplex_2_3d(seed, x, y, z),
419 NoiseType::OpenSimplex2S => self.single_open_simplex_2s_3d(seed, x, y, z),
420 NoiseType::Cellular => self.single_cellular_3d(seed, x, y, z),
421 NoiseType::Perlin => self.single_perlin_3d(seed, x, y, z),
422 NoiseType::ValueCubic => self.single_value_cubic_3d(seed, x, y, z),
423 NoiseType::Value => self.single_value_3d(seed, x, y, z),
424 }
425 }
426
427 fn transform_noise_coordinate_2d(&self, x: &mut f32, y: &mut f32) {
428 *x *= self.frequency;
429 *y *= self.frequency;
430
431 match self.noise_type {
432 NoiseType::OpenSimplex2 | NoiseType::OpenSimplex2S => {
433 const SQRT3: f32 = 1.7320508075688772935274463415059;
434 const F2: f32 = 0.5 * (SQRT3 - 1.0);
435 let t: f32 = (*x + *y) * F2;
436 *x += t;
437 *y += t;
438 }
439 _ => {}
440 }
441 }
442
443 fn transform_noise_coordinate_3d(&self, x: &mut f32, y: &mut f32, z: &mut f32) {
444 *x *= self.frequency;
445 *y *= self.frequency;
446 *z *= self.frequency;
447
448 match self.transform_type3d {
449 TransformType3D::ImproveXYPlanes => {
450 let xy: f32 = *x + *y;
451 let s2: f32 = xy * -0.211324865405187;
452 *z *= 0.577350269189626;
453 *x += s2 - *z;
454 *y = *y + s2 - *z;
455 *z += xy * 0.577350269189626;
456 }
457 TransformType3D::ImproveXZPlanes => {
458 let xz: f32 = *x + *z;
459 let s2: f32 = xz * -0.211324865405187;
460 *y *= 0.577350269189626;
461 *x += s2 - *y;
462 *z += s2 - *y;
463 *y += xz * 0.577350269189626;
464 }
465 TransformType3D::DefaultOpenSimplex2 => {
466 const R3: f32 = 2.0 / 3.0;
467 let r: f32 = (*x + *y + *z) * R3; *x = r - *x;
469 *y = r - *y;
470 *z = r - *z;
471 }
472 TransformType3D::None => {}
473 }
474 }
475
476 fn update_transform_type_3d(&mut self) {
477 match self.rotation_type3d {
478 RotationType3D::ImproveXYPlanes => {
479 self.transform_type3d = TransformType3D::ImproveXYPlanes;
480 }
481 RotationType3D::ImproveXZPlanes => {
482 self.transform_type3d = TransformType3D::ImproveXZPlanes;
483 }
484 RotationType3D::None => match self.noise_type {
485 NoiseType::OpenSimplex2 | NoiseType::OpenSimplex2S => {
486 self.transform_type3d = TransformType3D::DefaultOpenSimplex2;
487 }
488 _ => {
489 self.transform_type3d = TransformType3D::None;
490 }
491 },
492 };
493 }
494
495 fn transform_domain_warp_coordinate_2d(&self, x: &mut f32, y: &mut f32) {
498 match self.domain_warp_type {
499 DomainWarpType::OpenSimplex2 | DomainWarpType::OpenSimplex2Reduced => {
500 const SQRT3: f32 = 1.7320508075688772935274463415059;
501 const F2: f32 = 0.5 * (SQRT3 - 1.0);
502 let t: f32 = (*x + *y) * F2;
503 *x += t;
504 *y += t;
505 }
506 _ => {}
507 }
508 }
509
510 fn transform_domain_warp_coordinate_3d(&self, x: &mut f32, y: &mut f32, z: &mut f32) {
511 match self.warp_transform_type3d {
512 TransformType3D::ImproveXYPlanes => {
513 let xy: f32 = *x + *y;
514 let s2: f32 = xy * -0.211324865405187;
515 *z *= 0.577350269189626;
516 *x += s2 - *z;
517 *y = *y + s2 - *z;
518 *z += xy * 0.577350269189626;
519 }
520 TransformType3D::ImproveXZPlanes => {
521 let xz: f32 = *x + *z;
522 let s2: f32 = xz * -0.211324865405187;
523 *y *= 0.577350269189626;
524 *x += s2 - *y;
525 *z += s2 - *y;
526 *y += xz * 0.577350269189626;
527 }
528 TransformType3D::DefaultOpenSimplex2 => {
529 const R3: f32 = 2.0 / 3.0;
530 let r: f32 = (*x + *y + *z) * R3; *x = r - *x;
532 *y = r - *y;
533 *z = r - *z;
534 }
535 _ => {}
536 }
537 }
538
539 fn update_warp_transform_type_3d(&mut self) {
540 match self.rotation_type3d {
541 RotationType3D::ImproveXYPlanes => {
542 self.warp_transform_type3d = TransformType3D::ImproveXYPlanes
543 }
544 RotationType3D::ImproveXZPlanes => {
545 self.warp_transform_type3d = TransformType3D::ImproveXZPlanes
546 }
547 RotationType3D::None => match self.domain_warp_type {
548 DomainWarpType::OpenSimplex2 | DomainWarpType::OpenSimplex2Reduced => {
549 self.warp_transform_type3d = TransformType3D::DefaultOpenSimplex2
550 }
551 _ => self.warp_transform_type3d = TransformType3D::None,
552 },
553 }
554 }
555
556 fn gen_fractal_fbm_2d(&self, mut x: f32, mut y: f32) -> f32 {
557 let mut seed = self.seed;
558 let mut sum = 0.0;
559 let mut amp = self.fractal_bounding;
560
561 for _ in 0..self.octaves {
562 let noise = self.gen_noise_single_2d(seed, x, y);
563 seed += 1;
564 sum += noise * amp;
565 amp *= lerp(
566 1.0,
567 fast_min(noise + 1.0, 2.0) * 0.5,
568 self.weighted_strength,
569 );
570
571 x *= self.lacunarity;
572 y *= self.lacunarity;
573 amp *= self.gain;
574 }
575
576 return sum;
577 }
578
579 fn gen_fractal_fbm_3d(&self, mut x: f32, mut y: f32, mut z: f32) -> f32 {
580 let mut seed = self.seed;
581 let mut sum = 0.0;
582 let mut amp = self.fractal_bounding;
583
584 for _ in 0..self.octaves {
585 let noise = self.gen_noise_single_3d(seed, x, y, z);
586 seed += 1;
587 sum += noise * amp;
588 amp *= lerp(1.0, (noise + 1.0) * 0.5, self.weighted_strength);
589
590 x *= self.lacunarity;
591 y *= self.lacunarity;
592 z *= self.lacunarity;
593 amp *= self.gain;
594 }
595
596 return sum;
597 }
598
599 fn gen_fractal_ridged_2d(&self, mut x: f32, mut y: f32) -> f32 {
600 let mut seed = self.seed;
601 let mut sum = 0.0;
602 let mut amp = self.fractal_bounding;
603
604 for _ in 0..self.octaves {
605 let noise = fast_abs(self.gen_noise_single_2d(seed, x, y));
606 seed += 1;
607 sum += (noise * -2.0 + 1.0) * amp;
608 amp *= lerp(1.0, 1.0 - noise, self.weighted_strength);
609
610 x *= self.lacunarity;
611 y *= self.lacunarity;
612 amp *= self.gain;
613 }
614
615 return sum;
616 }
617
618 fn gen_fractal_ridged_3d(&self, mut x: f32, mut y: f32, mut z: f32) -> f32 {
619 let mut seed = self.seed;
620 let mut sum = 0.0;
621 let mut amp = self.fractal_bounding;
622
623 for _ in 0..self.octaves {
624 let noise = fast_abs(self.gen_noise_single_3d(seed, x, y, z));
625 seed += 1;
626 sum += (noise * -2.0 + 1.0) * amp;
627 amp *= lerp(1.0, 1.0 - noise, self.weighted_strength);
628
629 x *= self.lacunarity;
630 y *= self.lacunarity;
631 z *= self.lacunarity;
632 amp *= self.gain;
633 }
634
635 return sum;
636 }
637
638 fn gen_fractal_ping_pong_2d(&self, mut x: f32, mut y: f32) -> f32 {
639 let mut seed = self.seed;
640 let mut sum = 0.0;
641 let mut amp = self.fractal_bounding;
642
643 for _ in 0..self.octaves {
644 let noise =
645 ping_pong((self.gen_noise_single_2d(seed, x, y) + 1.0) * self.ping_pong_strength);
646 seed += 1;
647 sum += (noise - 0.5) * 2.0 * amp;
648 amp *= lerp(1.0, noise, self.weighted_strength);
649
650 x *= self.lacunarity;
651 y *= self.lacunarity;
652 amp *= self.gain;
653 }
654
655 return sum;
656 }
657
658 fn gen_fractal_ping_pong_3d(&self, mut x: f32, mut y: f32, mut z: f32) -> f32 {
659 let mut seed = self.seed;
660 let mut sum = 0.0;
661 let mut amp = self.fractal_bounding;
662
663 for _ in 0..self.octaves {
664 let noise = ping_pong(
665 (self.gen_noise_single_3d(seed, x, y, z) + 1.0) * self.ping_pong_strength,
666 );
667 seed += 1;
668 sum += (noise - 0.5) * 2.0 * amp;
669 amp *= lerp(1.0, noise, self.weighted_strength);
670
671 x *= self.lacunarity;
672 y *= self.lacunarity;
673 z *= self.lacunarity;
674 amp *= self.gain;
675 }
676
677 return sum;
678 }
679 fn single_open_simplex_2_2d(&self, seed: i32, x: f32, y: f32) -> f32 {
680 const SQRT3: f32 = 1.7320508075688772935274463415059;
683 const G2: f32 = (3.0 - SQRT3) / 6.0;
684
685 let mut i: i32 = fast_floor(x);
693 let mut j: i32 = fast_floor(y);
694 let xi: f32 = x - i as f32;
695 let yi: f32 = y - j as f32;
696
697 let t: f32 = (xi + yi) * G2;
698 let x0: f32 = xi - t;
699 let y0: f32 = yi - t;
700
701 i = i.wrapping_mul(Self::PRIME_X);
702 j = j.wrapping_mul(Self::PRIME_Y);
703
704 let n0: f32;
705 let n1: f32;
706 let n2: f32;
707
708 let a: f32 = 0.5 - x0 * x0 - y0 * y0;
709 if a <= 0.0 {
710 n0 = 0.0;
711 } else {
712 n0 = (a * a) * (a * a) * Self::grad_coord_2d(seed, i, j, x0, y0);
713 }
714
715 let c: f32 = (2.0 * (1.0 - 2.0 * G2) * (1.0 / G2 - 2.0)) * t
716 + ((-2.0 * (1.0 - 2.0 * G2) * (1.0 - 2.0 * G2)) + a);
717 if c <= 0.0 {
718 n2 = 0.0;
719 } else {
720 let x2: f32 = x0 + (2.0 * G2 - 1.0);
721 let y2: f32 = y0 + (2.0 * G2 - 1.0);
722 n2 = (c * c)
723 * (c * c)
724 * Self::grad_coord_2d(
725 seed,
726 i.wrapping_add(Self::PRIME_X),
727 j.wrapping_add(Self::PRIME_Y),
728 x2,
729 y2,
730 );
731 }
732
733 if y0 > x0 {
734 let x1: f32 = x0 + G2;
735 let y1: f32 = y0 + (G2 - 1.0);
736 let b: f32 = 0.5 - x1 * x1 - y1 * y1;
737 if b <= 0.0 {
738 n1 = 0.0;
739 } else {
740 n1 = (b * b)
741 * (b * b)
742 * Self::grad_coord_2d(seed, i, j.wrapping_add(Self::PRIME_Y), x1, y1);
743 }
744 } else {
745 let x1: f32 = x0 + (G2 - 1.0);
746 let y1: f32 = y0 + G2;
747 let b: f32 = 0.5 - x1 * x1 - y1 * y1;
748 if b <= 0.0 {
749 n1 = 0.0;
750 } else {
751 n1 = (b * b)
752 * (b * b)
753 * Self::grad_coord_2d(seed, i.wrapping_add(Self::PRIME_X), j, x1, y1);
754 }
755 }
756
757 return (n0 + n1 + n2) * 99.83685446303647;
758 }
759
760 fn single_open_simplex_2_3d(&self, mut seed: i32, x: f32, y: f32, z: f32) -> f32 {
761 let mut i: i32 = fast_round(x);
771 let mut j: i32 = fast_round(y);
772 let mut k: i32 = fast_round(z);
773 let mut x0: f32 = x - i as f32;
774 let mut y0: f32 = y - j as f32;
775 let mut z0: f32 = z - k as f32;
776
777 let mut x_nsign: i32 = (-1.0 - x0) as i32 | 1;
778 let mut y_nsign: i32 = (-1.0 - y0) as i32 | 1;
779 let mut z_nsign: i32 = (-1.0 - z0) as i32 | 1;
780
781 let mut ax0: f32 = x_nsign as f32 * -x0;
782 let mut ay0: f32 = y_nsign as f32 * -y0;
783 let mut az0: f32 = z_nsign as f32 * -z0;
784
785 i = i.wrapping_mul(Self::PRIME_X);
786 j = j.wrapping_mul(Self::PRIME_Y);
787 k = k.wrapping_mul(Self::PRIME_Z);
788
789 let mut value: f32 = 0.0;
790 let mut a: f32 = (0.6 - x0 * x0) - (y0 * y0 + z0 * z0);
791
792 for l in 0..2 {
793 if a > 0.0 {
794 value += (a * a) * (a * a) * Self::grad_coord_3d(seed, i, j, k, x0, y0, z0);
795 }
796
797 let mut b: f32 = a + 1.0;
798 let mut i1: i32 = i;
799 let mut j1: i32 = j;
800 let mut k1: i32 = k;
801 let mut x1: f32 = x0;
802 let mut y1: f32 = y0;
803 let mut z1: f32 = z0;
804
805 if ax0 >= ay0 && ax0 >= az0 {
806 x1 += x_nsign as f32;
807 b -= x_nsign as f32 * 2.0 * x1;
808 i1 -= x_nsign * Self::PRIME_X;
809 } else if ay0 > ax0 && ay0 >= az0 {
810 y1 += y_nsign as f32;
811 b -= y_nsign as f32 * 2.0 * y1;
812 j1 -= y_nsign * Self::PRIME_Y;
813 } else {
814 z1 += z_nsign as f32;
815 b -= z_nsign as f32 * 2.0 * z1;
816 k1 -= z_nsign * Self::PRIME_Z;
817 }
818
819 if b > 0.0 {
820 value += (b * b) * (b * b) * Self::grad_coord_3d(seed, i1, j1, k1, x1, y1, z1);
821 }
822
823 if l == 1 {
824 break;
825 }
826
827 ax0 = 0.5 - ax0;
828 ay0 = 0.5 - ay0;
829 az0 = 0.5 - az0;
830
831 x0 = x_nsign as f32 * ax0;
832 y0 = y_nsign as f32 * ay0;
833 z0 = z_nsign as f32 * az0;
834
835 a += (0.75 - ax0) - (ay0 + az0);
836
837 i += (x_nsign >> 1) & Self::PRIME_X;
838 j += (y_nsign >> 1) & Self::PRIME_Y;
839 k += (z_nsign >> 1) & Self::PRIME_Z;
840
841 x_nsign = -x_nsign;
842 y_nsign = -y_nsign;
843 z_nsign = -z_nsign;
844
845 seed = !seed;
846 }
847
848 return value * 32.69428253173828125;
849 }
850
851 fn single_open_simplex2s_2d(&self, seed: i32, x: f32, y: f32) -> f32 {
854 const SQRT3: f32 = 1.7320508075688772935274463415059;
857 const G2: f32 = (3.0 - SQRT3) / 6.0;
858
859 let mut i: i32 = fast_floor(x);
867 let mut j: i32 = fast_floor(y);
868 let xi: f32 = x - i as f32;
869 let yi: f32 = y - j as f32;
870
871 i = i.wrapping_mul(Self::PRIME_X);
872 j = j.wrapping_mul(Self::PRIME_Y);
873 let i1: i32 = i.wrapping_add(Self::PRIME_X);
874 let j1: i32 = j.wrapping_add(Self::PRIME_Y);
875
876 let t: f32 = (xi + yi) * G2;
877 let x0: f32 = xi - t;
878 let y0: f32 = yi - t;
879
880 let a0: f32 = (2.0 / 3.0) - x0 * x0 - y0 * y0;
881 let mut value: f32 = (a0 * a0) * (a0 * a0) * Self::grad_coord_2d(seed, i, j, x0, y0);
882
883 let a1: f32 = (2.0 * (1.0 - 2.0 * G2) * (1.0 / G2 - 2.0)) * t
884 + ((-2.0 * (1.0 - 2.0 * G2) * (1.0 - 2.0 * G2)) + a0);
885 let x1: f32 = x0 - (1.0 - 2.0 * G2);
886 let y1: f32 = y0 - (1.0 - 2.0 * G2);
887 value += (a1 * a1) * (a1 * a1) * Self::grad_coord_2d(seed, i1, j1, x1, y1);
888
889 let xmyi: f32 = xi - yi;
891 if t > G2 {
892 if xi + xmyi > 1.0 {
893 let x2: f32 = x0 + (3.0 * G2 - 2.0);
894 let y2: f32 = y0 + (3.0 * G2 - 1.0);
895 let a2: f32 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
896 if a2 > 0.0 {
897 value += (a2 * a2)
898 * (a2 * a2)
899 * Self::grad_coord_2d(
900 seed,
901 i.wrapping_add(Self::PRIME_X << 1),
902 j.wrapping_add(Self::PRIME_Y),
903 x2,
904 y2,
905 );
906 }
907 } else {
908 let x2: f32 = x0 + G2;
909 let y2: f32 = y0 + (G2 - 1.0);
910 let a2: f32 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
911 if a2 > 0.0 {
912 value += (a2 * a2)
913 * (a2 * a2)
914 * Self::grad_coord_2d(seed, i, j.wrapping_add(Self::PRIME_Y), x2, y2);
915 }
916 }
917
918 if yi - xmyi > 1.0 {
919 let x3: f32 = x0 + (3.0 * G2 - 1.0);
920 let y3: f32 = y0 + (3.0 * G2 - 2.0);
921 let a3: f32 = (2.0 / 3.0) - x3 * x3 - y3 * y3;
922 if a3 > 0.0 {
923 value += (a3 * a3)
924 * (a3 * a3)
925 * Self::grad_coord_2d(
926 seed,
927 i.wrapping_add(Self::PRIME_X),
928 j.wrapping_add(Self::PRIME_Y << 1),
929 x3,
930 y3,
931 );
932 }
933 } else {
934 let x3: f32 = x0 + (G2 - 1.0);
935 let y3: f32 = y0 + G2;
936 let a3: f32 = (2.0 / 3.0) - x3 * x3 - y3 * y3;
937 if a3 > 0.0 {
938 value += (a3 * a3)
939 * (a3 * a3)
940 * Self::grad_coord_2d(seed, i.wrapping_add(Self::PRIME_X), j, x3, y3);
941 }
942 }
943 } else {
944 if xi + xmyi < 0.0 {
945 let x2: f32 = x0 + (1.0 - G2);
946 let y2: f32 = y0 - G2;
947 let a2: f32 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
948 if a2 > 0.0 {
949 value += (a2 * a2)
950 * (a2 * a2)
951 * Self::grad_coord_2d(seed, i.wrapping_sub(Self::PRIME_X), j, x2, y2);
952 }
953 } else {
954 let x2: f32 = x0 + (G2 - 1.0);
955 let y2: f32 = y0 + G2;
956 let a2: f32 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
957 if a2 > 0.0 {
958 value += (a2 * a2)
959 * (a2 * a2)
960 * Self::grad_coord_2d(seed, i.wrapping_add(Self::PRIME_X), j, x2, y2);
961 }
962 }
963
964 if yi < xmyi {
965 let x2: f32 = x0 - G2;
966 let y2: f32 = y0 - (G2 - 1.0);
967 let a2: f32 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
968 if a2 > 0.0 {
969 value += (a2 * a2)
970 * (a2 * a2)
971 * Self::grad_coord_2d(seed, i, j.wrapping_sub(Self::PRIME_Y), x2, y2);
972 }
973 } else {
974 let x2: f32 = x0 + G2;
975 let y2: f32 = y0 + (G2 - 1.0);
976 let a2: f32 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
977 if a2 > 0.0 {
978 value += (a2 * a2)
979 * (a2 * a2)
980 * Self::grad_coord_2d(seed, i, j.wrapping_add(Self::PRIME_Y), x2, y2);
981 }
982 }
983 }
984
985 return value * 18.24196194486065;
986 }
987
988 fn single_open_simplex_2s_3d(&self, seed: i32, x: f32, y: f32, z: f32) -> f32 {
989 let mut i: i32 = fast_floor(x);
999 let mut j: i32 = fast_floor(y);
1000 let mut k: i32 = fast_floor(z);
1001 let xi: f32 = x - i as f32;
1002 let yi: f32 = y - j as f32;
1003 let zi: f32 = z - k as f32;
1004
1005 i = i.wrapping_mul(Self::PRIME_X);
1006 j = j.wrapping_mul(Self::PRIME_Y);
1007 k = k.wrapping_mul(Self::PRIME_Z);
1008 let seed2: i32 = seed.wrapping_add(1293373);
1009
1010 let x_n_mask: i32 = (-0.5 - xi) as i32;
1011 let y_n_mask: i32 = (-0.5 - yi) as i32;
1012 let z_n_mask: i32 = (-0.5 - zi) as i32;
1013
1014 let x0: f32 = xi + x_n_mask as f32;
1015 let y0: f32 = yi + y_n_mask as f32;
1016 let z0: f32 = zi + z_n_mask as f32;
1017 let a0: f32 = 0.75 - x0 * x0 - y0 * y0 - z0 * z0;
1018 let mut value: f32 = (a0 * a0)
1019 * (a0 * a0)
1020 * Self::grad_coord_3d(
1021 seed,
1022 i + (x_n_mask & Self::PRIME_X),
1023 j + (y_n_mask & Self::PRIME_Y),
1024 k + (z_n_mask & Self::PRIME_Z),
1025 x0,
1026 y0,
1027 z0,
1028 );
1029
1030 let x1: f32 = xi - 0.5;
1031 let y1: f32 = yi - 0.5;
1032 let z1: f32 = zi - 0.5;
1033 let a1: f32 = 0.75 - x1 * x1 - y1 * y1 - z1 * z1;
1034 value += (a1 * a1)
1035 * (a1 * a1)
1036 * Self::grad_coord_3d(
1037 seed2,
1038 i.wrapping_add(Self::PRIME_X),
1039 j.wrapping_add(Self::PRIME_Y),
1040 k.wrapping_add(Self::PRIME_Z),
1041 x1,
1042 y1,
1043 z1,
1044 );
1045
1046 let x_a_flip_mask_0: f32 = ((x_n_mask | 1) << 1) as f32 * x1;
1047 let y_a_flip_mask_0: f32 = ((y_n_mask | 1) << 1) as f32 * y1;
1048 let z_a_flip_mask_0: f32 = ((z_n_mask | 1) << 1) as f32 * z1;
1049 let x_a_flip_mask_1: f32 = (-2 - (x_n_mask << 2)) as f32 * x1 - 1.0;
1050 let y_a_flip_mask_1: f32 = (-2 - (y_n_mask << 2)) as f32 * y1 - 1.0;
1051 let z_a_flip_mask_1: f32 = (-2 - (z_n_mask << 2)) as f32 * z1 - 1.0;
1052
1053 let mut skip_5 = false;
1054 let a2: f32 = x_a_flip_mask_0 + a0;
1055 if a2 > 0.0 {
1056 let x2: f32 = x0 - (x_n_mask | 1) as f32;
1057 let y2: f32 = y0;
1058 let z2: f32 = z0;
1059 value += (a2 * a2)
1060 * (a2 * a2)
1061 * Self::grad_coord_3d(
1062 seed,
1063 i + (!x_n_mask & Self::PRIME_X),
1064 j + (y_n_mask & Self::PRIME_Y),
1065 k + (z_n_mask & Self::PRIME_Z),
1066 x2,
1067 y2,
1068 z2,
1069 );
1070 } else {
1071 let a3: f32 = y_a_flip_mask_0 + z_a_flip_mask_0 + a0;
1072 if a3 > 0.0 {
1073 let x3: f32 = x0;
1074 let y3: f32 = y0 - (y_n_mask | 1) as f32;
1075 let z3: f32 = z0 - (z_n_mask | 1) as f32;
1076 value += (a3 * a3)
1077 * (a3 * a3)
1078 * Self::grad_coord_3d(
1079 seed,
1080 i + (x_n_mask & Self::PRIME_X),
1081 j + (!y_n_mask & Self::PRIME_Y),
1082 k + (!z_n_mask & Self::PRIME_Z),
1083 x3,
1084 y3,
1085 z3,
1086 );
1087 }
1088
1089 let a4: f32 = x_a_flip_mask_1 + a1;
1090 if a4 > 0.0 {
1091 let x4: f32 = (x_n_mask | 1) as f32 + x1;
1092 let y4: f32 = y1;
1093 let z4: f32 = z1;
1094 value += (a4 * a4)
1095 * (a4 * a4)
1096 * Self::grad_coord_3d(
1097 seed2,
1098 i + (x_n_mask & (Self::PRIME_X * 2)),
1099 j.wrapping_add(Self::PRIME_Y),
1100 k.wrapping_add(Self::PRIME_Z),
1101 x4,
1102 y4,
1103 z4,
1104 );
1105 skip_5 = true;
1106 }
1107 }
1108
1109 let mut skip_9 = false;
1110 let a6: f32 = y_a_flip_mask_0 + a0;
1111 if a6 > 0.0 {
1112 let x6: f32 = x0;
1113 let y6: f32 = y0 - (y_n_mask | 1) as f32;
1114 let z6: f32 = z0;
1115 value += (a6 * a6)
1116 * (a6 * a6)
1117 * Self::grad_coord_3d(
1118 seed,
1119 i + (x_n_mask & Self::PRIME_X),
1120 j + (!y_n_mask & Self::PRIME_Y),
1121 k + (z_n_mask & Self::PRIME_Z),
1122 x6,
1123 y6,
1124 z6,
1125 );
1126 } else {
1127 let a7: f32 = x_a_flip_mask_0 + z_a_flip_mask_0 + a0;
1128 if a7 > 0.0 {
1129 let x7: f32 = x0 - (x_n_mask | 1) as f32;
1130 let y7: f32 = y0;
1131 let z7: f32 = z0 - (z_n_mask | 1) as f32;
1132 value += (a7 * a7)
1133 * (a7 * a7)
1134 * Self::grad_coord_3d(
1135 seed,
1136 i + (!x_n_mask & Self::PRIME_X),
1137 j + (y_n_mask & Self::PRIME_Y),
1138 k + (!z_n_mask & Self::PRIME_Z),
1139 x7,
1140 y7,
1141 z7,
1142 );
1143 }
1144
1145 let a8: f32 = y_a_flip_mask_1 + a1;
1146 if a8 > 0.0 {
1147 let x8: f32 = x1;
1148 let y8: f32 = (y_n_mask | 1) as f32 + y1;
1149 let z8: f32 = z1;
1150 value += (a8 * a8)
1151 * (a8 * a8)
1152 * Self::grad_coord_3d(
1153 seed2,
1154 i.wrapping_add(Self::PRIME_X),
1155 j + (y_n_mask & (Self::PRIME_Y << 1)),
1156 k.wrapping_add(Self::PRIME_Z),
1157 x8,
1158 y8,
1159 z8,
1160 );
1161 skip_9 = true;
1162 }
1163 }
1164
1165 let mut skip_d = false;
1166 let a_a: f32 = z_a_flip_mask_0 + a0;
1167 if a_a > 0.0 {
1168 let x_a: f32 = x0;
1169 let y_a: f32 = y0;
1170 let z_a: f32 = z0 - (z_n_mask | 1) as f32;
1171 value += (a_a * a_a)
1172 * (a_a * a_a)
1173 * Self::grad_coord_3d(
1174 seed,
1175 i + (x_n_mask & Self::PRIME_X),
1176 j + (y_n_mask & Self::PRIME_Y),
1177 k + (!z_n_mask & Self::PRIME_Z),
1178 x_a,
1179 y_a,
1180 z_a,
1181 );
1182 } else {
1183 let a_b: f32 = x_a_flip_mask_0 + y_a_flip_mask_0 + a0;
1184 if a_b > 0.0 {
1185 let x_b: f32 = x0 - (x_n_mask | 1) as f32;
1186 let y_b: f32 = y0 - (y_n_mask | 1) as f32;
1187 let z_b: f32 = z0;
1188 value += (a_b * a_b)
1189 * (a_b * a_b)
1190 * Self::grad_coord_3d(
1191 seed,
1192 i + (!x_n_mask & Self::PRIME_X),
1193 j + (!y_n_mask & Self::PRIME_Y),
1194 k + (z_n_mask & Self::PRIME_Z),
1195 x_b,
1196 y_b,
1197 z_b,
1198 );
1199 }
1200
1201 let a_c: f32 = z_a_flip_mask_1 + a1;
1202 if a_c > 0.0 {
1203 let x_c: f32 = x1;
1204 let y_c: f32 = y1;
1205 let z_c: f32 = (z_n_mask | 1) as f32 + z1;
1206 value += (a_c * a_c)
1207 * (a_c * a_c)
1208 * Self::grad_coord_3d(
1209 seed2,
1210 i.wrapping_add(Self::PRIME_X),
1211 j.wrapping_add(Self::PRIME_Y),
1212 k + (z_n_mask & (Self::PRIME_Z << 1)),
1213 x_c,
1214 y_c,
1215 z_c,
1216 );
1217 skip_d = true;
1218 }
1219 }
1220
1221 if !skip_5 {
1222 let a5: f32 = y_a_flip_mask_1 + z_a_flip_mask_1 + a1;
1223 if a5 > 0.0 {
1224 let x5: f32 = x1;
1225 let y5: f32 = (y_n_mask | 1) as f32 + y1;
1226 let z5: f32 = (z_n_mask | 1) as f32 + z1;
1227 value += (a5 * a5)
1228 * (a5 * a5)
1229 * Self::grad_coord_3d(
1230 seed2,
1231 i.wrapping_add(Self::PRIME_X),
1232 j + (y_n_mask & (Self::PRIME_Y << 1)),
1233 k + (z_n_mask & (Self::PRIME_Z << 1)),
1234 x5,
1235 y5,
1236 z5,
1237 );
1238 }
1239 }
1240
1241 if !skip_9 {
1242 let a9: f32 = x_a_flip_mask_1 + z_a_flip_mask_1 + a1;
1243 if a9 > 0.0 {
1244 let x9: f32 = (x_n_mask | 1) as f32 + x1;
1245 let y9: f32 = y1;
1246 let z9: f32 = (z_n_mask | 1) as f32 + z1;
1247 value += (a9 * a9)
1248 * (a9 * a9)
1249 * Self::grad_coord_3d(
1250 seed2,
1251 i + (x_n_mask & (Self::PRIME_X * 2)),
1252 j.wrapping_add(Self::PRIME_Y),
1253 k + (z_n_mask & (Self::PRIME_Z << 1)),
1254 x9,
1255 y9,
1256 z9,
1257 );
1258 }
1259 }
1260
1261 if !skip_d {
1262 let a_d: f32 = x_a_flip_mask_1 + y_a_flip_mask_1 + a1;
1263 if a_d > 0.0 {
1264 let x_d: f32 = (x_n_mask | 1) as f32 + x1;
1265 let y_d: f32 = (y_n_mask | 1) as f32 + y1;
1266 let z_d: f32 = z1;
1267 value += (a_d * a_d)
1268 * (a_d * a_d)
1269 * Self::grad_coord_3d(
1270 seed2,
1271 i + (x_n_mask & (Self::PRIME_X << 1)),
1272 j + (y_n_mask & (Self::PRIME_Y << 1)),
1273 k.wrapping_add(Self::PRIME_Z),
1274 x_d,
1275 y_d,
1276 z_d,
1277 );
1278 }
1279 }
1280
1281 return value * 9.046026385208288;
1282 }
1283
1284 fn single_cellular_2d(&self, seed: i32, x: f32, y: f32) -> f32 {
1285 let xr: i32 = fast_round(x);
1286 let yr: i32 = fast_round(y);
1287
1288 let mut distance0: f32 = 1e10;
1289 let mut distance1: f32 = 1e10;
1290 let mut closest_hash: i32 = 0;
1291
1292 let cellular_jitter: f32 = 0.43701595 * self.cellular_jitter_modifier;
1293
1294 let mut x_primed: i32 = (xr - 1) * Self::PRIME_X;
1295 let y_primed_base: i32 = (yr - 1) * Self::PRIME_Y;
1296
1297 match self.cellular_distance_function {
1298 CellularDistanceFunction::Manhattan => {
1299 for xi in (xr - 1)..=(xr + 1) {
1300 let mut y_primed: i32 = y_primed_base;
1301
1302 for yi in (yr - 1)..=(yr + 1) {
1303 let hash: i32 = Self::hash_2d(seed, x_primed, y_primed);
1304 let idx: i32 = hash & (255 << 1);
1305
1306 let vec_x: f32 =
1307 (xi as f32 - x) + lookup::RAND_VECS_2D[idx as usize] * cellular_jitter;
1308 let vec_y: f32 = (yi as f32 - y)
1309 + lookup::RAND_VECS_2D[(idx | 1) as usize] * cellular_jitter;
1310
1311 let new_distance: f32 = fast_abs(vec_x) + fast_abs(vec_y);
1312
1313 distance1 = fast_max(fast_min(distance1, new_distance), distance0);
1314 if new_distance < distance0 {
1315 distance0 = new_distance;
1316 closest_hash = hash;
1317 }
1318 y_primed += Self::PRIME_Y;
1319 }
1320 x_primed += Self::PRIME_X;
1321 }
1322 }
1323 CellularDistanceFunction::Hybrid => {
1324 for xi in (xr - 1)..=(xr + 1) {
1325 let mut y_primed: i32 = y_primed_base;
1326
1327 for yi in (yr - 1)..=(yr + 1) {
1328 let hash: i32 = Self::hash_2d(seed, x_primed, y_primed);
1329 let idx: i32 = hash & (255 << 1);
1330
1331 let vec_x: f32 =
1332 (xi as f32 - x) + lookup::RAND_VECS_2D[idx as usize] * cellular_jitter;
1333 let vec_y: f32 = (yi as f32 - y)
1334 + lookup::RAND_VECS_2D[(idx | 1) as usize] * cellular_jitter;
1335
1336 let new_distance: f32 =
1337 (fast_abs(vec_x) + fast_abs(vec_y)) + (vec_x * vec_x + vec_y * vec_y);
1338
1339 distance1 = fast_max(fast_min(distance1, new_distance), distance0);
1340 if new_distance < distance0 {
1341 distance0 = new_distance;
1342 closest_hash = hash;
1343 }
1344 y_primed += Self::PRIME_Y;
1345 }
1346 x_primed += Self::PRIME_X;
1347 }
1348 }
1349 _ => {
1350 for xi in (xr - 1)..=(xr + 1) {
1351 let mut y_primed: i32 = y_primed_base;
1352
1353 for yi in (yr - 1)..=(yr + 1) {
1354 let hash: i32 = Self::hash_2d(seed, x_primed, y_primed);
1355 let idx: i32 = hash & (255 << 1);
1356
1357 let vec_x: f32 =
1358 (xi as f32 - x) + lookup::RAND_VECS_2D[idx as usize] * cellular_jitter;
1359 let vec_y: f32 = (yi as f32 - y)
1360 + lookup::RAND_VECS_2D[(idx | 1) as usize] * cellular_jitter;
1361
1362 let new_distance: f32 = vec_x * vec_x + vec_y * vec_y;
1363
1364 distance1 = fast_max(fast_min(distance1, new_distance), distance0);
1365 if new_distance < distance0 {
1366 distance0 = new_distance;
1367 closest_hash = hash;
1368 }
1369 y_primed += Self::PRIME_Y;
1370 }
1371 x_primed += Self::PRIME_X;
1372 }
1373 }
1374 }
1375
1376 if self.cellular_distance_function == CellularDistanceFunction::Euclidean
1377 && self.cellular_return_type >= CellularReturnType::Distance
1378 {
1379 distance0 = fast_sqrt(distance0);
1380
1381 if self.cellular_return_type >= CellularReturnType::Distance2 {
1382 distance1 = fast_sqrt(distance1);
1383 }
1384 }
1385
1386 match self.cellular_return_type {
1387 CellularReturnType::CellValue => closest_hash as f32 * (1.0 / 2147483648.0),
1388 CellularReturnType::Distance => distance0 - 1.0,
1389 CellularReturnType::Distance2 => distance1 - 1.0,
1390 CellularReturnType::Distance2Add => (distance1 + distance0) * 0.5 - 1.0,
1391 CellularReturnType::Distance2Sub => distance1 - distance0 - 1.0,
1392 CellularReturnType::Distance2Mul => distance1 * distance0 * 0.5 - 1.0,
1393 CellularReturnType::Distance2Div => distance0 / distance1 - 1.0,
1394 }
1395 }
1396
1397 fn single_cellular_3d(&self, seed: i32, x: f32, y: f32, z: f32) -> f32 {
1398 let xr: i32 = fast_round(x);
1399 let yr: i32 = fast_round(y);
1400 let zr: i32 = fast_round(z);
1401
1402 let mut distance0: f32 = 1e10;
1403 let mut distance1: f32 = 1e10;
1404 let mut closest_hash: i32 = 0;
1405
1406 let cellular_jitter: f32 = 0.39614353 * self.cellular_jitter_modifier;
1407
1408 let mut x_primed: i32 = (xr - 1) * Self::PRIME_X;
1409 let y_primed_base: i32 = (yr - 1) * Self::PRIME_Y;
1410 let z_primed_base: i32 = (zr - 1) * Self::PRIME_Z;
1411
1412 match self.cellular_distance_function {
1413 CellularDistanceFunction::Euclidean | CellularDistanceFunction::EuclideanSq => {
1414 for xi in (xr - 1)..=(xr + 1) {
1415 let mut y_primed: i32 = y_primed_base;
1416
1417 for yi in (yr - 1)..=(yr + 1) {
1418 let mut z_primed: i32 = z_primed_base;
1419
1420 for zi in (zr - 1)..=(zr + 1) {
1421 let hash: i32 = Self::hash_3d(seed, x_primed, y_primed, z_primed);
1422 let idx: i32 = hash & (255 << 2);
1423
1424 let vec_x: f32 = (xi as f32 - x)
1425 + lookup::RAND_VECS_3D[idx as usize] * cellular_jitter;
1426 let vec_y: f32 = (yi as f32 - y)
1427 + lookup::RAND_VECS_3D[(idx | 1) as usize] * cellular_jitter;
1428 let vec_z: f32 = (zi as f32 - z)
1429 + lookup::RAND_VECS_3D[(idx | 2) as usize] * cellular_jitter;
1430
1431 let new_distance: f32 = vec_x * vec_x + vec_y * vec_y + vec_z * vec_z;
1432
1433 distance1 = fast_max(fast_min(distance1, new_distance), distance0);
1434 if new_distance < distance0 {
1435 distance0 = new_distance;
1436 closest_hash = hash;
1437 }
1438 z_primed += Self::PRIME_Z;
1439 }
1440 y_primed += Self::PRIME_Y;
1441 }
1442 x_primed += Self::PRIME_X;
1443 }
1444 }
1445 CellularDistanceFunction::Manhattan => {
1446 for xi in (xr - 1)..=(xr + 1) {
1447 let mut y_primed: i32 = y_primed_base;
1448
1449 for yi in (yr - 1)..=(yr + 1) {
1450 let mut z_primed: i32 = z_primed_base;
1451
1452 for zi in (zr - 1)..=(zr + 1) {
1453 let hash: i32 = Self::hash_3d(seed, x_primed, y_primed, z_primed);
1454 let idx: i32 = hash & (255 << 2);
1455
1456 let vec_x: f32 = (xi as f32 - x)
1457 + lookup::RAND_VECS_3D[idx as usize] * cellular_jitter;
1458 let vec_y: f32 = (yi as f32 - y)
1459 + lookup::RAND_VECS_3D[(idx | 1) as usize] * cellular_jitter;
1460 let vec_z: f32 = (zi as f32 - z)
1461 + lookup::RAND_VECS_3D[(idx | 2) as usize] * cellular_jitter;
1462
1463 let new_distance: f32 =
1464 fast_abs(vec_x) + fast_abs(vec_y) + fast_abs(vec_z);
1465
1466 distance1 = fast_max(fast_min(distance1, new_distance), distance0);
1467 if new_distance < distance0 {
1468 distance0 = new_distance;
1469 closest_hash = hash;
1470 }
1471 z_primed += Self::PRIME_Z;
1472 }
1473 y_primed += Self::PRIME_Y;
1474 }
1475 x_primed += Self::PRIME_X;
1476 }
1477 }
1478 CellularDistanceFunction::Hybrid => {
1479 for xi in (xr - 1)..=(xr + 1) {
1480 let mut y_primed: i32 = y_primed_base;
1481
1482 for yi in (yr - 1)..=(yr + 1) {
1483 let mut z_primed: i32 = z_primed_base;
1484
1485 for zi in (zr - 1)..=(zr + 1) {
1486 let hash: i32 = Self::hash_3d(seed, x_primed, y_primed, z_primed);
1487 let idx: i32 = hash & (255 << 2);
1488
1489 let vec_x: f32 = (xi as f32 - x)
1490 + lookup::RAND_VECS_3D[idx as usize] * cellular_jitter;
1491 let vec_y: f32 = (yi as f32 - y)
1492 + lookup::RAND_VECS_3D[(idx | 1) as usize] * cellular_jitter;
1493 let vec_z: f32 = (zi as f32 - z)
1494 + lookup::RAND_VECS_3D[(idx | 2) as usize] * cellular_jitter;
1495
1496 let new_distance: f32 =
1497 (fast_abs(vec_x) + fast_abs(vec_y) + fast_abs(vec_z))
1498 + (vec_x * vec_x + vec_y * vec_y + vec_z * vec_z);
1499
1500 distance1 = fast_max(fast_min(distance1, new_distance), distance0);
1501 if new_distance < distance0 {
1502 distance0 = new_distance;
1503 closest_hash = hash;
1504 }
1505 z_primed += Self::PRIME_Z;
1506 }
1507 y_primed += Self::PRIME_Y;
1508 }
1509 x_primed += Self::PRIME_X;
1510 }
1511 }
1512 };
1513
1514 if self.cellular_distance_function == CellularDistanceFunction::Euclidean
1515 && self.cellular_return_type >= CellularReturnType::Distance
1516 {
1517 distance0 = fast_sqrt(distance0);
1518
1519 if self.cellular_return_type >= CellularReturnType::Distance2 {
1520 distance1 = fast_sqrt(distance1);
1521 }
1522 }
1523
1524 match self.cellular_return_type {
1525 CellularReturnType::CellValue => closest_hash as f32 * (1.0 / 2147483648.0),
1526 CellularReturnType::Distance => distance0 - 1.0,
1527 CellularReturnType::Distance2 => distance1 - 1.0,
1528 CellularReturnType::Distance2Add => (distance1 + distance0) * 0.5 - 1.0,
1529 CellularReturnType::Distance2Sub => distance1 - distance0 - 1.0,
1530 CellularReturnType::Distance2Mul => distance1 * distance0 * 0.5 - 1.0,
1531 CellularReturnType::Distance2Div => distance0 / distance1 - 1.0,
1532 }
1533 }
1534
1535 fn single_perlin_2d(&self, seed: i32, x: f32, y: f32) -> f32 {
1536 let mut x0: i32 = fast_floor(x);
1537 let mut y0: i32 = fast_floor(y);
1538
1539 let xd0: f32 = x - x0 as f32;
1540 let yd0: f32 = y - y0 as f32;
1541 let xd1: f32 = xd0 - 1.0;
1542 let yd1: f32 = yd0 - 1.0;
1543
1544 let xs: f32 = interp_quintic(xd0);
1545 let ys: f32 = interp_quintic(yd0);
1546
1547 x0 *= Self::PRIME_X;
1548 y0 *= Self::PRIME_Y;
1549 let x1: i32 = x0.wrapping_add(Self::PRIME_X);
1550 let y1: i32 = y0.wrapping_add(Self::PRIME_Y);
1551
1552 let xf0: f32 = lerp(
1553 Self::grad_coord_2d(seed, x0, y0, xd0, yd0),
1554 Self::grad_coord_2d(seed, x1, y0, xd1, yd0),
1555 xs,
1556 );
1557 let xf1: f32 = lerp(
1558 Self::grad_coord_2d(seed, x0, y1, xd0, yd1),
1559 Self::grad_coord_2d(seed, x1, y1, xd1, yd1),
1560 xs,
1561 );
1562
1563 return lerp(xf0, xf1, ys) * 1.4247691104677813;
1564 }
1565
1566 fn single_perlin_3d(&self, seed: i32, x: f32, y: f32, z: f32) -> f32 {
1567 let mut x0: i32 = fast_floor(x);
1568 let mut y0: i32 = fast_floor(y);
1569 let mut z0: i32 = fast_floor(z);
1570
1571 let xd0: f32 = x - x0 as f32;
1572 let yd0: f32 = y - y0 as f32;
1573 let zd0: f32 = z - z0 as f32;
1574 let xd1: f32 = xd0 - 1.0;
1575 let yd1: f32 = yd0 - 1.0;
1576 let zd1: f32 = zd0 - 1.0;
1577
1578 let xs: f32 = interp_quintic(xd0);
1579 let ys: f32 = interp_quintic(yd0);
1580 let zs: f32 = interp_quintic(zd0);
1581
1582 x0 *= Self::PRIME_X;
1583 y0 *= Self::PRIME_Y;
1584 z0 *= Self::PRIME_Z;
1585 let x1: i32 = x0.wrapping_add(Self::PRIME_X);
1586 let y1: i32 = y0.wrapping_add(Self::PRIME_Y);
1587 let z1: i32 = z0.wrapping_add(Self::PRIME_Z);
1588
1589 let xf00: f32 = lerp(
1590 Self::grad_coord_3d(seed, x0, y0, z0, xd0, yd0, zd0),
1591 Self::grad_coord_3d(seed, x1, y0, z0, xd1, yd0, zd0),
1592 xs,
1593 );
1594 let xf10: f32 = lerp(
1595 Self::grad_coord_3d(seed, x0, y1, z0, xd0, yd1, zd0),
1596 Self::grad_coord_3d(seed, x1, y1, z0, xd1, yd1, zd0),
1597 xs,
1598 );
1599 let xf01: f32 = lerp(
1600 Self::grad_coord_3d(seed, x0, y0, z1, xd0, yd0, zd1),
1601 Self::grad_coord_3d(seed, x1, y0, z1, xd1, yd0, zd1),
1602 xs,
1603 );
1604 let xf11: f32 = lerp(
1605 Self::grad_coord_3d(seed, x0, y1, z1, xd0, yd1, zd1),
1606 Self::grad_coord_3d(seed, x1, y1, z1, xd1, yd1, zd1),
1607 xs,
1608 );
1609
1610 let yf0: f32 = lerp(xf00, xf10, ys);
1611 let yf1: f32 = lerp(xf01, xf11, ys);
1612
1613 return lerp(yf0, yf1, zs) * 0.964921414852142333984375;
1614 }
1615
1616 fn single_value_cubic_2d(&self, seed: i32, x: f32, y: f32) -> f32 {
1617 let mut x1: i32 = fast_floor(x);
1618 let mut y1: i32 = fast_floor(y);
1619
1620 let xs: f32 = x - x1 as f32;
1621 let ys: f32 = y - y1 as f32;
1622
1623 x1 *= Self::PRIME_X;
1624 y1 *= Self::PRIME_Y;
1625 let x0: i32 = x1.wrapping_sub(Self::PRIME_X);
1626 let y0: i32 = y1.wrapping_sub(Self::PRIME_Y);
1627 let x2: i32 = x1.wrapping_add(Self::PRIME_X);
1628 let y2: i32 = y1.wrapping_add(Self::PRIME_Y);
1629 let x3: i32 = x1 + ((Self::PRIME_X as i64) << 1) as i32;
1630 let y3: i32 = y1 + ((Self::PRIME_Y as i64) << 1) as i32;
1631
1632 return cubic_lerp(
1633 cubic_lerp(
1634 Self::val_coord_2d(seed, x0, y0),
1635 Self::val_coord_2d(seed, x1, y0),
1636 Self::val_coord_2d(seed, x2, y0),
1637 Self::val_coord_2d(seed, x3, y0),
1638 xs,
1639 ),
1640 cubic_lerp(
1641 Self::val_coord_2d(seed, x0, y1),
1642 Self::val_coord_2d(seed, x1, y1),
1643 Self::val_coord_2d(seed, x2, y1),
1644 Self::val_coord_2d(seed, x3, y1),
1645 xs,
1646 ),
1647 cubic_lerp(
1648 Self::val_coord_2d(seed, x0, y2),
1649 Self::val_coord_2d(seed, x1, y2),
1650 Self::val_coord_2d(seed, x2, y2),
1651 Self::val_coord_2d(seed, x3, y2),
1652 xs,
1653 ),
1654 cubic_lerp(
1655 Self::val_coord_2d(seed, x0, y3),
1656 Self::val_coord_2d(seed, x1, y3),
1657 Self::val_coord_2d(seed, x2, y3),
1658 Self::val_coord_2d(seed, x3, y3),
1659 xs,
1660 ),
1661 ys,
1662 ) * (1.0 / (1.5 * 1.5));
1663 }
1664
1665 fn single_value_cubic_3d(&self, seed: i32, x: f32, y: f32, z: f32) -> f32 {
1666 let mut x1: i32 = fast_floor(x);
1667 let mut y1: i32 = fast_floor(y);
1668 let mut z1: i32 = fast_floor(z);
1669
1670 let xs: f32 = x - x1 as f32;
1671 let ys: f32 = y - y1 as f32;
1672 let zs: f32 = z - z1 as f32;
1673
1674 x1 *= Self::PRIME_X;
1675 y1 *= Self::PRIME_Y;
1676 z1 *= Self::PRIME_Z;
1677
1678 let x0: i32 = x1.wrapping_sub(Self::PRIME_X);
1679 let y0: i32 = y1.wrapping_sub(Self::PRIME_Y);
1680 let z0: i32 = z1.wrapping_sub(Self::PRIME_Z);
1681 let x2: i32 = x1.wrapping_add(Self::PRIME_X);
1682 let y2: i32 = y1.wrapping_add(Self::PRIME_Y);
1683 let z2: i32 = z1.wrapping_add(Self::PRIME_Z);
1684 let x3: i32 = x1 + ((Self::PRIME_X as i64) << 1) as i32;
1685 let y3: i32 = y1 + ((Self::PRIME_Y as i64) << 1) as i32;
1686 let z3: i32 = z1 + ((Self::PRIME_Z as i64) << 1) as i32;
1687
1688 return cubic_lerp(
1689 cubic_lerp(
1690 cubic_lerp(
1691 Self::val_coord_3d(seed, x0, y0, z0),
1692 Self::val_coord_3d(seed, x1, y0, z0),
1693 Self::val_coord_3d(seed, x2, y0, z0),
1694 Self::val_coord_3d(seed, x3, y0, z0),
1695 xs,
1696 ),
1697 cubic_lerp(
1698 Self::val_coord_3d(seed, x0, y1, z0),
1699 Self::val_coord_3d(seed, x1, y1, z0),
1700 Self::val_coord_3d(seed, x2, y1, z0),
1701 Self::val_coord_3d(seed, x3, y1, z0),
1702 xs,
1703 ),
1704 cubic_lerp(
1705 Self::val_coord_3d(seed, x0, y2, z0),
1706 Self::val_coord_3d(seed, x1, y2, z0),
1707 Self::val_coord_3d(seed, x2, y2, z0),
1708 Self::val_coord_3d(seed, x3, y2, z0),
1709 xs,
1710 ),
1711 cubic_lerp(
1712 Self::val_coord_3d(seed, x0, y3, z0),
1713 Self::val_coord_3d(seed, x1, y3, z0),
1714 Self::val_coord_3d(seed, x2, y3, z0),
1715 Self::val_coord_3d(seed, x3, y3, z0),
1716 xs,
1717 ),
1718 ys,
1719 ),
1720 cubic_lerp(
1721 cubic_lerp(
1722 Self::val_coord_3d(seed, x0, y0, z1),
1723 Self::val_coord_3d(seed, x1, y0, z1),
1724 Self::val_coord_3d(seed, x2, y0, z1),
1725 Self::val_coord_3d(seed, x3, y0, z1),
1726 xs,
1727 ),
1728 cubic_lerp(
1729 Self::val_coord_3d(seed, x0, y1, z1),
1730 Self::val_coord_3d(seed, x1, y1, z1),
1731 Self::val_coord_3d(seed, x2, y1, z1),
1732 Self::val_coord_3d(seed, x3, y1, z1),
1733 xs,
1734 ),
1735 cubic_lerp(
1736 Self::val_coord_3d(seed, x0, y2, z1),
1737 Self::val_coord_3d(seed, x1, y2, z1),
1738 Self::val_coord_3d(seed, x2, y2, z1),
1739 Self::val_coord_3d(seed, x3, y2, z1),
1740 xs,
1741 ),
1742 cubic_lerp(
1743 Self::val_coord_3d(seed, x0, y3, z1),
1744 Self::val_coord_3d(seed, x1, y3, z1),
1745 Self::val_coord_3d(seed, x2, y3, z1),
1746 Self::val_coord_3d(seed, x3, y3, z1),
1747 xs,
1748 ),
1749 ys,
1750 ),
1751 cubic_lerp(
1752 cubic_lerp(
1753 Self::val_coord_3d(seed, x0, y0, z2),
1754 Self::val_coord_3d(seed, x1, y0, z2),
1755 Self::val_coord_3d(seed, x2, y0, z2),
1756 Self::val_coord_3d(seed, x3, y0, z2),
1757 xs,
1758 ),
1759 cubic_lerp(
1760 Self::val_coord_3d(seed, x0, y1, z2),
1761 Self::val_coord_3d(seed, x1, y1, z2),
1762 Self::val_coord_3d(seed, x2, y1, z2),
1763 Self::val_coord_3d(seed, x3, y1, z2),
1764 xs,
1765 ),
1766 cubic_lerp(
1767 Self::val_coord_3d(seed, x0, y2, z2),
1768 Self::val_coord_3d(seed, x1, y2, z2),
1769 Self::val_coord_3d(seed, x2, y2, z2),
1770 Self::val_coord_3d(seed, x3, y2, z2),
1771 xs,
1772 ),
1773 cubic_lerp(
1774 Self::val_coord_3d(seed, x0, y3, z2),
1775 Self::val_coord_3d(seed, x1, y3, z2),
1776 Self::val_coord_3d(seed, x2, y3, z2),
1777 Self::val_coord_3d(seed, x3, y3, z2),
1778 xs,
1779 ),
1780 ys,
1781 ),
1782 cubic_lerp(
1783 cubic_lerp(
1784 Self::val_coord_3d(seed, x0, y0, z3),
1785 Self::val_coord_3d(seed, x1, y0, z3),
1786 Self::val_coord_3d(seed, x2, y0, z3),
1787 Self::val_coord_3d(seed, x3, y0, z3),
1788 xs,
1789 ),
1790 cubic_lerp(
1791 Self::val_coord_3d(seed, x0, y1, z3),
1792 Self::val_coord_3d(seed, x1, y1, z3),
1793 Self::val_coord_3d(seed, x2, y1, z3),
1794 Self::val_coord_3d(seed, x3, y1, z3),
1795 xs,
1796 ),
1797 cubic_lerp(
1798 Self::val_coord_3d(seed, x0, y2, z3),
1799 Self::val_coord_3d(seed, x1, y2, z3),
1800 Self::val_coord_3d(seed, x2, y2, z3),
1801 Self::val_coord_3d(seed, x3, y2, z3),
1802 xs,
1803 ),
1804 cubic_lerp(
1805 Self::val_coord_3d(seed, x0, y3, z3),
1806 Self::val_coord_3d(seed, x1, y3, z3),
1807 Self::val_coord_3d(seed, x2, y3, z3),
1808 Self::val_coord_3d(seed, x3, y3, z3),
1809 xs,
1810 ),
1811 ys,
1812 ),
1813 zs,
1814 ) * (1.0 / (1.5 * 1.5 * 1.5));
1815 }
1816
1817 fn single_value_2d(&self, seed: i32, x: f32, y: f32) -> f32 {
1818 let mut x0: i32 = fast_floor(x);
1819 let mut y0: i32 = fast_floor(y);
1820
1821 let xs: f32 = interp_hermite(x - x0 as f32);
1822 let ys: f32 = interp_hermite(y - y0 as f32);
1823
1824 x0 *= Self::PRIME_X;
1825 y0 *= Self::PRIME_Y;
1826 let x1: i32 = x0.wrapping_add(Self::PRIME_X);
1827 let y1: i32 = y0.wrapping_add(Self::PRIME_Y);
1828
1829 let xf0: f32 = lerp(
1830 Self::val_coord_2d(seed, x0, y0),
1831 Self::val_coord_2d(seed, x1, y0),
1832 xs,
1833 );
1834 let xf1: f32 = lerp(
1835 Self::val_coord_2d(seed, x0, y1),
1836 Self::val_coord_2d(seed, x1, y1),
1837 xs,
1838 );
1839
1840 return lerp(xf0, xf1, ys);
1841 }
1842
1843 fn single_value_3d(&self, seed: i32, x: f32, y: f32, z: f32) -> f32 {
1844 let mut x0: i32 = fast_floor(x);
1845 let mut y0: i32 = fast_floor(y);
1846 let mut z0: i32 = fast_floor(z);
1847
1848 let xs: f32 = interp_hermite(x - x0 as f32);
1849 let ys: f32 = interp_hermite(y - y0 as f32);
1850 let zs: f32 = interp_hermite(z - z0 as f32);
1851
1852 x0 *= Self::PRIME_X;
1853 y0 *= Self::PRIME_Y;
1854 z0 *= Self::PRIME_Z;
1855 let x1: i32 = x0.wrapping_add(Self::PRIME_X);
1856 let y1: i32 = y0.wrapping_add(Self::PRIME_Y);
1857 let z1: i32 = z0.wrapping_add(Self::PRIME_Z);
1858
1859 let xf00: f32 = lerp(
1860 Self::val_coord_3d(seed, x0, y0, z0),
1861 Self::val_coord_3d(seed, x1, y0, z0),
1862 xs,
1863 );
1864 let xf10: f32 = lerp(
1865 Self::val_coord_3d(seed, x0, y1, z0),
1866 Self::val_coord_3d(seed, x1, y1, z0),
1867 xs,
1868 );
1869 let xf01: f32 = lerp(
1870 Self::val_coord_3d(seed, x0, y0, z1),
1871 Self::val_coord_3d(seed, x1, y0, z1),
1872 xs,
1873 );
1874 let xf11: f32 = lerp(
1875 Self::val_coord_3d(seed, x0, y1, z1),
1876 Self::val_coord_3d(seed, x1, y1, z1),
1877 xs,
1878 );
1879
1880 let yf0: f32 = lerp(xf00, xf10, ys);
1881 let yf1: f32 = lerp(xf01, xf11, ys);
1882
1883 return lerp(yf0, yf1, zs);
1884 }
1885
1886 fn do_single_domain_warp_2d(
1887 &self,
1888 seed: i32,
1889 amp: f32,
1890 freq: f32,
1891 x: f32,
1892 y: f32,
1893 xr: &mut f32,
1894 yr: &mut f32,
1895 ) {
1896 match self.domain_warp_type {
1897 DomainWarpType::OpenSimplex2 => self.single_domain_warp_simplex_gradient_2d(
1898 seed,
1899 amp * 38.283687591552734375,
1900 freq,
1901 x,
1902 y,
1903 xr,
1904 yr,
1905 false,
1906 ),
1907 DomainWarpType::OpenSimplex2Reduced => self.single_domain_warp_simplex_gradient_2d(
1908 seed,
1909 amp * 16.0,
1910 freq,
1911 x,
1912 y,
1913 xr,
1914 yr,
1915 true,
1916 ),
1917 DomainWarpType::BasicGrid => {
1918 self.single_domain_warp_basic_grid_2d(seed, amp, freq, x, y, xr, yr)
1919 }
1920 }
1921 }
1922
1923 fn do_single_domain_warp_3d(
1924 &self,
1925 seed: i32,
1926 amp: f32,
1927 freq: f32,
1928 x: f32,
1929 y: f32,
1930 z: f32,
1931 xr: &mut f32,
1932 yr: &mut f32,
1933 zr: &mut f32,
1934 ) {
1935 match self.domain_warp_type {
1936 DomainWarpType::OpenSimplex2 => self.single_domain_warp_open_simplex2_gradient_3d(
1937 seed,
1938 amp * 32.69428253173828125,
1939 freq,
1940 x,
1941 y,
1942 z,
1943 xr,
1944 yr,
1945 zr,
1946 false,
1947 ),
1948 DomainWarpType::OpenSimplex2Reduced => self
1949 .single_domain_warp_open_simplex2_gradient_3d(
1950 seed,
1951 amp * 7.71604938271605,
1952 freq,
1953 x,
1954 y,
1955 z,
1956 xr,
1957 yr,
1958 zr,
1959 true,
1960 ),
1961 DomainWarpType::BasicGrid => {
1962 self.single_domain_warp_basic_grid_3d(seed, amp, freq, x, y, z, xr, yr, zr)
1963 }
1964 }
1965 }
1966
1967 fn domain_warp_single_2d(&self, x: &mut f32, y: &mut f32) {
1968 let seed: i32 = self.seed;
1969 let amp: f32 = self.domain_warp_amp * self.fractal_bounding;
1970 let freq: f32 = self.frequency;
1971
1972 let mut xs: f32 = *x;
1973 let mut ys: f32 = *y;
1974 self.transform_domain_warp_coordinate_2d(&mut xs, &mut ys);
1975
1976 self.do_single_domain_warp_2d(seed, amp, freq, xs, ys, x, y);
1977 }
1978
1979 fn domain_warp_single_3d(&self, x: &mut f32, y: &mut f32, z: &mut f32) {
1980 let seed: i32 = self.seed;
1981 let amp: f32 = self.domain_warp_amp * self.fractal_bounding;
1982 let freq: f32 = self.frequency;
1983
1984 let mut xs: f32 = *x;
1985 let mut ys: f32 = *y;
1986 let mut zs: f32 = *z;
1987 self.transform_domain_warp_coordinate_3d(&mut xs, &mut ys, &mut zs);
1988
1989 self.do_single_domain_warp_3d(seed, amp, freq, xs, ys, zs, x, y, z);
1990 }
1991
1992 fn domain_warp_fractal_progressive_2d(&self, x: &mut f32, y: &mut f32) {
1993 let mut seed: i32 = self.seed;
1994 let mut amp: f32 = self.domain_warp_amp * self.fractal_bounding;
1995 let mut freq: f32 = self.frequency;
1996
1997 for _ in 0..self.octaves {
1998 let mut xs: f32 = *x;
1999 let mut ys: f32 = *y;
2000 self.transform_domain_warp_coordinate_2d(&mut xs, &mut ys);
2001
2002 self.do_single_domain_warp_2d(seed, amp, freq, xs, ys, x, y);
2003
2004 seed += 1;
2005 amp *= self.gain;
2006 freq *= self.lacunarity;
2007 }
2008 }
2009
2010 fn domain_warp_fractal_progressive_3d(&self, x: &mut f32, y: &mut f32, z: &mut f32) {
2011 let mut seed: i32 = self.seed;
2012 let mut amp: f32 = self.domain_warp_amp * self.fractal_bounding;
2013 let mut freq: f32 = self.frequency;
2014
2015 for _ in 0..self.octaves {
2016 let mut xs: f32 = *x;
2017 let mut ys: f32 = *y;
2018 let mut zs: f32 = *z;
2019 self.transform_domain_warp_coordinate_3d(&mut xs, &mut ys, &mut zs);
2020
2021 self.do_single_domain_warp_3d(seed, amp, freq, xs, ys, zs, x, y, z);
2022
2023 seed += 1;
2024 amp *= self.gain;
2025 freq *= self.lacunarity;
2026 }
2027 }
2028
2029 fn domain_warp_fractal_independent_2d(&self, x: &mut f32, y: &mut f32) {
2030 let mut xs: f32 = *x;
2031 let mut ys: f32 = *y;
2032 self.transform_domain_warp_coordinate_2d(&mut xs, &mut ys);
2033
2034 let mut seed: i32 = self.seed;
2035 let mut amp: f32 = self.domain_warp_amp * self.fractal_bounding;
2036 let mut freq: f32 = self.frequency;
2037
2038 for _ in 0..self.octaves {
2039 self.do_single_domain_warp_2d(seed, amp, freq, xs, ys, x, y);
2040
2041 seed += 1;
2042 amp *= self.gain;
2043 freq *= self.lacunarity;
2044 }
2045 }
2046
2047 fn domain_warp_fractal_independent_3d(&self, x: &mut f32, y: &mut f32, z: &mut f32) {
2048 let mut xs: f32 = *x;
2049 let mut ys: f32 = *y;
2050 let mut zs: f32 = *z;
2051 self.transform_domain_warp_coordinate_3d(&mut xs, &mut ys, &mut zs);
2052
2053 let mut seed: i32 = self.seed;
2054 let mut amp: f32 = self.domain_warp_amp * self.fractal_bounding;
2055 let mut freq: f32 = self.frequency;
2056
2057 for _ in 0..self.octaves {
2058 self.do_single_domain_warp_3d(seed, amp, freq, xs, ys, zs, x, y, z);
2059
2060 seed += 1;
2061 amp *= self.gain;
2062 freq *= self.lacunarity;
2063 }
2064 }
2065
2066 fn single_domain_warp_basic_grid_2d(
2067 &self,
2068 seed: i32,
2069 warp_amp: f32,
2070 frequency: f32,
2071 x: f32,
2072 y: f32,
2073 xr: &mut f32,
2074 yr: &mut f32,
2075 ) {
2076 let xf: f32 = x * frequency;
2077 let yf: f32 = y * frequency;
2078
2079 let mut x0: i32 = fast_floor(xf);
2080 let mut y0: i32 = fast_floor(yf);
2081
2082 let xs: f32 = interp_hermite(xf - x0 as f32);
2083 let ys: f32 = interp_hermite(yf - y0 as f32);
2084
2085 x0 *= Self::PRIME_X;
2086 y0 *= Self::PRIME_Y;
2087 let x1: i32 = x0.wrapping_add(Self::PRIME_X);
2088 let y1: i32 = y0.wrapping_add(Self::PRIME_Y);
2089
2090 let mut hash0: i32 = Self::hash_2d(seed, x0, y0) & (255 << 1);
2091 let mut hash1: i32 = Self::hash_2d(seed, x1, y0) & (255 << 1);
2092
2093 let lx0x: f32 = lerp(
2094 lookup::RAND_VECS_2D[hash0 as usize],
2095 lookup::RAND_VECS_2D[hash1 as usize],
2096 xs,
2097 );
2098 let ly0x: f32 = lerp(
2099 lookup::RAND_VECS_2D[(hash0 | 1) as usize],
2100 lookup::RAND_VECS_2D[(hash1 | 1) as usize],
2101 xs,
2102 );
2103
2104 hash0 = Self::hash_2d(seed, x0, y1) & (255 << 1);
2105 hash1 = Self::hash_2d(seed, x1, y1) & (255 << 1);
2106
2107 let lx1x: f32 = lerp(
2108 lookup::RAND_VECS_2D[hash0 as usize],
2109 lookup::RAND_VECS_2D[hash1 as usize],
2110 xs,
2111 );
2112 let ly1x: f32 = lerp(
2113 lookup::RAND_VECS_2D[(hash0 | 1) as usize],
2114 lookup::RAND_VECS_2D[(hash1 | 1) as usize],
2115 xs,
2116 );
2117
2118 *xr += lerp(lx0x, lx1x, ys) * warp_amp;
2119 *yr += lerp(ly0x, ly1x, ys) * warp_amp;
2120 }
2121
2122 fn single_domain_warp_basic_grid_3d(
2123 &self,
2124 seed: i32,
2125 warp_amp: f32,
2126 frequency: f32,
2127 x: f32,
2128 y: f32,
2129 z: f32,
2130 xr: &mut f32,
2131 yr: &mut f32,
2132 zr: &mut f32,
2133 ) {
2134 let xf: f32 = x * frequency;
2135 let yf: f32 = y * frequency;
2136 let zf: f32 = z * frequency;
2137
2138 let mut x0: i32 = fast_floor(xf);
2139 let mut y0: i32 = fast_floor(yf);
2140 let mut z0: i32 = fast_floor(zf);
2141
2142 let xs: f32 = interp_hermite(xf - x0 as f32);
2143 let ys: f32 = interp_hermite(yf - y0 as f32);
2144 let zs: f32 = interp_hermite(zf - z0 as f32);
2145
2146 x0 *= Self::PRIME_X;
2147 y0 *= Self::PRIME_Y;
2148 z0 *= Self::PRIME_Z;
2149 let x1: i32 = x0.wrapping_add(Self::PRIME_X);
2150 let y1: i32 = y0.wrapping_add(Self::PRIME_Y);
2151 let z1: i32 = z0.wrapping_add(Self::PRIME_Z);
2152
2153 let mut hash0: i32 = Self::hash_3d(seed, x0, y0, z0) & (255 << 2);
2154 let mut hash1: i32 = Self::hash_3d(seed, x1, y0, z0) & (255 << 2);
2155
2156 let mut lx0x: f32 = lerp(
2157 lookup::RAND_VECS_3D[hash0 as usize],
2158 lookup::RAND_VECS_3D[hash1 as usize],
2159 xs,
2160 );
2161 let mut ly0x: f32 = lerp(
2162 lookup::RAND_VECS_3D[(hash0 | 1) as usize],
2163 lookup::RAND_VECS_3D[(hash1 | 1) as usize],
2164 xs,
2165 );
2166 let mut lz0x: f32 = lerp(
2167 lookup::RAND_VECS_3D[(hash0 | 2) as usize],
2168 lookup::RAND_VECS_3D[(hash1 | 2) as usize],
2169 xs,
2170 );
2171
2172 hash0 = Self::hash_3d(seed, x0, y1, z0) & (255 << 2);
2173 hash1 = Self::hash_3d(seed, x1, y1, z0) & (255 << 2);
2174
2175 let mut lx1x: f32 = lerp(
2176 lookup::RAND_VECS_3D[hash0 as usize],
2177 lookup::RAND_VECS_3D[hash1 as usize],
2178 xs,
2179 );
2180 let mut ly1x: f32 = lerp(
2181 lookup::RAND_VECS_3D[(hash0 | 1) as usize],
2182 lookup::RAND_VECS_3D[(hash1 | 1) as usize],
2183 xs,
2184 );
2185 let mut lz1x: f32 = lerp(
2186 lookup::RAND_VECS_3D[(hash0 | 2) as usize],
2187 lookup::RAND_VECS_3D[(hash1 | 2) as usize],
2188 xs,
2189 );
2190
2191 let lx0y: f32 = lerp(lx0x, lx1x, ys);
2192 let ly0y: f32 = lerp(ly0x, ly1x, ys);
2193 let lz0y: f32 = lerp(lz0x, lz1x, ys);
2194
2195 hash0 = Self::hash_3d(seed, x0, y0, z1) & (255 << 2);
2196 hash1 = Self::hash_3d(seed, x1, y0, z1) & (255 << 2);
2197
2198 lx0x = lerp(
2199 lookup::RAND_VECS_3D[hash0 as usize],
2200 lookup::RAND_VECS_3D[hash1 as usize],
2201 xs,
2202 );
2203 ly0x = lerp(
2204 lookup::RAND_VECS_3D[(hash0 | 1) as usize],
2205 lookup::RAND_VECS_3D[(hash1 | 1) as usize],
2206 xs,
2207 );
2208 lz0x = lerp(
2209 lookup::RAND_VECS_3D[(hash0 | 2) as usize],
2210 lookup::RAND_VECS_3D[(hash1 | 2) as usize],
2211 xs,
2212 );
2213
2214 hash0 = Self::hash_3d(seed, x0, y1, z1) & (255 << 2);
2215 hash1 = Self::hash_3d(seed, x1, y1, z1) & (255 << 2);
2216
2217 lx1x = lerp(
2218 lookup::RAND_VECS_3D[hash0 as usize],
2219 lookup::RAND_VECS_3D[hash1 as usize],
2220 xs,
2221 );
2222 ly1x = lerp(
2223 lookup::RAND_VECS_3D[(hash0 | 1) as usize],
2224 lookup::RAND_VECS_3D[(hash1 | 1) as usize],
2225 xs,
2226 );
2227 lz1x = lerp(
2228 lookup::RAND_VECS_3D[(hash0 | 2) as usize],
2229 lookup::RAND_VECS_3D[(hash1 | 2) as usize],
2230 xs,
2231 );
2232
2233 *xr += lerp(lx0y, lerp(lx0x, lx1x, ys), zs) * warp_amp;
2234 *yr += lerp(ly0y, lerp(ly0x, ly1x, ys), zs) * warp_amp;
2235 *zr += lerp(lz0y, lerp(lz0x, lz1x, ys), zs) * warp_amp;
2236 }
2237
2238 fn single_domain_warp_simplex_gradient_2d(
2239 &self,
2240 seed: i32,
2241 warp_amp: f32,
2242 frequency: f32,
2243 mut x: f32,
2244 mut y: f32,
2245 xr: &mut f32,
2246 yr: &mut f32,
2247 out_grad_only: bool,
2248 ) {
2249 const SQRT3: f32 = 1.7320508075688772935274463415059;
2250 const G2: f32 = (3.0 - SQRT3) / 6.0;
2251
2252 x *= frequency;
2253 y *= frequency;
2254
2255 let mut i: i32 = fast_floor(x);
2263 let mut j: i32 = fast_floor(y);
2264 let xi: f32 = x - i as f32;
2265 let yi: f32 = y - j as f32;
2266
2267 let t: f32 = (xi + yi) * G2;
2268 let x0: f32 = xi - t;
2269 let y0: f32 = yi - t;
2270
2271 i = i.wrapping_mul(Self::PRIME_X);
2272 j = j.wrapping_mul(Self::PRIME_Y);
2273
2274 let mut vx: f32 = 0.0;
2275 let mut vy: f32 = 0.0;
2276
2277 let a: f32 = 0.5 - x0 * x0 - y0 * y0;
2278 if a > 0.0 {
2279 let aaaa: f32 = (a * a) * (a * a);
2280 let mut xo: f32 = 0.0;
2281 let mut yo: f32 = 0.0;
2282 if out_grad_only {
2283 Self::grad_coord_out_2d(seed, i, j, &mut xo, &mut yo);
2284 } else {
2285 Self::grad_coord_dual_2d(seed, i, j, x0, y0, &mut xo, &mut yo);
2286 }
2287 vx += aaaa * xo;
2288 vy += aaaa * yo;
2289 }
2290
2291 let c: f32 = (2.0 * (1.0 - 2.0 * G2) * (1.0 / G2 - 2.0)) * t
2292 + ((-2.0 * (1.0 - 2.0 * G2) * (1.0 - 2.0 * G2)) + a);
2293 if c > 0.0 {
2294 let x2: f32 = x0 + (2.0 * G2 - 1.0);
2295 let y2: f32 = y0 + (2.0 * G2 - 1.0);
2296 let cccc: f32 = (c * c) * (c * c);
2297 let mut xo: f32 = 0.0;
2298 let mut yo: f32 = 0.0;
2299 if out_grad_only {
2300 Self::grad_coord_out_2d(
2301 seed,
2302 i.wrapping_add(Self::PRIME_X),
2303 j.wrapping_add(Self::PRIME_Y),
2304 &mut xo,
2305 &mut yo,
2306 );
2307 } else {
2308 Self::grad_coord_dual_2d(
2309 seed,
2310 i.wrapping_add(Self::PRIME_X),
2311 j.wrapping_add(Self::PRIME_Y),
2312 x2,
2313 y2,
2314 &mut xo,
2315 &mut yo,
2316 );
2317 }
2318 vx += cccc * xo;
2319 vy += cccc * yo;
2320 }
2321
2322 if y0 > x0 {
2323 let x1: f32 = x0 + G2;
2324 let y1: f32 = y0 + (G2 - 1.0);
2325 let b: f32 = 0.5 - x1 * x1 - y1 * y1;
2326 if b > 0.0 {
2327 let bbbb: f32 = (b * b) * (b * b);
2328 let mut xo: f32 = 0.0;
2329 let mut yo: f32 = 0.0;
2330 if out_grad_only {
2331 Self::grad_coord_out_2d(
2332 seed,
2333 i,
2334 j.wrapping_add(Self::PRIME_Y),
2335 &mut xo,
2336 &mut yo,
2337 );
2338 } else {
2339 Self::grad_coord_dual_2d(
2340 seed,
2341 i,
2342 j.wrapping_add(Self::PRIME_Y),
2343 x1,
2344 y1,
2345 &mut xo,
2346 &mut yo,
2347 );
2348 }
2349 vx += bbbb * xo;
2350 vy += bbbb * yo;
2351 }
2352 } else {
2353 let x1: f32 = x0 + (G2 - 1.0);
2354 let y1: f32 = y0 + G2;
2355 let b: f32 = 0.5 - x1 * x1 - y1 * y1;
2356 if b > 0.0 {
2357 let bbbb: f32 = (b * b) * (b * b);
2358 let mut xo: f32 = 0.0;
2359 let mut yo: f32 = 0.0;
2360 if out_grad_only {
2361 Self::grad_coord_out_2d(
2362 seed,
2363 i.wrapping_add(Self::PRIME_X),
2364 j,
2365 &mut xo,
2366 &mut yo,
2367 );
2368 } else {
2369 Self::grad_coord_dual_2d(
2370 seed,
2371 i.wrapping_add(Self::PRIME_X),
2372 j,
2373 x1,
2374 y1,
2375 &mut xo,
2376 &mut yo,
2377 );
2378 }
2379 vx += bbbb * xo;
2380 vy += bbbb * yo;
2381 }
2382 }
2383
2384 *xr += vx * warp_amp;
2385 *yr += vy * warp_amp;
2386 }
2387
2388 fn single_domain_warp_open_simplex2_gradient_3d(
2389 &self,
2390 mut seed: i32,
2391 warp_amp: f32,
2392 frequency: f32,
2393 mut x: f32,
2394 mut y: f32,
2395 mut z: f32,
2396 xr: &mut f32,
2397 yr: &mut f32,
2398 zr: &mut f32,
2399 out_grad_only: bool,
2400 ) {
2401 x *= frequency;
2402 y *= frequency;
2403 z *= frequency;
2404
2405 let mut i: i32 = fast_round(x);
2413 let mut j: i32 = fast_round(y);
2414 let mut k: i32 = fast_round(z);
2415 let mut x0: f32 = x - i as f32;
2416 let mut y0: f32 = y - j as f32;
2417 let mut z0: f32 = z - k as f32;
2418
2419 let mut xn_sign: i32 = (-x0 - 1.0) as i32 | 1;
2420 let mut yn_sign: i32 = (-y0 - 1.0) as i32 | 1;
2421 let mut zn_sign: i32 = (-z0 - 1.0) as i32 | 1;
2422
2423 let mut ax0: f32 = xn_sign as f32 * -x0;
2424 let mut ay0: f32 = yn_sign as f32 * -y0;
2425 let mut az0: f32 = zn_sign as f32 * -z0;
2426
2427 i = i.wrapping_mul(Self::PRIME_X);
2428 j = j.wrapping_mul(Self::PRIME_Y);
2429 k = k.wrapping_mul(Self::PRIME_Z);
2430
2431 let mut vx: f32 = 0.0;
2432 let mut vy: f32 = 0.0;
2433 let mut vz: f32 = 0.0;
2434
2435 let mut a: f32 = (0.6 - x0 * x0) - (y0 * y0 + z0 * z0);
2436
2437 for l in 0..2 {
2438 if a > 0.0 {
2439 let aaaa: f32 = (a * a) * (a * a);
2440 let mut xo: f32 = 0.0;
2441 let mut yo: f32 = 0.0;
2442 let mut zo: f32 = 0.0;
2443 if out_grad_only {
2444 Self::grad_coord_out_3d(seed, i, j, k, &mut xo, &mut yo, &mut zo);
2445 } else {
2446 Self::grad_coord_dual_3d(seed, i, j, k, x0, y0, z0, &mut xo, &mut yo, &mut zo);
2447 }
2448 vx += aaaa * xo;
2449 vy += aaaa * yo;
2450 vz += aaaa * zo;
2451 }
2452
2453 let mut b: f32 = a + 1.0;
2454 let mut i1: i32 = i;
2455 let mut j1: i32 = j;
2456 let mut k1: i32 = k;
2457 let mut x1: f32 = x0;
2458 let mut y1: f32 = y0;
2459 let mut z1: f32 = z0;
2460
2461 if ax0 >= ay0 && ax0 >= az0 {
2462 x1 += xn_sign as f32;
2463 b -= xn_sign as f32 * 2.0 * x1;
2464 i1 -= xn_sign * Self::PRIME_X;
2465 } else if ay0 > ax0 && ay0 >= az0 {
2466 y1 += yn_sign as f32;
2467 b -= yn_sign as f32 * 2.0 * y1;
2468 j1 -= yn_sign * Self::PRIME_Y;
2469 } else {
2470 z1 += zn_sign as f32;
2471 b -= zn_sign as f32 * 2.0 * z1;
2472 k1 -= zn_sign * Self::PRIME_Z;
2473 }
2474
2475 if b > 0.0 {
2476 let bbbb: f32 = (b * b) * (b * b);
2477 let mut xo: f32 = 0.0;
2478 let mut yo: f32 = 0.0;
2479 let mut zo: f32 = 0.0;
2480 if out_grad_only {
2481 Self::grad_coord_out_3d(seed, i1, j1, k1, &mut xo, &mut yo, &mut zo);
2482 } else {
2483 Self::grad_coord_dual_3d(
2484 seed, i1, j1, k1, x1, y1, z1, &mut xo, &mut yo, &mut zo,
2485 );
2486 }
2487 vx += bbbb * xo;
2488 vy += bbbb * yo;
2489 vz += bbbb * zo;
2490 }
2491
2492 if l == 1 {
2493 break;
2494 }
2495
2496 ax0 = 0.5 - ax0;
2497 ay0 = 0.5 - ay0;
2498 az0 = 0.5 - az0;
2499
2500 x0 = xn_sign as f32 * ax0;
2501 y0 = yn_sign as f32 * ay0;
2502 z0 = zn_sign as f32 * az0;
2503
2504 a += (0.75 - ax0) - (ay0 + az0);
2505
2506 i += (xn_sign >> 1) & Self::PRIME_X;
2507 j += (yn_sign >> 1) & Self::PRIME_Y;
2508 k += (zn_sign >> 1) & Self::PRIME_Z;
2509
2510 xn_sign = -xn_sign;
2511 yn_sign = -yn_sign;
2512 zn_sign = -zn_sign;
2513
2514 seed += 1293373;
2515 }
2516
2517 *xr += vx * warp_amp;
2518 *yr += vy * warp_amp;
2519 *zr += vz * warp_amp;
2520 }
2521}