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