9
3

intersect.inl 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /// @ref gtx_intersect
  2. namespace glm
  3. {
  4. template<typename genType>
  5. GLM_FUNC_QUALIFIER bool intersectRayPlane
  6. (
  7. genType const& orig, genType const& dir,
  8. genType const& planeOrig, genType const& planeNormal,
  9. typename genType::value_type & intersectionDistance
  10. )
  11. {
  12. typename genType::value_type d = glm::dot(dir, planeNormal);
  13. typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
  14. if(glm::abs(d) > Epsilon) // if dir and planeNormal are not perpendicular
  15. {
  16. typename genType::value_type const tmp_intersectionDistance = glm::dot(planeOrig - orig, planeNormal) / d;
  17. if (tmp_intersectionDistance > static_cast<typename genType::value_type>(0)) { // allow only intersections
  18. intersectionDistance = tmp_intersectionDistance;
  19. return true;
  20. }
  21. }
  22. return false;
  23. }
  24. template<typename T, qualifier Q>
  25. GLM_FUNC_QUALIFIER bool intersectRayTriangle
  26. (
  27. vec<3, T, Q> const& orig, vec<3, T, Q> const& dir,
  28. vec<3, T, Q> const& vert0, vec<3, T, Q> const& vert1, vec<3, T, Q> const& vert2,
  29. vec<2, T, Q>& baryPosition, T& distance
  30. )
  31. {
  32. // find vectors for two edges sharing vert0
  33. vec<3, T, Q> const edge1 = vert1 - vert0;
  34. vec<3, T, Q> const edge2 = vert2 - vert0;
  35. // begin calculating determinant - also used to calculate U parameter
  36. vec<3, T, Q> const p = glm::cross(dir, edge2);
  37. // if determinant is near zero, ray lies in plane of triangle
  38. T const det = glm::dot(edge1, p);
  39. vec<3, T, Q> Perpendicular(0);
  40. if(det > std::numeric_limits<T>::epsilon())
  41. {
  42. // calculate distance from vert0 to ray origin
  43. vec<3, T, Q> const dist = orig - vert0;
  44. // calculate U parameter and test bounds
  45. baryPosition.x = glm::dot(dist, p);
  46. if(baryPosition.x < static_cast<T>(0) || baryPosition.x > det)
  47. return false;
  48. // prepare to test V parameter
  49. Perpendicular = glm::cross(dist, edge1);
  50. // calculate V parameter and test bounds
  51. baryPosition.y = glm::dot(dir, Perpendicular);
  52. if((baryPosition.y < static_cast<T>(0)) || ((baryPosition.x + baryPosition.y) > det))
  53. return false;
  54. }
  55. else if(det < -std::numeric_limits<T>::epsilon())
  56. {
  57. // calculate distance from vert0 to ray origin
  58. vec<3, T, Q> const dist = orig - vert0;
  59. // calculate U parameter and test bounds
  60. baryPosition.x = glm::dot(dist, p);
  61. if((baryPosition.x > static_cast<T>(0)) || (baryPosition.x < det))
  62. return false;
  63. // prepare to test V parameter
  64. Perpendicular = glm::cross(dist, edge1);
  65. // calculate V parameter and test bounds
  66. baryPosition.y = glm::dot(dir, Perpendicular);
  67. if((baryPosition.y > static_cast<T>(0)) || (baryPosition.x + baryPosition.y < det))
  68. return false;
  69. }
  70. else
  71. return false; // ray is parallel to the plane of the triangle
  72. T inv_det = static_cast<T>(1) / det;
  73. // calculate distance, ray intersects triangle
  74. distance = glm::dot(edge2, Perpendicular) * inv_det;
  75. baryPosition *= inv_det;
  76. return true;
  77. }
  78. template<typename genType>
  79. GLM_FUNC_QUALIFIER bool intersectLineTriangle
  80. (
  81. genType const& orig, genType const& dir,
  82. genType const& vert0, genType const& vert1, genType const& vert2,
  83. genType & position
  84. )
  85. {
  86. typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
  87. genType edge1 = vert1 - vert0;
  88. genType edge2 = vert2 - vert0;
  89. genType Perpendicular = cross(dir, edge2);
  90. float det = dot(edge1, Perpendicular);
  91. if (det > -Epsilon && det < Epsilon)
  92. return false;
  93. typename genType::value_type inv_det = typename genType::value_type(1) / det;
  94. genType Tengant = orig - vert0;
  95. position.y = dot(Tengant, Perpendicular) * inv_det;
  96. if (position.y < typename genType::value_type(0) || position.y > typename genType::value_type(1))
  97. return false;
  98. genType Cotengant = cross(Tengant, edge1);
  99. position.z = dot(dir, Cotengant) * inv_det;
  100. if (position.z < typename genType::value_type(0) || position.y + position.z > typename genType::value_type(1))
  101. return false;
  102. position.x = dot(edge2, Cotengant) * inv_det;
  103. return true;
  104. }
  105. template<typename genType>
  106. GLM_FUNC_QUALIFIER bool intersectRaySphere
  107. (
  108. genType const& rayStarting, genType const& rayNormalizedDirection,
  109. genType const& sphereCenter, const typename genType::value_type sphereRadiusSquered,
  110. typename genType::value_type & intersectionDistance
  111. )
  112. {
  113. typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
  114. genType diff = sphereCenter - rayStarting;
  115. typename genType::value_type t0 = dot(diff, rayNormalizedDirection);
  116. typename genType::value_type dSquared = dot(diff, diff) - t0 * t0;
  117. if( dSquared > sphereRadiusSquered )
  118. {
  119. return false;
  120. }
  121. typename genType::value_type t1 = sqrt( sphereRadiusSquered - dSquared );
  122. intersectionDistance = t0 > t1 + Epsilon ? t0 - t1 : t0 + t1;
  123. return intersectionDistance > Epsilon;
  124. }
  125. template<typename genType>
  126. GLM_FUNC_QUALIFIER bool intersectRaySphere
  127. (
  128. genType const& rayStarting, genType const& rayNormalizedDirection,
  129. genType const& sphereCenter, const typename genType::value_type sphereRadius,
  130. genType & intersectionPosition, genType & intersectionNormal
  131. )
  132. {
  133. typename genType::value_type distance;
  134. if( intersectRaySphere( rayStarting, rayNormalizedDirection, sphereCenter, sphereRadius * sphereRadius, distance ) )
  135. {
  136. intersectionPosition = rayStarting + rayNormalizedDirection * distance;
  137. intersectionNormal = (intersectionPosition - sphereCenter) / sphereRadius;
  138. return true;
  139. }
  140. return false;
  141. }
  142. template<typename genType>
  143. GLM_FUNC_QUALIFIER bool intersectLineSphere
  144. (
  145. genType const& point0, genType const& point1,
  146. genType const& sphereCenter, typename genType::value_type sphereRadius,
  147. genType & intersectionPoint1, genType & intersectionNormal1,
  148. genType & intersectionPoint2, genType & intersectionNormal2
  149. )
  150. {
  151. typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
  152. genType dir = normalize(point1 - point0);
  153. genType diff = sphereCenter - point0;
  154. typename genType::value_type t0 = dot(diff, dir);
  155. typename genType::value_type dSquared = dot(diff, diff) - t0 * t0;
  156. if( dSquared > sphereRadius * sphereRadius )
  157. {
  158. return false;
  159. }
  160. typename genType::value_type t1 = sqrt( sphereRadius * sphereRadius - dSquared );
  161. if( t0 < t1 + Epsilon )
  162. t1 = -t1;
  163. intersectionPoint1 = point0 + dir * (t0 - t1);
  164. intersectionNormal1 = (intersectionPoint1 - sphereCenter) / sphereRadius;
  165. intersectionPoint2 = point0 + dir * (t0 + t1);
  166. intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius;
  167. return true;
  168. }
  169. }//namespace glm