[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/FastLED/FastLED/master/src/simplex.cpp.hpp [Back]  [Original]

/// @file simplex.cpp
/// Implements simplex noise functions

#define FASTLED_INTERNAL
#include "fl/system/fastled.h"

// This file implements simplex noise, which is an improved Perlin noise. This
// implementation is a fixed-point version that avoids all uses of floating
// point while still being compatible with the floating point version.

// Original author: Stefan Gustavson, converted to Go by Lars Pensj, converted
// to fixed-point Go and then to C++ by Ayke van Laethem.
// https://github.com/larspensjo/Go-simplex-noise/blob/master/simplexnoise/simplexnoise.go
// https://github.com/aykevl/ledsgo/blob/master/noise.go
//
// The code in this file has been placed in the public domain. You can do
// whatever you want with it. Attribution is appreciated but not required.

// Notation:
// Every fixed-point calculation has a line comment saying how many bits in the
// given integer are used for the fractional part. For example:
//
//     uint32_t n = a + b; // .12
//
// means the result of this operation has the floating point 12 bits from the
// right. Specifically, there are 20 integer bits and 12 fractional bits. It
// can be converted to a floating point using:
//
//     double nf = (double)n / (1 > 12;
    fl::u32 i1 = i0 + 1;
    fl::i32 x0 = x & 0xfff;   // .12
    fl::i32 x1 = x0 - 0x1000; // .12

    fl::i32 t0 = 0x8000 - ((x0*x0)>>9);             // .15
    t0 = (t0 * t0) >> 15;                           // .15
    t0 = (t0 * t0) >> 15;                           // .15
    fl::i32 n0 = (t0 * grad(SIMPLEX_P(i0&0xff), x0)) >> 12; // .15 * .12 = .15

    fl::i32 t1 = 0x8000 - ((x1*x1)>>9);             // .15
    t1 = (t1 * t1) >> 15;                           // .15
    t1 = (t1 * t1) >> 15;                           // .15
    fl::i32 n1 = (t1 * grad(SIMPLEX_P(i1&0xff), x1)) >> 12; // .15 * .12 = .15

    fl::i32 n = n0 + n1;   // .15
    n += 2503;             // .15: fix offset, adjust to +0.03
    n = (n * 26694) >> 16; // .15: fix scale to fit in [-1,1]
    return fl::u16(n) + 0x8000;
}

