MeshTopology.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. // This code is in the public domain -- castanyo@yahoo.es
  2. #include "nvmesh.h" // pch
  3. #include "nvcore/Array.h"
  4. #include "nvcore/BitArray.h"
  5. #include "nvmesh/MeshTopology.h"
  6. #include "nvmesh/halfedge/Mesh.h"
  7. #include "nvmesh/halfedge/Edge.h"
  8. #include "nvmesh/halfedge/Face.h"
  9. using namespace nv;
  10. void MeshTopology::buildTopologyInfo(const HalfEdge::Mesh * mesh)
  11. {
  12. const uint vertexCount = mesh->colocalVertexCount();
  13. const uint faceCount = mesh->faceCount();
  14. const uint edgeCount = mesh->edgeCount();
  15. nvDebug( "--- Building mesh topology:\n" );
  16. Array<uint> stack(faceCount);
  17. BitArray bitFlags(faceCount);
  18. bitFlags.clearAll();
  19. // Compute connectivity.
  20. nvDebug( "--- Computing connectivity.\n" );
  21. m_connectedCount = 0;
  22. for(uint f = 0; f < faceCount; f++ ) {
  23. if( bitFlags.bitAt(f) == false ) {
  24. m_connectedCount++;
  25. stack.pushBack( f );
  26. while( !stack.isEmpty() ) {
  27. const uint top = stack.back();
  28. nvCheck(top != NIL);
  29. stack.popBack();
  30. if( bitFlags.bitAt(top) == false ) {
  31. bitFlags.setBitAt(top);
  32. const HalfEdge::Face * face = mesh->faceAt(top);
  33. const HalfEdge::Edge * firstEdge = face->edge;
  34. const HalfEdge::Edge * edge = firstEdge;
  35. do {
  36. const HalfEdge::Face * neighborFace = edge->pair->face;
  37. if (neighborFace != NULL) {
  38. stack.pushBack(neighborFace->id);
  39. }
  40. edge = edge->next;
  41. } while(edge != firstEdge);
  42. }
  43. }
  44. }
  45. }
  46. nvCheck(stack.isEmpty());
  47. nvDebug( "--- %d connected components.\n", m_connectedCount );
  48. // Count boundary loops.
  49. nvDebug( "--- Counting boundary loops.\n" );
  50. m_boundaryCount = 0;
  51. bitFlags.resize(edgeCount);
  52. bitFlags.clearAll();
  53. // Don't forget to link the boundary otherwise this won't work.
  54. for (uint e = 0; e < edgeCount; e++)
  55. {
  56. const HalfEdge::Edge * startEdge = mesh->edgeAt(e);
  57. if (startEdge != NULL && startEdge->isBoundary() && bitFlags.bitAt(e) == false)
  58. {
  59. nvDebugCheck(startEdge->face != NULL);
  60. nvDebugCheck(startEdge->pair->face == NULL);
  61. startEdge = startEdge->pair;
  62. m_boundaryCount++;
  63. const HalfEdge::Edge * edge = startEdge;
  64. do {
  65. bitFlags.setBitAt(edge->id / 2);
  66. edge = edge->next;
  67. } while(startEdge != edge);
  68. }
  69. }
  70. nvDebug("--- %d boundary loops found.\n", m_boundaryCount );
  71. // Compute euler number.
  72. m_eulerNumber = vertexCount - edgeCount + faceCount;
  73. nvDebug("--- Euler number: %d.\n", m_eulerNumber);
  74. // Compute genus. (only valid on closed connected surfaces)
  75. m_genus = -1;
  76. if( isClosed() && isConnected() ) {
  77. m_genus = (2 - m_eulerNumber) / 2;
  78. nvDebug("--- Genus: %d.\n", m_genus);
  79. }
  80. }
  81. /*static*/ bool MeshTopology::isQuadOnly(const HalfEdge::Mesh * mesh)
  82. {
  83. const uint faceCount = mesh->faceCount();
  84. for(uint f = 0; f < faceCount; f++)
  85. {
  86. const HalfEdge::Face * face = mesh->faceAt(f);
  87. if (face->edgeCount() != 4) {
  88. return false;
  89. }
  90. }
  91. return true;
  92. }