00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <stdlib.h>
00042 #include <math.h>
00043 #include "BV.h"
00044 #include "MatVec.h"
00045 #include "RectDist.h"
00046 #include "OBB_Disjoint.h"
00047
00048 BV::BV()
00049 {
00050 first_child = 0;
00051 }
00052
00053 BV::~BV()
00054 {
00055 }
00056
00057 static
00058 inline
00059 PQP_REAL
00060 MaxOfTwo(PQP_REAL a, PQP_REAL b)
00061 {
00062 if (a > b) return a;
00063 return b;
00064 }
00065
00066 void
00067 BV::FitToTris(PQP_REAL O[3][3], Tri *tris, int num_tris)
00068 {
00069
00070
00071 McM(R,O);
00072
00073
00074
00075 int num_points = 3*num_tris;
00076 PQP_REAL (*P)[3] = new PQP_REAL[num_points][3];
00077 int point = 0;
00078 int i;
00079 for (i = 0; i < num_tris; i++)
00080 {
00081 MTxV(P[point],R,tris[i].p1);
00082 point++;
00083
00084 MTxV(P[point],R,tris[i].p2);
00085 point++;
00086
00087 MTxV(P[point],R,tris[i].p3);
00088 point++;
00089 }
00090
00091 PQP_REAL minx, maxx, miny, maxy, minz, maxz, c[3];
00092
00093 #if PQP_BV_TYPE & OBB_TYPE
00094 minx = maxx = P[0][0];
00095 miny = maxy = P[0][1];
00096 minz = maxz = P[0][2];
00097 for (i = 1; i < num_points; i++)
00098 {
00099 if (P[i][0] < minx) minx = P[i][0];
00100 else if (P[i][0] > maxx) maxx = P[i][0];
00101 if (P[i][1] < miny) miny = P[i][1];
00102 else if (P[i][1] > maxy) maxy = P[i][1];
00103 if (P[i][2] < minz) minz = P[i][2];
00104 else if (P[i][2] > maxz) maxz = P[i][2];
00105 }
00106 c[0] = (PQP_REAL)0.5*(maxx + minx);
00107 c[1] = (PQP_REAL)0.5*(maxy + miny);
00108 c[2] = (PQP_REAL)0.5*(maxz + minz);
00109 MxV(To,R,c);
00110
00111 d[0] = (PQP_REAL)0.5*(maxx - minx);
00112 d[1] = (PQP_REAL)0.5*(maxy - miny);
00113 d[2] = (PQP_REAL)0.5*(maxz - minz);
00114 #endif
00115
00116 #if PQP_BV_TYPE & RSS_TYPE
00117
00118
00119
00120 PQP_REAL cz,radsqr;
00121 minz = maxz = P[0][2];
00122 for (i = 1; i < num_points; i++)
00123 {
00124 if (P[i][2] < minz) minz = P[i][2];
00125 else if (P[i][2] > maxz) maxz = P[i][2];
00126 }
00127 r = (PQP_REAL)0.5*(maxz - minz);
00128 radsqr = r*r;
00129 cz = (PQP_REAL)0.5*(maxz + minz);
00130
00131
00132
00133
00134
00135 int minindex, maxindex;
00136 minindex = maxindex = 0;
00137 for (i = 1; i < num_points; i++)
00138 {
00139 if (P[i][0] < P[minindex][0]) minindex = i;
00140 else if (P[i][0] > P[maxindex][0]) maxindex = i;
00141 }
00142 PQP_REAL x, dz;
00143 dz = P[minindex][2] - cz;
00144 minx = P[minindex][0] + sqrt(MaxOfTwo(radsqr - dz*dz,0));
00145 dz = P[maxindex][2] - cz;
00146 maxx = P[maxindex][0] - sqrt(MaxOfTwo(radsqr - dz*dz,0));
00147
00148
00149
00150 for (i = 0; i < num_points; i++)
00151 {
00152 if (P[i][0] < minx)
00153 {
00154 dz = P[i][2] - cz;
00155 x = P[i][0] + sqrt(MaxOfTwo(radsqr - dz*dz,0));
00156 if (x < minx) minx = x;
00157 }
00158 }
00159
00160
00161
00162 for (i = 0; i < num_points; i++)
00163 {
00164 if (P[i][0] > maxx)
00165 {
00166 dz = P[i][2] - cz;
00167 x = P[i][0] - sqrt(MaxOfTwo(radsqr - dz*dz,0));
00168 if (x > maxx) maxx = x;
00169 }
00170 }
00171
00172
00173
00174
00175
00176 minindex = maxindex = 0;
00177 for (i = 1; i < num_points; i++)
00178 {
00179 if (P[i][1] < P[minindex][1]) minindex = i;
00180 else if (P[i][1] > P[maxindex][1]) maxindex = i;
00181 }
00182 PQP_REAL y;
00183 dz = P[minindex][2] - cz;
00184 miny = P[minindex][1] + sqrt(MaxOfTwo(radsqr - dz*dz,0));
00185 dz = P[maxindex][2] - cz;
00186 maxy = P[maxindex][1] - sqrt(MaxOfTwo(radsqr - dz*dz,0));
00187
00188
00189
00190 for (i = 0; i < num_points; i++)
00191 {
00192 if (P[i][1] < miny)
00193 {
00194 dz = P[i][2] - cz;
00195 y = P[i][1] + sqrt(MaxOfTwo(radsqr - dz*dz,0));
00196 if (y < miny) miny = y;
00197 }
00198 }
00199
00200
00201
00202 for (i = 0; i < num_points; i++)
00203 {
00204 if (P[i][1] > maxy)
00205 {
00206 dz = P[i][2] - cz;
00207 y = P[i][1] - sqrt(MaxOfTwo(radsqr - dz*dz,0));
00208 if (y > maxy) maxy = y;
00209 }
00210 }
00211
00212
00213
00214
00215 PQP_REAL dx, dy, u, t;
00216 PQP_REAL a = sqrt((PQP_REAL)0.5);
00217 for (i = 0; i < num_points; i++)
00218 {
00219 if (P[i][0] > maxx)
00220 {
00221 if (P[i][1] > maxy)
00222 {
00223 dx = P[i][0] - maxx;
00224 dy = P[i][1] - maxy;
00225 u = dx*a + dy*a;
00226 t = (a*u - dx)*(a*u - dx) +
00227 (a*u - dy)*(a*u - dy) +
00228 (cz - P[i][2])*(cz - P[i][2]);
00229 u = u - sqrt(MaxOfTwo(radsqr - t,0));
00230 if (u > 0)
00231 {
00232 maxx += u*a;
00233 maxy += u*a;
00234 }
00235 }
00236 else if (P[i][1] < miny)
00237 {
00238 dx = P[i][0] - maxx;
00239 dy = P[i][1] - miny;
00240 u = dx*a - dy*a;
00241 t = (a*u - dx)*(a*u - dx) +
00242 (-a*u - dy)*(-a*u - dy) +
00243 (cz - P[i][2])*(cz - P[i][2]);
00244 u = u - sqrt(MaxOfTwo(radsqr - t,0));
00245 if (u > 0)
00246 {
00247 maxx += u*a;
00248 miny -= u*a;
00249 }
00250 }
00251 }
00252 else if (P[i][0] < minx)
00253 {
00254 if (P[i][1] > maxy)
00255 {
00256 dx = P[i][0] - minx;
00257 dy = P[i][1] - maxy;
00258 u = dy*a - dx*a;
00259 t = (-a*u - dx)*(-a*u - dx) +
00260 (a*u - dy)*(a*u - dy) +
00261 (cz - P[i][2])*(cz - P[i][2]);
00262 u = u - sqrt(MaxOfTwo(radsqr - t,0));
00263 if (u > 0)
00264 {
00265 minx -= u*a;
00266 maxy += u*a;
00267 }
00268 }
00269 else if (P[i][1] < miny)
00270 {
00271 dx = P[i][0] - minx;
00272 dy = P[i][1] - miny;
00273 u = -dx*a - dy*a;
00274 t = (-a*u - dx)*(-a*u - dx) +
00275 (-a*u - dy)*(-a*u - dy) +
00276 (cz - P[i][2])*(cz - P[i][2]);
00277 u = u - sqrt(MaxOfTwo(radsqr - t,0));
00278 if (u > 0)
00279 {
00280 minx -= u*a;
00281 miny -= u*a;
00282 }
00283 }
00284 }
00285 }
00286
00287 c[0] = minx;
00288 c[1] = miny;
00289 c[2] = cz;
00290 MxV(Tr,R,c);
00291
00292 l[0] = maxx - minx;
00293 if (l[0] < 0) l[0] = 0;
00294 l[1] = maxy - miny;
00295 if (l[1] < 0) l[1] = 0;
00296 #endif
00297
00298 delete [] P;
00299 }
00300
00301 int
00302 BV_Overlap(PQP_REAL R[3][3], PQP_REAL T[3], BV *b1, BV *b2)
00303 {
00304 #if PQP_BV_TYPE & OBB_TYPE
00305 return (obb_disjoint(R,T,b1->d,b2->d) == 0);
00306 #else
00307 PQP_REAL dist = RectDist(R,T,b1->l,b2->l);
00308 if (dist <= (b1->r + b2->r)) return 1;
00309 return 0;
00310 #endif
00311 }
00312
00313 #if PQP_BV_TYPE & RSS_TYPE
00314 PQP_REAL
00315 BV_Distance(PQP_REAL R[3][3], PQP_REAL T[3], BV *b1, BV *b2)
00316 {
00317 PQP_REAL dist = RectDist(R,T,b1->l,b2->l);
00318 dist -= (b1->r + b2->r);
00319 return (dist < (PQP_REAL)0.0)? (PQP_REAL)0.0 : dist;
00320 }
00321 #endif
00322
00323