// Compute intervals static int COMPUTE_INTERVALS( float VV0, float VV1, float VV2, float D0, float D1, float D2, float D0D1, float D0D2, float *isect0, float *isect1, vector3 *N1, vector3 *V0, vector3 *V1, vector3 *V2, vector3 *U0, vector3 *U1, vector3 *U2 ) { if ( D0D1 > 0.0f ) ISECT( VV2, VV0, VV1, D2, D0, D1, isect0, isect1 ); else if ( D0D2 > 0.0f ) ISECT( VV1, VV0, VV2, D1, D0, D2, isect0, isect1 ); else if ( D1*D2 > 0.0f || D0 != 0.0f ) ISECT( VV0, VV1, VV2, D0, D1, D2, isect0, isect1 ); else if ( D1 != 0.0f ) ISECT( VV1, VV0, VV2, D1, D0, D2, isect0, isect1 ); else if ( D2 != 0.0f ) ISECT( VV2, VV0, VV1, D2, D0, D1, isect0, isect1 ); else return coplanar_tri_tri( N1, V0, V1, V2, U0, U1, U2 ); return -1; }
int tri_tri_intersect(float V0[3],float V1[3],float V2[3], float U0[3],float U1[3],float U2[3]) { float E1[3],E2[3]; float N1[3],N2[3],d1,d2; float tmp[3]; float du0,du1,du2,dv0,dv1,dv2; float N[3]; float tdu0,tdu1,tdv0,tdv1; float du01,du02; /* flags of which vertex is single on one side of plane(U0,U1,U2), and plane(V0,V1,V2) */ /* VV0 is the pointer to the single vertex in (V0,V1,V2) of the plane(U0,U1,U2) */ /* UU0 is the pointer to the single vertex in (U0,U1,U2) of the plane(V0,V1,V2) */ float *UU0,*UU1,*UU2,*VV0,*VV1,*VV2; /* compute plane equation of triangle(U0,U1,U2) */ SUB(E1,U1,U0); SUB(E2,U2,U0); CROSS(N1,E1,E2); d1=-DOT(N1,U0); /* plane equation 1: N1.X+d1=0 */ /* put V0,V1,V2 into plane equation 1 to compute signed distances to the plane*/ dv0=DOT(N1,V0)+d1; dv1=DOT(N1,V1)+d1; dv2=DOT(N1,V2)+d1; /* coplanarity robustness check */ #if USE_EPSILON_TEST==TRUE if(FABS(dv0)<EPSILON) dv0=0.0; if(FABS(dv1)<EPSILON) dv1=0.0; if(FABS(dv2)<EPSILON) dv2=0.0; #endif if(SAMESIGN012(dv0,dv1,dv2)) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute plane equation of triangle(V0,V1,V2) */ SUB(E1,V1,V0); SUB(E2,V2,V0); CROSS(N2,E1,E2); d2=-DOT(N2,V0); /* plane equation 2: N2.X+d2=0 */ /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/ du0=DOT(N2,U0)+d2; du1=DOT(N2,U1)+d2; du2=DOT(N2,U2)+d2; /* coplanarity robustness check */ #if USE_EPSILON_TEST==TRUE if(FABS(du0)<EPSILON) du0=0.0; if(FABS(du1)<EPSILON) du1=0.0; if(FABS(du2)<EPSILON) du2=0.0; #endif if(SAMESIGN012(du0,du1,du2)) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* V0,V1,V2,U0,U1,U2 are all in the same plane */ if ((dv0==0)&&(dv1==0)&&(dv2==0)) return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); /* replace V0,V1,V2 with VV0,VV1,VV2 */ if (SIGN01_DIF_SIGN2(dv1,dv2,dv0)) { VV0=V0;VV1=V1;VV2=V2;tdv0=dv0;tdv1=dv1; /* V0 is single vertex of the plane of triangle (U0,U1,U2) */ } else if (SIGN01_DIF_SIGN2(dv2,dv0,dv1)) { VV0=V1;VV1=V2;VV2=V0;tdv0=dv1;tdv1=dv2; /* V1 is single vertex of the plane of triangle (U0,U1,U2) */ } else if (SIGN01_DIF_SIGN2(dv0,dv1,dv2)) { VV0=V2;VV1=V0;VV2=V1;tdv0=dv2;tdv1=dv0; /* V2 is single vertex of the plane of triangle (U0,U1,U2) */ } /* replace U0,U1,U2 with UU0,UU1,UU2 */ if (SIGN01_DIF_SIGN2(du1,du2,du0)) { UU0=U0;UU1=U1;UU2=U2;tdu0=du0;tdu1=du1; /* U0 is single vertex of the plane of triangle (V0,V1,V2) */ } else if (SIGN01_DIF_SIGN2(du2,du0,du1)) { UU0=U1;UU1=U2;UU2=U0;tdu0=du1;tdu1=du2; /* U1 is single vertex of the plane of triangle (V0,V1,V2) */ } else if (SIGN01_DIF_SIGN2(du0,du1,du2)) { UU0=U2;UU1=U0;UU2=U1;tdu0=du2;tdu1=du0; /* U2 is single vertex of the plane of triangle (V0,V1,V2) */ } /* compute distance between lines of triangle (V0,V1,V2) and triangle (U0,U1,U2) */ if ((tdu0>=0) && (tdu1<=0)) { if ((tdv0>=0) && (tdv1<=0)) { SUB(E1,VV0,VV2); SUB(E2,UU0,UU2); CROSS(N,E1,E2); SUB(tmp,UU0,VV0); du02=DOT(N,tmp); #if USE_EPSILON_TEST==TRUE if (du02>EPSILON) #else if (du02>0) #endif return 0; SUB(E1,VV1,VV0); SUB(E2,UU1,UU0); CROSS(N,E1,E2); SUB(tmp,UU0,VV0); du01=DOT(N,tmp); #if USE_EPSILON_TEST==TRUE if (du01<-EPSILON) #else if (du01<0) #endif return 0; } else { SUB(E1,VV1,VV0); SUB(E2,UU0,UU2); CROSS(N,E1,E2); SUB(tmp,UU0,VV0); du02=DOT(N,tmp); #if USE_EPSILON_TEST==TRUE if (du02>EPSILON) #else if (du02>0) #endif return 0; SUB(E1,VV0,VV2); SUB(E2,UU1,UU0); CROSS(N,E1,E2); SUB(tmp,UU0,VV0); du01=DOT(N,tmp); #if USE_EPSILON_TEST==TRUE if (du01<-EPSILON) #else if (du01<0) #endif return 0; } } else { if ((tdv0>=0) && (tdv1<=0)) { SUB(E1,VV0,VV2); SUB(E2,UU1,UU0); CROSS(N,E1,E2); SUB(tmp,UU0,VV0); du01=DOT(N,tmp); #if USE_EPSILON_TEST==TRUE if (du01>EPSILON) #else if (du01>0) #endif return 0; SUB(E1,VV1,VV0); SUB(E2,UU0,UU2); CROSS(N,E1,E2); SUB(tmp,UU0,VV0); du02=DOT(N,tmp); #if USE_EPSILON_TEST==TRUE if (du02<-EPSILON) #else if (du02<0) #endif return 0; } else { SUB(E1,VV1,VV0); SUB(E2,UU1,UU0); CROSS(N,E1,E2); SUB(tmp,UU0,VV0); du01=DOT(N,tmp); #if USE_EPSILON_TEST==TRUE if (du01>EPSILON) #else if (du01>0) #endif return 0; SUB(E1,VV0,VV2); SUB(E2,UU0,UU2); CROSS(N,E1,E2); SUB(tmp,UU0,VV0); du02=DOT(N,tmp); #if USE_EPSILON_TEST==TRUE if (du02<-EPSILON) #else if (du02<0) #endif return 0; } } return 1; }
qboolean tri_tri_intersect( vector3 *V0, vector3 *V1, vector3 *V2, vector3 *U0, vector3 *U1, vector3 *U2 ) { vector3 E1, E2, N1, N2, D; float d1, d2; float du0, du1, du2, dv0, dv1, dv2; float isect1[2], isect2[2]; float du0du1, du0du2, dv0dv1, dv0dv2; short index; float vp0, vp1, vp2, up0, up1, up2; float bb, cc, max; float a, b, c, d, e, f, x0, x1, y0, y1; float xx, yy, xxyy, tmp; // compute plane of tri(V0, V1, V2) VectorSubtract( V1, V0, &E1 ); VectorSubtract( V2, V0, &E2 ); CrossProduct( &E1, &E2, &N1 ); d1 = -DotProduct( &N1, V0 ); // put U0,U1,U2 into plane equation 1 to compute signed distances to the plane du0 = DotProduct( &N1, U0 ) + d1; du1 = DotProduct( &N1, U1 ) + d1; du2 = DotProduct( &N1, U2 ) + d1; // coplanarity robustness check if ( Q_fabs( du0 ) < epsilon ) { du0 = 0.0f; } if ( Q_fabs( du1 ) < epsilon ) { du1 = 0.0f; } if ( Q_fabs( du2 ) < epsilon ) { du2 = 0.0f; } du0du1 = du0 * du1; du0du2 = du0 * du2; // same sign on all of them + not equal 0, no intersection occurs if ( du0du1 > 0.0f && du0du2 > 0.0f ) { return qfalse; } // compute plane of tri(U0, U1, U2) VectorSubtract( U1, U0, &E1 ); VectorSubtract( U2, U0, &E2 ); CrossProduct( &E1, &E2, &N2 ); d2 = -DotProduct( &N2, U0 ); // put V0,V1,V2 into plane equation 1 to compute signed distances to the plane dv0 = DotProduct( &N2, V0 ) + d2; dv1 = DotProduct( &N2, V1 ) + d2; dv2 = DotProduct( &N2, V2 ) + d2; // coplanarity robustness check if ( Q_fabs( dv0 ) < epsilon ) { dv0 = 0.0f; } if ( Q_fabs( dv1 ) < epsilon ) { dv1 = 0.0f; } if ( Q_fabs( dv2 ) < epsilon ) { dv2 = 0.0f; } dv0dv1 = dv0 * dv1; dv0dv2 = dv0 * dv2; // same sign on all of them + not equal 0, no intersection occurs if ( dv0dv1 > 0.0f && dv0dv2 > 0.0f ) { return qfalse; } // compute direction of intersection line CrossProduct( &D, &N1, &N2 ); // compute and index to the largest component of D max = Q_fabs( D.x ); index = 0; bb = Q_fabs( D.y ); cc = Q_fabs( D.z ); if ( bb > max ) { max = bb; index = 1; } if ( cc > max ) { max = cc; index = 2; } // this is the simplified projection onto L vp0 = V0->raw[index]; vp1 = V1->raw[index]; vp2 = V2->raw[index]; up0 = U0->raw[index]; up1 = U1->raw[index]; up2 = U2->raw[index]; // compute_intervals if ( dv0dv1 > 0.0f ) { a = vp2; b = (vp0 - vp2) * dv2; c = (vp1 - vp2) * dv2; x0 = dv2 - dv0; x1 = dv2 - dv1; } else if ( dv0dv2 > 0.0f ) { a = vp1; b = (vp0 - vp1) * dv1; c = (vp2 - vp1) * dv1; x0 = dv1 - dv0; x1 = dv1 - dv2; } else if ( dv1 * dv2 > 0.0f || dv0 != 0.0f ) { a = vp0; b = (vp1 - vp0) * dv0; c = (vp2 - vp0) * dv0; x0 = dv0 - dv1; x1 = dv0 - dv2; } else if ( dv1 != 0.0f ) { a = vp1; b = (vp0 - vp1) * dv1; c = (vp2 - vp1) * dv1; x0 = dv1 - dv0; x1 = dv1 - dv2; } else if ( dv2 != 0.0f ) { a = vp2; b = (vp0 - vp2) * dv2; c = (vp1 - vp2) * dv2; x0 = dv2 - dv0; x1 = dv2 - dv1; } else { return coplanar_tri_tri( &N1, V0, V1, V2, U0, U1, U2 ); } // compute_intervals if ( du0du1 > 0.0f ) { d = up2; e = (up0 - up2) * du2; f = (up1 - up2) * du2; y0 = du2 - du0; y1 = du2 - du1; } else if ( du0du2 > 0.0f ) { d = up1; e = (up0 - up1) * du1; f = (up2 - up1) * du1; y0 = du1 - du0; y1 = du1 - du2; } else if ( du1 * du2 > 0.0f || du0 != 0.0f ) { d = up0; e = (up1 - up0) * du0; f = (up2 - up0) * du0; y0 = du0 - du1; y1 = du0 - du2; } else if ( du1 != 0.0f ) { d = up1; e = (up0 - up1) * du1; f = (up2 - up1) * du1; y0 = du1 - du0; y1 = du1 - du2; } else if ( du2 != 0.0f ) { d = up2; e = (up0 - up2) * du2; f = (up1 - up2) * du2; y0 = du2 - du0; y1 = du2 - du1; } else { return coplanar_tri_tri( &N1, V0, V1, V2, U0, U1, U2 ); } xx = x0 * x1; yy = y0 * y1; xxyy = xx * yy; tmp = a * xxyy; isect1[0] = tmp + b * x1 * yy; isect1[1] = tmp + c * x0 * yy; tmp = d * xxyy; isect2[0] = tmp + e * xx * y1; isect2[1] = tmp + f * xx * y0; // sort so that a <= b sort( &isect1[0], &isect1[1] ); sort( &isect2[0], &isect2[1] ); if ( isect1[1] < isect2[0] || isect2[1] < isect1[0] ) { return qfalse; } return qtrue; }
int bn_tri_tri_isect_with_line(point_t V0, point_t V1, point_t V2, point_t U0, point_t U1, point_t U2, int *coplanar, point_t *isectpt1, point_t *isectpt2) { point_t E1, E2; point_t N1, N2; fastf_t d1, d2; fastf_t du0, du1, du2, dv0, dv1, dv2; fastf_t D[3]; fastf_t isect1[2] = {0, 0}; fastf_t isect2[2] = {0, 0}; point_t isectpointA1 = VINIT_ZERO; point_t isectpointA2 = VINIT_ZERO; point_t isectpointB1 = VINIT_ZERO; point_t isectpointB2 = VINIT_ZERO; fastf_t du0du1, du0du2, dv0dv1, dv0dv2; short index; fastf_t vp0, vp1, vp2; fastf_t up0, up1, up2; fastf_t b, c, max; int smallest1, smallest2; /* compute plane equation of triangle(V0, V1, V2) */ VSUB2(E1, V1, V0); VSUB2(E2, V2, V0); VCROSS(N1, E1, E2); d1=-VDOT(N1, V0); /* plane equation 1: N1.X+d1=0 */ /* put U0, U1, U2 into plane equation 1 to compute signed distances to the plane*/ du0=VDOT(N1, U0)+d1; du1=VDOT(N1, U1)+d1; du2=VDOT(N1, U2)+d1; /* coplanarity robustness check */ #if USE_EPSILON_TEST if (fabs(du0)<EPSILON) du0=0.0; if (fabs(du1)<EPSILON) du1=0.0; if (fabs(du2)<EPSILON) du2=0.0; #endif du0du1=du0*du1; du0du2=du0*du2; if (du0du1>0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute plane of triangle (U0, U1, U2) */ VSUB2(E1, U1, U0); VSUB2(E2, U2, U0); VCROSS(N2, E1, E2); d2=-VDOT(N2, U0); /* plane equation 2: N2.X+d2=0 */ /* put V0, V1, V2 into plane equation 2 */ dv0=VDOT(N2, V0)+d2; dv1=VDOT(N2, V1)+d2; dv2=VDOT(N2, V2)+d2; #if USE_EPSILON_TEST if (fabs(dv0)<EPSILON) dv0=0.0; if (fabs(dv1)<EPSILON) dv1=0.0; if (fabs(dv2)<EPSILON) dv2=0.0; #endif dv0dv1=dv0*dv1; dv0dv2=dv0*dv2; if (dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */ return 0; /* no intersection occurs */ /* compute direction of intersection line */ VCROSS(D, N1, N2); /* compute and index to the largest component of D */ max=fabs(D[0]); index=0; b=fabs(D[1]); c=fabs(D[2]); if (b>max) max=b, index=1; if (c>max) index=2; /* this is the simplified projection onto L*/ vp0=V0[index]; vp1=V1[index]; vp2=V2[index]; up0=U0[index]; up1=U1[index]; up2=U2[index]; /* compute interval for triangle 1 */ *coplanar=compute_intervals_isectline(V0, V1, V2, vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2, &isect1[0], &isect1[1], isectpointA1, isectpointA2); if (*coplanar) return coplanar_tri_tri(N1, V0, V1, V2, U0, U1, U2); /* compute interval for triangle 2 */ compute_intervals_isectline(U0, U1, U2, up0, up1, up2, du0, du1, du2, du0du1, du0du2, &isect2[0], &isect2[1], isectpointB1, isectpointB2); SORT2(isect1[0], isect1[1], smallest1); SORT2(isect2[0], isect2[1], smallest2); if (isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0; /* at this point, we know that the triangles intersect */ if (isect2[0]<isect1[0]) { if (smallest1==0) { VMOVE(*isectpt1, isectpointA1); } else { VMOVE(*isectpt1, isectpointA2); } if (isect2[1]<isect1[1]) { if (smallest2==0) { VMOVE(*isectpt2, isectpointB2); } else { VMOVE(*isectpt2, isectpointB1); } } else { if (smallest1==0) { VMOVE(*isectpt2, isectpointA2); } else { VMOVE(*isectpt2, isectpointA1); } } } else { if (smallest2==0) { VMOVE(*isectpt1, isectpointB1); } else { VMOVE(*isectpt1, isectpointB2); } if (isect2[1]>isect1[1]) { if (smallest1==0) { VMOVE(*isectpt2, isectpointA2); } else { VMOVE(*isectpt2, isectpointA1); } } else { if (smallest2==0) { VMOVE(*isectpt2, isectpointB2); } else { VMOVE(*isectpt2, isectpointB1); } } } return 1; }