Exemple #1
0
        public float Sample3D(float x, float y, float z)
        {
            var stretchOffset = (x + y + z) * STRETCH_3D;
            var xs            = x + stretchOffset;
            var ys            = y + stretchOffset;
            var zs            = z + stretchOffset;

            var xsb = NoiseUtil.FastFloor(xs);
            var ysb = NoiseUtil.FastFloor(ys);
            var zsb = NoiseUtil.FastFloor(zs);

            var squishOffset = (xsb + ysb + zsb) * SQUISH_3D;
            var dx0          = x - (xsb + squishOffset);
            var dy0          = y - (ysb + squishOffset);
            var dz0          = z - (zsb + squishOffset);

            var xins = xs - xsb;
            var yins = ys - ysb;
            var zins = zs - zsb;

            var inSum = xins + yins + zins;

            var hash =
                (int)(yins - zins + 1) |
                (int)(xins - yins + 1) << 1 |
                    (int)(xins - zins + 1) << 2 |
                    (int)inSum << 3 |
                    (int)(inSum + zins) << 5 |
                    (int)(inSum + yins) << 7 |
                    (int)(inSum + xins) << 9;

            var c = lookup3D[hash];

            var value = 0.0;

            while (c != null)
            {
                var dx   = dx0 + c.dx;
                var dy   = dy0 + c.dy;
                var dz   = dz0 + c.dz;
                var attn = 2 - dx * dx - dy * dy - dz * dz;

                if (attn > 0)
                {
                    var px = xsb + c.xsb;
                    var py = ysb + c.ysb;
                    var pz = zsb + c.zsb;

                    var i         = perm3D[(perm[(perm[px & 0xFF] + py) & 0xFF] + pz) & 0xFF];
                    var valuePart = gradients3D[i] * dx + gradients3D[i + 1] * dy + gradients3D[i + 2] * dz;

                    attn  *= attn;
                    value += attn * attn * valuePart;
                }

                c = c.Next;
            }

            return((float)(value * NORM_3D));
        }
Exemple #2
0
        public float Sample2D(float x, float y)
        {
            var stretchOffset = (x + y) * STRETCH_2D;
            var xs            = x + stretchOffset;
            var ys            = y + stretchOffset;

            var xsb = NoiseUtil.FastFloor(xs);
            var ysb = NoiseUtil.FastFloor(ys);

            var squishOffset = (xsb + ysb) * SQUISH_2D;
            var dx0          = x - (xsb + squishOffset);
            var dy0          = y - (ysb + squishOffset);

            var xins = xs - xsb;
            var yins = ys - ysb;

            var inSum = xins + yins;

            var hash =
                (int)(xins - yins + 1) |
                (int)(inSum) << 1 |
                    (int)(inSum + yins) << 2 |
                    (int)(inSum + xins) << 4;

            var c = lookup2D[hash];

            var value = 0.0;

            while (c != null)
            {
                var dx   = dx0 + c.dx;
                var dy   = dy0 + c.dy;
                var attn = 2 - dx * dx - dy * dy;

                if (attn > 0)
                {
                    var px = xsb + c.xsb;
                    var py = ysb + c.ysb;

                    var i         = perm2D[(perm[px & 0xFF] + py) & 0xFF];
                    var valuePart = gradients2D[i] * dx + gradients2D[i + 1] * dy;

                    attn  *= attn;
                    value += attn * attn * valuePart;
                }

                c = c.Next;
            }

            return((float)(value * NORM_2D));
        }
Exemple #3
0
        /**
         * Generate overlapping cubic lattices for 3D Re-oriented BCC noise.
         * Lookup table implementation inspired by DigitalShadow.
         * It was actually faster to narrow down the points in the loop itself,
         * than to build up the index with enough info to isolate 4 points.
         */
        private double Noise3_BCC(double xr, double yr, double zr)
        {
            // Get base and offsets inside cube of first lattice.
            int    xrb = NoiseUtil.FastFloor(xr), yrb = NoiseUtil.FastFloor(yr), zrb = NoiseUtil.FastFloor(zr);
            double xri = xr - xrb, yri = yr - yrb, zri = zr - zrb;

            // Identify which octant of the cube we're in. This determines which cell
            // in the other cubic lattice we're in, and also narrows down one point on each.
            int xht = (int)(xri + 0.5), yht = (int)(yri + 0.5), zht = (int)(zri + 0.5);
            int index = (xht << 0) | (yht << 1) | (zht << 2);

            // Point contributions
            double         value = 0;
            LatticePoint3D c     = LOOKUP_3D[index];

            while (c != null)
            {
                double dxr = xri + c.dxr, dyr = yri + c.dyr, dzr = zri + c.dzr;
                double attn = 0.5 - dxr * dxr - dyr * dyr - dzr * dzr;

                if (attn < 0)
                {
                    c = c.NextOnFailure;
                }
                else
                {
                    int    pxm = (xrb + c.xrv) & PMASK, pym = (yrb + c.yrv) & PMASK, pzm = (zrb + c.zrv) & PMASK;
                    Grad3  grad          = permGrad3[perm[perm[pxm] ^ pym] ^ pzm];
                    double extrapolation = grad.dx * dxr + grad.dy * dyr + grad.dz * dzr;

                    attn  *= attn;
                    value += attn * attn * extrapolation;
                    c      = c.NextOnSuccess;
                }
            }

            return(value);
        }
