forked from Mirrorlandia_minetest/minetest
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.
This commit is contained in:
parent
c0edb8e313
commit
4c9a8a91c4
@ -2640,16 +2640,30 @@ Format of `size` is `{x=dimx, y=dimy, z=dimz}`. The `z` conponent is ommitted
|
|||||||
for 2D noise, and it must be must be larger than 1 for 3D noise (otherwise
|
for 2D noise, and it must be must be larger than 1 for 3D noise (otherwise
|
||||||
`nil` is returned).
|
`nil` is returned).
|
||||||
|
|
||||||
|
For each of the functions with an optional `buffer` parameter: If `buffer` is not
|
||||||
|
nil, this table will be used to store the result instead of creating a new table.
|
||||||
|
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
* `get2dMap(pos)`: returns a `<size.x>` times `<size.y>` 2D array of 2D noise
|
* `get2dMap(pos)`: returns a `<size.x>` times `<size.y>` 2D array of 2D noise
|
||||||
with values starting at `pos={x=,y=}`
|
with values starting at `pos={x=,y=}`
|
||||||
* `get3dMap(pos)`: returns a `<size.x>` times `<size.y>` times `<size.z>` 3D array
|
* `get3dMap(pos)`: returns a `<size.x>` times `<size.y>` times `<size.z>` 3D array
|
||||||
of 3D noise with values starting at `pos={x=,y=,z=}`
|
of 3D noise with values starting at `pos={x=,y=,z=}`
|
||||||
* `get2dMap_flat(pos)`: returns a flat `<size.x * size.y>` element array of 2D noise
|
* `get2dMap_flat(pos, buffer)`: returns a flat `<size.x * size.y>` element array of 2D noise
|
||||||
with values starting at `pos={x=,y=}`
|
with values starting at `pos={x=,y=}`
|
||||||
* if the param `buffer` is present, this table will be used to store the result instead
|
* `get3dMap_flat(pos, buffer)`: Same as `get2dMap_flat`, but 3D noise
|
||||||
* `get3dMap_flat(pos)`: Same as `get2dMap_flat`, but 3D noise
|
* `calc2dMap(pos)`: Calculates the 2d noise map starting at `pos`. The result is stored internally.
|
||||||
* if the param `buffer` is present, this table will be used to store the result instead
|
* `calc3dMap(pos)`: Calculates the 3d noise map starting at `pos`. The result is stored internally.
|
||||||
|
* `getMapSlice(slice_offset, slice_size, buffer)`: In the form of an array, returns a slice of the
|
||||||
|
most recently computed noise results. The result slice begins at coordinates `slice_offset` and
|
||||||
|
takes a chunk of `slice_size`.
|
||||||
|
E.g. to grab a 2-slice high horizontal 2d plane of noise starting at buffer offset y = 20:
|
||||||
|
`noisevals = noise:getMapSlice({y=20}, {y=2})`
|
||||||
|
It is important to note that `slice_offset` offset coordinates begin at 1, and are relative to
|
||||||
|
the starting position of the most recently calculated noise.
|
||||||
|
To grab a single vertical column of noise starting at map coordinates x = 1023, y=1000, z = 1000:
|
||||||
|
`noise:calc3dMap({x=1000, y=1000, z=1000})`
|
||||||
|
`noisevals = noise:getMapSlice({x=24, z=1}, {x=1, z=1})`
|
||||||
|
|
||||||
### `VoxelManip`
|
### `VoxelManip`
|
||||||
An interface to the `MapVoxelManipulator` for Lua.
|
An interface to the `MapVoxelManipulator` for Lua.
|
||||||
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
|
|
||||||
typedef core::vector3df v3f;
|
typedef core::vector3df v3f;
|
||||||
typedef core::vector3d<s16> v3s16;
|
typedef core::vector3d<s16> v3s16;
|
||||||
|
typedef core::vector3d<u16> v3u16;
|
||||||
typedef core::vector3d<s32> v3s32;
|
typedef core::vector3d<s32> v3s32;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -510,3 +510,95 @@ void setboolfield(lua_State *L, int table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////
|
||||||
|
//// Array table slices
|
||||||
|
////
|
||||||
|
|
||||||
|
size_t write_array_slice_float(
|
||||||
|
lua_State *L,
|
||||||
|
int table_index,
|
||||||
|
float *data,
|
||||||
|
v3u16 data_size,
|
||||||
|
v3u16 slice_offset,
|
||||||
|
v3u16 slice_size)
|
||||||
|
{
|
||||||
|
v3u16 pmin, pmax(data_size);
|
||||||
|
|
||||||
|
if (slice_offset.X > 0) {
|
||||||
|
slice_offset.X--;
|
||||||
|
pmin.X = slice_offset.X;
|
||||||
|
pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slice_offset.Y > 0) {
|
||||||
|
slice_offset.Y--;
|
||||||
|
pmin.Y = slice_offset.Y;
|
||||||
|
pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slice_offset.Z > 0) {
|
||||||
|
slice_offset.Z--;
|
||||||
|
pmin.Z = slice_offset.Z;
|
||||||
|
pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 ystride = data_size.X;
|
||||||
|
const u32 zstride = data_size.X * data_size.Y;
|
||||||
|
|
||||||
|
u32 elem_index = 1;
|
||||||
|
for (u32 z = pmin.Z; z != pmax.Z; z++)
|
||||||
|
for (u32 y = pmin.Y; y != pmax.Y; y++)
|
||||||
|
for (u32 x = pmin.X; x != pmax.X; x++) {
|
||||||
|
u32 i = z * zstride + y * ystride + x;
|
||||||
|
lua_pushnumber(L, data[i]);
|
||||||
|
lua_rawseti(L, table_index, elem_index);
|
||||||
|
elem_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem_index - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t write_array_slice_u16(
|
||||||
|
lua_State *L,
|
||||||
|
int table_index,
|
||||||
|
u16 *data,
|
||||||
|
v3u16 data_size,
|
||||||
|
v3u16 slice_offset,
|
||||||
|
v3u16 slice_size)
|
||||||
|
{
|
||||||
|
v3u16 pmin, pmax(data_size);
|
||||||
|
|
||||||
|
if (slice_offset.X > 0) {
|
||||||
|
slice_offset.X--;
|
||||||
|
pmin.X = slice_offset.X;
|
||||||
|
pmax.X = MYMIN(slice_offset.X + slice_size.X, data_size.X);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slice_offset.Y > 0) {
|
||||||
|
slice_offset.Y--;
|
||||||
|
pmin.Y = slice_offset.Y;
|
||||||
|
pmax.Y = MYMIN(slice_offset.Y + slice_size.Y, data_size.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slice_offset.Z > 0) {
|
||||||
|
slice_offset.Z--;
|
||||||
|
pmin.Z = slice_offset.Z;
|
||||||
|
pmax.Z = MYMIN(slice_offset.Z + slice_size.Z, data_size.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 ystride = data_size.X;
|
||||||
|
const u32 zstride = data_size.X * data_size.Y;
|
||||||
|
|
||||||
|
u32 elem_index = 1;
|
||||||
|
for (u32 z = pmin.Z; z != pmax.Z; z++)
|
||||||
|
for (u32 y = pmin.Y; y != pmax.Y; y++)
|
||||||
|
for (u32 x = pmin.X; x != pmax.X; x++) {
|
||||||
|
u32 i = z * zstride + y * ystride + x;
|
||||||
|
lua_pushinteger(L, data[i]);
|
||||||
|
lua_rawseti(L, table_index, elem_index);
|
||||||
|
elem_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return elem_index - 1;
|
||||||
|
}
|
||||||
|
@ -106,4 +106,9 @@ void warn_if_field_exists(lua_State *L, int table,
|
|||||||
const char *fieldname,
|
const char *fieldname,
|
||||||
const std::string &message);
|
const std::string &message);
|
||||||
|
|
||||||
|
size_t write_array_slice_float(lua_State *L, int table_index, float *data,
|
||||||
|
v3u16 data_size, v3u16 slice_offset, v3u16 slice_size);
|
||||||
|
size_t write_array_slice_u16(lua_State *L, int table_index, u16 *data,
|
||||||
|
v3u16 data_size, v3u16 slice_offset, v3u16 slice_size);
|
||||||
|
|
||||||
#endif /* C_CONVERTER_H_ */
|
#endif /* C_CONVERTER_H_ */
|
||||||
|
@ -272,6 +272,61 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LuaPerlinNoiseMap::l_calc2dMap(lua_State *L)
|
||||||
|
{
|
||||||
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
|
||||||
|
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||||
|
v2f p = check_v2f(L, 2);
|
||||||
|
|
||||||
|
Noise *n = o->noise;
|
||||||
|
n->perlinMap2D(p.X, p.Y);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LuaPerlinNoiseMap::l_calc3dMap(lua_State *L)
|
||||||
|
{
|
||||||
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
|
||||||
|
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||||
|
v3f p = check_v3f(L, 2);
|
||||||
|
|
||||||
|
if (!o->m_is3d)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Noise *n = o->noise;
|
||||||
|
n->perlinMap3D(p.X, p.Y, p.Z);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LuaPerlinNoiseMap::l_getMapSlice(lua_State *L)
|
||||||
|
{
|
||||||
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
|
||||||
|
LuaPerlinNoiseMap *o = checkobject(L, 1);
|
||||||
|
v3s16 slice_offset = read_v3s16(L, 2);
|
||||||
|
v3s16 slice_size = read_v3s16(L, 3);
|
||||||
|
bool use_buffer = lua_istable(L, 4);
|
||||||
|
|
||||||
|
Noise *n = o->noise;
|
||||||
|
|
||||||
|
if (use_buffer)
|
||||||
|
lua_pushvalue(L, 3);
|
||||||
|
else
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
write_array_slice_float(L, lua_gettop(L), n->result,
|
||||||
|
v3u16(n->sx, n->sy, n->sz),
|
||||||
|
v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z),
|
||||||
|
v3u16(slice_size.X, slice_size.Y, slice_size.Z));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int LuaPerlinNoiseMap::create_object(lua_State *L)
|
int LuaPerlinNoiseMap::create_object(lua_State *L)
|
||||||
{
|
{
|
||||||
NoiseParams np;
|
NoiseParams np;
|
||||||
@ -339,8 +394,11 @@ const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
|
|||||||
const luaL_reg LuaPerlinNoiseMap::methods[] = {
|
const luaL_reg LuaPerlinNoiseMap::methods[] = {
|
||||||
luamethod(LuaPerlinNoiseMap, get2dMap),
|
luamethod(LuaPerlinNoiseMap, get2dMap),
|
||||||
luamethod(LuaPerlinNoiseMap, get2dMap_flat),
|
luamethod(LuaPerlinNoiseMap, get2dMap_flat),
|
||||||
|
luamethod(LuaPerlinNoiseMap, calc2dMap),
|
||||||
luamethod(LuaPerlinNoiseMap, get3dMap),
|
luamethod(LuaPerlinNoiseMap, get3dMap),
|
||||||
luamethod(LuaPerlinNoiseMap, get3dMap_flat),
|
luamethod(LuaPerlinNoiseMap, get3dMap_flat),
|
||||||
|
luamethod(LuaPerlinNoiseMap, calc3dMap),
|
||||||
|
luamethod(LuaPerlinNoiseMap, getMapSlice),
|
||||||
{0,0}
|
{0,0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -74,6 +74,10 @@ class LuaPerlinNoiseMap : public ModApiBase {
|
|||||||
static int l_get3dMap(lua_State *L);
|
static int l_get3dMap(lua_State *L);
|
||||||
static int l_get3dMap_flat(lua_State *L);
|
static int l_get3dMap_flat(lua_State *L);
|
||||||
|
|
||||||
|
static int l_calc2dMap(lua_State *L);
|
||||||
|
static int l_calc3dMap(lua_State *L);
|
||||||
|
static int l_getMapSlice(lua_State *L);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size);
|
LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user