]> git.lizzy.rs Git - minetest.git/blob - src/script/lua_api/l_noise.cpp
Rename macros with two leading underscores
[minetest.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 ///////////////////////////////////////
27 /*
28   LuaPerlinNoise
29 */
30
31 LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
32         np(*params)
33 {
34 }
35
36
37 LuaPerlinNoise::~LuaPerlinNoise()
38 {
39 }
40
41
42 int LuaPerlinNoise::l_get2d(lua_State *L)
43 {
44         NO_MAP_LOCK_REQUIRED;
45         LuaPerlinNoise *o = checkobject(L, 1);
46         v2f p = check_v2f(L, 2);
47         lua_Number val = NoisePerlin2D(&o->np, p.X, p.Y, 0);
48         lua_pushnumber(L, val);
49         return 1;
50 }
51
52
53 int LuaPerlinNoise::l_get3d(lua_State *L)
54 {
55         NO_MAP_LOCK_REQUIRED;
56         LuaPerlinNoise *o = checkobject(L, 1);
57         v3f p = check_v3f(L, 2);
58         lua_Number val = NoisePerlin3D(&o->np, p.X, p.Y, p.Z, 0);
59         lua_pushnumber(L, val);
60         return 1;
61 }
62
63
64 int LuaPerlinNoise::create_object(lua_State *L)
65 {
66         NO_MAP_LOCK_REQUIRED;
67
68         NoiseParams params;
69
70         if (lua_istable(L, 1)) {
71                 read_noiseparams(L, 1, &params);
72         } else {
73                 params.seed    = luaL_checkint(L, 1);
74                 params.octaves = luaL_checkint(L, 2);
75                 params.persist = luaL_checknumber(L, 3);
76                 params.spread  = v3f(1, 1, 1) * luaL_checknumber(L, 4);
77         }
78
79         LuaPerlinNoise *o = new LuaPerlinNoise(&params);
80
81         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
82         luaL_getmetatable(L, className);
83         lua_setmetatable(L, -2);
84         return 1;
85 }
86
87
88 int LuaPerlinNoise::gc_object(lua_State *L)
89 {
90         LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
91         delete o;
92         return 0;
93 }
94
95
96 LuaPerlinNoise *LuaPerlinNoise::checkobject(lua_State *L, int narg)
97 {
98         NO_MAP_LOCK_REQUIRED;
99         luaL_checktype(L, narg, LUA_TUSERDATA);
100         void *ud = luaL_checkudata(L, narg, className);
101         if (!ud)
102                 luaL_typerror(L, narg, className);
103         return *(LuaPerlinNoise **)ud;
104 }
105
106
107 void LuaPerlinNoise::Register(lua_State *L)
108 {
109         lua_newtable(L);
110         int methodtable = lua_gettop(L);
111         luaL_newmetatable(L, className);
112         int metatable = lua_gettop(L);
113
114         lua_pushliteral(L, "__metatable");
115         lua_pushvalue(L, methodtable);
116         lua_settable(L, metatable);
117
118         lua_pushliteral(L, "__index");
119         lua_pushvalue(L, methodtable);
120         lua_settable(L, metatable);
121
122         lua_pushliteral(L, "__gc");
123         lua_pushcfunction(L, gc_object);
124         lua_settable(L, metatable);
125
126         lua_pop(L, 1);
127
128         luaL_openlib(L, 0, methods, 0);
129         lua_pop(L, 1);
130
131         lua_register(L, className, create_object);
132 }
133
134
135 const char LuaPerlinNoise::className[] = "PerlinNoise";
136 const luaL_reg LuaPerlinNoise::methods[] = {
137         luamethod(LuaPerlinNoise, get2d),
138         luamethod(LuaPerlinNoise, get3d),
139         {0,0}
140 };
141
142 ///////////////////////////////////////
143 /*
144   LuaPerlinNoiseMap
145 */
146
147 LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, int seed, v3s16 size)
148 {
149         m_is3d = size.Z > 1;
150         np = *params;
151         try {
152                 noise = new Noise(&np, seed, size.X, size.Y, size.Z);
153         } catch (InvalidNoiseParamsException &e) {
154                 throw LuaError(e.what());
155         }
156 }
157
158
159 LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
160 {
161         delete noise;
162 }
163
164
165 int LuaPerlinNoiseMap::l_get2dMap(lua_State *L)
166 {
167         NO_MAP_LOCK_REQUIRED;
168         size_t i = 0;
169
170         LuaPerlinNoiseMap *o = checkobject(L, 1);
171         v2f p = check_v2f(L, 2);
172
173         Noise *n = o->noise;
174         n->perlinMap2D(p.X, p.Y);
175
176         lua_newtable(L);
177         for (u32 y = 0; y != n->sy; y++) {
178                 lua_newtable(L);
179                 for (u32 x = 0; x != n->sx; x++) {
180                         lua_pushnumber(L, n->result[i++]);
181                         lua_rawseti(L, -2, x + 1);
182                 }
183                 lua_rawseti(L, -2, y + 1);
184         }
185         return 1;
186 }
187
188
189 int LuaPerlinNoiseMap::l_get2dMap_flat(lua_State *L)
190 {
191         NO_MAP_LOCK_REQUIRED;
192
193         LuaPerlinNoiseMap *o = checkobject(L, 1);
194         v2f p                = check_v2f(L, 2);
195         bool use_buffer      = lua_istable(L, 3);
196
197         Noise *n = o->noise;
198         n->perlinMap2D(p.X, p.Y);
199
200         size_t maplen = n->sx * n->sy;
201
202         if (use_buffer)
203                 lua_pushvalue(L, 3);
204         else
205                 lua_newtable(L);
206
207         for (size_t i = 0; i != maplen; i++) {
208                 lua_pushnumber(L, n->result[i]);
209                 lua_rawseti(L, -2, i + 1);
210         }
211         return 1;
212 }
213
214
215 int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
216 {
217         NO_MAP_LOCK_REQUIRED;
218         size_t i = 0;
219
220         LuaPerlinNoiseMap *o = checkobject(L, 1);
221         v3f p = check_v3f(L, 2);
222
223         if (!o->m_is3d)
224                 return 0;
225
226         Noise *n = o->noise;
227         n->perlinMap3D(p.X, p.Y, p.Z);
228
229         lua_newtable(L);
230         for (u32 z = 0; z != n->sz; z++) {
231                 lua_newtable(L);
232                 for (u32 y = 0; y != n->sy; y++) {
233                         lua_newtable(L);
234                         for (u32 x = 0; x != n->sx; x++) {
235                                 lua_pushnumber(L, n->result[i++]);
236                                 lua_rawseti(L, -2, x + 1);
237                         }
238                         lua_rawseti(L, -2, y + 1);
239                 }
240                 lua_rawseti(L, -2, z + 1);
241         }
242         return 1;
243 }
244
245
246 int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
247 {
248         NO_MAP_LOCK_REQUIRED;
249
250         LuaPerlinNoiseMap *o = checkobject(L, 1);
251         v3f p                = check_v3f(L, 2);
252         bool use_buffer      = lua_istable(L, 3);
253
254         if (!o->m_is3d)
255                 return 0;
256
257         Noise *n = o->noise;
258         n->perlinMap3D(p.X, p.Y, p.Z);
259
260         size_t maplen = n->sx * n->sy * n->sz;
261
262         if (use_buffer)
263                 lua_pushvalue(L, 3);
264         else
265                 lua_newtable(L);
266
267         for (size_t i = 0; i != maplen; i++) {
268                 lua_pushnumber(L, n->result[i]);
269                 lua_rawseti(L, -2, i + 1);
270         }
271         return 1;
272 }
273
274
275 int LuaPerlinNoiseMap::l_calc2dMap(lua_State *L)
276 {
277         NO_MAP_LOCK_REQUIRED;
278
279         LuaPerlinNoiseMap *o = checkobject(L, 1);
280         v2f p                = check_v2f(L, 2);
281
282         Noise *n = o->noise;
283         n->perlinMap2D(p.X, p.Y);
284
285         return 0;
286 }
287
288 int LuaPerlinNoiseMap::l_calc3dMap(lua_State *L)
289 {
290         NO_MAP_LOCK_REQUIRED;
291
292         LuaPerlinNoiseMap *o = checkobject(L, 1);
293         v3f p                = check_v3f(L, 2);
294
295         if (!o->m_is3d)
296                 return 0;
297
298         Noise *n = o->noise;
299         n->perlinMap3D(p.X, p.Y, p.Z);
300
301         return 0;
302 }
303
304
305 int LuaPerlinNoiseMap::l_getMapSlice(lua_State *L)
306 {
307         NO_MAP_LOCK_REQUIRED;
308
309         LuaPerlinNoiseMap *o = checkobject(L, 1);
310         v3s16 slice_offset   = read_v3s16(L, 2);
311         v3s16 slice_size     = read_v3s16(L, 3);
312         bool use_buffer      = lua_istable(L, 4);
313
314         Noise *n = o->noise;
315
316         if (use_buffer)
317                 lua_pushvalue(L, 3);
318         else
319                 lua_newtable(L);
320
321         write_array_slice_float(L, lua_gettop(L), n->result,
322                 v3u16(n->sx, n->sy, n->sz),
323                 v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z),
324                 v3u16(slice_size.X, slice_size.Y, slice_size.Z));
325
326         return 1;
327 }
328
329
330 int LuaPerlinNoiseMap::create_object(lua_State *L)
331 {
332         NoiseParams np;
333         if (!read_noiseparams(L, 1, &np))
334                 return 0;
335         v3s16 size = read_v3s16(L, 2);
336
337         LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(&np, 0, size);
338         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
339         luaL_getmetatable(L, className);
340         lua_setmetatable(L, -2);
341         return 1;
342 }
343
344
345 int LuaPerlinNoiseMap::gc_object(lua_State *L)
346 {
347         LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
348         delete o;
349         return 0;
350 }
351
352
353 LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
354 {
355         luaL_checktype(L, narg, LUA_TUSERDATA);
356
357         void *ud = luaL_checkudata(L, narg, className);
358         if (!ud)
359                 luaL_typerror(L, narg, className);
360
361         return *(LuaPerlinNoiseMap **)ud;
362 }
363
364
365 void LuaPerlinNoiseMap::Register(lua_State *L)
366 {
367         lua_newtable(L);
368         int methodtable = lua_gettop(L);
369         luaL_newmetatable(L, className);
370         int metatable = lua_gettop(L);
371
372         lua_pushliteral(L, "__metatable");
373         lua_pushvalue(L, methodtable);
374         lua_settable(L, metatable);
375
376         lua_pushliteral(L, "__index");
377         lua_pushvalue(L, methodtable);
378         lua_settable(L, metatable);
379
380         lua_pushliteral(L, "__gc");
381         lua_pushcfunction(L, gc_object);
382         lua_settable(L, metatable);
383
384         lua_pop(L, 1);
385
386         luaL_openlib(L, 0, methods, 0);
387         lua_pop(L, 1);
388
389         lua_register(L, className, create_object);
390 }
391
392
393 const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
394 const luaL_reg LuaPerlinNoiseMap::methods[] = {
395         luamethod(LuaPerlinNoiseMap, get2dMap),
396         luamethod(LuaPerlinNoiseMap, get2dMap_flat),
397         luamethod(LuaPerlinNoiseMap, calc2dMap),
398         luamethod(LuaPerlinNoiseMap, get3dMap),
399         luamethod(LuaPerlinNoiseMap, get3dMap_flat),
400         luamethod(LuaPerlinNoiseMap, calc3dMap),
401         luamethod(LuaPerlinNoiseMap, getMapSlice),
402         {0,0}
403 };
404
405 ///////////////////////////////////////
406 /*
407         LuaPseudoRandom
408 */
409
410 int LuaPseudoRandom::l_next(lua_State *L)
411 {
412         NO_MAP_LOCK_REQUIRED;
413         LuaPseudoRandom *o = checkobject(L, 1);
414         int min = 0;
415         int max = 32767;
416         lua_settop(L, 3);
417         if (lua_isnumber(L, 2))
418                 min = luaL_checkinteger(L, 2);
419         if (lua_isnumber(L, 3))
420                 max = luaL_checkinteger(L, 3);
421         if (max < min) {
422                 errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
423                 throw LuaError("PseudoRandom.next(): max < min");
424         }
425         if(max - min != 32767 && max - min > 32767/5)
426                 throw LuaError("PseudoRandom.next() max-min is not 32767"
427                                 " and is > 32768/5. This is disallowed due to"
428                                 " the bad random distribution the"
429                                 " implementation would otherwise make.");
430         PseudoRandom &pseudo = o->m_pseudo;
431         int val = pseudo.next();
432         val = (val % (max-min+1)) + min;
433         lua_pushinteger(L, val);
434         return 1;
435 }
436
437
438 int LuaPseudoRandom::create_object(lua_State *L)
439 {
440         int seed = luaL_checknumber(L, 1);
441         LuaPseudoRandom *o = new LuaPseudoRandom(seed);
442         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
443         luaL_getmetatable(L, className);
444         lua_setmetatable(L, -2);
445         return 1;
446 }
447
448
449 int LuaPseudoRandom::gc_object(lua_State *L)
450 {
451         LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
452         delete o;
453         return 0;
454 }
455
456
457 LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
458 {
459         luaL_checktype(L, narg, LUA_TUSERDATA);
460         void *ud = luaL_checkudata(L, narg, className);
461         if (!ud)
462                 luaL_typerror(L, narg, className);
463         return *(LuaPseudoRandom **)ud;
464 }
465
466
467 void LuaPseudoRandom::Register(lua_State *L)
468 {
469         lua_newtable(L);
470         int methodtable = lua_gettop(L);
471         luaL_newmetatable(L, className);
472         int metatable = lua_gettop(L);
473
474         lua_pushliteral(L, "__metatable");
475         lua_pushvalue(L, methodtable);
476         lua_settable(L, metatable);
477
478         lua_pushliteral(L, "__index");
479         lua_pushvalue(L, methodtable);
480         lua_settable(L, metatable);
481
482         lua_pushliteral(L, "__gc");
483         lua_pushcfunction(L, gc_object);
484         lua_settable(L, metatable);
485
486         lua_pop(L, 1);
487
488         luaL_openlib(L, 0, methods, 0);
489         lua_pop(L, 1);
490
491         lua_register(L, className, create_object);
492 }
493
494
495 const char LuaPseudoRandom::className[] = "PseudoRandom";
496 const luaL_reg LuaPseudoRandom::methods[] = {
497         luamethod(LuaPseudoRandom, next),
498         {0,0}
499 };
500
501 ///////////////////////////////////////
502 /*
503         LuaPcgRandom
504 */
505
506 int LuaPcgRandom::l_next(lua_State *L)
507 {
508         NO_MAP_LOCK_REQUIRED;
509
510         LuaPcgRandom *o = checkobject(L, 1);
511         u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
512         u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
513
514         lua_pushinteger(L, o->m_rnd.range(min, max));
515         return 1;
516 }
517
518
519 int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
520 {
521         NO_MAP_LOCK_REQUIRED;
522
523         LuaPcgRandom *o = checkobject(L, 1);
524         u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
525         u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
526         int num_trials = lua_isnumber(L, 4) ? lua_tointeger(L, 4) : 6;
527
528         lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
529         return 1;
530 }
531
532
533 int LuaPcgRandom::create_object(lua_State *L)
534 {
535         lua_Integer seed = luaL_checknumber(L, 1);
536         LuaPcgRandom *o  = lua_isnumber(L, 2) ?
537                 new LuaPcgRandom(seed, lua_tointeger(L, 2)) :
538                 new LuaPcgRandom(seed);
539         *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
540         luaL_getmetatable(L, className);
541         lua_setmetatable(L, -2);
542         return 1;
543 }
544
545
546 int LuaPcgRandom::gc_object(lua_State *L)
547 {
548         LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
549         delete o;
550         return 0;
551 }
552
553
554 LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
555 {
556         luaL_checktype(L, narg, LUA_TUSERDATA);
557         void *ud = luaL_checkudata(L, narg, className);
558         if (!ud)
559                 luaL_typerror(L, narg, className);
560         return *(LuaPcgRandom **)ud;
561 }
562
563
564 void LuaPcgRandom::Register(lua_State *L)
565 {
566         lua_newtable(L);
567         int methodtable = lua_gettop(L);
568         luaL_newmetatable(L, className);
569         int metatable = lua_gettop(L);
570
571         lua_pushliteral(L, "__metatable");
572         lua_pushvalue(L, methodtable);
573         lua_settable(L, metatable);
574
575         lua_pushliteral(L, "__index");
576         lua_pushvalue(L, methodtable);
577         lua_settable(L, metatable);
578
579         lua_pushliteral(L, "__gc");
580         lua_pushcfunction(L, gc_object);
581         lua_settable(L, metatable);
582
583         lua_pop(L, 1);
584
585         luaL_openlib(L, 0, methods, 0);
586         lua_pop(L, 1);
587
588         lua_register(L, className, create_object);
589 }
590
591
592 const char LuaPcgRandom::className[] = "PcgRandom";
593 const luaL_reg LuaPcgRandom::methods[] = {
594         luamethod(LuaPcgRandom, next),
595         luamethod(LuaPcgRandom, rand_normal_dist),
596         {0,0}
597 };