Exemple #4
0
        /**
         * 2D Simplex noise base.
         * Lookup table implementation inspired by DigitalShadow.
         */
        private double Noise2_Base(double xs, double ys)
        {
            double value = 0;

            // Get base points and offsets
            int    xsb = NoiseUtil.FastFloor(xs), ysb = NoiseUtil.FastFloor(ys);
            double xsi = xs - xsb, ysi = ys - ysb;

            // Index to point list
            int index = (int)((ysi - xsi) / 2 + 1);

            double ssi = (xsi + ysi) * -0.211324865405187;
            double xi = xsi + ssi, yi = ysi + ssi;

            // Point contributions
            for (int i = 0; i < 3; ++i)
            {
                LatticePoint2D c = LOOKUP_2D[index + i];

                double dx = xi + c.dx, dy = yi + c.dy;
                double attn = 0.5 - dx * dx - dy * dy;
                if (attn <= 0)
                {
                    continue;
                }

                int    pxm = (xsb + c.xsv) & PMASK, pym = (ysb + c.ysv) & PMASK;
                Grad2  grad          = permGrad2[perm[pxm] ^ pym];
                double extrapolation = grad.dx * dx + grad.dy * dy;

                attn  *= attn;
                value += attn * attn * extrapolation;
            }

            return(value);
        }
Exemple #5
0
        public float Sample4D(float x, float y, float z, float w)
        {
            var stretchOffset = (x + y + z + w) * STRETCH_4D;
            var xs            = x + stretchOffset;
            var ys            = y + stretchOffset;
            var zs            = z + stretchOffset;
            var ws            = w + stretchOffset;

            var xsb = NoiseUtil.FastFloor(xs);
            var ysb = NoiseUtil.FastFloor(ys);
            var zsb = NoiseUtil.FastFloor(zs);
            var wsb = NoiseUtil.FastFloor(ws);

            var squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_4D;
            var dx0          = x - (xsb + squishOffset);
            var dy0          = y - (ysb + squishOffset);
            var dz0          = z - (zsb + squishOffset);
            var dw0          = w - (wsb + squishOffset);

            var xins = xs - xsb;
            var yins = ys - ysb;
            var zins = zs - zsb;
            var wins = ws - wsb;

            var inSum = xins + yins + zins + wins;

            var hash =
                (int)(zins - wins + 1) |
                (int)(yins - zins + 1) << 1 |
                    (int)(yins - wins + 1) << 2 |
                    (int)(xins - yins + 1) << 3 |
                    (int)(xins - zins + 1) << 4 |
                    (int)(xins - wins + 1) << 5 |
                    (int)inSum << 6 |
                    (int)(inSum + wins) << 8 |
                    (int)(inSum + zins) << 11 |
                    (int)(inSum + yins) << 14 |
                    (int)(inSum + xins) << 17;

            var c = lookup4D[hash];

            var value = 0.0;

            while (c != null)
            {
                var dx   = dx0 + c.dx;
                var dy   = dy0 + c.dy;
                var dz   = dz0 + c.dz;
                var dw   = dw0 + c.dw;
                var attn = 2 - dx * dx - dy * dy - dz * dz - dw * dw;

                if (attn > 0)
                {
                    var px = xsb + c.xsb;
                    var py = ysb + c.ysb;
                    var pz = zsb + c.zsb;
                    var pw = wsb + c.wsb;

                    var i         = perm4D[(perm[(perm[(perm[px & 0xFF] + py) & 0xFF] + pz) & 0xFF] + pw) & 0xFF];
                    var valuePart = gradients4D[i] * dx + gradients4D[i + 1] * dy + gradients4D[i + 2] * dz + gradients4D[i + 3] * dw;

                    attn  *= attn;
                    value += attn * attn * valuePart;
                }

                c = c.Next;
            }

            return((float)(value * NORM_4D));
        }
