Some refactoring and fixes to VoxelArea and VoxelManip

In particular this validates the edges of VoxelArea and fixes
all the nonsense tests uncovered by it.
This commit is contained in:
sfan5 2024-10-07 17:48:19 +02:00
parent 5532248cd7
commit 6d5103900f
11 changed files with 178 additions and 183 deletions

View file

@ -5010,8 +5010,7 @@ Methods
the `VoxelManip`.
* `calc_lighting([p1, p2], [propagate_shadow])`: Calculate lighting within the
`VoxelManip`.
* To be used only by a `VoxelManip` object from
`minetest.get_mapgen_object`.
* To be used only with a `VoxelManip` object from `minetest.get_mapgen_object`.
* (`p1`, `p2`) is the area in which lighting is set, defaults to the whole
area if left out or nil. For almost all uses these should be left out
or nil to use the default.
@ -5019,9 +5018,11 @@ Methods
generated mapchunk above are propagated down into the mapchunk, defaults
to `true` if left out.
* `update_liquids()`: Update liquid flow
* `was_modified()`: Returns `true` or `false` if the data in the voxel
manipulator had been modified since the last read from map, due to a call to
`minetest.set_data()` on the loaded area elsewhere.
* `was_modified()`: Returns `true` if the data in the voxel manipulator has been modified
since it was last read from the map. This means you have to call `get_data` again.
This only applies to a `VoxelManip` object from `minetest.get_mapgen_object`,
where the engine will keep the map and the VM in sync automatically.
* Note: this doesn't do what you think it does and is subject to removal. Don't use it!
* `get_emerged_area()`: Returns actual emerged minimum and maximum positions.
`VoxelArea`

View file

