mirror of
https://github.com/luanti-org/luanti.git
synced 2025-07-27 17:28: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:
parent
5532248cd7
commit
6d5103900f
11 changed files with 178 additions and 183 deletions
110
src/voxel.h
110
src/voxel.h
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue