Work on MeshDecimator.
This commit is contained in:
parent
fff36662a5
commit
68ac0f0056
@ -52,14 +52,19 @@ void OpenGLWidget::initializeGL()
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthFunc(GL_LEQUAL);
|
glDepthFunc(GL_LEQUAL);
|
||||||
|
|
||||||
//Anable smooth lighting
|
//Enable smooth lighting
|
||||||
glEnable(GL_LIGHTING);
|
//glEnable(GL_LIGHTING);
|
||||||
glEnable(GL_LIGHT0);
|
//glEnable(GL_LIGHT0);
|
||||||
glShadeModel(GL_SMOOTH);
|
glShadeModel(GL_SMOOTH);
|
||||||
|
|
||||||
//We'll be rendering with index/vertex arrays
|
//We'll be rendering with index/vertex arrays
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glEnableClientState(GL_NORMAL_ARRAY);
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
glCullFace(GL_BACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLWidget::resizeGL(int w, int h)
|
void OpenGLWidget::resizeGL(int w, int h)
|
||||||
@ -70,7 +75,7 @@ void OpenGLWidget::resizeGL(int w, int h)
|
|||||||
//Set up the projection matrix
|
//Set up the projection matrix
|
||||||
glMatrixMode(GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
float frustumSize = 32.0f; //Half the volume size
|
float frustumSize = 16.0f; //Half the volume size
|
||||||
float aspect = static_cast<float>(width()) / static_cast<float>(height());
|
float aspect = static_cast<float>(width()) / static_cast<float>(height());
|
||||||
glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 1.0, 1000);
|
glOrtho(frustumSize*aspect, -frustumSize*aspect, frustumSize, -frustumSize, 1.0, 1000);
|
||||||
}
|
}
|
||||||
@ -86,7 +91,7 @@ void OpenGLWidget::paintGL()
|
|||||||
glTranslatef(0.0f,0.0f,-100.0f); //Centre volume and move back
|
glTranslatef(0.0f,0.0f,-100.0f); //Centre volume and move back
|
||||||
glRotatef(m_xRotation, 1.0f, 0.0f, 0.0f);
|
glRotatef(m_xRotation, 1.0f, 0.0f, 0.0f);
|
||||||
glRotatef(m_yRotation, 0.0f, 1.0f, 0.0f);
|
glRotatef(m_yRotation, 0.0f, 1.0f, 0.0f);
|
||||||
glTranslatef(-32.0f,-32.0f,-32.0f); //Centre volume and move back
|
glTranslatef(-16.0f,-16.0f,-16.0f); //Centre volume and move back
|
||||||
|
|
||||||
//Bind the index buffer
|
//Bind the index buffer
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
|
||||||
|
@ -24,10 +24,13 @@ freely, subject to the following restrictions:
|
|||||||
#include "OpenGLWidget.h"
|
#include "OpenGLWidget.h"
|
||||||
|
|
||||||
#include "MaterialDensityPair.h"
|
#include "MaterialDensityPair.h"
|
||||||
|
#include "CubicSurfaceExtractor.h"
|
||||||
#include "CubicSurfaceExtractorWithNormals.h"
|
#include "CubicSurfaceExtractorWithNormals.h"
|
||||||
#include "SurfaceMesh.h"
|
#include "SurfaceMesh.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
#include "MeshDecimator.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
//Use the PolyVox namespace
|
//Use the PolyVox namespace
|
||||||
@ -36,7 +39,9 @@ using namespace PolyVox;
|
|||||||
void createSphereInVolume(Volume<MaterialDensityPair44>& volData, float fRadius)
|
void createSphereInVolume(Volume<MaterialDensityPair44>& volData, float fRadius)
|
||||||
{
|
{
|
||||||
//This vector hold the position of the center of the volume
|
//This vector hold the position of the center of the volume
|
||||||
Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
//Vector3DFloat v3dVolCenter(volData.getWidth() / 2, volData.getHeight() / 2, volData.getDepth() / 2);
|
||||||
|
|
||||||
|
Vector3DFloat v3dVolCenter(16, 16, 16);
|
||||||
|
|
||||||
//This three-level for loop iterates over every voxel in the volume
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
for (int z = 0; z < volData.getWidth(); z++)
|
for (int z = 0; z < volData.getWidth(); z++)
|
||||||
@ -55,14 +60,16 @@ void createSphereInVolume(Volume<MaterialDensityPair44>& volData, float fRadius)
|
|||||||
{
|
{
|
||||||
//Our new density value
|
//Our new density value
|
||||||
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
|
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
|
||||||
|
uint8_t uMaterial = 3;
|
||||||
|
|
||||||
//Get the old voxel
|
//Get the old voxel
|
||||||
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
|
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
|
||||||
|
|
||||||
//Modify the density
|
//Modify the density
|
||||||
voxel.setDensity(uDensity);
|
voxel.setDensity(uDensity);
|
||||||
|
voxel.setMaterial(uMaterial);
|
||||||
|
|
||||||
//Wrte the voxel value into the volume
|
//Write the voxel value into the volume
|
||||||
volData.setVoxelAt(x, y, z, voxel);
|
volData.setVoxelAt(x, y, z, voxel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,6 +77,28 @@ void createSphereInVolume(Volume<MaterialDensityPair44>& volData, float fRadius)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addNormals(const PolyVox::SurfaceMesh<PolyVox::PositionMaterial>& inputMesh, PolyVox::SurfaceMesh<PolyVox::PositionMaterialNormal>& outputMesh)
|
||||||
|
{
|
||||||
|
outputMesh.m_Region = inputMesh.m_Region;
|
||||||
|
|
||||||
|
outputMesh.m_vecTriangleIndices.clear();
|
||||||
|
for(int ct = 0; ct < inputMesh.m_vecTriangleIndices.size(); ++ct)
|
||||||
|
{
|
||||||
|
outputMesh.m_vecTriangleIndices.push_back(inputMesh.m_vecTriangleIndices[ct]);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputMesh.m_vecVertices.clear();
|
||||||
|
for(int ct = 0; ct < inputMesh.m_vecVertices.size(); ++ct)
|
||||||
|
{
|
||||||
|
PositionMaterialNormal vertex;
|
||||||
|
vertex.position = inputMesh.m_vecVertices[ct].position;
|
||||||
|
vertex.material = inputMesh.m_vecVertices[ct].material;
|
||||||
|
outputMesh.m_vecVertices.push_back(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
outputMesh.generateAveragedFaceNormals(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
//Create and show the Qt OpenGL window
|
//Create and show the Qt OpenGL window
|
||||||
@ -78,16 +107,77 @@ int main(int argc, char *argv[])
|
|||||||
openGLWidget.show();
|
openGLWidget.show();
|
||||||
|
|
||||||
//Create an empty volume and then place a sphere in it
|
//Create an empty volume and then place a sphere in it
|
||||||
Volume<MaterialDensityPair44> volData(64, 64, 64);
|
Volume<MaterialDensityPair44> volData(32, 32, 32, 32);
|
||||||
createSphereInVolume(volData, 30);
|
//createSphereInVolume(volData, 30);
|
||||||
|
|
||||||
|
//This three-level for loop iterates over every voxel in the volume
|
||||||
|
/*for (int z = 8; z < 24; z++)
|
||||||
|
{
|
||||||
|
for (int y = 8; y < 24; y++)
|
||||||
|
{
|
||||||
|
for (int x = 8; x < 16; x++)
|
||||||
|
{
|
||||||
|
//Our new density value
|
||||||
|
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
|
||||||
|
|
||||||
|
//Get the old voxel
|
||||||
|
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
|
||||||
|
|
||||||
|
//Modify the density
|
||||||
|
voxel.setDensity(uDensity);
|
||||||
|
voxel.setMaterial(5);
|
||||||
|
|
||||||
|
//Write the voxel value into the volume
|
||||||
|
volData.setVoxelAt(x, y, z, voxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int z = 8; z < 24; z++)
|
||||||
|
{
|
||||||
|
for (int y = 8; y < 24; y++)
|
||||||
|
{
|
||||||
|
for (int x = 16; x < 24; x++)
|
||||||
|
{
|
||||||
|
//Our new density value
|
||||||
|
uint8_t uDensity = MaterialDensityPair44::getMaxDensity();
|
||||||
|
|
||||||
|
//Get the old voxel
|
||||||
|
MaterialDensityPair44 voxel = volData.getVoxelAt(x,y,z);
|
||||||
|
|
||||||
|
//Modify the density
|
||||||
|
voxel.setDensity(uDensity);
|
||||||
|
voxel.setMaterial(5);
|
||||||
|
|
||||||
|
//Write the voxel value into the volume
|
||||||
|
volData.setVoxelAt(x, y, z, voxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
createSphereInVolume(volData, 10);
|
||||||
|
|
||||||
//Extract the surface
|
//Extract the surface
|
||||||
SurfaceMesh<PositionMaterialNormal> mesh;
|
Region region(Vector3DInt16(2,2,2), Vector3DInt16(20,20,20));
|
||||||
CubicSurfaceExtractorWithNormals<MaterialDensityPair44> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
SurfaceMesh<PositionMaterial> mesh;
|
||||||
|
//CubicSurfaceExtractor<MaterialDensityPair44> surfaceExtractor(&volData, volData.getEnclosingRegion(), &mesh);
|
||||||
|
CubicSurfaceExtractor<MaterialDensityPair44> surfaceExtractor(&volData, region, &mesh);
|
||||||
surfaceExtractor.execute();
|
surfaceExtractor.execute();
|
||||||
|
|
||||||
|
/*SurfaceMesh<PositionMaterialNormal> meshWithNormals;
|
||||||
|
addNormals(mesh, meshWithNormals);
|
||||||
|
|
||||||
|
meshWithNormals.decimate(0.99);*/
|
||||||
|
|
||||||
|
MeshDecimator<PositionMaterial> decimator(&mesh);
|
||||||
|
decimator.execute();
|
||||||
|
|
||||||
|
SurfaceMesh<PositionMaterialNormal> meshWithNormals;
|
||||||
|
addNormals(mesh, meshWithNormals);
|
||||||
|
|
||||||
//Pass the surface to the OpenGL window
|
//Pass the surface to the OpenGL window
|
||||||
openGLWidget.setSurfaceMeshToRender(mesh);
|
openGLWidget.setSurfaceMeshToRender(meshWithNormals);
|
||||||
|
//openGLWidget.setSurfaceMeshToRender(mesh);
|
||||||
|
|
||||||
//Run the message pump.
|
//Run the message pump.
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@ -28,6 +28,7 @@ freely, subject to the following restrictions:
|
|||||||
#include "GradientEstimators.h"
|
#include "GradientEstimators.h"
|
||||||
#include "MaterialDensityPair.h"
|
#include "MaterialDensityPair.h"
|
||||||
#include "SurfaceExtractor.h"
|
#include "SurfaceExtractor.h"
|
||||||
|
#include "MeshDecimator.h"
|
||||||
|
|
||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
|
|
||||||
@ -125,6 +126,9 @@ void OpenGLWidget::setVolume(PolyVox::Volume<MaterialDensityPair44>* volData)
|
|||||||
|
|
||||||
//mesh->decimate(0.999f);
|
//mesh->decimate(0.999f);
|
||||||
|
|
||||||
|
MeshDecimator<PositionMaterialNormal> decimator(mesh.get());
|
||||||
|
decimator.execute();
|
||||||
|
|
||||||
//mesh->generateAveragedFaceNormals(true);
|
//mesh->generateAveragedFaceNormals(true);
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -72,10 +72,10 @@ namespace PolyVox
|
|||||||
bool isSubsetCubic(std::bitset<NF_NO_OF_FLAGS> a, std::bitset<NF_NO_OF_FLAGS> b);
|
bool isSubsetCubic(std::bitset<NF_NO_OF_FLAGS> a, std::bitset<NF_NO_OF_FLAGS> b);
|
||||||
|
|
||||||
bool canCollapseEdge(uint32_t uSrc, uint32_t uDest);
|
bool canCollapseEdge(uint32_t uSrc, uint32_t uDest);
|
||||||
bool canCollapseNormalEdge(uint32_t uSrc, uint32_t uDest);
|
bool canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst);
|
||||||
bool canCollapseRegionEdge(uint32_t uSrc, uint32_t uDest);
|
bool canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst);
|
||||||
bool canCollapseMaterialEdge(uint32_t uSrc, uint32_t uDest);
|
bool canCollapseMaterialEdge(uint32_t uSrc, uint32_t uDst);
|
||||||
bool collapseCausesFaceFlip(uint32_t uSrc, uint32_t uDest);
|
bool collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold);
|
||||||
|
|
||||||
//Data structures used during decimation
|
//Data structures used during decimation
|
||||||
std::vector<uint8_t> m_vecNoOfNeighboursUsingMaterial;
|
std::vector<uint8_t> m_vecNoOfNeighboursUsingMaterial;
|
||||||
|
@ -475,7 +475,7 @@ namespace PolyVox
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
//The last test is whether we will flip any of the faces
|
//The last test is whether we will flip any of the faces
|
||||||
if(collapseCausesFaceFlip(uSrc,uDst))
|
if(collapseChangesFaceNormals(uSrc,uDst, 0.9f))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -519,25 +519,30 @@ namespace PolyVox
|
|||||||
template <typename VertexType>
|
template <typename VertexType>
|
||||||
bool MeshDecimator<VertexType>::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst)
|
bool MeshDecimator<VertexType>::canCollapseNormalEdge(uint32_t uSrc, uint32_t uDst)
|
||||||
{
|
{
|
||||||
|
if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 1) //Face
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 3) //Corner
|
if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 3) //Corner
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isSubsetCubic(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags, m_vecInitialVertexMetadata[uDst].m_bNormalFlags) == false)
|
if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 2) //Edge
|
||||||
{
|
{
|
||||||
return false;
|
if(isSubsetCubic(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags, m_vecInitialVertexMetadata[uDst].m_bNormalFlags) == false)
|
||||||
}
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(collapseCausesFaceFlip(uSrc, uDst))
|
if(collapseChangesFaceNormals(uSrc, uDst, 0.999f))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*if(m_vecInitialVertexMetadata[uSrc].normal.dot(m_vecInitialVertexMetadata[v1].normal) < 0.999f)
|
return true;
|
||||||
{
|
}
|
||||||
return false;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -545,6 +550,51 @@ namespace PolyVox
|
|||||||
template <typename VertexType>
|
template <typename VertexType>
|
||||||
bool MeshDecimator<VertexType>::canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst)
|
bool MeshDecimator<VertexType>::canCollapseRegionEdge(uint32_t uSrc, uint32_t uDst)
|
||||||
{
|
{
|
||||||
|
//return false;
|
||||||
|
|
||||||
|
if(m_vecInitialVertexMetadata[uDst].isOnRegionEdge)
|
||||||
|
{
|
||||||
|
|
||||||
|
int matchingCoordinates = 0;
|
||||||
|
if(abs(m_pInputMesh->m_vecVertices[uSrc].getPosition().getX() - m_pInputMesh->m_vecVertices[uDst].getPosition().getX()) < 0.001)
|
||||||
|
{
|
||||||
|
matchingCoordinates++;
|
||||||
|
}
|
||||||
|
if(abs(m_pInputMesh->m_vecVertices[uSrc].getPosition().getY() - m_pInputMesh->m_vecVertices[uDst].getPosition().getY()) < 0.001)
|
||||||
|
{
|
||||||
|
matchingCoordinates++;
|
||||||
|
}
|
||||||
|
if(abs(m_pInputMesh->m_vecVertices[uSrc].getPosition().getZ() - m_pInputMesh->m_vecVertices[uDst].getPosition().getZ()) < 0.001)
|
||||||
|
{
|
||||||
|
matchingCoordinates++;
|
||||||
|
}
|
||||||
|
if(matchingCoordinates != 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() == 3) //Corner
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_vecInitialVertexMetadata[uSrc].trianglesUsingVertex.size() != m_vecInitialVertexMetadata[uDst].trianglesUsingVertex.size()) //Corner
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags.count() != m_vecInitialVertexMetadata[uDst].m_bNormalFlags.count()) //Corner
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isSubsetCubic(m_vecInitialVertexMetadata[uSrc].m_bNormalFlags, m_vecInitialVertexMetadata[uDst].m_bNormalFlags) == false)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !collapseChangesFaceNormals(uSrc, uDst, 0.999f);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,7 +605,7 @@ namespace PolyVox
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename VertexType>
|
template <typename VertexType>
|
||||||
bool MeshDecimator<VertexType>::collapseCausesFaceFlip(uint32_t uSrc, uint32_t uDst)
|
bool MeshDecimator<VertexType>::collapseChangesFaceNormals(uint32_t uSrc, uint32_t uDst, float fThreshold)
|
||||||
{
|
{
|
||||||
bool faceFlipped = false;
|
bool faceFlipped = false;
|
||||||
//list<uint32_t> triangles = trianglesUsingVertexCurrently[v0];
|
//list<uint32_t> triangles = trianglesUsingVertexCurrently[v0];
|
||||||
@ -596,7 +646,7 @@ namespace PolyVox
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3DFloat v0OldPos = m_pInputMesh->m_vecVertices[vertexMapper[v0Old]].getPosition();
|
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 v1OldPos = m_pInputMesh->m_vecVertices[vertexMapper[v1Old]].getPosition();
|
||||||
Vector3DFloat v2OldPos = m_pInputMesh->m_vecVertices[vertexMapper[v2Old]].getPosition();
|
Vector3DFloat v2OldPos = m_pInputMesh->m_vecVertices[vertexMapper[v2Old]].getPosition();
|
||||||
|
|
||||||
@ -622,7 +672,7 @@ namespace PolyVox
|
|||||||
// the 0.0 to 0.9 (which should still let coplanar faces merge) but oddly nothing then merged. Investigate this.
|
// the 0.0 to 0.9 (which should still let coplanar faces merge) but oddly nothing then merged. Investigate this.
|
||||||
float dotProduct = OldNormal.dot(NewNormal);
|
float dotProduct = OldNormal.dot(NewNormal);
|
||||||
//cout << dotProduct << endl;
|
//cout << dotProduct << endl;
|
||||||
if(dotProduct < 0.9f)
|
if(dotProduct < fThreshold)
|
||||||
{
|
{
|
||||||
//cout << " Face flipped!!" << endl;
|
//cout << " Face flipped!!" << endl;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user