From b285c2c866b6cbe4de5fe4efbeb993ba0f19f8ca Mon Sep 17 00:00:00 2001 From: Miku AuahDark Date: Sat, 24 Sep 2022 23:51:12 +0800 Subject: [PATCH] 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