BsTriangulation.cpp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Utility/BsTriangulation.h"
  4. #include "Math/BsVector3.h"
  5. // Third party
  6. #include "TetGen/tetgen.h"
  7. namespace bs
  8. {
  9. TetrahedronVolume Triangulation::tetrahedralize(const Vector<Vector3>& points)
  10. {
  11. TetrahedronVolume volume;
  12. if (points.size() < 4)
  13. return volume;
  14. tetgenio input;
  15. input.numberofpoints = (int)points.size();
  16. input.pointlist = new REAL[input.numberofpoints * 3]; // Must be allocated with "new" because TetGen deallocates it using "delete"
  17. for(UINT32 i = 0; i < (UINT32)points.size(); ++i)
  18. {
  19. input.pointlist[i * 3 + 0] = points[i].x;
  20. input.pointlist[i * 3 + 1] = points[i].y;
  21. input.pointlist[i * 3 + 2] = points[i].z;
  22. }
  23. tetgenbehavior options;
  24. options.neighout = 2; // Generate adjacency information between tets and outer faces
  25. options.facesout = 1; // Output face adjacency
  26. options.quiet = 1; // Don't print anything
  27. tetgenio output;
  28. ::tetrahedralize(&options, &input, &output);
  29. UINT32 numTetrahedra = (UINT32)output.numberoftetrahedra;
  30. volume.tetrahedra.resize(numTetrahedra);
  31. for (UINT32 i = 0; i < numTetrahedra; ++i)
  32. {
  33. memcpy(volume.tetrahedra[i].vertices, &output.tetrahedronlist[i * 4], sizeof(INT32) * 4);
  34. memcpy(volume.tetrahedra[i].neighbors, &output.neighborlist[i * 4], sizeof(INT32) * 4);
  35. }
  36. // Generate boundary faces
  37. UINT32 numFaces = (UINT32)output.numberoftrifaces;
  38. for (UINT32 i = 0; i < numFaces; ++i)
  39. {
  40. INT32 tetIdx = -1;
  41. if (output.adjtetlist[i * 2] == -1)
  42. tetIdx = output.adjtetlist[i * 2 + 1];
  43. else if (output.adjtetlist[i * 2 + 1] == -1)
  44. tetIdx = output.adjtetlist[i * 2];
  45. else // Not a boundary face
  46. continue;
  47. volume.outerFaces.push_back(TetrahedronFace());
  48. TetrahedronFace& face = volume.outerFaces.back();
  49. memcpy(face.vertices, &output.trifacelist[i * 3], sizeof(INT32) * 3);
  50. face.tetrahedron = tetIdx;
  51. }
  52. // Ensure that vertex at the specified location points a neighbor opposite to it
  53. for(UINT32 i = 0; i < numTetrahedra; ++i)
  54. {
  55. INT32 neighbors[4];
  56. memcpy(neighbors, volume.tetrahedra[i].neighbors, sizeof(INT32) * 4);
  57. for(UINT32 j = 0; j < 4; ++j)
  58. {
  59. INT32 vert = volume.tetrahedra[i].vertices[j];
  60. for (UINT32 k = 0; k < 4; ++k)
  61. {
  62. INT32 neighborIdx = neighbors[k];
  63. if (neighborIdx == -1)
  64. continue;
  65. Tetrahedron& neighbor = volume.tetrahedra[neighborIdx];
  66. if (vert != neighbor.vertices[0] && vert != neighbor.vertices[1] &&
  67. vert != neighbor.vertices[2] && vert != neighbor.vertices[3])
  68. {
  69. volume.tetrahedra[i].neighbors[j] = neighborIdx;
  70. break;
  71. }
  72. }
  73. }
  74. }
  75. return volume;
  76. }
  77. }