1 /////////////////////////////////////////////////////////////////////////////////////////////////// 2 // OpenGL Mathematics Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) 3 /////////////////////////////////////////////////////////////////////////////////////////////////// 4 // Created : 2007-04-03 5 // Updated : 2009-01-20 6 // Licence : This source is under MIT licence 7 // File : glm/gtx/intersect.inl 8 /////////////////////////////////////////////////////////////////////////////////////////////////// 9 10 #include "../geometric.hpp" 11 #include <cfloat> 12 #include <limits> 13 14 namespace glm 15 { 16 template <typename genType> 17 GLM_FUNC_QUALIFIER bool intersectRayPlane 18 ( 19 genType const & orig, genType const & dir, 20 genType const & planeOrig, genType const & planeNormal, 21 typename genType::value_type & intersectionDistance 22 ) 23 { 24 typename genType::value_type d = glm::dot(dir, planeNormal); 25 typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); 26 27 if(d < Epsilon) 28 { 29 intersectionDistance = glm::dot(planeOrig - orig, planeNormal) / d; 30 return true; 31 } 32 33 return false; 34 } 35 36 template <typename genType> 37 GLM_FUNC_QUALIFIER bool intersectRayTriangle 38 ( 39 genType const & orig, genType const & dir, 40 genType const & v0, genType const & v1, genType const & v2, 41 genType & baryPosition 42 ) 43 { 44 genType e1 = v1 - v0; 45 genType e2 = v2 - v0; 46 47 genType p = glm::cross(dir, e2); 48 49 typename genType::value_type a = glm::dot(e1, p); 50 51 typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); 52 if(a < Epsilon) 53 return false; 54 55 typename genType::value_type f = typename genType::value_type(1.0f) / a; 56 57 genType s = orig - v0; 58 baryPosition.x = f * glm::dot(s, p); 59 if(baryPosition.x < typename genType::value_type(0.0f)) 60 return false; 61 if(baryPosition.x > typename genType::value_type(1.0f)) 62 return false; 63 64 genType q = glm::cross(s, e1); 65 baryPosition.y = f * glm::dot(dir, q); 66 if(baryPosition.y < typename genType::value_type(0.0f)) 67 return false; 68 if(baryPosition.y + baryPosition.x > typename genType::value_type(1.0f)) 69 return false; 70 71 baryPosition.z = f * glm::dot(e2, q); 72 73 return baryPosition.z >= typename genType::value_type(0.0f); 74 } 75 76 //template <typename genType> 77 //GLM_FUNC_QUALIFIER bool intersectRayTriangle 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 // 86 // genType edge1 = vert1 - vert0; 87 // genType edge2 = vert2 - vert0; 88 // 89 // genType pvec = cross(dir, edge2); 90 // 91 // float det = dot(edge1, pvec); 92 // if(det < Epsilon) 93 // return false; 94 // 95 // genType tvec = orig - vert0; 96 // 97 // position.y = dot(tvec, pvec); 98 // if (position.y < typename genType::value_type(0) || position.y > det) 99 // return typename genType::value_type(0); 100 // 101 // genType qvec = cross(tvec, edge1); 102 // 103 // position.z = dot(dir, qvec); 104 // if (position.z < typename genType::value_type(0) || position.y + position.z > det) 105 // return typename genType::value_type(0); 106 // 107 // position.x = dot(edge2, qvec); 108 // position *= typename genType::value_type(1) / det; 109 // 110 // return typename genType::value_type(1); 111 //} 112 113 template <typename genType> 114 GLM_FUNC_QUALIFIER bool intersectLineTriangle 115 ( 116 genType const & orig, genType const & dir, 117 genType const & vert0, genType const & vert1, genType const & vert2, 118 genType & position 119 ) 120 { 121 typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); 122 123 genType edge1 = vert1 - vert0; 124 genType edge2 = vert2 - vert0; 125 126 genType pvec = cross(dir, edge2); 127 128 float det = dot(edge1, pvec); 129 130 if (det > -Epsilon && det < Epsilon) 131 return false; 132 float inv_det = typename genType::value_type(1) / det; 133 134 genType tvec = orig - vert0; 135 136 position.y = dot(tvec, pvec) * inv_det; 137 if (position.y < typename genType::value_type(0) || position.y > typename genType::value_type(1)) 138 return false; 139 140 genType qvec = cross(tvec, edge1); 141 142 position.z = dot(dir, qvec) * inv_det; 143 if (position.z < typename genType::value_type(0) || position.y + position.z > typename genType::value_type(1)) 144 return false; 145 146 position.x = dot(edge2, qvec) * inv_det; 147 148 return true; 149 } 150 151 template <typename genType> 152 GLM_FUNC_QUALIFIER bool intersectRaySphere 153 ( 154 genType const & rayStarting, genType const & rayNormalizedDirection, 155 genType const & sphereCenter, const typename genType::value_type sphereRadiusSquered, 156 typename genType::value_type & intersectionDistance 157 ) 158 { 159 typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); 160 genType diff = sphereCenter - rayStarting; 161 typename genType::value_type t0 = dot(diff, rayNormalizedDirection); 162 typename genType::value_type dSquared = dot(diff, diff) - t0 * t0; 163 if( dSquared > sphereRadiusSquered ) 164 { 165 return false; 166 } 167 typename genType::value_type t1 = sqrt( sphereRadiusSquered - dSquared ); 168 intersectionDistance = t0 > t1 + Epsilon ? t0 - t1 : t0 + t1; 169 return intersectionDistance > Epsilon; 170 } 171 172 template <typename genType> 173 GLM_FUNC_QUALIFIER bool intersectRaySphere 174 ( 175 genType const & rayStarting, genType const & rayNormalizedDirection, 176 genType const & sphereCenter, const typename genType::value_type sphereRadius, 177 genType & intersectionPosition, genType & intersectionNormal 178 ) 179 { 180 typename genType::value_type distance; 181 if( intersectRaySphere( rayStarting, rayNormalizedDirection, sphereCenter, sphereRadius * sphereRadius, distance ) ) 182 { 183 intersectionPosition = rayStarting + rayNormalizedDirection * distance; 184 intersectionNormal = (intersectionPosition - sphereCenter) / sphereRadius; 185 return true; 186 } 187 return false; 188 } 189 190 template <typename genType> 191 GLM_FUNC_QUALIFIER bool intersectLineSphere 192 ( 193 genType const & point0, genType const & point1, 194 genType const & sphereCenter, typename genType::value_type sphereRadius, 195 genType & intersectionPoint1, genType & intersectionNormal1, 196 genType & intersectionPoint2, genType & intersectionNormal2 197 ) 198 { 199 typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); 200 genType dir = normalize(point1 - point0); 201 genType diff = sphereCenter - point0; 202 typename genType::value_type t0 = dot(diff, dir); 203 typename genType::value_type dSquared = dot(diff, diff) - t0 * t0; 204 if( dSquared > sphereRadius * sphereRadius ) 205 { 206 return false; 207 } 208 typename genType::value_type t1 = sqrt( sphereRadius * sphereRadius - dSquared ); 209 if( t0 < t1 + Epsilon ) 210 t1 = -t1; 211 intersectionPoint1 = point0 + dir * (t0 - t1); 212 intersectionNormal1 = (intersectionPoint1 - sphereCenter) / sphereRadius; 213 intersectionPoint2 = point0 + dir * (t0 + t1); 214 intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius; 215 return true; 216 } 217 }//namespace glm 218