1/// @ref gtx_intersect
2/// @file glm/gtx/intersect.inl
3
4namespace glm
5{
6	template <typename genType>
7	GLM_FUNC_QUALIFIER bool intersectRayPlane
8	(
9		genType const & orig, genType const & dir,
10		genType const & planeOrig, genType const & planeNormal,
11		typename genType::value_type & intersectionDistance
12	)
13	{
14		typename genType::value_type d = glm::dot(dir, planeNormal);
15		typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
16
17		if(d < -Epsilon)
18		{
19			intersectionDistance = glm::dot(planeOrig - orig, planeNormal) / d;
20			return true;
21		}
22
23		return false;
24	}
25
26	template <typename genType>
27	GLM_FUNC_QUALIFIER bool intersectRayTriangle
28	(
29		genType const & orig, genType const & dir,
30		genType const & v0, genType const & v1, genType const & v2,
31		genType & baryPosition
32	)
33	{
34		genType e1 = v1 - v0;
35		genType e2 = v2 - v0;
36
37		genType p = glm::cross(dir, e2);
38
39		typename genType::value_type a = glm::dot(e1, p);
40
41		typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
42		if(a < Epsilon && a > -Epsilon)
43			return false;
44
45		typename genType::value_type f = typename genType::value_type(1.0f) / a;
46
47		genType s = orig - v0;
48		baryPosition.x = f * glm::dot(s, p);
49		if(baryPosition.x < typename genType::value_type(0.0f))
50			return false;
51		if(baryPosition.x > typename genType::value_type(1.0f))
52			return false;
53
54		genType q = glm::cross(s, e1);
55		baryPosition.y = f * glm::dot(dir, q);
56		if(baryPosition.y < typename genType::value_type(0.0f))
57			return false;
58		if(baryPosition.y + baryPosition.x > typename genType::value_type(1.0f))
59			return false;
60
61		baryPosition.z = f * glm::dot(e2, q);
62
63		return baryPosition.z >= typename genType::value_type(0.0f);
64	}
65
66	template <typename genType>
67	GLM_FUNC_QUALIFIER bool intersectLineTriangle
68	(
69		genType const & orig, genType const & dir,
70		genType const & vert0, genType const & vert1, genType const & vert2,
71		genType & position
72	)
73	{
74		typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
75
76		genType edge1 = vert1 - vert0;
77		genType edge2 = vert2 - vert0;
78
79		genType pvec = cross(dir, edge2);
80
81		float det = dot(edge1, pvec);
82
83		if (det > -Epsilon && det < Epsilon)
84			return false;
85		float inv_det = typename genType::value_type(1) / det;
86
87		genType tvec = orig - vert0;
88
89		position.y = dot(tvec, pvec) * inv_det;
90		if (position.y < typename genType::value_type(0) || position.y > typename genType::value_type(1))
91			return false;
92
93		genType qvec = cross(tvec, edge1);
94
95		position.z = dot(dir, qvec) * inv_det;
96		if (position.z < typename genType::value_type(0) || position.y + position.z > typename genType::value_type(1))
97			return false;
98
99		position.x = dot(edge2, qvec) * inv_det;
100
101		return true;
102	}
103
104	template <typename genType>
105	GLM_FUNC_QUALIFIER bool intersectRaySphere
106	(
107		genType const & rayStarting, genType const & rayNormalizedDirection,
108		genType const & sphereCenter, const typename genType::value_type sphereRadiusSquered,
109		typename genType::value_type & intersectionDistance
110	)
111	{
112		typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
113		genType diff = sphereCenter - rayStarting;
114		typename genType::value_type t0 = dot(diff, rayNormalizedDirection);
115		typename genType::value_type dSquared = dot(diff, diff) - t0 * t0;
116		if( dSquared > sphereRadiusSquered )
117		{
118			return false;
119		}
120		typename genType::value_type t1 = sqrt( sphereRadiusSquered - dSquared );
121		intersectionDistance = t0 > t1 + Epsilon ? t0 - t1 : t0 + t1;
122		return intersectionDistance > Epsilon;
123	}
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
143	template <typename genType>
144	GLM_FUNC_QUALIFIER bool intersectLineSphere
145	(
146		genType const & point0, genType const & point1,
147		genType const & sphereCenter, typename genType::value_type sphereRadius,
148		genType & intersectionPoint1, genType & intersectionNormal1,
149		genType & intersectionPoint2, genType & intersectionNormal2
150	)
151	{
152		typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
153		genType dir = normalize(point1 - point0);
154		genType diff = sphereCenter - point0;
155		typename genType::value_type t0 = dot(diff, dir);
156		typename genType::value_type dSquared = dot(diff, diff) - t0 * t0;
157		if( dSquared > sphereRadius * sphereRadius )
158		{
159			return false;
160		}
161		typename genType::value_type t1 = sqrt( sphereRadius * sphereRadius - dSquared );
162		if( t0 < t1 + Epsilon )
163			t1 = -t1;
164		intersectionPoint1 = point0 + dir * (t0 - t1);
165		intersectionNormal1 = (intersectionPoint1 - sphereCenter) / sphereRadius;
166		intersectionPoint2 = point0 + dir * (t0 + t1);
167		intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius;
168		return true;
169	}
170}//namespace glm
171