1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-08-01 17:38:41 +00:00

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

@ -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.