aboutsummaryrefslogtreecommitdiff
path: root/src/scriptapi_noise.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/scriptapi_noise.cpp')
-rw-r--r--src/scriptapi_noise.cpp389
1 files changed, 389 insertions, 0 deletions
diff --git a/src/scriptapi_noise.cpp b/src/scriptapi_noise.cpp
new file mode 100644
index 000000000..86f6e3097
--- /dev/null
+++ b/src/scriptapi_noise.cpp
@@ -0,0 +1,389 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "scriptapi.h"
+#include "scriptapi_noise.h"
+#include "scriptapi_types.h"
+#include "script.h"
+
+#include <irr_v2d.h>
+
+
+// garbage collector
+int LuaPerlinNoise::gc_object(lua_State *L)
+{
+ LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+int LuaPerlinNoise::l_get2d(lua_State *L)
+{
+ LuaPerlinNoise *o = checkobject(L, 1);
+ v2f pos2d = read_v2f(L,2);
+ lua_Number val = noise2d_perlin(pos2d.X/o->scale, pos2d.Y/o->scale, o->seed, o->octaves, o->persistence);
+ lua_pushnumber(L, val);
+ return 1;
+}
+int LuaPerlinNoise::l_get3d(lua_State *L)
+{
+ LuaPerlinNoise *o = checkobject(L, 1);
+ v3f pos3d = read_v3f(L,2);
+ lua_Number val = noise3d_perlin(pos3d.X/o->scale, pos3d.Y/o->scale, pos3d.Z/o->scale, o->seed, o->octaves, o->persistence);
+ lua_pushnumber(L, val);
+ return 1;
+}
+
+
+LuaPerlinNoise::LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence,
+ float a_scale):
+ seed(a_seed),
+ octaves(a_octaves),
+ persistence(a_persistence),
+ scale(a_scale)
+{
+}
+
+LuaPerlinNoise::~LuaPerlinNoise()
+{
+}
+
+// LuaPerlinNoise(seed, octaves, persistence, scale)
+// Creates an LuaPerlinNoise and leaves it on top of stack
+int LuaPerlinNoise::create_object(lua_State *L)
+{
+ int seed = luaL_checkint(L, 1);
+ int octaves = luaL_checkint(L, 2);
+ float persistence = luaL_checknumber(L, 3);
+ float scale = luaL_checknumber(L, 4);
+ LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+LuaPerlinNoise* LuaPerlinNoise::checkobject(lua_State *L, int narg)
+{
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+ void *ud = luaL_checkudata(L, narg, className);
+ if(!ud) luaL_typerror(L, narg, className);
+ return *(LuaPerlinNoise**)ud; // unbox pointer
+}
+
+void LuaPerlinNoise::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+
+ // Can be created from Lua (PerlinNoise(seed, octaves, persistence)
+ lua_register(L, className, create_object);
+}
+
+const char LuaPerlinNoise::className[] = "PerlinNoise";
+const luaL_reg LuaPerlinNoise::methods[] = {
+ luamethod(LuaPerlinNoise, get2d),
+ luamethod(LuaPerlinNoise, get3d),
+ {0,0}
+};
+
+/*
+ PerlinNoiseMap
+ */
+
+
+int LuaPerlinNoiseMap::gc_object(lua_State *L)
+{
+ LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+int LuaPerlinNoiseMap::l_get2dMap(lua_State *L)
+{
+ int i = 0;
+
+ LuaPerlinNoiseMap *o = checkobject(L, 1);
+ v2f p = read_v2f(L, 2);
+
+ Noise *n = o->noise;
+ n->perlinMap2D(p.X, p.Y);
+
+ lua_newtable(L);
+ for (int y = 0; y != n->sy; y++) {
+ lua_newtable(L);
+ for (int x = 0; x != n->sx; x++) {
+ float noiseval = n->np->offset + n->np->scale * n->result[i++];
+ lua_pushnumber(L, noiseval);
+ lua_rawseti(L, -2, x + 1);
+ }
+ lua_rawseti(L, -2, y + 1);
+ }
+ return 1;
+}
+
+int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
+{
+ int i = 0;
+
+ LuaPerlinNoiseMap *o = checkobject(L, 1);
+ v3f p = read_v3f(L, 2);
+
+ Noise *n = o->noise;
+ n->perlinMap3D(p.X, p.Y, p.Z);
+
+ lua_newtable(L);
+ for (int z = 0; z != n->sz; z++) {
+ lua_newtable(L);
+ for (int y = 0; y != n->sy; y++) {
+ lua_newtable(L);
+ for (int x = 0; x != n->sx; x++) {
+ lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]);
+ lua_rawseti(L, -2, x + 1);
+ }
+ lua_rawseti(L, -2, y + 1);
+ }
+ lua_rawseti(L, -2, z + 1);
+ }
+ return 1;
+}
+
+LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size) {
+ noise = new Noise(np, seed, size.X, size.Y, size.Z);
+}
+
+LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
+{
+ delete noise->np;
+ delete noise;
+}
+
+// LuaPerlinNoiseMap(np, size)
+// Creates an LuaPerlinNoiseMap and leaves it on top of stack
+int LuaPerlinNoiseMap::create_object(lua_State *L)
+{
+ NoiseParams *np = read_noiseparams(L, 1);
+ if (!np)
+ return 0;
+ v3s16 size = read_v3s16(L, 2);
+
+ LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+LuaPerlinNoiseMap* LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
+{
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+
+ void *ud = luaL_checkudata(L, narg, className);
+ if (!ud)
+ luaL_typerror(L, narg, className);
+
+ return *(LuaPerlinNoiseMap **)ud; // unbox pointer
+}
+
+void LuaPerlinNoiseMap::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+
+ // Can be created from Lua (PerlinNoiseMap(np, size)
+ lua_register(L, className, create_object);
+}
+
+const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
+const luaL_reg LuaPerlinNoiseMap::methods[] = {
+ luamethod(LuaPerlinNoiseMap, get2dMap),
+ luamethod(LuaPerlinNoiseMap, get3dMap),
+ {0,0}
+};
+
+/*
+ NoiseParams
+*/
+NoiseParams *read_noiseparams(lua_State *L, int index)
+{
+ if (index < 0)
+ index = lua_gettop(L) + 1 + index;
+
+ if (!lua_istable(L, index))
+ return NULL;
+
+ NoiseParams *np = new NoiseParams;
+
+ np->offset = getfloatfield_default(L, index, "offset", 0.0);
+ np->scale = getfloatfield_default(L, index, "scale", 0.0);
+ lua_getfield(L, index, "spread");
+ np->spread = read_v3f(L, -1);
+ np->seed = getintfield_default(L, index, "seed", 0);
+ np->octaves = getintfield_default(L, index, "octaves", 0);
+ np->persist = getfloatfield_default(L, index, "persist", 0.0);
+
+ return np;
+}
+
+/*
+ LuaPseudoRandom
+*/
+
+// garbage collector
+int LuaPseudoRandom::gc_object(lua_State *L)
+{
+ LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+// next(self, min=0, max=32767) -> get next value
+int LuaPseudoRandom::l_next(lua_State *L)
+{
+ LuaPseudoRandom *o = checkobject(L, 1);
+ int min = 0;
+ int max = 32767;
+ lua_settop(L, 3); // Fill 2 and 3 with nil if they don't exist
+ if(!lua_isnil(L, 2))
+ min = luaL_checkinteger(L, 2);
+ if(!lua_isnil(L, 3))
+ max = luaL_checkinteger(L, 3);
+ if(max < min){
+ errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
+ throw LuaError(L, "PseudoRandom.next(): max < min");
+ }
+ if(max - min != 32767 && max - min > 32767/5)
+ throw LuaError(L, "PseudoRandom.next() max-min is not 32767 and is > 32768/5. This is disallowed due to the bad random distribution the implementation would otherwise make.");
+ PseudoRandom &pseudo = o->m_pseudo;
+ int val = pseudo.next();
+ val = (val % (max-min+1)) + min;
+ lua_pushinteger(L, val);
+ return 1;
+}
+
+
+LuaPseudoRandom::LuaPseudoRandom(int seed):
+ m_pseudo(seed)
+{
+}
+
+LuaPseudoRandom::~LuaPseudoRandom()
+{
+}
+
+const PseudoRandom& LuaPseudoRandom::getItem() const
+{
+ return m_pseudo;
+}
+PseudoRandom& LuaPseudoRandom::getItem()
+{
+ return m_pseudo;
+}
+
+// LuaPseudoRandom(seed)
+// Creates an LuaPseudoRandom and leaves it on top of stack
+int LuaPseudoRandom::create_object(lua_State *L)
+{
+ int seed = luaL_checknumber(L, 1);
+ LuaPseudoRandom *o = new LuaPseudoRandom(seed);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+LuaPseudoRandom* LuaPseudoRandom::checkobject(lua_State *L, int narg)
+{
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+ void *ud = luaL_checkudata(L, narg, className);
+ if(!ud) luaL_typerror(L, narg, className);
+ return *(LuaPseudoRandom**)ud; // unbox pointer
+}
+
+void LuaPseudoRandom::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+
+ // Can be created from Lua (LuaPseudoRandom(seed))
+ lua_register(L, className, create_object);
+}
+
+const char LuaPseudoRandom::className[] = "PseudoRandom";
+const luaL_reg LuaPseudoRandom::methods[] = {
+ luamethod(LuaPseudoRandom, next),
+ {0,0}
+};