VOXELUTIL: improved fillPlane algorithm

master
Martin Gerhardy 2022-05-01 22:34:20 +02:00
parent 67e81f2ebe
commit 8887798aa6
3 changed files with 51 additions and 15 deletions

View File

@ -161,65 +161,87 @@ void fillHollow(voxel::RawVolume &in, const voxel::Voxel &voxel) {
fillRegion(in, voxel, in.region());
}
static void fillPlane_r(voxel::RawVolumeWrapper &in, const voxel::Region &region, const voxel::Voxel &voxel,
const voxel::Voxel &replace, const glm::ivec3 &position) {
static void fillPlane_r(voxel::RawVolumeWrapper &in, const voxel::Region &region, const voxel::Voxel &targetVoxel,
const voxel::Voxel &searchedVoxel, const glm::ivec3 &position, const glm::ivec3 &offset) {
if (!region.containsPoint(position)) {
return;
}
if (in.voxel(position).getColor() != replace.getColor()) {
if (in.voxel(position) != searchedVoxel) {
return;
}
if (!in.setVoxel(position, voxel)) {
const glm::ivec3 &ground = position + offset;
if (in.region().containsPoint(ground)) {
if (in.voxel(ground) == searchedVoxel) {
return;
}
}
if (!in.setVoxel(position, targetVoxel)) {
return;
}
if (region.containsPoint(position.x + 1, position.y, position.z)) {
fillPlane_r(in, region, voxel, replace, glm::ivec3(position.x + 1, position.y, position.z));
fillPlane_r(in, region, targetVoxel, searchedVoxel, glm::ivec3(position.x + 1, position.y, position.z), offset);
}
if (region.containsPoint(position.x - 1, position.y, position.z)) {
fillPlane_r(in, region, voxel, replace, glm::ivec3(position.x - 1, position.y, position.z));
fillPlane_r(in, region, targetVoxel, searchedVoxel, glm::ivec3(position.x - 1, position.y, position.z), offset);
}
if (region.containsPoint(position.x, position.y + 1, position.z)) {
fillPlane_r(in, region, voxel, replace, glm::ivec3(position.x, position.y + 1, position.z));
fillPlane_r(in, region, targetVoxel, searchedVoxel, glm::ivec3(position.x, position.y + 1, position.z), offset);
}
if (region.containsPoint(position.x, position.y - 1, position.z)) {
fillPlane_r(in, region, voxel, replace, glm::ivec3(position.x, position.y - 1, position.z));
fillPlane_r(in, region, targetVoxel, searchedVoxel, glm::ivec3(position.x, position.y - 1, position.z), offset);
}
if (region.containsPoint(position.x, position.y, position.z + 1)) {
fillPlane_r(in, region, voxel, replace, glm::ivec3(position.x, position.y, position.z + 1));
fillPlane_r(in, region, targetVoxel, searchedVoxel, glm::ivec3(position.x, position.y, position.z + 1), offset);
}
if (region.containsPoint(position.x, position.y, position.z - 1)) {
fillPlane_r(in, region, voxel, replace, glm::ivec3(position.x, position.y, position.z - 1));
fillPlane_r(in, region, targetVoxel, searchedVoxel, glm::ivec3(position.x, position.y, position.z - 1), offset);
}
}
void fillPlane(voxel::RawVolumeWrapper &in, const voxel::Voxel &voxel, const voxel::Voxel &replace, const glm::ivec3 &position,
voxel::FaceNames face) {
if (voxel.getColor() == replace.getColor()) {
void fillPlane(voxel::RawVolumeWrapper &in, const voxel::Voxel &targetVoxel, const voxel::Voxel &searchedVoxel,
const glm::ivec3 &position, voxel::FaceNames face) {
if (targetVoxel == searchedVoxel) {
return;
}
glm::ivec3 mins = in.region().getLowerCorner();
glm::ivec3 maxs = in.region().getUpperCorner();
glm::ivec3 offset(0);
switch (face) {
case voxel::FaceNames::PositiveX:
mins.x = position.x;
maxs.x = position.x;
offset.x = -1;
break;
case voxel::FaceNames::NegativeX:
mins.x = position.x;
maxs.x = position.x;
offset.x = 1;
break;
case voxel::FaceNames::PositiveY:
mins.y = position.y;
maxs.y = position.y;
offset.y = -1;
break;
case voxel::FaceNames::NegativeY:
mins.y = position.y;
maxs.y = position.y;
offset.y = 1;
break;
case voxel::FaceNames::PositiveZ:
mins.z = position.z;
maxs.z = position.z;
offset.z = -1;
break;
case voxel::FaceNames::NegativeZ:
mins.z = position.z;
maxs.z = position.z;
offset.z = 1;
break;
case voxel::FaceNames::Max:
return;
}
const voxel::Region region(mins, maxs);
fillPlane_r(in, region, voxel, replace, position);
fillPlane_r(in, region, targetVoxel, searchedVoxel, position, offset);
}
} // namespace voxelutil

View File

@ -21,7 +21,7 @@ bool copy(const voxel::RawVolume &in, const voxel::Region& inRegion, voxel::RawV
* @sa voxel::isBlocked()
*/
bool isEmpty(const voxel::RawVolume &in, const voxel::Region &region);
void fillPlane(voxel::RawVolumeWrapper &in, const voxel::Voxel &voxel, const voxel::Voxel &replace, const glm::ivec3 &position, voxel::FaceNames face);
void fillPlane(voxel::RawVolumeWrapper &in, const voxel::Voxel &targetVoxel, const voxel::Voxel &searchedVoxel, const glm::ivec3 &position, voxel::FaceNames face);
void fillHollow(voxel::RawVolume &in, const voxel::Voxel &voxel);
}

View File

@ -59,6 +59,20 @@ TEST_F(VoxelUtilTest, testFillHollowLeak) {
EXPECT_EQ(0, v.voxel(region.getCenter()).getColor());
}
TEST_F(VoxelUtilTest, testFillPlanePositiveYExtrude) {
voxel::Region region(0, 2);
voxel::RawVolume v(region);
const voxel::Voxel fillVoxel = voxel::createVoxel(voxel::VoxelType::Generic, 2);
voxel::RawVolumeWrapper wrapper(&v);
// build an L
v.setVoxel(0, 0, 0, fillVoxel);
v.setVoxel(1, 0, 0, fillVoxel);
v.setVoxel(2, 0, 0, fillVoxel);
v.setVoxel(2, 0, 1, fillVoxel);
voxelutil::fillPlane(wrapper, fillVoxel, voxel::Voxel(), glm::ivec3(1, 1, 0), voxel::FaceNames::PositiveY);
EXPECT_EQ(8, voxelutil::visitVolume(v, [&](int, int, int, const voxel::Voxel &) {}));
}
TEST_F(VoxelUtilTest, testFillPlanePositiveY) {
voxel::Region region(0, 2);
voxel::RawVolume v(region);