Browse Source

Add love.math.perlinNoise and love.math.simplexNoise.

Miku AuahDark 2 years ago
parent
commit
b285c2c866
3 changed files with 150 additions and 30 deletions
  1. 31 10
      src/modules/math/MathModule.h
  2. 83 12
      src/modules/math/wrap_Math.cpp
  3. 36 8
      src/modules/math/wrap_Math.lua

+ 31 - 10
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 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 noise3(double x, double y, double z)
+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;
 }

+ 83 - 12
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 }
 };

+ 36 - 8
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