FastLED 3.10.8
Loading...
Searching...
No Matches

◆ snoise16() [4/4]

fl::u16 snoise16 ( fl::u32 x,
fl::u32 y,
fl::u32 z,
fl::u32 w )

Definition at line 329 of file simplex.cpp.hpp.

329 {
330 // The skewing and unskewing factors are hairy again for the 4D case
331 const u64 F4 = 331804471; // .30: (Math.sqrt(5.0)-1.0)/4.0 = 0.30901699437494745
332 const u64 G4 = 593549882; // .32: (5.0-Math.sqrt(5.0))/20.0 = 0.1381966011250105
333
334 // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're
335 // in.
336 fl::u32 s = (((u64)x + (u64)y + (u64)z + (u64)w) * F4) >> 32; // .12 + .30 = .10: Factor for 4D skewing.
337 fl::u32 i = ((x>>2) + s) >> 10; // .0
338 fl::u32 j = ((y>>2) + s) >> 10; // .0
339 fl::u32 k = ((z>>2) + s) >> 10; // .0
340 fl::u32 l = ((w>>2) + s) >> 10; // .0
341
342 u64 t = (((u64)i + (u64)j + (u64)k + (u64)l) * G4) >> 18; // .14
343 u64 X0 = ((u64)i<<14) - t; // .14: Unskew the cell origin back to (x,y,z,w) space
344 u64 Y0 = ((u64)j<<14) - t; // .14
345 u64 Z0 = ((u64)k<<14) - t; // .14
346 u64 W0 = ((u64)l<<14) - t; // .14
347 fl::i32 x0 = ((u64)x<<2) - X0; // .14: The x,y,z,w distances from the cell origin
348 fl::i32 y0 = ((u64)y<<2) - Y0; // .14
349 fl::i32 z0 = ((u64)z<<2) - Z0; // .14
350 fl::i32 w0 = ((u64)w<<2) - W0; // .14
351
352 // For the 4D case, the simplex is a 4D shape I won't even try to describe.
353 // To find out which of the 24 possible simplices we're in, we need to
354 // determine the magnitude ordering of x0, y0, z0 and w0.
355 // The method below is a good way of finding the ordering of x,y,z,w and
356 // then find the correct traversal order for the simplex we’re in.
357 // First, six pair-wise comparisons are performed between each possible pair
358 // of the four coordinates, and the results are used to add up binary bits
359 // for an integer index.
360 int c = 0;
361 if (x0 > y0) {
362 c += 32;
363 }
364 if (x0 > z0) {
365 c += 16;
366 }
367 if (y0 > z0) {
368 c += 8;
369 }
370 if (x0 > w0) {
371 c += 4;
372 }
373 if (y0 > w0) {
374 c += 2;
375 }
376 if (z0 > w0) {
377 c += 1;
378 }
379
380 // simplex_detail::simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
381 // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
382 // impossible. Only the 24 indices which have non-zero entries make any sense.
383 // We use a thresholding to set the coordinates in turn from the largest magnitude.
384 // The number 3 in the "simplex" array is at the position of the largest coordinate.
385 // The integer offsets for the second simplex corner
386 fl::u32 i1 = simplex_detail::simplex[c][0] >= 3 ? 1 : 0;
387 fl::u32 j1 = simplex_detail::simplex[c][1] >= 3 ? 1 : 0;
388 fl::u32 k1 = simplex_detail::simplex[c][2] >= 3 ? 1 : 0;
389 fl::u32 l1 = simplex_detail::simplex[c][3] >= 3 ? 1 : 0;
390 // The number 2 in the "simplex" array is at the second largest coordinate.
391 // The integer offsets for the third simplex corner
392 fl::u32 i2 = simplex_detail::simplex[c][0] >= 2 ? 1 : 0;
393 fl::u32 j2 = simplex_detail::simplex[c][1] >= 2 ? 1 : 0;
394 fl::u32 k2 = simplex_detail::simplex[c][2] >= 2 ? 1 : 0;
395 fl::u32 l2 = simplex_detail::simplex[c][3] >= 2 ? 1 : 0;
396 // The number 1 in the "simplex" array is at the second smallest coordinate.
397 // The integer offsets for the fourth simplex corner
398 fl::u32 i3 = simplex_detail::simplex[c][0] >= 1 ? 1 : 0;
399 fl::u32 j3 = simplex_detail::simplex[c][1] >= 1 ? 1 : 0;
400 fl::u32 k3 = simplex_detail::simplex[c][2] >= 1 ? 1 : 0;
401 fl::u32 l3 = simplex_detail::simplex[c][3] >= 1 ? 1 : 0;
402 // The fifth corner has all coordinate offsets = 1, so no need to look that up.
403
404 fl::i32 x1 = x0 - ((fl::i32)i1<<14) + (fl::i32)(G4>>18); // .14: Offsets for second corner in (x,y,z,w) coords
405 fl::i32 y1 = y0 - ((fl::i32)j1<<14) + (fl::i32)(G4>>18);
406 fl::i32 z1 = z0 - ((fl::i32)k1<<14) + (fl::i32)(G4>>18);
407 fl::i32 w1 = w0 - ((fl::i32)l1<<14) + (fl::i32)(G4>>18);
408 fl::i32 x2 = x0 - ((fl::i32)i2<<14) + (fl::i32)(2*G4>>18); // .14: Offsets for third corner in (x,y,z,w) coords
409 fl::i32 y2 = y0 - ((fl::i32)j2<<14) + (fl::i32)(2*G4>>18);
410 fl::i32 z2 = z0 - ((fl::i32)k2<<14) + (fl::i32)(2*G4>>18);
411 fl::i32 w2 = w0 - ((fl::i32)l2<<14) + (fl::i32)(2*G4>>18);
412 fl::i32 x3 = x0 - ((fl::i32)i3<<14) + (fl::i32)(3*G4>>18); // .14: Offsets for fourth corner in (x,y,z,w) coords
413 fl::i32 y3 = y0 - ((fl::i32)j3<<14) + (fl::i32)(3*G4>>18);
414 fl::i32 z3 = z0 - ((fl::i32)k3<<14) + (fl::i32)(3*G4>>18);
415 fl::i32 w3 = w0 - ((fl::i32)l3<<14) + (fl::i32)(3*G4>>18);
416 fl::i32 x4 = x0 - (1 << 14) + (fl::i32)(4*G4>>18); // .14: Offsets for last corner in (x,y,z,w) coords
417 fl::i32 y4 = y0 - (1 << 14) + (fl::i32)(4*G4>>18);
418 fl::i32 z4 = z0 - (1 << 14) + (fl::i32)(4*G4>>18);
419 fl::i32 w4 = w0 - (1 << 14) + (fl::i32)(4*G4>>18);
420
421 fl::i32 n0 = 0, n1 = 0, n2 = 0, n3 = 0, n4 = 0; // Noise contributions from the five corners
422 const fl::i32 fix0_6 = 161061274; // .28: 0.6
423
424 // Calculate the contribution from the five corners
425 fl::i32 t0 = (fix0_6 - x0*x0 - y0*y0 - z0*z0 - w0*w0) >> 12; // .16
426 if (t0 > 0) {
427 t0 = (t0 * t0) >> 16;
428 t0 = (t0 * t0) >> 16;
429 // .16 * .14 = .30
430 n0 = t0 * grad(SIMPLEX_P((i+(fl::u32)(SIMPLEX_P((j+(fl::u32)(SIMPLEX_P((k+(fl::u32)(SIMPLEX_P(l&0xff)))&0xff)))&0xff)))&0xff), x0, y0, z0, w0);
431 }
432
433 fl::i32 t1 = (fix0_6 - x1*x1 - y1*y1 - z1*z1 - w1*w1) >> 12; // .16
434 if (t1 > 0) {
435 t1 = (t1 * t1) >> 16;
436 t1 = (t1 * t1) >> 16;
437 // .16 * .14 = .30
438 n1 = t1 * grad(SIMPLEX_P((i+i1+(fl::u32)(SIMPLEX_P((j+j1+(fl::u32)(SIMPLEX_P((k+k1+(fl::u32)(SIMPLEX_P((l+l1)&0xff)))&0xff)))&0xff)))&0xff), x1, y1, z1, w1);
439 }
440
441 fl::i32 t2 = (fix0_6 - x2*x2 - y2*y2 - z2*z2 - w2*w2) >> 12; // .16
442 if (t2 > 0) {
443 t2 = (t2 * t2) >> 16;
444 t2 = (t2 * t2) >> 16;
445 // .16 * .14 = .30
446 n2 = t2 * grad(SIMPLEX_P((i+i2+(fl::u32)(SIMPLEX_P((j+j2+(fl::u32)(SIMPLEX_P((k+k2+(fl::u32)(SIMPLEX_P((l+l2)&0xff)))&0xff)))&0xff)))&0xff), x2, y2, z2, w2);
447 }
448
449 fl::i32 t3 = (fix0_6 - x3*x3 - y3*y3 - z3*z3 - w3*w3) >> 12; // .16
450 if (t3 > 0) {
451 t3 = (t3 * t3) >> 16;
452 t3 = (t3 * t3) >> 16;
453 // .16 * .14 = .30
454 n3 = t3 * grad(SIMPLEX_P((i+i3+(fl::u32)(SIMPLEX_P((j+j3+(fl::u32)(SIMPLEX_P((k+k3+(fl::u32)(SIMPLEX_P((l+l3)&0xff)))&0xff)))&0xff)))&0xff), x3, y3, z3, w3);
455 }
456
457 fl::i32 t4 = (fix0_6 - x4*x4 - y4*y4 - z4*z4 - w4*w4) >> 12; // .16
458 if (t4 > 0) {
459 t4 = (t4 * t4) >> 16;
460 t4 = (t4 * t4) >> 16;
461 // .16 * .14 = .30
462 n4 = t4 * grad(SIMPLEX_P((i+1+(fl::u32)(SIMPLEX_P((j+1+(fl::u32)(SIMPLEX_P((k+1+(fl::u32)(SIMPLEX_P((l+1)&0xff)))&0xff)))&0xff)))&0xff), x4, y4, z4, w4);
463 }
464
465 fl::i32 n = n0 + n1 + n2 + n3 + n4; // .30
466 n = ((n >> 8) * 13832) >> 16; // fix scale
467 return fl::u16(n) + 0x8000;
468}
int y
Definition simple.h:93
int x
Definition simple.h:92
uint32_t z[NUM_LAYERS]
Definition Fire2023.h:93
constexpr EOrderW W0
Definition eorder.h:27
static uint32_t t
Definition Luminova.h:55
static fl::u8 const simplex[64][4]
#define SIMPLEX_P(x)
static fl::i32 grad(fl::u8 hash, fl::i32 x) FL_NO_EXCEPT
fl::u64 u64
Definition stdint.h:220

References FL_NO_EXCEPT, grad(), simplex_detail::simplex, SIMPLEX_P, t, W0, x, y, and z.

+ Here is the call graph for this function: