TSManifoldMesh.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Logger.h>
  9. #include <Mathematics/TetrahedronKey.h>
  10. #include <Mathematics/TriangleKey.h>
  11. #include <map>
  12. #include <memory>
  13. namespace WwiseGTE
  14. {
  15. class TSManifoldMesh
  16. {
  17. public:
  18. // Triangle data types.
  19. class Triangle;
  20. typedef std::shared_ptr<Triangle>(*TCreator)(int, int, int);
  21. typedef std::map<TriangleKey<false>, std::shared_ptr<Triangle>> TMap;
  22. // Tetrahedron data types.
  23. class Tetrahedron;
  24. typedef std::shared_ptr<Tetrahedron>(*SCreator)(int, int, int, int);
  25. typedef std::map<TetrahedronKey<true>, std::shared_ptr<Tetrahedron>> SMap;
  26. // Triangle object.
  27. class Triangle
  28. {
  29. public:
  30. virtual ~Triangle() = default;
  31. Triangle(int v0, int v1, int v2)
  32. :
  33. V{ v0, v1, v2 }
  34. {
  35. }
  36. // Vertices of the face.
  37. std::array<int, 3> V;
  38. // Tetrahedra sharing the face.
  39. std::array<std::weak_ptr<Tetrahedron>, 2> T;
  40. };
  41. // Tetrahedron object.
  42. class Tetrahedron
  43. {
  44. public:
  45. virtual ~Tetrahedron() = default;
  46. Tetrahedron(int v0, int v1, int v2, int v3)
  47. :
  48. V{ v0, v1, v2, v3 }
  49. {
  50. }
  51. // Vertices, listed in an order so that each face vertices in
  52. // counterclockwise order when viewed from outside the
  53. // tetrahedron.
  54. std::array<int, 4> V;
  55. // Adjacent faces. T[i] points to the triangle face
  56. // opposite V[i].
  57. // T[0] points to face (V[1],V[2],V[3])
  58. // T[1] points to face (V[0],V[3],V[2])
  59. // T[2] points to face (V[0],V[1],V[3])
  60. // T[3] points to face (V[0],V[2],V[1])
  61. std::array<std::weak_ptr<Triangle>, 4> T;
  62. // Adjacent tetrahedra. S[i] points to the adjacent tetrahedron
  63. // sharing face T[i].
  64. std::array<std::weak_ptr<Tetrahedron>, 4> S;
  65. };
  66. // Construction and destruction.
  67. virtual ~TSManifoldMesh() = default;
  68. TSManifoldMesh(TCreator tCreator = nullptr, SCreator sCreator = nullptr)
  69. :
  70. mTCreator(tCreator ? tCreator : CreateTriangle),
  71. mSCreator(sCreator ? sCreator : CreateTetrahedron),
  72. mThrowOnNonmanifoldInsertion(true)
  73. {
  74. }
  75. // Support for a deep copy of the mesh. The mTMap and mSMap objects
  76. // have dynamically allocated memory for triangles and tetrahedra. A
  77. // shallow/ copy of the pointers to this memory is problematic.
  78. // Allowing sharing, say, via std::shared_ptr, is an option but not
  79. // really the intent of copying the mesh graph.
  80. TSManifoldMesh(TSManifoldMesh const& mesh)
  81. {
  82. *this = mesh;
  83. }
  84. TSManifoldMesh& operator=(TSManifoldMesh const& mesh)
  85. {
  86. Clear();
  87. mTCreator = mesh.mTCreator;
  88. mSCreator = mesh.mSCreator;
  89. mThrowOnNonmanifoldInsertion = mesh.mThrowOnNonmanifoldInsertion;
  90. for (auto const& element : mesh.mSMap)
  91. {
  92. Insert(element.first.V[0], element.first.V[1], element.first.V[2], element.first.V[3]);
  93. }
  94. return *this;
  95. }
  96. // Member access.
  97. inline TMap const& GetTriangles() const
  98. {
  99. return mTMap;
  100. }
  101. inline SMap const& GetTetrahedra() const
  102. {
  103. return mSMap;
  104. }
  105. // If the insertion of a tetrahedron fails because the mesh would
  106. // become nonmanifold, the default behavior is to throw an exception.
  107. // You can disable this behavior and continue gracefully without an
  108. // exception.
  109. void ThrowOnNonmanifoldInsertion(bool doException)
  110. {
  111. mThrowOnNonmanifoldInsertion = doException;
  112. }
  113. // If <v0,v1,v2,v3> is not in the mesh, a Tetrahedron object is
  114. // created and returned; otherwise, <v0,v1,v2,v3> is in the mesh and
  115. // nullptr is returned. If the insertion leads to a nonmanifold mesh,
  116. // the call fails with a nullptr returned.
  117. std::shared_ptr<Tetrahedron> Insert(int v0, int v1, int v2, int v3)
  118. {
  119. TetrahedronKey<true> skey(v0, v1, v2, v3);
  120. if (mSMap.find(skey) != mSMap.end())
  121. {
  122. // The tetrahedron already exists. Return a null pointer as
  123. // a signal to the caller that the insertion failed.
  124. return nullptr;
  125. }
  126. // Add the new tetrahedron.
  127. std::shared_ptr<Tetrahedron> tetra = mSCreator(v0, v1, v2, v3);
  128. mSMap[skey] = tetra;
  129. // Add the faces to the mesh if they do not already exist.
  130. for (int i = 0; i < 4; ++i)
  131. {
  132. auto opposite = TetrahedronKey<true>::GetOppositeFace()[i];
  133. TriangleKey<false> tkey(tetra->V[opposite[0]], tetra->V[opposite[1]], tetra->V[opposite[2]]);
  134. std::shared_ptr<Triangle> face;
  135. auto titer = mTMap.find(tkey);
  136. if (titer == mTMap.end())
  137. {
  138. // This is the first time the face is encountered.
  139. face = mTCreator(tetra->V[opposite[0]], tetra->V[opposite[1]], tetra->V[opposite[2]]);
  140. mTMap[tkey] = face;
  141. // Update the face and tetrahedron.
  142. face->T[0] = tetra;
  143. tetra->T[i] = face;
  144. }
  145. else
  146. {
  147. // This is the second time the face is encountered.
  148. face = titer->second;
  149. LogAssert(face != nullptr, "Unexpected condition.");
  150. // Update the face.
  151. if (face->T[1].lock())
  152. {
  153. if (mThrowOnNonmanifoldInsertion)
  154. {
  155. LogError("Attempt to create nonmanifold mesh.");
  156. }
  157. else
  158. {
  159. return nullptr;
  160. }
  161. }
  162. face->T[1] = tetra;
  163. // Update the adjacent tetrahedra.
  164. auto adjacent = face->T[0].lock();
  165. LogAssert(adjacent != nullptr, "Unexpected condition.");
  166. for (int j = 0; j < 4; ++j)
  167. {
  168. if (adjacent->T[j].lock() == face)
  169. {
  170. adjacent->S[j] = tetra;
  171. break;
  172. }
  173. }
  174. // Update the tetrahedron.
  175. tetra->T[i] = face;
  176. tetra->S[i] = adjacent;
  177. }
  178. }
  179. return tetra;
  180. }
  181. // If <v0,v1,v2,v3> is in the mesh, it is removed and 'true' is
  182. // returned; otherwise, <v0,v1,v2,v3> is not in the mesh and 'false'
  183. // is returned.
  184. bool Remove(int v0, int v1, int v2, int v3)
  185. {
  186. TetrahedronKey<true> skey(v0, v1, v2, v3);
  187. auto siter = mSMap.find(skey);
  188. if (siter == mSMap.end())
  189. {
  190. // The tetrahedron does not exist.
  191. return false;
  192. }
  193. // Get the tetrahedron.
  194. std::shared_ptr<Tetrahedron> tetra = siter->second;
  195. // Remove the faces and update adjacent tetrahedra if necessary.
  196. for (int i = 0; i < 4; ++i)
  197. {
  198. // Inform the faces the tetrahedron is being deleted.
  199. auto face = tetra->T[i].lock();
  200. LogAssert(face != nullptr, "Unexpected condition.");
  201. if (face->T[0].lock() == tetra)
  202. {
  203. // One-tetrahedron faces always have pointer at index
  204. // zero.
  205. face->T[0] = face->T[1];
  206. face->T[1].reset();
  207. }
  208. else if (face->T[1].lock() == tetra)
  209. {
  210. face->T[1].reset();
  211. }
  212. else
  213. {
  214. LogError("Unexpected condition.");
  215. }
  216. // Remove the face if you have the last reference to it.
  217. if (!face->T[0].lock() && !face->T[1].lock())
  218. {
  219. TriangleKey<false> tkey(face->V[0], face->V[1], face->V[2]);
  220. mTMap.erase(tkey);
  221. }
  222. // Inform adjacent tetrahedra the tetrahedron is being
  223. // deleted.
  224. auto adjacent = tetra->S[i].lock();
  225. if (adjacent)
  226. {
  227. for (int j = 0; j < 4; ++j)
  228. {
  229. if (adjacent->S[j].lock() == tetra)
  230. {
  231. adjacent->S[j].reset();
  232. break;
  233. }
  234. }
  235. }
  236. }
  237. mSMap.erase(skey);
  238. return true;
  239. }
  240. // Destroy the triangles and tetrahedra to obtain an empty mesh.
  241. virtual void Clear()
  242. {
  243. mTMap.clear();
  244. mSMap.clear();
  245. }
  246. // A manifold mesh is closed if each face is shared twice.
  247. bool IsClosed() const
  248. {
  249. for (auto const& element : mSMap)
  250. {
  251. auto tri = element.second;
  252. if (!tri->S[0].lock() || !tri->S[1].lock())
  253. {
  254. return false;
  255. }
  256. }
  257. return true;
  258. }
  259. protected:
  260. // The triangle data and default triangle creation.
  261. static std::shared_ptr<Triangle> CreateTriangle(int v0, int v1, int v2)
  262. {
  263. return std::make_shared<Triangle>(v0, v1, v2);
  264. }
  265. TCreator mTCreator;
  266. TMap mTMap;
  267. // The tetrahedron data and default tetrahedron creation.
  268. static std::shared_ptr<Tetrahedron> CreateTetrahedron(int v0, int v1, int v2, int v3)
  269. {
  270. return std::make_shared<Tetrahedron>(v0, v1, v2, v3);
  271. }
  272. SCreator mSCreator;
  273. SMap mSMap;
  274. bool mThrowOnNonmanifoldInsertion; // default: true
  275. };
  276. }