Home | History | Annotate | Download | only in gtx
      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