]> git.lizzy.rs Git - dragonfireclient.git/blob - src/scriptapi_noise.cpp
Pre-select current game in world creation dialog
[dragonfireclient.git] / src / scriptapi_noise.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "scriptapi.h"
21 #include "scriptapi_noise.h"
22 #include "scriptapi_types.h"
23 #include "script.h"
24
25 // garbage collector
26 int LuaPerlinNoise::gc_object(lua_State *L)
27 {
28         LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
29         delete o;
30         return 0;
31 }
32
33 int LuaPerlinNoise::l_get2d(lua_State *L)
34 {
35         LuaPerlinNoise *o = checkobject(L, 1);
36         v2f pos2d = read_v2f(L,2);
37         lua_Number val = noise2d_perlin(pos2d.X/o->scale, pos2d.Y/o->scale, o->seed, o->octaves, o->persistence);
38         lua_pushnumber(L, val);
39         return 1;
40 }
41 int LuaPerlinNoise::l_get3d(lua_State *L)
42 {
43         LuaPerlinNoise *o = checkobject(L, 1);
44         v3f pos3d = read_v3f(L,2);
45         lua_Number val = noise3d_perlin(pos3d.X/o->scale, pos3d.Y/o->scale, pos3d.Z/o->scale, o->seed, o->octaves, o->persistence);
46         lua_pushnumber(L, val);
47         return 1;
48 }
49
50
51 LuaPerlinNoise::LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence,
52                 float a_scale):
53         seed(a_seed),
54         octaves(a_octaves),
55         persistence(a_persistence),
56         scale(a_scale)
57 {
58 }
59
60 LuaPerlinNoise::~LuaPerlinNoise()
61 {
62 }
63
64 // LuaPerlinNoise(seed, octaves, persistence, scale)
65 // Creates an LuaPerlinNoise and leaves it on top of stack
66 int LuaPerlinNoise::create_object(lua_State *L)
67 {
68         int seed = luaL_checkint(L, 1);
69         int octaves = luaL_checkint(L, 2);
70         float persistence = luaL_checknumber(L, 3);
71         float scale = luaL_checknumber(L, 4);
72         LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale);
73         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
74         luaL_getmetatable(L, className);
75         lua_setmetatable(L, -2);
76         return 1;
77 }
78
79 LuaPerlinNoise* LuaPerlinNoise::checkobject(lua_State *L, int narg)
80 {
81         luaL_checktype(L, narg, LUA_TUSERDATA);
82         void *ud = luaL_checkudata(L, narg, className);
83         if(!ud) luaL_typerror(L, narg, className);
84         return *(LuaPerlinNoise**)ud;  // unbox pointer
85 }
86
87 void LuaPerlinNoise::Register(lua_State *L)
88 {
89         lua_newtable(L);
90         int methodtable = lua_gettop(L);
91         luaL_newmetatable(L, className);
92         int metatable = lua_gettop(L);
93
94         lua_pushliteral(L, "__metatable");
95         lua_pushvalue(L, methodtable);
96         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
97
98         lua_pushliteral(L, "__index");
99         lua_pushvalue(L, methodtable);
100         lua_settable(L, metatable);
101
102         lua_pushliteral(L, "__gc");
103         lua_pushcfunction(L, gc_object);
104         lua_settable(L, metatable);
105
106         lua_pop(L, 1);  // drop metatable
107
108         luaL_openlib(L, 0, methods, 0);  // fill methodtable
109         lua_pop(L, 1);  // drop methodtable
110
111         // Can be created from Lua (PerlinNoise(seed, octaves, persistence)
112         lua_register(L, className, create_object);
113 }
114
115 const char LuaPerlinNoise::className[] = "PerlinNoise";
116 const luaL_reg LuaPerlinNoise::methods[] = {
117         luamethod(LuaPerlinNoise, get2d),
118         luamethod(LuaPerlinNoise, get3d),
119         {0,0}
120 };
121
122 /*
123   PerlinNoiseMap
124  */
125
126
127 int LuaPerlinNoiseMap::gc_object(lua_State *L)
128 {
129         LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
130         delete o;
131         return 0;
132 }
133
134 int LuaPerlinNoiseMap::l_get2dMap(lua_State *L)
135 {
136         int i = 0;
137
138         LuaPerlinNoiseMap *o = checkobject(L, 1);
139         v2f p = read_v2f(L, 2);
140
141         Noise *n = o->noise;
142         n->perlinMap2D(p.X, p.Y);
143
144         lua_newtable(L);
145         for (int y = 0; y != n->sy; y++) {
146                 lua_newtable(L);
147                 for (int x = 0; x != n->sx; x++) {
148                         float noiseval = n->np->offset + n->np->scale * n->result[i++];
149                         lua_pushnumber(L, noiseval);
150                         lua_rawseti(L, -2, x + 1);
151                 }
152                 lua_rawseti(L, -2, y + 1);
153         }
154         return 1;
155 }
156
157 int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
158 {
159         int i = 0;
160
161         LuaPerlinNoiseMap *o = checkobject(L, 1);
162         v3f p = read_v3f(L, 2);
163
164         Noise *n = o->noise;
165         n->perlinMap3D(p.X, p.Y, p.Z);
166
167         lua_newtable(L);
168         for (int z = 0; z != n->sz; z++) {
169                 lua_newtable(L);
170                 for (int y = 0; y != n->sy; y++) {
171                         lua_newtable(L);
172                         for (int x = 0; x != n->sx; x++) {
173                                 lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]);
174                                 lua_rawseti(L, -2, x + 1);
175                         }
176                         lua_rawseti(L, -2, y + 1);
177                 }
178                 lua_rawseti(L, -2, z + 1);
179         }
180         return 1;
181 }
182
183 LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size) {
184         noise = new Noise(np, seed, size.X, size.Y, size.Z);
185 }
186
187 LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
188 {
189         delete noise->np;
190         delete noise;
191 }
192
193 // LuaPerlinNoiseMap(np, size)
194 // Creates an LuaPerlinNoiseMap and leaves it on top of stack
195 int LuaPerlinNoiseMap::create_object(lua_State *L)
196 {
197         NoiseParams *np = read_noiseparams(L, 1);
198         if (!np)
199                 return 0;
200         v3s16 size = read_v3s16(L, 2);
201
202         LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size);
203         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
204         luaL_getmetatable(L, className);
205         lua_setmetatable(L, -2);
206         return 1;
207 }
208
209 LuaPerlinNoiseMap* LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
210 {
211         luaL_checktype(L, narg, LUA_TUSERDATA);
212
213         void *ud = luaL_checkudata(L, narg, className);
214         if (!ud)
215                 luaL_typerror(L, narg, className);
216
217         return *(LuaPerlinNoiseMap **)ud;  // unbox pointer
218 }
219
220 void LuaPerlinNoiseMap::Register(lua_State *L)
221 {
222         lua_newtable(L);
223         int methodtable = lua_gettop(L);
224         luaL_newmetatable(L, className);
225         int metatable = lua_gettop(L);
226
227         lua_pushliteral(L, "__metatable");
228         lua_pushvalue(L, methodtable);
229         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
230
231         lua_pushliteral(L, "__index");
232         lua_pushvalue(L, methodtable);
233         lua_settable(L, metatable);
234
235         lua_pushliteral(L, "__gc");
236         lua_pushcfunction(L, gc_object);
237         lua_settable(L, metatable);
238
239         lua_pop(L, 1);  // drop metatable
240
241         luaL_openlib(L, 0, methods, 0);  // fill methodtable
242         lua_pop(L, 1);  // drop methodtable
243
244         // Can be created from Lua (PerlinNoiseMap(np, size)
245         lua_register(L, className, create_object);
246 }
247
248 const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
249 const luaL_reg LuaPerlinNoiseMap::methods[] = {
250         luamethod(LuaPerlinNoiseMap, get2dMap),
251         luamethod(LuaPerlinNoiseMap, get3dMap),
252         {0,0}
253 };
254
255 /*
256         NoiseParams
257 */
258 NoiseParams *read_noiseparams(lua_State *L, int index)
259 {
260         if (index < 0)
261                 index = lua_gettop(L) + 1 + index;
262
263         if (!lua_istable(L, index))
264                 return NULL;
265
266         NoiseParams *np = new NoiseParams;
267
268         np->offset  = getfloatfield_default(L, index, "offset", 0.0);
269         np->scale   = getfloatfield_default(L, index, "scale", 0.0);
270         lua_getfield(L, index, "spread");
271         np->spread  = read_v3f(L, -1);
272         lua_pop(L, 1);
273         np->seed    = getintfield_default(L, index, "seed", 0);
274         np->octaves = getintfield_default(L, index, "octaves", 0);
275         np->persist = getfloatfield_default(L, index, "persist", 0.0);
276
277         return np;
278 }
279
280
281 /*
282         LuaPseudoRandom
283 */
284
285 // garbage collector
286 int LuaPseudoRandom::gc_object(lua_State *L)
287 {
288         LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
289         delete o;
290         return 0;
291 }
292
293 // next(self, min=0, max=32767) -> get next value
294 int LuaPseudoRandom::l_next(lua_State *L)
295 {
296         LuaPseudoRandom *o = checkobject(L, 1);
297         int min = 0;
298         int max = 32767;
299         lua_settop(L, 3); // Fill 2 and 3 with nil if they don't exist
300         if(!lua_isnil(L, 2))
301                 min = luaL_checkinteger(L, 2);
302         if(!lua_isnil(L, 3))
303                 max = luaL_checkinteger(L, 3);
304         if(max < min){
305                 errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
306                 throw LuaError(L, "PseudoRandom.next(): max < min");
307         }
308         if(max - min != 32767 && max - min > 32767/5)
309                 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.");
310         PseudoRandom &pseudo = o->m_pseudo;
311         int val = pseudo.next();
312         val = (val % (max-min+1)) + min;
313         lua_pushinteger(L, val);
314         return 1;
315 }
316
317
318 LuaPseudoRandom::LuaPseudoRandom(int seed):
319         m_pseudo(seed)
320 {
321 }
322
323 LuaPseudoRandom::~LuaPseudoRandom()
324 {
325 }
326
327 const PseudoRandom& LuaPseudoRandom::getItem() const
328 {
329         return m_pseudo;
330 }
331 PseudoRandom& LuaPseudoRandom::getItem()
332 {
333         return m_pseudo;
334 }
335
336 // LuaPseudoRandom(seed)
337 // Creates an LuaPseudoRandom and leaves it on top of stack
338 int LuaPseudoRandom::create_object(lua_State *L)
339 {
340         int seed = luaL_checknumber(L, 1);
341         LuaPseudoRandom *o = new LuaPseudoRandom(seed);
342         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
343         luaL_getmetatable(L, className);
344         lua_setmetatable(L, -2);
345         return 1;
346 }
347
348 LuaPseudoRandom* LuaPseudoRandom::checkobject(lua_State *L, int narg)
349 {
350         luaL_checktype(L, narg, LUA_TUSERDATA);
351         void *ud = luaL_checkudata(L, narg, className);
352         if(!ud) luaL_typerror(L, narg, className);
353         return *(LuaPseudoRandom**)ud;  // unbox pointer
354 }
355
356 void LuaPseudoRandom::Register(lua_State *L)
357 {
358         lua_newtable(L);
359         int methodtable = lua_gettop(L);
360         luaL_newmetatable(L, className);
361         int metatable = lua_gettop(L);
362
363         lua_pushliteral(L, "__metatable");
364         lua_pushvalue(L, methodtable);
365         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
366
367         lua_pushliteral(L, "__index");
368         lua_pushvalue(L, methodtable);
369         lua_settable(L, metatable);
370
371         lua_pushliteral(L, "__gc");
372         lua_pushcfunction(L, gc_object);
373         lua_settable(L, metatable);
374
375         lua_pop(L, 1);  // drop metatable
376
377         luaL_openlib(L, 0, methods, 0);  // fill methodtable
378         lua_pop(L, 1);  // drop methodtable
379
380         // Can be created from Lua (LuaPseudoRandom(seed))
381         lua_register(L, className, create_object);
382 }
383
384 const char LuaPseudoRandom::className[] = "PseudoRandom";
385 const luaL_reg LuaPseudoRandom::methods[] = {
386         luamethod(LuaPseudoRandom, next),
387         {0,0}
388 };