Polyhedron3.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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/Vector3.h>
  9. #include <memory>
  10. #include <set>
  11. #include <vector>
  12. // The Polyhedron3 object represents a simple polyhedron. The 'vertexPool'
  13. // array can contain more points than needed to define the polyhedron, which
  14. // allows the vertex pool to have multiple polyhedra associated with it.
  15. // Thus, the programmer must ensure that the vertex pool persists as long as
  16. // any Polyhedron3 objects exist that depend on the pool. The number of
  17. // polyhedron indices is 'numIndices' and must be 6 or larger The 'indices'
  18. // array refers to the points in 'vertexPool' that form the triangle faces,
  19. // so 'numIndices' must be a multiple of 3. The number of vertices is
  20. // the number of unique elements in 'indices' and is determined during
  21. // construction. The programmer should ensure the polyhedron is simple. The
  22. // geometric queries are valid regardless of whether the polyhedron triangles
  23. // are oriented clockwise or counterclockwise.
  24. //
  25. // NOTE: Comparison operators are not provided. The semantics of equal
  26. // polyhedra is complicated and (at the moment) not useful. The vertex pools
  27. // can be different and indices do not match, but the vertices they reference
  28. // can match. Even with a shared vertex pool, the indices can be permuted,
  29. // leading to the same polyhedron abstractly but the data structures do not
  30. // match.
  31. namespace WwiseGTE
  32. {
  33. template <typename Real>
  34. class Polyhedron3
  35. {
  36. public:
  37. // Construction. The constructor succeeds when 'numIndices >= 12' (at
  38. // least 4 triangles), and 'vertexPool' and 'indices' are not null; we
  39. // cannot test whether you have a valid number of elements in the
  40. // input arrays. A copy is made of 'indices', but the 'vertexPool' is
  41. // not copied. If the constructor fails, the internal vertex pointer
  42. // is set to null, the number of vertices is set to zero, the index
  43. // array has no elements, and the triangle face orientation is set to
  44. // clockwise.
  45. Polyhedron3(std::shared_ptr<std::vector<Vector3<Real>>> const& vertexPool,
  46. int numIndices, int const* indices, bool counterClockwise)
  47. :
  48. mVertexPool(vertexPool),
  49. mCounterClockwise(counterClockwise)
  50. {
  51. if (vertexPool && indices && numIndices >= 12 && (numIndices % 3) == 0)
  52. {
  53. for (int i = 0; i < numIndices; ++i)
  54. {
  55. mUniqueIndices.insert(indices[i]);
  56. }
  57. mIndices.resize(numIndices);
  58. std::copy(indices, indices + numIndices, mIndices.begin());
  59. }
  60. else
  61. {
  62. // Encountered an invalid input.
  63. mVertexPool = nullptr;
  64. mCounterClockwise = false;
  65. }
  66. }
  67. // To validate construction, create an object as shown:
  68. // Polyhedron3<Real> polyhedron(parameters);
  69. // if (!polyhedron) { <constructor failed, handle accordingly>; }
  70. inline operator bool() const
  71. {
  72. return mVertexPool != nullptr;
  73. }
  74. // Member access.
  75. inline std::shared_ptr<std::vector<Vector3<Real>>> const& GetVertexPool() const
  76. {
  77. return mVertexPool;
  78. }
  79. inline std::vector<Vector3<Real>> const& GetVertices() const
  80. {
  81. return *mVertexPool.get();
  82. }
  83. inline std::set<int> const& GetUniqueIndices() const
  84. {
  85. return mUniqueIndices;
  86. }
  87. inline std::vector<int> const& GetIndices() const
  88. {
  89. return mIndices;
  90. }
  91. inline bool CounterClockwise() const
  92. {
  93. return mCounterClockwise;
  94. }
  95. // Geometric queries.
  96. Vector3<Real> ComputeVertexAverage() const
  97. {
  98. Vector3<Real> average = Vector3<Real>::Zero();
  99. if (mVertexPool)
  100. {
  101. auto vertexPool = GetVertices();
  102. for (int index : mUniqueIndices)
  103. {
  104. average += vertexPool[index];
  105. }
  106. average /= static_cast<Real>(mUniqueIndices.size());
  107. }
  108. return average;
  109. }
  110. Real ComputeSurfaceArea() const
  111. {
  112. Real surfaceArea(0);
  113. if (mVertexPool)
  114. {
  115. auto vertexPool = GetVertices();
  116. int const numTriangles = static_cast<int>(mIndices.size()) / 3;
  117. int const* indices = mIndices.data();
  118. for (int t = 0; t < numTriangles; ++t)
  119. {
  120. int v0 = *indices++;
  121. int v1 = *indices++;
  122. int v2 = *indices++;
  123. Vector3<Real> edge0 = vertexPool[v1] - vertexPool[v0];
  124. Vector3<Real> edge1 = vertexPool[v2] - vertexPool[v0];
  125. Vector3<Real> cross = Cross(edge0, edge1);
  126. surfaceArea += Length(cross);
  127. }
  128. surfaceArea *= (Real)0.5;
  129. }
  130. return surfaceArea;
  131. }
  132. Real ComputeVolume() const
  133. {
  134. Real volume(0);
  135. if (mVertexPool)
  136. {
  137. auto vertexPool = GetVertices();
  138. int const numTriangles = static_cast<int>(mIndices.size()) / 3;
  139. int const* indices = mIndices.data();
  140. for (int t = 0; t < numTriangles; ++t)
  141. {
  142. int v0 = *indices++;
  143. int v1 = *indices++;
  144. int v2 = *indices++;
  145. volume += DotCross(vertexPool[v0], vertexPool[v1], vertexPool[v2]);
  146. }
  147. volume /= (Real)6;
  148. }
  149. return std::fabs(volume);
  150. }
  151. private:
  152. std::shared_ptr<std::vector<Vector3<Real>>> mVertexPool;
  153. std::set<int> mUniqueIndices;
  154. std::vector<int> mIndices;
  155. bool mCounterClockwise;
  156. };
  157. }