DistRayRay.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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/DCPQuery.h>
  9. #include <Mathematics/Ray.h>
  10. namespace WwiseGTE
  11. {
  12. template <int N, typename Real>
  13. class DCPQuery<Real, Ray<N, Real>, Ray<N, Real>>
  14. {
  15. public:
  16. struct Result
  17. {
  18. Real distance, sqrDistance;
  19. Real parameter[2];
  20. Vector<N, Real> closestPoint[2];
  21. };
  22. Result operator()(Ray<N, Real> const& ray0, Ray<N, Real> const& ray1)
  23. {
  24. Result result;
  25. Vector<N, Real> diff = ray0.origin - ray1.origin;
  26. Real a01 = -Dot(ray0.direction, ray1.direction);
  27. Real b0 = Dot(diff, ray0.direction), b1;
  28. Real s0, s1;
  29. if (std::fabs(a01) < (Real)1)
  30. {
  31. // Rays are not parallel.
  32. b1 = -Dot(diff, ray1.direction);
  33. s0 = a01 * b1 - b0;
  34. s1 = a01 * b0 - b1;
  35. if (s0 >= (Real)0)
  36. {
  37. if (s1 >= (Real)0) // region 0 (interior)
  38. {
  39. // Minimum at two interior points of rays.
  40. Real det = (Real)1 - a01 * a01;
  41. s0 /= det;
  42. s1 /= det;
  43. }
  44. else // region 3 (side)
  45. {
  46. s1 = (Real)0;
  47. if (b0 >= (Real)0)
  48. {
  49. s0 = (Real)0;
  50. }
  51. else
  52. {
  53. s0 = -b0;
  54. }
  55. }
  56. }
  57. else
  58. {
  59. if (s1 >= (Real)0) // region 1 (side)
  60. {
  61. s0 = (Real)0;
  62. if (b1 >= (Real)0)
  63. {
  64. s1 = (Real)0;
  65. }
  66. else
  67. {
  68. s1 = -b1;
  69. }
  70. }
  71. else // region 2 (corner)
  72. {
  73. if (b0 < (Real)0)
  74. {
  75. s0 = -b0;
  76. s1 = (Real)0;
  77. }
  78. else
  79. {
  80. s0 = (Real)0;
  81. if (b1 >= (Real)0)
  82. {
  83. s1 = (Real)0;
  84. }
  85. else
  86. {
  87. s1 = -b1;
  88. }
  89. }
  90. }
  91. }
  92. }
  93. else
  94. {
  95. // Rays are parallel.
  96. if (a01 > (Real)0)
  97. {
  98. // Opposite direction vectors.
  99. s1 = (Real)0;
  100. if (b0 >= (Real)0)
  101. {
  102. s0 = (Real)0;
  103. }
  104. else
  105. {
  106. s0 = -b0;
  107. }
  108. }
  109. else
  110. {
  111. // Same direction vectors.
  112. if (b0 >= (Real)0)
  113. {
  114. b1 = -Dot(diff, ray1.direction);
  115. s0 = (Real)0;
  116. s1 = -b1;
  117. }
  118. else
  119. {
  120. s0 = -b0;
  121. s1 = (Real)0;
  122. }
  123. }
  124. }
  125. result.parameter[0] = s0;
  126. result.parameter[1] = s1;
  127. result.closestPoint[0] = ray0.origin + s0 * ray0.direction;
  128. result.closestPoint[1] = ray1.origin + s1 * ray1.direction;
  129. diff = result.closestPoint[0] - result.closestPoint[1];
  130. result.sqrDistance = Dot(diff, diff);
  131. result.distance = std::sqrt(result.sqrDistance);
  132. return result;
  133. }
  134. };
  135. // Template aliases for convenience.
  136. template <int N, typename Real>
  137. using DCPRayRay = DCPQuery<Real, Ray<N, Real>, Ray<N, Real>>;
  138. template <typename Real>
  139. using DCPRay2Ray2 = DCPRayRay<2, Real>;
  140. template <typename Real>
  141. using DCPRay3Ray3 = DCPRayRay<3, Real>;
  142. }