diff --git a/library/PolyVoxCore/include/IndexedSurfacePatch.h b/library/PolyVoxCore/include/IndexedSurfacePatch.h index cddffee9..aa1b9a8e 100644 --- a/library/PolyVoxCore/include/IndexedSurfacePatch.h +++ b/library/PolyVoxCore/include/IndexedSurfacePatch.h @@ -53,7 +53,7 @@ namespace PolyVox void clear(void); const bool isEmpty(void) const; - void smoothPositions(float fAmount, uint8_t uNoRequiredUses = 0); + void smoothPositions(float fAmount, bool bIncludeEdgeVertices = false); void sumNearbyNormals(bool bNormaliseResult = true); POLYVOX_SHARED_PTR extractSubset(std::set setMaterials); diff --git a/library/PolyVoxCore/include/SurfaceExtractor.h b/library/PolyVoxCore/include/SurfaceExtractor.h index da91fb99..e0c286f5 100644 --- a/library/PolyVoxCore/include/SurfaceExtractor.h +++ b/library/PolyVoxCore/include/SurfaceExtractor.h @@ -104,7 +104,7 @@ namespace PolyVox //The surface patch we are currently filling. IndexedSurfacePatch* m_ispCurrent; - //Information about the region we a re currently processing + //Information about the region we are currently processing Region m_regInputCropped; Region m_regInputUncropped; Region m_regVolumeCropped; diff --git a/library/PolyVoxCore/include/SurfaceVertex.h b/library/PolyVoxCore/include/SurfaceVertex.h index 5bfb0b2d..bc33d55f 100644 --- a/library/PolyVoxCore/include/SurfaceVertex.h +++ b/library/PolyVoxCore/include/SurfaceVertex.h @@ -37,7 +37,10 @@ namespace PolyVox float getMaterial(void) const; const Vector3DFloat& getNormal(void) const; const Vector3DFloat& getPosition(void) const; + + bool isEdgeVertex(void) const; + void setEdgeVertex(bool isEdgeVertex); void setMaterial(float materialToSet); void setNormal(const Vector3DFloat& normalToSet); void setPosition(const Vector3DFloat& positionToSet); @@ -46,6 +49,7 @@ namespace PolyVox Vector3DFloat position; Vector3DFloat normal; float material; + bool m_bIsEdgeVertex; }; diff --git a/library/PolyVoxCore/source/IndexedSurfacePatch.cpp b/library/PolyVoxCore/source/IndexedSurfacePatch.cpp index f258f6d0..f22055eb 100644 --- a/library/PolyVoxCore/source/IndexedSurfacePatch.cpp +++ b/library/PolyVoxCore/source/IndexedSurfacePatch.cpp @@ -121,20 +121,16 @@ namespace PolyVox /// normals must hve been set to something sensible before this functions is called. /// \param fAmount A factor controlling how much the vertices move by. Find a good /// value by experimentation, starting with something small such as 0.1f. - /// \param uNoRequiredUses The minumum number of triangles which have to be using - /// a vertex for that vertex to be modified. This is can be used to help prevent - /// the operation being carried out on edge vertices, which could cause discontinuities. + /// \param bIncludeEdgeVertices Indicates whether vertices on the edge of an + /// IndexedSurfacePatch should be smoothed. This can cause dicontinuities between + /// neighbouring patches. //////////////////////////////////////////////////////////////////////////////// - void IndexedSurfacePatch::smoothPositions(float fAmount, uint8_t uNoRequiredUses) + void IndexedSurfacePatch::smoothPositions(float fAmount, bool bIncludeEdgeVertices) { if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise... { return; } - //Used to count how many times a given vertex is used. This helps determine if it's on an edge. - std::vector useCount(m_vecVertices.size()); - //Initialise all counts to zero. Should be ok as the vector should store all elements contiguously. - memset(&useCount[0], 0, useCount.size() * sizeof(uint32_t)); //This will hold the new positions, and is initialised with the current positions. std::vector newPositions(m_vecVertices.size()); @@ -149,15 +145,12 @@ namespace PolyVox //Get the vertex data for the triangle SurfaceVertex& v0 = m_vecVertices[*iterIndex]; Vector3DFloat& v0New = newPositions[*iterIndex]; - useCount[*iterIndex]++; iterIndex++; SurfaceVertex& v1 = m_vecVertices[*iterIndex]; Vector3DFloat& v1New = newPositions[*iterIndex]; - useCount[*iterIndex]++; iterIndex++; SurfaceVertex& v2 = m_vecVertices[*iterIndex]; Vector3DFloat& v2New = newPositions[*iterIndex]; - useCount[*iterIndex]++; iterIndex++; //Find the midpoint @@ -193,8 +186,7 @@ namespace PolyVox //Update with the new positions for(uint32_t uIndex = 0; uIndex < newPositions.size(); uIndex++) { - //Check we have enough uses. - if(useCount[uIndex] >= uNoRequiredUses) + if((bIncludeEdgeVertices) || (m_vecVertices[uIndex].isEdgeVertex() == false)) { m_vecVertices[uIndex].setPosition(newPositions[uIndex]); } diff --git a/library/PolyVoxCore/source/SurfaceExtractor.cpp b/library/PolyVoxCore/source/SurfaceExtractor.cpp index 775a016a..042cd8f0 100644 --- a/library/PolyVoxCore/source/SurfaceExtractor.cpp +++ b/library/PolyVoxCore/source/SurfaceExtractor.cpp @@ -554,17 +554,21 @@ namespace PolyVox void SurfaceExtractor::generateVerticesForSlice() { + uint16_t uZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); + const uint16_t uZRegSpace = uZVolSpace - m_regInputCropped.getLowerCorner().getZ(); + bool isZEdge = ((uZVolSpace == m_regInputCropped.getLowerCorner().getZ()) || (uZVolSpace == m_regInputCropped.getUpperCorner().getZ())); + //Iterate over each cell in the region for(uint16_t uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); uYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); uYVolSpace += m_uStepSize) { + const uint16_t uYRegSpace = uYVolSpace - m_regInputCropped.getLowerCorner().getY(); + bool isYEdge = ((uYVolSpace == m_regInputCropped.getLowerCorner().getY()) || (uYVolSpace == m_regInputCropped.getUpperCorner().getY())); + for(uint16_t uXVolSpace = m_regSliceCurrent.getLowerCorner().getX(); uXVolSpace <= m_regSliceCurrent.getUpperCorner().getX(); uXVolSpace += m_uStepSize) { - uint16_t uZVolSpace = m_regSliceCurrent.getLowerCorner().getZ(); - //Current position const uint16_t uXRegSpace = uXVolSpace - m_regInputCropped.getLowerCorner().getX(); - const uint16_t uYRegSpace = uYVolSpace - m_regInputCropped.getLowerCorner().getY(); - const uint16_t uZRegSpace = uZVolSpace - m_regInputCropped.getLowerCorner().getZ(); + bool isXEdge = ((uXVolSpace == m_regInputCropped.getLowerCorner().getX()) || (uXVolSpace == m_regInputCropped.getUpperCorner().getX())); //Determine the index into the edge table which tells us which vertices are inside of the surface uint8_t iCubeIndex = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace)]; @@ -575,6 +579,9 @@ namespace PolyVox continue; } + //Check whether the generated vertex will lie on the edge of the region + + m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace); const uint8_t v000 = m_sampVolume.getSubSampledVoxel(m_uLodLevel); @@ -587,6 +594,7 @@ namespace PolyVox const Vector3DFloat v3dNormal(v000 > v100 ? 1.0f : -1.0f,0.0,0.0); const uint8_t uMaterial = v000 | v100; //Because one of these is 0, the or operation takes the max. SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + surfaceVertex.setEdgeVertex(isXEdge || isYEdge || isZEdge); uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesX[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; } @@ -598,6 +606,7 @@ namespace PolyVox const Vector3DFloat v3dNormal(0.0,v000 > v010 ? 1.0f : -1.0f,0.0); const uint8_t uMaterial = v000 | v010; //Because one of these is 0, the or operation takes the max. SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + surfaceVertex.setEdgeVertex(isXEdge || isYEdge || isZEdge); uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesY[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; } @@ -608,7 +617,8 @@ namespace PolyVox const Vector3DFloat v3dPosition(uXVolSpace - m_regInputCropped.getLowerCorner().getX(), uYVolSpace - m_regInputCropped.getLowerCorner().getY(), uZVolSpace - m_regInputCropped.getLowerCorner().getZ() + 0.5f * m_uStepSize); const Vector3DFloat v3dNormal(0.0,0.0,v000 > v001 ? 1.0f : -1.0f); const uint8_t uMaterial = v000 | v001; //Because one of these is 0, the or operation takes the max. - const SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial); + surfaceVertex.setEdgeVertex(isXEdge || isYEdge || isZEdge); uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex); m_pCurrentVertexIndicesZ[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex; } diff --git a/library/PolyVoxCore/source/SurfaceVertex.cpp b/library/PolyVoxCore/source/SurfaceVertex.cpp index b0471315..159cdc5f 100644 --- a/library/PolyVoxCore/source/SurfaceVertex.cpp +++ b/library/PolyVoxCore/source/SurfaceVertex.cpp @@ -58,6 +58,16 @@ namespace PolyVox return position; } + bool SurfaceVertex::isEdgeVertex(void) const + { + return m_bIsEdgeVertex; + } + + void SurfaceVertex::setEdgeVertex(bool isEdgeVertex) + { + m_bIsEdgeVertex = isEdgeVertex; + } + void SurfaceVertex::setMaterial(float materialToSet) { material = materialToSet;