From da27af1eda3f7c3352ef233dc0f5065385d2b87a Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 24 Sep 2022 18:37:07 +0800 Subject: [PATCH] Re-add 3D and 4D Simplex Noise. This partially revert 97806f87c018d77d44d30ae2cf3c4384ab9f3047 --- src/libraries/noise1234/noise1234.cpp | 2 + src/libraries/noise1234/noise1234.h | 2 + src/libraries/noise1234/simplexnoise1234.cpp | 266 ++++++++++++++++++- src/libraries/noise1234/simplexnoise1234.h | 8 +- 4 files changed, 273 insertions(+), 5 deletions(-) diff --git a/src/libraries/noise1234/noise1234.cpp b/src/libraries/noise1234/noise1234.cpp index a62bb08c8..72f609604 100644 --- a/src/libraries/noise1234/noise1234.cpp +++ b/src/libraries/noise1234/noise1234.cpp @@ -11,6 +11,8 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. +// Modified by the LOVE Development Team to use double precision. + /** \file \brief Implements the Noise1234 class for producing Perlin noise. \author Stefan Gustavson (stegu@itn.liu.se) diff --git a/src/libraries/noise1234/noise1234.h b/src/libraries/noise1234/noise1234.h index dbc867e13..2d5d0f81b 100644 --- a/src/libraries/noise1234/noise1234.h +++ b/src/libraries/noise1234/noise1234.h @@ -11,6 +11,8 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. +// Modified by the LOVE Development Team to use double precision. + /** \file \brief Declares the Noise1234 class for producing Perlin noise. \author Stefan Gustavson (stegu@itn.liu.se) diff --git a/src/libraries/noise1234/simplexnoise1234.cpp b/src/libraries/noise1234/simplexnoise1234.cpp index 71039d757..d208f7fc0 100644 --- a/src/libraries/noise1234/simplexnoise1234.cpp +++ b/src/libraries/noise1234/simplexnoise1234.cpp @@ -13,8 +13,7 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. -// Modified by the LOVE Development Team to remove 3D and 4D implementations due -// to patent issues. +// Modified by the LOVE Development Team to use double precision. /** \file \brief Implements the SimplexNoise1234 class for producing Perlin simplex noise. @@ -117,6 +116,34 @@ double SimplexNoise1234::grad( int hash, double x, double y ) { return ((h&1)? -u : u) + ((h&2)? -2.0*v : 2.0*v); } +double SimplexNoise1234::grad( int hash, double x, double y , double z ) { + int h = hash & 15; // Convert low 4 bits of hash code into 12 simple + double u = h<8 ? x : y; // gradient directions, and compute dot product. + double v = h<4 ? y : h==12||h==14 ? x : z; // Fix repeats at h = 12 to 15 + return ((h&1)? -u : u) + ((h&2)? -v : v); +} + +double SimplexNoise1234::grad( int hash, double x, double y, double z, double t ) { + int h = hash & 31; // Convert low 5 bits of hash code into 32 simple + double u = h<24 ? x : y; // gradient directions, and compute dot product. + double v = h<16 ? y : z; + double w = h<8 ? z : t; + return ((h&1)? -u : u) + ((h&2)? -v : v) + ((h&4)? -w : w); +} + +// A lookup table to traverse the simplex around a given point in 4D. +// Details can be found where this table is used, in the 4D noise method. +/* TODO: This should not be required, backport it from Bill's GLSL code! */ +static unsigned char simplex[64][4] = { + {0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0}, + {0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0}, + {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, + {1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0}, + {1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0}, + {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}, + {2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0}, + {2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}; + // 1D simplex noise float SimplexNoise1234::noise(double x) { @@ -206,3 +233,238 @@ float SimplexNoise1234::noise(double x, double y) { // The result is scaled to return values in the interval [-1,1]. return 45.23f * (n0 + n1 + n2); // TODO: The scale factor is preliminary! } + +// 3D simplex noise +float SimplexNoise1234::noise(double x, double y, double z) { + + // Simple skewing factors for the 3D case +#define F3 0.333333333 +#define G3 0.166666667 + + double n0, n1, n2, n3; // Noise contributions from the four corners + + // Skew the input space to determine which simplex cell we're in + double s = (x+y+z)*F3; // Very nice and simple skew factor for 3D + double xs = x+s; + double ys = y+s; + double zs = z+s; + int i = FASTFLOOR(xs); + int j = FASTFLOOR(ys); + int k = FASTFLOOR(zs); + + double t = (float)(i+j+k)*G3; + double X0 = i-t; // Unskew the cell origin back to (x,y,z) space + double Y0 = j-t; + double Z0 = k-t; + double x0 = x-X0; // The x,y,z distances from the cell origin + double y0 = y-Y0; + double z0 = z-Z0; + + // For the 3D case, the simplex shape is a slightly irregular tetrahedron. + // Determine which simplex we are in. + int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords + int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords + + /* This code would benefit from a backport from the GLSL version! */ + if(x0>=y0) { + if(y0>=z0) + { i1=1; j1=0; k1=0; i2=1; j2=1; k2=0; } // X Y Z order + else if(x0>=z0) { i1=1; j1=0; k1=0; i2=1; j2=0; k2=1; } // X Z Y order + else { i1=0; j1=0; k1=1; i2=1; j2=0; k2=1; } // Z X Y order + } + else { // x0 y0) ? 32 : 0; + int c2 = (x0 > z0) ? 16 : 0; + int c3 = (y0 > z0) ? 8 : 0; + int c4 = (x0 > w0) ? 4 : 0; + int c5 = (y0 > w0) ? 2 : 0; + int c6 = (z0 > w0) ? 1 : 0; + int c = c1 + c2 + c3 + c4 + c5 + c6; + + int i1, j1, k1, l1; // The integer offsets for the second simplex corner + int i2, j2, k2, l2; // The integer offsets for the third simplex corner + int i3, j3, k3, l3; // The integer offsets for the fourth simplex corner + + // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order. + // Many values of c will never occur, since e.g. x>y>z>w makes x=3 ? 1 : 0; + j1 = simplex[c][1]>=3 ? 1 : 0; + k1 = simplex[c][2]>=3 ? 1 : 0; + l1 = simplex[c][3]>=3 ? 1 : 0; + // The number 2 in the "simplex" array is at the second largest coordinate. + i2 = simplex[c][0]>=2 ? 1 : 0; + j2 = simplex[c][1]>=2 ? 1 : 0; + k2 = simplex[c][2]>=2 ? 1 : 0; + l2 = simplex[c][3]>=2 ? 1 : 0; + // The number 1 in the "simplex" array is at the second smallest coordinate. + i3 = simplex[c][0]>=1 ? 1 : 0; + j3 = simplex[c][1]>=1 ? 1 : 0; + k3 = simplex[c][2]>=1 ? 1 : 0; + l3 = simplex[c][3]>=1 ? 1 : 0; + // The fifth corner has all coordinate offsets = 1, so no need to look that up. + + double x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords + double y1 = y0 - j1 + G4; + double z1 = z0 - k1 + G4; + double w1 = w0 - l1 + G4; + double x2 = x0 - i2 + 2.0f*G4; // Offsets for third corner in (x,y,z,w) coords + double y2 = y0 - j2 + 2.0f*G4; + double z2 = z0 - k2 + 2.0f*G4; + double w2 = w0 - l2 + 2.0f*G4; + double x3 = x0 - i3 + 3.0f*G4; // Offsets for fourth corner in (x,y,z,w) coords + double y3 = y0 - j3 + 3.0f*G4; + double z3 = z0 - k3 + 3.0f*G4; + double w3 = w0 - l3 + 3.0f*G4; + double x4 = x0 - 1.0f + 4.0f*G4; // Offsets for last corner in (x,y,z,w) coords + double y4 = y0 - 1.0f + 4.0f*G4; + double z4 = z0 - 1.0f + 4.0f*G4; + double w4 = w0 - 1.0f + 4.0f*G4; + + // Wrap the integer indices at 256, to avoid indexing perm[] out of bounds + int ii = i & 0xff; + int jj = j & 0xff; + int kk = k & 0xff; + int ll = l & 0xff; + + // Calculate the contribution from the five corners + double t0 = 0.6f - x0*x0 - y0*y0 - z0*z0 - w0*w0; + if(t0 < 0.0f) n0 = 0.0f; + else { + t0 *= t0; + n0 = t0 * t0 * grad(perm[ii+perm[jj+perm[kk+perm[ll]]]], x0, y0, z0, w0); + } + + double t1 = 0.6f - x1*x1 - y1*y1 - z1*z1 - w1*w1; + if(t1 < 0.0f) n1 = 0.0f; + else { + t1 *= t1; + n1 = t1 * t1 * grad(perm[ii+i1+perm[jj+j1+perm[kk+k1+perm[ll+l1]]]], x1, y1, z1, w1); + } + + double t2 = 0.6f - x2*x2 - y2*y2 - z2*z2 - w2*w2; + if(t2 < 0.0f) n2 = 0.0f; + else { + t2 *= t2; + n2 = t2 * t2 * grad(perm[ii+i2+perm[jj+j2+perm[kk+k2+perm[ll+l2]]]], x2, y2, z2, w2); + } + + double t3 = 0.6f - x3*x3 - y3*y3 - z3*z3 - w3*w3; + if(t3 < 0.0f) n3 = 0.0f; + else { + t3 *= t3; + n3 = t3 * t3 * grad(perm[ii+i3+perm[jj+j3+perm[kk+k3+perm[ll+l3]]]], x3, y3, z3, w3); + } + + double t4 = 0.6f - x4*x4 - y4*y4 - z4*z4 - w4*w4; + if(t4 < 0.0f) n4 = 0.0f; + else { + t4 *= t4; + n4 = t4 * t4 * grad(perm[ii+1+perm[jj+1+perm[kk+1+perm[ll+1]]]], x4, y4, z4, w4); + } + + // Sum up and scale the result to cover the range [-1,1] + return 27.3f * (n0 + n1 + n2 + n3 + n4); // TODO: The scale factor is preliminary! +} +//--------------------------------------------------------------------- diff --git a/src/libraries/noise1234/simplexnoise1234.h b/src/libraries/noise1234/simplexnoise1234.h index 33bb25b59..023a01e96 100644 --- a/src/libraries/noise1234/simplexnoise1234.h +++ b/src/libraries/noise1234/simplexnoise1234.h @@ -13,8 +13,7 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. -// Modified by the LOVE Development Team to remove 3D and 4D implementations due -// to patent issues. +// Modified by the LOVE Development Team to use double precision. /** \file \brief Declares the SimplexNoise1234 class for producing Perlin simplex noise. @@ -37,10 +36,13 @@ class SimplexNoise1234 { */ static float noise( double x ); static float noise( double x, double y ); + static float noise( double x, double y, double z ); + static float noise( double x, double y, double z, double w); private: static unsigned char perm[]; static double grad( int hash, double x ); static double grad( int hash, double x, double y ); - + static double grad( int hash, double x, double y, double z ); + static double grad( int hash, double x, double y, double z, double t ); };