From a7828995d9589c2ae8f2e95a63839726d9a50c17 Mon Sep 17 00:00:00 2001 From: David Williams Date: Wed, 5 Jan 2011 22:05:53 +0000 Subject: [PATCH] Just tidying up the MeshDecimator stuff a bit... --- examples/Basic/main.cpp | 21 ++- examples/OpenGL/OpenGLWidget.cpp | 11 +- library/PolyVoxCore/include/MeshDecimator.h | 12 +- library/PolyVoxCore/include/MeshDecimator.inl | 136 ++++++++++-------- 4 files changed, 106 insertions(+), 74 deletions(-) diff --git a/examples/Basic/main.cpp b/examples/Basic/main.cpp index 5e639d04..98d777ac 100644 --- a/examples/Basic/main.cpp +++ b/examples/Basic/main.cpp @@ -32,6 +32,7 @@ freely, subject to the following restrictions: #include "MeshDecimator.h" #include +#include //Use the PolyVox namespace using namespace PolyVox; @@ -41,7 +42,7 @@ 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(16, 16, 16); + Vector3DFloat v3dVolCenter(16, 16, 1); //This three-level for loop iterates over every voxel in the volume for (int z = 0; z < volData.getWidth(); z++) @@ -155,25 +156,35 @@ int main(int argc, char *argv[]) } }*/ - createSphereInVolume(volData, 10); + createSphereInVolume(volData, 24); //Extract the surface - Region region(Vector3DInt16(0,0,0), Vector3DInt16(20,20,20)); + Region region(Vector3DInt16(-1,-1,-1), Vector3DInt16(32,32,32)); SurfaceMesh mesh; //CubicSurfaceExtractor surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh); + + QTime t; + t.start(); + CubicSurfaceExtractor surfaceExtractor(&volData, region, &mesh); surfaceExtractor.execute(); + cout << "E: " << t.elapsed(); + t.restart(); + /*SurfaceMesh meshWithNormals; addNormals(mesh, meshWithNormals); meshWithNormals.decimate(0.99);*/ - MeshDecimator decimator(&mesh); + SurfaceMesh decimatedMesh; + MeshDecimator decimator(&mesh, &decimatedMesh); decimator.execute(); + cout << "D: " << t.elapsed(); + SurfaceMesh meshWithNormals; - addNormals(mesh, meshWithNormals); + addNormals(decimatedMesh, meshWithNormals); //Pass the surface to the OpenGL window openGLWidget.setSurfaceMeshToRender(meshWithNormals); diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index 8347e7ce..f37fdaba 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -126,7 +126,8 @@ void OpenGLWidget::setVolume(PolyVox::Volume* volData) //mesh->decimate(0.999f); - MeshDecimator decimator(mesh.get()); + polyvox_shared_ptr< SurfaceMesh > decimatedMesh(new SurfaceMesh); + MeshDecimator decimator(mesh.get(), decimatedMesh.get()); decimator.execute(); //mesh->generateAveragedFaceNormals(true); @@ -143,12 +144,12 @@ void OpenGLWidget::setVolume(PolyVox::Volume* volData) Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ); if(m_bUseOpenGLVertexBufferObjects) { - OpenGLSurfaceMesh openGLSurfaceMesh = BuildOpenGLSurfaceMesh(*(mesh.get())); + OpenGLSurfaceMesh openGLSurfaceMesh = BuildOpenGLSurfaceMesh(*(decimatedMesh.get())); m_mapOpenGLSurfaceMeshes.insert(make_pair(v3dRegPos, openGLSurfaceMesh)); } //else //{ - m_mapSurfaceMeshes.insert(make_pair(v3dRegPos, mesh)); + m_mapSurfaceMeshes.insert(make_pair(v3dRegPos, decimatedMesh)); //} //delete meshCurrent; } @@ -216,8 +217,8 @@ void OpenGLWidget::paintGL() //Moves the camera back so we can see the volume glTranslatef(0.0f, 0.0f, -m_volData->getDiagonalLength()); - glRotatef(m_xRotation, 1.0f, 0.0f, 0.0f); - glRotatef(m_yRotation, 0.0f, 1.0f, 0.0f); + glRotatef(10, 1.0f, 0.0f, 0.0f); + glRotatef(20, 0.0f, 1.0f, 0.0f); //Centre the volume on the origin glTranslatef(-g_uVolumeSideLength/2,-g_uVolumeSideLength/2,-g_uVolumeSideLength/2); diff --git a/library/PolyVoxCore/include/MeshDecimator.h b/library/PolyVoxCore/include/MeshDecimator.h index 74d4f9fe..bc375ec6 100644 --- a/library/PolyVoxCore/include/MeshDecimator.h +++ b/library/PolyVoxCore/include/MeshDecimator.h @@ -62,7 +62,7 @@ namespace PolyVox Vector3DFloat normal; }; public: - MeshDecimator(SurfaceMesh* pInputMesh/*, SurfaceMesh* pMeshOutput*/); + MeshDecimator(const SurfaceMesh* pInputMesh, SurfaceMesh* pOutputMesh, float fEdgeCollapseThreshold = 0.95f); void execute(); @@ -74,10 +74,10 @@ namespace PolyVox bool attemptEdgeCollapse(uint32_t uSrc, uint32_t uDest); - SurfaceMesh* m_pInputMesh; - //SurfaceMesh* pMeshOutput; + const SurfaceMesh* m_pInputMesh; + SurfaceMesh* m_pOutputMesh; - uint32_t performDecimationPass(float fMinDotProductForCollapse); + uint32_t performDecimationPass(float m_fMinDotProductForCollapse); bool isSubset(std::bitset a, std::bitset b); bool canCollapseEdge(uint32_t uSrc, uint32_t uDest); @@ -92,11 +92,11 @@ namespace PolyVox std::vector vertexMapper; std::vector m_vecTriangles; - std::vector< list > trianglesUsingVertex; + std::vector< list > trianglesUsingVertex; //Should probably use vector of vectors, and resise in advance. std::vector m_vecInitialVertexMetadata; - float fMinDotProductForCollapse; + float m_fMinDotProductForCollapse; }; } diff --git a/library/PolyVoxCore/include/MeshDecimator.inl b/library/PolyVoxCore/include/MeshDecimator.inl index ceccb4b5..6139554b 100644 --- a/library/PolyVoxCore/include/MeshDecimator.inl +++ b/library/PolyVoxCore/include/MeshDecimator.inl @@ -24,55 +24,64 @@ freely, subject to the following restrictions: namespace PolyVox { template - MeshDecimator::MeshDecimator(SurfaceMesh* pInputMesh/*, SurfaceMesh* pMeshOutput*/) + MeshDecimator::MeshDecimator(const SurfaceMesh* pInputMesh, SurfaceMesh* pOutputMesh, float fEdgeCollapseThreshold) :m_pInputMesh(pInputMesh) - //,m_pOutputMesh(pOutputMesh) + ,m_pOutputMesh(pOutputMesh) + ,m_fMinDotProductForCollapse(fEdgeCollapseThreshold) { - fMinDotProductForCollapse = 0.999; + *m_pOutputMesh = *m_pInputMesh; } template void MeshDecimator::execute() { + //Sanity check. + if((m_pOutputMesh->m_vecVertices.empty()) || (m_pOutputMesh->m_vecTriangleIndices.empty())) + { + return; + } + buildConnectivityData(); fillInitialVertexMetadata(m_vecInitialVertexMetadata); uint32_t noOfEdgesCollapsed; do { - noOfEdgesCollapsed = performDecimationPass(fMinDotProductForCollapse); - m_pInputMesh->removeDegenerateTris(); + noOfEdgesCollapsed = performDecimationPass(m_fMinDotProductForCollapse); + m_pOutputMesh->removeDegenerateTris(); if(noOfEdgesCollapsed > 0) { //Build the connectivity data for the next pass. If this is slow, then look //at adjusting it (based on vertex mapper?) rather than bulding from scratch. buildConnectivityData(); } - //m_pInputMesh->removeUnusedVertices(); }while(noOfEdgesCollapsed > 0); + m_pOutputMesh->removeUnusedVertices(); + //Decimation will have invalidated LOD levels. - m_pInputMesh->m_vecLodRecords.clear(); + m_pOutputMesh->m_vecLodRecords.clear(); LodRecord lodRecord; lodRecord.beginIndex = 0; - lodRecord.endIndex = m_pInputMesh->getNoOfIndices(); - m_pInputMesh->m_vecLodRecords.push_back(lodRecord); + lodRecord.endIndex = m_pOutputMesh->getNoOfIndices(); + m_pOutputMesh->m_vecLodRecords.push_back(lodRecord); } template void MeshDecimator::buildConnectivityData(void) { + //Build a list of all the triangles, complete with face normals. m_vecTriangles.clear(); - m_vecTriangles.resize(m_pInputMesh->m_vecTriangleIndices.size() / 3); + m_vecTriangles.resize(m_pOutputMesh->m_vecTriangleIndices.size() / 3); for(int triCt = 0; triCt < m_vecTriangles.size(); triCt++) { - m_vecTriangles[triCt].v0 = m_pInputMesh->m_vecTriangleIndices[triCt * 3 + 0]; - m_vecTriangles[triCt].v1 = m_pInputMesh->m_vecTriangleIndices[triCt * 3 + 1]; - m_vecTriangles[triCt].v2 = m_pInputMesh->m_vecTriangleIndices[triCt * 3 + 2]; + m_vecTriangles[triCt].v0 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 0]; + m_vecTriangles[triCt].v1 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 1]; + m_vecTriangles[triCt].v2 = m_pOutputMesh->m_vecTriangleIndices[triCt * 3 + 2]; - Vector3DFloat v0Pos = m_pInputMesh->m_vecVertices[m_vecTriangles[triCt].v0].position; - Vector3DFloat v1Pos = m_pInputMesh->m_vecVertices[m_vecTriangles[triCt].v1].position; - Vector3DFloat v2Pos = m_pInputMesh->m_vecVertices[m_vecTriangles[triCt].v2].position; + Vector3DFloat v0Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v0].position; + Vector3DFloat v1Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v1].position; + Vector3DFloat v2Pos = m_pOutputMesh->m_vecVertices[m_vecTriangles[triCt].v2].position; Vector3DFloat v0v1 = v1Pos - v0Pos; Vector3DFloat v0v2 = v2Pos - v0Pos; @@ -82,8 +91,9 @@ namespace PolyVox m_vecTriangles[triCt].normal = normal; } + //For each vertex, determine which triangles are using it. trianglesUsingVertex.clear(); - trianglesUsingVertex.resize(m_pInputMesh->m_vecVertices.size()); + trianglesUsingVertex.resize(m_pOutputMesh->m_vecVertices.size()); for(int ct = 0; ct < m_vecTriangles.size(); ct++) { trianglesUsingVertex[m_vecTriangles[ct].v0].push_back(ct); @@ -95,7 +105,7 @@ namespace PolyVox void MeshDecimator::fillInitialVertexMetadata(std::vector& vecVertexMetadata) { vecVertexMetadata.clear(); - vecVertexMetadata.resize(m_pInputMesh->m_vecVertices.size()); + vecVertexMetadata.resize(m_pOutputMesh->m_vecVertices.size()); //Initialise the metadata for(int ct = 0; ct < vecVertexMetadata.size(); ct++) { @@ -104,11 +114,15 @@ namespace PolyVox vecVertexMetadata[ct].isOnRegionFace.reset(); } - for(int outerCt = 0; outerCt < m_pInputMesh->m_vecVertices.size()-1; outerCt++) + //Identify duplicate vertices, as they lie on the material edge. Note that this is a particularly slow way of + //findong the duplicates. Better to hash into integer (with upper bits being z and lower bits being x) and sort + //the resulting integers. The should be mostly in order as this is the order they come out of the + //CubicSurfaceExtractor in. Duplicates are now neighbours in the resulting list so just scan through for pairs. + for(int outerCt = 0; outerCt < m_pOutputMesh->m_vecVertices.size()-1; outerCt++) { - for(int innerCt = outerCt+1; innerCt < m_pInputMesh->m_vecVertices.size(); innerCt++) + for(int innerCt = outerCt+1; innerCt < m_pOutputMesh->m_vecVertices.size(); innerCt++) { - if((m_pInputMesh->m_vecVertices[innerCt].position - m_pInputMesh->m_vecVertices[outerCt].position).lengthSquared() < 0.001f) + if((m_pOutputMesh->m_vecVertices[innerCt].position - m_pOutputMesh->m_vecVertices[outerCt].position).lengthSquared() < 0.001f) { vecVertexMetadata[innerCt].isOnMaterialEdge = true; vecVertexMetadata[outerCt].isOnMaterialEdge = true; @@ -116,7 +130,8 @@ namespace PolyVox } } - for(int ct = 0; ct < m_pInputMesh->m_vecVertices.size(); ct++) + //Compute an approcimation to the normal, used when deciding if an edge can collapse. + for(int ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++) { Vector3DFloat sumOfNormals(0.0f,0.0f,0.0f); for(list::const_iterator iter = trianglesUsingVertex[ct].cbegin(); iter != trianglesUsingVertex[ct].cend(); iter++) @@ -128,50 +143,52 @@ namespace PolyVox vecVertexMetadata[ct].normal.normalise(); } + //Identify those vertices on the edge of a region. Care will need to be taken when moving them. for(int ct = 0; ct < vecVertexMetadata.size(); ct++) { - Region regTransformed = m_pInputMesh->m_Region; + Region regTransformed = m_pOutputMesh->m_Region; regTransformed.shift(regTransformed.getLowerCorner() * static_cast(-1)); //Plus and minus X - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pInputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pInputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f); //Plus and minus Y - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pInputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pInputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f); //Plus and minus Z - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pInputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pInputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f); } } void MeshDecimator::fillInitialVertexMetadata(std::vector& vecVertexMetadata) { vecVertexMetadata.clear(); - vecVertexMetadata.resize(m_pInputMesh->m_vecVertices.size()); + vecVertexMetadata.resize(m_pOutputMesh->m_vecVertices.size()); //Initialise the metadata for(int ct = 0; ct < vecVertexMetadata.size(); ct++) { vecVertexMetadata[ct].isOnRegionFace.reset(); vecVertexMetadata[ct].isOnMaterialEdge = false; - vecVertexMetadata[ct].normal = m_pInputMesh->m_vecVertices[ct].normal; + vecVertexMetadata[ct].normal = m_pOutputMesh->m_vecVertices[ct].normal; } + //Identify those vertices on the edge of a region. Care will need to be taken when moving them. for(int ct = 0; ct < vecVertexMetadata.size(); ct++) { - Region regTransformed = m_pInputMesh->m_Region; + Region regTransformed = m_pOutputMesh->m_Region; regTransformed.shift(regTransformed.getLowerCorner() * static_cast(-1)); //Plus and minus X - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pInputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pInputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() < regTransformed.getLowerCorner().getX() + 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_X, m_pOutputMesh->m_vecVertices[ct].getPosition().getX() > regTransformed.getUpperCorner().getX() - 0.001f); //Plus and minus Y - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pInputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pInputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() < regTransformed.getLowerCorner().getY() + 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Y, m_pOutputMesh->m_vecVertices[ct].getPosition().getY() > regTransformed.getUpperCorner().getY() - 0.001f); //Plus and minus Z - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pInputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f); - vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pInputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_NEG_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() < regTransformed.getLowerCorner().getZ() + 0.001f); + vecVertexMetadata[ct].isOnRegionFace.set(RFF_ON_REGION_FACE_POS_Z, m_pOutputMesh->m_vecVertices[ct].getPosition().getZ() > regTransformed.getUpperCorner().getZ() - 0.001f); } //If all three vertices have the same material then we are not on a material edge. If any vertex has a different @@ -184,8 +201,8 @@ namespace PolyVox uint32_t v2 = m_vecTriangles[ct].v2; bool allMatch = - (m_pInputMesh->m_vecVertices[v0].material == m_pInputMesh->m_vecVertices[v1].material) && - (m_pInputMesh->m_vecVertices[v1].material == m_pInputMesh->m_vecVertices[v2].material); + (m_pOutputMesh->m_vecVertices[v0].material == m_pOutputMesh->m_vecVertices[v1].material) && + (m_pOutputMesh->m_vecVertices[v1].material == m_pOutputMesh->m_vecVertices[v2].material); if(!allMatch) { @@ -197,24 +214,24 @@ namespace PolyVox } template - uint32_t MeshDecimator::performDecimationPass(float fMinDotProductForCollapse) + uint32_t MeshDecimator::performDecimationPass(float m_fMinDotProductForCollapse) { // Count how many edges we have collapsed uint32_t noOfEdgesCollapsed = 0; // The vertex mapper track whick vertices collapse onto which. vertexMapper.clear(); - vertexMapper.resize(m_pInputMesh->m_vecVertices.size()); + vertexMapper.resize(m_pOutputMesh->m_vecVertices.size()); // Once a vertex is involved in a collapse (either because it // moves onto a different vertex, or because a different vertex // moves onto it) it is forbidden to take part in another collapse // this pass. We enforce this by setting the vertex locked flag. vertexLocked.clear(); - vertexLocked.resize(m_pInputMesh->m_vecVertices.size()); + vertexLocked.resize(m_pOutputMesh->m_vecVertices.size()); // Initialise the vectors - for(uint32_t ct = 0; ct < m_pInputMesh->m_vecVertices.size(); ct++) + for(uint32_t ct = 0; ct < m_pOutputMesh->m_vecVertices.size(); ct++) { // Initiall all vertices points to themselves vertexMapper[ct] = ct; @@ -244,13 +261,13 @@ namespace PolyVox if(noOfEdgesCollapsed > 0) { //Fix up the indices - for(int triCt = 0; triCt < m_pInputMesh->m_vecTriangleIndices.size(); triCt++) + for(int triCt = 0; triCt < m_pOutputMesh->m_vecTriangleIndices.size(); triCt++) { - uint32_t before = m_pInputMesh->m_vecTriangleIndices[triCt]; - uint32_t after = vertexMapper[m_pInputMesh->m_vecTriangleIndices[triCt]]; + uint32_t before = m_pOutputMesh->m_vecTriangleIndices[triCt]; + uint32_t after = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]]; if(before != after) { - m_pInputMesh->m_vecTriangleIndices[triCt] = vertexMapper[m_pInputMesh->m_vecTriangleIndices[triCt]]; + m_pOutputMesh->m_vecTriangleIndices[triCt] = vertexMapper[m_pOutputMesh->m_vecTriangleIndices[triCt]]; } } } @@ -307,12 +324,15 @@ namespace PolyVox template<> bool MeshDecimator::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst) { - return !collapseChangesFaceNormals(uSrc, uDst, fMinDotProductForCollapse); + //With the marching cubes surface we honour the user specified threshold + return !collapseChangesFaceNormals(uSrc, uDst, m_fMinDotProductForCollapse); } template<> bool MeshDecimator::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst) { + //User specified threshold is not used for cubic surface, any + //movement is too much (but allow for floating point error). return !collapseChangesFaceNormals(uSrc, uDst, 0.999f); } @@ -355,9 +375,9 @@ namespace PolyVox { uint32_t tri = *triIter; - uint32_t v0Old = m_pInputMesh->m_vecTriangleIndices[tri * 3]; - uint32_t v1Old = m_pInputMesh->m_vecTriangleIndices[tri * 3 + 1]; - uint32_t v2Old = m_pInputMesh->m_vecTriangleIndices[tri * 3 + 2]; + uint32_t v0Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3]; + uint32_t v1Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 1]; + uint32_t v2Old = m_pOutputMesh->m_vecTriangleIndices[tri * 3 + 2]; //Check if degenerate if((v0Old == v1Old) || (v1Old == v2Old) || (v2Old == v0Old)) @@ -382,13 +402,13 @@ namespace PolyVox continue; } - 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(); + Vector3DFloat v0OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0Old]].getPosition(); //Note: we need the vertex mapper here. These neighbouring vertices may have been moved. + Vector3DFloat v1OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1Old]].getPosition(); + Vector3DFloat v2OldPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2Old]].getPosition(); - Vector3DFloat v0NewPos = m_pInputMesh->m_vecVertices[vertexMapper[v0New]].getPosition(); - Vector3DFloat v1NewPos = m_pInputMesh->m_vecVertices[vertexMapper[v1New]].getPosition(); - Vector3DFloat v2NewPos = m_pInputMesh->m_vecVertices[vertexMapper[v2New]].getPosition(); + Vector3DFloat v0NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v0New]].getPosition(); + Vector3DFloat v1NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v1New]].getPosition(); + Vector3DFloat v2NewPos = m_pOutputMesh->m_vecVertices[vertexMapper[v2New]].getPosition(); /*Vector3DFloat v0OldPos = m_vecVertices[v0Old].getPosition(); Vector3DFloat v1OldPos = m_vecVertices[v1Old].getPosition();