常用图形学求交函数汇总(三角形与轴对齐盒体相交,射线与三角形相交,两个三角形相交)...

计算机图形学里最重要的是检测基本几何体之间的相交测试(检测两个基本几何体是否相交),以及求出交点在空间中的具体位置。一旦解决了基本的求交问题,那么对于复杂的几何体,如果视其为许多基本几何体的组合,问题也就迎刃而解了。

上国外网站淘了一些源码,自己把它整理了一下,变成了直接就能用的独立函数,贴在这里。原作者网址已经有一定年头了,貌似是Sun公司做CPU那会的年代......所以并不知道里面所做的一些优化对于现代的CPU有没有什么帮助,没准会有副作用。

但至少是一个robust的实现。

一、射线——三角形相交:

  1 #pragma once
  2 /* Ray-Triangle Intersection Test Routines          */
  3 /* Different optimizations of my and Ben Trumbore's */
  4 /* code from journals of graphics tools (JGT)       */
  5 /* http://www.acm.org/jgt/                          */
  6 /* by Tomas Moller, May 2000                        */
  7 
  8 #include <math.h>
  9 
 10 #define EPSILON 0.000001
 11 #define CROSS(dest,v1,v2) \
 12           dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
 13           dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
 14           dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
 15 #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
 16 #define SUB(dest,v1,v2) \
 17           dest[0]=v1[0]-v2[0]; \
 18           dest[1]=v1[1]-v2[1]; \
 19           dest[2]=v1[2]-v2[2]; 
 20 
 21 /* the original jgt code */
 22 int intersect_triangle(double orig[3], double dir[3],
 23     double vert0[3], double vert1[3], double vert2[3],
 24     double *t, double *u, double *v)
 25 {
 26     double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
 27     double det, inv_det;
 28 
 29     /* find vectors for two edges sharing vert0 */
 30     SUB(edge1, vert1, vert0);
 31     SUB(edge2, vert2, vert0);
 32 
 33     /* begin calculating determinant - also used to calculate U parameter */
 34     CROSS(pvec, dir, edge2);
 35 
 36     /* if determinant is near zero, ray lies in plane of triangle */
 37     det = DOT(edge1, pvec);
 38 
 39     if (det > -EPSILON && det < EPSILON)
 40         return 0;
 41     inv_det = 1.0 / det;
 42 
 43     /* calculate distance from vert0 to ray origin */
 44     SUB(tvec, orig, vert0);
 45 
 46     /* calculate U parameter and test bounds */
 47     *u = DOT(tvec, pvec) * inv_det;
 48     if (*u < 0.0 || *u > 1.0)
 49         return 0;
 50 
 51     /* prepare to test V parameter */
 52     CROSS(qvec, tvec, edge1);
 53 
 54     /* calculate V parameter and test bounds */
 55     *v = DOT(dir, qvec) * inv_det;
 56     if (*v < 0.0 || *u + *v > 1.0)
 57         return 0;
 58 
 59     /* calculate t, ray intersects triangle */
 60     *t = DOT(edge2, qvec) * inv_det;
 61 
 62     return 1;
 63 }
 64 
 65 
 66 /* code rewritten to do tests on the sign of the determinant */
 67 /* the division is at the end in the code                    */
 68 int intersect_triangle1(double orig[3], double dir[3],
 69     double vert0[3], double vert1[3], double vert2[3],
 70     double *t, double *u, double *v)
 71 {
 72     double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
 73     double det, inv_det;
 74 
 75     /* find vectors for two edges sharing vert0 */
 76     SUB(edge1, vert1, vert0);
 77     SUB(edge2, vert2, vert0);
 78 
 79     /* begin calculating determinant - also used to calculate U parameter */
 80     CROSS(pvec, dir, edge2);
 81 
 82     /* if determinant is near zero, ray lies in plane of triangle */
 83     det = DOT(edge1, pvec);
 84 
 85     if (det > EPSILON)
 86     {
 87         /* calculate distance from vert0 to ray origin */
 88         SUB(tvec, orig, vert0);
 89 
 90         /* calculate U parameter and test bounds */
 91         *u = DOT(tvec, pvec);
 92         if (*u < 0.0 || *u > det)
 93             return 0;
 94 
 95         /* prepare to test V parameter */
 96         CROSS(qvec, tvec, edge1);
 97 
 98         /* calculate V parameter and test bounds */
 99         *v = DOT(dir, qvec);
100         if (*v < 0.0 || *u + *v > det)
101             return 0;
102 
103     }
104     else if (det < -EPSILON)
105     {
106         /* calculate distance from vert0 to ray origin */
107         SUB(tvec, orig, vert0);
108 
109         /* calculate U parameter and test bounds */
110         *u = DOT(tvec, pvec);
111         /*      printf("*u=%f\n",(float)*u); */
112         /*      printf("det=%f\n",det); */
113         if (*u > 0.0 || *u < det)
114             return 0;
115 
116         /* prepare to test V parameter */
117         CROSS(qvec, tvec, edge1);
118 
119         /* calculate V parameter and test bounds */
120         *v = DOT(dir, qvec);
121         if (*v > 0.0 || *u + *v < det)
122             return 0;
123     }
124     else return 0;  /* ray is parallell to the plane of the triangle */
125 
126 
127     inv_det = 1.0 / det;
128 
129     /* calculate t, ray intersects triangle */
130     *t = DOT(edge2, qvec) * inv_det;
131     (*u) *= inv_det;
132     (*v) *= inv_det;
133 
134     return 1;
135 }
136 
137 /* code rewritten to do tests on the sign of the determinant */
138 /* the division is before the test of the sign of the det    */
139 int intersect_triangle2(double orig[3], double dir[3],
140     double vert0[3], double vert1[3], double vert2[3],
141     double *t, double *u, double *v)
142 {
143     double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
144     double det, inv_det;
145 
146     /* find vectors for two edges sharing vert0 */
147     SUB(edge1, vert1, vert0);
148     SUB(edge2, vert2, vert0);
149 
150     /* begin calculating determinant - also used to calculate U parameter */
151     CROSS(pvec, dir, edge2);
152 
153     /* if determinant is near zero, ray lies in plane of triangle */
154     det = DOT(edge1, pvec);
155 
156     /* calculate distance from vert0 to ray origin */
157     SUB(tvec, orig, vert0);
158     inv_det = 1.0 / det;
159 
160     if (det > EPSILON)
161     {
162         /* calculate U parameter and test bounds */
163         *u = DOT(tvec, pvec);
164         if (*u < 0.0 || *u > det)
165             return 0;
166 
167         /* prepare to test V parameter */
168         CROSS(qvec, tvec, edge1);
169 
170         /* calculate V parameter and test bounds */
171         *v = DOT(dir, qvec);
172         if (*v < 0.0 || *u + *v > det)
173             return 0;
174 
175     }
176     else if (det < -EPSILON)
177     {
178         /* calculate U parameter and test bounds */
179         *u = DOT(tvec, pvec);
180         if (*u > 0.0 || *u < det)
181             return 0;
182 
183         /* prepare to test V parameter */
184         CROSS(qvec, tvec, edge1);
185 
186         /* calculate V parameter and test bounds */
187         *v = DOT(dir, qvec);
188         if (*v > 0.0 || *u + *v < det)
189             return 0;
190     }
191     else return 0;  /* ray is parallell to the plane of the triangle */
192 
193                     /* calculate t, ray intersects triangle */
194     *t = DOT(edge2, qvec) * inv_det;
195     (*u) *= inv_det;
196     (*v) *= inv_det;
197 
198     return 1;
199 }
200 
201 /* code rewritten to do tests on the sign of the determinant */
202 /* the division is before the test of the sign of the det    */
203 /* and one CROSS has been moved out from the if-else if-else */
204 int intersect_triangle3(double orig[3], double dir[3],
205     double vert0[3], double vert1[3], double vert2[3],
206     double *t, double *u, double *v)
207 {
208     double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
209     double det, inv_det;
210 
211     /* find vectors for two edges sharing vert0 */
212     SUB(edge1, vert1, vert0);
213     SUB(edge2, vert2, vert0);
214 
215     /* begin calculating determinant - also used to calculate U parameter */
216     CROSS(pvec, dir, edge2);
217 
218     /* if determinant is near zero, ray lies in plane of triangle */
219     det = DOT(edge1, pvec);
220 
221     /* calculate distance from vert0 to ray origin */
222     SUB(tvec, orig, vert0);
223     inv_det = 1.0 / det;
224 
225     CROSS(qvec, tvec, edge1);
226 
227     if (det > EPSILON)
228     {
229         *u = DOT(tvec, pvec);
230         if (*u < 0.0 || *u > det)
231             return 0;
232 
233         /* calculate V parameter and test bounds */
234         *v = DOT(dir, qvec);
235         if (*v < 0.0 || *u + *v > det)
236             return 0;
237 
238     }
239     else if (det < -EPSILON)
240     {
241         /* calculate U parameter and test bounds */
242         *u = DOT(tvec, pvec);
243         if (*u > 0.0 || *u < det)
244             return 0;
245 
246         /* calculate V parameter and test bounds */
247         *v = DOT(dir, qvec);
248         if (*v > 0.0 || *u + *v < det)
249             return 0;
250     }
251     else return 0;  /* ray is parallell to the plane of the triangle */
252 
253     *t = DOT(edge2, qvec) * inv_det;
254     (*u) *= inv_det;
255     (*v) *= inv_det;
256 
257     return 1;
258 }

 二、两个三角形相交:

  1 #pragma once
  2 /* Triangle/triangle intersection test routine,
  3 * by Tomas Moller, 1997.
  4 * See article "A Fast Triangle-Triangle Intersection Test",
  5 * Journal of Graphics Tools, 2(2), 1997
  6 *
  7 * Updated June 1999: removed the divisions -- a little faster now!
  8 * Updated October 1999: added {} to CROSS and SUB macros
  9 *
 10 * int NoDivTriTriIsect(float V0[3],float V1[3],float V2[3],
 11 *                      float U0[3],float U1[3],float U2[3])
 12 *
 13 * parameters: vertices of triangle 1: V0,V1,V2
 14 *             vertices of triangle 2: U0,U1,U2
 15 * result    : returns 1 if the triangles intersect, otherwise 0
 16 *
 17 */
 18 
 19 #include <math.h>
 20 #define FABS(x) (float(fabs(x)))        /* implement as is fastest on your machine */
 21 
 22 /* if USE_EPSILON_TEST is true then we do a check:
 23 if |dv|<EPSILON then dv=0.0;
 24 else no check is done (which is less robust)
 25 */
 26 #define USE_EPSILON_TEST TRUE
 27 #define EPSILON 0.000001
 28 
 29 
 30 /* some macros */
 31 #define CROSS(dest,v1,v2){                     \
 32               dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
 33               dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
 34               dest[2]=v1[0]*v2[1]-v1[1]*v2[0];}
 35 
 36 #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
 37 
 38 #define SUB(dest,v1,v2){         \
 39             dest[0]=v1[0]-v2[0]; \
 40             dest[1]=v1[1]-v2[1]; \
 41             dest[2]=v1[2]-v2[2];}
 42 
 43 /* sort so that a<=b */
 44 #define SORT(a,b)       \
 45              if(a>b)    \
 46              {          \
 47                float c; \
 48                c=a;     \
 49                a=b;     \
 50                b=c;     \
 51              }
 52 
 53 
 54 /* this edge to edge test is based on Franlin Antonio's gem:
 55 "Faster Line Segment Intersection", in Graphics Gems III,
 56 pp. 199-202 */
 57 #define EDGE_EDGE_TEST(V0,U0,U1)                      \
 58   Bx=U0[i0]-U1[i0];                                   \
 59   By=U0[i1]-U1[i1];                                   \
 60   Cx=V0[i0]-U0[i0];                                   \
 61   Cy=V0[i1]-U0[i1];                                   \
 62   f=Ay*Bx-Ax*By;                                      \
 63   d=By*Cx-Bx*Cy;                                      \
 64   if((f>0 && d>=0 && d<=f) || (f<0 && d<=0 && d>=f))  \
 65   {                                                   \
 66     e=Ax*Cy-Ay*Cx;                                    \
 67     if(f>0)                                           \
 68     {                                                 \
 69       if(e>=0 && e<=f) return 1;                      \
 70     }                                                 \
 71     else                                              \
 72     {                                                 \
 73       if(e<=0 && e>=f) return 1;                      \
 74     }                                                 \
 75   }
 76 
 77 #define EDGE_AGAINST_TRI_EDGES(V0,V1,U0,U1,U2) \
 78 {                                              \
 79   float Ax,Ay,Bx,By,Cx,Cy,e,d,f;               \
 80   Ax=V1[i0]-V0[i0];                            \
 81   Ay=V1[i1]-V0[i1];                            \
 82   /* test edge U0,U1 against V0,V1 */          \
 83   EDGE_EDGE_TEST(V0,U0,U1);                    \
 84   /* test edge U1,U2 against V0,V1 */          \
 85   EDGE_EDGE_TEST(V0,U1,U2);                    \
 86   /* test edge U2,U1 against V0,V1 */          \
 87   EDGE_EDGE_TEST(V0,U2,U0);                    \
 88 }
 89 
 90 #define POINT_IN_TRI(V0,U0,U1,U2)           \
 91 {                                           \
 92   float a,b,c,d0,d1,d2;                     \
 93   /* is T1 completly inside T2? */          \
 94   /* check if V0 is inside tri(U0,U1,U2) */ \
 95   a=U1[i1]-U0[i1];                          \
 96   b=-(U1[i0]-U0[i0]);                       \
 97   c=-a*U0[i0]-b*U0[i1];                     \
 98   d0=a*V0[i0]+b*V0[i1]+c;                   \
 99                                             \
100   a=U2[i1]-U1[i1];                          \
101   b=-(U2[i0]-U1[i0]);                       \
102   c=-a*U1[i0]-b*U1[i1];                     \
103   d1=a*V0[i0]+b*V0[i1]+c;                   \
104                                             \
105   a=U0[i1]-U2[i1];                          \
106   b=-(U0[i0]-U2[i0]);                       \
107   c=-a*U2[i0]-b*U2[i1];                     \
108   d2=a*V0[i0]+b*V0[i1]+c;                   \
109   if(d0*d1>0.0)                             \
110   {                                         \
111     if(d0*d2>0.0) return 1;                 \
112   }                                         \
113 }
114 
115 int coplanar_tri_tri(float N[3], float V0[3], float V1[3], float V2[3],
116     float U0[3], float U1[3], float U2[3])
117 {
118     float A[3];
119     short i0, i1;
120     /* first project onto an axis-aligned plane, that maximizes the area */
121     /* of the triangles, compute indices: i0,i1. */
122     A[0] = FABS(N[0]);
123     A[1] = FABS(N[1]);
124     A[2] = FABS(N[2]);
125     if (A[0]>A[1])
126     {
127         if (A[0]>A[2])
128         {
129             i0 = 1;      /* A[0] is greatest */
130             i1 = 2;
131         }
132         else
133         {
134             i0 = 0;      /* A[2] is greatest */
135             i1 = 1;
136         }
137     }
138     else   /* A[0]<=A[1] */
139     {
140         if (A[2]>A[1])
141         {
142             i0 = 0;      /* A[2] is greatest */
143             i1 = 1;
144         }
145         else
146         {
147             i0 = 0;      /* A[1] is greatest */
148             i1 = 2;
149         }
150     }
151 
152     /* test all edges of triangle 1 against the edges of triangle 2 */
153     EDGE_AGAINST_TRI_EDGES(V0, V1, U0, U1, U2);
154     EDGE_AGAINST_TRI_EDGES(V1, V2, U0, U1, U2);
155     EDGE_AGAINST_TRI_EDGES(V2, V0, U0, U1, U2);
156 
157     /* finally, test if tri1 is totally contained in tri2 or vice versa */
158     POINT_IN_TRI(V0, U0, U1, U2);
159     POINT_IN_TRI(U0, V0, V1, V2);
160 
161     return 0;
162 }
163 
164 
165 
166 #define NEWCOMPUTE_INTERVALS(VV0,VV1,VV2,D0,D1,D2,D0D1,D0D2,A,B,C,X0,X1) \
167 { \
168         if(D0D1>0.0f) \
169         { \
170                 /* here we know that D0D2<=0.0 */ \
171             /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
172                 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
173         } \
174         else if(D0D2>0.0f)\
175         { \
176                 /* here we know that d0d1<=0.0 */ \
177             A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
178         } \
179         else if(D1*D2>0.0f || D0!=0.0f) \
180         { \
181                 /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
182                 A=VV0; B=(VV1-VV0)*D0; C=(VV2-VV0)*D0; X0=D0-D1; X1=D0-D2; \
183         } \
184         else if(D1!=0.0f) \
185         { \
186                 A=VV1; B=(VV0-VV1)*D1; C=(VV2-VV1)*D1; X0=D1-D0; X1=D1-D2; \
187         } \
188         else if(D2!=0.0f) \
189         { \
190                 A=VV2; B=(VV0-VV2)*D2; C=(VV1-VV2)*D2; X0=D2-D0; X1=D2-D1; \
191         } \
192         else \
193         { \
194                 /* triangles are coplanar */ \
195                 return coplanar_tri_tri(N1,V0,V1,V2,U0,U1,U2); \
196         } \
197 }
198 
199 
200 
201 int NoDivTriTriIsect(float V0[3], float V1[3], float V2[3],
202     float U0[3], float U1[3], float U2[3])
203 {
204     float E1[3], E2[3];
205     float N1[3], N2[3], d1, d2;
206     float du0, du1, du2, dv0, dv1, dv2;
207     float D[3];
208     float isect1[2], isect2[2];
209     float du0du1, du0du2, dv0dv1, dv0dv2;
210     short index;
211     float vp0, vp1, vp2;
212     float up0, up1, up2;
213     float bb, cc, max;
214 
215     /* compute plane equation of triangle(V0,V1,V2) */
216     SUB(E1, V1, V0);
217     SUB(E2, V2, V0);
218     CROSS(N1, E1, E2);
219     d1 = -DOT(N1, V0);
220     /* plane equation 1: N1.X+d1=0 */
221 
222     /* put U0,U1,U2 into plane equation 1 to compute signed distances to the plane*/
223     du0 = DOT(N1, U0) + d1;
224     du1 = DOT(N1, U1) + d1;
225     du2 = DOT(N1, U2) + d1;
226 
227     /* coplanarity robustness check */
228 #if USE_EPSILON_TEST==TRUE
229     if (FABS(du0)<EPSILON) du0 = 0.0;
230     if (FABS(du1)<EPSILON) du1 = 0.0;
231     if (FABS(du2)<EPSILON) du2 = 0.0;
232 #endif
233     du0du1 = du0*du1;
234     du0du2 = du0*du2;
235 
236     if (du0du1>0.0f && du0du2>0.0f) /* same sign on all of them + not equal 0 ? */
237         return 0;                    /* no intersection occurs */
238 
239                                      /* compute plane of triangle (U0,U1,U2) */
240     SUB(E1, U1, U0);
241     SUB(E2, U2, U0);
242     CROSS(N2, E1, E2);
243     d2 = -DOT(N2, U0);
244     /* plane equation 2: N2.X+d2=0 */
245 
246     /* put V0,V1,V2 into plane equation 2 */
247     dv0 = DOT(N2, V0) + d2;
248     dv1 = DOT(N2, V1) + d2;
249     dv2 = DOT(N2, V2) + d2;
250 
251 #if USE_EPSILON_TEST==TRUE
252     if (FABS(dv0)<EPSILON) dv0 = 0.0;
253     if (FABS(dv1)<EPSILON) dv1 = 0.0;
254     if (FABS(dv2)<EPSILON) dv2 = 0.0;
255 #endif
256 
257     dv0dv1 = dv0*dv1;
258     dv0dv2 = dv0*dv2;
259 
260     if (dv0dv1>0.0f && dv0dv2>0.0f) /* same sign on all of them + not equal 0 ? */
261         return 0;                    /* no intersection occurs */
262 
263                                      /* compute direction of intersection line */
264     CROSS(D, N1, N2);
265 
266     /* compute and index to the largest component of D */
267     max = (float)FABS(D[0]);
268     index = 0;
269     bb = (float)FABS(D[1]);
270     cc = (float)FABS(D[2]);
271     if (bb>max) max = bb, index = 1;
272     if (cc>max) max = cc, index = 2;
273 
274     /* this is the simplified projection onto L*/
275     vp0 = V0[index];
276     vp1 = V1[index];
277     vp2 = V2[index];
278 
279     up0 = U0[index];
280     up1 = U1[index];
281     up2 = U2[index];
282 
283     /* compute interval for triangle 1 */
284     float a, b, c, x0, x1;
285     NEWCOMPUTE_INTERVALS(vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2, a, b, c, x0, x1);
286 
287     /* compute interval for triangle 2 */
288     float d, e, f, y0, y1;
289     NEWCOMPUTE_INTERVALS(up0, up1, up2, du0, du1, du2, du0du1, du0du2, d, e, f, y0, y1);
290 
291     float xx, yy, xxyy, tmp;
292     xx = x0*x1;
293     yy = y0*y1;
294     xxyy = xx*yy;
295 
296     tmp = a*xxyy;
297     isect1[0] = tmp + b*x1*yy;
298     isect1[1] = tmp + c*x0*yy;
299 
300     tmp = d*xxyy;
301     isect2[0] = tmp + e*xx*y1;
302     isect2[1] = tmp + f*xx*y0;
303 
304     SORT(isect1[0], isect1[1]);
305     SORT(isect2[0], isect2[1]);
306 
307     if (isect1[1]<isect2[0] || isect2[1]<isect1[0]) return 0;
308     return 1;
309 }

 

