diff --git a/examples/OpenGL/OpenGLWidget.cpp b/examples/OpenGL/OpenGLWidget.cpp index 7f2132f5..986db96b 100644 --- a/examples/OpenGL/OpenGLWidget.cpp +++ b/examples/OpenGL/OpenGLWidget.cpp @@ -3,7 +3,6 @@ #include #include "GradientEstimators.h" -#include "SurfaceAdjusters.h" #include "SurfaceExtractor.h" //Some namespaces we need @@ -73,6 +72,8 @@ void OpenGLWidget::setVolume(PolyVox::Volume* volData) //computeNormalsForVertices(m_volData, *ispCurrent, SOBEL_SMOOTHED); //*ispCurrent = getSmoothedSurface(*ispCurrent); + ispCurrent->smooth(0.2f); + ispCurrent->generateAveragedFaceNormals(true); Vector3DUint8 v3dRegPos(uRegionX,uRegionY,uRegionZ); diff --git a/library/PolyVoxCore/CMakeLists.txt b/library/PolyVoxCore/CMakeLists.txt index 8c4c8b88..553051ec 100644 --- a/library/PolyVoxCore/CMakeLists.txt +++ b/library/PolyVoxCore/CMakeLists.txt @@ -8,7 +8,6 @@ SET(CORE_SRC_FILES source/IndexedSurfacePatch.cpp source/Log.cpp source/Region.cpp - source/SurfaceAdjusters.cpp source/SurfaceExtractor.cpp source/SurfaceExtractors.cpp source/SurfaceVertex.cpp @@ -22,7 +21,6 @@ SET(CORE_INC_FILES include/Log.h include/PolyVoxForwardDeclarations.h include/Region.h - include/SurfaceAdjusters.h include/SurfaceExtractor.h include/SurfaceExtractors.h include/SurfaceVertex.h diff --git a/library/PolyVoxCore/include/IndexedSurfacePatch.h b/library/PolyVoxCore/include/IndexedSurfacePatch.h index 0ae65dad..70bb9dae 100644 --- a/library/PolyVoxCore/include/IndexedSurfacePatch.h +++ b/library/PolyVoxCore/include/IndexedSurfacePatch.h @@ -51,6 +51,10 @@ namespace PolyVox void clear(void); const bool isEmpty(void) const; + void smooth(float fAmount, bool bIncludeEdgeVertices = false); + + void generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices = false); + Vector3DInt32 m_v3dRegionPosition; //FIXME - remove this? int32_t m_iTimeStamp; diff --git a/library/PolyVoxCore/include/SurfaceAdjusters.h b/library/PolyVoxCore/include/SurfaceAdjusters.h deleted file mode 100644 index 6bcf79a8..00000000 --- a/library/PolyVoxCore/include/SurfaceAdjusters.h +++ /dev/null @@ -1,39 +0,0 @@ -#pragma region License -/****************************************************************************** -This file is part of the PolyVox library -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ -#pragma endregion - -#ifndef __PolyVox_SurfaceAdjusters_H__ -#define __PolyVox_SurfaceAdjusters_H__ - -#pragma region Headers -#include "PolyVoxForwardDeclarations.h" -#include "PolyVoxImpl/TypeDef.h" - -#include "PolyVoxImpl/CPlusPlusZeroXSupport.h" -#pragma endregion - -namespace PolyVox -{ - POLYVOXCORE_API void smoothRegionGeometry(Volume* volumeData, IndexedSurfacePatch& isp); - POLYVOXCORE_API void adjustDecimatedGeometry(Volume* volumeData, IndexedSurfacePatch& isp, uint8_t val); - POLYVOXCORE_API IndexedSurfacePatch getSmoothedSurface(IndexedSurfacePatch ispInput); -} - -#endif \ No newline at end of file diff --git a/library/PolyVoxCore/include/SurfaceTriangle.h b/library/PolyVoxCore/include/SurfaceTriangle.h deleted file mode 100644 index 5f9756e8..00000000 --- a/library/PolyVoxCore/include/SurfaceTriangle.h +++ /dev/null @@ -1,50 +0,0 @@ -/****************************************************************************** -This file is part of a voxel plugin for OGRE -Copyright (C) 2006 David Williams - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -******************************************************************************/ - -#ifndef __PolyVox_SurfaceTriangle_H__ -#define __PolyVox_SurfaceTriangle_H__ - -#include "SurfaceTypes.h" - -namespace PolyVox -{ - class SurfaceTriangle - { - public: - SurfaceTriangle(); - - friend bool operator == (const SurfaceTriangle& lhs, const SurfaceTriangle& rhs); - friend bool operator < (const SurfaceTriangle& lhs, const SurfaceTriangle& rhs); - - const SurfaceEdgeIterator& getEdge(void) const; - - void setEdge(const SurfaceEdgeIterator& edgeToSet); - - //std::string tostring(void); - - private: - SurfaceEdgeIterator edge; - }; - - - - //bool operator < (const SurfaceTriangleIterator& lhs, const SurfaceTriangleIterator& rhs); -} - -#endif diff --git a/library/PolyVoxCore/source/IndexedSurfacePatch.cpp b/library/PolyVoxCore/source/IndexedSurfacePatch.cpp index 33374b6b..194034c4 100644 --- a/library/PolyVoxCore/source/IndexedSurfacePatch.cpp +++ b/library/PolyVoxCore/source/IndexedSurfacePatch.cpp @@ -114,5 +114,78 @@ namespace PolyVox return (getNoOfVertices() == 0) || (getNoOfIndices() == 0); } - + void IndexedSurfacePatch::smooth(float fAmount, bool bIncludeEdgeVertices) + { + std::vector vecOriginalVertices = m_vecVertices; + + for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) + { + SurfaceVertex& v0 = vecOriginalVertices[*iterIndex]; + SurfaceVertex& v0New = m_vecVertices[*iterIndex]; + iterIndex++; + SurfaceVertex& v1 = vecOriginalVertices[*iterIndex]; + SurfaceVertex& v1New = m_vecVertices[*iterIndex]; + iterIndex++; + SurfaceVertex& v2 = vecOriginalVertices[*iterIndex]; + SurfaceVertex& v2New = m_vecVertices[*iterIndex]; + iterIndex++; + + //FIXME - instead of finding these opposite points (Opp) we could just use the midpoint? + Vector3DFloat v0Opp = (v1.position + v2.position) / 2.0f; + Vector3DFloat v1Opp = (v0.position + v2.position) / 2.0f; + Vector3DFloat v2Opp = (v0.position + v1.position) / 2.0f; + + Vector3DFloat v0ToOpp = v0Opp - v0.position; + v0ToOpp.normalise(); + Vector3DFloat v1ToOpp = v1Opp - v1.position; + v1ToOpp.normalise(); + Vector3DFloat v2ToOpp = v2Opp - v2.position; + v2ToOpp.normalise(); + + Vector3DFloat n0 = v0.getNormal(); + n0.normalise(); + Vector3DFloat n1 = v1.getNormal(); + n1.normalise(); + Vector3DFloat n2 = v2.getNormal(); + n2.normalise(); + + v0New.position += (n0 * (n0.dot(v0ToOpp)) * fAmount); + v1New.position += (n1 * (n1.dot(v1ToOpp)) * fAmount); + v2New.position += (n2 * (n2.dot(v2ToOpp)) * fAmount); + } + } + + void IndexedSurfacePatch::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices) + { + for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) + { + iterVertex->setNormal(Vector3DFloat(0.0f,0.0f,0.0f)); + } + + for(vector::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();) + { + SurfaceVertex& v0 = m_vecVertices[*iterIndex]; + iterIndex++; + SurfaceVertex& v1 = m_vecVertices[*iterIndex]; + iterIndex++; + SurfaceVertex& v2 = m_vecVertices[*iterIndex]; + iterIndex++; + + Vector3DFloat triangleNormal = (v1.getPosition()-v0.getPosition()).cross(v2.getPosition()-v0.getPosition()); + + v0.setNormal(v0.getNormal() + triangleNormal); + v1.setNormal(v1.getNormal() + triangleNormal); + v2.setNormal(v2.getNormal() + triangleNormal); + } + + if(bNormalise) + { + for(vector::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++) + { + Vector3DFloat normal = iterVertex->getNormal(); + normal.normalise(); + iterVertex->setNormal(normal); + } + } + } } diff --git a/library/PolyVoxCore/source/SurfaceAdjusters.cpp b/library/PolyVoxCore/source/SurfaceAdjusters.cpp deleted file mode 100644 index e0da1c4f..00000000 --- a/library/PolyVoxCore/source/SurfaceAdjusters.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include "SurfaceAdjusters.h" - -#include "VolumeSampler.h" -#include "GradientEstimators.h" -#include "IndexedSurfacePatch.h" -#include "PolyVoxImpl/Utility.h" -#include "VoxelFilters.h" - -#include - -using namespace std; - -namespace PolyVox -{ - void smoothRegionGeometry(Volume* volumeData, IndexedSurfacePatch& isp) - { - const uint8_t uSmoothingFactor = 2; - const float fThreshold = 0.5f; - - VolumeSampler volIter(*volumeData); - - std::vector& vecVertices = isp.getRawVertexData(); - std::vector::iterator iterSurfaceVertex = vecVertices.begin(); - while(iterSurfaceVertex != vecVertices.end()) - { - for(int ct = 0; ct < uSmoothingFactor; ++ct) - { - const Vector3DFloat& v3dPos = iterSurfaceVertex->getPosition() + static_cast(isp.m_v3dRegionPosition); - const Vector3DInt32 v3dFloor = static_cast(v3dPos); - const Vector3DFloat& v3dRem = v3dPos - static_cast(v3dFloor); - - //Check all corners are within the volume, allowing a boundary for gradient estimation - bool lowerCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor,2); - bool upperCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor+Vector3DInt32(1,1,1),2); - - if(lowerCornerInside && upperCornerInside) //If this test fails the vertex will be left as it was - { - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,0,0))); - const float v000 = computeSmoothedVoxel(volIter); - Vector3DFloat grad000 = computeSmoothCentralDifferenceGradient(volIter); - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,0,0))); - const float v100 = computeSmoothedVoxel(volIter); - Vector3DFloat grad100 = computeSmoothCentralDifferenceGradient(volIter); - - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,1,0))); - const float v010 = computeSmoothedVoxel(volIter); - Vector3DFloat grad010 = computeSmoothCentralDifferenceGradient(volIter); - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,1,0))); - const float v110 = computeSmoothedVoxel(volIter); - Vector3DFloat grad110 = computeSmoothCentralDifferenceGradient(volIter); - - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,0,1))); - const float v001 = computeSmoothedVoxel(volIter); - Vector3DFloat grad001 = computeSmoothCentralDifferenceGradient(volIter); - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,0,1))); - const float v101 = computeSmoothedVoxel(volIter); - Vector3DFloat grad101 = computeSmoothCentralDifferenceGradient(volIter); - - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(0,1,1))); - const float v011 = computeSmoothedVoxel(volIter); - Vector3DFloat grad011 = computeSmoothCentralDifferenceGradient(volIter); - volIter.setPosition(static_cast(v3dFloor + Vector3DInt32(1,1,1))); - const float v111 = computeSmoothedVoxel(volIter); - Vector3DFloat grad111 = computeSmoothCentralDifferenceGradient(volIter); - - float fInterVal = trilinearlyInterpolate(v000,v100,v010,v110,v001,v101,v011,v111,v3dRem.getX(),v3dRem.getY(),v3dRem.getZ()); - Vector3DFloat fInterGrad = trilinearlyInterpolate(grad000,grad100,grad010,grad110,grad001,grad101,grad011,grad111,v3dRem.getX(),v3dRem.getY(),v3dRem.getZ()); - - fInterGrad.normalise(); - float fDiff = fInterVal - fThreshold; - iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() + (fInterGrad * fDiff)); - iterSurfaceVertex->setNormal(fInterGrad); //This is actually the gradient for the previous position, but it won't have moved much. - } //if(lowerCornerInside && upperCornerInside) - } //for(int ct = 0; ct < uSmoothingFactor; ++ct) - ++iterSurfaceVertex; - } //while(iterSurfaceVertex != vecVertices.end()) - } - - void adjustDecimatedGeometry(Volume* volumeData, IndexedSurfacePatch& isp, uint8_t val) - { - VolumeSampler volIter(*volumeData); - - std::vector& vecVertices = isp.getRawVertexData(); - std::vector::iterator iterSurfaceVertex = vecVertices.begin(); - while(iterSurfaceVertex != vecVertices.end()) - { - Vector3DFloat v3dPos = iterSurfaceVertex->getPosition() + static_cast(isp.m_v3dRegionPosition); - Vector3DInt32 v3dFloor = static_cast(v3dPos); - - VolumeSampler volIter(*volumeData); - - //Check all corners are within the volume, allowing a boundary for gradient estimation - bool lowerCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor,1); - bool upperCornerInside = volumeData->getEnclosingRegion().containsPoint(v3dFloor+Vector3DInt32(1,1,1),1); - - if(lowerCornerInside && upperCornerInside) //If this test fails the vertex will be left as it was - { - //volIter.setPosition(static_cast(v3dFloor)); - //const uint8_t uFloor = volIter.getVoxel(); - if(((v3dPos.getX() - v3dFloor.getX()) < 0.001) && ((v3dPos.getY() - v3dFloor.getY()) < 0.001) && ((v3dPos.getZ() - v3dFloor.getZ()) < 0.001)) - //int x = v3dPos.getX(); - //if(x % 2 != 0) - //if((iterSurfaceVertex->getNormal().getX() > 0.5f) || (iterSurfaceVertex->getNormal().getX() < -0.5f)) - { - //exit(0); - //volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(1,0,0))); - //const uint8_t uCeil = volIter.getVoxel(); - //if(uFloor == uCeil) //In this case they must both be zero - { - //if(iterSurfaceVertex->getNormal().getX() > 0) - { - iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() - iterSurfaceVertex->getNormal() * 0.5f); - v3dPos = iterSurfaceVertex->getPosition() + static_cast(isp.m_v3dRegionPosition); - v3dFloor = static_cast(v3dPos); - - volIter.setPosition(static_cast(v3dFloor)); - const uint8_t uFloor = volIter.getVoxel(); - - uint8_t uCeil; - if((iterSurfaceVertex->getNormal().getX() > 0.5f) || (iterSurfaceVertex->getNormal().getX() < -0.5f)) - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(1,0,0))); - uCeil = volIter.getVoxel(); - } - if((iterSurfaceVertex->getNormal().getY() > 0.5f) || (iterSurfaceVertex->getNormal().getY() < -0.5f)) - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(0,1,0))); - uCeil = volIter.getVoxel(); - } - if((iterSurfaceVertex->getNormal().getZ() > 0.5f) || (iterSurfaceVertex->getNormal().getZ() < -0.5f)) - { - volIter.setPosition(static_cast(v3dFloor+Vector3DInt32(0,0,1))); - uCeil = volIter.getVoxel(); - } - - if(uFloor == uCeil) - { - //NOTE: The normal should actually be multiplied by 1.0f. This works - //for the simple cube but causes depth fighting on more complex shapes. - iterSurfaceVertex->setPosition(iterSurfaceVertex->getPosition() - iterSurfaceVertex->getNormal() * 0.5f); - } - } - } - } - } - - ++iterSurfaceVertex; - } //while(iterSurfaceVertex != vecVertices.end()) - } - - IndexedSurfacePatch getSmoothedSurface(IndexedSurfacePatch ispInput) - { - IndexedSurfacePatch ispOutput = ispInput; - - for(vector::iterator iterIndex = ispInput.m_vecTriangleIndices.begin(); iterIndex != ispInput.m_vecTriangleIndices.end();) - { - SurfaceVertex& v0 = ispOutput.m_vecVertices[*iterIndex]; - iterIndex++; - SurfaceVertex& v1 = ispOutput.m_vecVertices[*iterIndex]; - iterIndex++; - SurfaceVertex& v2 = ispOutput.m_vecVertices[*iterIndex]; - iterIndex++; - - //FIXME - instead of finding these opposite points (Opp) we could just use the midpoint? - Vector3DFloat v0Opp = (v1.position + v2.position) / 2.0f; - Vector3DFloat v1Opp = (v0.position + v2.position) / 2.0f; - Vector3DFloat v2Opp = (v0.position + v1.position) / 2.0f; - - Vector3DFloat v0ToOpp = v0Opp - v0.position; - v0ToOpp.normalise(); - Vector3DFloat v1ToOpp = v1Opp - v1.position; - v1ToOpp.normalise(); - Vector3DFloat v2ToOpp = v2Opp - v2.position; - v2ToOpp.normalise(); - - Vector3DFloat n0 = v0.getNormal(); - n0.normalise(); - Vector3DFloat n1 = v1.getNormal(); - n1.normalise(); - Vector3DFloat n2 = v2.getNormal(); - n2.normalise(); - - v0.position += (n0 * (n0.dot(v0ToOpp)) * 0.1f); - v1.position += (n1 * (n1.dot(v1ToOpp)) * 0.1f); - v2.position += (n2 * (n2.dot(v2ToOpp)) * 0.1f); - - /*Vector3DFloat triNormal = (v0.getPosition() - v1.getPosition()).cross(v2.getPosition() - v1.getPosition()); - triNormal.normalise(); - - v0.position += (n0 * (triNormal.dot(n0)) * -0.01f); - v1.position += (n1 * (triNormal.dot(n1)) * -0.01f); - v2.position += (n2 * (triNormal.dot(n2)) * -0.01f);*/ - } - - return ispOutput; - } -} \ No newline at end of file diff --git a/library/PolyVoxCore/source/SurfaceExtractors.cpp b/library/PolyVoxCore/source/SurfaceExtractors.cpp index cad1dcca..cc2f72a7 100644 --- a/library/PolyVoxCore/source/SurfaceExtractors.cpp +++ b/library/PolyVoxCore/source/SurfaceExtractors.cpp @@ -5,7 +5,6 @@ #include "IndexedSurfacePatch.h" #include "PolyVoxImpl/MarchingCubesTables.h" #include "Region.h" -#include "SurfaceAdjusters.h" #include "VolumeSampler.h" #include "PolyVoxImpl/DecimatedSurfaceExtractor.h" diff --git a/library/PolyVoxCore/source/SurfaceTriangle.cpp b/library/PolyVoxCore/source/SurfaceTriangle.cpp deleted file mode 100644 index e9b703a4..00000000 --- a/library/PolyVoxCore/source/SurfaceTriangle.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "SurfaceTriangle.h" -#include "SurfaceVertex.h" -#include "SurfaceEdge.h" - -namespace PolyVox -{ - SurfaceTriangle::SurfaceTriangle() - { - } - - const SurfaceEdgeIterator& SurfaceTriangle::getEdge(void) const - { - return edge; - } - - void SurfaceTriangle::setEdge(const SurfaceEdgeIterator& edgeToSet) - { - edge = edgeToSet; - } - - /*std::string SurfaceTriangle::tostring(void) - { - std::stringstream ss; - - uint16_t ct = 0; - SurfaceEdgeIterator edgeIter = edge; - ss << "SurfaceTriangle:"; - do - { - ss << "\n Edge " << ct << " = " << edgeIter->tostring(); - if(edgeIter->hasOtherHalfEdge) - { - ss << "\n Opp Edge " << ct << " = " << edgeIter->otherHalfEdge->tostring(); - } - else - { - ss << "\n No Other Half"; - } - edgeIter = edgeIter->nextHalfEdge; - ++ct; - } - while(edgeIter != edge); - return ss.str(); - }*/ - - bool operator == (const SurfaceTriangle& lhs, const SurfaceTriangle& rhs) - { - //Edges are unique in the set, so if the two positions are the same the - //two iterators must also be the same. So we just check the iterators. - return (lhs.edge == rhs.edge); - } - - bool operator < (const SurfaceTriangle& lhs, const SurfaceTriangle& rhs) - { - //Unlike the equality operator, we can't compare iterators. - //So dereference and compare the results. - return (*lhs.edge < *rhs.edge); - } -}