AABB-triangle overlap test code

本文介绍了一种使用分离轴定理来测试三维空间中三角形与轴对齐包围盒(AABB)之间是否发生碰撞的方法。该算法通过一系列方向上的重叠测试来判断两者是否存在交集。
 http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/tribox3.txt

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

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值