// 2D simplex noise.
fl::u16 snoise16(fl::u32 x, fl::u32 y) {
    const u64 F2 = 1572067135; // .32: F2 = 0.5*(sqrt(3.0)-1.0)
    const u64 G2 = 907633384;  // .32: G2 = (3.0-Math.sqrt(3.0))/6.0

    // Skew the input space to determine which simplex cell we're in
    fl::u32 s = (((u64)x + (u64)y) * F2) >> 32; // (.12 + .12) * .32 = .12: Hairy factor for 2D
    fl::u32 i = ((x>>1) + (s>>1)) >> 11;                  // .0
    fl::u32 j = ((y>>1) + (s>>1)) >> 11;                  // .0

    u64 t = ((u64)i + (u64)j) * G2; // .32
    u64 X0 = ((u64)i(0,1)->(1,1)

    // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
    // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
    // c = (3-sqrt(3))/6

    fl::i32 x1 = x0 - ((fl::i32)i118); // .14: Offsets for middle corner in (x,y) unskewed coords
    fl::i32 y1 = y0 - ((fl::i32)j118); // .14
    fl::i32 x2 = x0 - (1 >18);     // .14: Offsets for last corner in (x,y) unskewed coords
    fl::i32 y2 = y0 - (1 >18);     // .14

    fl::i32 n0 = 0, n1 = 0, n2 = 0; // Noise contributions from the three corners

    // Calculate the contribution from the three corners
    fl::i32 t0 = (((fl::i32)1 > 12; // .16
    if (t0 > 0) {
        t0 = (t0 * t0) >> 16;                                      // .16
        t0 = (t0 * t0) >> 16;                                      // .16
        n0 = t0 * grad(SIMPLEX_P((i+(fl::u32)(SIMPLEX_P(j&0xff)))&0xff), x0, y0); // .16 * .14 = .30
    }

    fl::i32 t1 = (((fl::i32)1 > 12; // .16
    if (t1 > 0) {
        t1 = (t1 * t1) >> 16;                                              // .16
        t1 = (t1 * t1) >> 16;                                              // .16
        n1 = t1 * grad(SIMPLEX_P((i+i1+(fl::u32)(SIMPLEX_P((j+j1)&0xff)))&0xff), x1, y1); // .16 * .14 = .30
    }

    fl::i32 t2 = (((fl::i32)1 > 12; // .16
    if (t2 > 0) {
        t2 = (t2 * t2) >> 16;                                            // .16
        t2 = (t2 * t2) >> 16;                                            // .16
        n2 = t2 * grad(SIMPLEX_P((i+1+(fl::u32)(SIMPLEX_P((j+1)&0xff)))&0xff), x2, y2); // .16 * .14 = .30
    }

    // Add contributions from each corner to get the final noise value.
    // The result is scaled to return values in the interval [-1,1].
    fl::i32 n = n0 + n1 + n2;    // .30
    n = ((n >> 8) * 23163) >> 16; // fix scale to fit exactly in an int16
    return (fl::u16)n + 0x8000;
}

// 3D simplex noise.
fl::u16 snoise16(fl::u32 x, fl::u32 y, fl::u32 z) {
    // Simple skewing factors for the 3D case
    const u64 F3 = 1431655764; // .32: 0.333333333
    const u64 G3 = 715827884;  // .32: 0.166666667

    // Skew the input space to determine which simplex cell we're in
    fl::u32 s = (((u64)x + (u64)y + (u64)z) * F3) >> 32; // .12 + .32 = .12: Very nice and simple skew factor for 3D
    fl::u32 i = ((x>>1) + (s>>1)) >> 11;                                // .0
    fl::u32 j = ((y>>1) + (s>>1)) >> 11;                                // .0
    fl::u32 k = ((z>>1) + (s>>1)) >> 11;                                // .0

    u64 t = ((u64)i + (u64)j + (u64)k) * G3; // .32
    u64 X0 = ((u64)i> 12; // .16
    if (t0 > 0) {
        t0 = (t0 * t0) >> 16; // .16
        t0 = (t0 * t0) >> 16; // .16
        // .16 * .14 = .30
        n0 = t0 * grad(SIMPLEX_P((i+(fl::u32)SIMPLEX_P((j+(fl::u32)SIMPLEX_P(k&0xff))&0xff))&0xff), x0, y0, z0);
    }

    fl::i32 t1 = (fix0_6 - x1*x1 - y1*y1 - z1*z1) >> 12; // .16
    if (t1 > 0) {
        t1 = (t1 * t1) >> 16; // .16
        t1 = (t1 * t1) >> 16; // .16
        // .16 * .14 = .30
        n1 = t1 * grad(SIMPLEX_P((i+i1+(fl::u32)SIMPLEX_P((j+j1+(fl::u32)SIMPLEX_P((k+k1)&0xff))&0xff))&0xff), x1, y1, z1);
    }

    fl::i32 t2 = (fix0_6 - x2*x2 - y2*y2 - z2*z2) >> 12; // .16
    if (t2 > 0) {
        t2 = (t2 * t2) >> 16; // .16
        t2 = (t2 * t2) >> 16; // .16
        // .16 * .14 = .30
        n2 = t2 * grad(SIMPLEX_P((i+i2+(fl::u32)SIMPLEX_P((j+j2+(fl::u32)SIMPLEX_P((k+k2)&0xff))&0xff))&0xff), x2, y2, z2);
    }

    fl::i32 t3 = (fix0_6 - x3*x3 - y3*y3 - z3*z3) >> 12; // .16
    if (t3 > 0) {
        t3 = (t3 * t3) >> 16; // .16
        t3 = (t3 * t3) >> 16; // .16
        // .16 * .14 = .30
        n3 = t3 * grad(SIMPLEX_P((i+1+(fl::u32)SIMPLEX_P((j+1+(fl::u32)SIMPLEX_P((k+1)&0xff))&0xff))&0xff), x3, y3, z3);
    }

    // Add contributions from each corner to get the final noise value.
    // The result is scaled to stay just inside [-1,1]
    fl::i32 n = n0 + n1 + n2 + n3; // .30
    n = ((n >> 8) * 16748) >> 16 ; // fix scale to fit exactly in an int16
    return (fl::u16)n + 0x8000;
}

// 4D simplex noise.
fl::u16 snoise16(fl::u32 x, fl::u32 y, fl::u32 z, fl::u32 w) {
    // The skewing and unskewing factors are hairy again for the 4D case
    const u64 F4 = 331804471; // .30: (Math.sqrt(5.0)-1.0)/4.0 = 0.30901699437494745
    const u64 G4 = 593549882; // .32: (5.0-Math.sqrt(5.0))/20.0 = 0.1381966011250105

    // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're
    // in.
    fl::u32 s = (((u64)x + (u64)y + (u64)z + (u64)w) * F4) >> 32; // .12 + .30 = .10: Factor for 4D skewing.
    fl::u32 i = ((x>>2) + s) >> 10;                                                   // .0
    fl::u32 j = ((y>>2) + s) >> 10;                                                   // .0
    fl::u32 k = ((z>>2) + s) >> 10;                                                   // .0
    fl::u32 l = ((w>>2) + s) >> 10;                                                   // .0

    u64 t = (((u64)i + (u64)j + (u64)k + (u64)l) * G4) >> 18; // .14
    u64 X0 = ((u64)i= 1 ? 1 : 0;
    fl::u32 k3 = simplex_detail::simplex[c][2] >= 1 ? 1 : 0;
    fl::u32 l3 = simplex_detail::simplex[c][3] >= 1 ? 1 : 0;
    // The fifth corner has all coordinate offsets = 1, so no need to look that up.

    fl::i32 x1 = x0 - ((fl::i32)i118); // .14: Offsets for second corner in (x,y,z,w) coords
    fl::i32 y1 = y0 - ((fl::i32)j118);
    fl::i32 z1 = z0 - ((fl::i32)k118);
    fl::i32 w1 = w0 - ((fl::i32)l118);
    fl::i32 x2 = x0 - ((fl::i32)i218); // .14: Offsets for third corner in (x,y,z,w) coords
    fl::i32 y2 = y0 - ((fl::i32)j218);
    fl::i32 z2 = z0 - ((fl::i32)k218);
    fl::i32 w2 = w0 - ((fl::i32)l218);
    fl::i32 x3 = x0 - ((fl::i32)i318); // .14: Offsets for fourth corner in (x,y,z,w) coords
    fl::i32 y3 = y0 - ((fl::i32)j318);
    fl::i32 z3 = z0 - ((fl::i32)k318);
    fl::i32 w3 = w0 - ((fl::i32)l318);
    fl::i32 x4 = x0 - (1 >18); // .14: Offsets for last corner in (x,y,z,w) coords
    fl::i32 y4 = y0 - (1 >18);
    fl::i32 z4 = z0 - (1 >18);
    fl::i32 w4 = w0 - (1 >18);

    fl::i32 n0 = 0, n1 = 0, n2 = 0, n3 = 0, n4 = 0; // Noise contributions from the five corners
    const fl::i32 fix0_6 = 161061274;               // .28: 0.6

    // Calculate the contribution from the five corners
    fl::i32 t0 = (fix0_6 - x0*x0 - y0*y0 - z0*z0 - w0*w0) >> 12; // .16
    if (t0 > 0) {
        t0 = (t0 * t0) >> 16;
        t0 = (t0 * t0) >> 16;
        // .16 * .14 = .30
        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);
    }

    fl::i32 t1 = (fix0_6 - x1*x1 - y1*y1 - z1*z1 - w1*w1) >> 12; // .16
    if (t1 > 0) {
        t1 = (t1 * t1) >> 16;
        t1 = (t1 * t1) >> 16;
        // .16 * .14 = .30
        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);
    }

    fl::i32 t2 = (fix0_6 - x2*x2 - y2*y2 - z2*z2 - w2*w2) >> 12; // .16
    if (t2 > 0) {
        t2 = (t2 * t2) >> 16;
        t2 = (t2 * t2) >> 16;
        // .16 * .14 = .30
        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);
    }

    fl::i32 t3 = (fix0_6 - x3*x3 - y3*y3 - z3*z3 - w3*w3) >> 12; // .16
    if (t3 > 0) {
        t3 = (t3 * t3) >> 16;
        t3 = (t3 * t3) >> 16;
        // .16 * .14 = .30
        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);
    }

    fl::i32 t4 = (fix0_6 - x4*x4 - y4*y4 - z4*z4 - w4*w4) >> 12; // .16
    if (t4 > 0) {
        t4 = (t4 * t4) >> 16;
        t4 = (t4 * t4) >> 16;
        // .16 * .14 = .30
        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);
    }

    fl::i32 n = n0 + n1 + n2 + n3 + n4;  // .30
	n = ((n >> 8) * 13832) >> 16; // fix scale
	return fl::u16(n) + 0x8000;
}


Web Proxy Viewer  |  New URL  |  Original Page