00001
00002
00003
00004
00005
00006
00007
00008
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
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
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
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
00106
00107
00108
00109
00110
00111
00112
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
00119
00120
00121
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
00139
00140 e0 = v1 - v0;
00141 e1 = v2 - v1;
00142 normal = cross(e0,e1);
00143 d=-dot(normal,v0);
00144
00145 if(!aabb_intersects_plane(length, normal, d))
00146 return false;
00147
00148
00149 e2 = v0 - v2;
00150
00151
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
00179
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
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 double aabb_distance_to_point(
00211 const gmVector3& center,
00212 const gmVector3& length,
00213 const gmVector3& p,
00214 gmVector3 * where )
00215 {
00216
00217 gmVector3 diff = p - center;
00218
00219
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 }