Vertices now know whether they are on the edge of an indexed surface patch. This allows improved smoothing.
This commit is contained in:
parent
ab906a03f6
commit
e5d38b597e
@ -53,7 +53,7 @@ namespace PolyVox
|
|||||||
void clear(void);
|
void clear(void);
|
||||||
const bool isEmpty(void) const;
|
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);
|
void sumNearbyNormals(bool bNormaliseResult = true);
|
||||||
|
|
||||||
POLYVOX_SHARED_PTR<IndexedSurfacePatch> extractSubset(std::set<uint8_t> setMaterials);
|
POLYVOX_SHARED_PTR<IndexedSurfacePatch> extractSubset(std::set<uint8_t> setMaterials);
|
||||||
|
@ -104,7 +104,7 @@ namespace PolyVox
|
|||||||
//The surface patch we are currently filling.
|
//The surface patch we are currently filling.
|
||||||
IndexedSurfacePatch* m_ispCurrent;
|
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_regInputCropped;
|
||||||
Region m_regInputUncropped;
|
Region m_regInputUncropped;
|
||||||
Region m_regVolumeCropped;
|
Region m_regVolumeCropped;
|
||||||
|
@ -37,7 +37,10 @@ namespace PolyVox
|
|||||||
float getMaterial(void) const;
|
float getMaterial(void) const;
|
||||||
const Vector3DFloat& getNormal(void) const;
|
const Vector3DFloat& getNormal(void) const;
|
||||||
const Vector3DFloat& getPosition(void) const;
|
const Vector3DFloat& getPosition(void) const;
|
||||||
|
|
||||||
|
bool isEdgeVertex(void) const;
|
||||||
|
|
||||||
|
void setEdgeVertex(bool isEdgeVertex);
|
||||||
void setMaterial(float materialToSet);
|
void setMaterial(float materialToSet);
|
||||||
void setNormal(const Vector3DFloat& normalToSet);
|
void setNormal(const Vector3DFloat& normalToSet);
|
||||||
void setPosition(const Vector3DFloat& positionToSet);
|
void setPosition(const Vector3DFloat& positionToSet);
|
||||||
@ -46,6 +49,7 @@ namespace PolyVox
|
|||||||
Vector3DFloat position;
|
Vector3DFloat position;
|
||||||
Vector3DFloat normal;
|
Vector3DFloat normal;
|
||||||
float material;
|
float material;
|
||||||
|
bool m_bIsEdgeVertex;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,20 +121,16 @@ namespace PolyVox
|
|||||||
/// normals must hve been set to something sensible before this functions is called.
|
/// 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
|
/// \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.
|
/// value by experimentation, starting with something small such as 0.1f.
|
||||||
/// \param uNoRequiredUses The minumum number of triangles which have to be using
|
/// \param bIncludeEdgeVertices Indicates whether vertices on the edge of an
|
||||||
/// a vertex for that vertex to be modified. This is can be used to help prevent
|
/// IndexedSurfacePatch should be smoothed. This can cause dicontinuities between
|
||||||
/// the operation being carried out on edge vertices, which could cause discontinuities.
|
/// 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...
|
if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise...
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//Used to count how many times a given vertex is used. This helps determine if it's on an edge.
|
|
||||||
std::vector<uint32_t> 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.
|
//This will hold the new positions, and is initialised with the current positions.
|
||||||
std::vector<Vector3DFloat> newPositions(m_vecVertices.size());
|
std::vector<Vector3DFloat> newPositions(m_vecVertices.size());
|
||||||
@ -149,15 +145,12 @@ namespace PolyVox
|
|||||||
//Get the vertex data for the triangle
|
//Get the vertex data for the triangle
|
||||||
SurfaceVertex& v0 = m_vecVertices[*iterIndex];
|
SurfaceVertex& v0 = m_vecVertices[*iterIndex];
|
||||||
Vector3DFloat& v0New = newPositions[*iterIndex];
|
Vector3DFloat& v0New = newPositions[*iterIndex];
|
||||||
useCount[*iterIndex]++;
|
|
||||||
iterIndex++;
|
iterIndex++;
|
||||||
SurfaceVertex& v1 = m_vecVertices[*iterIndex];
|
SurfaceVertex& v1 = m_vecVertices[*iterIndex];
|
||||||
Vector3DFloat& v1New = newPositions[*iterIndex];
|
Vector3DFloat& v1New = newPositions[*iterIndex];
|
||||||
useCount[*iterIndex]++;
|
|
||||||
iterIndex++;
|
iterIndex++;
|
||||||
SurfaceVertex& v2 = m_vecVertices[*iterIndex];
|
SurfaceVertex& v2 = m_vecVertices[*iterIndex];
|
||||||
Vector3DFloat& v2New = newPositions[*iterIndex];
|
Vector3DFloat& v2New = newPositions[*iterIndex];
|
||||||
useCount[*iterIndex]++;
|
|
||||||
iterIndex++;
|
iterIndex++;
|
||||||
|
|
||||||
//Find the midpoint
|
//Find the midpoint
|
||||||
@ -193,8 +186,7 @@ namespace PolyVox
|
|||||||
//Update with the new positions
|
//Update with the new positions
|
||||||
for(uint32_t uIndex = 0; uIndex < newPositions.size(); uIndex++)
|
for(uint32_t uIndex = 0; uIndex < newPositions.size(); uIndex++)
|
||||||
{
|
{
|
||||||
//Check we have enough uses.
|
if((bIncludeEdgeVertices) || (m_vecVertices[uIndex].isEdgeVertex() == false))
|
||||||
if(useCount[uIndex] >= uNoRequiredUses)
|
|
||||||
{
|
{
|
||||||
m_vecVertices[uIndex].setPosition(newPositions[uIndex]);
|
m_vecVertices[uIndex].setPosition(newPositions[uIndex]);
|
||||||
}
|
}
|
||||||
|
@ -554,17 +554,21 @@ namespace PolyVox
|
|||||||
|
|
||||||
void SurfaceExtractor::generateVerticesForSlice()
|
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
|
//Iterate over each cell in the region
|
||||||
for(uint16_t uYVolSpace = m_regSliceCurrent.getLowerCorner().getY(); uYVolSpace <= m_regSliceCurrent.getUpperCorner().getY(); uYVolSpace += m_uStepSize)
|
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)
|
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
|
//Current position
|
||||||
const uint16_t uXRegSpace = uXVolSpace - m_regInputCropped.getLowerCorner().getX();
|
const uint16_t uXRegSpace = uXVolSpace - m_regInputCropped.getLowerCorner().getX();
|
||||||
const uint16_t uYRegSpace = uYVolSpace - m_regInputCropped.getLowerCorner().getY();
|
bool isXEdge = ((uXVolSpace == m_regInputCropped.getLowerCorner().getX()) || (uXVolSpace == m_regInputCropped.getUpperCorner().getX()));
|
||||||
const uint16_t uZRegSpace = uZVolSpace - m_regInputCropped.getLowerCorner().getZ();
|
|
||||||
|
|
||||||
//Determine the index into the edge table which tells us which vertices are inside of the surface
|
//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)];
|
uint8_t iCubeIndex = m_pCurrentBitmask[getIndex(uXRegSpace,uYRegSpace)];
|
||||||
@ -575,6 +579,9 @@ namespace PolyVox
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check whether the generated vertex will lie on the edge of the region
|
||||||
|
|
||||||
|
|
||||||
m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace);
|
m_sampVolume.setPosition(uXVolSpace,uYVolSpace,uZVolSpace);
|
||||||
const uint8_t v000 = m_sampVolume.getSubSampledVoxel(m_uLodLevel);
|
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 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.
|
const uint8_t uMaterial = v000 | v100; //Because one of these is 0, the or operation takes the max.
|
||||||
SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
||||||
|
surfaceVertex.setEdgeVertex(isXEdge || isYEdge || isZEdge);
|
||||||
uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex);
|
uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex);
|
||||||
m_pCurrentVertexIndicesX[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex;
|
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 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.
|
const uint8_t uMaterial = v000 | v010; //Because one of these is 0, the or operation takes the max.
|
||||||
SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
||||||
|
surfaceVertex.setEdgeVertex(isXEdge || isYEdge || isZEdge);
|
||||||
uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex);
|
uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex);
|
||||||
m_pCurrentVertexIndicesY[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex;
|
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 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 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 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);
|
uint32_t uLastVertexIndex = m_ispCurrent->addVertex(surfaceVertex);
|
||||||
m_pCurrentVertexIndicesZ[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex;
|
m_pCurrentVertexIndicesZ[getIndex(uXVolSpace - m_regInputCropped.getLowerCorner().getX(),uYVolSpace - m_regInputCropped.getLowerCorner().getY())] = uLastVertexIndex;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,16 @@ namespace PolyVox
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SurfaceVertex::isEdgeVertex(void) const
|
||||||
|
{
|
||||||
|
return m_bIsEdgeVertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SurfaceVertex::setEdgeVertex(bool isEdgeVertex)
|
||||||
|
{
|
||||||
|
m_bIsEdgeVertex = isEdgeVertex;
|
||||||
|
}
|
||||||
|
|
||||||
void SurfaceVertex::setMaterial(float materialToSet)
|
void SurfaceVertex::setMaterial(float materialToSet)
|
||||||
{
|
{
|
||||||
material = materialToSet;
|
material = materialToSet;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user