From 5dfa7e2562da59c3139d31f0450dd0013063f1a8 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 5 May 2014 20:53:47 +0200 Subject: [PATCH 1/6] The CubicSurfaceExtractor now generates vertices of type PositionMaterialNormal rather than PositionMaterial. The normal property is just a dummy and is not filled in, though conceptually we could put something in there in the future (average normal of surrounding faces?) The point of this change is to move towards having a single vertex class with known properties (including normal). This makes it simpler to write code which uses the vertices because we always know which properties are present. This will probably be useful when working with vertex buffer objects. --- examples/Basic/OpenGLWidget.cpp | 6 +++--- examples/Basic/OpenGLWidget.h | 2 +- examples/Basic/main.cpp | 2 +- .../PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h | 6 +++--- .../include/PolyVoxCore/CubicSurfaceExtractor.inl | 4 ++-- tests/TestCubicSurfaceExtractor.cpp | 2 +- tests/TestVolumeSubclass.cpp | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index 9b662fb2..d3bc72c0 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -14,7 +14,7 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh) { //Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); @@ -27,7 +27,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh); + void setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 9a3dac94..516fb9d4 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -78,7 +78,7 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); //A mesh object to hold the result of surface extraction - SurfaceMesh mesh; + SurfaceMesh mesh; //Create a surface extractor. Comment out one of the following two lines to decide which type gets created. CubicSurfaceExtractor< SimpleVolume > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index a225a3b5..c3149de2 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -113,9 +113,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #else - CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #endif @@ -135,7 +135,7 @@ namespace PolyVox Region m_regSizeInVoxels; //The surface patch we are currently filling. - SurfaceMesh* m_meshCurrent; + SurfaceMesh* m_meshCurrent; //Used to avoid creating duplicate vertices. Array<3, IndexAndMaterial> m_previousSliceVertices; diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 3174c63f..e069cfbe 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -36,7 +36,7 @@ namespace PolyVox const uint32_t CubicSurfaceExtractor::MaxVerticesPerPosition = 8; template - CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) + CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) :m_volData(volData) ,m_regSizeInVoxels(region) ,m_meshCurrent(result) @@ -214,7 +214,7 @@ namespace PolyVox if(rEntry.iIndex == -1) { //No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. - rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(static_cast(uX) - 0.5f, static_cast(uY) - 0.5f, static_cast(uZ) - 0.5f), uMaterialIn)); + rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(static_cast(uX)-0.5f, static_cast(uY)-0.5f, static_cast(uZ)-0.5f), uMaterialIn)); rEntry.uMaterial = uMaterialIn; return rEntry.iIndex; diff --git a/tests/TestCubicSurfaceExtractor.cpp b/tests/TestCubicSurfaceExtractor.cpp index 45919e85..8e184162 100644 --- a/tests/TestCubicSurfaceExtractor.cpp +++ b/tests/TestCubicSurfaceExtractor.cpp @@ -106,7 +106,7 @@ uint32_t testForType(void) { for (int32_t x = 0; x < uVolumeSideLength; x += uRegionSideLength) { - SurfaceMesh result; + SurfaceMesh result; Region regionToExtract(x, y, z, x + uRegionSideLength - 1, y + uRegionSideLength - 1, z + uRegionSideLength - 1); CubicSurfaceExtractor< SimpleVolume > extractor(&volData, regionToExtract, &result); extractor.execute(); diff --git a/tests/TestVolumeSubclass.cpp b/tests/TestVolumeSubclass.cpp index 91a619b4..b9a71b6b 100644 --- a/tests/TestVolumeSubclass.cpp +++ b/tests/TestVolumeSubclass.cpp @@ -184,7 +184,7 @@ void TestVolumeSubclass::testExtractSurface() } } - SurfaceMesh result; + SurfaceMesh result; CubicSurfaceExtractor< VolumeSubclass > cubicSurfaceExtractor(&volumeSubclass, volumeSubclass.getEnclosingRegion(), &result); cubicSurfaceExtractor.execute(); From 12246d163312264988278fa08326ccd16d76ada3 Mon Sep 17 00:00:00 2001 From: David Williams Date: Mon, 5 May 2014 20:58:35 +0200 Subject: [PATCH 2/6] The PositionMaterial class can now be removed as we're not using it. --- .../PolyVoxCore/PolyVoxForwardDeclarations.h | 5 --- .../include/PolyVoxCore/VertexTypes.h | 21 ----------- library/PolyVoxCore/source/VertexTypes.cpp | 35 ------------------- 3 files changed, 61 deletions(-) diff --git a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h index 702e786a..75df4b80 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h +++ b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h @@ -129,11 +129,6 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// template class Pager; - //////////////////////////////////////////////////////////////////////////////// - // PositionMaterial - //////////////////////////////////////////////////////////////////////////////// - class PositionMaterial; - //////////////////////////////////////////////////////////////////////////////// // PositionMaterialNormal //////////////////////////////////////////////////////////////////////////////// diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index 033fad6b..e743ed32 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -33,27 +33,6 @@ freely, subject to the following restrictions: namespace PolyVox { -#ifdef SWIG - class PositionMaterial -#else - class POLYVOX_API PositionMaterial -#endif - { - public: - PositionMaterial(); - PositionMaterial(Vector3DFloat positionToSet, float materialToSet); - - float getMaterial(void) const; - const Vector3DFloat& getPosition(void) const; - - void setMaterial(float materialToSet); - void setPosition(const Vector3DFloat& positionToSet); - public: - //Nicely fits into four floats. - Vector3DFloat position; - float material; - }; - #ifdef SWIG class PositionMaterialNormal #else diff --git a/library/PolyVoxCore/source/VertexTypes.cpp b/library/PolyVoxCore/source/VertexTypes.cpp index db41759e..dd043554 100644 --- a/library/PolyVoxCore/source/VertexTypes.cpp +++ b/library/PolyVoxCore/source/VertexTypes.cpp @@ -72,39 +72,4 @@ namespace PolyVox { position = positionToSet; } - - //////////////////////////////////////////////////////////////////////////////// - // PositionMaterial - //////////////////////////////////////////////////////////////////////////////// - - PositionMaterial::PositionMaterial() - { - } - - PositionMaterial::PositionMaterial(Vector3DFloat positionToSet, float materialToSet) - :position(positionToSet) - ,material(materialToSet) - { - - } - - float PositionMaterial::getMaterial(void) const - { - return material; - } - - const Vector3DFloat& PositionMaterial::getPosition(void) const - { - return position; - } - - void PositionMaterial::setMaterial(float materialToSet) - { - material = materialToSet; - } - - void PositionMaterial::setPosition(const Vector3DFloat& positionToSet) - { - position = positionToSet; - } } From 4c2aea3db10b278f17a66f1ee92d3117af6d8945 Mon Sep 17 00:00:00 2001 From: David Williams Date: Tue, 6 May 2014 22:00:24 +0200 Subject: [PATCH 3/6] Removed CubicSurfaceExtractorWithNornals. Going forward users will be expected to compute flat normals in the fragment shader. --- examples/Paging/OpenGLWidget.cpp | 8 +- examples/Paging/main.cpp | 4 +- library/PolyVoxCore/CMakeLists.txt | 2 - .../CubicSurfaceExtractorWithNormals.h | 70 --------- .../CubicSurfaceExtractorWithNormals.inl | 137 ------------------ 5 files changed, 6 insertions(+), 215 deletions(-) delete mode 100644 library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.h delete mode 100644 library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.inl diff --git a/examples/Paging/OpenGLWidget.cpp b/examples/Paging/OpenGLWidget.cpp index 4347be2f..758bf56e 100644 --- a/examples/Paging/OpenGLWidget.cpp +++ b/examples/Paging/OpenGLWidget.cpp @@ -62,10 +62,10 @@ void OpenGLWidget::initializeGL() glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); - //Anable smooth lighting - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); - glShadeModel(GL_SMOOTH); + //Enable smooth lighting + //glEnable(GL_LIGHTING); + //glEnable(GL_LIGHT0); + //glShadeModel(GL_SMOOTH); //We'll be rendering with index/vertex arrays glEnableClientState(GL_VERTEX_ARRAY); diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index 27236afd..b5df0e20 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -25,7 +25,7 @@ freely, subject to the following restrictions: #include "Perlin.h" #include "PolyVoxCore/MaterialDensityPair.h" -#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.h" +#include "PolyVoxCore/CubicSurfaceExtractor.h" #include "PolyVoxCore/MarchingCubesSurfaceExtractor.h" #include "PolyVoxCore/Pager.h" #include "PolyVoxCore/RLEBlockCompressor.h" @@ -187,7 +187,7 @@ int main(int argc, char *argv[]) //Extract the surface SurfaceMesh mesh; - CubicSurfaceExtractorWithNormals< LargeVolume > surfaceExtractor(&volData, reg, &mesh); + CubicSurfaceExtractor< LargeVolume > surfaceExtractor(&volData, reg, &mesh); //MarchingCubesSurfaceExtractor< LargeVolume > surfaceExtractor(&volData, reg, &mesh); //CubicSurfaceExtractorWithNormals surfaceExtractor(&volData, reg, &mesh); surfaceExtractor.execute(); diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 0d07f2b8..e4289feb 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -48,8 +48,6 @@ SET(CORE_INC_FILES include/PolyVoxCore/CompressedBlock.inl include/PolyVoxCore/CubicSurfaceExtractor.h include/PolyVoxCore/CubicSurfaceExtractor.inl - include/PolyVoxCore/CubicSurfaceExtractorWithNormals.h - include/PolyVoxCore/CubicSurfaceExtractorWithNormals.inl include/PolyVoxCore/DefaultIsQuadNeeded.h include/PolyVoxCore/DefaultMarchingCubesController.h include/PolyVoxCore/Density.h diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.h deleted file mode 100644 index 211734f0..00000000 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.h +++ /dev/null @@ -1,70 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David 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_CubicSurfaceExtractorWithNormals_H__ -#define __PolyVox_CubicSurfaceExtractorWithNormals_H__ - -#include "PolyVoxCore/DefaultIsQuadNeeded.h" - -#include "PolyVoxCore/Array.h" -#include "PolyVoxCore/BaseVolume.h" //For wrap modes... should move these? -#include "PolyVoxCore/SurfaceMesh.h" - -namespace PolyVox -{ - template > - class CubicSurfaceExtractorWithNormals - { - public: - // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template - // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? -#if defined(_MSC_VER) - CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), IsQuadNeeded isQuadNeeded = IsQuadNeeded()); -#else - CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), IsQuadNeeded isQuadNeeded = IsQuadNeeded()); -#endif - - void execute(); - - private: - IsQuadNeeded m_funcIsQuadNeededCallback; - - //The volume data and a sampler to access it. - VolumeType* m_volData; - typename VolumeType::Sampler m_sampVolume; - - //The surface patch we are currently filling. - SurfaceMesh* m_meshCurrent; - - //Information about the region we are currently processing - Region m_regSizeInVoxels; - - //The wrap mode - WrapMode m_eWrapMode; - typename VolumeType::VoxelType m_tBorderValue; - }; -} - -#include "PolyVoxCore/CubicSurfaceExtractorWithNormals.inl" - -#endif diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.inl deleted file mode 100644 index bd8259c5..00000000 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractorWithNormals.inl +++ /dev/null @@ -1,137 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David 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 "PolyVoxCore/Impl/Timer.h" - -namespace PolyVox -{ - template - CubicSurfaceExtractorWithNormals::CubicSurfaceExtractorWithNormals(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, IsQuadNeeded isQuadNeeded) - :m_volData(volData) - ,m_sampVolume(volData) - ,m_meshCurrent(result) - ,m_regSizeInVoxels(region) - ,m_eWrapMode(eWrapMode) - ,m_tBorderValue(tBorderValue) - { - m_funcIsQuadNeededCallback = isQuadNeeded; - } - - template - void CubicSurfaceExtractorWithNormals::execute() - { - Timer timer; - m_meshCurrent->clear(); - - for(int32_t z = m_regSizeInVoxels.getLowerZ(); z < m_regSizeInVoxels.getUpperZ(); z++) - { - for(int32_t y = m_regSizeInVoxels.getLowerY(); y < m_regSizeInVoxels.getUpperY(); y++) - { - for(int32_t x = m_regSizeInVoxels.getLowerX(); x < m_regSizeInVoxels.getUpperX(); x++) - { - // these are always positive anyway - float regX = static_cast(x - m_regSizeInVoxels.getLowerX()); - float regY = static_cast(y - m_regSizeInVoxels.getLowerY()); - float regZ = static_cast(z - m_regSizeInVoxels.getLowerZ()); - - uint32_t material = 0; - - if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(x+1,y,z,m_eWrapMode,m_tBorderValue), material)) - { - uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast(material))); - uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast(material))); - uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast(material))); - uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), static_cast(material))); - - m_meshCurrent->addTriangleCubic(v0,v2,v1); - m_meshCurrent->addTriangleCubic(v1,v2,v3); - } - if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x+1,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), material)) - { - uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast(material))); - uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast(material))); - uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast(material))); - uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), static_cast(material))); - - m_meshCurrent->addTriangleCubic(v0,v1,v2); - m_meshCurrent->addTriangleCubic(v1,v3,v2); - } - - if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(x,y+1,z,m_eWrapMode,m_tBorderValue), material)) - { - uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast(material))); - uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast(material))); - uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast(material))); - uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), static_cast(material))); - - m_meshCurrent->addTriangleCubic(v0,v1,v2); - m_meshCurrent->addTriangleCubic(v1,v3,v2); - } - if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y+1,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), material)) - { - uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast(material))); - uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast(material))); - uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast(material))); - uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), static_cast(material))); - - m_meshCurrent->addTriangleCubic(v0,v2,v1); - m_meshCurrent->addTriangleCubic(v1,v2,v3); - } - - if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(x,y,z+1,m_eWrapMode,m_tBorderValue), material)) - { - uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast(material))); - uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast(material))); - uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast(material))); - uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), static_cast(material))); - - m_meshCurrent->addTriangleCubic(v0,v2,v1); - m_meshCurrent->addTriangleCubic(v1,v2,v3); - } - if(m_funcIsQuadNeededCallback(m_volData->getVoxel(x,y,z+1,m_eWrapMode,m_tBorderValue), m_volData->getVoxel(x,y,z,m_eWrapMode,m_tBorderValue), material)) - { - uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast(material))); - uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast(material))); - uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast(material))); - uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), static_cast(material))); - - m_meshCurrent->addTriangleCubic(v0,v1,v2); - m_meshCurrent->addTriangleCubic(v1,v3,v2); - } - } - } - } - - m_meshCurrent->m_Region = m_regSizeInVoxels; - - m_meshCurrent->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = m_meshCurrent->getNoOfIndices(); - m_meshCurrent->m_vecLodRecords.push_back(lodRecord); - - POLYVOX_LOG_TRACE("Cubic surface extraction took " << timer.elapsedTimeInMilliSeconds() - << "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels() - << "x" << m_regSizeInVoxels.getDepthInVoxels() << ")"); - } -} From b0a8ca8a640ef9491e121be53df71209b3302308 Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 7 May 2014 23:47:18 +0200 Subject: [PATCH 4/6] This commit templatizes the vertex classes on voxel types. This was the main change which was made for Cubiquity and it's very messy at the moment. However, this will improve when we make more use of 'auto' to hide the template madness. --- examples/Basic/OpenGLWidget.cpp | 6 +- examples/Basic/OpenGLWidget.h | 2 +- examples/Basic/main.cpp | 2 +- .../OpenGL/OpenGLImmediateModeSupport.cpp | 10 +- examples/OpenGL/OpenGLImmediateModeSupport.h | 3 +- .../OpenGLVertexBufferObjectSupport.cpp | 12 +- .../OpenGL/OpenGLVertexBufferObjectSupport.h | 4 +- examples/OpenGL/OpenGLWidget.cpp | 4 +- examples/OpenGL/OpenGLWidget.h | 2 +- examples/Paging/OpenGLWidget.cpp | 12 +- examples/Paging/OpenGLWidget.h | 3 +- examples/Paging/main.cpp | 2 +- examples/SmoothLOD/OpenGLWidget.cpp | 20 +- examples/SmoothLOD/OpenGLWidget.h | 4 +- examples/SmoothLOD/main.cpp | 4 +- .../PolyVoxCore/CubicSurfaceExtractor.h | 10 +- .../PolyVoxCore/CubicSurfaceExtractor.inl | 12 +- .../include/PolyVoxCore/DefaultIsQuadNeeded.h | 102 +- .../DefaultMarchingCubesController.h | 6 +- .../MarchingCubesSurfaceExtractor.h | 6 +- .../MarchingCubesSurfaceExtractor.inl | 1256 ++++++++--------- .../include/PolyVoxCore/Material.h | 4 +- .../include/PolyVoxCore/MaterialDensityPair.h | 10 +- .../PolyVoxCore/PolyVoxForwardDeclarations.h | 2 +- .../include/PolyVoxCore/VertexTypes.h | 99 +- library/PolyVoxCore/source/VertexTypes.cpp | 75 - tests/TestCubicSurfaceExtractor.cpp | 2 +- tests/TestSurfaceExtractor.cpp | 104 +- tests/TestVolumeSubclass.cpp | 2 +- 29 files changed, 898 insertions(+), 882 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index d3bc72c0..49c0f5c0 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -14,7 +14,7 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) { //Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); @@ -27,7 +27,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh), vecVertices.data(), GL_STATIC_DRAW); //and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &indexBuffer); @@ -36,7 +36,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) glBindVertexArray(0); diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index fab416e4..133c21eb 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -42,7 +42,7 @@ public: void mousePressEvent(QMouseEvent* event); //Convert a SurfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh); + void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 516fb9d4..9ec7e3a1 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -78,7 +78,7 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); //A mesh object to hold the result of surface extraction - SurfaceMesh mesh; + SurfaceMesh > mesh; //Create a surface extractor. Comment out one of the following two lines to decide which type gets created. CubicSurfaceExtractor< SimpleVolume > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.cpp b/examples/OpenGL/OpenGLImmediateModeSupport.cpp index c891008d..553203f4 100644 --- a/examples/OpenGL/OpenGLImmediateModeSupport.cpp +++ b/examples/OpenGL/OpenGLImmediateModeSupport.cpp @@ -29,9 +29,9 @@ freely, subject to the following restrictions: using namespace PolyVox; using namespace std; -void renderRegionImmediateMode(PolyVox::SurfaceMesh& mesh, unsigned int uLodLevel) +void renderRegionImmediateMode(PolyVox::SurfaceMesh >& mesh, unsigned int uLodLevel) { - const vector& vecVertices = mesh.getVertices(); + const vector >& vecVertices = mesh.getVertices(); const vector& vecIndices = mesh.getIndices(); int beginIndex = mesh.m_vecLodRecords[uLodLevel].beginIndex; @@ -41,7 +41,7 @@ void renderRegionImmediateMode(PolyVox::SurfaceMesh& mes //for(vector::const_iterator iterIndex = vecIndices.begin(); iterIndex != vecIndices.end(); ++iterIndex) for(int index = beginIndex; index < endIndex; ++index) { - const PositionMaterialNormal& vertex = vecVertices[vecIndices[index]]; + const PositionMaterialNormal & vertex = vecVertices[vecIndices[index]]; const Vector3DFloat& v3dVertexPos = vertex.getPosition(); //const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength); const Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast(mesh.m_Region.getLowerCorner()); @@ -49,7 +49,9 @@ void renderRegionImmediateMode(PolyVox::SurfaceMesh& mes - uint8_t material = static_cast(vertex.getMaterial() + 0.5); + //uint8_t material = static_cast(static_cast(vertex.getMaterial()) + 0.5); + uint8_t material = 1; + OpenGLColour colour = convertMaterialIDToColour(material); diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.h b/examples/OpenGL/OpenGLImmediateModeSupport.h index f28baca0..671d53a5 100644 --- a/examples/OpenGL/OpenGLImmediateModeSupport.h +++ b/examples/OpenGL/OpenGLImmediateModeSupport.h @@ -24,10 +24,11 @@ freely, subject to the following restrictions: #ifndef __OpenGLExample_OpenGLImmediateModeSupport_H__ #define __OpenGLExample_OpenGLImmediateModeSupport_H__ +#include "PolyVoxCore/MaterialDensityPair.h" #include "PolyVoxCore/PolyVoxForwardDeclarations.h" #include "glew/glew.h" -void renderRegionImmediateMode(PolyVox::SurfaceMesh& mesh, unsigned int uLodLevel); +void renderRegionImmediateMode(PolyVox::SurfaceMesh >& mesh, unsigned int uLodLevel); #endif //__OpenGLExample_OpenGLImmediateModeSupport_H__ diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp index 8dfb3351..066525a7 100644 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp +++ b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp @@ -24,12 +24,13 @@ freely, subject to the following restrictions: #include "OpenGLSupport.h" #include "OpenGLVertexBufferObjectSupport.h" +#include "PolyVoxCore/MaterialDensityPair.h" #include "PolyVoxCore/SurfaceMesh.h" using namespace PolyVox; using namespace std; -OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh& mesh) +OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh >& mesh) { //Represents our filled in OpenGL vertex and index buffer objects. OpenGLSurfaceMesh result; @@ -38,7 +39,7 @@ OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh& vecVertices = mesh.getVertices(); + const vector >& vecVertices = mesh.getVertices(); const vector& vecIndices = mesh.getIndices(); //If we have any indices... @@ -62,9 +63,9 @@ OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh::const_iterator iterVertex = vecVertices.begin(); iterVertex != vecVertices.end(); ++iterVertex) + for (vector >::const_iterator iterVertex = vecVertices.begin(); iterVertex != vecVertices.end(); ++iterVertex) { - const PositionMaterialNormal& vertex = *iterVertex; + const PositionMaterialNormal & vertex = *iterVertex; const Vector3DFloat& v3dVertexPos = vertex.getPosition(); //const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength); const Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast(mesh.m_Region.getLowerCorner()); @@ -83,7 +84,8 @@ OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh(vertex.getMaterial() + 0.5); + //uint8_t material = static_cast(vertex.getMaterial() + 0.5); + uint8_t material = 1; OpenGLColour colour = convertMaterialIDToColour(material); diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.h b/examples/OpenGL/OpenGLVertexBufferObjectSupport.h index 0bb91f72..73a361f5 100644 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.h +++ b/examples/OpenGL/OpenGLVertexBufferObjectSupport.h @@ -33,10 +33,10 @@ struct OpenGLSurfaceMesh GLulong noOfIndices; GLuint indexBuffer; GLuint vertexBuffer; - const PolyVox::SurfaceMesh* sourceMesh; + const PolyVox::SurfaceMesh >* sourceMesh; }; -OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const PolyVox::SurfaceMesh& mesh); +OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const PolyVox::SurfaceMesh >& mesh); void renderRegionVertexBufferObject(const OpenGLSurfaceMesh& openGLSurfaceMesh, unsigned int uLodLevel); #endif //__OpenGLExample_OpenGLVertexBufferObjectSupport_H__ diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index beebc2eb..c761488b 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -87,7 +87,7 @@ void OpenGLWidget::setVolume(PolyVox::LargeVolume* volDat //Extract the surface for this region //extractSurface(m_volData, 0, PolyVox::Region(regLowerCorner, regUpperCorner), meshCurrent); - std::shared_ptr< SurfaceMesh > mesh(new SurfaceMesh); + std::shared_ptr< SurfaceMesh > > mesh(new SurfaceMesh >); MarchingCubesSurfaceExtractor< LargeVolume > surfaceExtractor(volData, PolyVox::Region(regLowerCorner, regUpperCorner), mesh.get()); surfaceExtractor.execute(); @@ -193,7 +193,7 @@ void OpenGLWidget::paintGL() Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ); if(m_mapSurfaceMeshes.find(v3dRegPos) != m_mapSurfaceMeshes.end()) { - std::shared_ptr< SurfaceMesh > meshCurrent = m_mapSurfaceMeshes[v3dRegPos]; + std::shared_ptr< SurfaceMesh > > meshCurrent = m_mapSurfaceMeshes[v3dRegPos]; unsigned int uLodLevel = 0; //meshCurrent->m_vecLodRecords.size() - 1; if(m_bUseOpenGLVertexBufferObjects) { diff --git a/examples/OpenGL/OpenGLWidget.h b/examples/OpenGL/OpenGLWidget.h index ca475b3a..873a5605 100644 --- a/examples/OpenGL/OpenGLWidget.h +++ b/examples/OpenGL/OpenGLWidget.h @@ -88,7 +88,7 @@ class OpenGLWidget : public QGLWidget //Rather than storing one big mesh, the volume is broken into regions and a mesh is stored for each region std::map m_mapOpenGLSurfaceMeshes; - std::map >, Vector3DUint8Compare> m_mapSurfaceMeshes; + std::map > >, Vector3DUint8Compare> m_mapSurfaceMeshes; unsigned int m_uRegionSideLength; unsigned int m_uVolumeWidthInRegions; diff --git a/examples/Paging/OpenGLWidget.cpp b/examples/Paging/OpenGLWidget.cpp index 758bf56e..734ac02b 100644 --- a/examples/Paging/OpenGLWidget.cpp +++ b/examples/Paging/OpenGLWidget.cpp @@ -15,7 +15,7 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) { if((surfaceMesh.getNoOfIndices() == 0) || (surfaceMesh.getNoOfVertices() == 0)) { @@ -25,7 +25,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& vecIndices = surfaceMesh.getIndices(); - const vector& vecVertices = surfaceMesh.getVertices(); + const vector >& vecVertices = surfaceMesh.getVertices(); //Build an OpenGL index buffer glGenBuffers(1, &indexBuffer); @@ -37,7 +37,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); m_uBeginIndex = 0; m_uEndIndex = vecIndices.size(); @@ -69,7 +69,7 @@ void OpenGLWidget::initializeGL() //We'll be rendering with index/vertex arrays glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); + //glEnableClientState(GL_NORMAL_ARRAY); } void OpenGLWidget::resizeGL(int w, int h) @@ -109,8 +109,8 @@ void OpenGLWidget::paintGL() //Bind the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); - glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); + glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); + //glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0); } diff --git a/examples/Paging/OpenGLWidget.h b/examples/Paging/OpenGLWidget.h index 011b9734..1dcddd21 100644 --- a/examples/Paging/OpenGLWidget.h +++ b/examples/Paging/OpenGLWidget.h @@ -24,6 +24,7 @@ distribution. #ifndef __BasicExample_OpenGLWidget_H__ #define __BasicExample_OpenGLWidget_H__ +#include "PolyVoxCore/MaterialDensityPair.h" #include "PolyVoxCore/SurfaceMesh.h" #include "glew/glew.h" @@ -41,7 +42,7 @@ public: void mousePressEvent(QMouseEvent* event); //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh); + void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index b5df0e20..9a625a6e 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -186,7 +186,7 @@ int main(int argc, char *argv[]) std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl; //Extract the surface - SurfaceMesh mesh; + SurfaceMesh > mesh; CubicSurfaceExtractor< LargeVolume > surfaceExtractor(&volData, reg, &mesh); //MarchingCubesSurfaceExtractor< LargeVolume > surfaceExtractor(&volData, reg, &mesh); //CubicSurfaceExtractorWithNormals surfaceExtractor(&volData, reg, &mesh); diff --git a/examples/SmoothLOD/OpenGLWidget.cpp b/examples/SmoothLOD/OpenGLWidget.cpp index 9b016303..812a287d 100644 --- a/examples/SmoothLOD/OpenGLWidget.cpp +++ b/examples/SmoothLOD/OpenGLWidget.cpp @@ -21,11 +21,11 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) { //Convienient access to the vertices and indices const vector& vecIndices = surfaceMesh.getIndices(); - const vector& vecVertices = surfaceMesh.getVertices(); + const vector >& vecVertices = surfaceMesh.getVertices(); //Build an OpenGL index buffer glGenBuffers(1, &indexBuffer); @@ -37,17 +37,17 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); m_uBeginIndex = 0; m_uEndIndex = vecIndices.size(); } -void OpenGLWidget::setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh >& surfaceMesh) { //Convienient access to the vertices and indices const vector& vecIndices = surfaceMesh.getIndices(); - const vector& vecVertices = surfaceMesh.getVertices(); + const vector >& vecVertices = surfaceMesh.getVertices(); //Build an OpenGL index buffer glGenBuffers(1, &indexBufferLow); @@ -59,7 +59,7 @@ void OpenGLWidget::setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); m_uBeginIndexLow = 0; m_uEndIndexLow = vecIndices.size(); @@ -152,8 +152,8 @@ void OpenGLWidget::paintGL() //Bind the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); - glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); + glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); + glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0); @@ -162,8 +162,8 @@ void OpenGLWidget::paintGL() //Bind the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, vertexBufferLow); - glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); - glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); + glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); + glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); glDrawRangeElements(GL_TRIANGLES, m_uBeginIndexLow, m_uEndIndexLow-1, m_uEndIndexLow - m_uBeginIndexLow, GL_UNSIGNED_INT, 0); diff --git a/examples/SmoothLOD/OpenGLWidget.h b/examples/SmoothLOD/OpenGLWidget.h index 059c369e..e92a812a 100644 --- a/examples/SmoothLOD/OpenGLWidget.h +++ b/examples/SmoothLOD/OpenGLWidget.h @@ -41,8 +41,8 @@ public: void mousePressEvent(QMouseEvent* event); //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh& surfaceMesh); - void setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh& surfaceMesh); + void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); + void setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh >& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index 9b8f6f78..d42dd4a8 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -90,13 +90,13 @@ int main(int argc, char *argv[]) volumeResampler.execute(); //Extract the surface - SurfaceMesh meshLowLOD; + SurfaceMesh > meshLowLOD; MarchingCubesSurfaceExtractor< RawVolume > surfaceExtractor(&volDataLowLOD, volDataLowLOD.getEnclosingRegion(), &meshLowLOD); surfaceExtractor.execute(); meshLowLOD.scaleVertices(/*2.0f*/63.0f / 31.0f); //Extract the surface - SurfaceMesh meshHighLOD; + SurfaceMesh > meshHighLOD; MarchingCubesSurfaceExtractor< SimpleVolume > surfaceExtractorHigh(&volData, PolyVox::Region(Vector3DInt32(30,0,0), Vector3DInt32(63, 63, 63)), &meshHighLOD); surfaceExtractorHigh.execute(); meshHighLOD.translateVertices(Vector3DFloat(30, 0, 0)); diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index c3149de2..6ec45eeb 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -82,7 +82,7 @@ namespace PolyVox struct IndexAndMaterial { int32_t iIndex; - int32_t uMaterial; //Should actually use the material type here, but this is ok for now. + typename VolumeType::VoxelType uMaterial; }; enum FaceNames @@ -113,16 +113,16 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #else - CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #endif void execute(); private: - int32_t addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, uint32_t uMaterial, Array<3, IndexAndMaterial>& existingVertices); + int32_t addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterial, Array<3, IndexAndMaterial>& existingVertices); bool performQuadMerging(std::list& quads); bool mergeQuads(Quad& q1, Quad& q2); @@ -135,7 +135,7 @@ namespace PolyVox Region m_regSizeInVoxels; //The surface patch we are currently filling. - SurfaceMesh* m_meshCurrent; + SurfaceMesh >* m_meshCurrent; //Used to avoid creating duplicate vertices. Array<3, IndexAndMaterial> m_previousSliceVertices; diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index e069cfbe..03996a6b 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -36,7 +36,7 @@ namespace PolyVox const uint32_t CubicSurfaceExtractor::MaxVerticesPerPosition = 8; template - CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) + CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) :m_volData(volData) ,m_regSizeInVoxels(region) ,m_meshCurrent(result) @@ -88,7 +88,7 @@ namespace PolyVox { uint32_t regX = x - m_regSizeInVoxels.getLowerX(); - uint32_t material; //Filled in by callback + typename VolumeType::VoxelType material; //Filled in by callback typename VolumeType::VoxelType currentVoxel = volumeSampler.getVoxel(); typename VolumeType::VoxelType negXVoxel = volumeSampler.peekVoxel1nx0py0pz(); typename VolumeType::VoxelType negYVoxel = volumeSampler.peekVoxel0px1ny0pz(); @@ -205,7 +205,7 @@ namespace PolyVox } template - int32_t CubicSurfaceExtractor::addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, uint32_t uMaterialIn, Array<3, IndexAndMaterial>& existingVertices) + int32_t CubicSurfaceExtractor::addVertex(uint32_t uX, uint32_t uY, uint32_t uZ, typename VolumeType::VoxelType uMaterialIn, Array<3, IndexAndMaterial>& existingVertices) { for(uint32_t ct = 0; ct < MaxVerticesPerPosition; ct++) { @@ -214,14 +214,14 @@ namespace PolyVox if(rEntry.iIndex == -1) { //No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. - rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(static_cast(uX)-0.5f, static_cast(uY)-0.5f, static_cast(uZ)-0.5f), uMaterialIn)); + rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(static_cast(uX)-0.5f, static_cast(uY)-0.5f, static_cast(uZ)-0.5f), uMaterialIn)); rEntry.uMaterial = uMaterialIn; return rEntry.iIndex; } //If we have an existing vertex and the material matches then we can return it. - if(rEntry.uMaterial == static_cast(uMaterialIn)) + if(rEntry.uMaterial == uMaterialIn) { return rEntry.iIndex; } @@ -268,7 +268,7 @@ namespace PolyVox { //All four vertices of a given quad have the same material, //so just check that the first pair of vertices match. - if(std::abs(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() - m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial()) < 0.001) + if(m_meshCurrent->getVertices()[q1.vertices[0]].getMaterial() == m_meshCurrent->getVertices()[q2.vertices[0]].getMaterial()) { //Now check whether quad 2 is adjacent to quad one by comparing vertices. //Adjacent quads must share two vertices, and the second quad could be to the diff --git a/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h b/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h index fcaebe7b..c74f9b97 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h +++ b/library/PolyVoxCore/include/PolyVoxCore/DefaultIsQuadNeeded.h @@ -1,52 +1,52 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David 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_DefaultIsQuadNeeded_H__ -#define __PolyVox_DefaultIsQuadNeeded_H__ - -#include "PolyVoxCore/Impl/TypeDef.h" - -#include - -namespace PolyVox -{ - template - class DefaultIsQuadNeeded - { - public: - bool operator()(VoxelType back, VoxelType front, uint32_t& materialToUse) - { - if((back > 0) && (front == 0)) - { - materialToUse = static_cast(back); - return true; - } - else - { - return false; - } - } - }; -} - +/******************************************************************************* +Copyright (c) 2005-2009 David 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_DefaultIsQuadNeeded_H__ +#define __PolyVox_DefaultIsQuadNeeded_H__ + +#include "PolyVoxCore/Impl/TypeDef.h" + +#include + +namespace PolyVox +{ + template + class DefaultIsQuadNeeded + { + public: + bool operator()(VoxelType back, VoxelType front, VoxelType& materialToUse) + { + if((back > 0) && (front == 0)) + { + materialToUse = static_cast(back); + return true; + } + else + { + return false; + } + } + }; +} + #endif //__PolyVox_DefaultIsQuadNeeded_H__ \ No newline at end of file diff --git a/library/PolyVoxCore/include/PolyVoxCore/DefaultMarchingCubesController.h b/library/PolyVoxCore/include/PolyVoxCore/DefaultMarchingCubesController.h index bd7adf5a..6a7aaa22 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/DefaultMarchingCubesController.h +++ b/library/PolyVoxCore/include/PolyVoxCore/DefaultMarchingCubesController.h @@ -64,10 +64,8 @@ namespace PolyVox public: /// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing densities. typedef VoxelType DensityType; - /// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing materials. We're using a float here - /// because this implementation always returns a constant value off 1.0f. PolyVox also uses floats to store the materials in the mesh vertices - /// but this is not really desirable on modern hardware. We'll probably come back to material representation in the future. - typedef float MaterialType; + /// Used to inform the MarchingCubesSurfaceExtractor about which type it should use for representing materials. + typedef VoxelType MaterialType; /** * Constructor diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index 31803437..b5a0b637 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -41,9 +41,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), Controller controller = Controller()); + MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), Controller controller = Controller()); #else - MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), Controller controller = Controller()); + MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), Controller controller = Controller()); #endif void execute(); @@ -193,7 +193,7 @@ namespace PolyVox uint32_t m_uNoOfOccupiedCells; //The surface patch we are currently filling. - SurfaceMesh* m_meshCurrent; + SurfaceMesh >* m_meshCurrent; //Information about the region we are currently processing Region m_regSizeInVoxels; diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 0ddc75f7..e4a58f41 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -1,628 +1,628 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David 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 "PolyVoxCore/Impl/Timer.h" - -namespace PolyVox -{ - template - MarchingCubesSurfaceExtractor::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) - :m_volData(volData) - ,m_sampVolume(volData) - ,m_meshCurrent(result) - ,m_regSizeInVoxels(region) - ,m_controller(controller) - ,m_tThreshold(m_controller.getThreshold()) - { - //m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion()); - m_regSizeInCells = m_regSizeInVoxels; - m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt32(1,1,1)); - - m_sampVolume.setWrapMode(eWrapMode, tBorderValue); - } - - template - void MarchingCubesSurfaceExtractor::execute() - { - Timer timer; - m_meshCurrent->clear(); - - const uint32_t uArrayWidth = m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 1; - const uint32_t uArrayHeight = m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 1; - const uint32_t arraySizes[2]= {uArrayWidth, uArrayHeight}; // Array dimensions - - //For edge indices - Array2DInt32 m_pPreviousVertexIndicesX(arraySizes); - Array2DInt32 m_pPreviousVertexIndicesY(arraySizes); - Array2DInt32 m_pPreviousVertexIndicesZ(arraySizes); - Array2DInt32 m_pCurrentVertexIndicesX(arraySizes); - Array2DInt32 m_pCurrentVertexIndicesY(arraySizes); - Array2DInt32 m_pCurrentVertexIndicesZ(arraySizes); - - Array2DUint8 pPreviousBitmask(arraySizes); - Array2DUint8 pCurrentBitmask(arraySizes); - - //Create a region corresponding to the first slice - m_regSlicePrevious = m_regSizeInVoxels; - Vector3DInt32 v3dUpperCorner = m_regSlicePrevious.getUpperCorner(); - v3dUpperCorner.setZ(m_regSlicePrevious.getLowerZ()); //Set the upper z to the lower z to make it one slice thick. - m_regSlicePrevious.setUpperCorner(v3dUpperCorner); - m_regSliceCurrent = m_regSlicePrevious; - - uint32_t uNoOfNonEmptyCellsForSlice0 = 0; - uint32_t uNoOfNonEmptyCellsForSlice1 = 0; - - //Process the first slice (previous slice not available) - computeBitmaskForSlice(pPreviousBitmask, pCurrentBitmask); - uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells; - - if(uNoOfNonEmptyCellsForSlice1 != 0) - { - memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4); - memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4); - memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4); - generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ); - } - - std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1); - pPreviousBitmask.swap(pCurrentBitmask); - m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX); - m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY); - m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ); - - m_regSlicePrevious = m_regSliceCurrent; - m_regSliceCurrent.shift(Vector3DInt32(0,0,1)); - - //Process the other slices (previous slice is available) - for(int32_t uSlice = 1; uSlice <= m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ(); uSlice++) - { - computeBitmaskForSlice(pPreviousBitmask, pCurrentBitmask); - uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells; - - if(uNoOfNonEmptyCellsForSlice1 != 0) - { - memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4); - memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4); - memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4); - generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ); - } - - if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0)) - { - generateIndicesForSlice(pPreviousBitmask, m_pPreviousVertexIndicesX, m_pPreviousVertexIndicesY, m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY); - } - - std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1); - pPreviousBitmask.swap(pCurrentBitmask); - m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX); - m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY); - m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ); - - m_regSlicePrevious = m_regSliceCurrent; - m_regSliceCurrent.shift(Vector3DInt32(0,0,1)); - } - - m_meshCurrent->m_Region = m_regSizeInVoxels; - - m_meshCurrent->m_vecLodRecords.clear(); - LodRecord lodRecord; - lodRecord.beginIndex = 0; - lodRecord.endIndex = m_meshCurrent->getNoOfIndices(); - m_meshCurrent->m_vecLodRecords.push_back(lodRecord); - - POLYVOX_LOG_TRACE("Marching cubes surface extraction took " << timer.elapsedTimeInMilliSeconds() - << "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels() - << "x" << m_regSizeInVoxels.getDepthInVoxels() << ")"); - } - - template - template - uint32_t MarchingCubesSurfaceExtractor::computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask) - { - m_uNoOfOccupiedCells = 0; - - const int32_t iMaxXVolSpace = m_regSliceCurrent.getUpperX(); - const int32_t iMaxYVolSpace = m_regSliceCurrent.getUpperY(); - - const int32_t iZVolSpace = m_regSliceCurrent.getLowerZ(); - - //Process the lower left corner - int32_t iYVolSpace = m_regSliceCurrent.getLowerY(); - int32_t iXVolSpace = m_regSliceCurrent.getLowerX(); - - uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); - uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); - - - m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); - computeBitmaskForCell(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); - - //Process the edge where x is minimal. - iXVolSpace = m_regSliceCurrent.getLowerX(); - m_sampVolume.setPosition(iXVolSpace, m_regSliceCurrent.getLowerY(), iZVolSpace); - for(iYVolSpace = m_regSliceCurrent.getLowerY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++) - { - uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); - uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); - - m_sampVolume.movePositiveY(); - - computeBitmaskForCell(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); - } - - //Process the edge where y is minimal. - iYVolSpace = m_regSliceCurrent.getLowerY(); - m_sampVolume.setPosition(m_regSliceCurrent.getLowerX(), iYVolSpace, iZVolSpace); - for(iXVolSpace = m_regSliceCurrent.getLowerX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++) - { - uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); - uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); - - m_sampVolume.movePositiveX(); - - computeBitmaskForCell(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); - } - - //Process all remaining elemnents of the slice. In this case, previous x and y values are always available - for(iYVolSpace = m_regSliceCurrent.getLowerY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++) - { - m_sampVolume.setPosition(m_regSliceCurrent.getLowerX(), iYVolSpace, iZVolSpace); - for(iXVolSpace = m_regSliceCurrent.getLowerX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++) - { - uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); - uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); - - m_sampVolume.movePositiveX(); - - computeBitmaskForCell(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); - } - } - - return m_uNoOfOccupiedCells; - } - - template - template - void MarchingCubesSurfaceExtractor::computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask, uint32_t uXRegSpace, uint32_t uYRegSpace) - { - uint8_t iCubeIndex = 0; - - typename VolumeType::VoxelType v000; - typename VolumeType::VoxelType v100; - typename VolumeType::VoxelType v010; - typename VolumeType::VoxelType v110; - typename VolumeType::VoxelType v001; - typename VolumeType::VoxelType v101; - typename VolumeType::VoxelType v011; - typename VolumeType::VoxelType v111; - - if(isPrevZAvail) - { - if(isPrevYAvail) - { - if(isPrevXAvail) - { - v111 = m_sampVolume.peekVoxel1px1py1pz(); - - //z - uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace]; - iPreviousCubeIndexZ >>= 4; - - //y - uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1]; - iPreviousCubeIndexY &= 192; //192 = 128 + 64 - iPreviousCubeIndexY >>= 2; - - //x - uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace]; - iPreviousCubeIndexX &= 128; - iPreviousCubeIndexX >>= 1; - - iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY | iPreviousCubeIndexZ; - - if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; - } - else //previous X not available - { - v011 = m_sampVolume.peekVoxel0px1py1pz(); - v111 = m_sampVolume.peekVoxel1px1py1pz(); - - //z - uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace]; - iPreviousCubeIndexZ >>= 4; - - //y - uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1]; - iPreviousCubeIndexY &= 192; //192 = 128 + 64 - iPreviousCubeIndexY >>= 2; - - iCubeIndex = iPreviousCubeIndexY | iPreviousCubeIndexZ; - - if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64; - if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; - } - } - else //previous Y not available - { - if(isPrevXAvail) - { - v101 = m_sampVolume.peekVoxel1px0py1pz(); - v111 = m_sampVolume.peekVoxel1px1py1pz(); - - //z - uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace]; - iPreviousCubeIndexZ >>= 4; - - //x - uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace]; - iPreviousCubeIndexX &= 160; //160 = 128+32 - iPreviousCubeIndexX >>= 1; - - iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexZ; - - if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32; - if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; - } - else //previous X not available - { - v001 = m_sampVolume.peekVoxel0px0py1pz(); - v101 = m_sampVolume.peekVoxel1px0py1pz(); - v011 = m_sampVolume.peekVoxel0px1py1pz(); - v111 = m_sampVolume.peekVoxel1px1py1pz(); - - //z - uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace]; - iCubeIndex = iPreviousCubeIndexZ >> 4; - - if (m_controller.convertToDensity(v001) < m_tThreshold) iCubeIndex |= 16; - if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32; - if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64; - if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; - } - } - } - else //previous Z not available - { - if(isPrevYAvail) - { - if(isPrevXAvail) - { - v110 = m_sampVolume.peekVoxel1px1py0pz(); - v111 = m_sampVolume.peekVoxel1px1py1pz(); - - //y - uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1]; - iPreviousCubeIndexY &= 204; //204 = 128+64+8+4 - iPreviousCubeIndexY >>= 2; - - //x - uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace]; - iPreviousCubeIndexX &= 170; //170 = 128+32+8+2 - iPreviousCubeIndexX >>= 1; - - iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY; - - if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8; - if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; - } - else //previous X not available - { - v010 = m_sampVolume.peekVoxel0px1py0pz(); - v110 = m_sampVolume.peekVoxel1px1py0pz(); - - v011 = m_sampVolume.peekVoxel0px1py1pz(); - v111 = m_sampVolume.peekVoxel1px1py1pz(); - - //y - uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1]; - iPreviousCubeIndexY &= 204; //204 = 128+64+8+4 - iPreviousCubeIndexY >>= 2; - - iCubeIndex = iPreviousCubeIndexY; - - if (m_controller.convertToDensity(v010) < m_tThreshold) iCubeIndex |= 4; - if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8; - if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64; - if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; - } - } - else //previous Y not available - { - if(isPrevXAvail) - { - v100 = m_sampVolume.peekVoxel1px0py0pz(); - v110 = m_sampVolume.peekVoxel1px1py0pz(); - - v101 = m_sampVolume.peekVoxel1px0py1pz(); - v111 = m_sampVolume.peekVoxel1px1py1pz(); - - //x - uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace]; - iPreviousCubeIndexX &= 170; //170 = 128+32+8+2 - iPreviousCubeIndexX >>= 1; - - iCubeIndex = iPreviousCubeIndexX; - - if (m_controller.convertToDensity(v100) < m_tThreshold) iCubeIndex |= 2; - if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8; - if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32; - if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; - } - else //previous X not available - { - v000 = m_sampVolume.getVoxel(); - v100 = m_sampVolume.peekVoxel1px0py0pz(); - v010 = m_sampVolume.peekVoxel0px1py0pz(); - v110 = m_sampVolume.peekVoxel1px1py0pz(); - - v001 = m_sampVolume.peekVoxel0px0py1pz(); - v101 = m_sampVolume.peekVoxel1px0py1pz(); - v011 = m_sampVolume.peekVoxel0px1py1pz(); - v111 = m_sampVolume.peekVoxel1px1py1pz(); - - if (m_controller.convertToDensity(v000) < m_tThreshold) iCubeIndex |= 1; - if (m_controller.convertToDensity(v100) < m_tThreshold) iCubeIndex |= 2; - if (m_controller.convertToDensity(v010) < m_tThreshold) iCubeIndex |= 4; - if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8; - if (m_controller.convertToDensity(v001) < m_tThreshold) iCubeIndex |= 16; - if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32; - if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64; - if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; - } - } - } - - //Save the bitmask - pCurrentBitmask[uXRegSpace][uYRegSpace] = iCubeIndex; - - if(edgeTable[iCubeIndex] != 0) - { - ++m_uNoOfOccupiedCells; - } - } - - template - void MarchingCubesSurfaceExtractor::generateVerticesForSlice(const Array2DUint8& pCurrentBitmask, - Array2DInt32& m_pCurrentVertexIndicesX, - Array2DInt32& m_pCurrentVertexIndicesY, - Array2DInt32& m_pCurrentVertexIndicesZ) - { - const int32_t iZVolSpace = m_regSliceCurrent.getLowerZ(); - - //Iterate over each cell in the region - for(int32_t iYVolSpace = m_regSliceCurrent.getLowerY(); iYVolSpace <= m_regSliceCurrent.getUpperY(); iYVolSpace++) - { - const uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); - - for(int32_t iXVolSpace = m_regSliceCurrent.getLowerX(); iXVolSpace <= m_regSliceCurrent.getUpperX(); iXVolSpace++) - { - //Current position - const uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - const uint8_t iCubeIndex = pCurrentBitmask[uXRegSpace][uYRegSpace]; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[iCubeIndex] == 0) - { - continue; - } - - //Check whether the generated vertex will lie on the edge of the region - - - m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); - const typename VolumeType::VoxelType v000 = m_sampVolume.getVoxel(); - const Vector3DFloat n000 = computeCentralDifferenceGradient(m_sampVolume); - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[iCubeIndex] & 1) - { - m_sampVolume.movePositiveX(); - const typename VolumeType::VoxelType v100 = m_sampVolume.getVoxel(); - POLYVOX_ASSERT(v000 != v100, "Attempting to insert vertex between two voxels with the same value"); - const Vector3DFloat n100 = computeCentralDifferenceGradient(m_sampVolume); - - const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000)); - - const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()) + fInterp, static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInCells.getLowerZ())); - - Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp)); - - // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so - // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). - if(v3dNormal.lengthSquared() > 0.000001f) - { - v3dNormal.normalise(); - } - - // Allow the controller to decide how the material should be derived from the voxels. - const typename Controller::MaterialType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); - - const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast(uMaterial)); - const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); - m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; - - m_sampVolume.moveNegativeX(); - } - if (edgeTable[iCubeIndex] & 8) - { - m_sampVolume.movePositiveY(); - const typename VolumeType::VoxelType v010 = m_sampVolume.getVoxel(); - POLYVOX_ASSERT(v000 != v010, "Attempting to insert vertex between two voxels with the same value"); - const Vector3DFloat n010 = computeCentralDifferenceGradient(m_sampVolume); - - const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000)); - - const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()) + fInterp, static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ())); - - Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp)); - - // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so - // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). - if(v3dNormal.lengthSquared() > 0.000001f) - { - v3dNormal.normalise(); - } - - // Allow the controller to decide how the material should be derived from the voxels. - const typename Controller::MaterialType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); - - const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast(uMaterial)); - const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); - m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; - - m_sampVolume.moveNegativeY(); - } - if (edgeTable[iCubeIndex] & 256) - { - m_sampVolume.movePositiveZ(); - const typename VolumeType::VoxelType v001 = m_sampVolume.getVoxel(); - POLYVOX_ASSERT(v000 != v001, "Attempting to insert vertex between two voxels with the same value"); - const Vector3DFloat n001 = computeCentralDifferenceGradient(m_sampVolume); - - const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000)); - - const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ()) + fInterp); - - Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp)); - // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so - // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). - if(v3dNormal.lengthSquared() > 0.000001f) - { - v3dNormal.normalise(); - } - - // Allow the controller to decide how the material should be derived from the voxels. - const typename Controller::MaterialType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); - - const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, static_cast(uMaterial)); - const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); - m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; - - m_sampVolume.moveNegativeZ(); - } - }//For each cell - } - } - - template - void MarchingCubesSurfaceExtractor::generateIndicesForSlice(const Array2DUint8& pPreviousBitmask, - const Array2DInt32& m_pPreviousVertexIndicesX, - const Array2DInt32& m_pPreviousVertexIndicesY, - const Array2DInt32& m_pPreviousVertexIndicesZ, - const Array2DInt32& m_pCurrentVertexIndicesX, - const Array2DInt32& m_pCurrentVertexIndicesY) - { - int32_t indlist[12]; - for(int i = 0; i < 12; i++) - { - indlist[i] = -1; - } - - const int32_t iZVolSpace = m_regSlicePrevious.getLowerZ(); - - for(int32_t iYVolSpace = m_regSlicePrevious.getLowerY(); iYVolSpace <= m_regSizeInCells.getUpperY(); iYVolSpace++) - { - for(int32_t iXVolSpace = m_regSlicePrevious.getLowerX(); iXVolSpace <= m_regSizeInCells.getUpperX(); iXVolSpace++) - { - m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); - - //Current position - const uint32_t uXRegSpace = m_sampVolume.getPosition().getX() - m_regSizeInVoxels.getLowerX(); - const uint32_t uYRegSpace = m_sampVolume.getPosition().getY() - m_regSizeInVoxels.getLowerY(); - - //Determine the index into the edge table which tells us which vertices are inside of the surface - const uint8_t iCubeIndex = pPreviousBitmask[uXRegSpace][uYRegSpace]; - - /* Cube is entirely in/out of the surface */ - if (edgeTable[iCubeIndex] == 0) - { - continue; - } - - /* Find the vertices where the surface intersects the cube */ - if (edgeTable[iCubeIndex] & 1) - { - indlist[0] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace]; - } - if (edgeTable[iCubeIndex] & 2) - { - indlist[1] = m_pPreviousVertexIndicesY[uXRegSpace+1][uYRegSpace]; - } - if (edgeTable[iCubeIndex] & 4) - { - indlist[2] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace+1]; - } - if (edgeTable[iCubeIndex] & 8) - { - indlist[3] = m_pPreviousVertexIndicesY[uXRegSpace][uYRegSpace]; - } - if (edgeTable[iCubeIndex] & 16) - { - indlist[4] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace]; - } - if (edgeTable[iCubeIndex] & 32) - { - indlist[5] = m_pCurrentVertexIndicesY[uXRegSpace+1][uYRegSpace]; - } - if (edgeTable[iCubeIndex] & 64) - { - indlist[6] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace+1]; - } - if (edgeTable[iCubeIndex] & 128) - { - indlist[7] = m_pCurrentVertexIndicesY[uXRegSpace][uYRegSpace]; - } - if (edgeTable[iCubeIndex] & 256) - { - indlist[8] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace]; - } - if (edgeTable[iCubeIndex] & 512) - { - indlist[9] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace]; - } - if (edgeTable[iCubeIndex] & 1024) - { - indlist[10] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace+1]; - } - if (edgeTable[iCubeIndex] & 2048) - { - indlist[11] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace+1]; - } - - for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3) - { - const int32_t ind0 = indlist[triTable[iCubeIndex][i ]]; - const int32_t ind1 = indlist[triTable[iCubeIndex][i+1]]; - const int32_t ind2 = indlist[triTable[iCubeIndex][i+2]]; - - if((ind0 != -1) && (ind1 != -1) && (ind2 != -1)) - { - m_meshCurrent->addTriangle(ind0, ind1, ind2); - } - }//For each triangle - }//For each cell - } - } -} +/******************************************************************************* +Copyright (c) 2005-2009 David 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 "PolyVoxCore/Impl/Timer.h" + +namespace PolyVox +{ + template + MarchingCubesSurfaceExtractor::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) + :m_volData(volData) + ,m_sampVolume(volData) + ,m_meshCurrent(result) + ,m_regSizeInVoxels(region) + ,m_controller(controller) + ,m_tThreshold(m_controller.getThreshold()) + { + //m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion()); + m_regSizeInCells = m_regSizeInVoxels; + m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt32(1,1,1)); + + m_sampVolume.setWrapMode(eWrapMode, tBorderValue); + } + + template + void MarchingCubesSurfaceExtractor::execute() + { + Timer timer; + m_meshCurrent->clear(); + + const uint32_t uArrayWidth = m_regSizeInVoxels.getUpperX() - m_regSizeInVoxels.getLowerX() + 1; + const uint32_t uArrayHeight = m_regSizeInVoxels.getUpperY() - m_regSizeInVoxels.getLowerY() + 1; + const uint32_t arraySizes[2]= {uArrayWidth, uArrayHeight}; // Array dimensions + + //For edge indices + Array2DInt32 m_pPreviousVertexIndicesX(arraySizes); + Array2DInt32 m_pPreviousVertexIndicesY(arraySizes); + Array2DInt32 m_pPreviousVertexIndicesZ(arraySizes); + Array2DInt32 m_pCurrentVertexIndicesX(arraySizes); + Array2DInt32 m_pCurrentVertexIndicesY(arraySizes); + Array2DInt32 m_pCurrentVertexIndicesZ(arraySizes); + + Array2DUint8 pPreviousBitmask(arraySizes); + Array2DUint8 pCurrentBitmask(arraySizes); + + //Create a region corresponding to the first slice + m_regSlicePrevious = m_regSizeInVoxels; + Vector3DInt32 v3dUpperCorner = m_regSlicePrevious.getUpperCorner(); + v3dUpperCorner.setZ(m_regSlicePrevious.getLowerZ()); //Set the upper z to the lower z to make it one slice thick. + m_regSlicePrevious.setUpperCorner(v3dUpperCorner); + m_regSliceCurrent = m_regSlicePrevious; + + uint32_t uNoOfNonEmptyCellsForSlice0 = 0; + uint32_t uNoOfNonEmptyCellsForSlice1 = 0; + + //Process the first slice (previous slice not available) + computeBitmaskForSlice(pPreviousBitmask, pCurrentBitmask); + uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells; + + if(uNoOfNonEmptyCellsForSlice1 != 0) + { + memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4); + memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4); + memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4); + generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ); + } + + std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1); + pPreviousBitmask.swap(pCurrentBitmask); + m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX); + m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY); + m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ); + + m_regSlicePrevious = m_regSliceCurrent; + m_regSliceCurrent.shift(Vector3DInt32(0,0,1)); + + //Process the other slices (previous slice is available) + for(int32_t uSlice = 1; uSlice <= m_regSizeInVoxels.getUpperZ() - m_regSizeInVoxels.getLowerZ(); uSlice++) + { + computeBitmaskForSlice(pPreviousBitmask, pCurrentBitmask); + uNoOfNonEmptyCellsForSlice1 = m_uNoOfOccupiedCells; + + if(uNoOfNonEmptyCellsForSlice1 != 0) + { + memset(m_pCurrentVertexIndicesX.getRawData(), 0xff, m_pCurrentVertexIndicesX.getNoOfElements() * 4); + memset(m_pCurrentVertexIndicesY.getRawData(), 0xff, m_pCurrentVertexIndicesY.getNoOfElements() * 4); + memset(m_pCurrentVertexIndicesZ.getRawData(), 0xff, m_pCurrentVertexIndicesZ.getNoOfElements() * 4); + generateVerticesForSlice(pCurrentBitmask, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY, m_pCurrentVertexIndicesZ); + } + + if((uNoOfNonEmptyCellsForSlice0 != 0) || (uNoOfNonEmptyCellsForSlice1 != 0)) + { + generateIndicesForSlice(pPreviousBitmask, m_pPreviousVertexIndicesX, m_pPreviousVertexIndicesY, m_pPreviousVertexIndicesZ, m_pCurrentVertexIndicesX, m_pCurrentVertexIndicesY); + } + + std::swap(uNoOfNonEmptyCellsForSlice0, uNoOfNonEmptyCellsForSlice1); + pPreviousBitmask.swap(pCurrentBitmask); + m_pPreviousVertexIndicesX.swap(m_pCurrentVertexIndicesX); + m_pPreviousVertexIndicesY.swap(m_pCurrentVertexIndicesY); + m_pPreviousVertexIndicesZ.swap(m_pCurrentVertexIndicesZ); + + m_regSlicePrevious = m_regSliceCurrent; + m_regSliceCurrent.shift(Vector3DInt32(0,0,1)); + } + + m_meshCurrent->m_Region = m_regSizeInVoxels; + + m_meshCurrent->m_vecLodRecords.clear(); + LodRecord lodRecord; + lodRecord.beginIndex = 0; + lodRecord.endIndex = m_meshCurrent->getNoOfIndices(); + m_meshCurrent->m_vecLodRecords.push_back(lodRecord); + + POLYVOX_LOG_TRACE("Marching cubes surface extraction took " << timer.elapsedTimeInMilliSeconds() + << "ms (Region size = " << m_regSizeInVoxels.getWidthInVoxels() << "x" << m_regSizeInVoxels.getHeightInVoxels() + << "x" << m_regSizeInVoxels.getDepthInVoxels() << ")"); + } + + template + template + uint32_t MarchingCubesSurfaceExtractor::computeBitmaskForSlice(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask) + { + m_uNoOfOccupiedCells = 0; + + const int32_t iMaxXVolSpace = m_regSliceCurrent.getUpperX(); + const int32_t iMaxYVolSpace = m_regSliceCurrent.getUpperY(); + + const int32_t iZVolSpace = m_regSliceCurrent.getLowerZ(); + + //Process the lower left corner + int32_t iYVolSpace = m_regSliceCurrent.getLowerY(); + int32_t iXVolSpace = m_regSliceCurrent.getLowerX(); + + uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); + uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); + + + m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); + computeBitmaskForCell(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); + + //Process the edge where x is minimal. + iXVolSpace = m_regSliceCurrent.getLowerX(); + m_sampVolume.setPosition(iXVolSpace, m_regSliceCurrent.getLowerY(), iZVolSpace); + for(iYVolSpace = m_regSliceCurrent.getLowerY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++) + { + uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); + uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); + + m_sampVolume.movePositiveY(); + + computeBitmaskForCell(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); + } + + //Process the edge where y is minimal. + iYVolSpace = m_regSliceCurrent.getLowerY(); + m_sampVolume.setPosition(m_regSliceCurrent.getLowerX(), iYVolSpace, iZVolSpace); + for(iXVolSpace = m_regSliceCurrent.getLowerX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++) + { + uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); + uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); + + m_sampVolume.movePositiveX(); + + computeBitmaskForCell(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); + } + + //Process all remaining elemnents of the slice. In this case, previous x and y values are always available + for(iYVolSpace = m_regSliceCurrent.getLowerY() + 1; iYVolSpace <= iMaxYVolSpace; iYVolSpace++) + { + m_sampVolume.setPosition(m_regSliceCurrent.getLowerX(), iYVolSpace, iZVolSpace); + for(iXVolSpace = m_regSliceCurrent.getLowerX() + 1; iXVolSpace <= iMaxXVolSpace; iXVolSpace++) + { + uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); + uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); + + m_sampVolume.movePositiveX(); + + computeBitmaskForCell(pPreviousBitmask, pCurrentBitmask, uXRegSpace, uYRegSpace); + } + } + + return m_uNoOfOccupiedCells; + } + + template + template + void MarchingCubesSurfaceExtractor::computeBitmaskForCell(const Array2DUint8& pPreviousBitmask, Array2DUint8& pCurrentBitmask, uint32_t uXRegSpace, uint32_t uYRegSpace) + { + uint8_t iCubeIndex = 0; + + typename VolumeType::VoxelType v000; + typename VolumeType::VoxelType v100; + typename VolumeType::VoxelType v010; + typename VolumeType::VoxelType v110; + typename VolumeType::VoxelType v001; + typename VolumeType::VoxelType v101; + typename VolumeType::VoxelType v011; + typename VolumeType::VoxelType v111; + + if(isPrevZAvail) + { + if(isPrevYAvail) + { + if(isPrevXAvail) + { + v111 = m_sampVolume.peekVoxel1px1py1pz(); + + //z + uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace]; + iPreviousCubeIndexZ >>= 4; + + //y + uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1]; + iPreviousCubeIndexY &= 192; //192 = 128 + 64 + iPreviousCubeIndexY >>= 2; + + //x + uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace]; + iPreviousCubeIndexX &= 128; + iPreviousCubeIndexX >>= 1; + + iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY | iPreviousCubeIndexZ; + + if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; + } + else //previous X not available + { + v011 = m_sampVolume.peekVoxel0px1py1pz(); + v111 = m_sampVolume.peekVoxel1px1py1pz(); + + //z + uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace]; + iPreviousCubeIndexZ >>= 4; + + //y + uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1]; + iPreviousCubeIndexY &= 192; //192 = 128 + 64 + iPreviousCubeIndexY >>= 2; + + iCubeIndex = iPreviousCubeIndexY | iPreviousCubeIndexZ; + + if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64; + if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; + } + } + else //previous Y not available + { + if(isPrevXAvail) + { + v101 = m_sampVolume.peekVoxel1px0py1pz(); + v111 = m_sampVolume.peekVoxel1px1py1pz(); + + //z + uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace]; + iPreviousCubeIndexZ >>= 4; + + //x + uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace]; + iPreviousCubeIndexX &= 160; //160 = 128+32 + iPreviousCubeIndexX >>= 1; + + iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexZ; + + if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32; + if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; + } + else //previous X not available + { + v001 = m_sampVolume.peekVoxel0px0py1pz(); + v101 = m_sampVolume.peekVoxel1px0py1pz(); + v011 = m_sampVolume.peekVoxel0px1py1pz(); + v111 = m_sampVolume.peekVoxel1px1py1pz(); + + //z + uint8_t iPreviousCubeIndexZ = pPreviousBitmask[uXRegSpace][uYRegSpace]; + iCubeIndex = iPreviousCubeIndexZ >> 4; + + if (m_controller.convertToDensity(v001) < m_tThreshold) iCubeIndex |= 16; + if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32; + if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64; + if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; + } + } + } + else //previous Z not available + { + if(isPrevYAvail) + { + if(isPrevXAvail) + { + v110 = m_sampVolume.peekVoxel1px1py0pz(); + v111 = m_sampVolume.peekVoxel1px1py1pz(); + + //y + uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1]; + iPreviousCubeIndexY &= 204; //204 = 128+64+8+4 + iPreviousCubeIndexY >>= 2; + + //x + uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace]; + iPreviousCubeIndexX &= 170; //170 = 128+32+8+2 + iPreviousCubeIndexX >>= 1; + + iCubeIndex = iPreviousCubeIndexX | iPreviousCubeIndexY; + + if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8; + if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; + } + else //previous X not available + { + v010 = m_sampVolume.peekVoxel0px1py0pz(); + v110 = m_sampVolume.peekVoxel1px1py0pz(); + + v011 = m_sampVolume.peekVoxel0px1py1pz(); + v111 = m_sampVolume.peekVoxel1px1py1pz(); + + //y + uint8_t iPreviousCubeIndexY = pCurrentBitmask[uXRegSpace][uYRegSpace-1]; + iPreviousCubeIndexY &= 204; //204 = 128+64+8+4 + iPreviousCubeIndexY >>= 2; + + iCubeIndex = iPreviousCubeIndexY; + + if (m_controller.convertToDensity(v010) < m_tThreshold) iCubeIndex |= 4; + if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8; + if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64; + if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; + } + } + else //previous Y not available + { + if(isPrevXAvail) + { + v100 = m_sampVolume.peekVoxel1px0py0pz(); + v110 = m_sampVolume.peekVoxel1px1py0pz(); + + v101 = m_sampVolume.peekVoxel1px0py1pz(); + v111 = m_sampVolume.peekVoxel1px1py1pz(); + + //x + uint8_t iPreviousCubeIndexX = pCurrentBitmask[uXRegSpace-1][uYRegSpace]; + iPreviousCubeIndexX &= 170; //170 = 128+32+8+2 + iPreviousCubeIndexX >>= 1; + + iCubeIndex = iPreviousCubeIndexX; + + if (m_controller.convertToDensity(v100) < m_tThreshold) iCubeIndex |= 2; + if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8; + if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32; + if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; + } + else //previous X not available + { + v000 = m_sampVolume.getVoxel(); + v100 = m_sampVolume.peekVoxel1px0py0pz(); + v010 = m_sampVolume.peekVoxel0px1py0pz(); + v110 = m_sampVolume.peekVoxel1px1py0pz(); + + v001 = m_sampVolume.peekVoxel0px0py1pz(); + v101 = m_sampVolume.peekVoxel1px0py1pz(); + v011 = m_sampVolume.peekVoxel0px1py1pz(); + v111 = m_sampVolume.peekVoxel1px1py1pz(); + + if (m_controller.convertToDensity(v000) < m_tThreshold) iCubeIndex |= 1; + if (m_controller.convertToDensity(v100) < m_tThreshold) iCubeIndex |= 2; + if (m_controller.convertToDensity(v010) < m_tThreshold) iCubeIndex |= 4; + if (m_controller.convertToDensity(v110) < m_tThreshold) iCubeIndex |= 8; + if (m_controller.convertToDensity(v001) < m_tThreshold) iCubeIndex |= 16; + if (m_controller.convertToDensity(v101) < m_tThreshold) iCubeIndex |= 32; + if (m_controller.convertToDensity(v011) < m_tThreshold) iCubeIndex |= 64; + if (m_controller.convertToDensity(v111) < m_tThreshold) iCubeIndex |= 128; + } + } + } + + //Save the bitmask + pCurrentBitmask[uXRegSpace][uYRegSpace] = iCubeIndex; + + if(edgeTable[iCubeIndex] != 0) + { + ++m_uNoOfOccupiedCells; + } + } + + template + void MarchingCubesSurfaceExtractor::generateVerticesForSlice(const Array2DUint8& pCurrentBitmask, + Array2DInt32& m_pCurrentVertexIndicesX, + Array2DInt32& m_pCurrentVertexIndicesY, + Array2DInt32& m_pCurrentVertexIndicesZ) + { + const int32_t iZVolSpace = m_regSliceCurrent.getLowerZ(); + + //Iterate over each cell in the region + for(int32_t iYVolSpace = m_regSliceCurrent.getLowerY(); iYVolSpace <= m_regSliceCurrent.getUpperY(); iYVolSpace++) + { + const uint32_t uYRegSpace = iYVolSpace - m_regSizeInVoxels.getLowerY(); + + for(int32_t iXVolSpace = m_regSliceCurrent.getLowerX(); iXVolSpace <= m_regSliceCurrent.getUpperX(); iXVolSpace++) + { + //Current position + const uint32_t uXRegSpace = iXVolSpace - m_regSizeInVoxels.getLowerX(); + + //Determine the index into the edge table which tells us which vertices are inside of the surface + const uint8_t iCubeIndex = pCurrentBitmask[uXRegSpace][uYRegSpace]; + + /* Cube is entirely in/out of the surface */ + if (edgeTable[iCubeIndex] == 0) + { + continue; + } + + //Check whether the generated vertex will lie on the edge of the region + + + m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); + const typename VolumeType::VoxelType v000 = m_sampVolume.getVoxel(); + const Vector3DFloat n000 = computeCentralDifferenceGradient(m_sampVolume); + + /* Find the vertices where the surface intersects the cube */ + if (edgeTable[iCubeIndex] & 1) + { + m_sampVolume.movePositiveX(); + const typename VolumeType::VoxelType v100 = m_sampVolume.getVoxel(); + POLYVOX_ASSERT(v000 != v100, "Attempting to insert vertex between two voxels with the same value"); + const Vector3DFloat n100 = computeCentralDifferenceGradient(m_sampVolume); + + const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000)); + + const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()) + fInterp, static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInCells.getLowerZ())); + + Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp)); + + // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so + // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). + if(v3dNormal.lengthSquared() > 0.000001f) + { + v3dNormal.normalise(); + } + + // Allow the controller to decide how the material should be derived from the voxels. + const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); + + const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial); + const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); + m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; + + m_sampVolume.moveNegativeX(); + } + if (edgeTable[iCubeIndex] & 8) + { + m_sampVolume.movePositiveY(); + const typename VolumeType::VoxelType v010 = m_sampVolume.getVoxel(); + POLYVOX_ASSERT(v000 != v010, "Attempting to insert vertex between two voxels with the same value"); + const Vector3DFloat n010 = computeCentralDifferenceGradient(m_sampVolume); + + const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000)); + + const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()) + fInterp, static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ())); + + Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp)); + + // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so + // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). + if(v3dNormal.lengthSquared() > 0.000001f) + { + v3dNormal.normalise(); + } + + // Allow the controller to decide how the material should be derived from the voxels. + const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); + + PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial); + uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); + m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; + + m_sampVolume.moveNegativeY(); + } + if (edgeTable[iCubeIndex] & 256) + { + m_sampVolume.movePositiveZ(); + const typename VolumeType::VoxelType v001 = m_sampVolume.getVoxel(); + POLYVOX_ASSERT(v000 != v001, "Attempting to insert vertex between two voxels with the same value"); + const Vector3DFloat n001 = computeCentralDifferenceGradient(m_sampVolume); + + const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000)); + + const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ()) + fInterp); + + Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp)); + // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so + // the interpolated normal can also be zero (e.g. a grid of alternating solid and empty voxels). + if(v3dNormal.lengthSquared() > 0.000001f) + { + v3dNormal.normalise(); + } + + // Allow the controller to decide how the material should be derived from the voxels. + const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); + + const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial); + const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); + m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; + + m_sampVolume.moveNegativeZ(); + } + }//For each cell + } + } + + template + void MarchingCubesSurfaceExtractor::generateIndicesForSlice(const Array2DUint8& pPreviousBitmask, + const Array2DInt32& m_pPreviousVertexIndicesX, + const Array2DInt32& m_pPreviousVertexIndicesY, + const Array2DInt32& m_pPreviousVertexIndicesZ, + const Array2DInt32& m_pCurrentVertexIndicesX, + const Array2DInt32& m_pCurrentVertexIndicesY) + { + int32_t indlist[12]; + for(int i = 0; i < 12; i++) + { + indlist[i] = -1; + } + + const int32_t iZVolSpace = m_regSlicePrevious.getLowerZ(); + + for(int32_t iYVolSpace = m_regSlicePrevious.getLowerY(); iYVolSpace <= m_regSizeInCells.getUpperY(); iYVolSpace++) + { + for(int32_t iXVolSpace = m_regSlicePrevious.getLowerX(); iXVolSpace <= m_regSizeInCells.getUpperX(); iXVolSpace++) + { + m_sampVolume.setPosition(iXVolSpace,iYVolSpace,iZVolSpace); + + //Current position + const uint32_t uXRegSpace = m_sampVolume.getPosition().getX() - m_regSizeInVoxels.getLowerX(); + const uint32_t uYRegSpace = m_sampVolume.getPosition().getY() - m_regSizeInVoxels.getLowerY(); + + //Determine the index into the edge table which tells us which vertices are inside of the surface + const uint8_t iCubeIndex = pPreviousBitmask[uXRegSpace][uYRegSpace]; + + /* Cube is entirely in/out of the surface */ + if (edgeTable[iCubeIndex] == 0) + { + continue; + } + + /* Find the vertices where the surface intersects the cube */ + if (edgeTable[iCubeIndex] & 1) + { + indlist[0] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace]; + } + if (edgeTable[iCubeIndex] & 2) + { + indlist[1] = m_pPreviousVertexIndicesY[uXRegSpace+1][uYRegSpace]; + } + if (edgeTable[iCubeIndex] & 4) + { + indlist[2] = m_pPreviousVertexIndicesX[uXRegSpace][uYRegSpace+1]; + } + if (edgeTable[iCubeIndex] & 8) + { + indlist[3] = m_pPreviousVertexIndicesY[uXRegSpace][uYRegSpace]; + } + if (edgeTable[iCubeIndex] & 16) + { + indlist[4] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace]; + } + if (edgeTable[iCubeIndex] & 32) + { + indlist[5] = m_pCurrentVertexIndicesY[uXRegSpace+1][uYRegSpace]; + } + if (edgeTable[iCubeIndex] & 64) + { + indlist[6] = m_pCurrentVertexIndicesX[uXRegSpace][uYRegSpace+1]; + } + if (edgeTable[iCubeIndex] & 128) + { + indlist[7] = m_pCurrentVertexIndicesY[uXRegSpace][uYRegSpace]; + } + if (edgeTable[iCubeIndex] & 256) + { + indlist[8] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace]; + } + if (edgeTable[iCubeIndex] & 512) + { + indlist[9] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace]; + } + if (edgeTable[iCubeIndex] & 1024) + { + indlist[10] = m_pPreviousVertexIndicesZ[uXRegSpace+1][uYRegSpace+1]; + } + if (edgeTable[iCubeIndex] & 2048) + { + indlist[11] = m_pPreviousVertexIndicesZ[uXRegSpace][uYRegSpace+1]; + } + + for (int i=0;triTable[iCubeIndex][i]!=-1;i+=3) + { + const int32_t ind0 = indlist[triTable[iCubeIndex][i ]]; + const int32_t ind1 = indlist[triTable[iCubeIndex][i+1]]; + const int32_t ind2 = indlist[triTable[iCubeIndex][i+2]]; + + if((ind0 != -1) && (ind1 != -1) && (ind2 != -1)) + { + m_meshCurrent->addTriangle(ind0, ind1, ind2); + } + }//For each triangle + }//For each cell + } + } +} diff --git a/library/PolyVoxCore/include/PolyVoxCore/Material.h b/library/PolyVoxCore/include/PolyVoxCore/Material.h index 86bfbc9a..1e4857c3 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/Material.h +++ b/library/PolyVoxCore/include/PolyVoxCore/Material.h @@ -73,11 +73,11 @@ namespace PolyVox class DefaultIsQuadNeeded< Material > { public: - bool operator()(Material back, Material front, uint32_t& materialToUse) + bool operator()(Material back, Material front, Material& materialToUse) { if((back.getMaterial() > 0) && (front.getMaterial() == 0)) { - materialToUse = static_cast(back.getMaterial()); + materialToUse = back; return true; } else diff --git a/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h b/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h index 0e5131fd..f8374d9d 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MaterialDensityPair.h @@ -90,11 +90,11 @@ namespace PolyVox class DefaultIsQuadNeeded< MaterialDensityPair > { public: - bool operator()(MaterialDensityPair back, MaterialDensityPair front, uint32_t& materialToUse) + bool operator()(MaterialDensityPair back, MaterialDensityPair front, MaterialDensityPair& materialToUse) { if((back.getMaterial() > 0) && (front.getMaterial() == 0)) { - materialToUse = static_cast(back.getMaterial()); + materialToUse = back; return true; } else @@ -132,15 +132,15 @@ namespace PolyVox return voxel.getMaterial(); } - MaterialType blendMaterials(MaterialDensityPair a, MaterialDensityPair b, float /*weight*/) + MaterialDensityPair blendMaterials(MaterialDensityPair a, MaterialDensityPair b, float /*weight*/) { if(convertToDensity(a) > convertToDensity(b)) { - return convertToMaterial(a); + return a; } else { - return convertToMaterial(b); + return b; } } diff --git a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h index 75df4b80..9af1a924 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h +++ b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h @@ -132,7 +132,7 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// // PositionMaterialNormal //////////////////////////////////////////////////////////////////////////////// - class PositionMaterialNormal; + template class PositionMaterialNormal; //////////////////////////////////////////////////////////////////////////////// // RawVolume diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index e743ed32..3eb18072 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -33,31 +33,110 @@ freely, subject to the following restrictions: namespace PolyVox { +#ifdef SWIG + class PositionMaterial +#else + template + class POLYVOX_API PositionMaterial +#endif + { + public: + PositionMaterial() + { + } + + PositionMaterial(Vector3DFloat positionToSet, MaterialType materialToSet) + :position(positionToSet) + ,material(materialToSet) + { + } + + MaterialType getMaterial(void) const + { + return material; + } + + const Vector3DFloat& getPosition(void) const + { + return position; + } + + void setMaterial(MaterialType materialToSet) + { + material = materialToSet; + } + + void setPosition(const Vector3DFloat& positionToSet) + { + position = positionToSet; + } + public: + //Nicely fits into four floats. + Vector3DFloat position; + MaterialType material; + }; + #ifdef SWIG class PositionMaterialNormal #else + template class POLYVOX_API PositionMaterialNormal #endif { public: - PositionMaterialNormal(); - PositionMaterialNormal(Vector3DFloat positionToSet, float materialToSet); - PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet); + PositionMaterialNormal() + { + } - float getMaterial(void) const; - const Vector3DFloat& getNormal(void) const; - const Vector3DFloat& getPosition(void) const; + PositionMaterialNormal(Vector3DFloat positionToSet, MaterialType materialToSet) + :position(positionToSet) + ,material(materialToSet) + { + } - void setMaterial(float materialToSet); - void setNormal(const Vector3DFloat& normalToSet); - void setPosition(const Vector3DFloat& positionToSet); + PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, MaterialType materialToSet) + :position(positionToSet) + ,normal(normalToSet) + ,material(materialToSet) + { + } + + MaterialType getMaterial(void) const + { + return material; + } + + const Vector3DFloat& getNormal(void) const + { + return normal; + } + + const Vector3DFloat& getPosition(void) const + { + return position; + } + + void setMaterial(MaterialType materialToSet) + { + material = materialToSet; + } + + void setNormal(const Vector3DFloat& normalToSet) + { + normal = normalToSet; + } + + void setPosition(const Vector3DFloat& positionToSet) + { + position = positionToSet; + } public: //Nicely fits into seven floats, meaning we //can squeeze in one more for material blending. Vector3DFloat position; Vector3DFloat normal; - float material; //FIXME: This shouldn't be float on CPU? + MaterialType material; //FIXME: This shouldn't be float on CPU? }; } diff --git a/library/PolyVoxCore/source/VertexTypes.cpp b/library/PolyVoxCore/source/VertexTypes.cpp index dd043554..e69de29b 100644 --- a/library/PolyVoxCore/source/VertexTypes.cpp +++ b/library/PolyVoxCore/source/VertexTypes.cpp @@ -1,75 +0,0 @@ -/******************************************************************************* -Copyright (c) 2005-2009 David 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 "PolyVoxCore/VertexTypes.h" - -namespace PolyVox -{ - PositionMaterialNormal::PositionMaterialNormal() - { - } - - PositionMaterialNormal::PositionMaterialNormal(Vector3DFloat positionToSet, float materialToSet) - :position(positionToSet) - ,material(materialToSet) - { - - } - - PositionMaterialNormal::PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet) - :position(positionToSet) - ,normal(normalToSet) - ,material(materialToSet) - { - } - - float PositionMaterialNormal::getMaterial(void) const - { - return material; - } - - const Vector3DFloat& PositionMaterialNormal::getNormal(void) const - { - return normal; - } - - const Vector3DFloat& PositionMaterialNormal::getPosition(void) const - { - return position; - } - - void PositionMaterialNormal::setMaterial(float materialToSet) - { - material = materialToSet; - } - - void PositionMaterialNormal::setNormal(const Vector3DFloat& normalToSet) - { - normal = normalToSet; - } - - void PositionMaterialNormal::setPosition(const Vector3DFloat& positionToSet) - { - position = positionToSet; - } -} diff --git a/tests/TestCubicSurfaceExtractor.cpp b/tests/TestCubicSurfaceExtractor.cpp index 8e184162..ba04268a 100644 --- a/tests/TestCubicSurfaceExtractor.cpp +++ b/tests/TestCubicSurfaceExtractor.cpp @@ -106,7 +106,7 @@ uint32_t testForType(void) { for (int32_t x = 0; x < uVolumeSideLength; x += uRegionSideLength) { - SurfaceMesh result; + SurfaceMesh > result; Region regionToExtract(x, y, z, x + uRegionSideLength - 1, y + uRegionSideLength - 1, z + uRegionSideLength - 1); CubicSurfaceExtractor< SimpleVolume > extractor(&volData, regionToExtract, &result); extractor.execute(); diff --git a/tests/TestSurfaceExtractor.cpp b/tests/TestSurfaceExtractor.cpp index 796f3b2c..74030b07 100644 --- a/tests/TestSurfaceExtractor.cpp +++ b/tests/TestSurfaceExtractor.cpp @@ -102,7 +102,7 @@ void writeMaterialValueToVoxel(int valueToWrite, MaterialDensityPair88& voxel) // Runs the surface extractor for a given type. template -void testForType(SurfaceMesh& result) +void testForType(SurfaceMesh >& result) { const int32_t uVolumeSideLength = 32; @@ -131,7 +131,7 @@ void testForType(SurfaceMesh& result) extractor.execute(); } -void testCustomController(SurfaceMesh& result) +void testCustomController(SurfaceMesh >& result) { const int32_t uVolumeSideLength = 32; @@ -163,66 +163,74 @@ void TestSurfaceExtractor::testExecute() const static float fExpectedMaterial = 42.0f; const static float fNoMaterial = 1.0f; - SurfaceMesh mesh; - + SurfaceMesh > int8Mesh; //Run the test for various voxel types. QBENCHMARK { - testForType(mesh); + testForType(int8Mesh); } - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + QCOMPARE(int8Mesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(int8Mesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(int8Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + SurfaceMesh > uint8Mesh; + testForType(uint8Mesh); + QCOMPARE(uint8Mesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(uint8Mesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(uint8Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + SurfaceMesh > int16Mesh; + testForType(int16Mesh); + QCOMPARE(int16Mesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(int16Mesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(int16Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + SurfaceMesh > uint16Mesh; + testForType(uint16Mesh); + QCOMPARE(uint16Mesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(uint16Mesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(uint16Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + SurfaceMesh > int32Mesh; + testForType(int32Mesh); + QCOMPARE(int32Mesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(int32Mesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(int32Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + SurfaceMesh > uint32Mesh; + testForType(uint32Mesh); + QCOMPARE(uint32Mesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(uint32Mesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(uint32Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + SurfaceMesh > floatMesh; + testForType(floatMesh); + QCOMPARE(floatMesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(floatMesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + SurfaceMesh > doubleMesh; + testForType(doubleMesh); + QCOMPARE(doubleMesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(doubleMesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(doubleMesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + SurfaceMesh > densityMesh; + testForType(densityMesh); + QCOMPARE(densityMesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(densityMesh.getNoOfIndices(), uExpectedIndices); + //QCOMPARE(densityMesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - testForType(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fExpectedMaterial); + SurfaceMesh > materialDensityMesh; + testForType(materialDensityMesh); + QCOMPARE(materialDensityMesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(materialDensityMesh.getNoOfIndices(), uExpectedIndices); + //QCOMPARE(materialDensityMesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); //Test whether the CustomSurfaceExtractor works. - testCustomController(mesh); - QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); - QCOMPARE(mesh.getNoOfIndices(), uExpectedIndices); - QCOMPARE(mesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); + testCustomController(floatMesh); + QCOMPARE(floatMesh.getNoOfVertices(), uExpectedVertices); + QCOMPARE(floatMesh.getNoOfIndices(), uExpectedIndices); + QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); } QTEST_MAIN(TestSurfaceExtractor) diff --git a/tests/TestVolumeSubclass.cpp b/tests/TestVolumeSubclass.cpp index b9a71b6b..87b57407 100644 --- a/tests/TestVolumeSubclass.cpp +++ b/tests/TestVolumeSubclass.cpp @@ -184,7 +184,7 @@ void TestVolumeSubclass::testExtractSurface() } } - SurfaceMesh result; + SurfaceMesh > result; CubicSurfaceExtractor< VolumeSubclass > cubicSurfaceExtractor(&volumeSubclass, volumeSubclass.getEnclosingRegion(), &result); cubicSurfaceExtractor.execute(); From ae87dbee7702ac45b6cee0d58c51f62e187f7cff Mon Sep 17 00:00:00 2001 From: David Williams Date: Thu, 8 May 2014 16:40:27 +0200 Subject: [PATCH 5/6] Fixed materials in OpenGL example. --- examples/OpenGL/OpenGLImmediateModeSupport.cpp | 4 ++-- examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.cpp b/examples/OpenGL/OpenGLImmediateModeSupport.cpp index 553203f4..6c25b915 100644 --- a/examples/OpenGL/OpenGLImmediateModeSupport.cpp +++ b/examples/OpenGL/OpenGLImmediateModeSupport.cpp @@ -49,8 +49,8 @@ void renderRegionImmediateMode(PolyVox::SurfaceMesh(static_cast(vertex.getMaterial()) + 0.5); - uint8_t material = 1; + uint8_t material = static_cast(static_cast(vertex.getMaterial().getMaterial()) + 0.5); + //uint8_t material = 1; OpenGLColour colour = convertMaterialIDToColour(material); diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp index 066525a7..7066523a 100644 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp +++ b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp @@ -84,8 +84,8 @@ OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh(vertex.getMaterial() + 0.5); - uint8_t material = 1; + uint8_t material = static_cast(vertex.getMaterial().getMaterial() + 0.5); + //uint8_t material = 1; OpenGLColour colour = convertMaterialIDToColour(material); From 573c36db871f678b6c15bea07495129197dc1f86 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 11 May 2014 15:17:59 +0200 Subject: [PATCH 6/6] Renamed vertex classes to the far more meaningful 'CubicVertex' and 'MarchingCubesVertex'. The old names didn't make much sense, even less so now they are templatized. --- examples/Basic/OpenGLWidget.cpp | 6 +- examples/Basic/OpenGLWidget.h | 2 +- examples/Basic/main.cpp | 2 +- .../OpenGL/OpenGLImmediateModeSupport.cpp | 6 +- examples/OpenGL/OpenGLImmediateModeSupport.h | 2 +- .../OpenGLVertexBufferObjectSupport.cpp | 8 +- .../OpenGL/OpenGLVertexBufferObjectSupport.h | 4 +- examples/OpenGL/OpenGLWidget.cpp | 4 +- examples/OpenGL/OpenGLWidget.h | 2 +- examples/Paging/OpenGLWidget.cpp | 10 +- examples/Paging/OpenGLWidget.h | 2 +- examples/Paging/main.cpp | 2 +- examples/SmoothLOD/OpenGLWidget.cpp | 20 +-- examples/SmoothLOD/OpenGLWidget.h | 4 +- examples/SmoothLOD/main.cpp | 4 +- .../PolyVoxCore/CubicSurfaceExtractor.h | 6 +- .../PolyVoxCore/CubicSurfaceExtractor.inl | 4 +- .../MarchingCubesSurfaceExtractor.h | 6 +- .../MarchingCubesSurfaceExtractor.inl | 8 +- .../PolyVoxCore/PolyVoxForwardDeclarations.h | 15 ++- .../include/PolyVoxCore/VertexTypes.h | 126 ++++++++++-------- tests/TestCubicSurfaceExtractor.cpp | 4 +- tests/TestSurfaceExtractor.cpp | 24 ++-- tests/TestVolumeSubclass.cpp | 2 +- 24 files changed, 147 insertions(+), 126 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index 49c0f5c0..a3f6ad96 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -14,7 +14,7 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) { //Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); @@ -27,7 +27,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh), vecVertices.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), vecVertices.data(), GL_STATIC_DRAW); //and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &indexBuffer); @@ -36,7 +36,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(CubicVertex), 0); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) glBindVertexArray(0); diff --git a/examples/Basic/OpenGLWidget.h b/examples/Basic/OpenGLWidget.h index 133c21eb..a7cac3ca 100644 --- a/examples/Basic/OpenGLWidget.h +++ b/examples/Basic/OpenGLWidget.h @@ -42,7 +42,7 @@ public: void mousePressEvent(QMouseEvent* event); //Convert a SurfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); + void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 9ec7e3a1..c66067df 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -78,7 +78,7 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); //A mesh object to hold the result of surface extraction - SurfaceMesh > mesh; + SurfaceMesh > mesh; //Create a surface extractor. Comment out one of the following two lines to decide which type gets created. CubicSurfaceExtractor< SimpleVolume > surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.cpp b/examples/OpenGL/OpenGLImmediateModeSupport.cpp index 6c25b915..7aff64df 100644 --- a/examples/OpenGL/OpenGLImmediateModeSupport.cpp +++ b/examples/OpenGL/OpenGLImmediateModeSupport.cpp @@ -29,9 +29,9 @@ freely, subject to the following restrictions: using namespace PolyVox; using namespace std; -void renderRegionImmediateMode(PolyVox::SurfaceMesh >& mesh, unsigned int uLodLevel) +void renderRegionImmediateMode(PolyVox::SurfaceMesh >& mesh, unsigned int uLodLevel) { - const vector >& vecVertices = mesh.getVertices(); + const vector >& vecVertices = mesh.getVertices(); const vector& vecIndices = mesh.getIndices(); int beginIndex = mesh.m_vecLodRecords[uLodLevel].beginIndex; @@ -41,7 +41,7 @@ void renderRegionImmediateMode(PolyVox::SurfaceMesh::const_iterator iterIndex = vecIndices.begin(); iterIndex != vecIndices.end(); ++iterIndex) for(int index = beginIndex; index < endIndex; ++index) { - const PositionMaterialNormal & vertex = vecVertices[vecIndices[index]]; + const MarchingCubesVertex & vertex = vecVertices[vecIndices[index]]; const Vector3DFloat& v3dVertexPos = vertex.getPosition(); //const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength); const Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast(mesh.m_Region.getLowerCorner()); diff --git a/examples/OpenGL/OpenGLImmediateModeSupport.h b/examples/OpenGL/OpenGLImmediateModeSupport.h index 671d53a5..9f5aea79 100644 --- a/examples/OpenGL/OpenGLImmediateModeSupport.h +++ b/examples/OpenGL/OpenGLImmediateModeSupport.h @@ -29,6 +29,6 @@ freely, subject to the following restrictions: #include "glew/glew.h" -void renderRegionImmediateMode(PolyVox::SurfaceMesh >& mesh, unsigned int uLodLevel); +void renderRegionImmediateMode(PolyVox::SurfaceMesh >& mesh, unsigned int uLodLevel); #endif //__OpenGLExample_OpenGLImmediateModeSupport_H__ diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp index 7066523a..ae5afd15 100644 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp +++ b/examples/OpenGL/OpenGLVertexBufferObjectSupport.cpp @@ -30,7 +30,7 @@ freely, subject to the following restrictions: using namespace PolyVox; using namespace std; -OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh >& mesh) +OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh >& mesh) { //Represents our filled in OpenGL vertex and index buffer objects. OpenGLSurfaceMesh result; @@ -39,7 +39,7 @@ OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh >& vecVertices = mesh.getVertices(); + const vector >& vecVertices = mesh.getVertices(); const vector& vecIndices = mesh.getIndices(); //If we have any indices... @@ -63,9 +63,9 @@ OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh >::const_iterator iterVertex = vecVertices.begin(); iterVertex != vecVertices.end(); ++iterVertex) + for (vector >::const_iterator iterVertex = vecVertices.begin(); iterVertex != vecVertices.end(); ++iterVertex) { - const PositionMaterialNormal & vertex = *iterVertex; + const MarchingCubesVertex & vertex = *iterVertex; const Vector3DFloat& v3dVertexPos = vertex.getPosition(); //const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength); const Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast(mesh.m_Region.getLowerCorner()); diff --git a/examples/OpenGL/OpenGLVertexBufferObjectSupport.h b/examples/OpenGL/OpenGLVertexBufferObjectSupport.h index 73a361f5..fc97dfb8 100644 --- a/examples/OpenGL/OpenGLVertexBufferObjectSupport.h +++ b/examples/OpenGL/OpenGLVertexBufferObjectSupport.h @@ -33,10 +33,10 @@ struct OpenGLSurfaceMesh GLulong noOfIndices; GLuint indexBuffer; GLuint vertexBuffer; - const PolyVox::SurfaceMesh >* sourceMesh; + const PolyVox::SurfaceMesh >* sourceMesh; }; -OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const PolyVox::SurfaceMesh >& mesh); +OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const PolyVox::SurfaceMesh >& mesh); void renderRegionVertexBufferObject(const OpenGLSurfaceMesh& openGLSurfaceMesh, unsigned int uLodLevel); #endif //__OpenGLExample_OpenGLVertexBufferObjectSupport_H__ diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index c761488b..475ba846 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -87,7 +87,7 @@ void OpenGLWidget::setVolume(PolyVox::LargeVolume* volDat //Extract the surface for this region //extractSurface(m_volData, 0, PolyVox::Region(regLowerCorner, regUpperCorner), meshCurrent); - std::shared_ptr< SurfaceMesh > > mesh(new SurfaceMesh >); + std::shared_ptr< SurfaceMesh > > mesh(new SurfaceMesh >); MarchingCubesSurfaceExtractor< LargeVolume > surfaceExtractor(volData, PolyVox::Region(regLowerCorner, regUpperCorner), mesh.get()); surfaceExtractor.execute(); @@ -193,7 +193,7 @@ void OpenGLWidget::paintGL() Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ); if(m_mapSurfaceMeshes.find(v3dRegPos) != m_mapSurfaceMeshes.end()) { - std::shared_ptr< SurfaceMesh > > meshCurrent = m_mapSurfaceMeshes[v3dRegPos]; + std::shared_ptr< SurfaceMesh > > meshCurrent = m_mapSurfaceMeshes[v3dRegPos]; unsigned int uLodLevel = 0; //meshCurrent->m_vecLodRecords.size() - 1; if(m_bUseOpenGLVertexBufferObjects) { diff --git a/examples/OpenGL/OpenGLWidget.h b/examples/OpenGL/OpenGLWidget.h index 873a5605..1b4b4612 100644 --- a/examples/OpenGL/OpenGLWidget.h +++ b/examples/OpenGL/OpenGLWidget.h @@ -88,7 +88,7 @@ class OpenGLWidget : public QGLWidget //Rather than storing one big mesh, the volume is broken into regions and a mesh is stored for each region std::map m_mapOpenGLSurfaceMeshes; - std::map > >, Vector3DUint8Compare> m_mapSurfaceMeshes; + std::map > >, Vector3DUint8Compare> m_mapSurfaceMeshes; unsigned int m_uRegionSideLength; unsigned int m_uVolumeWidthInRegions; diff --git a/examples/Paging/OpenGLWidget.cpp b/examples/Paging/OpenGLWidget.cpp index 734ac02b..0227a66f 100644 --- a/examples/Paging/OpenGLWidget.cpp +++ b/examples/Paging/OpenGLWidget.cpp @@ -15,7 +15,7 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) { if((surfaceMesh.getNoOfIndices() == 0) || (surfaceMesh.getNoOfVertices() == 0)) { @@ -25,7 +25,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh& vecIndices = surfaceMesh.getIndices(); - const vector >& vecVertices = surfaceMesh.getVertices(); + const vector >& vecVertices = surfaceMesh.getVertices(); //Build an OpenGL index buffer glGenBuffers(1, &indexBuffer); @@ -37,7 +37,7 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(CubicVertex), pVertices, GL_STATIC_DRAW); m_uBeginIndex = 0; m_uEndIndex = vecIndices.size(); @@ -109,8 +109,8 @@ void OpenGLWidget::paintGL() //Bind the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); - //glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); + glVertexPointer(3, GL_FLOAT, sizeof(CubicVertex), 0); + //glNormalPointer(GL_FLOAT, sizeof(CubicVertex), (GLvoid*)12); glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0); } diff --git a/examples/Paging/OpenGLWidget.h b/examples/Paging/OpenGLWidget.h index 1dcddd21..61702be1 100644 --- a/examples/Paging/OpenGLWidget.h +++ b/examples/Paging/OpenGLWidget.h @@ -42,7 +42,7 @@ public: void mousePressEvent(QMouseEvent* event); //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); + void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/Paging/main.cpp b/examples/Paging/main.cpp index 9a625a6e..c1879427 100644 --- a/examples/Paging/main.cpp +++ b/examples/Paging/main.cpp @@ -186,7 +186,7 @@ int main(int argc, char *argv[]) std::cout << "Compression ratio: 1 to " << (1.0/(volData.calculateCompressionRatio())) << std::endl; //Extract the surface - SurfaceMesh > mesh; + SurfaceMesh > mesh; CubicSurfaceExtractor< LargeVolume > surfaceExtractor(&volData, reg, &mesh); //MarchingCubesSurfaceExtractor< LargeVolume > surfaceExtractor(&volData, reg, &mesh); //CubicSurfaceExtractorWithNormals surfaceExtractor(&volData, reg, &mesh); diff --git a/examples/SmoothLOD/OpenGLWidget.cpp b/examples/SmoothLOD/OpenGLWidget.cpp index 812a287d..e804240b 100644 --- a/examples/SmoothLOD/OpenGLWidget.cpp +++ b/examples/SmoothLOD/OpenGLWidget.cpp @@ -21,11 +21,11 @@ OpenGLWidget::OpenGLWidget(QWidget *parent) { } -void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh) { //Convienient access to the vertices and indices const vector& vecIndices = surfaceMesh.getIndices(); - const vector >& vecVertices = surfaceMesh.getVertices(); + const vector >& vecVertices = surfaceMesh.getVertices(); //Build an OpenGL index buffer glGenBuffers(1, &indexBuffer); @@ -37,17 +37,17 @@ void OpenGLWidget::setSurfaceMeshToRender(const PolyVox::SurfaceMesh(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex), pVertices, GL_STATIC_DRAW); m_uBeginIndex = 0; m_uEndIndex = vecIndices.size(); } -void OpenGLWidget::setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh >& surfaceMesh) +void OpenGLWidget::setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh >& surfaceMesh) { //Convienient access to the vertices and indices const vector& vecIndices = surfaceMesh.getIndices(); - const vector >& vecVertices = surfaceMesh.getVertices(); + const vector >& vecVertices = surfaceMesh.getVertices(); //Build an OpenGL index buffer glGenBuffers(1, &indexBufferLow); @@ -59,7 +59,7 @@ void OpenGLWidget::setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh(&(vecVertices[0])); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(PositionMaterialNormal), pVertices, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex), pVertices, GL_STATIC_DRAW); m_uBeginIndexLow = 0; m_uEndIndexLow = vecIndices.size(); @@ -152,8 +152,8 @@ void OpenGLWidget::paintGL() //Bind the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); - glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); - glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); + glVertexPointer(3, GL_FLOAT, sizeof(MarchingCubesVertex), 0); + glNormalPointer(GL_FLOAT, sizeof(MarchingCubesVertex), (GLvoid*)12); glDrawRangeElements(GL_TRIANGLES, m_uBeginIndex, m_uEndIndex-1, m_uEndIndex - m_uBeginIndex, GL_UNSIGNED_INT, 0); @@ -162,8 +162,8 @@ void OpenGLWidget::paintGL() //Bind the vertex buffer glBindBuffer(GL_ARRAY_BUFFER, vertexBufferLow); - glVertexPointer(3, GL_FLOAT, sizeof(PositionMaterialNormal), 0); - glNormalPointer(GL_FLOAT, sizeof(PositionMaterialNormal), (GLvoid*)12); + glVertexPointer(3, GL_FLOAT, sizeof(MarchingCubesVertex), 0); + glNormalPointer(GL_FLOAT, sizeof(MarchingCubesVertex), (GLvoid*)12); glDrawRangeElements(GL_TRIANGLES, m_uBeginIndexLow, m_uEndIndexLow-1, m_uEndIndexLow - m_uBeginIndexLow, GL_UNSIGNED_INT, 0); diff --git a/examples/SmoothLOD/OpenGLWidget.h b/examples/SmoothLOD/OpenGLWidget.h index e92a812a..895e9e74 100644 --- a/examples/SmoothLOD/OpenGLWidget.h +++ b/examples/SmoothLOD/OpenGLWidget.h @@ -41,8 +41,8 @@ public: void mousePressEvent(QMouseEvent* event); //Convert a SrfaceMesh to OpenGL index/vertex buffers - void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); - void setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh >& surfaceMesh); + void setSurfaceMeshToRender(const PolyVox::SurfaceMesh >& surfaceMesh); + void setSurfaceMeshToRenderLowLOD(const PolyVox::SurfaceMesh >& surfaceMesh); protected: //Qt OpenGL functions diff --git a/examples/SmoothLOD/main.cpp b/examples/SmoothLOD/main.cpp index d42dd4a8..29e9cd25 100644 --- a/examples/SmoothLOD/main.cpp +++ b/examples/SmoothLOD/main.cpp @@ -90,13 +90,13 @@ int main(int argc, char *argv[]) volumeResampler.execute(); //Extract the surface - SurfaceMesh > meshLowLOD; + SurfaceMesh > meshLowLOD; MarchingCubesSurfaceExtractor< RawVolume > surfaceExtractor(&volDataLowLOD, volDataLowLOD.getEnclosingRegion(), &meshLowLOD); surfaceExtractor.execute(); meshLowLOD.scaleVertices(/*2.0f*/63.0f / 31.0f); //Extract the surface - SurfaceMesh > meshHighLOD; + SurfaceMesh > meshHighLOD; MarchingCubesSurfaceExtractor< SimpleVolume > surfaceExtractorHigh(&volData, PolyVox::Region(Vector3DInt32(30,0,0), Vector3DInt32(63, 63, 63)), &meshHighLOD); surfaceExtractorHigh.execute(); meshHighLOD.translateVertices(Vector3DFloat(30, 0, 0)); diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h index 6ec45eeb..bb349641 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.h @@ -113,9 +113,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #else - CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); + CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), bool bMergeQuads = true, IsQuadNeeded isQuadNeeded = IsQuadNeeded()); #endif @@ -135,7 +135,7 @@ namespace PolyVox Region m_regSizeInVoxels; //The surface patch we are currently filling. - SurfaceMesh >* m_meshCurrent; + SurfaceMesh >* m_meshCurrent; //Used to avoid creating duplicate vertices. Array<3, IndexAndMaterial> m_previousSliceVertices; diff --git a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl index 03996a6b..822b9256 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/CubicSurfaceExtractor.inl @@ -36,7 +36,7 @@ namespace PolyVox const uint32_t CubicSurfaceExtractor::MaxVerticesPerPosition = 8; template - CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) + CubicSurfaceExtractor::CubicSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, bool bMergeQuads, IsQuadNeeded isQuadNeeded) :m_volData(volData) ,m_regSizeInVoxels(region) ,m_meshCurrent(result) @@ -214,7 +214,7 @@ namespace PolyVox if(rEntry.iIndex == -1) { //No vertices matched and we've now hit an empty space. Fill it by creating a vertex. The 0.5f offset is because vertices set between voxels in order to build cubes around them. - rEntry.iIndex = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(static_cast(uX)-0.5f, static_cast(uY)-0.5f, static_cast(uZ)-0.5f), uMaterialIn)); + rEntry.iIndex = m_meshCurrent->addVertex(CubicVertex(Vector3DFloat(static_cast(uX)-0.5f, static_cast(uY)-0.5f, static_cast(uZ)-0.5f), uMaterialIn)); rEntry.uMaterial = uMaterialIn; return rEntry.iIndex; diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h index b5a0b637..87c7df13 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.h @@ -41,9 +41,9 @@ namespace PolyVox // This is a bit ugly - it seems that the C++03 syntax is different from the C++11 syntax? See this thread: http://stackoverflow.com/questions/6076015/typename-outside-of-template // Long term we should probably come back to this and if the #ifdef is still needed then maybe it should check for C++11 mode instead of MSVC? #if defined(_MSC_VER) - MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), Controller controller = Controller()); + MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = VolumeType::VoxelType(), Controller controller = Controller()); #else - MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), Controller controller = Controller()); + MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode = WrapModes::Border, typename VolumeType::VoxelType tBorderValue = typename VolumeType::VoxelType(), Controller controller = Controller()); #endif void execute(); @@ -193,7 +193,7 @@ namespace PolyVox uint32_t m_uNoOfOccupiedCells; //The surface patch we are currently filling. - SurfaceMesh >* m_meshCurrent; + SurfaceMesh >* m_meshCurrent; //Information about the region we are currently processing Region m_regSizeInVoxels; diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index e4a58f41..535060bb 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -26,7 +26,7 @@ freely, subject to the following restrictions: namespace PolyVox { template - MarchingCubesSurfaceExtractor::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) + MarchingCubesSurfaceExtractor::MarchingCubesSurfaceExtractor(VolumeType* volData, Region region, SurfaceMesh >* result, WrapMode eWrapMode, typename VolumeType::VoxelType tBorderValue, Controller controller) :m_volData(volData) ,m_sampVolume(volData) ,m_meshCurrent(result) @@ -459,7 +459,7 @@ namespace PolyVox // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); - const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial); + const MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesX[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; @@ -488,7 +488,7 @@ namespace PolyVox // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); - PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial); + MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesY[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; @@ -516,7 +516,7 @@ namespace PolyVox // Allow the controller to decide how the material should be derived from the voxels. const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); - const PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial); + const MarchingCubesVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); const uint32_t uLastVertexIndex = m_meshCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesZ[iXVolSpace - m_regSizeInVoxels.getLowerX()][iYVolSpace - m_regSizeInVoxels.getLowerY()] = uLastVertexIndex; diff --git a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h index 9af1a924..0d68b3e9 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h +++ b/library/PolyVoxCore/include/PolyVoxCore/PolyVoxForwardDeclarations.h @@ -78,6 +78,11 @@ namespace PolyVox template class DefaultIsQuadNeeded; template > class CubicSurfaceExtractor; + //////////////////////////////////////////////////////////////////////////////// + // CubicVertex + //////////////////////////////////////////////////////////////////////////////// + template class CubicVertex; + //////////////////////////////////////////////////////////////////////////////// // Density //////////////////////////////////////////////////////////////////////////////// @@ -103,6 +108,11 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// template class LargeVolume; + //////////////////////////////////////////////////////////////////////////////// + // MarchingCubesVertex + //////////////////////////////////////////////////////////////////////////////// + template class MarchingCubesVertex; + //////////////////////////////////////////////////////////////////////////////// // Material //////////////////////////////////////////////////////////////////////////////// @@ -129,11 +139,6 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// template class Pager; - //////////////////////////////////////////////////////////////////////////////// - // PositionMaterialNormal - //////////////////////////////////////////////////////////////////////////////// - template class PositionMaterialNormal; - //////////////////////////////////////////////////////////////////////////////// // RawVolume //////////////////////////////////////////////////////////////////////////////// diff --git a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h index 3eb18072..a5a24d79 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h +++ b/library/PolyVoxCore/include/PolyVoxCore/VertexTypes.h @@ -34,74 +34,31 @@ freely, subject to the following restrictions: namespace PolyVox { #ifdef SWIG - class PositionMaterial + class CubicVertex #else - template - class POLYVOX_API PositionMaterial + template + class POLYVOX_API CubicVertex #endif { public: - PositionMaterial() + CubicVertex() { } - PositionMaterial(Vector3DFloat positionToSet, MaterialType materialToSet) + CubicVertex(Vector3DFloat positionToSet, VoxelType materialToSet) :position(positionToSet) ,material(materialToSet) { } - MaterialType getMaterial(void) const - { - return material; - } - - const Vector3DFloat& getPosition(void) const - { - return position; - } - - void setMaterial(MaterialType materialToSet) - { - material = materialToSet; - } - - void setPosition(const Vector3DFloat& positionToSet) - { - position = positionToSet; - } - public: - //Nicely fits into four floats. - Vector3DFloat position; - MaterialType material; - }; - -#ifdef SWIG - class PositionMaterialNormal -#else - template - class POLYVOX_API PositionMaterialNormal -#endif - { - public: - PositionMaterialNormal() - { - } - - PositionMaterialNormal(Vector3DFloat positionToSet, MaterialType materialToSet) - :position(positionToSet) - ,material(materialToSet) - { - } - - PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, MaterialType materialToSet) + CubicVertex(Vector3DFloat positionToSet, Vector3DFloat normalToSet, VoxelType materialToSet) :position(positionToSet) ,normal(normalToSet) ,material(materialToSet) { } - MaterialType getMaterial(void) const + VoxelType getMaterial(void) const { return material; } @@ -116,7 +73,7 @@ namespace PolyVox return position; } - void setMaterial(MaterialType materialToSet) + void setMaterial(VoxelType materialToSet) { material = materialToSet; } @@ -131,12 +88,71 @@ namespace PolyVox position = positionToSet; } - public: - //Nicely fits into seven floats, meaning we - //can squeeze in one more for material blending. + public: Vector3DFloat position; Vector3DFloat normal; - MaterialType material; //FIXME: This shouldn't be float on CPU? + VoxelType material; + }; + +#ifdef SWIG + class MarchingCubesVertex +#else + template + class POLYVOX_API MarchingCubesVertex +#endif + { + public: + MarchingCubesVertex() + { + } + + MarchingCubesVertex(Vector3DFloat positionToSet, VoxelType materialToSet) + :position(positionToSet) + , material(materialToSet) + { + } + + MarchingCubesVertex(Vector3DFloat positionToSet, Vector3DFloat normalToSet, VoxelType materialToSet) + :position(positionToSet) + , normal(normalToSet) + , material(materialToSet) + { + } + + VoxelType getMaterial(void) const + { + return material; + } + + const Vector3DFloat& getNormal(void) const + { + return normal; + } + + const Vector3DFloat& getPosition(void) const + { + return position; + } + + void setMaterial(VoxelType materialToSet) + { + material = materialToSet; + } + + void setNormal(const Vector3DFloat& normalToSet) + { + normal = normalToSet; + } + + void setPosition(const Vector3DFloat& positionToSet) + { + position = positionToSet; + } + + public: + Vector3DFloat position; + Vector3DFloat normal; + VoxelType material; }; } diff --git a/tests/TestCubicSurfaceExtractor.cpp b/tests/TestCubicSurfaceExtractor.cpp index ba04268a..7dc85571 100644 --- a/tests/TestCubicSurfaceExtractor.cpp +++ b/tests/TestCubicSurfaceExtractor.cpp @@ -106,7 +106,7 @@ uint32_t testForType(void) { for (int32_t x = 0; x < uVolumeSideLength; x += uRegionSideLength) { - SurfaceMesh > result; + SurfaceMesh > result; Region regionToExtract(x, y, z, x + uRegionSideLength - 1, y + uRegionSideLength - 1, z + uRegionSideLength - 1); CubicSurfaceExtractor< SimpleVolume > extractor(&volData, regionToExtract, &result); extractor.execute(); @@ -131,7 +131,7 @@ void TestCubicSurfaceExtractor::testExecute() const static uint32_t uIndexToCheck = 2000; const static uint32_t uExpectedIndex = 1334; - SurfaceMesh mesh;*/ + SurfaceMesh mesh;*/ /*testForType(mesh); QCOMPARE(mesh.getNoOfVertices(), uExpectedVertices); diff --git a/tests/TestSurfaceExtractor.cpp b/tests/TestSurfaceExtractor.cpp index 74030b07..81610212 100644 --- a/tests/TestSurfaceExtractor.cpp +++ b/tests/TestSurfaceExtractor.cpp @@ -102,7 +102,7 @@ void writeMaterialValueToVoxel(int valueToWrite, MaterialDensityPair88& voxel) // Runs the surface extractor for a given type. template -void testForType(SurfaceMesh >& result) +void testForType(SurfaceMesh >& result) { const int32_t uVolumeSideLength = 32; @@ -131,7 +131,7 @@ void testForType(SurfaceMesh >& result) extractor.execute(); } -void testCustomController(SurfaceMesh >& result) +void testCustomController(SurfaceMesh >& result) { const int32_t uVolumeSideLength = 32; @@ -163,7 +163,7 @@ void TestSurfaceExtractor::testExecute() const static float fExpectedMaterial = 42.0f; const static float fNoMaterial = 1.0f; - SurfaceMesh > int8Mesh; + SurfaceMesh > int8Mesh; //Run the test for various voxel types. QBENCHMARK { testForType(int8Mesh); @@ -172,55 +172,55 @@ void TestSurfaceExtractor::testExecute() QCOMPARE(int8Mesh.getNoOfIndices(), uExpectedIndices); QCOMPARE(int8Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - SurfaceMesh > uint8Mesh; + SurfaceMesh > uint8Mesh; testForType(uint8Mesh); QCOMPARE(uint8Mesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(uint8Mesh.getNoOfIndices(), uExpectedIndices); QCOMPARE(uint8Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - SurfaceMesh > int16Mesh; + SurfaceMesh > int16Mesh; testForType(int16Mesh); QCOMPARE(int16Mesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(int16Mesh.getNoOfIndices(), uExpectedIndices); QCOMPARE(int16Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - SurfaceMesh > uint16Mesh; + SurfaceMesh > uint16Mesh; testForType(uint16Mesh); QCOMPARE(uint16Mesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(uint16Mesh.getNoOfIndices(), uExpectedIndices); QCOMPARE(uint16Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - SurfaceMesh > int32Mesh; + SurfaceMesh > int32Mesh; testForType(int32Mesh); QCOMPARE(int32Mesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(int32Mesh.getNoOfIndices(), uExpectedIndices); QCOMPARE(int32Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - SurfaceMesh > uint32Mesh; + SurfaceMesh > uint32Mesh; testForType(uint32Mesh); QCOMPARE(uint32Mesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(uint32Mesh.getNoOfIndices(), uExpectedIndices); QCOMPARE(uint32Mesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - SurfaceMesh > floatMesh; + SurfaceMesh > floatMesh; testForType(floatMesh); QCOMPARE(floatMesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(floatMesh.getNoOfIndices(), uExpectedIndices); QCOMPARE(floatMesh.getVertices()[uMaterialToCheck].getMaterial(), fNoMaterial); - SurfaceMesh > doubleMesh; + SurfaceMesh > doubleMesh; testForType(doubleMesh); QCOMPARE(doubleMesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(doubleMesh.getNoOfIndices(), uExpectedIndices); QCOMPARE(doubleMesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - SurfaceMesh > densityMesh; + SurfaceMesh > densityMesh; testForType(densityMesh); QCOMPARE(densityMesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(densityMesh.getNoOfIndices(), uExpectedIndices); //QCOMPARE(densityMesh.getVertices()[uMaterialToCheck].getMaterial(), static_cast(fNoMaterial)); - SurfaceMesh > materialDensityMesh; + SurfaceMesh > materialDensityMesh; testForType(materialDensityMesh); QCOMPARE(materialDensityMesh.getNoOfVertices(), uExpectedVertices); QCOMPARE(materialDensityMesh.getNoOfIndices(), uExpectedIndices); diff --git a/tests/TestVolumeSubclass.cpp b/tests/TestVolumeSubclass.cpp index 87b57407..98bbe8c4 100644 --- a/tests/TestVolumeSubclass.cpp +++ b/tests/TestVolumeSubclass.cpp @@ -184,7 +184,7 @@ void TestVolumeSubclass::testExtractSurface() } } - SurfaceMesh > result; + SurfaceMesh > result; CubicSurfaceExtractor< VolumeSubclass > cubicSurfaceExtractor(&volumeSubclass, volumeSubclass.getEnclosingRegion(), &result); cubicSurfaceExtractor.execute();