三、三角形与轴对齐盒体相交:

  1 #pragma once
  2 
  3 /********************************************************/
  4 /* AABB-triangle overlap test code                      */
  5 /* by Tomas Akenine-Möller                              */
  6 /* Function: int triBoxOverlap(float boxcenter[3],      */
  7 /*          float boxhalfsize[3],float triverts[3][3]); */
  8 /* History:                                             */
  9 /*   2001-03-05: released the code in its first version */
 10 /*   2001-06-18: changed the order of the tests, faster */
 11 /*                                                      */
 12 /* Acknowledgement: Many thanks to Pierre Terdiman for  */
 13 /* suggestions and discussions on how to optimize code. */
 14 /* Thanks to David Hunt for finding a ">="-bug!         */
 15 /********************************************************/
 16 
 17 #include <math.h>
 18 #include <stdio.h>
 19 
 20 #define X 0
 21 #define Y 1
 22 #define Z 2
 23 
 24 #define CROSS(dest,v1,v2) \
 25 dest[0] = v1[1] * v2[2] - v1[2] * v2[1]; \
 26 dest[1] = v1[2] * v2[0] - v1[0] * v2[2]; \
 27 dest[2] = v1[0] * v2[1] - v1[1] * v2[0];
 28 
 29 #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
 30 
 31 #define SUB(dest,v1,v2) \
 32 dest[0] = v1[0] - v2[0]; \
 33 dest[1] = v1[1] - v2[1]; \
 34 dest[2] = v1[2] - v2[2];
 35 
 36 #define FINDMINMAX(x0,x1,x2,min,max) \
 37 min = max = x0;   \
 38 if (x1<min) min = x1; \
 39     if (x1>max) max = x1; \
 40         if (x2<min) min = x2; \
 41             if (x2>max) max = x2;
 42 
 43 int planeBoxOverlap(float normal[3], float vert[3], float maxbox[3])    // -NJMP-
 44 {
 45     int q;
 46     float vmin[3], vmax[3], v;
 47     for (q = X; q <= Z; q++)
 48     {
 49         v = vert[q];                    // -NJMP-
 50         if (normal[q]>0.0f)
 51         {
 52             vmin[q] = -maxbox[q] - v;    // -NJMP-
 53             vmax[q] = maxbox[q] - v;    // -NJMP-
 54         }
 55         else
 56         {
 57             vmin[q] = maxbox[q] - v;    // -NJMP-
 58             vmax[q] = -maxbox[q] - v;    // -NJMP-
 59         }
 60     }
 61     if (DOT(normal, vmin)>0.0f) return 0;    // -NJMP-
 62     if (DOT(normal, vmax) >= 0.0f) return 1;    // -NJMP-
 63     return 0;
 64 }
 65 
 66 /*======================== X-tests ========================*/
 67 
 68 #define AXISTEST_X01(a, b, fa, fb)               \
 69 p0 = a*v0[Y] - b*v0[Z];                          \
 70 p2 = a*v2[Y] - b*v2[Z];                          \
 71 if (p0<p2) { min = p0; max = p2; }\
 72 else { min = p2; max = p0; } \
 73 rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z];   \
 74 if (min>rad || max<-rad) return 0;
 75 
 76 #define AXISTEST_X2(a, b, fa, fb)               \
 77 p0 = a*v0[Y] - b*v0[Z];                       \
 78 p1 = a*v1[Y] - b*v1[Z];                          \
 79 if (p0<p1) { min = p0; max = p1; }\
 80 else { min = p1; max = p0; } \
 81 rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z];   \
 82 if (min>rad || max<-rad) return 0;
 83 
 84 /*======================== Y-tests ========================*/
 85 
 86 #define AXISTEST_Y02(a, b, fa, fb)               \
 87 p0 = -a*v0[X] + b*v0[Z];                     \
 88 p2 = -a*v2[X] + b*v2[Z];                             \
 89 if (p0<p2) { min = p0; max = p2; }\
 90 else { min = p2; max = p0; } \
 91 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z];   \
 92 if (min>rad || max<-rad) return 0;
 93 
 94 #define AXISTEST_Y1(a, b, fa, fb)               \
 95 p0 = -a*v0[X] + b*v0[Z];                     \
 96 p1 = -a*v1[X] + b*v1[Z];                           \
 97 if (p0<p1) { min = p0; max = p1; }\
 98 else { min = p1; max = p0; } \
 99 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z];   \
100 if (min>rad || max<-rad) return 0;
101 
102 /*======================== Z-tests ========================*/
103 
104 #define AXISTEST_Z12(a, b, fa, fb)               \
105 p1 = a*v1[X] - b*v1[Y];                       \
106 p2 = a*v2[X] - b*v2[Y];                          \
107 if (p2<p1) { min = p2; max = p1; }\
108 else { min = p1; max = p2; } \
109 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y];   \
110 if (min>rad || max<-rad) return 0;
111 
112 #define AXISTEST_Z0(a, b, fa, fb)               \
113 p0 = a*v0[X] - b*v0[Y];                   \
114 p1 = a*v1[X] - b*v1[Y];                       \
115 if (p0<p1) { min = p0; max = p1; }\
116 else { min = p1; max = p0; } \
117 rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y];   \
118 if (min>rad || max<-rad) return 0;
119 
120 int triBoxOverlap(float* vert1, float* vert2, float* vert3, float* boxcenter, float* boxhalfsize)
121 {
122     /*    use separating axis theorem to test overlap between triangle and box */
123     /*    need to test for overlap in these directions: */
124     /*    1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
125     /*       we do not even need to test these) */
126     /*    2) normal of the triangle */
127     /*    3) crossproduct(edge from tri, {x,y,z}-directin) */
128     /*       this gives 3x3=9 more tests */
129     float v0[3], v1[3], v2[3];
130     float min, max, p0, p1, p2, rad, fex, fey, fez;        // -NJMP- "d" local variable removed
131     float normal[3], e0[3], e1[3], e2[3];
132 
133     /* This is the fastest branch on Sun */
134     /* move everything so that the boxcenter is in (0,0,0) */
135 
136     SUB(v0, vert1, boxcenter);
137     SUB(v1, vert2, boxcenter);
138     SUB(v2, vert3, boxcenter);
139 
140     /* compute triangle edges */
141     SUB(e0, v1, v0);      /* tri edge 0 */
142     SUB(e1, v2, v1);      /* tri edge 1 */
143     SUB(e2, v0, v2);      /* tri edge 2 */
144 
145     /* Bullet 3:  */
146     /*  test the 9 tests first (this was faster) */
147     fex = fabsf(e0[X]);
148     fey = fabsf(e0[Y]);
149     fez = fabsf(e0[Z]);
150     AXISTEST_X01(e0[Z], e0[Y], fez, fey);
151     AXISTEST_Y02(e0[Z], e0[X], fez, fex);
152     AXISTEST_Z12(e0[Y], e0[X], fey, fex);
153 
154     fex = fabsf(e1[X]);
155     fey = fabsf(e1[Y]);
156     fez = fabsf(e1[Z]);
157     AXISTEST_X01(e1[Z], e1[Y], fez, fey);
158     AXISTEST_Y02(e1[Z], e1[X], fez, fex);
159     AXISTEST_Z0(e1[Y], e1[X], fey, fex);
160 
161     fex = fabsf(e2[X]);
162     fey = fabsf(e2[Y]);
163     fez = fabsf(e2[Z]);
164     AXISTEST_X2(e2[Z], e2[Y], fez, fey);
165     AXISTEST_Y1(e2[Z], e2[X], fez, fex);
166     AXISTEST_Z12(e2[Y], e2[X], fey, fex);
167 
168     /* Bullet 1: */
169     /*  first test overlap in the {x,y,z}-directions */
170     /*  find min, max of the triangle each direction, and test for overlap in */
171     /*  that direction -- this is equivalent to testing a minimal AABB around */
172     /*  the triangle against the AABB */
173 
174     /* test in X-direction */
175     FINDMINMAX(v0[X], v1[X], v2[X], min, max);
176     if (min>boxhalfsize[X] || max<-boxhalfsize[X]) return 0;
177 
178     /* test in Y-direction */
179     FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
180     if (min>boxhalfsize[Y] || max<-boxhalfsize[Y]) return 0;
181 
182     /* test in Z-direction */
183     FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
184     if (min>boxhalfsize[Z] || max<-boxhalfsize[Z]) return 0;
185 
186     /* Bullet 2: */
187     /*  test if the box intersects the plane of the triangle */
188     /*  compute plane equation of triangle: normal*x+d=0 */
189     CROSS(normal, e0, e1);
190     if (!planeBoxOverlap(normal, v0, boxhalfsize)) return 0;    // -NJMP-
191 
192     return 1;   /* box and triangle overlaps */
193 }

 

转载于:https://www.cnblogs.com/time-flow1024/p/10061781.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值