Skip to content

Commit 4c9a8a9

Browse files
committedMay 17, 2015
SAPI/Noise: Add PerlinNoiseMap:getMapSlice() function
This adds the ability to grab 'slices' of noise calculated by PerlinNoiseMap. Retrieving smaller slices of noise from the computation result as needed optimizes memory usage while maintaining a reasonable amount of CPU overhead.
1 parent c0edb8e commit 4c9a8a9

File tree

6 files changed

+178
-4
lines changed

6 files changed

+178
-4
lines changed
 

Diff for: ‎doc/lua_api.txt

+18-4
Original file line numberDiff line numberDiff line change
@@ -2640,16 +2640,30 @@ Format of `size` is `{x=dimx, y=dimy, z=dimz}`. The `z` conponent is ommitted
26402640
for 2D noise, and it must be must be larger than 1 for 3D noise (otherwise
26412641
`nil` is returned).
26422642

2643+
For each of the functions with an optional `buffer` parameter: If `buffer` is not
2644+
nil, this table will be used to store the result instead of creating a new table.
2645+
2646+
26432647
#### Methods
26442648
* `get2dMap(pos)`: returns a `<size.x>` times `<size.y>` 2D array of 2D noise
26452649
with values starting at `pos={x=,y=}`
26462650
* `get3dMap(pos)`: returns a `<size.x>` times `<size.y>` times `<size.z>` 3D array
26472651
of 3D noise with values starting at `pos={x=,y=,z=}`
2648-
* `get2dMap_flat(pos)`: returns a flat `<size.x * size.y>` element array of 2D noise
2652+
* `get2dMap_flat(pos, buffer)`: returns a flat `<size.x * size.y>` element array of 2D noise
26492653
with values starting at `pos={x=,y=}`
2650-
* if the param `buffer` is present, this table will be used to store the result instead
2651-
* `get3dMap_flat(pos)`: Same as `get2dMap_flat`, but 3D noise
2652-
* if the param `buffer` is present, this table will be used to store the result instead
2654+
* `get3dMap_flat(pos, buffer)`: Same as `get2dMap_flat`, but 3D noise
2655+
* `calc2dMap(pos)`: Calculates the 2d noise map starting at `pos`. The result is stored internally.
2656+
* `calc3dMap(pos)`: Calculates the 3d noise map starting at `pos`. The result is stored internally.
2657+
* `getMapSlice(slice_offset, slice_size, buffer)`: In the form of an array, returns a slice of the
2658+
most recently computed noise results. The result slice begins at coordinates `slice_offset` and
2659+
takes a chunk of `slice_size`.
2660+
E.g. to grab a 2-slice high horizontal 2d plane of noise starting at buffer offset y = 20:
2661+
`noisevals = noise:getMapSlice({y=20}, {y=2})`
2662+
It is important to note that `slice_offset` offset coordinates begin at 1, and are relative to
2663+
the starting position of the most recently calculated noise.
2664+
To grab a single vertical column of noise starting at map coordinates x = 1023, y=1000, z = 1000:
2665+
`noise:calc3dMap({x=1000, y=1000, z=1000})`
2666+
`noisevals = noise:getMapSlice({x=24, z=1}, {x=1, z=1})`
26532667

26542668
### `VoxelManip`
26552669
An interface to the `MapVoxelManipulator` for Lua.

Diff for: ‎src/irr_v3d.h

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
2626

2727
typedef core::vector3df v3f;
2828
typedef core::vector3d<s16> v3s16;
29+
typedef core::vector3d<u16> v3u16;
2930
typedef core::vector3d<s32> v3s32;
3031

3132
#endif

Diff for: ‎src/script/common/c_converter.cpp

+92
Original file line numberDiff line numberDiff line change
@@ -510,3 +510,95 @@ void setboolfield(lua_State *L, int table,
510510
}
511511

512512

