Templatised SurfaceMesh class on vertex type.
Replaced 'SurfaceVertex' with PositionMaterial and PositionMaterialNormal classes. Different surface extractors can now work with different vertex types.
This commit is contained in:
@ -35,7 +35,7 @@ namespace PolyVox
|
||||
class CubicSurfaceExtractor
|
||||
{
|
||||
public:
|
||||
CubicSurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh* result);
|
||||
CubicSurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result);
|
||||
|
||||
void execute();
|
||||
|
||||
@ -45,7 +45,7 @@ namespace PolyVox
|
||||
VolumeSampler<VoxelType> m_sampVolume;
|
||||
|
||||
//The surface patch we are currently filling.
|
||||
SurfaceMesh* m_meshCurrent;
|
||||
SurfaceMesh<PositionMaterial>* m_meshCurrent;
|
||||
|
||||
//Information about the region we are currently processing
|
||||
Region m_regSizeInVoxels;
|
||||
|
@ -30,7 +30,7 @@ freely, subject to the following restrictions:
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
CubicSurfaceExtractor<VoxelType>::CubicSurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh* result)
|
||||
CubicSurfaceExtractor<VoxelType>::CubicSurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterial>* result)
|
||||
:m_volData(volData)
|
||||
,m_sampVolume(volData)
|
||||
,m_regSizeInVoxels(region)
|
||||
@ -63,25 +63,25 @@ namespace PolyVox
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
|
||||
m_meshCurrent->addTriangle(v0,v2,v1);
|
||||
m_meshCurrent->addTriangle(v1,v2,v3);
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
if(currentVoxel < plusXVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x+1,y,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
|
||||
m_meshCurrent->addTriangle(v0,v1,v2);
|
||||
m_meshCurrent->addTriangle(v1,v3,v2);
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
|
||||
int plusYVoxel = m_volData->getVoxelAt(x,y+1,z).getDensity() >= VoxelType::getThreshold();
|
||||
@ -89,25 +89,25 @@ namespace PolyVox
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), material));
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
|
||||
m_meshCurrent->addTriangle(v0,v1,v2);
|
||||
m_meshCurrent->addTriangle(v1,v3,v2);
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
if(currentVoxel < plusYVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y+1,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), material));
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
|
||||
m_meshCurrent->addTriangle(v0,v2,v1);
|
||||
m_meshCurrent->addTriangle(v1,v2,v3);
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
|
||||
int plusZVoxel = m_volData->getVoxelAt(x,y,z+1).getDensity() >= VoxelType::getThreshold();
|
||||
@ -115,25 +115,25 @@ namespace PolyVox
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), material));
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
|
||||
m_meshCurrent->addTriangle(v0,v2,v1);
|
||||
m_meshCurrent->addTriangle(v1,v2,v3);
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
if(currentVoxel < plusZVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y,z+1).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(SurfaceVertex(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), material));
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterial(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), material));
|
||||
|
||||
m_meshCurrent->addTriangle(v0,v1,v2);
|
||||
m_meshCurrent->addTriangle(v1,v3,v2);
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
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_CubicSurfaceExtractorWithNormals_H__
|
||||
#define __PolyVox_CubicSurfaceExtractorWithNormals_H__
|
||||
|
||||
#include "PolyVoxForwardDeclarations.h"
|
||||
#include "VolumeSampler.h"
|
||||
|
||||
#include "PolyVoxImpl/TypeDef.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
class CubicSurfaceExtractorWithNormals
|
||||
{
|
||||
public:
|
||||
CubicSurfaceExtractorWithNormals(Volume<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result);
|
||||
|
||||
void execute();
|
||||
|
||||
private:
|
||||
//The volume data and a sampler to access it.
|
||||
Volume<VoxelType>* m_volData;
|
||||
VolumeSampler<VoxelType> m_sampVolume;
|
||||
|
||||
//The surface patch we are currently filling.
|
||||
SurfaceMesh<PositionMaterialNormal>* m_meshCurrent;
|
||||
|
||||
//Information about the region we are currently processing
|
||||
Region m_regSizeInVoxels;
|
||||
Region m_regSizeInCells;
|
||||
};
|
||||
}
|
||||
|
||||
#include "CubicSurfaceExtractorWithNormals.inl"
|
||||
|
||||
#endif
|
150
library/PolyVoxCore/include/CubicSurfaceExtractorWithNormals.inl
Normal file
150
library/PolyVoxCore/include/CubicSurfaceExtractorWithNormals.inl
Normal file
@ -0,0 +1,150 @@
|
||||
/*******************************************************************************
|
||||
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 "SurfaceVertex.h"
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
CubicSurfaceExtractorWithNormals<VoxelType>::CubicSurfaceExtractorWithNormals(Volume<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result)
|
||||
:m_volData(volData)
|
||||
,m_sampVolume(volData)
|
||||
,m_regSizeInVoxels(region)
|
||||
,m_meshCurrent(result)
|
||||
{
|
||||
m_regSizeInVoxels.cropTo(m_volData->getEnclosingRegion());
|
||||
m_regSizeInCells = m_regSizeInVoxels;
|
||||
m_regSizeInCells.setUpperCorner(m_regSizeInCells.getUpperCorner() - Vector3DInt16(1,1,1));
|
||||
|
||||
m_meshCurrent->clear();
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
void CubicSurfaceExtractorWithNormals<VoxelType>::execute()
|
||||
{
|
||||
for(uint16_t z = m_regSizeInVoxels.getLowerCorner().getZ(); z < m_regSizeInVoxels.getUpperCorner().getZ(); z++)
|
||||
{
|
||||
for(uint16_t y = m_regSizeInVoxels.getLowerCorner().getY(); y < m_regSizeInVoxels.getUpperCorner().getY(); y++)
|
||||
{
|
||||
for(uint16_t x = m_regSizeInVoxels.getLowerCorner().getX(); x < m_regSizeInVoxels.getUpperCorner().getX(); x++)
|
||||
{
|
||||
uint16_t regX = x - m_regSizeInVoxels.getLowerCorner().getX();
|
||||
uint16_t regY = y - m_regSizeInVoxels.getLowerCorner().getY();
|
||||
uint16_t regZ = z - m_regSizeInVoxels.getLowerCorner().getZ();
|
||||
|
||||
int currentVoxel = m_volData->getVoxelAt(x,y,z).getDensity() >= VoxelType::getThreshold();
|
||||
|
||||
int plusXVoxel = m_volData->getVoxelAt(x+1,y,z).getDensity() >= VoxelType::getThreshold();
|
||||
if(currentVoxel > plusXVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(1.0f, 0.0f, 0.0f), material));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
if(currentVoxel < plusXVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x+1,y,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(-1.0f, 0.0f, 0.0f), material));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
|
||||
int plusYVoxel = m_volData->getVoxelAt(x,y+1,z).getDensity() >= VoxelType::getThreshold();
|
||||
if(currentVoxel > plusYVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 1.0f, 0.0f), material));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
if(currentVoxel < plusYVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y+1,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ - 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, -1.0f, 0.0f), material));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
|
||||
int plusZVoxel = m_volData->getVoxelAt(x,y,z+1).getDensity() >= VoxelType::getThreshold();
|
||||
if(currentVoxel > plusZVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y,z).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, 1.0f), material));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v2,v1);
|
||||
m_meshCurrent->addTriangleCubic(v1,v2,v3);
|
||||
}
|
||||
if(currentVoxel < plusZVoxel)
|
||||
{
|
||||
int material = m_volData->getVoxelAt(x,y,z+1).getMaterial();
|
||||
|
||||
uint32_t v0 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), material));
|
||||
uint32_t v1 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX - 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), material));
|
||||
uint32_t v2 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY - 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), material));
|
||||
uint32_t v3 = m_meshCurrent->addVertex(PositionMaterialNormal(Vector3DFloat(regX + 0.5f, regY + 0.5f, regZ + 0.5f), Vector3DFloat(0.0f, 0.0f, -1.0f), material));
|
||||
|
||||
m_meshCurrent->addTriangleCubic(v0,v1,v2);
|
||||
m_meshCurrent->addTriangleCubic(v1,v3,v2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@ -55,7 +55,7 @@ namespace PolyVox
|
||||
template <typename VoxelType>
|
||||
Vector3DFloat computeSmoothSobelGradient(VolumeSampler<VoxelType>& volIter);
|
||||
|
||||
POLYVOXCORE_API void computeNormalsForVertices(Volume<uint8_t>* volumeData, SurfaceMesh& mesh, NormalGenerationMethod normalGenerationMethod);
|
||||
POLYVOXCORE_API void computeNormalsForVertices(Volume<uint8_t>* volumeData, SurfaceMesh<PositionMaterialNormal>& mesh, NormalGenerationMethod normalGenerationMethod);
|
||||
POLYVOXCORE_API Vector3DFloat computeNormal(Volume<uint8_t>* volumeData, const Vector3DFloat& v3dPos, NormalGenerationMethod normalGenerationMethod);
|
||||
}
|
||||
|
||||
|
@ -38,8 +38,8 @@ namespace PolyVox
|
||||
{
|
||||
public:
|
||||
|
||||
void buildFromMesh(SurfaceMesh* pMesh);
|
||||
void fillMesh(SurfaceMesh* pMesh);
|
||||
void buildFromMesh(SurfaceMesh<PositionMaterialNormal>* pMesh);
|
||||
void fillMesh(SurfaceMesh<PositionMaterialNormal>* pMesh);
|
||||
void matchEdgePairs(void);
|
||||
void computeEdgeCosts(void);
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace PolyVox
|
||||
{
|
||||
public:
|
||||
MeshVertex();
|
||||
SurfaceVertex m_vertexData;
|
||||
PositionMaterialNormal m_vertexData;
|
||||
//MeshEdge* m_pEdge;
|
||||
//std::set<MeshFace*> m_faces;
|
||||
//std::set<MeshEdge*> m_edges; //Edges which have this vertex as the src
|
||||
|
@ -77,9 +77,10 @@ namespace PolyVox
|
||||
template <typename Type, uint8_t NoOfMaterialBits, uint8_t NoOfDensityBits> class MaterialDensityPair;
|
||||
typedef MaterialDensityPair<uint8_t, 4, 4> MaterialDensityPair44;
|
||||
|
||||
class SurfaceMesh;
|
||||
template <typename VertexType> class SurfaceMesh;
|
||||
class Region;
|
||||
class SurfaceVertex;
|
||||
class PositionMaterial;
|
||||
class PositionMaterialNormal;
|
||||
template <typename VoxelType> class CubicSurfaceExtractor;
|
||||
template <typename VoxelType> class SurfaceExtractor;
|
||||
|
||||
|
@ -35,7 +35,7 @@ namespace PolyVox
|
||||
class SurfaceExtractor
|
||||
{
|
||||
public:
|
||||
SurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh* result);
|
||||
SurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result);
|
||||
|
||||
void execute();
|
||||
|
||||
@ -84,7 +84,7 @@ namespace PolyVox
|
||||
uint32_t m_uNoOfOccupiedCells;
|
||||
|
||||
//The surface patch we are currently filling.
|
||||
SurfaceMesh* m_meshCurrent;
|
||||
SurfaceMesh<PositionMaterialNormal>* m_meshCurrent;
|
||||
|
||||
//Information about the region we are currently processing
|
||||
Region m_regSizeInVoxels;
|
||||
|
@ -30,7 +30,7 @@ freely, subject to the following restrictions:
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VoxelType>
|
||||
SurfaceExtractor<VoxelType>::SurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh* result)
|
||||
SurfaceExtractor<VoxelType>::SurfaceExtractor(Volume<VoxelType>* volData, Region region, SurfaceMesh<PositionMaterialNormal>* result)
|
||||
:m_volData(volData)
|
||||
,m_sampVolume(volData)
|
||||
,m_regSizeInVoxels(region)
|
||||
@ -457,7 +457,7 @@ namespace PolyVox
|
||||
|
||||
const uint8_t uMaterial = v000.getMaterial() | v100.getMaterial(); //Because one of these is 0, the or operation takes the max.
|
||||
|
||||
SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
||||
PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
||||
//surfaceVertex.setOnGeometryEdge(isXEdge || isYEdge || isZEdge);
|
||||
surfaceVertex.setOnGeometryEdgeNegX(isNegXEdge);
|
||||
surfaceVertex.setOnGeometryEdgePosX(isPosXEdge);
|
||||
@ -487,7 +487,7 @@ namespace PolyVox
|
||||
|
||||
const uint8_t uMaterial = v000.getMaterial() | v010.getMaterial(); //Because one of these is 0, the or operation takes the max.
|
||||
|
||||
SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
||||
PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
||||
//surfaceVertex.setOnGeometryEdge(isXEdge || isYEdge || isZEdge);
|
||||
surfaceVertex.setOnGeometryEdgeNegX(isNegXEdge);
|
||||
surfaceVertex.setOnGeometryEdgePosX(isPosXEdge);
|
||||
@ -517,7 +517,7 @@ namespace PolyVox
|
||||
|
||||
const uint8_t uMaterial = v000.getMaterial() | v001.getMaterial(); //Because one of these is 0, the or operation takes the max.
|
||||
|
||||
SurfaceVertex surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
||||
PositionMaterialNormal surfaceVertex(v3dPosition, v3dNormal, uMaterial);
|
||||
//surfaceVertex.setOnGeometryEdge(isXEdge || isYEdge || isZEdge);
|
||||
surfaceVertex.setOnGeometryEdgeNegX(isNegXEdge);
|
||||
surfaceVertex.setOnGeometryEdgePosX(isPosXEdge);
|
||||
|
@ -42,7 +42,8 @@ namespace PolyVox
|
||||
int endIndex; //Let's put it just past the end STL style
|
||||
};
|
||||
|
||||
class POLYVOXCORE_API SurfaceMesh
|
||||
template <typename VertexType>
|
||||
class SurfaceMesh
|
||||
{
|
||||
public:
|
||||
SurfaceMesh();
|
||||
@ -53,26 +54,21 @@ namespace PolyVox
|
||||
uint32_t getNoOfNonUniformTrianges(void) const;
|
||||
uint32_t getNoOfUniformTrianges(void) const;
|
||||
uint32_t getNoOfVertices(void) const;
|
||||
std::vector<SurfaceVertex>& getRawVertexData(void); //FIXME - this should be removed
|
||||
const std::vector<SurfaceVertex>& getVertices(void) const;
|
||||
std::vector<VertexType>& getRawVertexData(void); //FIXME - this should be removed
|
||||
const std::vector<VertexType>& getVertices(void) const;
|
||||
|
||||
void addTriangle(uint32_t index0, uint32_t index1, uint32_t index2);
|
||||
uint32_t addVertex(const SurfaceVertex& vertex);
|
||||
void addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2);
|
||||
uint32_t addVertex(const VertexType& vertex);
|
||||
void clear(void);
|
||||
const bool isEmpty(void) const;
|
||||
|
||||
void smoothPositions(float fAmount, bool bIncludeGeometryEdgeVertices = false);
|
||||
void sumNearbyNormals(bool bNormaliseResult = true);
|
||||
|
||||
polyvox_shared_ptr<SurfaceMesh> extractSubset(std::set<uint8_t> setMaterials);
|
||||
polyvox_shared_ptr< SurfaceMesh<VertexType> > extractSubset(std::set<uint8_t> setMaterials);
|
||||
|
||||
void generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices = false);
|
||||
|
||||
|
||||
//Vector3DInt32 m_v3dRegionPosition; //FIXME - remove this?
|
||||
|
||||
/*void growMaterialBoundary(void);
|
||||
int countMaterialBoundary(void);*/
|
||||
|
||||
bool isSubset(std::bitset<VF_NO_OF_FLAGS> a, std::bitset<VF_NO_OF_FLAGS> b);
|
||||
|
||||
@ -90,7 +86,7 @@ namespace PolyVox
|
||||
|
||||
public:
|
||||
std::vector<uint32_t> m_vecTriangleIndices;
|
||||
std::vector<SurfaceVertex> m_vecVertices;
|
||||
std::vector<VertexType> m_vecVertices;
|
||||
|
||||
std::vector<LodRecord> m_vecLodRecords;
|
||||
|
||||
@ -107,4 +103,6 @@ namespace PolyVox
|
||||
};
|
||||
}
|
||||
|
||||
#include "SurfaceMesh.inl"
|
||||
|
||||
#endif /* __SurfaceMesh_H__ */
|
||||
|
862
library/PolyVoxCore/include/SurfaceMesh.inl
Normal file
862
library/PolyVoxCore/include/SurfaceMesh.inl
Normal file
@ -0,0 +1,862 @@
|
||||
/*******************************************************************************
|
||||
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 <cstdlib>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace PolyVox
|
||||
{
|
||||
template <typename VertexType>
|
||||
SurfaceMesh<VertexType>::SurfaceMesh()
|
||||
{
|
||||
m_iTimeStamp = -1;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
SurfaceMesh<VertexType>::~SurfaceMesh()
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
const std::vector<uint32_t>& SurfaceMesh<VertexType>::getIndices(void) const
|
||||
{
|
||||
return m_vecTriangleIndices;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::getNoOfIndices(void) const
|
||||
{
|
||||
return m_vecTriangleIndices.size();
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::getNoOfNonUniformTrianges(void) const
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3)
|
||||
{
|
||||
if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial())
|
||||
&& (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial()))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::getNoOfUniformTrianges(void) const
|
||||
{
|
||||
uint32_t result = 0;
|
||||
for(uint32_t i = 0; i < m_vecTriangleIndices.size() - 2; i += 3)
|
||||
{
|
||||
if((m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+1]].getMaterial())
|
||||
&& (m_vecVertices[m_vecTriangleIndices[i]].getMaterial() == m_vecVertices[m_vecTriangleIndices[i+2]].getMaterial()))
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::getNoOfVertices(void) const
|
||||
{
|
||||
return m_vecVertices.size();
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
std::vector<VertexType>& SurfaceMesh<VertexType>::getRawVertexData(void)
|
||||
{
|
||||
return m_vecVertices;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
const std::vector<VertexType>& SurfaceMesh<VertexType>::getVertices(void) const
|
||||
{
|
||||
return m_vecVertices;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::addTriangle(uint32_t index0, uint32_t index1, uint32_t index2)
|
||||
{
|
||||
m_vecTriangleIndices.push_back(index0);
|
||||
m_vecTriangleIndices.push_back(index1);
|
||||
m_vecTriangleIndices.push_back(index2);
|
||||
|
||||
if((m_vecVertices[index0].material == m_vecVertices[index1].material) && (m_vecVertices[index0].material == m_vecVertices[index2].material))
|
||||
{
|
||||
m_mapUsedMaterials.insert(m_vecVertices[index0].material);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_vecVertices[index0].setOnMaterialEdge(true);
|
||||
m_vecVertices[index1].setOnMaterialEdge(true);
|
||||
m_vecVertices[index2].setOnMaterialEdge(true);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::addTriangleCubic(uint32_t index0, uint32_t index1, uint32_t index2)
|
||||
{
|
||||
m_vecTriangleIndices.push_back(index0);
|
||||
m_vecTriangleIndices.push_back(index1);
|
||||
m_vecTriangleIndices.push_back(index2);
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::addVertex(const VertexType& vertex)
|
||||
{
|
||||
m_vecVertices.push_back(vertex);
|
||||
return m_vecVertices.size() - 1;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::clear(void)
|
||||
{
|
||||
m_vecVertices.clear();
|
||||
m_vecTriangleIndices.clear();
|
||||
m_vecLodRecords.clear();
|
||||
m_mapUsedMaterials.clear();
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
const bool SurfaceMesh<VertexType>::isEmpty(void) const
|
||||
{
|
||||
return (getNoOfVertices() == 0) || (getNoOfIndices() == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The function works on a per triangle basis without any need for connectivity
|
||||
/// information. It determines whether a triangle is lying on a flat or curved
|
||||
/// section of the surface patch by examining the normals - therefore these
|
||||
/// 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 bIncludeGeometryEdgeVertices Indicates whether vertices on the edge of an
|
||||
/// SurfaceMesh should be smoothed. This can cause dicontinuities between
|
||||
/// neighbouring patches.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::smoothPositions(float fAmount, bool bIncludeGeometryEdgeVertices)
|
||||
{
|
||||
if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise...
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//This will hold the new positions, and is initialised with the current positions.
|
||||
std::vector<Vector3DFloat> newPositions(m_vecVertices.size());
|
||||
for(uint32_t uIndex = 0; uIndex < newPositions.size(); uIndex++)
|
||||
{
|
||||
newPositions[uIndex] = m_vecVertices[uIndex].getPosition();
|
||||
}
|
||||
|
||||
//Iterate over each triangle
|
||||
for(vector<uint32_t>::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();)
|
||||
{
|
||||
//Get the vertex data for the triangle
|
||||
PositionMaterialNormal& v0 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v0New = newPositions[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v1 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v1New = newPositions[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v2 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v2New = newPositions[*iterIndex];
|
||||
iterIndex++;
|
||||
|
||||
//Find the midpoint
|
||||
Vector3DFloat v3dMidpoint = (v0.position + v1.position + v2.position) / 3.0f;
|
||||
|
||||
//Vectors from vertex to midpoint
|
||||
Vector3DFloat v0ToMidpoint = v3dMidpoint - v0.position;
|
||||
Vector3DFloat v1ToMidpoint = v3dMidpoint - v1.position;
|
||||
Vector3DFloat v2ToMidpoint = v3dMidpoint - v2.position;
|
||||
|
||||
//Get the vertex normals
|
||||
Vector3DFloat n0 = v0.getNormal();
|
||||
Vector3DFloat n1 = v1.getNormal();
|
||||
Vector3DFloat n2 = v2.getNormal();
|
||||
|
||||
//I don't think these normalisation are necessary... and could be slow.
|
||||
//Normals should be normalised anyway, and as long as all triangles are
|
||||
//about the same size the distances to midpoint should be similar too.
|
||||
//v0ToMidpoint.normalise();
|
||||
//v1ToMidpoint.normalise();
|
||||
//v2ToMidpoint.normalise();
|
||||
//n0.normalise();
|
||||
//n1.normalise();
|
||||
//n2.normalise();
|
||||
|
||||
//If the dot product is zero the the normals are perpendicular
|
||||
//to the triangle, hence the positions do not move.
|
||||
v0New += (n0 * (n0.dot(v0ToMidpoint)) * fAmount);
|
||||
v1New += (n1 * (n1.dot(v1ToMidpoint)) * fAmount);
|
||||
v2New += (n2 * (n2.dot(v2ToMidpoint)) * fAmount);
|
||||
}
|
||||
|
||||
//Update with the new positions
|
||||
for(uint32_t uIndex = 0; uIndex < newPositions.size(); uIndex++)
|
||||
{
|
||||
if((bIncludeGeometryEdgeVertices) || (m_vecVertices[uIndex].isOnGeometryEdge() == false))
|
||||
{
|
||||
m_vecVertices[uIndex].setPosition(newPositions[uIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// This function can help improve the visual appearance of a surface patch by
|
||||
/// smoothing normals with other nearby normals. It iterates over each triangle
|
||||
/// in the surface patch and determines the sum of its corners normals. For any
|
||||
/// given vertex, these sums are in turn summed for any triangles which use the
|
||||
/// vertex. Usually, the resulting normals should be renormalised afterwards.
|
||||
/// Note: This function can cause lighting discontinuities accross region boundaries.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::sumNearbyNormals(bool bNormaliseResult)
|
||||
{
|
||||
if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise...
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Vector3DFloat> summedNormals(m_vecVertices.size());
|
||||
|
||||
//Initialise all normals to zero. Should be ok as the vector should store all elements contiguously.
|
||||
memset(&summedNormals[0], 0, summedNormals.size() * sizeof(Vector3DFloat));
|
||||
|
||||
for(vector<uint32_t>::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();)
|
||||
{
|
||||
PositionMaterialNormal& v0 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v0New = summedNormals[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v1 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v1New = summedNormals[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v2 = m_vecVertices[*iterIndex];
|
||||
Vector3DFloat& v2New = summedNormals[*iterIndex];
|
||||
iterIndex++;
|
||||
|
||||
Vector3DFloat sumOfNormals = v0.getNormal() + v1.getNormal() + v2.getNormal();
|
||||
|
||||
v0New += sumOfNormals;
|
||||
v1New += sumOfNormals;
|
||||
v2New += sumOfNormals;
|
||||
}
|
||||
|
||||
for(uint32_t uIndex = 0; uIndex < summedNormals.size(); uIndex++)
|
||||
{
|
||||
if(bNormaliseResult)
|
||||
{
|
||||
summedNormals[uIndex].normalise();
|
||||
}
|
||||
m_vecVertices[uIndex].setNormal(summedNormals[uIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::generateAveragedFaceNormals(bool bNormalise, bool bIncludeEdgeVertices)
|
||||
{
|
||||
Vector3DFloat offset = static_cast<Vector3DFloat>(m_Region.getLowerCorner());
|
||||
|
||||
//Initially zero the normals
|
||||
for(vector<PositionMaterialNormal>::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++)
|
||||
{
|
||||
if(m_Region.containsPoint(iterVertex->getPosition() + offset, 0.001))
|
||||
{
|
||||
iterVertex->setNormal(Vector3DFloat(0.0f,0.0f,0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
for(vector<uint32_t>::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();)
|
||||
{
|
||||
PositionMaterialNormal& v0 = m_vecVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v1 = m_vecVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v2 = m_vecVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
|
||||
Vector3DFloat triangleNormal = (v1.getPosition()-v0.getPosition()).cross(v2.getPosition()-v0.getPosition());
|
||||
|
||||
if(m_Region.containsPoint(v0.getPosition() + offset, 0.001))
|
||||
{
|
||||
v0.setNormal(v0.getNormal() + triangleNormal);
|
||||
}
|
||||
if(m_Region.containsPoint(v1.getPosition() + offset, 0.001))
|
||||
{
|
||||
v1.setNormal(v1.getNormal() + triangleNormal);
|
||||
}
|
||||
if(m_Region.containsPoint(v2.getPosition() + offset, 0.001))
|
||||
{
|
||||
v2.setNormal(v2.getNormal() + triangleNormal);
|
||||
}
|
||||
}
|
||||
|
||||
if(bNormalise)
|
||||
{
|
||||
for(vector<PositionMaterialNormal>::iterator iterVertex = m_vecVertices.begin(); iterVertex != m_vecVertices.end(); iterVertex++)
|
||||
{
|
||||
Vector3DFloat normal = iterVertex->getNormal();
|
||||
normal.normalise();
|
||||
iterVertex->setNormal(normal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//This function looks at every vertex in the mesh and determines
|
||||
//how many of it's neighbours have the same material.
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::countNoOfNeighboursUsingMaterial(void)
|
||||
{
|
||||
//Find all the neighbouring vertices for each vertex
|
||||
std::vector< std::set<int> > neighbouringVertices(m_vecVertices.size());
|
||||
for(int triCt = 0; triCt < m_vecTriangleIndices.size() / 3; triCt++)
|
||||
{
|
||||
int v0 = m_vecTriangleIndices[(triCt * 3 + 0)];
|
||||
int v1 = m_vecTriangleIndices[(triCt * 3 + 1)];
|
||||
int v2 = m_vecTriangleIndices[(triCt * 3 + 2)];
|
||||
|
||||
neighbouringVertices[v0].insert(v1);
|
||||
neighbouringVertices[v0].insert(v2);
|
||||
|
||||
neighbouringVertices[v1].insert(v0);
|
||||
neighbouringVertices[v1].insert(v2);
|
||||
|
||||
neighbouringVertices[v2].insert(v0);
|
||||
neighbouringVertices[v2].insert(v1);
|
||||
}
|
||||
|
||||
//For each vertex, check how many neighbours have the same material
|
||||
m_vecNoOfNeighboursUsingMaterial.resize(m_vecVertices.size());
|
||||
for(int vertCt = 0; vertCt < m_vecVertices.size(); vertCt++)
|
||||
{
|
||||
m_vecNoOfNeighboursUsingMaterial[vertCt] = 0;
|
||||
for(std::set<int>::iterator iter = neighbouringVertices[vertCt].begin(); iter != neighbouringVertices[vertCt].end(); iter++)
|
||||
{
|
||||
if(m_vecVertices[vertCt].getMaterial() == m_vecVertices[*iter].getMaterial())
|
||||
{
|
||||
m_vecNoOfNeighboursUsingMaterial[vertCt]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
polyvox_shared_ptr< SurfaceMesh<VertexType> > SurfaceMesh<VertexType>::extractSubset(std::set<uint8_t> setMaterials)
|
||||
{
|
||||
polyvox_shared_ptr< SurfaceMesh<VertexType> > result(new SurfaceMesh<VertexType>);
|
||||
|
||||
if(m_vecVertices.size() == 0) //FIXME - I don't think we should need this test, but I have seen crashes otherwise...
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
assert(m_vecLodRecords.size() == 1);
|
||||
if(m_vecLodRecords.size() != 1)
|
||||
{
|
||||
//If we have done progressive LOD then it's too late to split into subsets.
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<int32_t> indexMap(m_vecVertices.size());
|
||||
std::fill(indexMap.begin(), indexMap.end(), -1);
|
||||
|
||||
for(uint32_t triCt = 0; triCt < m_vecTriangleIndices.size(); triCt += 3)
|
||||
{
|
||||
|
||||
PositionMaterialNormal& v0 = m_vecVertices[m_vecTriangleIndices[triCt]];
|
||||
PositionMaterialNormal& v1 = m_vecVertices[m_vecTriangleIndices[triCt + 1]];
|
||||
PositionMaterialNormal& v2 = m_vecVertices[m_vecTriangleIndices[triCt + 2]];
|
||||
|
||||
if(
|
||||
(setMaterials.find(v0.getMaterial()) != setMaterials.end()) ||
|
||||
(setMaterials.find(v1.getMaterial()) != setMaterials.end()) ||
|
||||
(setMaterials.find(v2.getMaterial()) != setMaterials.end()))
|
||||
{
|
||||
uint32_t i0;
|
||||
if(indexMap[m_vecTriangleIndices[triCt]] == -1)
|
||||
{
|
||||
indexMap[m_vecTriangleIndices[triCt]] = result->addVertex(v0);
|
||||
}
|
||||
i0 = indexMap[m_vecTriangleIndices[triCt]];
|
||||
|
||||
uint32_t i1;
|
||||
if(indexMap[m_vecTriangleIndices[triCt+1]] == -1)
|
||||
{
|
||||
indexMap[m_vecTriangleIndices[triCt+1]] = result->addVertex(v1);
|
||||
}
|
||||
i1 = indexMap[m_vecTriangleIndices[triCt+1]];
|
||||
|
||||
uint32_t i2;
|
||||
if(indexMap[m_vecTriangleIndices[triCt+2]] == -1)
|
||||
{
|
||||
indexMap[m_vecTriangleIndices[triCt+2]] = result->addVertex(v2);
|
||||
}
|
||||
i2 = indexMap[m_vecTriangleIndices[triCt+2]];
|
||||
|
||||
result->addTriangle(i0,i1,i2);
|
||||
}
|
||||
}
|
||||
|
||||
result->m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = result->getNoOfIndices();
|
||||
result->m_vecLodRecords.push_back(lodRecord);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*int SurfaceMesh::countMaterialBoundary(void)
|
||||
{
|
||||
int count = 0;
|
||||
for(int ct = 0; ct < m_vecVertices.size(); ct++)
|
||||
{
|
||||
if(m_vecVertices[ct].m_bIsMaterialEdgeVertex)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void SurfaceMesh::growMaterialBoundary(void)
|
||||
{
|
||||
std::vector<PositionMaterialNormal> vecNewVertices = m_vecVertices;
|
||||
|
||||
for(vector<uint32_t>::iterator iterIndex = m_vecTriangleIndices.begin(); iterIndex != m_vecTriangleIndices.end();)
|
||||
{
|
||||
PositionMaterialNormal& v0 = m_vecVertices[*iterIndex];
|
||||
PositionMaterialNormal& v0New = vecNewVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v1 = m_vecVertices[*iterIndex];
|
||||
PositionMaterialNormal& v1New = vecNewVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
PositionMaterialNormal& v2 = m_vecVertices[*iterIndex];
|
||||
PositionMaterialNormal& v2New = vecNewVertices[*iterIndex];
|
||||
iterIndex++;
|
||||
|
||||
if(v0.m_bIsMaterialEdgeVertex || v1.m_bIsMaterialEdgeVertex || v2.m_bIsMaterialEdgeVertex)
|
||||
{
|
||||
v0New.m_bIsMaterialEdgeVertex = true;
|
||||
v1New.m_bIsMaterialEdgeVertex = true;
|
||||
v2New.m_bIsMaterialEdgeVertex = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_vecVertices = vecNewVertices;
|
||||
}*/
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::decimate(float fMinDotProductForCollapse)
|
||||
{
|
||||
// We will need the information from this function to
|
||||
// determine when material boundary edges can collapse.
|
||||
countNoOfNeighboursUsingMaterial();
|
||||
|
||||
uint32_t noOfEdgesCollapsed;
|
||||
do
|
||||
{
|
||||
noOfEdgesCollapsed = performDecimationPass(fMinDotProductForCollapse);
|
||||
removeDegenerateTris();
|
||||
}while(noOfEdgesCollapsed > 0);
|
||||
|
||||
//Decimation will have invalidated LOD levels.
|
||||
m_vecLodRecords.clear();
|
||||
LodRecord lodRecord;
|
||||
lodRecord.beginIndex = 0;
|
||||
lodRecord.endIndex = getNoOfIndices();
|
||||
m_vecLodRecords.push_back(lodRecord);
|
||||
}
|
||||
|
||||
// Returns true if every bit which is set in 'a' is also set in 'b'. The reverse does not need to be true.
|
||||
template <typename VertexType>
|
||||
bool SurfaceMesh<VertexType>::isSubset(std::bitset<VF_NO_OF_FLAGS> a, std::bitset<VF_NO_OF_FLAGS> b)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
for(int ct = 1; ct < 7; ct++) //Start at '1' to skip material flag
|
||||
{
|
||||
if(a.test(ct))
|
||||
{
|
||||
if(b.test(ct) == false)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
uint32_t SurfaceMesh<VertexType>::performDecimationPass(float fMinDotProductForCollapse)
|
||||
{
|
||||
// I'm using a vector of lists here, rather than a vector of sets,
|
||||
// because I don't believe that duplicaes should occur. But this
|
||||
// might be worth checking if we have problems in the future.
|
||||
vector< list<uint32_t> > trianglesUsingVertex(m_vecVertices.size());
|
||||
for(int ct = 0; ct < m_vecTriangleIndices.size(); ct++)
|
||||
{
|
||||
int triangle = ct / 3;
|
||||
|
||||
trianglesUsingVertex[m_vecTriangleIndices[ct]].push_back(triangle);
|
||||
}
|
||||
|
||||
// Count how many edges we have collapsed
|
||||
uint32_t noOfEdgesCollapsed = 0;
|
||||
|
||||
// The vertex mapper track whick vertices collapse onto which.
|
||||
vector<uint32_t> vertexMapper(m_vecVertices.size());
|
||||
|
||||
// Once a vertex is involved in a collapse (either because it
|
||||
// moves onto a different vertex, or because a different vertex
|
||||
// moves onto it) it is forbidden to take part in another collapse
|
||||
// this pass. We enforce this by setting the vertex locked flag.
|
||||
vector<bool> vertexLocked(m_vecVertices.size());
|
||||
|
||||
// Initialise the vectors
|
||||
for(uint32_t ct = 0; ct < m_vecVertices.size(); ct++)
|
||||
{
|
||||
// Initiall all vertices points to themselves
|
||||
vertexMapper[ct] = ct;
|
||||
// All vertices are initially unlocked
|
||||
vertexLocked[ct] = false;
|
||||
}
|
||||
|
||||
|
||||
// Each triangle exists in this vector once.
|
||||
vector<int> vecOfTriCts(m_vecTriangleIndices.size() / 3);
|
||||
for(int triCt = 0; triCt < vecOfTriCts.size(); triCt++)
|
||||
{
|
||||
vecOfTriCts[triCt] = triCt;
|
||||
}
|
||||
|
||||
// It *may* be beneficial to randomise the order in which triangles
|
||||
// are processed to get a more uniform distribution off collapses and
|
||||
// more equally sized triangles at the end. This need more testing really.
|
||||
random_shuffle(vecOfTriCts.begin(), vecOfTriCts.end());
|
||||
|
||||
//For each triange...
|
||||
for(int ctIter = 0; ctIter < vecOfTriCts.size(); ctIter++)
|
||||
{
|
||||
int triCt = vecOfTriCts[ctIter];
|
||||
|
||||
//For each edge in each triangle
|
||||
for(int edgeCt = 0; edgeCt < 3; edgeCt++)
|
||||
{
|
||||
int v0 = m_vecTriangleIndices[triCt * 3 + (edgeCt)];
|
||||
int v1 = m_vecTriangleIndices[triCt * 3 + ((edgeCt +1) % 3)];
|
||||
|
||||
//A vertex will be locked if it has already been involved in a collapse this pass.
|
||||
if(vertexLocked[v0] || vertexLocked[v1])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(m_vecVertices[v0].getMaterial() != m_vecVertices[v1].getMaterial())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//For now, don't collapse vertices on material edges...
|
||||
if(m_vecVertices[v0].isOnMaterialEdge() || m_vecVertices[v1].isOnMaterialEdge())
|
||||
{
|
||||
if(true)
|
||||
{
|
||||
bool pass = false;
|
||||
|
||||
bool allMatch = false;
|
||||
|
||||
// On the original undecimated mesh a material boundary vertex on a straight edge will
|
||||
// have four neighbours with the same material. If it's on a corner it will have a
|
||||
// different number. We only collapse straight edges to avoid changingthe shape of the
|
||||
// material boundary.
|
||||
if(m_vecNoOfNeighboursUsingMaterial[v0] == m_vecNoOfNeighboursUsingMaterial[v1])
|
||||
{
|
||||
if(m_vecNoOfNeighboursUsingMaterial[v0] == 4)
|
||||
{
|
||||
allMatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool movementValid = false;
|
||||
Vector3DFloat movement = m_vecVertices[v1].getPosition() - m_vecVertices[v0].getPosition();
|
||||
movement.normalise();
|
||||
if(movement.dot(Vector3DFloat(0,0,1)) > 0.999)
|
||||
{
|
||||
movementValid = true;
|
||||
}
|
||||
|
||||
if(movement.dot(Vector3DFloat(0,1,0)) > 0.999)
|
||||
{
|
||||
movementValid = true;
|
||||
}
|
||||
|
||||
if(movement.dot(Vector3DFloat(1,0,0)) > 0.999)
|
||||
{
|
||||
movementValid = true;
|
||||
}
|
||||
|
||||
if(movement.dot(Vector3DFloat(0,0,-1)) > 0.999)
|
||||
{
|
||||
movementValid = true;
|
||||
}
|
||||
|
||||
if(movement.dot(Vector3DFloat(0,-1,0)) > 0.999)
|
||||
{
|
||||
movementValid = true;
|
||||
}
|
||||
|
||||
if(movement.dot(Vector3DFloat(-1,0,0)) > 0.999)
|
||||
{
|
||||
movementValid = true;
|
||||
}
|
||||
|
||||
if(movementValid && allMatch)
|
||||
{
|
||||
pass = true;
|
||||
}
|
||||
|
||||
if(!pass)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else //Material collapses not allowed
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Vertices on the geometrical edge of surface meshes need special handling.
|
||||
// We check for this by whether any of the edge flags are set.
|
||||
if(m_vecVertices[v0].m_bFlags.any() || m_vecVertices[v1].m_bFlags.any())
|
||||
{
|
||||
// Assume we can't collapse until we prove otherwise...
|
||||
bool bCollapseGeometryEdgePair = false;
|
||||
|
||||
// We can collapse normal vertices onto edge vertices, and edge vertices
|
||||
// onto corner vertices, but not vice-versa. Hence we check whether all
|
||||
// the edge flags in the source vertex are also set in the destination vertex.
|
||||
if(isSubset(m_vecVertices[v0].m_bFlags, m_vecVertices[v1].m_bFlags))
|
||||
{
|
||||
// In general adjacent regions surface meshes may collapse differently
|
||||
// and this can cause cracks. We solve this by only allowing the collapse
|
||||
// is the normals are exactly the same. We do not use the user provided
|
||||
// tolerence here (but do allow for floating point error).
|
||||
if(m_vecVertices[v0].getNormal().dot(m_vecVertices[v1].getNormal()) > 0.999)
|
||||
{
|
||||
// Ok, this pair can collapse.
|
||||
bCollapseGeometryEdgePair = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Use the result.
|
||||
if(!bCollapseGeometryEdgePair)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//Check the normals are within the threashold.
|
||||
if(m_vecVertices[v0].getNormal().dot(m_vecVertices[v1].getNormal()) < fMinDotProductForCollapse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//The last test is whether we will flip any of the faces
|
||||
|
||||
bool faceFlipped = false;
|
||||
list<uint32_t> triangles = trianglesUsingVertex[v0];
|
||||
/*set<uint32_t> triangles;
|
||||
std::set_union(trianglesUsingVertex[v0].begin(), trianglesUsingVertex[v0].end(),
|
||||
trianglesUsingVertex[v1].begin(), trianglesUsingVertex[v1].end(),
|
||||
std::inserter(triangles, triangles.begin()));*/
|
||||
|
||||
for(list<uint32_t>::iterator triIter = triangles.begin(); triIter != triangles.end(); triIter++)
|
||||
{
|
||||
uint32_t tri = *triIter;
|
||||
|
||||
uint32_t v0Old = m_vecTriangleIndices[tri * 3];
|
||||
uint32_t v1Old = m_vecTriangleIndices[tri * 3 + 1];
|
||||
uint32_t v2Old = m_vecTriangleIndices[tri * 3 + 2];
|
||||
|
||||
//Check if degenerate
|
||||
if((v0Old == v1Old) || (v1Old == v2Old) || (v2Old == v0Old))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t v0New = v0Old;
|
||||
uint32_t v1New = v1Old;
|
||||
uint32_t v2New = v2Old;
|
||||
|
||||
if(v0New == v0)
|
||||
v0New = v1;
|
||||
if(v1New == v0)
|
||||
v1New = v1;
|
||||
if(v2New == v0)
|
||||
v2New = v1;
|
||||
|
||||
//Check if degenerate
|
||||
if((v0New == v1New) || (v1New == v2New) || (v2New == v0New))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector3DFloat v0OldPos = m_vecVertices[vertexMapper[v0Old]].getPosition();
|
||||
Vector3DFloat v1OldPos = m_vecVertices[vertexMapper[v1Old]].getPosition();
|
||||
Vector3DFloat v2OldPos = m_vecVertices[vertexMapper[v2Old]].getPosition();
|
||||
|
||||
Vector3DFloat v0NewPos = m_vecVertices[vertexMapper[v0New]].getPosition();
|
||||
Vector3DFloat v1NewPos = m_vecVertices[vertexMapper[v1New]].getPosition();
|
||||
Vector3DFloat v2NewPos = m_vecVertices[vertexMapper[v2New]].getPosition();
|
||||
|
||||
/*Vector3DFloat v0OldPos = m_vecVertices[v0Old].getPosition();
|
||||
Vector3DFloat v1OldPos = m_vecVertices[v1Old].getPosition();
|
||||
Vector3DFloat v2OldPos = m_vecVertices[v2Old].getPosition();
|
||||
|
||||
Vector3DFloat v0NewPos = m_vecVertices[v0New].getPosition();
|
||||
Vector3DFloat v1NewPos = m_vecVertices[v1New].getPosition();
|
||||
Vector3DFloat v2NewPos = m_vecVertices[v2New].getPosition();*/
|
||||
|
||||
Vector3DFloat OldNormal = (v1OldPos - v0OldPos).cross(v2OldPos - v1OldPos);
|
||||
Vector3DFloat NewNormal = (v1NewPos - v0NewPos).cross(v2NewPos - v1NewPos);
|
||||
|
||||
OldNormal.normalise();
|
||||
NewNormal.normalise();
|
||||
|
||||
// Note for after holiday - We are still getting faces flipping despite the following test. I tried changing
|
||||
// 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);
|
||||
//cout << dotProduct << endl;
|
||||
if(dotProduct < 0.9f)
|
||||
{
|
||||
//cout << " Face flipped!!" << endl;
|
||||
|
||||
faceFlipped = true;
|
||||
|
||||
/*vertexLocked[v0] = true;
|
||||
vertexLocked[v1] = true;*/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(faceFlipped == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Move v0 onto v1
|
||||
vertexMapper[v0] = v1; //vertexMapper[v1];
|
||||
vertexLocked[v0] = true;
|
||||
vertexLocked[v1] = true;
|
||||
|
||||
//Increment the counter
|
||||
++noOfEdgesCollapsed;
|
||||
}
|
||||
}
|
||||
|
||||
if(noOfEdgesCollapsed > 0)
|
||||
{
|
||||
//Fix up the indices
|
||||
for(int triCt = 0; triCt < m_vecTriangleIndices.size(); triCt++)
|
||||
{
|
||||
uint32_t before = m_vecTriangleIndices[triCt];
|
||||
uint32_t after = vertexMapper[m_vecTriangleIndices[triCt]];
|
||||
if(before != after)
|
||||
{
|
||||
m_vecTriangleIndices[triCt] = vertexMapper[m_vecTriangleIndices[triCt]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return noOfEdgesCollapsed;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
int SurfaceMesh<VertexType>::noOfDegenerateTris(void)
|
||||
{
|
||||
int count = 0;
|
||||
for(int triCt = 0; triCt < m_vecTriangleIndices.size();)
|
||||
{
|
||||
int v0 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
int v1 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
int v2 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
|
||||
if((v0 == v1) || (v1 == v2) || (v2 == v0))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
template <typename VertexType>
|
||||
void SurfaceMesh<VertexType>::removeDegenerateTris(void)
|
||||
{
|
||||
int noOfNonDegenerate = 0;
|
||||
int targetCt = 0;
|
||||
for(int triCt = 0; triCt < m_vecTriangleIndices.size();)
|
||||
{
|
||||
int v0 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
int v1 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
int v2 = m_vecTriangleIndices[triCt];
|
||||
triCt++;
|
||||
|
||||
if((v0 != v1) && (v1 != v2) & (v2 != v0))
|
||||
{
|
||||
m_vecTriangleIndices[targetCt] = v0;
|
||||
targetCt++;
|
||||
m_vecTriangleIndices[targetCt] = v1;
|
||||
targetCt++;
|
||||
m_vecTriangleIndices[targetCt] = v2;
|
||||
targetCt++;
|
||||
|
||||
noOfNonDegenerate++;
|
||||
}
|
||||
}
|
||||
|
||||
m_vecTriangleIndices.resize(noOfNonDegenerate * 3);
|
||||
}
|
||||
}
|
@ -44,12 +44,28 @@ namespace PolyVox
|
||||
VF_NO_OF_FLAGS
|
||||
};
|
||||
|
||||
class POLYVOXCORE_API SurfaceVertex
|
||||
class POLYVOXCORE_API PositionMaterial
|
||||
{
|
||||
public:
|
||||
SurfaceVertex();
|
||||
SurfaceVertex(Vector3DFloat positionToSet, float materialToSet);
|
||||
SurfaceVertex(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet);
|
||||
PositionMaterial();
|
||||
PositionMaterial(Vector3DFloat positionToSet, float materialToSet);
|
||||
|
||||
float getMaterial(void) const;
|
||||
const Vector3DFloat& getPosition(void) const;
|
||||
|
||||
void setMaterial(float materialToSet);
|
||||
void setPosition(const Vector3DFloat& positionToSet);
|
||||
public:
|
||||
Vector3DFloat position;
|
||||
float material;
|
||||
};
|
||||
|
||||
class POLYVOXCORE_API PositionMaterialNormal
|
||||
{
|
||||
public:
|
||||
PositionMaterialNormal();
|
||||
PositionMaterialNormal(Vector3DFloat positionToSet, float materialToSet);
|
||||
PositionMaterialNormal(Vector3DFloat positionToSet, Vector3DFloat normalToSet, float materialToSet);
|
||||
|
||||
float getMaterial(void) const;
|
||||
const Vector3DFloat& getNormal(void) const;
|
||||
@ -83,11 +99,6 @@ namespace PolyVox
|
||||
float material; //FIXME: This shouldn't be float on CPU?
|
||||
std::bitset<VF_NO_OF_FLAGS> m_bFlags;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//bool operator < (const SurfaceVertexIterator& lhs, const SurfaceVertexIterator& rhs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -66,12 +66,12 @@ namespace PolyVox
|
||||
{
|
||||
}
|
||||
|
||||
template <typename VoxelType>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// The border value is returned whenever an atempt is made to read a voxel which
|
||||
/// is outside the extents of the volume.
|
||||
/// \return The value used for voxels outside of the volume
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename VoxelType>
|
||||
VoxelType Volume<VoxelType>::getBorderValue(void) const
|
||||
{
|
||||
return m_pBorderBlock->getVoxelAt(0,0,0);
|
||||
|
Reference in New Issue
Block a user