parent
faa21ffbb5
commit
f8aa6a6f31
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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})
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue