More work on tests.

This commit is contained in:
David Williams 2014-08-12 16:53:47 +02:00
parent ed4bdf08c4
commit d4118a2052
2 changed files with 26 additions and 130 deletions

View File

@ -318,6 +318,13 @@ namespace PolyVox
typename Controller::DensityType m_tThreshold;
};
// This version of the function performs the extraction into a user-provided mesh rather than allocating a mesh automatically.
// There are a few reasons why this might be useful to more advanced users:
//
// 1. It leaves the user in control of memory allocation and would allow them to implement e.g. a mesh pooling system.
// 2. The user-provided mesh could have a different index type (e.g. 16-bit indices) to reduce memory usage.
// 3. The user could provide a custom mesh class, e.g a thin wrapper around an openGL VBO to allow direct writing into this structure.
//
// We don't provide a default MeshType here. If the user doesn't want to provide a MeshType then it probably makes
// more sense to use the other variaent of this function where the mesh is a return value rather than a parameter.
template< typename VolumeType, typename MeshType, typename Controller = DefaultMarchingCubesController<typename VolumeType::VoxelType> >

View File

@ -52,12 +52,12 @@ public:
float convertToMaterial(float /*voxel*/)
{
return 1;
return 1.0f;
}
float blendMaterials(float /*a*/, float /*b*/, float /*weight*/)
{
return 1;
return 1.0f;
}
float getThreshold(void)
@ -75,12 +75,6 @@ void writeDensityValueToVoxel(int valueToWrite, VoxelType& voxel)
voxel = valueToWrite;
}
template<>
void writeDensityValueToVoxel(int valueToWrite, Density8& voxel)
{
voxel.setDensity(valueToWrite);
}
template<>
void writeDensityValueToVoxel(int valueToWrite, MaterialDensityPair88& voxel)
{
@ -128,150 +122,43 @@ SimpleVolume<VoxelType>* createAndFillVolume(void)
return volData;
}
// Runs the surface extractor for a given type.
template <typename VoxelType>
Mesh<MarchingCubesVertex<VoxelType> > testForType(void) //I think we could avoid specifying this return type by using auto/decltype?
{
const int32_t uVolumeSideLength = 32;
//Create empty volume
SimpleVolume<VoxelType> volData(Region(Vector3DInt32(0, 0, 0), Vector3DInt32(uVolumeSideLength - 1, uVolumeSideLength - 1, uVolumeSideLength - 1)));
for (int32_t z = 0; z < uVolumeSideLength; z++)
{
for (int32_t y = 0; y < uVolumeSideLength; y++)
{
for (int32_t x = 0; x < uVolumeSideLength; x++)
{
VoxelType voxelValue;
//Create a density field which changes throughout the volume.
writeDensityValueToVoxel<VoxelType>(x + y + z, voxelValue);
//Two different materials in two halves of the volume
writeMaterialValueToVoxel<VoxelType>(z > uVolumeSideLength / 2 ? 42 : 79, voxelValue);
volData.setVoxelAt(x, y, z, voxelValue);
}
}
}
DefaultMarchingCubesController<VoxelType> controller;
controller.setThreshold(50);
auto result = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion(), WrapModes::Border, VoxelType(), controller);
return result;
}
void testCustomController(Mesh<MarchingCubesVertex<float> >& result)
{
const int32_t uVolumeSideLength = 32;
//Create empty volume
SimpleVolume<float> volData(Region(Vector3DInt32(0,0,0), Vector3DInt32(uVolumeSideLength-1, uVolumeSideLength-1, uVolumeSideLength-1)));
for (int32_t z = 0; z < uVolumeSideLength; z++)
{
for (int32_t y = 0; y < uVolumeSideLength; y++)
{
for (int32_t x = 0; x < uVolumeSideLength; x++)
{
float voxelValue = x + y + z;
volData.setVoxelAt(x, y, z, voxelValue);
}
}
}
CustomMarchingCubesController controller;
extractMarchingCubesMesh(&volData, volData.getEnclosingRegion(), WrapModes::Border, 0, controller, &result);
}
void TestSurfaceExtractor::testExecute()
{
const static uint32_t uExpectedVertices = 4731;
const static uint32_t uExpectedIndices = 12810;
const static uint32_t uMaterialToCheck = 3000;
const static float fExpectedData = 1.0f;
const static float fNoMaterial = 1.0f;
Mesh<MarchingCubesVertex<int8_t> > mesh;
//Run the test for various voxel types.
QBENCHMARK {
mesh = testForType<int8_t>();
}
QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh.getVertices()[uMaterialToCheck].data, static_cast<int8_t>(fExpectedData));
auto mesh1 = testForType<uint8_t>();
QCOMPARE(mesh1.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh1.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh1.getVertices()[uMaterialToCheck].data, static_cast<uint8_t>(fExpectedData));
auto mesh2 = testForType<int16_t>();
QCOMPARE(mesh2.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh2.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh2.getVertices()[uMaterialToCheck].data, static_cast<int16_t>(fExpectedData));
auto mesh3 = testForType<uint16_t>();
QCOMPARE(mesh3.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh3.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh3.getVertices()[uMaterialToCheck].data, static_cast<uint16_t>(fExpectedData));
auto mesh4 = testForType<int32_t>();
QCOMPARE(mesh4.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh4.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh4.getVertices()[uMaterialToCheck].data, static_cast<int32_t>(fExpectedData));
auto mesh5 = testForType<uint32_t>();
QCOMPARE(mesh5.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh5.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh5.getVertices()[uMaterialToCheck].data, static_cast<uint32_t>(fExpectedData));
auto mesh6 = testForType<float>();
QCOMPARE(mesh6.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh6.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh6.getVertices()[uMaterialToCheck].data, static_cast<float>(fExpectedData));
auto mesh7 = testForType<double>();
QCOMPARE(mesh7.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh7.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh7.getVertices()[uMaterialToCheck].data, static_cast<double>(fExpectedData));
auto mesh8 = testForType<Density8>();
QCOMPARE(mesh8.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh8.getNoOfIndices(), uExpectedIndices);
QCOMPARE(mesh8.getVertices()[uMaterialToCheck].data, static_cast<Density8>(fExpectedData));
auto mesh9 = testForType<MaterialDensityPair88>();
QCOMPARE(mesh9.getNoOfVertices(), uExpectedVertices);
QCOMPARE(mesh9.getNoOfIndices(), uExpectedIndices);
//QCOMPARE(mesh9.getVertices()[uMaterialToCheck].data, fExpectedMaterial);
//Test whether the CustomSurfaceExtractor works.
/*testCustomController(floatMesh);
QCOMPARE(floatMesh.getNoOfVertices(), uExpectedVertices);
QCOMPARE(floatMesh.getNoOfIndices(), uExpectedIndices);
QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].data, fExpectedData);*/
// These tests apply the Marching Cubes surface extractor to volumes of various voxel types. In addition we sometimes make use of custom controllers
// and user-provided meshes to make sure these various combinations work as expected.
//
// It is also noted that the number of indices and vertices is varying quite significantly based on the voxel type. This seems unexpected, but could
// be explained if some overflow is occuring when writing data into the volume, causing volumes of different voxel types to have different distributions.
// Of course, the use of a custom controller will also make a significant diference, but this probably does need investigating further in the future.
// This basic test just uses the default controller and automatically generates a mesh of the appropriate type.
auto uintVol = createAndFillVolume<uint8_t>();
auto uintMesh = extractMarchingCubesMesh(uintVol, uintVol->getEnclosingRegion());
QCOMPARE(uintMesh.getNoOfVertices(), uint32_t(12096)); // Verifies size of mesh and that we have 32-bit indices
QCOMPARE(uintMesh.getNoOfIndices(), uint32_t(35157)); // Verifies size of mesh
QCOMPARE(uintMesh.getIndex(100), uint32_t(44)); // Verifies that we have 32-bit indices
QCOMPARE(uintMesh.getVertex(100).data, uint8_t(1)); // Not really meaningful for a primative type
// This test makes use of a custom controller
auto floatVol = createAndFillVolume<float>();
CustomMarchingCubesController floatCustomController;
auto floatMesh = extractMarchingCubesMesh(floatVol, floatVol->getEnclosingRegion(), WrapModes::Border, float(0), floatCustomController);
QCOMPARE(floatMesh.getNoOfVertices(), uint32_t(16113)); // Verifies size of mesh and that we have 32-bit indices
QCOMPARE(floatMesh.getNoOfIndices(), uint32_t(22053)); // Verifies size of mesh
QCOMPARE(floatMesh.getIndex(100), uint32_t(26)); // Verifies that we have 32-bit indices
QCOMPARE(floatMesh.getVertex(100).data, float(1.0f)); // Not really meaningful for a primative type
// This test makes use of a user provided mesh. It uses the default controller, but we have to explicitly provide this because C++ won't let us
// use a default for the second-to-last parameter but noot use a default for the last parameter.
auto intVol = createAndFillVolume<int8_t>();
Mesh< MarchingCubesVertex< int8_t >, uint16_t > intMesh;
extractMarchingCubesMesh(intVol, intVol->getEnclosingRegion(), WrapModes::Border, int8_t(0), DefaultMarchingCubesController<int8_t>(), &intMesh);
QCOMPARE(intMesh.getNoOfVertices(), uint16_t(11718)); // Verifies size of mesh and that we have 16-bit indices
QCOMPARE(intMesh.getNoOfIndices(), uint32_t(34041)); // Verifies size of mesh
QCOMPARE(intMesh.getIndex(100), uint16_t(29)); // Verifies that we have 16-bit indices
QCOMPARE(intMesh.getVertex(100).data, int8_t(1)); // Not really meaningful for a primative type
// This test makes use of a user-provided mesh and also a custom controller.
auto doubleVol = createAndFillVolume<double>();
CustomMarchingCubesController doubleCustomController;
Mesh< MarchingCubesVertex< double >, uint16_t > doubleMesh;
@ -279,13 +166,15 @@ void TestSurfaceExtractor::testExecute()
QCOMPARE(doubleMesh.getNoOfVertices(), uint16_t(16113)); // Verifies size of mesh and that we have 32-bit indices
QCOMPARE(doubleMesh.getNoOfIndices(), uint32_t(22053)); // Verifies size of mesh
QCOMPARE(doubleMesh.getIndex(100), uint16_t(26)); // Verifies that we have 32-bit indices
QCOMPARE(doubleMesh.getVertex(100).data, double(1.0f)); // Not really meaningful for a primative type
// This test ensures the extractor works on a non-primitive voxel type.
auto materialVol = createAndFillVolume<MaterialDensityPair88>();
auto materialMesh = extractMarchingCubesMesh(materialVol, materialVol->getEnclosingRegion());
QCOMPARE(materialMesh.getNoOfVertices(), uint32_t(12096)); // Verifies size of mesh and that we have 32-bit indices
QCOMPARE(materialMesh.getNoOfIndices(), uint32_t(35157)); // Verifies size of mesh
QCOMPARE(materialMesh.getIndex(100), uint32_t(44)); // Verifies that we have 32-bit indices
QCOMPARE(materialMesh.getVertex(100).data.getMaterial(), uint16_t(79));
QCOMPARE(materialMesh.getVertex(100).data.getMaterial(), uint16_t(79)); // Verify the data attached to the vertex
}
QTEST_MAIN(TestSurfaceExtractor)