@ -822,17 +822,9 @@ void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
} else {
flags |= VMANIP_BLOCK_DATA_INEXIST;
/*
Mark area inexistent
*/
// Mark area inexistent
VoxelArea a(p*MAP_BLOCKSIZE, (p+1)*MAP_BLOCKSIZE-v3s16(1,1,1));
// Fill with VOXELFLAG_NO_DATA
for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
for(s32 y=a.MinEdge.Y; y<=a.MaxEdge.Y; y++)
{
s32 i = m_area.index(a.MinEdge.X,y,z);
memset(&m_flags[i], VOXELFLAG_NO_DATA, MAP_BLOCKSIZE);
}
setFlags(a, VOXELFLAG_NO_DATA);
}
}
/*else if (block->getNode(0, 0, 0).getContent() == CONTENT_IGNORE)
@ -848,9 +840,9 @@ void MMVManip::initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max,
}
void MMVManip::blitBackAll(std::map<v3s16, MapBlock*> *modified_blocks,
bool overwrite_generated)
bool overwrite_generated) const
{
if(m_area.getExtent() == v3s16(0,0,0))
if (m_area.hasEmptyExtent())
return;
assert(m_map);

View file

@ -333,7 +333,7 @@ public:
// This is much faster with big chunks of generated data
void blitBackAll(std::map<v3s16, MapBlock*> * modified_blocks,
bool overwrite_generated = true);
bool overwrite_generated = true) const;
/*
Creates a copy of this VManip including contents, the copy will not be

View file

@ -178,13 +178,13 @@ void MapBlock::copyTo(VoxelManipulator &dst)
getPosRelative(), data_size);
}
void MapBlock::copyFrom(VoxelManipulator &dst)
void MapBlock::copyFrom(const VoxelManipulator &src)
{
v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1));
// Copy from VoxelManipulator to data
dst.copyTo(data, data_area, v3s16(0,0,0),
src.copyTo(data, data_area, v3s16(0,0,0),
getPosRelative(), data_size);
}

View file

@ -307,8 +307,8 @@ public:
// Copies data to VoxelManipulator to getPosRelative()
void copyTo(VoxelManipulator &dst);
// Copies data from VoxelManipulator getPosRelative()
void copyFrom(VoxelManipulator &dst);
// Copies data from VoxelManipulator to getPosRelative()
void copyFrom(const VoxelManipulator &src);
// Update is air flag.
// Sets m_is_air to appropriate value.

View file

@ -91,7 +91,7 @@ void DungeonGen::generate(MMVManip *vm, u32 bseed, v3s16 nmin, v3s16 nmax)
random.seed(bseed + 2);
// Dungeon generator doesn't modify places which have this set
vm->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
vm->clearFlags(vm->m_area, VMANIP_FLAG_DUNGEON_INSIDE | VMANIP_FLAG_DUNGEON_PRESERVE);
if (dp.only_in_ground) {
// Set all air and liquid drawtypes to be untouchable to make dungeons generate

View file

@ -333,6 +333,9 @@ int LuaVoxelManip::l_was_modified(lua_State *L)
LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
MMVManip *vm = o->vm;
if (!o->is_mapgen_vm)
log_deprecated(L, "was_modified called for a non-mapgen VoxelManip object");
lua_pushboolean(L, vm->m_is_dirty);
return 1;

View file

@ -38,6 +38,7 @@ public:
void test_equal();
void test_plus();
void test_minor();
void test_diff();
void test_intersect();
void test_index_xyz_all_pos();
void test_index_xyz_x_neg();
@ -75,6 +76,7 @@ void TestVoxelArea::runTests(IGameDef *gamedef)
TEST(test_equal);
TEST(test_plus);
TEST(test_minor);
TEST(test_diff);
TEST(test_intersect);
TEST(test_index_xyz_all_pos);
TEST(test_index_xyz_x_neg);
@ -100,21 +102,21 @@ void TestVoxelArea::runTests(IGameDef *gamedef)
void TestVoxelArea::test_addarea()
{
VoxelArea v1(v3s16(-1447, 8854, -875), v3s16(-147, -9547, 669));
VoxelArea v2(v3s16(-887, 4445, -5478), v3s16(447, -8779, 4778));
VoxelArea v1(v3s16(-1447, -9547, -875), v3s16(-147, 8854, 669));
VoxelArea v2(v3s16(-887, -8779, -5478), v3s16(447, 4445, 4778));
v1.addArea(v2);
UASSERT(v1.MinEdge == v3s16(-1447, 4445, -5478));
UASSERT(v1.MaxEdge == v3s16(447, -8779, 4778));
UASSERT(v1.MinEdge == v3s16(-1447, -9547, -5478));
UASSERT(v1.MaxEdge == v3s16(447, 8854, 4778));
}
void TestVoxelArea::test_pad()
{
VoxelArea v1(v3s16(-1447, 8854, -875), v3s16(-147, -9547, 669));
VoxelArea v1(v3s16(-1447, -9547, -875), v3s16(-147, 8854, 669));
v1.pad(v3s16(100, 200, 300));
UASSERT(v1.MinEdge == v3s16(-1547, 8654, -1175));
UASSERT(v1.MaxEdge == v3s16(-47, -9347, 969));
UASSERT(v1.MinEdge == v3s16(-1547, -9747, -1175));
UASSERT(v1.MaxEdge == v3s16(-47, 9054, 969));
}
void TestVoxelArea::test_extent()
@ -124,6 +126,9 @@ void TestVoxelArea::test_extent()
VoxelArea v2(v3s16(32493, -32507, 32752), v3s16(32508, -32492, 32767));
UASSERT(v2.getExtent() == v3s16(16, 16, 16));
UASSERT(VoxelArea({2,3,4}, {1,2,3}).hasEmptyExtent());
UASSERT(VoxelArea({2,3,4}, {2,2,3}).hasEmptyExtent() == false);
}
void TestVoxelArea::test_volume()
@ -133,6 +138,9 @@ void TestVoxelArea::test_volume()
VoxelArea v2(v3s16(32493, -32507, 32752), v3s16(32508, -32492, 32767));
UASSERTEQ(s32, v2.getVolume(), 4096);
UASSERTEQ(s32, VoxelArea({2,3,4}, {1,2,3}).getVolume(), 0);
UASSERTEQ(s32, VoxelArea({2,3,4}, {2,2,3}).getVolume(), 0);
}
void TestVoxelArea::test_contains_voxelarea()
@ -185,8 +193,7 @@ void TestVoxelArea::test_equal()
VoxelArea v1(v3s16(-1337, -9547, -789), v3s16(-147, 750, 669));
UASSERTEQ(bool, v1 == VoxelArea(v3s16(-1337, -9547, -789), v3s16(-147, 750, 669)),
true);
UASSERTEQ(bool, v1 == VoxelArea(v3s16(0, 0, 0), v3s16(-147, 750, 669)), false);
UASSERTEQ(bool, v1 == VoxelArea(v3s16(0, 0, 0), v3s16(-147, 750, 669)), false);
UASSERTEQ(bool, v1 == VoxelArea(v3s16(-147, 0, 0), v3s16(0, 750, 669)), false);
UASSERTEQ(bool, v1 == VoxelArea(v3s16(0, 0, 0), v3s16(0, 0, 0)), false);
}
@ -212,6 +219,30 @@ void TestVoxelArea::test_minor()
VoxelArea(v3s16(-10, -10, -45), v3s16(100, 100, 65)));
}
void TestVoxelArea::test_diff()
{
const VoxelArea v1({-10, -10, -10}, {100, 100, 100});
std::vector<VoxelArea> res;
v1.diff(VoxelArea({-10, -10, -10}, {99, 100, 100}), res);
UASSERTEQ(auto, res.size(), 1U);
UASSERT(res[0] == VoxelArea({100, -10, -10}, {100, 100, 100}));
res.clear();
v1.diff(VoxelArea({-10, -10, -10}, {100, 50, 80}), res);
UASSERTEQ(auto, res.size(), 2U);
UASSERT(res[0] == VoxelArea({-10, -10, 81}, {100, 100, 100}));
UASSERT(res[1] == VoxelArea({-10, 51, -10}, {100, 100, 80}));
res.clear();
// edge cases
v1.diff(v1, res);
UASSERT(res.empty());
v1.diff(VoxelArea(), res);
UASSERTEQ(auto, res.size(), 1U);
UASSERT(res[0] == v1);
}
void TestVoxelArea::test_intersect()
{
VoxelArea v1({-10, -10, -10}, {10, 10, 10});
@ -231,8 +262,8 @@ void TestVoxelArea::test_index_xyz_all_pos()
VoxelArea v1;
UASSERTEQ(s32, v1.index(156, 25, 236), 155);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(156, 25, 236), 1267138774);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(156, 25, 236), 1310722495);
}
void TestVoxelArea::test_index_xyz_x_neg()
@ -240,8 +271,8 @@ void TestVoxelArea::test_index_xyz_x_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(-147, 25, 366), -148);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(-147, 25, 366), -870244825);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(-147, 25, 366), -821642064);
}
void TestVoxelArea::test_index_xyz_y_neg()
@ -249,8 +280,8 @@ void TestVoxelArea::test_index_xyz_y_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(247, -269, 100), 246);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(247, -269, 100), -989760747);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(247, -269, 100), -951958678);
}
void TestVoxelArea::test_index_xyz_z_neg()
@ -258,8 +289,8 @@ void TestVoxelArea::test_index_xyz_z_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(244, 336, -887), 243);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(244, 336, -887), -191478876);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(244, 336, -887), -190690273);
}
void TestVoxelArea::test_index_xyz_xy_neg()
@ -267,8 +298,8 @@ void TestVoxelArea::test_index_xyz_xy_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(-365, -47, 6978), -366);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(-365, -47, 6978), 1493679101);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(-365, -47, 6978), 1797427926);
}
void TestVoxelArea::test_index_xyz_yz_neg()
@ -276,8 +307,8 @@ void TestVoxelArea::test_index_xyz_yz_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(66, -58, -789), 65);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(66, -58, -789), 1435362734);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(66, -58, -789), 1439223357);
}
void TestVoxelArea::test_index_xyz_xz_neg()
@ -285,8 +316,8 @@ void TestVoxelArea::test_index_xyz_xz_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(-36, 589, -992), -37);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(-36, 589, -992), -1934371362);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(-36, 589, -992), -1937179681);
}
void TestVoxelArea::test_index_xyz_all_neg()
@ -294,8 +325,8 @@ void TestVoxelArea::test_index_xyz_all_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(-88, -99, -1474), -89);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(-88, -99, -1474), -1343473846);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(-88, -99, -1474), -1366133749);
}
void TestVoxelArea::test_index_v3s16_all_pos()
@ -303,8 +334,8 @@ void TestVoxelArea::test_index_v3s16_all_pos()
VoxelArea v1;
UASSERTEQ(s32, v1.index(v3s16(156, 25, 236)), 155);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(v3s16(156, 25, 236)), 1267138774);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(v3s16(156, 25, 236)), 1310722495);
}
void TestVoxelArea::test_index_v3s16_x_neg()
@ -312,8 +343,8 @@ void TestVoxelArea::test_index_v3s16_x_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(v3s16(-147, 25, 366)), -148);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(v3s16(-147, 25, 366)), -870244825);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(v3s16(-147, 25, 366)), -821642064);
}
void TestVoxelArea::test_index_v3s16_y_neg()
@ -321,8 +352,8 @@ void TestVoxelArea::test_index_v3s16_y_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(v3s16(247, -269, 100)), 246);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(v3s16(247, -269, 100)), -989760747);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(v3s16(247, -269, 100)), -951958678);
}
void TestVoxelArea::test_index_v3s16_z_neg()
@ -330,8 +361,8 @@ void TestVoxelArea::test_index_v3s16_z_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(v3s16(244, 336, -887)), 243);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(v3s16(244, 336, -887)), -191478876);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(v3s16(244, 336, -887)), -190690273);
}
void TestVoxelArea::test_index_v3s16_xy_neg()
@ -339,8 +370,8 @@ void TestVoxelArea::test_index_v3s16_xy_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(v3s16(-365, -47, 6978)), -366);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(v3s16(-365, -47, 6978)), 1493679101);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(v3s16(-365, -47, 6978)), 1797427926);
}
void TestVoxelArea::test_index_v3s16_yz_neg()
@ -348,8 +379,8 @@ void TestVoxelArea::test_index_v3s16_yz_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(v3s16(66, -58, -789)), 65);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(v3s16(66, -58, -789)), 1435362734);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(v3s16(66, -58, -789)), 1439223357);
}
void TestVoxelArea::test_index_v3s16_xz_neg()
@ -357,8 +388,8 @@ void TestVoxelArea::test_index_v3s16_xz_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(v3s16(-36, 589, -992)), -37);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(v3s16(-36, 589, -992)), -1934371362);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(v3s16(-36, 589, -992)), -1937179681);
}
void TestVoxelArea::test_index_v3s16_all_neg()
@ -366,8 +397,8 @@ void TestVoxelArea::test_index_v3s16_all_neg()
VoxelArea v1;
UASSERTEQ(s32, v1.index(v3s16(-88, -99, -1474)), -89);
VoxelArea v2(v3s16(756, 8854, -875), v3s16(-147, -9547, 669));
UASSERTEQ(s32, v2.index(v3s16(-88, -99, -1474)), -1343473846);
VoxelArea v2(v3s16(-147, -9547, -875), v3s16(756, 8854, 669));
UASSERTEQ(s32, v2.index(v3s16(-88, -99, -1474)), -1366133749);
}
void TestVoxelArea::test_add_x()

View file

@ -29,10 +29,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
/*
Debug stuff
*/
u64 addarea_time = 0;
u64 emerge_time = 0;
u64 emerge_load_time = 0;
u64 clearflag_time = 0;
VoxelManipulator::~VoxelManipulator()
{
@ -53,7 +51,7 @@ void VoxelManipulator::clear()
}
void VoxelManipulator::print(std::ostream &o, const NodeDefManager *ndef,
VoxelPrintMode mode)
VoxelPrintMode mode) const
{
const v3s16 &em = m_area.getExtent();
v3s16 of = m_area.MinEdge;
@ -140,8 +138,6 @@ void VoxelManipulator::addArea(const VoxelArea &area)
if(m_area.contains(area))
return;
TimeTaker timer("addArea", &addarea_time);
// Calculate new area
VoxelArea new_area;
// New area is the requested area if m_area has zero volume
@ -158,15 +154,6 @@ void VoxelManipulator::addArea(const VoxelArea &area)
s32 new_size = new_area.getVolume();
/*dstream<<"adding area ";
area.print(dstream);
dstream<<", old area ";
m_area.print(dstream);
dstream<<", new area ";
new_area.print(dstream);
dstream<<", new_size="<<new_size;
dstream<<std::endl;*/
// Allocate new data and clear flags
MapNode *new_data = new MapNode[new_size];
assert(new_data);
@ -195,16 +182,11 @@ void VoxelManipulator::addArea(const VoxelArea &area)
MapNode *old_data = m_data;
u8 *old_flags = m_flags;
/*dstream<<"old_data="<<(int)old_data<<", new_data="<<(int)new_data
<<", old_flags="<<(int)m_flags<<", new_flags="<<(int)new_flags<<std::endl;*/
m_data = new_data;
m_flags = new_flags;
delete[] old_data;
delete[] old_flags;
//dstream<<"addArea done"<<std::endl;
}
void VoxelManipulator::copyFrom(MapNode *src, const VoxelArea& src_area,
@ -256,7 +238,7 @@ void VoxelManipulator::copyFrom(MapNode *src, const VoxelArea& src_area,
}
void VoxelManipulator::copyTo(MapNode *dst, const VoxelArea& dst_area,
v3s16 dst_pos, v3s16 from_pos, const v3s16 &size)
v3s16 dst_pos, v3s16 from_pos, const v3s16 &size) const
{
for(s16 z=0; z<size.Z; z++)
for(s16 y=0; y<size.Y; y++)
@ -277,46 +259,38 @@ void VoxelManipulator::copyTo(MapNode *dst, const VoxelArea& dst_area,
-----------------------------------------------------
*/
void VoxelManipulator::clearFlag(u8 flags)
void VoxelManipulator::setFlags(const VoxelArea &a, u8 flags)
{
// 0-1ms on moderate area
TimeTaker timer("clearFlag", &clearflag_time);
if (a.hasEmptyExtent())
return;
//v3s16 s = m_area.getExtent();
assert(m_area.contains(a));
/*dstream<<"clearFlag clearing area of size "
<<""<<s.X<<"x"<<s.Y<<"x"<<s.Z<<""
<<std::endl;*/
//s32 count = 0;
/*for(s32 z=m_area.MinEdge.Z; z<=m_area.MaxEdge.Z; z++)
for(s32 y=m_area.MinEdge.Y; y<=m_area.MaxEdge.Y; y++)
for(s32 x=m_area.MinEdge.X; x<=m_area.MaxEdge.X; x++)
const s32 stride = a.getExtent().X;
for (s32 z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++)
for (s32 y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++)
{
u8 f = m_flags[m_area.index(x,y,z)];
m_flags[m_area.index(x,y,z)] &= ~flags;
if(m_flags[m_area.index(x,y,z)] != f)
count++;
}*/
s32 volume = m_area.getVolume();
for(s32 i=0; i<volume; i++)
{
m_flags[i] &= ~flags;
const s32 start = m_area.index(a.MinEdge.X, y, z);
for (s32 i = start; i < start + stride; i++)
m_flags[i] |= flags;
}
}
/*s32 volume = m_area.getVolume();
for(s32 i=0; i<volume; i++)
void VoxelManipulator::clearFlags(const VoxelArea &a, u8 flags)
{
if (a.hasEmptyExtent())
return;
assert(m_area.contains(a));
const s32 stride = a.getExtent().X;
for (s32 z = a.MinEdge.Z; z <= a.MaxEdge.Z; z++)
for (s32 y = a.MinEdge.Y; y <= a.MaxEdge.Y; y++)
{
u8 f = m_flags[i];
m_flags[i] &= ~flags;
if(m_flags[i] != f)
count++;
const s32 start = m_area.index(a.MinEdge.X, y, z);
for (s32 i = start; i < start + stride; i++)
m_flags[i] &= ~flags;
}
dstream<<"clearFlag changed "<<count<<" flags out of "
<<volume<<" nodes"<<std::endl;*/
}
const MapNode VoxelManipulator::ContentIgnoreNode = MapNode(CONTENT_IGNORE);

View file

@ -59,7 +59,7 @@ class VoxelArea
{
public:
// Starts as zero sized
VoxelArea() = default;
constexpr VoxelArea() = default;
VoxelArea(const v3s16 &min_edge, const v3s16 &max_edge):
MinEdge(min_edge),
@ -129,12 +129,11 @@ public:
return m_cache_extent;
}
/* Because MaxEdge and MinEdge are included in the voxel area an empty extent
* is not represented by (0, 0, 0), but instead (-1, -1, -1)
*/
/// @note `getVolume() == 0` and `getEmptyExtent()` are not identical.
bool hasEmptyExtent() const
{
return MaxEdge - MinEdge == v3s16(-1, -1, -1);
// FIXME: shouldn't this actually be a component-wise check?
return m_cache_extent == v3s16(0,0,0);
}
s32 getVolume() const
@ -208,83 +207,74 @@ public:
return ret;
}
/*
/**
Returns 0-6 non-overlapping areas that can be added to
a to make up this area.
`a` to make up this area.
a: area inside *this
@tparam C container that has push_back
@param a area inside *this
*/
void diff(const VoxelArea &a, std::list<VoxelArea> &result)
template <typename C>
void diff(const VoxelArea &a, C &result) const
{
/*
This can result in a maximum of 6 areas
*/
// If a is an empty area, return the current area as a whole
if(a.getExtent() == v3s16(0,0,0))
if(a.hasEmptyExtent())
{
VoxelArea b = *this;
if(b.getVolume() != 0)
if (b.getVolume() != 0)
result.push_back(b);
return;
}
assert(contains(a)); // pre-condition
const auto &take = [&result] (v3s16 min, v3s16 max) {
VoxelArea b(min, max);
if (b.getVolume() != 0)
result.push_back(b);
};
// Take back area, XY inclusive
{
v3s16 min(MinEdge.X, MinEdge.Y, a.MaxEdge.Z+1);
v3s16 max(MaxEdge.X, MaxEdge.Y, MaxEdge.Z);
VoxelArea b(min, max);
if(b.getVolume() != 0)
result.push_back(b);
take(min, max);
}
// Take front area, XY inclusive
{
v3s16 min(MinEdge.X, MinEdge.Y, MinEdge.Z);
v3s16 max(MaxEdge.X, MaxEdge.Y, a.MinEdge.Z-1);
VoxelArea b(min, max);
if(b.getVolume() != 0)
result.push_back(b);
take(min, max);
}
// Take top area, X inclusive
{
v3s16 min(MinEdge.X, a.MaxEdge.Y+1, a.MinEdge.Z);
v3s16 max(MaxEdge.X, MaxEdge.Y, a.MaxEdge.Z);
VoxelArea b(min, max);
if(b.getVolume() != 0)
result.push_back(b);
take(min, max);
}
// Take bottom area, X inclusive
{
v3s16 min(MinEdge.X, MinEdge.Y, a.MinEdge.Z);
v3s16 max(MaxEdge.X, a.MinEdge.Y-1, a.MaxEdge.Z);
VoxelArea b(min, max);
if(b.getVolume() != 0)
result.push_back(b);
take(min, max);
}
// Take left area, non-inclusive
{
v3s16 min(MinEdge.X, a.MinEdge.Y, a.MinEdge.Z);
v3s16 max(a.MinEdge.X-1, a.MaxEdge.Y, a.MaxEdge.Z);
VoxelArea b(min, max);
if(b.getVolume() != 0)
result.push_back(b);
take(min, max);
}
// Take right area, non-inclusive
{
v3s16 min(a.MaxEdge.X+1, a.MinEdge.Y, a.MinEdge.Z);
v3s16 max(MaxEdge.X, a.MaxEdge.Y, a.MaxEdge.Z);
VoxelArea b(min, max);
if(b.getVolume() != 0)
result.push_back(b);
take(min, max);
}
}
/*
@ -344,30 +334,34 @@ public:
<< "=" << getVolume();
}
// Edges are inclusive
/// Minimum edge of the area (inclusive)
/// @warning read-only!
v3s16 MinEdge = v3s16(1,1,1);
/// Maximum edge of the area (inclusive)
/// @warning read-only!
v3s16 MaxEdge;
private:
void cacheExtent()
{
m_cache_extent = MaxEdge - MinEdge + v3s16(1,1,1);
// If positions were sorted correctly this must always hold.
// Note that this still permits empty areas (where MinEdge = MaxEdge + 1).
assert(m_cache_extent.X >= 0);
assert(m_cache_extent.Y >= 0);
assert(m_cache_extent.Z >= 0);
}
v3s16 m_cache_extent = v3s16(0,0,0);
};
// unused
#define VOXELFLAG_UNUSED (1 << 0)
// no data about that node
#define VOXELFLAG_NO_DATA (1 << 1)
// Algorithm-dependent
#define VOXELFLAG_CHECKED1 (1 << 2)
// Algorithm-dependent
#define VOXELFLAG_CHECKED2 (1 << 3)
// Algorithm-dependent
#define VOXELFLAG_CHECKED3 (1 << 4)
// Algorithm-dependent
#define VOXELFLAG_CHECKED4 (1 << 5)
enum : u8 {
VOXELFLAG_NO_DATA = 1 << 0, // no data about that node
VOXELFLAG_CHECKED1 = 1 << 1, // Algorithm-dependent
VOXELFLAG_CHECKED2 = 1 << 2, // Algorithm-dependent
VOXELFLAG_CHECKED3 = 1 << 3, // Algorithm-dependent
VOXELFLAG_CHECKED4 = 1 << 4, // Algorithm-dependent
};
enum VoxelPrintMode
{
@ -414,7 +408,7 @@ public:
return m_data[index];
}
MapNode getNodeNoExNoEmerge(const v3s16 &p)
MapNode getNodeNoExNoEmerge(const v3s16 &p) const
{
if (!m_area.contains(p))
return {CONTENT_IGNORE};
@ -430,7 +424,7 @@ public:
return m_data[m_area.index(p)];
}
const MapNode & getNodeRefUnsafeCheckFlags(const v3s16 &p)
const MapNode & getNodeRefUnsafeCheckFlags(const v3s16 &p) const
{
s32 index = m_area.index(p);
@ -483,10 +477,13 @@ public:
virtual void clear();
void print(std::ostream &o, const NodeDefManager *nodemgr,
VoxelPrintMode mode=VOXELPRINT_MATERIAL);
VoxelPrintMode mode=VOXELPRINT_MATERIAL) const;
void addArea(const VoxelArea &area);
void setFlags(const VoxelArea &area, u8 flag);
void clearFlags(const VoxelArea &area, u8 flag);
/*
Copy data and set flags to 0
dst_area.getExtent() <= src_area.getExtent()
@ -496,13 +493,7 @@ public:
// Copy data
void copyTo(MapNode *dst, const VoxelArea& dst_area,
v3s16 dst_pos, v3s16 from_pos, const v3s16 &size);
/*
Algorithms
*/
void clearFlag(u8 flag);
v3s16 dst_pos, v3s16 from_pos, const v3s16 &size) const;
/*
Member variables
@ -510,13 +501,12 @@ public:
/*
The area that is stored in m_data.
addInternalBox should not be used if getExtent() == v3s16(0,0,0)
MaxEdge is 1 higher than maximum allowed position
MaxEdge is 1 higher than maximum allowed position.
*/
VoxelArea m_area;
/*
nullptr if data size is 0 (extent (0,0,0))
nullptr if data size is 0 (empty extent)
Data is stored as [z*h*w + y*h + x]
*/
MapNode *m_data = nullptr;

View file

@ -943,14 +943,18 @@ bool propagate_block_sunlight(Map *map, const NodeDefManager *ndef,
* The areas do not overlap.
* Compatible with type 'direction'.
*/
const VoxelArea block_pad[] = {
VoxelArea(v3s16(15, 0, 0), v3s16(15, 15, 15)), //X+
VoxelArea(v3s16(1, 15, 0), v3s16(14, 15, 15)), //Y+
VoxelArea(v3s16(1, 1, 15), v3s16(14, 14, 15)), //Z+
VoxelArea(v3s16(1, 1, 0), v3s16(14, 14, 0)), //Z-
VoxelArea(v3s16(1, 0, 0), v3s16(14, 0, 15)), //Y-
VoxelArea(v3s16(0, 0, 0), v3s16(0, 15, 15)) //X-
#define B_1 (MAP_BLOCKSIZE - 1)
#define B_2 (MAP_BLOCKSIZE - 2)
const static VoxelArea block_pad[] = {
VoxelArea({B_1, 0, 0}, {B_1, B_1, B_1}), //X+
VoxelArea({1, B_1, 0}, {B_2, B_1, B_1}), //Y+
VoxelArea({1, 1, B_1}, {B_2, B_2, B_1}), //Z+
VoxelArea({1, 1, 0}, {B_2, B_2, 0}), //Z-
VoxelArea({1, 0, 0}, {B_2, 0, B_1}), //Y-
VoxelArea({0, 0, 0}, {0, B_1, B_1}) //X-
};
#undef B_1
#undef B_2
/*!
* The common part of bulk light updates - it is always executed.