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