From 68ac0f00563eac1e74b879e319a8510178526644 Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 2 Jan 2011 17:43:41 +0000 Subject: [PATCH] Work on MeshDecimator. --- examples/Basic/OpenGLWidget.cpp | 15 ++- examples/Basic/main.cpp | 104 ++++++++++++++++-- examples/OpenGL/OpenGLWidget.cpp | 4 + library/PolyVoxCore/include/MeshDecimator.h | 8 +- library/PolyVoxCore/include/MeshDecimator.inl | 80 +++++++++++--- 5 files changed, 180 insertions(+), 31 deletions(-) diff --git a/examples/Basic/OpenGLWidget.cpp b/examples/Basic/OpenGLWidget.cpp index 9732bd1b..a1d5f9c9 100644 --- a/examples/Basic/OpenGLWidget.cpp +++ b/examples/Basic/OpenGLWidget.cpp @@ -52,14 +52,19 @@ void OpenGLWidget::initializeGL() glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); - //Anable smooth lighting - glEnable(GL_LIGHTING); - glEnable(GL_LIGHT0); + //Enable smooth lighting + //glEnable(GL_LIGHTING); + //glEnable(GL_LIGHT0); glShadeModel(GL_SMOOTH); //We'll be rendering with index/vertex arrays glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); } void OpenGLWidget::resizeGL(int w, int h) @@ -70,7 +75,7 @@ void OpenGLWidget::resizeGL(int w, int h) //Set up the projection matrix glMatrixMode(GL_PROJECTION); glLoadIdentity(); - float frustumSize = 32.0f; //Half the volume size + float frustumSize = 16.0f; //Half the volume size float aspect = static_cast(width()) / static_cast(height()); glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 1.0, 1000); } @@ -86,7 +91,7 @@ void OpenGLWidget::paintGL() glTranslatef(0.0f,0.0f,-100.0f); //Centre volume and move back glRotatef(m_xRotation, 1.0f, 0.0f, 0.0f); glRotatef(m_yRotation, 0.0f, 1.0f, 0.0f); - glTranslatef(-32.0f,-32.0f,-32.0f); //Centre volume and move back + glTranslatef(-16.0f,-16.0f,-16.0f); //Centre volume and move back //Bind the index buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 51dd24e4..6491d743 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -24,10 +24,13 @@ freely, subject to the following restrictions: #include "OpenGLWidget.h" #include "MaterialDensityPair.h" +#include "CubicSurfaceExtractor.h" #include "CubicSurfaceExtractorWithNormals.h" #include "SurfaceMesh.h" #include "Volume.h" +#include "MeshDecimator.h" + #include //Use the PolyVox namespace @@ -36,7 +39,9 @@ using namespace PolyVox; void createSphereInVolume(Volume& volData, float fRadius) { //This vector hold the position of the center of the volume - Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2); + //Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2); + + Vector3DFloat v3dVolCenter(16, 16, 16); //This three-level for loop iterates over every voxel in the volume for (int z = 0; z < volData.getWidth(); z++) @@ -55,14 +60,16 @@ void createSphereInVolume(Volume& volData, float fRadius) { //Our new density value uint8_t uDensity = MaterialDensityPair44::getMaxDensity(); + uint8_t uMaterial = 3; //Get the old voxel MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z); //Modify the density voxel.setDensity(uDensity); + voxel.setMaterial(uMaterial); - //Wrte the voxel value into the volume + //Write the voxel value into the volume volData.setVoxelAt(x, y, z, voxel); } } @@ -70,6 +77,28 @@ void createSphereInVolume(Volume& volData, float fRadius) } } +void addNormals(const PolyVox::SurfaceMesh& inputMesh, PolyVox::SurfaceMesh& outputMesh) +{ + outputMesh.m_Region = inputMesh.m_Region; + + outputMesh.m_vecTriangleIndices.clear(); + for(int ct = 0; ct < inputMesh.m_vecTriangleIndices.size(); ++ct) + { + outputMesh.m_vecTriangleIndices.push_back(inputMesh.m_vecTriangleIndices[ct]); + } + + outputMesh.m_vecVertices.clear(); + for(int ct = 0; ct < inputMesh.m_vecVertices.size(); ++ct) + { + PositionMaterialNormal vertex; + vertex.position = inputMesh.m_vecVertices[ct].position; + vertex.material = inputMesh.m_vecVertices[ct].material; + outputMesh.m_vecVertices.push_back(vertex); + } + + outputMesh.generateAveragedFaceNormals(true, true); +} + int main(int argc, char *argv[]) { //Create and show the Qt OpenGL window @@ -78,16 +107,77 @@ int main(int argc, char *argv[]) openGLWidget.show(); //Create an empty volume and then place a sphere in it - Volume volData(64, 64, 64); - createSphereInVolume(volData, 30); + Volume volData(32, 32, 32, 32); + //createSphereInVolume(volData, 30); + + //This three-level for loop iterates over every voxel in the volume + /*for (int z = 8; z < 24; z++) + { + for (int y = 8; y < 24; y++) + { + for (int x = 8; x < 16; x++) + { + //Our new density value + uint8_t uDensity = MaterialDensityPair44::getMaxDensity(); + + //Get the old voxel + MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z); + + //Modify the density + voxel.setDensity(uDensity); + voxel.setMaterial(5); + + //Write the voxel value into the volume + volData.setVoxelAt(x, y, z, voxel); + } + } + } + + for (int z = 8; z < 24; z++) + { + for (int y = 8; y < 24; y++) + { + for (int x = 16; x < 24; x++) + { + //Our new density value + uint8_t uDensity = MaterialDensityPair44::getMaxDensity(); + + //Get the old voxel + MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z); + + //Modify the density + voxel.setDensity(uDensity); + voxel.setMaterial(5); + + //Write the voxel value into the volume + volData.setVoxelAt(x, y, z, voxel); + } + } + }*/ + + createSphereInVolume(volData, 10); //Extract the surface - SurfaceMesh mesh; - CubicSurfaceExtractorWithNormals surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); + Region region(Vector3DInt16(2,2,2), Vector3DInt16(20,20,20)); + SurfaceMesh mesh; + //CubicSurfaceExtractor surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); + CubicSurfaceExtractor surfaceExtractor(&volData, region, &mesh); surfaceExtractor.execute(); + /*SurfaceMesh meshWithNormals; + addNormals(mesh, meshWithNormals); + + meshWithNormals.decimate(0.99);*/ + + MeshDecimator decimator(&mesh); + decimator.execute(); + + SurfaceMesh meshWithNormals; + addNormals(mesh, meshWithNormals); + //Pass the surface to the OpenGL window - openGLWidget.setSurfaceMeshToRender(mesh); + openGLWidget.setSurfaceMeshToRender(meshWithNormals); + //openGLWidget.setSurfaceMeshToRender(mesh); //Run the message pump. return app.exec(); diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index 82c283c8..36acaf07 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -28,6 +28,7 @@ freely, subject to the following restrictions: #include "GradientEstimators.h" #include "MaterialDensityPair.h" #include "SurfaceExtractor.h" +#include "MeshDecimator.h" #include "Mesh.h" @@ -125,6 +126,9 @@ void OpenGLWidget::setVolume(PolyVox::Volume* volData) //mesh->decimate(0.999f); + MeshDecimator decimator(mesh.get()); + decimator.execute(); + //mesh->generateAveragedFaceNormals(true); //////////////////////////////////////////////////////////////////////////////// diff --git a/library/PolyVoxCore/include/MeshDecimator.h b/library/PolyVoxCore/include/MeshDecimator.h index f384cc61..1342a6e9 100644 --- a/library/PolyVoxCore/include/MeshDecimator.h +++ b/library/PolyVoxCore/include/MeshDecimator.h @@ -72,10 +72,10 @@ namespace PolyVox bool isSubsetCubic(std::bitset a, std::bitset b); bool canCollapseEdge(uint32_t uSrc, uint32_t uDest); - bool canCollapseNormalEdge(uint32_t uSrc, uint32_t uDest); - bool canCollapseRegionEdge(uint32_t uSrc, uint32_t uDest); - bool canCollapseMaterialEdge(uint32_t uSrc, uint32_t uDest); - bool collapseCausesFaceFlip(uint32_t uSrc, uint32_t uDest); + bool canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst); + bool canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst); + bool canCollapseMaterialEdge(uint32_t uSrc, uint32_t uDst); + bool collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold); //Data structures used during decimation std::vector m_vecNoOfNeighboursUsingMaterial; diff --git a/library/PolyVoxCore/include/MeshDecimator.inl b/library/PolyVoxCore/include/MeshDecimator.inl index e5d70566..8803627c 100644 --- a/library/PolyVoxCore/include/MeshDecimator.inl +++ b/library/PolyVoxCore/include/MeshDecimator.inl @@ -475,7 +475,7 @@ namespace PolyVox //////////////////////////////////////////////////////////////////////////////// //The last test is whether we will flip any of the faces - if(collapseCausesFaceFlip(uSrc,uDst)) + if(collapseChangesFaceNormals(uSrc,uDst, 0.9f)) { return false; } @@ -519,25 +519,30 @@ namespace PolyVox template bool MeshDecimator::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst) { + if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 1) //Face + { + return true; + } + if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 3) //Corner { return false; } - if(isSubsetCubic(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags, m_vecInitialVertexMetadata[uDst].m_bNormalFlags) == false) + if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 2) //Edge { - return false; - } + if(isSubsetCubic(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags, m_vecInitialVertexMetadata[uDst].m_bNormalFlags) == false) + { + return false; + } - if(collapseCausesFaceFlip(uSrc, uDst)) - { - return false; - } + if(collapseChangesFaceNormals(uSrc, uDst, 0.999f)) + { + return false; + } - /*if(m_vecInitialVertexMetadata[uSrc].normal.dot(m_vecInitialVertexMetadata[v1].normal) < 0.999f) - { - return false; - }*/ + return true; + } return true; } @@ -545,6 +550,51 @@ namespace PolyVox template bool MeshDecimator::canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst) { + //return false; + + if(m_vecInitialVertexMetadata[uDst].isOnRegionEdge) + { + + int matchingCoordinates = 0; + if(abs(m_pInputMesh->m_vecVertices[uSrc].getPosition().getX() - m_pInputMesh->m_vecVertices[uDst].getPosition().getX()) < 0.001) + { + matchingCoordinates++; + } + if(abs(m_pInputMesh->m_vecVertices[uSrc].getPosition().getY() - m_pInputMesh->m_vecVertices[uDst].getPosition().getY()) < 0.001) + { + matchingCoordinates++; + } + if(abs(m_pInputMesh->m_vecVertices[uSrc].getPosition().getZ() - m_pInputMesh->m_vecVertices[uDst].getPosition().getZ()) < 0.001) + { + matchingCoordinates++; + } + if(matchingCoordinates != 2) + { + return false; + } + + if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 3) //Corner + { + return false; + } + + if(m_vecInitialVertexMetadata[uSrc].trianglesUsingVertex.size() != m_vecInitialVertexMetadata[uDst].trianglesUsingVertex.size()) //Corner + { + return false; + } + + if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() != m_vecInitialVertexMetadata[uDst].m_bNormalFlags.count()) //Corner + { + return false; + } + + if(isSubsetCubic(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags, m_vecInitialVertexMetadata[uDst].m_bNormalFlags) == false) + { + return false; + } + + return !collapseChangesFaceNormals(uSrc, uDst, 0.999f); + } return false; } @@ -555,7 +605,7 @@ namespace PolyVox } template - bool MeshDecimator::collapseCausesFaceFlip(uint32_t uSrc, uint32_t uDst) + bool MeshDecimator::collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold) { bool faceFlipped = false; //list triangles = trianglesUsingVertexCurrently[v0]; @@ -596,7 +646,7 @@ namespace PolyVox continue; } - Vector3DFloat v0OldPos = m_pInputMesh->m_vecVertices[vertexMapper[v0Old]].getPosition(); + Vector3DFloat v0OldPos = m_pInputMesh->m_vecVertices[vertexMapper[v0Old]].getPosition(); //Note: we need the vertex mapper here. These neighbouring vertices may have been moved. Vector3DFloat v1OldPos = m_pInputMesh->m_vecVertices[vertexMapper[v1Old]].getPosition(); Vector3DFloat v2OldPos = m_pInputMesh->m_vecVertices[vertexMapper[v2Old]].getPosition(); @@ -622,7 +672,7 @@ namespace PolyVox // the 0.0 to 0.9 (which should still let coplanar faces merge) but oddly nothing then merged. Investigate this. float dotProduct = OldNormal.dot(NewNormal); //cout << dotProduct << endl; - if(dotProduct < 0.9f) + if(dotProduct < fThreshold) { //cout << " Face flipped!!" << endl;