Exemple #6
0
        /**
         * 4D OpenSimplex2F noise base.
         * Current implementation not fully optimized by lookup tables.
         * But still comes out slightly ahead of Gustavson's Simplex in tests.
         */
        private double Noise4_Base(double xs, double ys, double zs, double ws)
        {
            double value = 0;

            // Get base points and offsets
            int    xsb = NoiseUtil.FastFloor(xs), ysb = NoiseUtil.FastFloor(ys), zsb = NoiseUtil.FastFloor(zs), wsb = NoiseUtil.FastFloor(ws);
            double xsi = xs - xsb, ysi = ys - ysb, zsi = zs - zsb, wsi = ws - wsb;

            // If we're in the lower half, flip so we can repeat the code for the upper half. We'll flip back later.
            double siSum       = xsi + ysi + zsi + wsi;
            double ssi         = siSum * 0.309016994374947;     // Prep for vertex contributions.
            bool   inLowerHalf = (siSum < 2);

            if (inLowerHalf)
            {
                xsi   = 1 - xsi; ysi = 1 - ysi; zsi = 1 - zsi; wsi = 1 - wsi;
                siSum = 4 - siSum;
            }

            // Consider opposing vertex pairs of the octahedron formed by the central cross-section of the stretched tesseract
            double aabb = xsi + ysi - zsi - wsi, abab = xsi - ysi + zsi - wsi, abba = xsi - ysi - zsi + wsi;
            double aabbScore = System.Math.Abs(aabb), ababScore = System.Math.Abs(abab), abbaScore = System.Math.Abs(abba);

            // Find the closest point on the stretched tesseract as if it were the upper half
            int    vertexIndex, via, vib;
            double asi, bsi;

            if (aabbScore > ababScore && aabbScore > abbaScore)
            {
                if (aabb > 0)
                {
                    asi = zsi; bsi = wsi; vertexIndex = 0b0011; via = 0b0111; vib = 0b1011;
                }
                else
                {
                    asi = xsi; bsi = ysi; vertexIndex = 0b1100; via = 0b1101; vib = 0b1110;
                }
            }
            else if (ababScore > abbaScore)
            {
                if (abab > 0)
                {
                    asi = ysi; bsi = wsi; vertexIndex = 0b0101; via = 0b0111; vib = 0b1101;
                }
                else
                {
                    asi = xsi; bsi = zsi; vertexIndex = 0b1010; via = 0b1011; vib = 0b1110;
                }
            }
            else
            {
                if (abba > 0)
                {
                    asi = ysi; bsi = zsi; vertexIndex = 0b1001; via = 0b1011; vib = 0b1101;
                }
                else
                {
                    asi = xsi; bsi = wsi; vertexIndex = 0b0110; via = 0b0111; vib = 0b1110;
                }
            }

            if (bsi > asi)
            {
                via = vib;
                double temp = bsi;
                bsi = asi;
                asi = temp;
            }

            if (siSum + asi > 3)
            {
                vertexIndex = via;

                if (siSum + bsi > 4)
                {
                    vertexIndex = 0b1111;
                }
            }

            // Now flip back if we're actually in the lower half.
            if (inLowerHalf)
            {
                xsi          = 1 - xsi; ysi = 1 - ysi; zsi = 1 - zsi; wsi = 1 - wsi;
                vertexIndex ^= 0b1111;
            }

            // Five points to add, total, from five copies of the A4 lattice.
            for (int i = 0; i < 5; ++i)
            {
                // Update xsb/etc. and add the lattice point's contribution.
                LatticePoint4D c = VERTICES_4D[vertexIndex];
                xsb += c.xsv; ysb += c.ysv; zsb += c.zsv; wsb += c.wsv;
                double xi = xsi + ssi, yi = ysi + ssi, zi = zsi + ssi, wi = wsi + ssi;
                double dx = xi + c.dx, dy = yi + c.dy, dz = zi + c.dz, dw = wi + c.dw;
                double attn = 0.5 - dx * dx - dy * dy - dz * dz - dw * dw;

                if (attn > 0)
                {
                    int    pxm = xsb & PMASK, pym = ysb & PMASK, pzm = zsb & PMASK, pwm = wsb & PMASK;
                    Grad4  grad   = permGrad4[perm[perm[perm[pxm] ^ pym] ^ pzm] ^ pwm];
                    double ramped = grad.dx * dx + grad.dy * dy + grad.dz * dz + grad.dw * dw;

                    attn  *= attn;
                    value += attn * attn * ramped;
                }

                // Maybe this helps the compiler/JVM/LLVM/etc. know we can end the loop here. Maybe not.
                if (i == 4)
                {
                    break;
                }

                // Update the relative skewed coordinates to reference the vertex we just added.
                // Rather, reference its counterpart on the lattice copy that is shifted down by
                // the vector <-0.2, -0.2, -0.2, -0.2>
                xsi += c.xsi; ysi += c.ysi; zsi += c.zsi; wsi += c.wsi;
                ssi += c.ssiDelta;

                // Next point is the closest vertex on the 4-simplex whose base vertex is the aforementioned vertex.
                double score0 = 1.0 + ssi * (-1.0 / 0.309016994374947);                 // Seems slightly faster than 1.0-xsi-ysi-zsi-wsi
                vertexIndex = 0b0000;

                if (xsi >= ysi && xsi >= zsi && xsi >= wsi && xsi >= score0)
                {
                    vertexIndex = 0b0001;
                }
                else if (ysi > xsi && ysi >= zsi && ysi >= wsi && ysi >= score0)
                {
                    vertexIndex = 0b0010;
                }
                else if (zsi > xsi && zsi > ysi && zsi >= wsi && zsi >= score0)
                {
                    vertexIndex = 0b0100;
                }
                else if (wsi > xsi && wsi > ysi && wsi > zsi && wsi >= score0)
                {
                    vertexIndex = 0b1000;
                }
            }

            return(value);
        }