Refactoring of basic voxel types.

This commit is contained in:
p265186
2012-01-12 17:14:45 +01:00
parent 396e1fea30
commit 49b5fb3f67
13 changed files with 176 additions and 28 deletions

View File

@ -60,7 +60,7 @@ Note that this function is part of the BasicExample (rather than being part of t
if(fDistToCenter <= fRadius)
{
//Our new density value
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
uint8_t uDensity = VoxelTypeTraits<MaterialDensityPair44>::MaxDensity;
//Get the old voxel
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
@ -80,7 +80,7 @@ This function takes as input the :polyvox:`SimpleVolume` in which we want to cre
Because this is a simple example function it always places the sphere at the centre of the volume. It computes this centre by halving the dimensions of the volume as given by the functions :polyvox:`SimpleVolume::getWidth`, :polyvox:`SimpleVolume::getHeight` and :polyvox:`SimpleVolume::getDepth`. The resulting position is stored using a :polyvox:`Vector3DFloat`. This is simply a typedef from our templatised :polyvox:`Vector` class, meaning that other sizes and storage types are available if you need them.
Next, the function uses a three-level 'for' loop to iterate over each voxel in the volume. For each voxel it computes the distance from the voxel to the centre of the volume. If this distance is less than or equal to the specified radius then the voxel form part of the sphere and is made solid. During surface extraction, the voxel will be considered solid if it's density is set to any value greater than its threshold, which can be obtained by calling :polyvox:`MaterialDensityPair44::getThreshold <MaterialDensityPair::getThreshold>`. In our case we simply set it to the largest possible value by calling :polyvox:`MaterialDensityPair44::getMaxDensity <MaterialDensityPair::getMaxDensity>`.
Next, the function uses a three-level 'for' loop to iterate over each voxel in the volume. For each voxel it computes the distance from the voxel to the centre of the volume. If this distance is less than or equal to the specified radius then the voxel form part of the sphere and is made solid. During surface extraction, the voxel will be considered solid if it's density is set to any value greater than its threshold, which can be obtained by calling :polyvox:`MaterialDensityPair44::getThreshold <MaterialDensityPair::getThreshold>`. In our case we simply set it to the largest possible value by calling :polyvox:`VoxelTypeTraits<MaterialDensityPair44>::MaxDensity <VoxelTypeTraits<MaterialDensityPair44>::MaxDensity>`.
Extracting the surface
======================

View File

@ -54,7 +54,7 @@ void createSphereInVolume(SimpleVolume<MaterialDensityPair44>& volData, float fR
if(fDistToCenter <= fRadius)
{
//Our new density value
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
uint8_t uDensity = VoxelTypeTraits<MaterialDensityPair44>::MaxDensity;
//Get the old voxel
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);

View File

@ -29,6 +29,9 @@ using namespace PolyVox;
void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, float fRadius, uint8_t uValue)
{
int maxDen = VoxelTypeTraits<MaterialDensityPair44>::MaxDensity;
int minDen = VoxelTypeTraits<MaterialDensityPair44>::MinDensity;
//This vector hold the position of the center of the volume
Vector3DInt32 v3dVolCenter = (volData.getEnclosingRegion().getUpperCorner() - volData.getEnclosingRegion().getLowerCorner()) / 2;
@ -48,7 +51,7 @@ void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, float fRa
//then we make it solid, otherwise we make it empty space.
if(fDistToCenter <= fRadius)
{
volData.setVoxelAt(x,y,z, MaterialDensityPair44(uValue, uValue > 0 ? MaterialDensityPair44::getMaxDensity() : MaterialDensityPair44::getMinDensity()));
volData.setVoxelAt(x,y,z, MaterialDensityPair44(uValue, uValue > 0 ? maxDen : minDen));
}
}
}
@ -57,6 +60,8 @@ void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, float fRa
void createCubeInVolume(LargeVolume<MaterialDensityPair44>& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue)
{
int maxDen = VoxelTypeTraits<MaterialDensityPair44>::MaxDensity;
int minDen = VoxelTypeTraits<MaterialDensityPair44>::MinDensity;
//This three-level for loop iterates over every voxel between the specified corners
for (int z = lowerCorner.getZ(); z <= upperCorner.getZ(); z++)
{
@ -64,7 +69,7 @@ void createCubeInVolume(LargeVolume<MaterialDensityPair44>& volData, Vector3DInt
{
for (int x = lowerCorner.getX() ; x <= upperCorner.getX(); x++)
{
volData.setVoxelAt(x,y,z, MaterialDensityPair44(uValue, uValue > 0 ? MaterialDensityPair44::getMaxDensity() : MaterialDensityPair44::getMinDensity()));
volData.setVoxelAt(x,y,z, MaterialDensityPair44(uValue, uValue > 0 ? maxDen : minDen));
}
}
}

View File

@ -97,9 +97,9 @@ int main(int argc, char *argv[])
createCubeInVolume(volData, Vector3DInt32(midPos+1, minPos, midPos+1), Vector3DInt32(maxPos, midPos-1, maxPos), 0);
createCubeInVolume(volData, Vector3DInt32(minPos, midPos+1, midPos+1), Vector3DInt32(midPos-1, maxPos, maxPos), 0);
createCubeInVolume(volData, Vector3DInt32(1, midPos-10, midPos-10), Vector3DInt32(maxPos-1, midPos+10, midPos+10), MaterialDensityPair44::getMaxDensity());
createCubeInVolume(volData, Vector3DInt32(midPos-10, 1, midPos-10), Vector3DInt32(midPos+10, maxPos-1, midPos+10), MaterialDensityPair44::getMaxDensity());
createCubeInVolume(volData, Vector3DInt32(midPos-10, midPos-10 ,1), Vector3DInt32(midPos+10, midPos+10, maxPos-1), MaterialDensityPair44::getMaxDensity());
createCubeInVolume(volData, Vector3DInt32(1, midPos-10, midPos-10), Vector3DInt32(maxPos-1, midPos+10, midPos+10), VoxelTypeTraits<MaterialDensityPair44>::MaxDensity);
createCubeInVolume(volData, Vector3DInt32(midPos-10, 1, midPos-10), Vector3DInt32(midPos+10, maxPos-1, midPos+10), VoxelTypeTraits<MaterialDensityPair44>::MaxDensity);
createCubeInVolume(volData, Vector3DInt32(midPos-10, midPos-10 ,1), Vector3DInt32(midPos+10, midPos+10, maxPos-1), VoxelTypeTraits<MaterialDensityPair44>::MaxDensity);
//Smooth part of the volume
RawVolume<MaterialDensityPair44> tempVolume(PolyVox::Region(0,0,0,128, 128, 128));

View File

@ -50,7 +50,7 @@ void createPerlinVolumeSlow(LargeVolume<MaterialDensityPair44>& volData)
perlinVal += 1.0f;
perlinVal *= 0.5f;
perlinVal *= MaterialDensityPair44::getMaxDensity();
perlinVal *= VoxelTypeTraits<MaterialDensityPair44>::MaxDensity;
MaterialDensityPair44 voxel;
@ -60,12 +60,12 @@ void createPerlinVolumeSlow(LargeVolume<MaterialDensityPair44>& volData)
/*if(perlinVal < 0.0f)
{
voxel.setMaterial(245);
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MaxDensity);
}
else
{
voxel.setMaterial(0);
voxel.setDensity(MaterialDensityPair44::getMinDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MinDensity);
}*/
volData.setVoxelAt(x, y, z, voxel);
@ -105,12 +105,12 @@ void createPerlinVolumeSlow(LargeVolume<MaterialDensityPair44>& volData)
if(perlinVal < 0.0f)
{
voxel.setMaterial(245);
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MaxDensity);
}
else
{
voxel.setMaterial(0);
voxel.setDensity(MaterialDensityPair44::getMinDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MinDensity);
}
volData.setVoxelAt(x, y, z, voxel);
@ -143,12 +143,12 @@ void createPerlinTerrain(LargeVolume<MaterialDensityPair44>& volData)
if(z < perlinVal)
{
voxel.setMaterial(245);
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MaxDensity);
}
else
{
voxel.setMaterial(0);
voxel.setDensity(MaterialDensityPair44::getMinDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MinDensity);
}
volData.setVoxelAt(x, y, z, voxel);
@ -181,7 +181,7 @@ void createSphereInVolume(LargeVolume<MaterialDensityPair44>& volData, Vector3DF
if(fDistToCenter <= fRadius)
{
//Our new density value
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
uint8_t uDensity = VoxelTypeTraits<MaterialDensityPair44>::MaxDensity;
//Get the old voxel
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
@ -219,17 +219,17 @@ void load(const ConstVolumeProxy<MaterialDensityPair44>& volume, const PolyVox::
if((x-xpos)*(x-xpos) + (z-zpos)*(z-zpos) < 200) {
// tunnel
voxel.setMaterial(0);
voxel.setDensity(MaterialDensityPair44::getMinDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MinDensity);
} else {
// solid
voxel.setMaterial(245);
voxel.setDensity(MaterialDensityPair44::getMaxDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MaxDensity);
}
}
else
{
voxel.setMaterial(0);
voxel.setDensity(MaterialDensityPair44::getMinDensity());
voxel.setDensity(VoxelTypeTraits<MaterialDensityPair44>::MinDensity);
}
volume.setVoxelAt(x, y, z, voxel);

View File

@ -55,7 +55,8 @@ void createSphereInVolume(SimpleVolume<Density8>& volData, float fRadius)
if(fDistToCenter <= fRadius)
{
//Our new density value
uint8_t uDensity = Density8::getMaxDensity();
//uint8_t uDensity = Density8::getMaxDensity();
uint8_t uDensity = VoxelTypeTraits<Density8>::MaxDensity;
//Get the old voxel
Density8 voxel = volData.getVoxelAt(x,y,z);

View File

@ -75,8 +75,8 @@ namespace PolyVox
void setDensity(DensityType uDensity) { m_uDensity = uDensity; }
void setMaterial(MaterialType /*uMaterial*/) { assert(false); } //Cannot set material on voxel of type Density
static DensityType getMaxDensity() throw() { return (std::numeric_limits<DensityType>::max)(); }
static DensityType getMinDensity() throw() { return (std::numeric_limits<DensityType>::min)(); }
//static DensityType getMaxDensity() throw() { return (std::numeric_limits<DensityType>::max)(); }
//static DensityType getMinDensity() throw() { return (std::numeric_limits<DensityType>::min)(); }
static DensityType getThreshold() throw() { return (std::numeric_limits<DensityType>::max)() / 2; }
private:
@ -84,6 +84,24 @@ namespace PolyVox
};
typedef Density<uint8_t> Density8;
typedef Density<float> DensityFloat;
template<typename Type>
class VoxelTypeTraits< Density<Type> >
{
public:
const static Type MinDensity = 0;
const static Type MaxDensity = 255;
};
template<>
class VoxelTypeTraits< DensityFloat >
{
public:
const static float MinDensity = -1000000.0f;
const static float MaxDensity = 1000000.0f;
};
}
#endif //__PolyVox_Density_H__

View File

@ -74,11 +74,13 @@ namespace PolyVox
//We don't actually have a density, so make one up based on the material.
if(m_uMaterial == 0)
{
return getMinDensity();
//return getMinDensity();
return 0;
}
else
{
return getMaxDensity();
//return getMaxDensity();
return 2;
}
}
@ -87,8 +89,8 @@ namespace PolyVox
void setDensity(DensityType /*uDensity*/) { assert(false); } //Cannot set density on voxel of type Material
void setMaterial(MaterialType uMaterial) { m_uMaterial = uMaterial; }
static DensityType getMaxDensity() throw() { return 2; }
static DensityType getMinDensity() throw() { return 0; }
//static DensityType getMaxDensity() throw() { return 2; }
//static DensityType getMinDensity() throw() { return 0; }
static DensityType getThreshold() throw() { return 1; }
private:

View File

@ -74,8 +74,8 @@ namespace PolyVox
void setDensity(DensityType uDensity) { m_uDensity = uDensity; }
void setMaterial(MaterialType uMaterial) { m_uMaterial = uMaterial; }
static DensityType getMaxDensity() throw() { return (0x01 << NoOfDensityBits) - 1; }
static DensityType getMinDensity() throw() { return 0; }
//static DensityType getMaxDensity() throw() { return (0x01 << NoOfDensityBits) - 1; }
//static DensityType getMinDensity() throw() { return 0; }
static DensityType getThreshold() throw() {return 0x01 << (NoOfDensityBits - 1);}
private:
@ -85,6 +85,14 @@ namespace PolyVox
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
typedef MaterialDensityPair<uint16_t, 8, 8> MaterialDensityPair88;
template<typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits>
class VoxelTypeTraits< MaterialDensityPair<Type, NoOfDensityBits, NoOfMaterialBits> >
{
public:
const static Type MinDensity = 0;
const static Type MaxDensity = (0x01 << NoOfDensityBits) - 1;
};
}
#endif

