diff --git a/documentation/tutorial1.rst b/documentation/tutorial1.rst index 90cefeef..ddc59ca3 100644 --- a/documentation/tutorial1.rst +++ b/documentation/tutorial1.rst @@ -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::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 `. In our case we simply set it to the largest possible value by calling :polyvox:`MaterialDensityPair44::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 `. In our case we simply set it to the largest possible value by calling :polyvox:`VoxelTypeTraits::MaxDensity ::MaxDensity>`. Extracting the surface ====================== diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 5674948c..7da7d7cd 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -54,7 +54,7 @@ void createSphereInVolume(SimpleVolume& volData, float fR if(fDistToCenter <= fRadius) { //Our new density value - uint8_t uDensity = MaterialDensityPair44::getMaxDensity(); + uint8_t uDensity = VoxelTypeTraits::MaxDensity; //Get the old voxel MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z); diff --git a/examples/OpenGL/Shapes.cpp b/examples/OpenGL/Shapes.cpp index b0ebce02..2f2b84f5 100644 --- a/examples/OpenGL/Shapes.cpp +++ b/examples/OpenGL/Shapes.cpp @@ -29,6 +29,9 @@ using namespace PolyVox; void createSphereInVolume(LargeVolume& volData, float fRadius, uint8_t uValue) { + int maxDen = VoxelTypeTraits::MaxDensity; + int minDen = VoxelTypeTraits::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& 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& volData, float fRa void createCubeInVolume(LargeVolume& volData, Vector3DInt32 lowerCorner, Vector3DInt32 upperCorner, uint8_t uValue) { + int maxDen = VoxelTypeTraits::MaxDensity; + int minDen = VoxelTypeTraits::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& 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)); } } } diff --git a/examples/OpenGL/main.cpp b/examples/OpenGL/main.cpp index 9930082a..238fe113 100644 --- a/examples/OpenGL/main.cpp +++ b/examples/OpenGL/main.cpp @@ -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::MaxDensity); + createCubeInVolume(volData, Vector3DInt32(midPos-10, 1, midPos-10), Vector3DInt32(midPos+10, maxPos-1, midPos+10), VoxelTypeTraits::MaxDensity); + createCubeInVolume(volData, Vector3DInt32(midPos-10, midPos-10 ,1), Vector3DInt32(midPos+10, midPos+10, maxPos-1), VoxelTypeTraits::MaxDensity); //Smooth part of the volume RawVolume tempVolume(PolyVox::Region(0,0,0,128, 128, 128)); diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index 5a171110..c24aff55 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -50,7 +50,7 @@ void createPerlinVolumeSlow(LargeVolume& volData) perlinVal += 1.0f; perlinVal *= 0.5f; - perlinVal *= MaterialDensityPair44::getMaxDensity(); + perlinVal *= VoxelTypeTraits::MaxDensity; MaterialDensityPair44 voxel; @@ -60,12 +60,12 @@ void createPerlinVolumeSlow(LargeVolume& volData) /*if(perlinVal < 0.0f) { voxel.setMaterial(245); - voxel.setDensity(MaterialDensityPair44::getMaxDensity()); + voxel.setDensity(VoxelTypeTraits::MaxDensity); } else { voxel.setMaterial(0); - voxel.setDensity(MaterialDensityPair44::getMinDensity()); + voxel.setDensity(VoxelTypeTraits::MinDensity); }*/ volData.setVoxelAt(x, y, z, voxel); @@ -105,12 +105,12 @@ void createPerlinVolumeSlow(LargeVolume& volData) if(perlinVal < 0.0f) { voxel.setMaterial(245); - voxel.setDensity(MaterialDensityPair44::getMaxDensity()); + voxel.setDensity(VoxelTypeTraits::MaxDensity); } else { voxel.setMaterial(0); - voxel.setDensity(MaterialDensityPair44::getMinDensity()); + voxel.setDensity(VoxelTypeTraits::MinDensity); } volData.setVoxelAt(x, y, z, voxel); @@ -143,12 +143,12 @@ void createPerlinTerrain(LargeVolume& volData) if(z < perlinVal) { voxel.setMaterial(245); - voxel.setDensity(MaterialDensityPair44::getMaxDensity()); + voxel.setDensity(VoxelTypeTraits::MaxDensity); } else { voxel.setMaterial(0); - voxel.setDensity(MaterialDensityPair44::getMinDensity()); + voxel.setDensity(VoxelTypeTraits::MinDensity); } volData.setVoxelAt(x, y, z, voxel); @@ -181,7 +181,7 @@ void createSphereInVolume(LargeVolume& volData, Vector3DF if(fDistToCenter <= fRadius) { //Our new density value - uint8_t uDensity = MaterialDensityPair44::getMaxDensity(); + uint8_t uDensity = VoxelTypeTraits::MaxDensity; //Get the old voxel MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z); @@ -219,17 +219,17 @@ void load(const ConstVolumeProxy& volume, const PolyVox:: if((x-xpos)*(x-xpos) + (z-zpos)*(z-zpos) < 200) { // tunnel voxel.setMaterial(0); - voxel.setDensity(MaterialDensityPair44::getMinDensity()); + voxel.setDensity(VoxelTypeTraits::MinDensity); } else { // solid voxel.setMaterial(245); - voxel.setDensity(MaterialDensityPair44::getMaxDensity()); + voxel.setDensity(VoxelTypeTraits::MaxDensity); } } else { voxel.setMaterial(0); - voxel.setDensity(MaterialDensityPair44::getMinDensity()); + voxel.setDensity(VoxelTypeTraits::MinDensity); } volume.setVoxelAt(x, y, z, voxel); diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index f15458da..83bc2949 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -55,7 +55,8 @@ void createSphereInVolume(SimpleVolume& volData, float fRadius) if(fDistToCenter <= fRadius) { //Our new density value - uint8_t uDensity = Density8::getMaxDensity(); + //uint8_t uDensity = Density8::getMaxDensity(); + uint8_t uDensity = VoxelTypeTraits::MaxDensity; //Get the old voxel Density8 voxel = volData.getVoxelAt(x,y,z); diff --git a/library/PolyVoxCore/include/PolyVoxCore/Density.h b/library/PolyVoxCore/include/PolyVoxCore/Density.h index eefdb370..3b749dba 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Density.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Density.h @@ -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::max)(); } - static DensityType getMinDensity() throw() { return (std::numeric_limits::min)(); } + //static DensityType getMaxDensity() throw() { return (std::numeric_limits::max)(); } + //static DensityType getMinDensity() throw() { return (std::numeric_limits::min)(); } static DensityType getThreshold() throw() { return (std::numeric_limits::max)() / 2; } private: @@ -84,6 +84,24 @@ namespace PolyVox }; typedef Density Density8; + typedef Density DensityFloat; + + template + class VoxelTypeTraits< Density > + { + 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__ diff --git a/library/PolyVoxCore/include/PolyVoxCore/Material.h b/library/PolyVoxCore/include/PolyVoxCore/Material.h index 5c331cf5..ec91c9c0 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Material.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Material.h @@ -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: diff --git a/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h b/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h index 45a3433c..5d7ea364 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h @@ -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 MaterialDensityPair44; typedef MaterialDensityPair MaterialDensityPair88; + + template + class VoxelTypeTraits< MaterialDensityPair > + { + public: + const static Type MinDensity = 0; + const static Type MaxDensity = (0x01 << NoOfDensityBits) - 1; + }; } #endif \ No newline at end of file diff --git a/library/PolyVoxCore/include/PolyVoxCore/Voxel.h b/library/PolyVoxCore/include/PolyVoxCore/Voxel.h index d9d70454..22e0e05d 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Voxel.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Voxel.h @@ -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 + class VoxelTypeTraits + { + public: + const static typename Type::DensityType MinDensity = 0; + const static typename Type::DensityType MaxDensity = 0; + }; + } #endif //__PolyVox_Voxel_H__ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index db002c91..506f641e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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) diff --git a/tests/TestVoxels.cpp b/tests/TestVoxels.cpp new file mode 100644 index 00000000..ac5d239c --- /dev/null +++ b/tests/TestVoxels.cpp @@ -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 + +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::MinDensity; + QCOMPARE(iValue, 0); + iValue = VoxelTypeTraits::MaxDensity; + QCOMPARE(iValue, 255); + + fValue = VoxelTypeTraits::MinDensity; + QCOMPARE(fValue, -1000000.0f); + fValue = VoxelTypeTraits::MaxDensity; + QCOMPARE(fValue, 1000000.0f); + + iValue = VoxelTypeTraits::MinDensity; + QCOMPARE(iValue, 0); + iValue = VoxelTypeTraits::MaxDensity; + QCOMPARE(iValue, 0); + + iValue = VoxelTypeTraits::MinDensity; + QCOMPARE(iValue, 0); + iValue = VoxelTypeTraits::MaxDensity; + QCOMPARE(iValue, 15); +} + +QTEST_MAIN(TestVoxels) diff --git a/tests/TestVoxels.h b/tests/TestVoxels.h new file mode 100644 index 00000000..0892b4c7 --- /dev/null +++ b/tests/TestVoxels.h @@ -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 + +class TestVoxels: public QObject +{ + Q_OBJECT + + private slots: + void testTraits(); +}; + +#endif +