513+
////
514+
//// Array table slices
515+
////
516+
517+
size_t write_array_slice_float(
518+
lua_State *L,
519+
int table_index,
520+
float *data,
521+
v3u16 data_size,
522+
v3u16 slice_offset,
523+
v3u16 slice_size)
524+
{
525+
v3u16 pmin, pmax(data_size);
526+
527+
if (slice_offset.X > 0) {
528+
slice_offset.X--;
529+
pmin.X = slice_offset.X;
530+
pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
531+
}
532+
533+
if (slice_offset.Y > 0) {
534+
slice_offset.Y--;
535+
pmin.Y = slice_offset.Y;
536+
pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
537+
}
538+
539+
if (slice_offset.Z > 0) {
540+
slice_offset.Z--;
541+
pmin.Z = slice_offset.Z;
542+
pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
543+
}
544+
545+
const u32 ystride = data_size.X;
546+
const u32 zstride = data_size.X * data_size.Y;
547+
548+
u32 elem_index = 1;
549+
for (u32 z = pmin.Z; z != pmax.Z; z++)
550+
for (u32 y = pmin.Y; y != pmax.Y; y++)
551+
for (u32 x = pmin.X; x != pmax.X; x++) {
552+
u32 i = z * zstride + y * ystride + x;
553+
lua_pushnumber(L, data[i]);
554+
lua_rawseti(L, table_index, elem_index);
555+
elem_index++;
556+
}
557+
558+
return elem_index - 1;
559+
}
560+
561+
562+
size_t write_array_slice_u16(
563+
lua_State *L,
564+
int table_index,
565+
u16 *data,
566+
v3u16 data_size,
567+
v3u16 slice_offset,
568+
v3u16 slice_size)
569+
{
570+
v3u16 pmin, pmax(data_size);
571+
572+
if (slice_offset.X > 0) {
573+
slice_offset.X--;
574+
pmin.X = slice_offset.X;
575+
pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
576+
}
577+
578+
if (slice_offset.Y > 0) {
579+
slice_offset.Y--;
580+
pmin.Y = slice_offset.Y;
581+
pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
582+
}
583+
584+
if (slice_offset.Z > 0) {
585+
slice_offset.Z--;
586+
pmin.Z = slice_offset.Z;
587+
pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
588+
}
589+
590+
const u32 ystride = data_size.X;
591+
const u32 zstride = data_size.X * data_size.Y;
592+
593+
u32 elem_index = 1;
594+
for (u32 z = pmin.Z; z != pmax.Z; z++)
595+
for (u32 y = pmin.Y; y != pmax.Y; y++)
596+
for (u32 x = pmin.X; x != pmax.X; x++) {
597+
u32 i = z * zstride + y * ystride + x;
598+
lua_pushinteger(L, data[i]);
599+
lua_rawseti(L, table_index, elem_index);
600+
elem_index++;
601+
}
602+
603+
return elem_index - 1;
604+
}

Diff for: ‎src/script/common/c_converter.h

+5
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,9 @@ void warn_if_field_exists(lua_State *L, int table,
106106
const char *fieldname,
107107
const std::string &message);
108108

109+
size_t write_array_slice_float(lua_State *L, int table_index, float *data,
110+
v3u16 data_size, v3u16 slice_offset, v3u16 slice_size);
111+
size_t write_array_slice_u16(lua_State *L, int table_index, u16 *data,
112+
v3u16 data_size, v3u16 slice_offset, v3u16 slice_size);
113+
109114
#endif /* C_CONVERTER_H_ */

Diff for: ‎src/script/lua_api/l_noise.cpp

+58
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,61 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
272272
}
273273

274274

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+
275330
int LuaPerlinNoiseMap::create_object(lua_State *L)
276331
{
277332
NoiseParams np;
@@ -339,8 +394,11 @@ const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
339394
const luaL_reg LuaPerlinNoiseMap::methods[] = {
340395
luamethod(LuaPerlinNoiseMap, get2dMap),
341396
luamethod(LuaPerlinNoiseMap, get2dMap_flat),
397+
luamethod(LuaPerlinNoiseMap, calc2dMap),
342398
luamethod(LuaPerlinNoiseMap, get3dMap),
343399
luamethod(LuaPerlinNoiseMap, get3dMap_flat),
400+
luamethod(LuaPerlinNoiseMap, calc3dMap),
401+
luamethod(LuaPerlinNoiseMap, getMapSlice),
344402
{0,0}
345403
};
346404

Diff for: ‎src/script/lua_api/l_noise.h

+4
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ class LuaPerlinNoiseMap : public ModApiBase {
7474
static int l_get3dMap(lua_State *L);
7575
static int l_get3dMap_flat(lua_State *L);
7676

77+
static int l_calc2dMap(lua_State *L);
78+
static int l_calc3dMap(lua_State *L);
79+
static int l_getMapSlice(lua_State *L);
80+
7781
public:
7882
LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size);
7983

0 commit comments

Comments
 (0)
Please sign in to comment.