Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

aabb.cpp

Go to the documentation of this file.
00001 /************************************************************************
00002    AABB code.  This should probably be developed into a proper object, but
00003    for now, it's more useful as a collection of low-level functions.
00004    This includes:
00005      - intersection tests with planes and triangles
00006        Adapted with very few changes from code by Tomas Möller.
00007      - distance to point calculation
00008        Adapted from OBB-point distance code by Dave Eberly.
00009  ************************************************************************/
00010 
00011 #include "aabb.h"
00012 
00013 #define X 0
00014 #define Y 1
00015 #define Z 2
00016 
00017 #define FINDMINMAX(x0,x1,x2,min,max) \
00018   min = max = x0;   \
00019   if(x1<min) min=x1;\
00020   if(x1>max) max=x1;\
00021   if(x2<min) min=x2;\
00022   if(x2>max) max=x2;
00023 
00024 
00025 bool aabb_intersects_plane(
00026     const gmVector3& length,
00027     const gmVector3& normal, 
00028     double      d )
00029 {
00030     int q;
00031     gmVector3 vmin, vmax;
00032     for(q=X;q<=Z;q++)
00033     {
00034         if(normal[q]>0.0f)
00035         {
00036             vmin[q]=-length[q];
00037             vmax[q]=length[q];
00038         }
00039         else
00040         {
00041             vmin[q]=length[q];
00042             vmax[q]=-length[q];
00043         }
00044     }
00045     if(dot(normal,vmin)+d>0.0f) return false;
00046     if(dot(normal,vmax)+d>0.0f) return true;
00047   
00048     return false;
00049 }
00050 
00051 
00052 /*======================== X-tests ========================*/
00053 #define AXISTEST_X01(a, b, fa, fb)                         \
00054         p0 = a*v0[Y] - b*v0[Z];                            \
00055         p2 = a*v2[Y] - b*v2[Z];                            \
00056         if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
00057         rad = fa * length[Y] + fb * length[Z];   \
00058         if(min>rad || max<-rad) return false;
00059 
00060 #define AXISTEST_X2(a, b, fa, fb)                          \
00061         p0 = a*v0[Y] - b*v0[Z];                            \
00062         p1 = a*v1[Y] - b*v1[Z];                            \
00063         if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
00064         rad = fa * length[Y] + fb * length[Z];   \
00065         if(min>rad || max<-rad) return false;
00066 
00067 /*======================== Y-tests ========================*/
00068 #define AXISTEST_Y02(a, b, fa, fb)                         \
00069         p0 = -a*v0[X] + b*v0[Z];                           \
00070         p2 = -a*v2[X] + b*v2[Z];                           \
00071         if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
00072         rad = fa * length[X] + fb * length[Z];   \
00073         if(min>rad || max<-rad) return false;
00074 
00075 #define AXISTEST_Y1(a, b, fa, fb)                          \
00076         p0 = -a*v0[X] + b*v0[Z];                           \
00077         p1 = -a*v1[X] + b*v1[Z];                           \
00078         if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
00079         rad = fa * length[X] + fb * length[Z];   \
00080         if(min>rad || max<-rad) return false;
00081 
00082 /*======================== Z-tests ========================*/
00083 
00084 #define AXISTEST_Z12(a, b, fa, fb)                         \
00085         p1 = a*v1[X] - b*v1[Y];                            \
00086         p2 = a*v2[X] - b*v2[Y];                            \
00087         if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
00088         rad = fa * length[X] + fb * length[Y];   \
00089         if(min>rad || max<-rad) return false;
00090 
00091 #define AXISTEST_Z0(a, b, fa, fb)                          \
00092         p0 = a*v0[X] - b*v0[Y];                            \
00093         p1 = a*v1[X] - b*v1[Y];                            \
00094         if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
00095         rad = fa * length[X] + fb * length[Y];   \
00096         if(min>rad || max<-rad) return false;
00097 
00098 bool aabb_intersects_triangle(
00099     const gmVector3& aabbcenter,
00100     const gmVector3& length,
00101     const gmVector3& vv0,
00102     const gmVector3& vv1, 
00103     const gmVector3& vv2 )
00104 {
00105     // use separating axis theorem to test overlap between triangle and aabb 
00106     // need to test for overlap in these directions: 
00107     // 1) the {x,y,z}-directions 
00108     //    (actually, since we use the AABB of the triangle 
00109     //    we do not even need to test these) 
00110     // 2) normal of the triangle 
00111     // 3) crossproduct(edge from tri, {x,y,z}-directin) 
00112     //    this gives 3x3=9 more tests 
00113 
00114     gmVector3 v0, v1, v2;
00115     double min,max,d,p0,p1,p2,rad,fex,fey,fez;  
00116     gmVector3 normal, e0, e1, e2;
00117 
00118     // 1) first test overlap in the {x,y,z}-directions 
00119     //    find min, max of the triangle each direction, and test for 
00120     //    overlap in that direction -- this is equivalent to testing a 
00121     //    minimal AABB around the triangle against the AABB 
00122     v0 = vv0 - aabbcenter;
00123     v1 = vv1 - aabbcenter;
00124     v2 = vv2 - aabbcenter;
00125 
00126     FINDMINMAX(v0[X],v1[X],v2[X],min,max);
00127     if(min>length[X] || max<-length[X]) 
00128         return false;
00129 
00130     FINDMINMAX(v0[Y],v1[Y],v2[Y],min,max);
00131     if(min>length[Y] || max<-length[Y]) 
00132         return false;
00133 
00134     FINDMINMAX(v0[Z],v1[Z],v2[Z],min,max);
00135     if(min>length[Z] || max<-length[Z]) 
00136         return false;
00137 
00138     // 2) test if the aabb intersects the plane of the triangle 
00139     //    compute plane equation of triangle: normal*x+d=0 
00140     e0 = v1 - v0;
00141     e1 = v2 - v1;
00142     normal = cross(e0,e1);
00143     d=-dot(normal,v0);  // plane eq: normal.x+d=0 
00144 
00145     if(!aabb_intersects_plane(length, normal, d)) 
00146         return false;
00147 
00148     //    compute the last triangle edge 
00149     e2 = v0 - v2;
00150 
00151     //    3) 
00152     fex = fabs(e0[X]);
00153     fey = fabs(e0[Y]);
00154     fez = fabs(e0[Z]);
00155     AXISTEST_X01(e0[Z], e0[Y], fez, fey);
00156     AXISTEST_Y02(e0[Z], e0[X], fez, fex);
00157     AXISTEST_Z12(e0[Y], e0[X], fey, fex);
00158 
00159     fex = fabs(e1[X]);
00160     fey = fabs(e1[Y]);
00161     fez = fabs(e1[Z]);
00162     AXISTEST_X01(e1[Z], e1[Y], fez, fey);
00163     AXISTEST_Y02(e1[Z], e1[X], fez, fex);
00164     AXISTEST_Z0(e1[Y], e1[X], fey, fex);
00165 
00166 
00167     fex = fabs(e2[X]);
00168     fey = fabs(e2[Y]);
00169     fez = fabs(e2[Z]);
00170     AXISTEST_X2(e2[Z], e2[Y], fez, fey);
00171     AXISTEST_Y1(e2[Z], e2[X], fez, fex);
00172     AXISTEST_Z12(e2[Y], e2[X], fey, fex);
00173 
00174     return true;
00175 }
00176 
00177 
00178 // AABB-AABB intersection test, based on Gamasutra article by 
00179 // Miguel Gomez; October 18, 1999
00180 
00181 bool aabb_intersects_aabb(
00182     const gmVector3& center1,
00183     const gmVector3& length1,
00184     const gmVector3& center2,
00185     const gmVector3& length2 )
00186 {
00187     gmVector3 diff = center2 - center1;
00188     gmVector3 ext = length1 + length2;
00189 
00190     return (    ( fabs(diff[0]) <= ext[0] )
00191              && ( fabs(diff[1]) <= ext[1] )
00192              && ( fabs(diff[2]) <= ext[2] ) );
00193 }
00194 
00195 
00196 // Point-AABB distance based on code from Dave Eberly's Magic Software:
00197 //
00198 // Magic Software, Inc.
00199 // http://www.magic-software.com
00200 // Copyright (c) 2000, 2001.  All Rights Reserved
00201 //
00202 // Source code from Magic Software is supplied under the terms of a license
00203 // agreement and may not be copied or disclosed except in accordance with the
00204 // terms of that agreement.  The various license agreements may be found at
00205 // the Magic Software web site.  This file is subject to the license
00206 //
00207 // FREE SOURCE CODE
00208 // http://www.magic-software.com/License/free.pdf
00209 
00210 double aabb_distance_to_point(
00211     const gmVector3& center,
00212     const gmVector3& length,
00213     const gmVector3& p,
00214     gmVector3 *      where )
00215 {
00216     // compute coordinates of point in aabb coordinate system
00217     gmVector3 diff = p - center;
00218 
00219     // project test point onto aabb
00220     double distance = 0.0;
00221     double delta;
00222 
00223     for( int i=0; i<3; i++ )
00224         if ( diff[i] < -length[i] )
00225         {
00226             delta = diff[i] + length[i];
00227             distance += delta*delta;
00228             diff[i] = -length[i];
00229         }
00230         else if ( diff[i] > length[i] )
00231         {
00232             delta = diff[i] - length[i];
00233             distance += delta*delta;
00234             diff[i] = length[i];
00235         }
00236 
00237     if ( where )
00238         *where = diff;
00239 
00240     return distance;
00241 }

Generated on Mon Jun 28 14:58:12 2004 for Advanced Surface Library by doxygen 1.3.4