Initial checkin of ImprovedCubicSurfaceExtractor
This commit is contained in:
parent
dfc78eab05
commit
0cd7e5f7b1
128
library/PolyVoxCore/include/ImprovedCubicSurfaceExtractor.h
Normal file
128
library/PolyVoxCore/include/ImprovedCubicSurfaceExtractor.h
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __PolyVox_ImprovedCubicSurfaceExtractor_H__
|
||||||
|
#define __PolyVox_ImprovedCubicSurfaceExtractor_H__
|
||||||
|
|
||||||
|
#include "Array.h"
|
||||||
|
#include "PolyVoxForwardDeclarations.h"
|
||||||
|
#include "LargeVolume.h"
|
||||||
|
|
||||||
|
#include "PolyVoxImpl/TypeDef.h"
|
||||||
|
|
||||||
|
namespace PolyVox
|
||||||
|
{
|
||||||
|
struct IndexAndMaterial
|
||||||
|
{
|
||||||
|
int32_t iIndex : 24;
|
||||||
|
int32_t uMaterial : 8;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FaceNames
|
||||||
|
{
|
||||||
|
PositiveX,
|
||||||
|
PositiveY,
|
||||||
|
PositiveZ,
|
||||||
|
NegativeX,
|
||||||
|
NegativeY,
|
||||||
|
NegativeZ,
|
||||||
|
NoOfFaces
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Quad
|
||||||
|
{
|
||||||
|
uint32_t vertices[4];
|
||||||
|
uint8_t material; //Shouldn't hard code to uint8_t type?
|
||||||
|
};
|
||||||
|
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
class ImprovedCubicSurfaceExtractor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImprovedCubicSurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result);
|
||||||
|
|
||||||
|
void execute();
|
||||||
|
|
||||||
|
int32_t addVertex(float fX, float fY, float fZ, uint8_t uMaterial, Array<3, IndexAndMaterial>& existingVertices);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//The volume data and a sampler to access it.
|
||||||
|
VolumeType<VoxelType>* m_volData;
|
||||||
|
typename VolumeType<VoxelType>::Sampler m_sampVolume;
|
||||||
|
|
||||||
|
//Information about the region we are currently processing
|
||||||
|
Region m_regSizeInVoxels;
|
||||||
|
|
||||||
|
//The surface patch we are currently filling.
|
||||||
|
SurfaceMesh<PositionMaterial>* m_meshCurrent;
|
||||||
|
|
||||||
|
//Array<4, IndexAndMaterial> m_vertices;
|
||||||
|
Array<3, IndexAndMaterial> m_previousSliceVertices;
|
||||||
|
Array<3, IndexAndMaterial> m_currentSliceVertices;
|
||||||
|
|
||||||
|
Array<4, uint8_t> m_faces;
|
||||||
|
|
||||||
|
std::vector< std::list<Quad> > m_vecNegXQuads;
|
||||||
|
std::vector< std::list<Quad> > m_vecPosXQuads;
|
||||||
|
|
||||||
|
std::vector< std::list<Quad> > m_vecNegYQuads;
|
||||||
|
std::vector< std::list<Quad> > m_vecPosYQuads;
|
||||||
|
|
||||||
|
std::vector< std::list<Quad> > m_vecNegZQuads;
|
||||||
|
std::vector< std::list<Quad> > m_vecPosZQuads;
|
||||||
|
|
||||||
|
//Although we try to avoid creating multiple vertices at the same location, sometimes this is unavoidable
|
||||||
|
//if they have different materials. For example, four different materials next to each other would mean
|
||||||
|
//four quads (though more triangles) sharing the vertex. As far as I can tell, four is the worst case scenario.
|
||||||
|
static const uint32_t MaxQuadsSharingVertex;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Decimation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*class Triangle
|
||||||
|
{
|
||||||
|
uint32_t v0;
|
||||||
|
uint32_t v1;
|
||||||
|
uint32_t v2;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Triangle> triangles;
|
||||||
|
std::vector< std::vector<uint32_t> > trianglesUsingVertex;*/
|
||||||
|
|
||||||
|
//std::vector<Quad> decimate(const std::vector<Quad>& quads);
|
||||||
|
|
||||||
|
bool decimate(std::list<Quad>& quads);
|
||||||
|
|
||||||
|
Quad mergeQuads(Quad q1, Quad q2);
|
||||||
|
|
||||||
|
bool canMergeQuads(Quad q1, Quad q2);
|
||||||
|
|
||||||
|
int32_t quadContainsVertex(const Quad& quad, uint32_t uVertexIndex);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "ImprovedCubicSurfaceExtractor.inl"
|
||||||
|
|
||||||
|
#endif
|
516
library/PolyVoxCore/include/ImprovedCubicSurfaceExtractor.inl
Normal file
516
library/PolyVoxCore/include/ImprovedCubicSurfaceExtractor.inl
Normal file
@ -0,0 +1,516 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
Copyright (c) 2005-2009 David Williams
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any damages
|
||||||
|
arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any purpose,
|
||||||
|
including commercial applications, and to alter it and redistribute it
|
||||||
|
freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you must not
|
||||||
|
claim that you wrote the original software. If you use this software
|
||||||
|
in a product, an acknowledgment in the product documentation would be
|
||||||
|
appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include "Array.h"
|
||||||
|
#include "MaterialDensityPair.h"
|
||||||
|
#include "SurfaceMesh.h"
|
||||||
|
#include "PolyVoxImpl/MarchingCubesTables.h"
|
||||||
|
#include "VertexTypes.h"
|
||||||
|
|
||||||
|
namespace PolyVox
|
||||||
|
{
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
const uint32_t ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::MaxQuadsSharingVertex = 4;
|
||||||
|
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::ImprovedCubicSurfaceExtractor(VolumeType<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result)
|
||||||
|
:m_volData(volData)
|
||||||
|
,m_sampVolume(volData)
|
||||||
|
,m_regSizeInVoxels(region)
|
||||||
|
,m_meshCurrent(result)
|
||||||
|
{
|
||||||
|
m_meshCurrent->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
void ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::execute()
|
||||||
|
{
|
||||||
|
uint32_t uArrayWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2;
|
||||||
|
uint32_t uArrayHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2;
|
||||||
|
|
||||||
|
uint32_t arraySize[3]= {uArrayWidth, uArrayHeight, MaxQuadsSharingVertex};
|
||||||
|
m_previousSliceVertices.resize(arraySize);
|
||||||
|
m_currentSliceVertices.resize(arraySize);
|
||||||
|
memset(m_previousSliceVertices.getRawData(), 0xff, m_previousSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||||
|
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||||
|
|
||||||
|
uint32_t uRegionWidth = m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 1;
|
||||||
|
uint32_t uRegionHeight = m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 1;
|
||||||
|
uint32_t uRegionDepth = m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 1;
|
||||||
|
m_faces.resize(ArraySizes(uRegionWidth)(uRegionHeight)(uRegionDepth)(NoOfFaces));
|
||||||
|
memset(m_faces.getRawData(), 0x00, m_faces.getNoOfElements() * sizeof(uint8_t)); //Note: hard-coded type uint8_t
|
||||||
|
|
||||||
|
m_vecNegXQuads.resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2);
|
||||||
|
m_vecPosXQuads.resize(m_regSizeInVoxels.getUpperCorner().getX() - m_regSizeInVoxels.getLowerCorner().getX() + 2);
|
||||||
|
|
||||||
|
m_vecNegYQuads.resize(m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2);
|
||||||
|
m_vecPosYQuads.resize(m_regSizeInVoxels.getUpperCorner().getY() - m_regSizeInVoxels.getLowerCorner().getY() + 2);
|
||||||
|
|
||||||
|
m_vecNegZQuads.resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2);
|
||||||
|
m_vecPosZQuads.resize(m_regSizeInVoxels.getUpperCorner().getZ() - m_regSizeInVoxels.getLowerCorner().getZ() + 2);
|
||||||
|
|
||||||
|
|
||||||
|
for(int32_t z = m_regSizeInVoxels.getLowerCorner().getZ(); z <= m_regSizeInVoxels.getUpperCorner().getZ() + 1; z++)
|
||||||
|
{
|
||||||
|
for(int32_t y = m_regSizeInVoxels.getLowerCorner().getY(); y <= m_regSizeInVoxels.getUpperCorner().getY() + 1; y++)
|
||||||
|
{
|
||||||
|
for(int32_t x = m_regSizeInVoxels.getLowerCorner().getX(); x <= m_regSizeInVoxels.getUpperCorner().getX() + 1; x++)
|
||||||
|
{
|
||||||
|
// these are always positive anyway
|
||||||
|
uint32_t regX = x - m_regSizeInVoxels.getLowerCorner().getX();
|
||||||
|
uint32_t regY = y - m_regSizeInVoxels.getLowerCorner().getY();
|
||||||
|
uint32_t regZ = z - m_regSizeInVoxels.getLowerCorner().getZ();
|
||||||
|
|
||||||
|
bool finalX = (x == m_regSizeInVoxels.getUpperCorner().getX() + 1);
|
||||||
|
bool finalY = (y == m_regSizeInVoxels.getUpperCorner().getY() + 1);
|
||||||
|
bool finalZ = (z == m_regSizeInVoxels.getUpperCorner().getZ() + 1);
|
||||||
|
|
||||||
|
VoxelType currentVoxel = m_volData->getVoxelAt(x,y,z);
|
||||||
|
bool currentVoxelIsSolid = currentVoxel.getDensity() >= VoxelType::getThreshold();
|
||||||
|
|
||||||
|
VoxelType negXVoxel = m_volData->getVoxelAt(x-1,y,z);
|
||||||
|
bool negXVoxelIsSolid = negXVoxel.getDensity() >= VoxelType::getThreshold();
|
||||||
|
|
||||||
|
if((currentVoxelIsSolid != negXVoxelIsSolid) && (finalY == false) && (finalZ == false))
|
||||||
|
{
|
||||||
|
int material = (std::max)(currentVoxel.getMaterial(), negXVoxel.getMaterial());
|
||||||
|
|
||||||
|
// Check to ensure that when a voxel solid/non-solid change is right on a region border, the vertices are generated on the solid side of the region border
|
||||||
|
if(((currentVoxelIsSolid > negXVoxelIsSolid) && finalX == false) || ((currentVoxelIsSolid < negXVoxelIsSolid) && regX != 0))
|
||||||
|
{
|
||||||
|
uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
|
||||||
|
uint32_t v1 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
|
||||||
|
uint32_t v2 = addVertex(regX - 0.5f, regY + 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
|
||||||
|
uint32_t v3 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
|
||||||
|
|
||||||
|
if(currentVoxelIsSolid > negXVoxelIsSolid)
|
||||||
|
{
|
||||||
|
//m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||||
|
|
||||||
|
//m_faces[x][y][z][NegativeX] = material;
|
||||||
|
|
||||||
|
Quad quad;
|
||||||
|
quad.vertices[0] = v0;
|
||||||
|
quad.vertices[1] = v1;
|
||||||
|
quad.vertices[2] = v2;
|
||||||
|
quad.vertices[3] = v3;
|
||||||
|
quad.material = material;
|
||||||
|
|
||||||
|
m_vecNegXQuads[regX].push_back(quad);
|
||||||
|
|
||||||
|
/*m_vecNegXIndices[x].push_back(v0);
|
||||||
|
m_vecNegXIndices[x].push_back(v1);
|
||||||
|
m_vecNegXIndices[x].push_back(v2);
|
||||||
|
m_vecNegXIndices[x].push_back(v3);*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
Quad quad;
|
||||||
|
quad.vertices[0] = v0;
|
||||||
|
quad.vertices[1] = v3;
|
||||||
|
quad.vertices[2] = v2;
|
||||||
|
quad.vertices[3] = v1;
|
||||||
|
quad.material = material;
|
||||||
|
|
||||||
|
m_vecPosXQuads[regX].push_back(quad);
|
||||||
|
|
||||||
|
//m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||||
|
|
||||||
|
/*m_vecPosXIndices[x-1].push_back(v0);
|
||||||
|
m_vecPosXIndices[x-1].push_back(v2);
|
||||||
|
m_vecPosXIndices[x-1].push_back(v1);
|
||||||
|
m_vecPosXIndices[x-1].push_back(v1);
|
||||||
|
m_vecPosXIndices[x-1].push_back(v2);
|
||||||
|
m_vecPosXIndices[x-1].push_back(v3);*/
|
||||||
|
|
||||||
|
//m_faces[x-1][y][z][PositiveX] = material;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelType negYVoxel = m_volData->getVoxelAt(x,y-1,z);
|
||||||
|
bool negYVoxelIsSolid = negYVoxel.getDensity() >= VoxelType::getThreshold();
|
||||||
|
|
||||||
|
if((currentVoxelIsSolid != negYVoxelIsSolid) && (finalX == false) && (finalZ == false))
|
||||||
|
{
|
||||||
|
int material = (std::max)(currentVoxel.getMaterial(),negYVoxel.getMaterial());
|
||||||
|
|
||||||
|
if(((currentVoxelIsSolid > negYVoxelIsSolid) && finalY == false) || ((currentVoxelIsSolid < negYVoxelIsSolid) && regY != 0))
|
||||||
|
{
|
||||||
|
uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
|
||||||
|
uint32_t v1 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
|
||||||
|
uint32_t v2 = addVertex(regX + 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
|
||||||
|
uint32_t v3 = addVertex(regX - 0.5f, regY - 0.5f, regZ + 0.5f, material, m_currentSliceVertices);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(currentVoxelIsSolid > negYVoxelIsSolid)
|
||||||
|
{
|
||||||
|
//NOTE: For some reason y windong is opposite of X and Z. Investigate this...
|
||||||
|
Quad quad;
|
||||||
|
quad.vertices[0] = v0;
|
||||||
|
quad.vertices[1] = v3;
|
||||||
|
quad.vertices[2] = v2;
|
||||||
|
quad.vertices[3] = v1;
|
||||||
|
quad.material = material;
|
||||||
|
|
||||||
|
m_vecNegYQuads[regY].push_back(quad);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||||
|
|
||||||
|
//m_faces[x][y][z][NegativeY] = material;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//NOTE: For some reason y windong is opposite of X and Z. Investigate this...
|
||||||
|
Quad quad;
|
||||||
|
quad.vertices[0] = v0;
|
||||||
|
quad.vertices[1] = v1;
|
||||||
|
quad.vertices[2] = v2;
|
||||||
|
quad.vertices[3] = v3;
|
||||||
|
quad.material = material;
|
||||||
|
|
||||||
|
m_vecPosYQuads[regY].push_back(quad);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||||
|
|
||||||
|
//m_faces[x][y-1][z][PositiveY] = material;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelType negZVoxel = m_volData->getVoxelAt(x,y,z-1);
|
||||||
|
bool negZVoxelIsSolid = negZVoxel.getDensity() >= VoxelType::getThreshold();
|
||||||
|
|
||||||
|
if((currentVoxelIsSolid != negZVoxelIsSolid) && (finalX == false) && (finalY == false))
|
||||||
|
{
|
||||||
|
int material = (std::max)(currentVoxel.getMaterial(), negZVoxel.getMaterial());
|
||||||
|
|
||||||
|
if(((currentVoxelIsSolid > negZVoxelIsSolid) && finalZ == false) || ((currentVoxelIsSolid < negZVoxelIsSolid) && regZ != 0))
|
||||||
|
{
|
||||||
|
uint32_t v0 = addVertex(regX - 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
|
||||||
|
uint32_t v1 = addVertex(regX + 0.5f, regY - 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
|
||||||
|
uint32_t v2 = addVertex(regX + 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
|
||||||
|
uint32_t v3 = addVertex(regX - 0.5f, regY + 0.5f, regZ - 0.5f, material, m_previousSliceVertices);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(currentVoxelIsSolid > negZVoxelIsSolid)
|
||||||
|
{
|
||||||
|
Quad quad;
|
||||||
|
quad.vertices[0] = v0;
|
||||||
|
quad.vertices[1] = v1;
|
||||||
|
quad.vertices[2] = v2;
|
||||||
|
quad.vertices[3] = v3;
|
||||||
|
quad.material = material;
|
||||||
|
|
||||||
|
m_vecNegZQuads[regZ].push_back(quad);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||||
|
|
||||||
|
//m_faces[x][y][z][NegativeZ] = material;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Quad quad;
|
||||||
|
quad.vertices[0] = v0;
|
||||||
|
quad.vertices[1] = v3;
|
||||||
|
quad.vertices[2] = v2;
|
||||||
|
quad.vertices[3] = v1;
|
||||||
|
quad.material = material;
|
||||||
|
|
||||||
|
m_vecPosZQuads[regZ].push_back(quad);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||||
|
//m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||||
|
|
||||||
|
//m_faces[x][y][z-1][PositiveZ] = material;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_previousSliceVertices.swap(m_currentSliceVertices);
|
||||||
|
memset(m_currentSliceVertices.getRawData(), 0xff, m_currentSliceVertices.getNoOfElements() * sizeof(IndexAndMaterial));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32_t slice = 0; slice < m_vecNegXQuads.size(); slice++)
|
||||||
|
{
|
||||||
|
while(decimate(m_vecNegXQuads[slice])){}
|
||||||
|
|
||||||
|
for(std::list<Quad>::iterator quadIter = m_vecNegXQuads[slice].begin(); quadIter != m_vecNegXQuads[slice].end(); quadIter++)
|
||||||
|
{
|
||||||
|
//m_meshCurrent->addTriangleCubic(m_vecPosXIndices[slice][index], m_vecPosXIndices[slice][index+1], m_vecPosXIndices[slice][index+2]);
|
||||||
|
|
||||||
|
Quad quad = *quadIter;
|
||||||
|
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32_t slice = 0; slice < m_vecPosXQuads.size(); slice++)
|
||||||
|
{
|
||||||
|
while(decimate(m_vecPosXQuads[slice])){}
|
||||||
|
|
||||||
|
for(std::list<Quad>::iterator quadIter = m_vecPosXQuads[slice].begin(); quadIter != m_vecPosXQuads[slice].end(); quadIter++)
|
||||||
|
{
|
||||||
|
//m_meshCurrent->addTriangleCubic(m_vecPosXIndices[slice][index], m_vecPosXIndices[slice][index+1], m_vecPosXIndices[slice][index+2]);
|
||||||
|
|
||||||
|
Quad quad = *quadIter;
|
||||||
|
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32_t slice = 0; slice < m_vecNegYQuads.size(); slice++)
|
||||||
|
{
|
||||||
|
while(decimate(m_vecNegYQuads[slice])){}
|
||||||
|
|
||||||
|
for(std::list<Quad>::iterator quadIter = m_vecNegYQuads[slice].begin(); quadIter != m_vecNegYQuads[slice].end(); quadIter++)
|
||||||
|
{
|
||||||
|
//m_meshCurrent->addTriangleCubic(m_vecPosXIndices[slice][index], m_vecPosXIndices[slice][index+1], m_vecPosXIndices[slice][index+2]);
|
||||||
|
|
||||||
|
Quad quad = *quadIter;
|
||||||
|
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32_t slice = 0; slice < m_vecPosYQuads.size(); slice++)
|
||||||
|
{
|
||||||
|
while(decimate(m_vecPosYQuads[slice])){}
|
||||||
|
|
||||||
|
for(std::list<Quad>::iterator quadIter = m_vecPosYQuads[slice].begin(); quadIter != m_vecPosYQuads[slice].end(); quadIter++)
|
||||||
|
{
|
||||||
|
//m_meshCurrent->addTriangleCubic(m_vecPosXIndices[slice][index], m_vecPosXIndices[slice][index+1], m_vecPosXIndices[slice][index+2]);
|
||||||
|
|
||||||
|
Quad quad = *quadIter;
|
||||||
|
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32_t slice = 0; slice < m_vecNegZQuads.size(); slice++)
|
||||||
|
{
|
||||||
|
while(decimate(m_vecNegZQuads[slice])){}
|
||||||
|
|
||||||
|
for(std::list<Quad>::iterator quadIter = m_vecNegZQuads[slice].begin(); quadIter != m_vecNegZQuads[slice].end(); quadIter++)
|
||||||
|
{
|
||||||
|
//m_meshCurrent->addTriangleCubic(m_vecPosXIndices[slice][index], m_vecPosXIndices[slice][index+1], m_vecPosXIndices[slice][index+2]);
|
||||||
|
|
||||||
|
Quad quad = *quadIter;
|
||||||
|
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32_t slice = 0; slice < m_vecPosZQuads.size(); slice++)
|
||||||
|
{
|
||||||
|
while(decimate(m_vecPosZQuads[slice])){}
|
||||||
|
|
||||||
|
for(std::list<Quad>::iterator quadIter = m_vecPosZQuads[slice].begin(); quadIter != m_vecPosZQuads[slice].end(); quadIter++)
|
||||||
|
{
|
||||||
|
//m_meshCurrent->addTriangleCubic(m_vecPosXIndices[slice][index], m_vecPosXIndices[slice][index+1], m_vecPosXIndices[slice][index+2]);
|
||||||
|
|
||||||
|
Quad quad = *quadIter;
|
||||||
|
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[1],quad.vertices[2]);
|
||||||
|
m_meshCurrent->addTriangleCubic(quad.vertices[0], quad.vertices[2],quad.vertices[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_meshCurrent->m_Region = m_regSizeInVoxels;
|
||||||
|
|
||||||
|
m_meshCurrent->m_vecLodRecords.clear();
|
||||||
|
LodRecord lodRecord;
|
||||||
|
lodRecord.beginIndex = 0;
|
||||||
|
lodRecord.endIndex = m_meshCurrent->getNoOfIndices();
|
||||||
|
m_meshCurrent->m_vecLodRecords.push_back(lodRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
int32_t ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::addVertex(float fX, float fY, float fZ, uint8_t uMaterialIn, Array<3, IndexAndMaterial>& existingVertices)
|
||||||
|
{
|
||||||
|
uint32_t uX = static_cast<uint32_t>(fX + 0.75f);
|
||||||
|
uint32_t uY = static_cast<uint32_t>(fY + 0.75f);
|
||||||
|
|
||||||
|
for(uint32_t ct = 0; ct < MaxQuadsSharingVertex; ct++)
|
||||||
|
{
|
||||||
|
IndexAndMaterial& rEntry = existingVertices[uX][uY][ct];
|
||||||
|
|
||||||
|
int32_t iIndex = static_cast<int32_t>(rEntry.iIndex);
|
||||||
|
uint8_t uMaterial = static_cast<uint8_t>(rEntry.uMaterial);
|
||||||
|
|
||||||
|
//If we have an existing vertex and the material matches then we can return it.
|
||||||
|
if((iIndex != -1) && (uMaterial == uMaterialIn))
|
||||||
|
{
|
||||||
|
return iIndex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//No vertices matched and we've now hit an empty space. Fill it by creating a vertex.
|
||||||
|
uint32_t temp = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(fX, fY, fZ), uMaterialIn));
|
||||||
|
|
||||||
|
//Note - Slightly dodgy casting taking place here. No proper way to convert to 24-bit int though?
|
||||||
|
//If problematic in future then fix IndexAndMaterial to contain variables rather than bitfield.
|
||||||
|
rEntry.iIndex = temp;
|
||||||
|
rEntry.uMaterial = uMaterialIn;
|
||||||
|
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If we exit the loop here then apparently all the slots were full but none of
|
||||||
|
//them matched. I don't think this can happen so let's put an assert to make sure.
|
||||||
|
assert(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
bool ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::decimate(std::list<Quad>& quads)
|
||||||
|
{
|
||||||
|
for(std::list<Quad>::iterator outerIter = quads.begin(); outerIter != quads.end(); outerIter++)
|
||||||
|
{
|
||||||
|
std::list<Quad>::iterator innerIter = outerIter;
|
||||||
|
innerIter++;
|
||||||
|
while(innerIter != quads.end())
|
||||||
|
{
|
||||||
|
Quad q1 = *outerIter;
|
||||||
|
Quad q2 = *innerIter;
|
||||||
|
|
||||||
|
if(canMergeQuads(q1, q2))
|
||||||
|
{
|
||||||
|
//std::cout << "Can merge" << std::endl;
|
||||||
|
Quad result = mergeQuads(q1,q2);
|
||||||
|
|
||||||
|
quads.erase(innerIter);
|
||||||
|
quads.erase(outerIter);
|
||||||
|
|
||||||
|
quads.push_back(result);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
innerIter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
//std::cout << "Can not merge" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
Quad ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::mergeQuads(Quad q1, Quad q2)
|
||||||
|
{
|
||||||
|
/*Quad* pCurrentQuad = &q1;
|
||||||
|
Quad* pOtherQuad = &q2;
|
||||||
|
uint32_t uCurrentInputIndex = 0;
|
||||||
|
uint32_t uCurrentOutputIndex = 0;
|
||||||
|
|
||||||
|
Quad result;
|
||||||
|
result.material = q1.material;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
uint32_t uIndexInOtherQuad = quadContainsVertex(*pOtherQuad, (*(pCurrentQuad)).vertices[uCurrentInputIndex]);
|
||||||
|
if(uIndexInOtherQuad != -1)
|
||||||
|
{
|
||||||
|
std::swap(pCurrentQuad, pOtherQuad);
|
||||||
|
uCurrentInputIndex = (uIndexInOtherQuad + 1) % 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.vertices[uCurrentOutputIndex] = pCurrentQuad->vertices[uCurrentInputIndex];
|
||||||
|
uCurrentOutputIndex++;
|
||||||
|
uCurrentInputIndex = (uCurrentInputIndex + 1) % 4;
|
||||||
|
}
|
||||||
|
} while(uCurrentOutputIndex < 4);
|
||||||
|
|
||||||
|
return result;*/
|
||||||
|
|
||||||
|
Quad result;
|
||||||
|
result.material = q1.material;
|
||||||
|
|
||||||
|
for(uint32_t vertex = 0; vertex < 4; vertex++)
|
||||||
|
{
|
||||||
|
uint32_t quad1vertex = q1.vertices[vertex];
|
||||||
|
uint32_t quad2vertex = q2.vertices[vertex];
|
||||||
|
|
||||||
|
if(quadContainsVertex(q2, quad1vertex) != -1)
|
||||||
|
{
|
||||||
|
result.vertices[vertex] = quad2vertex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.vertices[vertex] = quad1vertex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
bool ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::canMergeQuads(Quad q1, Quad q2)
|
||||||
|
{
|
||||||
|
if(q1.material != q2.material)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t uNoOfMatchingVertices = 0;
|
||||||
|
for(uint32_t uQuad1Index = 0; uQuad1Index < 4; uQuad1Index++)
|
||||||
|
{
|
||||||
|
if(quadContainsVertex(q2, q1.vertices[uQuad1Index]) != -1)
|
||||||
|
{
|
||||||
|
uNoOfMatchingVertices++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uNoOfMatchingVertices == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< template<typename> class VolumeType, typename VoxelType>
|
||||||
|
int32_t ImprovedCubicSurfaceExtractor<VolumeType, VoxelType>::quadContainsVertex(const Quad& quad, uint32_t uVertexIndex)
|
||||||
|
{
|
||||||
|
for(uint32_t ct = 0; ct < 4; ct++)
|
||||||
|
{
|
||||||
|
if(quad.vertices[ct] == uVertexIndex)
|
||||||
|
{
|
||||||
|
//We've found a matching vertex.
|
||||||
|
return ct;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Vertex not found.
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user