From 1448f95b0a94380636a3d46494778a8f5fb8cdae Mon Sep 17 00:00:00 2001 From: David Williams Date: Sun, 7 Feb 2010 22:53:13 +0000 Subject: [PATCH] More work on LOD - allowing material boundaries to collapse. --- examples/OpenGL/OpenGLWidget.cpp | 2 + .../PolyVoxCore/include/IndexedSurfacePatch.h | 1 + library/PolyVoxCore/include/SurfaceVertex.h | 4 + .../source/IndexedSurfacePatch.cpp | 110 ++++++++++++++++-- 4 files changed, 110 insertions(+), 7 deletions(-) diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index 0038e242..f79e25ea 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -185,6 +185,8 @@ void OpenGLWidget::initializeGL() glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glEnable(GL_LIGHT0); + //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glShadeModel(GL_SMOOTH); } diff --git a/library/PolyVoxCore/include/IndexedSurfacePatch.h b/library/PolyVoxCore/include/IndexedSurfacePatch.h index b32a0bc6..aca7f04d 100644 --- a/library/PolyVoxCore/include/IndexedSurfacePatch.h +++ b/library/PolyVoxCore/include/IndexedSurfacePatch.h @@ -70,6 +70,7 @@ namespace PolyVox POLYVOX_SHARED_PTR extractSubset(std::set setMaterials); void generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices = false); + void generateMaterialWeightedNormals(); //Vector3DInt32 m_v3dRegionPosition; //FIXME - remove this? diff --git a/library/PolyVoxCore/include/SurfaceVertex.h b/library/PolyVoxCore/include/SurfaceVertex.h index 0a35d6ab..f09557d4 100644 --- a/library/PolyVoxCore/include/SurfaceVertex.h +++ b/library/PolyVoxCore/include/SurfaceVertex.h @@ -30,6 +30,7 @@ freely, subject to the following restrictions: #include "Vector.h" #include +#include namespace PolyVox { @@ -80,6 +81,9 @@ namespace PolyVox public: Vector3DFloat position; Vector3DFloat normal; + Vector3DFloat materialNormal; + int noOfMatchingNeighbours; + std::vector neighbourMaterials; float material; //FIXME: This shouldn't be float on CPU? std::bitset<7> m_bFlags; }; diff --git a/library/PolyVoxCore/source/IndexedSurfacePatch.cpp b/library/PolyVoxCore/source/IndexedSurfacePatch.cpp index 9faab46d..89b6fb15 100644 --- a/library/PolyVoxCore/source/IndexedSurfacePatch.cpp +++ b/library/PolyVoxCore/source/IndexedSurfacePatch.cpp @@ -313,6 +313,45 @@ namespace PolyVox } } + void IndexedSurfacePatch::generateMaterialWeightedNormals() + { + std::vector< std::set > neighbouringVertices(m_vecVertices.size()); + for(int triCt = 0; triCt < m_vecTriangleIndices.size() / 3; triCt++) + { + int v0 = m_vecTriangleIndices[(triCt * 3 + 0)]; + int v1 = m_vecTriangleIndices[(triCt * 3 + 1)]; + int v2 = m_vecTriangleIndices[(triCt * 3 + 2)]; + + neighbouringVertices[v0].insert(v1); + neighbouringVertices[v0].insert(v2); + + neighbouringVertices[v1].insert(v0); + neighbouringVertices[v1].insert(v2); + + neighbouringVertices[v2].insert(v0); + neighbouringVertices[v2].insert(v1); + } + + for(int vertCt = 0; vertCt < m_vecVertices.size(); vertCt++) + { + m_vecVertices[vertCt].noOfMatchingNeighbours = 0; + m_vecVertices[vertCt].neighbourMaterials.clear(); + Vector3DFloat materialNormal(0,0,0); + for(std::set::iterator iter = neighbouringVertices[vertCt].begin(); iter != neighbouringVertices[vertCt].end(); iter++) + { + m_vecVertices[vertCt].neighbourMaterials.push_back(m_vecVertices[*iter].getMaterial()); + + materialNormal += (m_vecVertices[*iter].getPosition() - m_vecVertices[vertCt].getPosition()) * m_vecVertices[vertCt].getMaterial(); + if(m_vecVertices[vertCt].getMaterial() == m_vecVertices[*iter].getMaterial()) + { + m_vecVertices[vertCt].noOfMatchingNeighbours++; + } + } + materialNormal.normalise(); + m_vecVertices[vertCt].materialNormal = materialNormal; + } + } + POLYVOX_SHARED_PTR IndexedSurfacePatch::extractSubset(std::set setMaterials) { POLYVOX_SHARED_PTR result(new IndexedSurfacePatch); @@ -420,11 +459,8 @@ namespace PolyVox void IndexedSurfacePatch::decimate(float fMinDotProductForCollapse) { - /* - Note for after holiday - This decimation is half working, but we get some undesirable collpses still. The face flip check - should stop these but doesn't quite seem to work. Also, note that before calling this function it is better if - 'generateAveragedFaceNormals(true);' has been called first, as this seems to give better normals for our purposes. - */ + generateMaterialWeightedNormals(); + uint32_t noOfEdgesCollapsed = 0; do { @@ -532,12 +568,72 @@ namespace PolyVox continue; } - //For now, don't collapse vertices on mateial edges... - if(m_vecVertices[v0].isOnMaterialEdge() || m_vecVertices[v1].isOnMaterialEdge()) + if(m_vecVertices[v0].getMaterial() != m_vecVertices[v1].getMaterial()) { continue; } + //For now, don't collapse vertices on material edges... + if(m_vecVertices[v0].isOnMaterialEdge() || m_vecVertices[v1].isOnMaterialEdge()) + { + if(true) + { + bool pass = false; + //if(m_vecVertices[v0].materialNormal.dot(m_vecVertices[v1].materialNormal) < 0.9999) + /*if(m_vecVertices[v0].isOnMaterialEdge() && m_vecVertices[v1].isOnMaterialEdge()) + { + if(m_vecVertices[v0].getMaterial() == m_vecVertices[v1].getMaterial()) + { + pass = true; + } + }*/ + + + + bool allMatch = false; + + if(m_vecVertices[v0].noOfMatchingNeighbours == m_vecVertices[v1].noOfMatchingNeighbours) + { + if(m_vecVertices[v0].noOfMatchingNeighbours == 4) + { + allMatch = true; + } + } + + bool movementValid = false; + Vector3DFloat movement = m_vecVertices[v1].getPosition() - m_vecVertices[v0].getPosition(); + movement.normalise(); + if(movement.dot(Vector3DFloat(0,0,1)) > 0.999) + { + movementValid = true; + } + + if(movement.dot(Vector3DFloat(0,1,0)) > 0.999) + { + movementValid = true; + } + + if(movement.dot(Vector3DFloat(1,0,0)) > 0.999) + { + movementValid = true; + } + + if(movementValid && allMatch) + { + pass = true; + } + + if(!pass) + { + continue; + } + } + else //Material collapses not allowed + { + continue; + } + } + //...or those on geometry (region) edges. /*if(m_vecVertices[v0].isOnGeometryEdge() || m_vecVertices[v1].isOnGeometryEdge()) {