From 6b493c164ed07833db44a93d1e77fa7a4e2c946a Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 24 Sep 2022 18:25:54 +0800 Subject: [PATCH 1/4] Fix SimplexNoise1234 file encoding. --- src/libraries/noise1234/simplexnoise1234.cpp | 2 +- src/libraries/noise1234/simplexnoise1234.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/noise1234/simplexnoise1234.cpp b/src/libraries/noise1234/simplexnoise1234.cpp index b2caec4ad..71039d757 100644 --- a/src/libraries/noise1234/simplexnoise1234.cpp +++ b/src/libraries/noise1234/simplexnoise1234.cpp @@ -1,5 +1,5 @@ // SimplexNoise1234 -// Copyright © 2003-2011, Stefan Gustavson +// Copyright © 2003-2011, Stefan Gustavson // // Contact: stegu@itn.liu.se // diff --git a/src/libraries/noise1234/simplexnoise1234.h b/src/libraries/noise1234/simplexnoise1234.h index 137edf5dc..33bb25b59 100644 --- a/src/libraries/noise1234/simplexnoise1234.h +++ b/src/libraries/noise1234/simplexnoise1234.h @@ -1,5 +1,5 @@ // SimplexNoise1234 -// Copyright � 2003-2011, Stefan Gustavson +// Copyright © 2003-2011, Stefan Gustavson // // Contact: stegu@itn.liu.se // From da27af1eda3f7c3352ef233dc0f5065385d2b87a Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 24 Sep 2022 18:37:07 +0800 Subject: [PATCH 2/4] 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 ); }; From b285c2c866b6cbe4de5fe4efbeb993ba0f19f8ca Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 24 Sep 2022 23:51:12 +0800 Subject: [PATCH 3/4] Add love.math.perlinNoise and love.math.simplexNoise. --- src/modules/math/MathModule.h | 41 +++++++++++---- src/modules/math/wrap_Math.cpp | 95 +++++++++++++++++++++++++++++----- src/modules/math/wrap_Math.lua | 44 +++++++++++++--- 3 files changed, 150 insertions(+), 30 deletions(-) diff --git a/src/modules/math/MathModule.h b/src/modules/math/MathModule.h index 849764ec4..231b1c42c 100644 --- a/src/modules/math/MathModule.h +++ b/src/modules/math/MathModule.h @@ -83,10 +83,14 @@ float linearToGamma(float c); * * @return Noise value in the range of [0, 1]. **/ -static float noise1(double x); -static float noise2(double x, double y); -static float noise3(double x, double y, double z); -static float noise4(double x, double y, double z, double w); +static float simplexNoise1(double x); +static float simplexNoise2(double x, double y); +static float simplexNoise3(double x, double y, double z); +static float simplexNoise4(double x, double y, double z, double w); +static float perlinNoise1(double x); +static float perlinNoise2(double x, double y); +static float perlinNoise3(double x, double y, double z); +static float perlinNoise4(double x, double y, double z, double w); class Math : public Module @@ -132,25 +136,42 @@ private: }; // Math -static inline float noise1(double x) +static inline float simplexNoise1(double x) { return SimplexNoise1234::noise(x) * 0.5f + 0.5f; } -static inline float noise2(double x, double y) +static inline float simplexNoise2(double x, double y) { return SimplexNoise1234::noise(x, y) * 0.5f + 0.5f; } -// Perlin noise is used instead of Simplex noise in the 3D and 4D cases to avoid -// patent issues. +static inline float simplexNoise3(double x, double y, double z) +{ + return SimplexNoise1234::noise(x, y, z) * 0.5f + 0.5f; +} -static inline float noise3(double x, double y, double z) +static inline float simplexNoise4(double x, double y, double z, double w) +{ + return SimplexNoise1234::noise(x, y, z, w) * 0.5f + 0.5f; +} + +static inline float perlinNoise1(double x) +{ + return Noise1234::noise(x) * 0.5f + 0.5f; +} + +static inline float perlinNoise2(double x, double y) +{ + return Noise1234::noise(x, y) * 0.5f + 0.5f; +} + +static inline float perlinNoise3(double x, double y, double z) { return Noise1234::noise(x, y, z) * 0.5f + 0.5f; } -static inline float noise4(double x, double y, double z, double w) +static inline float perlinNoise4(double x, double y, double z, double w) { return Noise1234::noise(x, y, z, w) * 0.5f + 0.5f; } diff --git a/src/modules/math/wrap_Math.cpp b/src/modules/math/wrap_Math.cpp index 1c237acd2..1e510ae24 100644 --- a/src/modules/math/wrap_Math.cpp +++ b/src/modules/math/wrap_Math.cpp @@ -329,16 +329,76 @@ int w_noise(lua_State *L) switch (nargs) { case 1: - val = noise1(args[0]); + val = simplexNoise1(args[0]); break; case 2: - val = noise2(args[0], args[1]); + val = simplexNoise2(args[0], args[1]); break; case 3: - val = noise3(args[0], args[1], args[2]); + val = perlinNoise3(args[0], args[1], args[2]); break; case 4: - val = noise4(args[0], args[1], args[2], args[3]); + val = perlinNoise4(args[0], args[1], args[2], args[3]); + break; + } + + lua_pushnumber(L, (lua_Number) val); + return 1; +} + +int w_perlinNoise(lua_State* L) +{ + int nargs = std::min(std::max(lua_gettop(L), 1), 4); + double args[4]; + + for (int i = 0; i < nargs; i++) + args[i] = luaL_checknumber(L, i + 1); + + float val = 0.0f; + + switch (nargs) + { + case 1: + val = perlinNoise1(args[0]); + break; + case 2: + val = perlinNoise2(args[0], args[1]); + break; + case 3: + val = perlinNoise3(args[0], args[1], args[2]); + break; + case 4: + val = perlinNoise4(args[0], args[1], args[2], args[3]); + break; + } + + lua_pushnumber(L, (lua_Number) val); + return 1; +} + +int w_simplexNoise(lua_State* L) +{ + int nargs = std::min(std::max(lua_gettop(L), 1), 4); + double args[4]; + + for (int i = 0; i < nargs; i++) + args[i] = luaL_checknumber(L, i + 1); + + float val = 0.0f; + + switch (nargs) + { + case 1: + val = simplexNoise1(args[0]); + break; + case 2: + val = simplexNoise2(args[0], args[1]); + break; + case 3: + val = simplexNoise3(args[0], args[1], args[2]); + break; + case 4: + val = simplexNoise4(args[0], args[1], args[2], args[3]); break; } @@ -349,10 +409,14 @@ int w_noise(lua_State *L) // C functions in a struct, necessary for the FFI versions of math functions. struct FFI_Math { - float (*noise1)(double x); - float (*noise2)(double x, double y); - float (*noise3)(double x, double y, double z); - float (*noise4)(double x, double y, double z, double w); + float (*snoise1)(double x); + float (*snoise2)(double x, double y); + float (*snoise3)(double x, double y, double z); + float (*snoise4)(double x, double y, double z, double w); + float (*pnoise1)(double x); + float (*pnoise2)(double x, double y); + float (*pnoise3)(double x, double y, double z); + float (*pnoise4)(double x, double y, double z, double w); float (*gammaToLinear)(float c); float (*linearToGamma)(float c); @@ -360,10 +424,15 @@ struct FFI_Math static FFI_Math ffifuncs = { - noise1, - noise2, - noise3, - noise4, + simplexNoise1, + simplexNoise2, + simplexNoise3, + simplexNoise4, + + perlinNoise1, + perlinNoise2, + perlinNoise3, + perlinNoise4, gammaToLinear, linearToGamma, @@ -383,6 +452,8 @@ static const luaL_Reg functions[] = { "gammaToLinear", w_gammaToLinear }, { "linearToGamma", w_linearToGamma }, { "noise", w_noise }, + { "perlinNoise", w_perlinNoise }, + { "simplexNoise", w_simplexNoise }, { 0, 0 } }; diff --git a/src/modules/math/wrap_Math.lua b/src/modules/math/wrap_Math.lua index a99c90202..17eb32257 100644 --- a/src/modules/math/wrap_Math.lua +++ b/src/modules/math/wrap_Math.lua @@ -93,10 +93,14 @@ if not status then return end pcall(ffi.cdef, [[ typedef struct FFI_Math { - float (*noise1)(double x); - float (*noise2)(double x, double y); - float (*noise3)(double x, double y, double z); - float (*noise4)(double x, double y, double z, double w); + float (*snoise1)(double x); + float (*snoise2)(double x, double y); + float (*snoise3)(double x, double y, double z); + float (*snoise4)(double x, double y, double z, double w); + float (*pnoise1)(double x); + float (*pnoise2)(double x, double y); + float (*pnoise3)(double x, double y, double z); + float (*pnoise4)(double x, double y, double z, double w); float (*gammaToLinear)(float c); float (*linearToGamma)(float c); @@ -110,13 +114,37 @@ local ffifuncs = ffi.cast("FFI_Math **", ffifuncspointer_str)[0] function love_math.noise(x, y, z, w) if w ~= nil then - return tonumber(ffifuncs.noise4(x, y, z, w)) + return tonumber(ffifuncs.pnoise4(x, y, z, w)) elseif z ~= nil then - return tonumber(ffifuncs.noise3(x, y, z)) + return tonumber(ffifuncs.pnoise3(x, y, z)) elseif y ~= nil then - return tonumber(ffifuncs.noise2(x, y)) + return tonumber(ffifuncs.snoise2(x, y)) else - return tonumber(ffifuncs.noise1(x)) + return tonumber(ffifuncs.snoise1(x)) + end +end + +function love_math.perlinNoise(x, y, z, w) + if w ~= nil then + return tonumber(ffifuncs.pnoise4(x, y, z, w)) + elseif z ~= nil then + return tonumber(ffifuncs.pnoise3(x, y, z)) + elseif y ~= nil then + return tonumber(ffifuncs.pnoise2(x, y)) + else + return tonumber(ffifuncs.pnoise1(x)) + end +end + +function love_math.simplexNoise(x, y, z, w) + if w ~= nil then + return tonumber(ffifuncs.snoise4(x, y, z, w)) + elseif z ~= nil then + return tonumber(ffifuncs.snoise3(x, y, z)) + elseif y ~= nil then + return tonumber(ffifuncs.snoise2(x, y)) + else + return tonumber(ffifuncs.snoise1(x)) end end From ed840b24eac466f710116f29e4dc29f880344b0c Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sun, 25 Sep 2022 00:01:11 +0800 Subject: [PATCH 4/4] Deprecate love.math.noise --- src/modules/math/wrap_Math.cpp | 2 ++ src/modules/math/wrap_Math.lua | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/modules/math/wrap_Math.cpp b/src/modules/math/wrap_Math.cpp index 1e510ae24..fa4bc5454 100644 --- a/src/modules/math/wrap_Math.cpp +++ b/src/modules/math/wrap_Math.cpp @@ -318,6 +318,8 @@ int w_linearToGamma(lua_State *L) int w_noise(lua_State *L) { + luax_markdeprecated(L, 1, "love.math.noise", API_FUNCTION, DEPRECATED_REPLACED, "love.math.perlinNoise or love.math.simplexNoise"); + int nargs = std::min(std::max(lua_gettop(L), 1), 4); double args[4]; diff --git a/src/modules/math/wrap_Math.lua b/src/modules/math/wrap_Math.lua index 17eb32257..d5ff62ece 100644 --- a/src/modules/math/wrap_Math.lua +++ b/src/modules/math/wrap_Math.lua @@ -113,6 +113,8 @@ local ffifuncs = ffi.cast("FFI_Math **", ffifuncspointer_str)[0] -- Overwrite some regular love.math functions with FFI implementations. function love_math.noise(x, y, z, w) + love.markDeprecated(2, "love.math.noise", "function", "replaced", "love.math.perlinNoise or love.math.simplexNoise") + if w ~= nil then return tonumber(ffifuncs.pnoise4(x, y, z, w)) elseif z ~= nil then