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