2 Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
\r
5 Physics Effects is open software; you can redistribute it and/or
\r
6 modify it under the terms of the BSD License.
\r
8 Physics Effects is distributed in the hope that it will be useful,
\r
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
\r
11 See the BSD License for more details.
\r
13 A copy of the BSD License is distributed with
\r
14 Physics Effects under the filename: physics_effects_license.txt
\r
17 #ifndef _SCE_PFX_INTERSECT_COMMON_H
\r
18 #define _SCE_PFX_INTERSECT_COMMON_H
\r
20 #include "../../../include/physics_effects/base_level/collision/pfx_ray.h"
\r
23 namespace PhysicsEffects {
\r
25 #define SCE_PFX_INTERSECT_COMMON_EPSILON 0.00001f
\r
26 #define SCE_PFX_RAY_TRIANGLE_EPSILON 0.00001f
\r
28 // Internally used intersect functions
\r
32 PfxVector3 points[3];
\r
34 PfxTriangle(const PfxVector3 &p0,const PfxVector3 &p1,const PfxVector3 &p2)
\r
44 PfxVector3 normal; // normal
\r
45 PfxVector3 point; // point on the plane
\r
47 PfxPlane(const PfxVector3 &n,const PfxVector3 &q)
\r
53 PfxPlane(const PfxTriangle &triangle)
\r
55 normal = normalize(cross(triangle.points[1]-triangle.points[0],triangle.points[2]-triangle.points[0]));
\r
56 point = triangle.points[0];
\r
59 PfxFloat onPlane(const PfxVector3 &p) const
\r
61 return dot((p-point),normal);
\r
65 static SCE_PFX_FORCE_INLINE
\r
66 PfxBool pfxIntersectRayAABBFast(
\r
67 const PfxVector3 &rayStartPosition,
\r
68 const PfxVector3 &rayDirection,
\r
69 const PfxVector3 &AABBcenter,
\r
70 const PfxVector3 &AABBhalf,
\r
73 PfxVector3 AABBmin = AABBcenter - AABBhalf;
\r
74 PfxVector3 AABBmax = AABBcenter + AABBhalf;
\r
76 PfxVector3 dir = rayDirection;
\r
77 PfxVector3 absDir = absPerElem(dir);
\r
78 PfxVector3 sign = copySignPerElem(PfxVector3(1.0),dir);
\r
80 if(absDir[0] < SCE_PFX_INTERSECT_COMMON_EPSILON) {
\r
81 if(rayStartPosition[0] < AABBmin[0] || rayStartPosition[0] > AABBmax[0]) {
\r
84 dir[0] = sign[0] * SCE_PFX_INTERSECT_COMMON_EPSILON;
\r
87 if(absDir[1] < SCE_PFX_INTERSECT_COMMON_EPSILON) {
\r
88 if(rayStartPosition[1] < AABBmin[1] || rayStartPosition[1] > AABBmax[1]) {
\r
91 dir[1] = sign[1] * SCE_PFX_INTERSECT_COMMON_EPSILON;
\r
94 if(absDir[2] < SCE_PFX_INTERSECT_COMMON_EPSILON) {
\r
95 if(rayStartPosition[2] < AABBmin[2] || rayStartPosition[2] > AABBmax[2]) {
\r
98 dir[2] = sign[2] * SCE_PFX_INTERSECT_COMMON_EPSILON;
\r
101 PfxVector3 t1 = divPerElem(AABBmin - rayStartPosition, dir);
\r
102 PfxVector3 t2 = divPerElem(AABBmax - rayStartPosition, dir);
\r
104 PfxVector3 tmin = minPerElem(t1,t2);
\r
105 PfxVector3 tmax = maxPerElem(t1,t2);
\r
107 if(maxElem(tmin) > minElem(tmax)) return false;
\r
109 if(tmin[0] > tmin[1]) {
\r
110 if(tmin[0] > tmin[2]) {
\r
111 variable = tmin[0];
\r
114 variable = tmin[2];
\r
118 if(tmin[1] > tmin[2]) {
\r
119 variable = tmin[1];
\r
122 variable = tmin[2];
\r
129 static SCE_PFX_FORCE_INLINE
\r
130 PfxBool pfxIntersectRayAABB(
\r
131 const PfxVector3 &rayStartPosition,
\r
132 const PfxVector3 &rayDirection,
\r
133 const PfxVector3 &AABBcenter,
\r
134 const PfxVector3 &AABBhalf,
\r
135 PfxFloat &variable,
\r
136 PfxVector3 &normal)
\r
138 PfxVector3 AABBmin = AABBcenter - AABBhalf;
\r
139 PfxVector3 AABBmax = AABBcenter + AABBhalf;
\r
141 PfxVector3 dir = rayDirection;
\r
142 PfxVector3 absDir = absPerElem(dir);
\r
143 PfxVector3 sign = copySignPerElem(PfxVector3(1.0),dir);
\r
146 if( AABBmin[0] < rayStartPosition[0] && rayStartPosition[0] < AABBmax[0] &&
\r
147 AABBmin[1] < rayStartPosition[1] && rayStartPosition[1] < AABBmax[1] &&
\r
148 AABBmin[2] < rayStartPosition[2] && rayStartPosition[2] < AABBmax[2]) {
\r
152 if(absDir[0] < SCE_PFX_INTERSECT_COMMON_EPSILON) {
\r
153 if(rayStartPosition[0] < AABBmin[0] || rayStartPosition[0] > AABBmax[0]) {
\r
156 dir[0] = sign[0] * SCE_PFX_INTERSECT_COMMON_EPSILON;
\r
159 if(absDir[1] < SCE_PFX_INTERSECT_COMMON_EPSILON) {
\r
160 if(rayStartPosition[1] < AABBmin[1] || rayStartPosition[1] > AABBmax[1]) {
\r
163 dir[1] = sign[1] * SCE_PFX_INTERSECT_COMMON_EPSILON;
\r
166 if(absDir[2] < SCE_PFX_INTERSECT_COMMON_EPSILON) {
\r
167 if(rayStartPosition[2] < AABBmin[2] || rayStartPosition[2] > AABBmax[2]) {
\r
170 dir[2] = sign[2] * SCE_PFX_INTERSECT_COMMON_EPSILON;
\r
173 PfxVector3 t1 = divPerElem(AABBmin - rayStartPosition, dir);
\r
174 PfxVector3 t2 = divPerElem(AABBmax - rayStartPosition, dir);
\r
176 PfxVector3 tmin = minPerElem(t1,t2);
\r
177 PfxVector3 tmax = maxPerElem(t1,t2);
\r
179 normal = PfxVector3(0);
\r
181 if(maxElem(tmin) > minElem(tmax)) return false;
\r
183 if(tmin[0] > tmin[1]) {
\r
184 if(tmin[0] > tmin[2]) {
\r
185 variable = tmin[0];
\r
186 normal[0] = -sign[0];
\r
189 variable = tmin[2];
\r
190 normal[2] = -sign[2];
\r
194 if(tmin[1] > tmin[2]) {
\r
195 variable = tmin[1];
\r
196 normal[1] = -sign[1];
\r
199 variable = tmin[2];
\r
200 normal[2] = -sign[2];
\r
207 static SCE_PFX_FORCE_INLINE
\r
208 void pfxClosestTwoLines(
\r
209 const PfxVector3 &p1,const PfxVector3 &q1, // line1
\r
210 const PfxVector3 &p2,const PfxVector3 &q2, // line2
\r
211 PfxVector3 &s1,PfxVector3 &s2)
\r
213 PfxVector3 v1 = q1-p1;
\r
214 PfxVector3 v2 = q2-p2;
\r
215 PfxVector3 r = p1 - p2;
\r
217 PfxFloat a = dot(v1,v1);
\r
218 PfxFloat e = dot(v2,v2);
\r
219 PfxFloat f = dot(v2,r);
\r
220 PfxFloat b = dot(v1,v2);
\r
221 PfxFloat c = dot(v1,r);
\r
222 PfxFloat den = a*e-b*b;
\r
227 s = SCE_PFX_CLAMP((b*f-c*e)/den,0.0f,1.0f);
\r
237 s = SCE_PFX_CLAMP(-c/a,0.0f,1.0f);
\r
239 else if(t > 1.0f) {
\r
241 s = SCE_PFX_CLAMP((b-c)/a,0.0f,1.0f);
\r
248 static SCE_PFX_FORCE_INLINE
\r
249 void pfxClosestPointAABB(
\r
250 const PfxVector3 &point,
\r
251 const PfxVector3 &AABBhalf,
\r
255 s = maxPerElem(s,-AABBhalf);
\r
256 s = minPerElem(s,AABBhalf);
\r
259 static SCE_PFX_FORCE_INLINE
\r
260 void pfxClosestPointTriangle(
\r
261 const PfxVector3 &point,
\r
262 const PfxTriangle &triangle,
\r
265 PfxVector3 a = triangle.points[0];
\r
266 PfxVector3 b = triangle.points[1];
\r
267 PfxVector3 c = triangle.points[2];
\r
268 PfxVector3 ab = b - a;
\r
269 PfxVector3 ac = c - a;
\r
270 PfxVector3 ap = point - a;
\r
271 PfxFloat d1 = dot(ab, ap);
\r
272 PfxFloat d2 = dot(ac, ap);
\r
273 if(d1 <= 0.0f && d2 <= 0.0f) {
\r
278 PfxVector3 bp = point - b;
\r
279 PfxFloat d3 = dot(ab, bp);
\r
280 PfxFloat d4 = dot(ac, bp);
\r
281 if (d3 >= 0.0f && d4 <= d3) {
\r
286 PfxFloat vc = d1*d4 - d3*d2;
\r
287 if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
\r
288 PfxFloat v = d1 / (d1 - d3);
\r
293 PfxVector3 cp = point - c;
\r
294 PfxFloat d5 = dot(ab, cp);
\r
295 PfxFloat d6 = dot(ac, cp);
\r
296 if (d6 >= 0.0f && d5 <= d6) {
\r
301 PfxFloat vb = d5*d2 - d1*d6;
\r
302 if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
\r
303 PfxFloat w = d2 / (d2 - d6);
\r
308 PfxFloat va = d3*d6 - d5*d4;
\r
309 if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
\r
310 PfxFloat w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
\r
311 s = b + w * (c - b);
\r
315 PfxFloat den = 1.0f / (va + vb + vc);
\r
316 PfxFloat v = vb * den;
\r
317 PfxFloat w = vc * den;
\r
318 s = a + ab * v + ac * w;
\r
321 static SCE_PFX_FORCE_INLINE
\r
322 PfxBool pfxIntersectRayTriangle(
\r
323 const PfxVector3 &rayStartPosition,
\r
324 const PfxVector3 &rayDirection,
\r
325 const PfxTriangle &triangle,
\r
326 PfxFloat &variable)
\r
329 PfxVector3 ab = triangle.points[1] - triangle.points[0];
\r
330 PfxVector3 ac = triangle.points[2] - triangle.points[0];
\r
332 PfxVector3 n = cross(ab,ac);
\r
334 PfxFloat d = dot(-rayDirection,n);
\r
336 if(fabsf(d) < 0.00001f) return false;
\r
338 PfxVector3 ap = rayStartPosition - triangle.points[0];
\r
339 PfxFloat t = dot(ap,n) / d;
\r
341 if(t <= 0.0f || t >= 1.0f) return false;
\r
345 PfxVector3 e = cross(-rayDirection,ap);
\r
347 if(v < -SCE_PFX_RAY_TRIANGLE_EPSILON || v > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false;
\r
349 w = -dot(ab,e) / d;
\r
350 if(w < -SCE_PFX_RAY_TRIANGLE_EPSILON || v+w > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false;
\r
355 static SCE_PFX_FORCE_INLINE
\r
356 PfxBool pfxIntersectRayTriangleWithoutFrontFace(
\r
357 const PfxVector3 &rayStartPosition,
\r
358 const PfxVector3 &rayDirection,
\r
359 const PfxTriangle &triangle,
\r
360 PfxFloat &variable)
\r
363 PfxVector3 ab = triangle.points[1] - triangle.points[0];
\r
364 PfxVector3 ac = triangle.points[2] - triangle.points[0];
\r
366 PfxVector3 n = cross(ab,ac);
\r
368 PfxFloat d = dot(-rayDirection,n);
\r
370 if(d >= 0.0f) return false;
\r
372 PfxVector3 ap = rayStartPosition - triangle.points[0];
\r
373 PfxFloat t = dot(ap,n) / d;
\r
375 if(t <= 0.0f || t >= 1.0f) return false;
\r
379 PfxVector3 e = cross(-rayDirection,ap);
\r
381 if(v < -SCE_PFX_RAY_TRIANGLE_EPSILON || v > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false;
\r
383 w = -dot(ab,e) / d;
\r
384 if(w < -SCE_PFX_RAY_TRIANGLE_EPSILON || v+w > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false;
\r
389 static SCE_PFX_FORCE_INLINE
\r
390 PfxBool pfxIntersectRayTriangleWithoutBackFace(
\r
391 const PfxVector3 &rayStartPosition,
\r
392 const PfxVector3 &rayDirection,
\r
393 const PfxTriangle &triangle,
\r
394 PfxFloat &variable)
\r
397 PfxVector3 ab = triangle.points[1] - triangle.points[0];
\r
398 PfxVector3 ac = triangle.points[2] - triangle.points[0];
\r
400 PfxVector3 n = cross(ab,ac);
\r
402 PfxFloat d = dot(-rayDirection,n);
\r
404 if(d <= 0.0f) return false;
\r
406 PfxVector3 ap = rayStartPosition - triangle.points[0];
\r
407 PfxFloat t = dot(ap,n) / d;
\r
409 if(t <= 0.0f || t >= 1.0f) return false;
\r
413 PfxVector3 e = cross(-rayDirection,ap);
\r
415 if(v < -SCE_PFX_RAY_TRIANGLE_EPSILON || v > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false;
\r
417 w = -dot(ab,e) / d;
\r
418 if(w < -SCE_PFX_RAY_TRIANGLE_EPSILON || v+w > 1.0f+SCE_PFX_RAY_TRIANGLE_EPSILON) return false;
\r
423 } //namespace PhysicsEffects
\r
427 #endif // _SCE_PFX_INTERSECT_COMMON_H
\r