From 6d5103900f9d8e6b78350b9e66a97c2ceaeb9be9 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 7 Oct 2024 17:48:19 +0200 Subject: [PATCH] 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. --- doc/lua_api.md | 11 ++-- src/map.cpp | 16 ++--- src/map.h | 2 +- src/mapblock.cpp | 4 +- src/mapblock.h | 4 +- src/mapgen/dungeongen.cpp | 2 +- src/script/lua_api/l_vmanip.cpp | 3 + src/unittest/test_voxelarea.cpp | 113 ++++++++++++++++++++------------ src/voxel.cpp | 78 ++++++++-------------- src/voxel.h | 110 ++++++++++++++----------------- src/voxelalgorithms.cpp | 18 +++-- 11 files changed, 178 insertions(+), 183 deletions(-) diff --git a/doc/lua_api.md b/doc/lua_api.md index f2f0a5ba3..d9e683da3 100644 --- a/doc/lua_api.md +++ b/doc/lua_api.md @@ -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` diff --git a/src/map.cpp b/src/map.cpp index d54ed1270..85ff0e84a 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -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 *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); diff --git a/src/map.h b/src/map.h index a4bf45314..e3624a68d 100644 --- a/src/map.h +++ b/src/map.h @@ -333,7 +333,7 @@ public: // This is much faster with big chunks of generated data void blitBackAll(std::map * modified_blocks, - bool overwrite_generated = true); + bool overwrite_generated = true) const; /* Creates a copy of this VManip including contents, the copy will not be diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 9a27a9f3d..714b47ec1 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -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); } diff --git a/src/mapblock.h b/src/mapblock.h index 843daf6ef..044c104bc 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -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. diff --git a/src/mapgen/dungeongen.cpp b/src/mapgen/dungeongen.cpp index 1d439abeb..0369bdac3 100644 --- a/src/mapgen/dungeongen.cpp +++ b/src/mapgen/dungeongen.cpp @@ -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 diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp index 76b5aff0f..72ecc55b6 100644 --- a/src/script/lua_api/l_vmanip.cpp +++ b/src/script/lua_api/l_vmanip.cpp @@ -333,6 +333,9 @@ int LuaVoxelManip::l_was_modified(lua_State *L) LuaVoxelManip *o = checkObject(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; diff --git a/src/unittest/test_voxelarea.cpp b/src/unittest/test_voxelarea.cpp index 386fe499c..1139e72fa 100644 --- a/src/unittest/test_voxelarea.cpp +++ b/src/unittest/test_voxelarea.cpp @@ -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 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() diff --git a/src/voxel.cpp b/src/voxel.cpp index 0f87cf282..9fb310962 100644 --- a/src/voxel.cpp +++ b/src/voxel.cpp @@ -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="< &result) + template + 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; diff --git a/src/voxelalgorithms.cpp b/src/voxelalgorithms.cpp index 607d6716c..6d159fcf2 100644 --- a/src/voxelalgorithms.cpp +++ b/src/voxelalgorithms.cpp @@ -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.