IntrRay3Triangle3.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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/FIQuery.h>
  9. #include <Mathematics/TIQuery.h>
  10. #include <Mathematics/Ray.h>
  11. #include <Mathematics/Triangle.h>
  12. #include <Mathematics/Vector3.h>
  13. namespace WwiseGTE
  14. {
  15. template <typename Real>
  16. class TIQuery<Real, Ray3<Real>, Triangle3<Real>>
  17. {
  18. public:
  19. struct Result
  20. {
  21. bool intersect;
  22. };
  23. Result operator()(Ray3<Real> const& ray, Triangle3<Real> const& triangle)
  24. {
  25. Result result;
  26. // Compute the offset origin, edges, and normal.
  27. Vector3<Real> diff = ray.origin - triangle.v[0];
  28. Vector3<Real> edge1 = triangle.v[1] - triangle.v[0];
  29. Vector3<Real> edge2 = triangle.v[2] - triangle.v[0];
  30. Vector3<Real> normal = Cross(edge1, edge2);
  31. // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
  32. // E1 = edge1, E2 = edge2, N = Cross(E1,E2)) by
  33. // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
  34. // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
  35. // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
  36. Real DdN = Dot(ray.direction, normal);
  37. Real sign;
  38. if (DdN > (Real)0)
  39. {
  40. sign = (Real)1;
  41. }
  42. else if (DdN < (Real)0)
  43. {
  44. sign = (Real)-1;
  45. DdN = -DdN;
  46. }
  47. else
  48. {
  49. // Ray and triangle are parallel, call it a "no intersection"
  50. // even if the ray does intersect.
  51. result.intersect = false;
  52. return result;
  53. }
  54. Real DdQxE2 = sign * DotCross(ray.direction, diff, edge2);
  55. if (DdQxE2 >= (Real)0)
  56. {
  57. Real DdE1xQ = sign * DotCross(ray.direction, edge1, diff);
  58. if (DdE1xQ >= (Real)0)
  59. {
  60. if (DdQxE2 + DdE1xQ <= DdN)
  61. {
  62. // Line intersects triangle, check whether ray does.
  63. Real QdN = -sign * Dot(diff, normal);
  64. if (QdN >= (Real)0)
  65. {
  66. // Ray intersects triangle.
  67. result.intersect = true;
  68. return result;
  69. }
  70. // else: t < 0, no intersection
  71. }
  72. // else: b1+b2 > 1, no intersection
  73. }
  74. // else: b2 < 0, no intersection
  75. }
  76. // else: b1 < 0, no intersection
  77. result.intersect = false;
  78. return result;
  79. }
  80. };
  81. template <typename Real>
  82. class FIQuery<Real, Ray3<Real>, Triangle3<Real>>
  83. {
  84. public:
  85. struct Result
  86. {
  87. Result()
  88. :
  89. intersect(false),
  90. parameter((Real)0),
  91. triangleBary{ (Real)0, (Real)0, (Real)0 },
  92. point{ (Real)0, (Real)0, (Real)0 }
  93. {
  94. }
  95. bool intersect;
  96. Real parameter;
  97. std::array<Real, 3> triangleBary;
  98. Vector3<Real> point;
  99. };
  100. Result operator()(Ray3<Real> const& ray, Triangle3<Real> const& triangle)
  101. {
  102. Result result;
  103. // Compute the offset origin, edges, and normal.
  104. Vector3<Real> diff = ray.origin - triangle.v[0];
  105. Vector3<Real> edge1 = triangle.v[1] - triangle.v[0];
  106. Vector3<Real> edge2 = triangle.v[2] - triangle.v[0];
  107. Vector3<Real> normal = Cross(edge1, edge2);
  108. // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
  109. // E1 = edge1, E2 = edge2, N = Cross(E1,E2)) by
  110. // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
  111. // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
  112. // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
  113. Real DdN = Dot(ray.direction, normal);
  114. Real sign;
  115. if (DdN > (Real)0)
  116. {
  117. sign = (Real)1;
  118. }
  119. else if (DdN < (Real)0)
  120. {
  121. sign = (Real)-1;
  122. DdN = -DdN;
  123. }
  124. else
  125. {
  126. // Ray and triangle are parallel, call it a "no intersection"
  127. // even if the ray does intersect.
  128. result.intersect = false;
  129. return result;
  130. }
  131. Real DdQxE2 = sign * DotCross(ray.direction, diff, edge2);
  132. if (DdQxE2 >= (Real)0)
  133. {
  134. Real DdE1xQ = sign * DotCross(ray.direction, edge1, diff);
  135. if (DdE1xQ >= (Real)0)
  136. {
  137. if (DdQxE2 + DdE1xQ <= DdN)
  138. {
  139. // Line intersects triangle, check whether ray does.
  140. Real QdN = -sign * Dot(diff, normal);
  141. if (QdN >= (Real)0)
  142. {
  143. // Ray intersects triangle.
  144. result.intersect = true;
  145. Real inv = (Real)1 / DdN;
  146. result.parameter = QdN * inv;
  147. result.triangleBary[1] = DdQxE2 * inv;
  148. result.triangleBary[2] = DdE1xQ * inv;
  149. result.triangleBary[0] =
  150. (Real)1 - result.triangleBary[1] - result.triangleBary[2];
  151. result.point = ray.origin + result.parameter * ray.direction;
  152. return result;
  153. }
  154. // else: t < 0, no intersection
  155. }
  156. // else: b1+b2 > 1, no intersection
  157. }
  158. // else: b2 < 0, no intersection
  159. }
  160. // else: b1 < 0, no intersection
  161. result.intersect = false;
  162. return result;
  163. }
  164. };
  165. }