VOXELGENERATOR: fixed shape generators

added shape generator tests
master
Martin Gerhardy 2020-08-30 12:22:06 +02:00
parent faa21ffbb5
commit f8aa6a6f31
9 changed files with 129 additions and 13 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -15,12 +15,25 @@ engine_add_module(TARGET ${LIB} SRCS ${SRCS} DEPENDENCIES voxel voxelutil noise
set(TEST_SRCS
tests/LSystemTest.cpp
tests/LUAGeneratorTest.cpp
tests/ShapeGeneratorTest.cpp
)
set(TEST_FILES
testvoxelgenerator/cone.qb
testvoxelgenerator/cube.qb
testvoxelgenerator/cylinder.qb
testvoxelgenerator/dome.qb
testvoxelgenerator/ellipse.qb
)
set(TEST_DEPENDENCIES voxelformat)
gtest_suite_sources(tests ${TEST_SRCS})
gtest_suite_deps(tests ${LIB})
gtest_suite_files(tests ${TEST_FILES})
gtest_suite_deps(tests ${LIB} ${TEST_DEPENDENCIES})
gtest_suite_begin(tests-${LIB} TEMPLATE ${ROOT_DIR}/src/modules/core/tests/main.cpp.in)
gtest_suite_sources(tests-${LIB} ${TEST_SRCS} ../core/tests/AbstractTest.cpp)
gtest_suite_deps(tests-${LIB} ${LIB})
gtest_suite_files(tests-${LIB} ${TEST_FILES})
gtest_suite_deps(tests-${LIB} ${LIB} ${TEST_DEPENDENCIES})
gtest_suite_end(tests-${LIB})

View File

@ -34,11 +34,10 @@ void createCirclePlane(Volume& volume, const glm::ivec3& center, int width, int
const double xRadius = width / 2.0;
const double zRadius = depth / 2.0;
radius = glm::pow(radius, 2.0);
for (double z = -zRadius; z <= zRadius; ++z) {
const double distanceZ = glm::pow(z, 2.0);
for (double x = -xRadius; x <= xRadius; ++x) {
const double distance = glm::pow(x, 2.0) + distanceZ;
const double distance = glm::sqrt(glm::pow(x, 2.0) + distanceZ);
if (distance > radius) {
continue;
}
@ -172,8 +171,12 @@ void createEllipse(Volume& volume, const glm::ivec3& center, int width, int heig
const int start = heightLow - 1;
const double minRadius = glm::pow(adjustedMinRadius + 0.5, 2.0);
for (int y = -start; y <= heightHigh; ++y) {
const double percent = glm::abs(y) / heightFactor;
const double circleRadius = minRadius - glm::pow(percent, 2.0);
const double percent = glm::pow(glm::abs(y / heightFactor), 2.0);
const double yRadiusSquared = minRadius - percent;
if (yRadiusSquared < 0.0) {
break;
}
const double circleRadius = glm::sqrt(yRadiusSquared);
const glm::ivec3 planePos(center.x, center.y + y, center.z);
createCirclePlane(volume, planePos, width, depth, circleRadius, voxel);
}
@ -203,7 +206,7 @@ void createCone(Volume& volume, const glm::ivec3& center, int width, int height,
const int start = heightLow - 1;
for (int y = -start; y <= heightHigh; ++y) {
const double percent = 1.0 - ((y + start) / dHeight);
const double circleRadius = glm::pow(percent * minRadius, 2.0);
const double circleRadius = percent * minRadius;
const glm::ivec3 planePos(center.x, center.y + y, center.z);
createCirclePlane(volume, planePos, width, depth, circleRadius, voxel);
}
@ -233,7 +236,12 @@ void createDome(Volume& volume, const glm::ivec3& center, int width, int height,
const int start = heightLow - 1;
for (int y = -start; y <= heightHigh; ++y) {
const double percent = glm::abs((y + start) / heightFactor);
const double circleRadius = minRadius - glm::pow(percent, 2.0);
const double yRadius = glm::pow(percent, 2.0);
const double circleRadiusSquared = minRadius - yRadius;
if (circleRadiusSquared < 0.0) {
break;
}
const double circleRadius = glm::sqrt(circleRadiusSquared);
const glm::ivec3 planePos(center.x, center.y + y, center.z);
createCirclePlane(volume, planePos, width, depth, circleRadius, voxel);
}
@ -397,15 +405,15 @@ void createTorus(Volume& volume, const glm::ivec3& center, int innerRadius, int
}
template<class Volume>
void createCylinder(Volume& volume, const glm::vec3& center, const math::Axis axis, int radius, int height, const voxel::Voxel& voxel) {
void createCylinder(Volume& volume, const glm::vec3& centerBottom, const math::Axis axis, int radius, int height, const voxel::Voxel& voxel) {
for (int i = 0; i < height; ++i) {
glm::ivec3 centerH;
if (axis == math::Axis::Y) {
centerH = glm::ivec3(center.x, center.y + i, center.z);
centerH = glm::ivec3(centerBottom.x, centerBottom.y + i, centerBottom.z);
} else if (axis == math::Axis::X) {
centerH = glm::ivec3(center.x + i, center.y, center.z);
centerH = glm::ivec3(centerBottom.x + i, centerBottom.y, centerBottom.z);
} else {
centerH = glm::ivec3(center.x, center.y, center.z + i);
centerH = glm::ivec3(centerBottom.x, centerBottom.y, centerBottom.z + i);
}
createCirclePlane(volume, centerH, radius * 2, radius * 2, radius, voxel, axis);
}

View File

@ -0,0 +1,95 @@
/**
* @file
*/
#include "core/App.h"
#include "core/io/Filesystem.h"
#include "core/tests/AbstractTest.h"
#include "voxel/RawVolume.h"
#include "voxel/RawVolumeWrapper.h"
#include "voxel/Voxel.h"
#include "voxel/tests/AbstractVoxelTest.h"
#include "voxelformat/QBFormat.h"
#include "voxelgenerator/ShapeGenerator.h"
#include "voxelutil/VolumeVisitor.h"
namespace voxelgenerator {
class ShapeGeneratorTest: public core::AbstractTest {
private:
using Super = core::AbstractTest;
protected:
static constexpr voxel::Region _region {0, 31};
static constexpr glm::ivec3 _center { 15 };
static constexpr int _width { 32 };
static constexpr int _height { 32 };
static constexpr int _depth { 32 };
static constexpr voxel::Voxel _voxel = voxel::createVoxel(voxel::VoxelType::Generic, 1);
voxel::RawVolume *_volume = nullptr;
void verify(const char* filename) {
voxel::QBFormat format;
const io::FilePtr& file = io::filesystem()->open(filename);
ASSERT_TRUE(file) << "Can't open " << filename;
voxel::RawVolume* v = format.load(file);
ASSERT_NE(nullptr, v) << "Can't load " << filename;
EXPECT_EQ(*v, *_volume);
delete v;
}
public:
void SetUp() override {
Super::SetUp();
_volume = new voxel::RawVolume(_region);
}
void TearDown() override {
delete _volume;
Super::TearDown();
}
};
TEST_F(ShapeGeneratorTest, testCreateCubeNoCenter) {
voxel::RawVolumeWrapper wrapper(_volume);
shape::createCubeNoCenter(wrapper, _region.getLowerCorner(), _width, _height, _depth, _voxel);
verify("cube.qb");
}
TEST_F(ShapeGeneratorTest, testCreateCube) {
voxel::RawVolumeWrapper wrapper(_volume);
shape::createCube(wrapper, _center, _width, _height, _depth, _voxel);
int count = 0;
voxelutil::visitVolume(*_volume, [&count] (int x, int y, int z, const voxel::Voxel& voxel) {
++count;
});
// this -1 is due to rounding errors - but those are expected. The shape generator doesn't
// know anything about the region position.
ASSERT_EQ((_width - 1) * (_height - 1) * (_depth - 1), count);
}
TEST_F(ShapeGeneratorTest, testCreateEllipse) {
voxel::RawVolumeWrapper wrapper(_volume);
shape::createEllipse(wrapper, _center, _width, _height, _depth, _voxel);
verify("ellipse.qb");
}
TEST_F(ShapeGeneratorTest, testCreateCone) {
voxel::RawVolumeWrapper wrapper(_volume);
shape::createCone(wrapper, _center, _width, _height, _depth, _voxel);
verify("cone.qb");
}
TEST_F(ShapeGeneratorTest, testCreateDome) {
voxel::RawVolumeWrapper wrapper(_volume);
shape::createDome(wrapper, _center, _width, _height, _depth, _voxel);
verify("dome.qb");
}
TEST_F(ShapeGeneratorTest, testCreateCylinder) {
voxel::RawVolumeWrapper wrapper(_volume);
glm::ivec3 centerBottom = _center;
centerBottom.y = _region.getLowerY();
shape::createCylinder(wrapper, centerBottom, math::Axis::Y, _width / 2, _height, _voxel);
verify("cylinder.qb");
}
}

View File

@ -122,7 +122,7 @@ bool Modifier::executeShapeAction(ModifierVolumeWrapper& wrapper, const glm::ive
const voxel::Region region(operateMins, operateMaxs);
voxel::logRegion("Shape action execution", region);
const glm::ivec3& center = region.getCenter();
glm::ivec3 centerBottom = region.getCenter();
glm::ivec3 centerBottom = center;
centerBottom.y = region.getLowerY();
const glm::ivec3& dimensions = region.getDimensionsInVoxels();
switch (_shapeType) {