intersect.inl 6.2 KB

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