]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/lua_api/l_noise.cpp
Omnicleanup: header cleanup, add ModApiUtil shared between game and mainmenu
[dragonfireclient.git] / src / script / lua_api / l_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 "lua_api/l_noise.h"
21 #include "lua_api/l_internal.h"
22 #include "common/c_converter.h"
23 #include "common/c_content.h"
24 #include "log.h"
25
26 // garbage collector
27 int LuaPerlinNoise::gc_object(lua_State *L)
28 {
29         LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
30         delete o;
31         return 0;
32 }
33
34 int LuaPerlinNoise::l_get2d(lua_State *L)
35 {
36         NO_MAP_LOCK_REQUIRED;
37         LuaPerlinNoise *o = checkobject(L, 1);
38         v2f pos2d = read_v2f(L,2);
39         lua_Number val = noise2d_perlin(pos2d.X/o->scale, pos2d.Y/o->scale, o->seed, o->octaves, o->persistence);
40         lua_pushnumber(L, val);
41         return 1;
42 }
43 int LuaPerlinNoise::l_get3d(lua_State *L)
44 {
45         NO_MAP_LOCK_REQUIRED;
46         LuaPerlinNoise *o = checkobject(L, 1);
47         v3f pos3d = read_v3f(L,2);
48         lua_Number val = noise3d_perlin(pos3d.X/o->scale, pos3d.Y/o->scale, pos3d.Z/o->scale, o->seed, o->octaves, o->persistence);
49         lua_pushnumber(L, val);
50         return 1;
51 }
52
53
54 LuaPerlinNoise::LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence,
55                 float a_scale):
56         seed(a_seed),
57         octaves(a_octaves),
58         persistence(a_persistence),
59         scale(a_scale)
60 {
61 }
62
63 LuaPerlinNoise::~LuaPerlinNoise()
64 {
65 }
66
67 // LuaPerlinNoise(seed, octaves, persistence, scale)
68 // Creates an LuaPerlinNoise and leaves it on top of stack
69 int LuaPerlinNoise::create_object(lua_State *L)
70 {
71         NO_MAP_LOCK_REQUIRED;
72         int seed = luaL_checkint(L, 1);
73         int octaves = luaL_checkint(L, 2);
74         float persistence = luaL_checknumber(L, 3);
75         float scale = luaL_checknumber(L, 4);
76         LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale);
77         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
78         luaL_getmetatable(L, className);
79         lua_setmetatable(L, -2);
80         return 1;
81 }
82
83 LuaPerlinNoise* LuaPerlinNoise::checkobject(lua_State *L, int narg)
84 {
85         NO_MAP_LOCK_REQUIRED;
86         luaL_checktype(L, narg, LUA_TUSERDATA);
87         void *ud = luaL_checkudata(L, narg, className);
88         if(!ud) luaL_typerror(L, narg, className);
89         return *(LuaPerlinNoise**)ud;  // unbox pointer
90 }
91
92 void LuaPerlinNoise::Register(lua_State *L)
93 {
94         lua_newtable(L);
95         int methodtable = lua_gettop(L);
96         luaL_newmetatable(L, className);
97         int metatable = lua_gettop(L);
98
99         lua_pushliteral(L, "__metatable");
100         lua_pushvalue(L, methodtable);
101         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
102
103         lua_pushliteral(L, "__index");
104         lua_pushvalue(L, methodtable);
105         lua_settable(L, metatable);
106
107         lua_pushliteral(L, "__gc");
108         lua_pushcfunction(L, gc_object);
109         lua_settable(L, metatable);
110
111         lua_pop(L, 1);  // drop metatable
112
113         luaL_openlib(L, 0, methods, 0);  // fill methodtable
114         lua_pop(L, 1);  // drop methodtable
115
116         // Can be created from Lua (PerlinNoise(seed, octaves, persistence)
117         lua_register(L, className, create_object);
118 }
119
120 const char LuaPerlinNoise::className[] = "PerlinNoise";
121 const luaL_reg LuaPerlinNoise::methods[] = {
122         luamethod(LuaPerlinNoise, get2d),
123         luamethod(LuaPerlinNoise, get3d),
124         {0,0}
125 };
126
127 /*
128   PerlinNoiseMap
129  */
130
131
132 int LuaPerlinNoiseMap::gc_object(lua_State *L)
133 {
134         LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
135         delete o;
136         return 0;
137 }
138
139 int LuaPerlinNoiseMap::l_get2dMap(lua_State *L)
140 {
141         NO_MAP_LOCK_REQUIRED;
142         int i = 0;
143
144         LuaPerlinNoiseMap *o = checkobject(L, 1);
145         v2f p = read_v2f(L, 2);
146
147         Noise *n = o->noise;
148         n->perlinMap2D(p.X, p.Y);
149
150         lua_newtable(L);
151         for (int y = 0; y != n->sy; y++) {
152                 lua_newtable(L);
153                 for (int x = 0; x != n->sx; x++) {
154                         float noiseval = n->np->offset + n->np->scale * n->result[i++];
155                         lua_pushnumber(L, noiseval);
156                         lua_rawseti(L, -2, x + 1);
157                 }
158                 lua_rawseti(L, -2, y + 1);
159         }
160         return 1;
161 }
162
163 int LuaPerlinNoiseMap::l_get2dMap_flat(lua_State *L)
164 {
165         NO_MAP_LOCK_REQUIRED;
166
167         LuaPerlinNoiseMap *o = checkobject(L, 1);
168         v2f p = read_v2f(L, 2);
169
170         Noise *n = o->noise;
171         n->perlinMap2D(p.X, p.Y);
172
173         int maplen = n->sx * n->sy;
174         
175         lua_newtable(L);
176         for (int i = 0; i != maplen; i++) {
177                 float noiseval = n->np->offset + n->np->scale * n->result[i];
178                 lua_pushnumber(L, noiseval);
179                 lua_rawseti(L, -2, i + 1);
180         }
181         return 1;
182 }
183
184 int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
185 {
186         NO_MAP_LOCK_REQUIRED;
187         int i = 0;
188
189         LuaPerlinNoiseMap *o = checkobject(L, 1);
190         v3f p = read_v3f(L, 2);
191
192         Noise *n = o->noise;
193         n->perlinMap3D(p.X, p.Y, p.Z);
194
195         lua_newtable(L);
196         for (int z = 0; z != n->sz; z++) {
197                 lua_newtable(L);
198                 for (int y = 0; y != n->sy; y++) {
199                         lua_newtable(L);
200                         for (int x = 0; x != n->sx; x++) {
201                                 lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]);
202                                 lua_rawseti(L, -2, x + 1);
203                         }
204                         lua_rawseti(L, -2, y + 1);
205                 }
206                 lua_rawseti(L, -2, z + 1);
207         }
208         return 1;
209 }
210
211 int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
212 {
213         NO_MAP_LOCK_REQUIRED;
214
215         LuaPerlinNoiseMap *o = checkobject(L, 1);
216         v3f p = read_v3f(L, 2);
217
218         Noise *n = o->noise;
219         n->perlinMap3D(p.X, p.Y, p.Z);
220
221
222         int maplen = n->sx * n->sy * n->sz;
223         
224         lua_newtable(L);
225         for (int i = 0; i != maplen; i++) {
226                 float noiseval = n->np->offset + n->np->scale * n->result[i];
227                 lua_pushnumber(L, noiseval);
228                 lua_rawseti(L, -2, i + 1);
229         }
230         return 1;
231 }
232
233 LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size) {
234         noise = new Noise(np, seed, size.X, size.Y, size.Z);
235 }
236
237 LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
238 {
239         delete noise->np;
240         delete noise;
241 }
242
243 // LuaPerlinNoiseMap(np, size)
244 // Creates an LuaPerlinNoiseMap and leaves it on top of stack
245 int LuaPerlinNoiseMap::create_object(lua_State *L)
246 {
247         NoiseParams *np = read_noiseparams(L, 1);
248         if (!np)
249                 return 0;
250         v3s16 size = read_v3s16(L, 2);
251
252         LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size);
253         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
254         luaL_getmetatable(L, className);
255         lua_setmetatable(L, -2);
256         return 1;
257 }
258
259 LuaPerlinNoiseMap* LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
260 {
261         luaL_checktype(L, narg, LUA_TUSERDATA);
262
263         void *ud = luaL_checkudata(L, narg, className);
264         if (!ud)
265                 luaL_typerror(L, narg, className);
266
267         return *(LuaPerlinNoiseMap **)ud;  // unbox pointer
268 }
269
270 void LuaPerlinNoiseMap::Register(lua_State *L)
271 {
272         lua_newtable(L);
273         int methodtable = lua_gettop(L);
274         luaL_newmetatable(L, className);
275         int metatable = lua_gettop(L);
276
277         lua_pushliteral(L, "__metatable");
278         lua_pushvalue(L, methodtable);
279         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
280
281         lua_pushliteral(L, "__index");
282         lua_pushvalue(L, methodtable);
283         lua_settable(L, metatable);
284
285         lua_pushliteral(L, "__gc");
286         lua_pushcfunction(L, gc_object);
287         lua_settable(L, metatable);
288
289         lua_pop(L, 1);  // drop metatable
290
291         luaL_openlib(L, 0, methods, 0);  // fill methodtable
292         lua_pop(L, 1);  // drop methodtable
293
294         // Can be created from Lua (PerlinNoiseMap(np, size)
295         lua_register(L, className, create_object);
296 }
297
298 const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
299 const luaL_reg LuaPerlinNoiseMap::methods[] = {
300         luamethod(LuaPerlinNoiseMap, get2dMap),
301         luamethod(LuaPerlinNoiseMap, get2dMap_flat),
302         luamethod(LuaPerlinNoiseMap, get3dMap),
303         luamethod(LuaPerlinNoiseMap, get3dMap_flat),
304         {0,0}
305 };
306
307 /*
308         LuaPseudoRandom
309 */
310
311 // garbage collector
312 int LuaPseudoRandom::gc_object(lua_State *L)
313 {
314         LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
315         delete o;
316         return 0;
317 }
318
319 // next(self, min=0, max=32767) -> get next value
320 int LuaPseudoRandom::l_next(lua_State *L)
321 {
322         NO_MAP_LOCK_REQUIRED;
323         LuaPseudoRandom *o = checkobject(L, 1);
324         int min = 0;
325         int max = 32767;
326         lua_settop(L, 3); // Fill 2 and 3 with nil if they don't exist
327         if(!lua_isnil(L, 2))
328                 min = luaL_checkinteger(L, 2);
329         if(!lua_isnil(L, 3))
330                 max = luaL_checkinteger(L, 3);
331         if(max < min){
332                 errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
333                 throw LuaError(L, "PseudoRandom.next(): max < min");
334         }
335         if(max - min != 32767 && max - min > 32767/5)
336                 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.");
337         PseudoRandom &pseudo = o->m_pseudo;
338         int val = pseudo.next();
339         val = (val % (max-min+1)) + min;
340         lua_pushinteger(L, val);
341         return 1;
342 }
343
344
345 LuaPseudoRandom::LuaPseudoRandom(int seed):
346         m_pseudo(seed)
347 {
348 }
349
350 LuaPseudoRandom::~LuaPseudoRandom()
351 {
352 }
353
354 const PseudoRandom& LuaPseudoRandom::getItem() const
355 {
356         return m_pseudo;
357 }
358 PseudoRandom& LuaPseudoRandom::getItem()
359 {
360         return m_pseudo;
361 }
362
363 // LuaPseudoRandom(seed)
364 // Creates an LuaPseudoRandom and leaves it on top of stack
365 int LuaPseudoRandom::create_object(lua_State *L)
366 {
367         int seed = luaL_checknumber(L, 1);
368         LuaPseudoRandom *o = new LuaPseudoRandom(seed);
369         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
370         luaL_getmetatable(L, className);
371         lua_setmetatable(L, -2);
372         return 1;
373 }
374
375 LuaPseudoRandom* LuaPseudoRandom::checkobject(lua_State *L, int narg)
376 {
377         luaL_checktype(L, narg, LUA_TUSERDATA);
378         void *ud = luaL_checkudata(L, narg, className);
379         if(!ud) luaL_typerror(L, narg, className);
380         return *(LuaPseudoRandom**)ud;  // unbox pointer
381 }
382
383 void LuaPseudoRandom::Register(lua_State *L)
384 {
385         lua_newtable(L);
386         int methodtable = lua_gettop(L);
387         luaL_newmetatable(L, className);
388         int metatable = lua_gettop(L);
389
390         lua_pushliteral(L, "__metatable");
391         lua_pushvalue(L, methodtable);
392         lua_settable(L, metatable);  // hide metatable from Lua getmetatable()
393
394         lua_pushliteral(L, "__index");
395         lua_pushvalue(L, methodtable);
396         lua_settable(L, metatable);
397
398         lua_pushliteral(L, "__gc");
399         lua_pushcfunction(L, gc_object);
400         lua_settable(L, metatable);
401
402         lua_pop(L, 1);  // drop metatable
403
404         luaL_openlib(L, 0, methods, 0);  // fill methodtable
405         lua_pop(L, 1);  // drop methodtable
406
407         // Can be created from Lua (LuaPseudoRandom(seed))
408         lua_register(L, className, create_object);
409 }
410
411 const char LuaPseudoRandom::className[] = "PseudoRandom";
412 const luaL_reg LuaPseudoRandom::methods[] = {
413         luamethod(LuaPseudoRandom, next),
414         {0,0}
415 };