View File

@ -52,6 +52,16 @@ namespace PolyVox
void setDensity(DensityType uDensity) { assert(false); }
void setMaterial(MaterialType /*uMaterial*/) { assert(false); }
};
// Syntax for templatised traits classes: http://stackoverflow.com/q/8606302/849083
template <typename Type>
class VoxelTypeTraits
{
public:
const static typename Type::DensityType MinDensity = 0;
const static typename Type::DensityType MaxDensity = 0;
};
}
#endif //__PolyVox_Voxel_H__

View File

@ -72,3 +72,7 @@ ADD_TEST(VectorEqualityTest ${LATEST_TEST} testEquality)
# Volume subclass tests
CREATE_TEST(TestVolumeSubclass.h TestVolumeSubclass.cpp TestVolumeSubclass)
ADD_TEST(VolumeSubclassExtractSurfaceTest ${LATEST_TEST} testExtractSurface)
# ClassName tests
CREATE_TEST(TestVoxels.h TestVoxels.cpp TestVoxels)
ADD_TEST(VoxelsTraitsTest ${LATEST_TEST} testTraits)

62
tests/TestVoxels.cpp Normal file
View File

@ -0,0 +1,62 @@
/*******************************************************************************
Copyright (c) 2010 Matt Williams
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*******************************************************************************/
#include "TestVoxels.h"
#include "PolyVoxCore/Density.h"
#include "PolyVoxCore/Material.h"
#include "PolyVoxCore/MaterialDensityPair.h"
#include "PolyVoxCore/Vector.h"
#include <QtTest>
using namespace PolyVox;
void TestVoxels::testTraits()
{
int iValue; float fValue; //Used for temporary storage as the QCOMPARE maro struggles with the complex types.
iValue = VoxelTypeTraits<Density8>::MinDensity;
QCOMPARE(iValue, 0);
iValue = VoxelTypeTraits<Density8>::MaxDensity;
QCOMPARE(iValue, 255);
fValue = VoxelTypeTraits<DensityFloat>::MinDensity;
QCOMPARE(fValue, -1000000.0f);
fValue = VoxelTypeTraits<DensityFloat>::MaxDensity;
QCOMPARE(fValue, 1000000.0f);
iValue = VoxelTypeTraits<Material8>::MinDensity;
QCOMPARE(iValue, 0);
iValue = VoxelTypeTraits<Material8>::MaxDensity;
QCOMPARE(iValue, 0);
iValue = VoxelTypeTraits<MaterialDensityPair44>::MinDensity;
QCOMPARE(iValue, 0);
iValue = VoxelTypeTraits<MaterialDensityPair44>::MaxDensity;
QCOMPARE(iValue, 15);
}
QTEST_MAIN(TestVoxels)

38
tests/TestVoxels.h Normal file
View File

@ -0,0 +1,38 @@
/*******************************************************************************
Copyright (c) 2010 Matt Williams
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*******************************************************************************/
#ifndef __PolyVox_TestVoxels_H__
#define __PolyVox_TestVoxels_H__
#include <QObject>
class TestVoxels: public QObject
{
Q_OBJECT
private slots:
void testTraits();
};
#endif