virtualx-engine/thirdparty/thekla_atlas/nvmesh/MeshTopology.cpp

123 lines
3.4 KiB
C++
Raw Normal View History

// This code is in the public domain -- castanyo@yahoo.es
#include "nvmesh.h" // pch
#include "nvcore/Array.h"
#include "nvcore/BitArray.h"
#include "nvmesh/MeshTopology.h"
#include "nvmesh/halfedge/Mesh.h"
#include "nvmesh/halfedge/Edge.h"
#include "nvmesh/halfedge/Face.h"
using namespace nv;
void MeshTopology::buildTopologyInfo(const HalfEdge::Mesh * mesh)
{
const uint vertexCount = mesh->colocalVertexCount();
const uint faceCount = mesh->faceCount();
const uint edgeCount = mesh->edgeCount();
nvDebug( "--- Building mesh topology:\n" );
Array<uint> stack(faceCount);
BitArray bitFlags(faceCount);
bitFlags.clearAll();
// Compute connectivity.
nvDebug( "--- Computing connectivity.\n" );
m_connectedCount = 0;
for(uint f = 0; f < faceCount; f++ ) {
if( bitFlags.bitAt(f) == false ) {
m_connectedCount++;
stack.pushBack( f );
while( !stack.isEmpty() ) {
const uint top = stack.back();
nvCheck(top != NIL);
stack.popBack();
if( bitFlags.bitAt(top) == false ) {
bitFlags.setBitAt(top);
const HalfEdge::Face * face = mesh->faceAt(top);
const HalfEdge::Edge * firstEdge = face->edge;
const HalfEdge::Edge * edge = firstEdge;
do {
const HalfEdge::Face * neighborFace = edge->pair->face;
if (neighborFace != NULL) {
stack.pushBack(neighborFace->id);
}
edge = edge->next;
} while(edge != firstEdge);
}
}
}
}
nvCheck(stack.isEmpty());
nvDebug( "--- %d connected components.\n", m_connectedCount );
// Count boundary loops.
nvDebug( "--- Counting boundary loops.\n" );
m_boundaryCount = 0;
bitFlags.resize(edgeCount);
bitFlags.clearAll();
// Don't forget to link the boundary otherwise this won't work.
for (uint e = 0; e < edgeCount; e++)
{
const HalfEdge::Edge * startEdge = mesh->edgeAt(e);
if (startEdge != NULL && startEdge->isBoundary() && bitFlags.bitAt(e) == false)
{
nvDebugCheck(startEdge->face != NULL);
nvDebugCheck(startEdge->pair->face == NULL);
startEdge = startEdge->pair;
m_boundaryCount++;
const HalfEdge::Edge * edge = startEdge;
do {
bitFlags.setBitAt(edge->id / 2);
edge = edge->next;
} while(startEdge != edge);
}
}
nvDebug("--- %d boundary loops found.\n", m_boundaryCount );
// Compute euler number.
m_eulerNumber = vertexCount - edgeCount + faceCount;
nvDebug("--- Euler number: %d.\n", m_eulerNumber);
// Compute genus. (only valid on closed connected surfaces)
m_genus = -1;
if( isClosed() && isConnected() ) {
m_genus = (2 - m_eulerNumber) / 2;
nvDebug("--- Genus: %d.\n", m_genus);
}
}
/*static*/ bool MeshTopology::isQuadOnly(const HalfEdge::Mesh * mesh)
{
const uint faceCount = mesh->faceCount();
for(uint f = 0; f < faceCount; f++)
{
const HalfEdge::Face * face = mesh->faceAt(f);
if (face->edgeCount() != 4) {
return false;
}
}
return true;
}