46 static const real zero = real(0);
47 static const real eps =
static_cast<real
>(1e-12);
50 #define ZERO_TEST(x) (abs(x) <= eps) 54 inline int tri_tri_overlap_test_3d(real p1[3], real q1[3], real r1[3],
55 real p2[3], real q2[3], real r2[3]);
57 inline int coplanar_tri_tri3d(real p1[3], real q1[3], real r1[3],
58 real p2[3], real q2[3], real r2[3],
59 real N1[3], real N2[3]);
61 inline int tri_tri_overlap_test_2d(real p1[2], real q1[2], real r1[2],
62 real p2[2], real q2[2], real r2[2]);
64 inline int tri_tri_intersection_test_3d(real p1[3], real q1[3], real r1[3],
65 real p2[3], real q2[3], real r2[3],
67 real source[3], real target[3]);
74 #define CROSS(dest,v1,v2) dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; \ 75 dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; \ 76 dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; 78 #define DOT(v1,v2) (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]) 82 #define SUB(dest,v1,v2) dest[0] = v1[0] - v2[0]; \ 83 dest[1] = v1[1] - v2[1]; \ 84 dest[2] = v1[2] - v2[2]; 87 #define SCALAR(dest,alpha,v) dest[0] = alpha * v[0]; \ 88 dest[1] = alpha * v[1]; \ 89 dest[2] = alpha * v[2]; 94 #define CHECK_MIN_MAX(p1,q1,r1,p2,q2,r2) \ 100 if (DOT(v1,N1) >= -eps) return 0; \ 105 if (DOT(v1,N1) >= -eps) return 0; \ 111 #define TRI_TRI_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2) \ 114 if (dq2 > zero) CHECK_MIN_MAX(p1,r1,q1,r2,p2,q2) \ 115 else if (dr2 > zero) CHECK_MIN_MAX(p1,r1,q1,q2,r2,p2) \ 116 else CHECK_MIN_MAX(p1,q1,r1,p2,q2,r2) \ 117 } else if (dp2 < zero) { \ 118 if (dq2 < zero) CHECK_MIN_MAX(p1,q1,r1,r2,p2,q2) \ 119 else if (dr2 < zero) CHECK_MIN_MAX(p1,q1,r1,q2,r2,p2) \ 120 else CHECK_MIN_MAX(p1,r1,q1,p2,q2,r2) \ 123 if (dr2 >= zero) CHECK_MIN_MAX(p1,r1,q1,q2,r2,p2) \ 124 else CHECK_MIN_MAX(p1,q1,r1,p2,q2,r2) \ 125 } else if (dq2 > zero) { \ 126 if (dr2 > zero) CHECK_MIN_MAX(p1,r1,q1,p2,q2,r2) \ 127 else CHECK_MIN_MAX(p1,q1,r1,q2,r2,p2) \ 129 if (dr2 > zero) CHECK_MIN_MAX(p1,q1,r1,r2,p2,q2) \ 130 else if (dr2 < zero) CHECK_MIN_MAX(p1,r1,q1,r2,p2,q2) \ 131 else return coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1,N2); \ 144 int tri_tri_overlap_test_3d(real p1[3], real q1[3], real r1[3],
145 real p2[3], real q2[3], real r2[3])
147 real dp1, dq1, dr1, dp2, dq2, dr2;
163 if (((dp1 * dq1) > zero) && ((dp1 * dr1) > zero)) return 0;
177 if (((dp2 * dq2) > zero) && ((dp2 * dr2) > zero)) return 0;
180 if (ZERO_TEST(dp1)) dp1 = zero;
181 if (ZERO_TEST(dq1)) dq1 = zero;
182 if (ZERO_TEST(dr1)) dr1 = zero;
184 if (ZERO_TEST(dp2)) dp2 = zero;
185 if (ZERO_TEST(dq2)) dq2 = zero;
186 if (ZERO_TEST(dr2)) dr2 = zero;
189 if (dq1 > zero) TRI_TRI_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2)
190 else if (dr1 > zero) TRI_TRI_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2)
191 else TRI_TRI_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2)
192 } else if (dp1 < zero) {
193 if (dq1 < zero) TRI_TRI_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2)
194 else if (dr1 < zero) TRI_TRI_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2)
195 else TRI_TRI_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2)
198 if (dr1 >= zero) TRI_TRI_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2)
199 else TRI_TRI_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2)
200 } else if (dq1 > zero) {
201 if (dr1 > zero) TRI_TRI_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2)
202 else TRI_TRI_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2)
204 if (dr1 > zero) TRI_TRI_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2)
205 else if (dr1 < zero) TRI_TRI_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2)
206 else return coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1,N2);
212 int coplanar_tri_tri3d(real p1[3], real q1[3], real r1[3],
213 real p2[3], real q2[3], real r2[3],
214 real normal_1[3], real normal_2[3])
216 real P1[2],Q1[2],R1[2];
217 real P2[2],Q2[2],R2[2];
221 n_x = ((normal_1[0] < zero) ? -normal_1[0] : normal_1[0]);
222 n_y = ((normal_1[1] < zero) ? -normal_1[1] : normal_1[1]);
223 n_z = ((normal_1[2] < zero) ? -normal_1[2] : normal_1[2]);
229 if (( n_x > n_z ) && ( n_x >= n_y )) {
231 P1[0] = q1[2]; P1[1] = q1[1];
232 Q1[0] = p1[2]; Q1[1] = p1[1];
233 R1[0] = r1[2]; R1[1] = r1[1];
235 P2[0] = q2[2]; P2[1] = q2[1];
236 Q2[0] = p2[2]; Q2[1] = p2[1];
237 R2[0] = r2[2]; R2[1] = r2[1];
240 }
else if (( n_y > n_z ) && ( n_y >= n_x )) {
242 P1[0] = q1[0]; P1[1] = q1[2];
243 Q1[0] = p1[0]; Q1[1] = p1[2];
244 R1[0] = r1[0]; R1[1] = r1[2];
246 P2[0] = q2[0]; P2[1] = q2[2];
247 Q2[0] = p2[0]; Q2[1] = p2[2];
248 R2[0] = r2[0]; R2[1] = r2[2];
253 P1[0] = p1[0]; P1[1] = p1[1];
254 Q1[0] = q1[0]; Q1[1] = q1[1];
255 R1[0] = r1[0]; R1[1] = r1[1];
257 P2[0] = p2[0]; P2[1] = p2[1];
258 Q2[0] = q2[0]; Q2[1] = q2[1];
259 R2[0] = r2[0]; R2[1] = r2[1];
263 return tri_tri_overlap_test_2d(P1,Q1,R1,P2,Q2,R2);
280 #define CONSTRUCT_INTERSECTION(p1,q1,r1,p2,q2,r2) \ 286 if (DOT(v,N) > zero) {\ 289 if (DOT(v,N) <= zero) { \ 292 if (DOT(v,N) > zero) { \ 295 alpha = DOT(v1,N2) / DOT(v2,N2); \ 296 SCALAR(v1,alpha,v2) \ 300 alpha = DOT(v1,N1) / DOT(v2,N1); \ 301 SCALAR(v1,alpha,v2) \ 307 alpha = DOT(v1,N1) / DOT(v2,N1); \ 308 SCALAR(v1,alpha,v2) \ 312 alpha = DOT(v1,N1) / DOT(v2,N1); \ 313 SCALAR(v1,alpha,v2) \ 323 if (DOT(v,N) < zero) { \ 328 if (DOT(v,N) >= zero) { \ 331 alpha = DOT(v1,N2) / DOT(v2,N2); \ 332 SCALAR(v1,alpha,v2) \ 336 alpha = DOT(v1,N2) / DOT(v2,N2); \ 337 SCALAR(v1,alpha,v2) \ 343 alpha = DOT(v1,N1) / DOT(v2,N1); \ 344 SCALAR(v1,alpha,v2) \ 348 alpha = DOT(v1,N2) / DOT(v2,N2); \ 349 SCALAR(v1,alpha,v2) \ 358 #define TRI_TRI_INTER_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2) \ 361 if (dq2 > zero) CONSTRUCT_INTERSECTION(p1,r1,q1,r2,p2,q2) \ 362 else if (dr2 > zero) CONSTRUCT_INTERSECTION(p1,r1,q1,q2,r2,p2) \ 363 else CONSTRUCT_INTERSECTION(p1,q1,r1,p2,q2,r2) \ 364 } else if (dp2 < zero) { \ 365 if (dq2 < zero) CONSTRUCT_INTERSECTION(p1,q1,r1,r2,p2,q2) \ 366 else if (dr2 < zero) CONSTRUCT_INTERSECTION(p1,q1,r1,q2,r2,p2) \ 367 else CONSTRUCT_INTERSECTION(p1,r1,q1,p2,q2,r2) \ 370 if (dr2 >= zero) CONSTRUCT_INTERSECTION(p1,r1,q1,q2,r2,p2) \ 371 else CONSTRUCT_INTERSECTION(p1,q1,r1,p2,q2,r2) \ 372 } else if (dq2 > zero) { \ 373 if (dr2 > zero) CONSTRUCT_INTERSECTION(p1,r1,q1,p2,q2,r2) \ 374 else CONSTRUCT_INTERSECTION(p1,q1,r1,q2,r2,p2) \ 376 if (dr2 > zero) CONSTRUCT_INTERSECTION(p1,q1,r1,r2,p2,q2) \ 377 else if (dr2 < zero) CONSTRUCT_INTERSECTION(p1,r1,q1,r2,p2,q2) \ 380 return coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1,N2);\ 394 int tri_tri_intersection_test_3d(real p1[3], real q1[3], real r1[3],
395 real p2[3], real q2[3], real r2[3],
397 real source[3], real target[3])
399 real dp1, dq1, dr1, dp2, dq2, dr2;
400 real v1[3], v2[3], v[3];
401 real N1[3], N2[3], N[3];
417 if (((dp1 * dq1) > zero) && ((dp1 * dr1) > zero)) return 0;
432 if (((dp2 * dq2) > zero) && ((dp2 * dr2) > zero)) return 0;
435 if (ZERO_TEST(dp1)) dp1 = zero;
436 if (ZERO_TEST(dq1)) dq1 = zero;
437 if (ZERO_TEST(dr1)) dr1 = zero;
439 if (ZERO_TEST(dp2)) dp2 = zero;
440 if (ZERO_TEST(dq2)) dq2 = zero;
441 if (ZERO_TEST(dr2)) dr2 = zero;
444 if (dq1 > zero) TRI_TRI_INTER_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2)
445 else if (dr1 > zero) TRI_TRI_INTER_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2)
446 else TRI_TRI_INTER_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2)
447 } else if (dp1 < zero) {
448 if (dq1 < zero) TRI_TRI_INTER_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2)
449 else if (dr1 < zero) TRI_TRI_INTER_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2)
450 else TRI_TRI_INTER_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2)
453 if (dr1 >= zero) TRI_TRI_INTER_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2)
454 else TRI_TRI_INTER_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2)
456 else if (dq1 > zero) {
457 if (dr1 > zero) TRI_TRI_INTER_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2)
458 else TRI_TRI_INTER_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2)
461 if (dr1 > zero) TRI_TRI_INTER_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2)
462 else if (dr1 < zero) TRI_TRI_INTER_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2)
465 return coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1,N2);
480 #define ORIENT_2D(a, b, c) ((a[0]-c[0])*(b[1]-c[1])-(a[1]-c[1])*(b[0]-c[0])) 483 #define INTERSECTION_TEST_VERTEX(P1, Q1, R1, P2, Q2, R2) \ 485 if (ORIENT_2D(R2,P2,Q1) >= zero) { \ 486 if (ORIENT_2D(R2,Q2,Q1) <= zero) { \ 487 if (ORIENT_2D(P1,P2,Q1) > zero) { \ 488 if (ORIENT_2D(P1,Q2,Q1) <= zero) return 1; \ 490 if (ORIENT_2D(P1,P2,R1) >= zero) { \ 491 if (ORIENT_2D(Q1,R1,P2) >= zero) return 1; \ 495 if (ORIENT_2D(P1,Q2,Q1) <= zero) { \ 496 if (ORIENT_2D(R2,Q2,R1) <= zero) { \ 497 if (ORIENT_2D(Q1,R1,Q2) >= zero) return 1; \ 502 if (ORIENT_2D(R2,P2,R1) >= zero) { \ 503 if (ORIENT_2D(Q1,R1,R2) >= zero) { \ 504 if (ORIENT_2D(P1,P2,R1) >= zero) return 1;\ 506 if (ORIENT_2D(Q1,R1,Q2) >= zero) { \ 507 if (ORIENT_2D(R2,R1,Q2) >= zero) return 1; \ 516 #define INTERSECTION_TEST_EDGE(P1, Q1, R1, P2, Q2, R2) \ 518 if (ORIENT_2D(R2,P2,Q1) >= zero) { \ 519 if (ORIENT_2D(P1,P2,Q1) >= zero) { \ 520 if (ORIENT_2D(P1,Q1,R2) >= zero) return 1; \ 522 if (ORIENT_2D(Q1,R1,P2) >= zero) { \ 523 if (ORIENT_2D(R1,P1,P2) >= zero) return 1; \ 527 if (ORIENT_2D(R2,P2,R1) >= zero) { \ 528 if (ORIENT_2D(P1,P2,R1) >= zero) { \ 529 if (ORIENT_2D(P1,R1,R2) >= zero) return 1; \ 530 if (ORIENT_2D(Q1,R1,R2) >= zero) return 1; \ 538 int ccw_tri_tri_intersection_2d(real p1[2], real q1[2], real r1[2],
539 real p2[2], real q2[2], real r2[2])
541 if (ORIENT_2D(p2,q2,p1) >= zero) {
542 if (ORIENT_2D(q2,r2,p1) >= zero) {
543 if (ORIENT_2D(r2,p2,p1) >= zero)
return 1;
544 INTERSECTION_TEST_EDGE(p1,q1,r1,p2,q2,r2)
546 if (ORIENT_2D(r2,p2,p1) >= zero) INTERSECTION_TEST_EDGE(p1,q1,r1,r2,p2,q2)
547 else INTERSECTION_TEST_VERTEX(p1,q1,r1,p2,q2,r2)
550 if (ORIENT_2D(q2,r2,p1) >= zero) {
551 if (ORIENT_2D(r2,p2,p1) >= zero) INTERSECTION_TEST_EDGE(p1,q1,r1,q2,r2,p2)
552 else INTERSECTION_TEST_VERTEX(p1,q1,r1,q2,r2,p2)
554 INTERSECTION_TEST_VERTEX(p1,q1,r1,r2,p2,q2)
560 int tri_tri_overlap_test_2d(real p1[2], real q1[2], real r1[2],
561 real p2[2], real q2[2], real r2[2])
563 if (ORIENT_2D(p1,q1,r1) < zero) {
564 if (ORIENT_2D(p2,q2,r2) < zero) {
565 return ccw_tri_tri_intersection_2d(p1,r1,q1,p2,r2,q2);
567 return ccw_tri_tri_intersection_2d(p1,r1,q1,p2,q2,r2);
570 if (ORIENT_2D(p2,q2,r2) < zero) {
571 return ccw_tri_tri_intersection_2d(p1,q1,r1,p2,r2,q2);
573 return ccw_tri_tri_intersection_2d(p1,q1,r1,p2,q2,r2);