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 <stdio.h>
00042 #include <string.h>
00043 #include "PQP.h"
00044 #include "BVTQ.h"
00045 #include "Build.h"
00046 #include "MatVec.h"
00047 #include "GetTime.h"
00048 #include "TriDist.h"
00049 
00050 enum BUILD_STATE
00051 { 
00052   PQP_BUILD_STATE_EMPTY,     
00053   PQP_BUILD_STATE_BEGUN,     
00054   PQP_BUILD_STATE_PROCESSED  
00055 };
00056 
00057 PQP_Model::PQP_Model()
00058 {
00059   
00060 
00061   b = 0;  
00062   num_bvs_alloced = 0;
00063   num_bvs = 0;
00064 
00065   
00066 
00067   tris = 0;
00068   num_tris = 0;
00069   num_tris_alloced = 0;
00070 
00071   last_tri = 0;
00072 
00073   build_state = PQP_BUILD_STATE_EMPTY;
00074 }
00075 
00076 PQP_Model::~PQP_Model()
00077 {
00078   if (b != NULL)
00079     delete [] b;
00080   if (tris != NULL)
00081     delete [] tris;
00082 }
00083 
00084 int
00085 PQP_Model::BeginModel(int n)
00086 {
00087   
00088 
00089   if (build_state != PQP_BUILD_STATE_EMPTY) 
00090   {
00091     delete [] b;
00092     delete [] tris;
00093   
00094     num_tris = num_bvs = num_tris_alloced = num_bvs_alloced = 0;
00095   }
00096 
00097   
00098 
00099   if (n <= 0) n = 8;
00100   num_tris_alloced = n;
00101   tris = new Tri[n];
00102   if (!tris) 
00103   {
00104     fprintf(stderr, "PQP Error!  Out of memory for tri array on "
00105                     "BeginModel() call!\n");
00106     return PQP_ERR_MODEL_OUT_OF_MEMORY;  
00107   }
00108 
00109   
00110 
00111   if (build_state != PQP_BUILD_STATE_EMPTY)
00112   {
00113     fprintf(stderr,
00114             "PQP Warning! Called BeginModel() on a PQP_Model that \n"
00115             "was not empty. This model was cleared and previous\n"
00116             "triangle additions were lost.\n");
00117     build_state = PQP_BUILD_STATE_BEGUN;
00118     return PQP_ERR_BUILD_OUT_OF_SEQUENCE;
00119   }
00120 
00121   build_state = PQP_BUILD_STATE_BEGUN;
00122   return PQP_OK;
00123 }
00124 
00125 int
00126 PQP_Model::AddTri(const PQP_REAL *p1, 
00127                   const PQP_REAL *p2, 
00128                   const PQP_REAL *p3, 
00129                   int id)
00130 {
00131   if (build_state == PQP_BUILD_STATE_EMPTY)
00132   {
00133     BeginModel();
00134   }
00135   else if (build_state == PQP_BUILD_STATE_PROCESSED)
00136   {
00137     fprintf(stderr,"PQP Warning! Called AddTri() on PQP_Model \n"
00138                    "object that was already ended. AddTri() was\n"
00139                    "ignored.  Must do a BeginModel() to clear the\n"
00140                    "model for addition of new triangles\n");
00141     return PQP_ERR_BUILD_OUT_OF_SEQUENCE;
00142   }
00143         
00144   
00145 
00146   if (num_tris >= num_tris_alloced)
00147   {
00148     Tri *temp;
00149     temp = new Tri[num_tris_alloced*2];
00150     if (!temp)
00151     {
00152       fprintf(stderr, "PQP Error!  Out of memory for tri array on"
00153                       " AddTri() call!\n");
00154       return PQP_ERR_MODEL_OUT_OF_MEMORY;  
00155     }
00156     memcpy(temp, tris, sizeof(Tri)*num_tris);
00157     delete [] tris;
00158     tris = temp;
00159     num_tris_alloced = num_tris_alloced*2;
00160   }
00161   
00162   
00163 
00164   tris[num_tris].p1[0] = p1[0];
00165   tris[num_tris].p1[1] = p1[1];
00166   tris[num_tris].p1[2] = p1[2];
00167 
00168   tris[num_tris].p2[0] = p2[0];
00169   tris[num_tris].p2[1] = p2[1];
00170   tris[num_tris].p2[2] = p2[2];
00171 
00172   tris[num_tris].p3[0] = p3[0];
00173   tris[num_tris].p3[1] = p3[1];
00174   tris[num_tris].p3[2] = p3[2];
00175 
00176   tris[num_tris].id = id;
00177 
00178   num_tris += 1;
00179 
00180   return PQP_OK;
00181 }
00182 
00183 int
00184 PQP_Model::EndModel()
00185 {
00186   if (build_state == PQP_BUILD_STATE_PROCESSED)
00187   {
00188     fprintf(stderr,"PQP Warning! Called EndModel() on PQP_Model \n"
00189                    "object that was already ended. EndModel() was\n"
00190                    "ignored.  Must do a BeginModel() to clear the\n"
00191                    "model for addition of new triangles\n");
00192     return PQP_ERR_BUILD_OUT_OF_SEQUENCE;
00193   }
00194 
00195   
00196 
00197   if (num_tris == 0)
00198   {
00199     fprintf(stderr,"PQP Error! EndModel() called on model with"
00200                    " no triangles\n");
00201     return PQP_ERR_BUILD_EMPTY_MODEL;
00202   }
00203 
00204   
00205 
00206   if (num_tris_alloced > num_tris)
00207   {
00208     Tri *new_tris = new Tri[num_tris];
00209     if (!new_tris) 
00210     {
00211       fprintf(stderr, "PQP Error!  Out of memory for tri array "
00212                       "in EndModel() call!\n");
00213       return PQP_ERR_MODEL_OUT_OF_MEMORY;  
00214     }
00215     memcpy(new_tris, tris, sizeof(Tri)*num_tris);
00216     delete [] tris;
00217     tris = new_tris;
00218     num_tris_alloced = num_tris;
00219   }
00220 
00221   
00222 
00223   b = new BV[2*num_tris - 1];
00224   if (!b)
00225   {
00226     fprintf(stderr,"PQP Error! out of memory for BV array "
00227                    "in EndModel()\n");
00228     return PQP_ERR_MODEL_OUT_OF_MEMORY;
00229   }
00230   num_bvs_alloced = 2*num_tris - 1;
00231   num_bvs = 0;
00232 
00233   
00234 
00235   build_model(this);
00236   build_state = PQP_BUILD_STATE_PROCESSED;
00237 
00238   last_tri = tris;
00239 
00240   return PQP_OK;
00241 }
00242 
00243 int
00244 PQP_Model::MemUsage(int msg)
00245 {
00246   int mem_bv_list = sizeof(BV)*num_bvs;
00247   int mem_tri_list = sizeof(Tri)*num_tris;
00248 
00249   int total_mem = mem_bv_list + mem_tri_list + sizeof(PQP_Model);
00250 
00251   if (msg) 
00252   {
00253     fprintf(stderr,"Total for model %p: %d bytes\n", this, total_mem);
00254     fprintf(stderr,"BVs: %d alloced, take %ld bytes each\n",
00255             num_bvs, sizeof(BV));
00256     fprintf(stderr,"Tris: %d alloced, take %ld bytes each\n",
00257             num_tris, sizeof(Tri));
00258   }
00259   
00260   return total_mem;
00261 }
00262 
00263 
00264 
00265 
00266 
00267 PQP_CollideResult::PQP_CollideResult()
00268 {
00269   pairs = 0;
00270   num_pairs = num_pairs_alloced = 0;
00271   num_bv_tests = 0;
00272   num_tri_tests = 0;
00273 }
00274 
00275 PQP_CollideResult::~PQP_CollideResult()
00276 {
00277   delete [] pairs;
00278 }
00279 
00280 void
00281 PQP_CollideResult::FreePairsList()
00282 {
00283   num_pairs = num_pairs_alloced = 0;
00284   delete [] pairs;
00285   pairs = 0;
00286 }
00287 
00288 
00289 void
00290 PQP_CollideResult::SizeTo(int n)
00291 {
00292   CollisionPair *temp;
00293 
00294   if (n < num_pairs) 
00295   {
00296     fprintf(stderr, "PQP Error: Internal error in "
00297                     "'PQP_CollideResult::SizeTo(int n)'\n");
00298     fprintf(stderr, "       n = %d, but num_pairs = %d\n", n, num_pairs);
00299     return;
00300   }
00301   
00302   temp = new CollisionPair[n];
00303   memcpy(temp, pairs, num_pairs*sizeof(CollisionPair));
00304   delete [] pairs;
00305   pairs = temp;
00306   num_pairs_alloced = n;
00307   return;
00308 }
00309 
00310 void
00311 PQP_CollideResult::Add(int a, int b)
00312 {
00313   if (num_pairs >= num_pairs_alloced) 
00314   {
00315     
00316 
00317     SizeTo(num_pairs_alloced*2+8);
00318   }
00319 
00320   
00321 
00322   pairs[num_pairs].id1 = a;
00323   pairs[num_pairs].id2 = b;
00324   num_pairs++;
00325 }
00326 
00327 
00328        
00329 inline
00330 PQP_REAL
00331 max(PQP_REAL a, PQP_REAL b, PQP_REAL c)
00332 {
00333   PQP_REAL t = a;
00334   if (b > t) t = b;
00335   if (c > t) t = c;
00336   return t;
00337 }
00338 
00339 inline
00340 PQP_REAL
00341 min(PQP_REAL a, PQP_REAL b, PQP_REAL c)
00342 {
00343   PQP_REAL t = a;
00344   if (b < t) t = b;
00345   if (c < t) t = c;
00346   return t;
00347 }
00348 
00349 int
00350 project6(PQP_REAL *ax, 
00351          PQP_REAL *p1, PQP_REAL *p2, PQP_REAL *p3, 
00352          PQP_REAL *q1, PQP_REAL *q2, PQP_REAL *q3)
00353 {
00354   PQP_REAL P1 = VdotV(ax, p1);
00355   PQP_REAL P2 = VdotV(ax, p2);
00356   PQP_REAL P3 = VdotV(ax, p3);
00357   PQP_REAL Q1 = VdotV(ax, q1);
00358   PQP_REAL Q2 = VdotV(ax, q2);
00359   PQP_REAL Q3 = VdotV(ax, q3);
00360   
00361   PQP_REAL mx1 = max(P1, P2, P3);
00362   PQP_REAL mn1 = min(P1, P2, P3);
00363   PQP_REAL mx2 = max(Q1, Q2, Q3);
00364   PQP_REAL mn2 = min(Q1, Q2, Q3);
00365 
00366   if (mn1 > mx2) return 0;
00367   if (mn2 > mx1) return 0;
00368   return 1;
00369 }
00370 
00371 
00372 
00373 
00374 int 
00375 TriContact(PQP_REAL *P1, PQP_REAL *P2, PQP_REAL *P3,
00376            PQP_REAL *Q1, PQP_REAL *Q2, PQP_REAL *Q3) 
00377 {
00378 
00379   
00380   
00381   
00382   
00383   
00384   
00385   
00386   
00387 
00388   PQP_REAL p1[3], p2[3], p3[3];
00389   PQP_REAL q1[3], q2[3], q3[3];
00390   PQP_REAL e1[3], e2[3], e3[3];
00391   PQP_REAL f1[3], f2[3], f3[3];
00392   PQP_REAL g1[3], g2[3], g3[3];
00393   PQP_REAL h1[3], h2[3], h3[3];
00394   PQP_REAL n1[3], m1[3];
00395 
00396   PQP_REAL ef11[3], ef12[3], ef13[3];
00397   PQP_REAL ef21[3], ef22[3], ef23[3];
00398   PQP_REAL ef31[3], ef32[3], ef33[3];
00399   
00400   p1[0] = P1[0] - P1[0];  p1[1] = P1[1] - P1[1];  p1[2] = P1[2] - P1[2];
00401   p2[0] = P2[0] - P1[0];  p2[1] = P2[1] - P1[1];  p2[2] = P2[2] - P1[2];
00402   p3[0] = P3[0] - P1[0];  p3[1] = P3[1] - P1[1];  p3[2] = P3[2] - P1[2];
00403   
00404   q1[0] = Q1[0] - P1[0];  q1[1] = Q1[1] - P1[1];  q1[2] = Q1[2] - P1[2];
00405   q2[0] = Q2[0] - P1[0];  q2[1] = Q2[1] - P1[1];  q2[2] = Q2[2] - P1[2];
00406   q3[0] = Q3[0] - P1[0];  q3[1] = Q3[1] - P1[1];  q3[2] = Q3[2] - P1[2];
00407   
00408   e1[0] = p2[0] - p1[0];  e1[1] = p2[1] - p1[1];  e1[2] = p2[2] - p1[2];
00409   e2[0] = p3[0] - p2[0];  e2[1] = p3[1] - p2[1];  e2[2] = p3[2] - p2[2];
00410   e3[0] = p1[0] - p3[0];  e3[1] = p1[1] - p3[1];  e3[2] = p1[2] - p3[2];
00411 
00412   f1[0] = q2[0] - q1[0];  f1[1] = q2[1] - q1[1];  f1[2] = q2[2] - q1[2];
00413   f2[0] = q3[0] - q2[0];  f2[1] = q3[1] - q2[1];  f2[2] = q3[2] - q2[2];
00414   f3[0] = q1[0] - q3[0];  f3[1] = q1[1] - q3[1];  f3[2] = q1[2] - q3[2];
00415   
00416   VcrossV(n1, e1, e2);
00417   VcrossV(m1, f1, f2);
00418 
00419   VcrossV(g1, e1, n1);
00420   VcrossV(g2, e2, n1);
00421   VcrossV(g3, e3, n1);
00422   VcrossV(h1, f1, m1);
00423   VcrossV(h2, f2, m1);
00424   VcrossV(h3, f3, m1);
00425 
00426   VcrossV(ef11, e1, f1);
00427   VcrossV(ef12, e1, f2);
00428   VcrossV(ef13, e1, f3);
00429   VcrossV(ef21, e2, f1);
00430   VcrossV(ef22, e2, f2);
00431   VcrossV(ef23, e2, f3);
00432   VcrossV(ef31, e3, f1);
00433   VcrossV(ef32, e3, f2);
00434   VcrossV(ef33, e3, f3);
00435   
00436   
00437 
00438   if (!project6(n1, p1, p2, p3, q1, q2, q3)) return 0;
00439   if (!project6(m1, p1, p2, p3, q1, q2, q3)) return 0;
00440   
00441   if (!project6(ef11, p1, p2, p3, q1, q2, q3)) return 0;
00442   if (!project6(ef12, p1, p2, p3, q1, q2, q3)) return 0;
00443   if (!project6(ef13, p1, p2, p3, q1, q2, q3)) return 0;
00444   if (!project6(ef21, p1, p2, p3, q1, q2, q3)) return 0;
00445   if (!project6(ef22, p1, p2, p3, q1, q2, q3)) return 0;
00446   if (!project6(ef23, p1, p2, p3, q1, q2, q3)) return 0;
00447   if (!project6(ef31, p1, p2, p3, q1, q2, q3)) return 0;
00448   if (!project6(ef32, p1, p2, p3, q1, q2, q3)) return 0;
00449   if (!project6(ef33, p1, p2, p3, q1, q2, q3)) return 0;
00450 
00451   if (!project6(g1, p1, p2, p3, q1, q2, q3)) return 0;
00452   if (!project6(g2, p1, p2, p3, q1, q2, q3)) return 0;
00453   if (!project6(g3, p1, p2, p3, q1, q2, q3)) return 0;
00454   if (!project6(h1, p1, p2, p3, q1, q2, q3)) return 0;
00455   if (!project6(h2, p1, p2, p3, q1, q2, q3)) return 0;
00456   if (!project6(h3, p1, p2, p3, q1, q2, q3)) return 0;
00457 
00458   return 1;
00459 }
00460 
00461 inline
00462 PQP_REAL
00463 TriDistance(PQP_REAL R[3][3], PQP_REAL T[3], Tri *t1, Tri *t2,
00464             PQP_REAL p[3], PQP_REAL q[3])
00465 {
00466   
00467 
00468   PQP_REAL tri1[3][3], tri2[3][3];
00469 
00470   VcV(tri1[0], t1->p1);
00471   VcV(tri1[1], t1->p2);
00472   VcV(tri1[2], t1->p3);
00473   MxVpV(tri2[0], R, t2->p1, T);
00474   MxVpV(tri2[1], R, t2->p2, T);
00475   MxVpV(tri2[2], R, t2->p3, T);
00476                                 
00477   return TriDist(p,q,tri1,tri2);
00478 }
00479 
00480 
00481 void
00482 CollideRecurse(PQP_CollideResult *res,
00483                PQP_REAL R[3][3], PQP_REAL T[3], 
00484                PQP_Model *o1, int b1, 
00485                PQP_Model *o2, int b2, int flag)
00486 {
00487   
00488 
00489   res->num_bv_tests++;
00490 
00491   if (!BV_Overlap(R, T, o1->child(b1), o2->child(b2))) return;
00492 
00493   
00494 
00495   int l1 = o1->child(b1)->Leaf();
00496   int l2 = o2->child(b2)->Leaf();
00497 
00498   if (l1 && l2) 
00499   {
00500     res->num_tri_tests++;
00501 
00502 #if 1
00503     
00504 
00505     Tri *t1 = &o1->tris[-o1->child(b1)->first_child - 1];
00506     Tri *t2 = &o2->tris[-o2->child(b2)->first_child - 1];
00507     PQP_REAL q1[3], q2[3], q3[3];
00508     PQP_REAL *p1 = t1->p1;
00509     PQP_REAL *p2 = t1->p2;
00510     PQP_REAL *p3 = t1->p3;    
00511     MxVpV(q1, res->R, t2->p1, res->T);
00512     MxVpV(q2, res->R, t2->p2, res->T);
00513     MxVpV(q3, res->R, t2->p3, res->T);
00514     if (TriContact(p1, p2, p3, q1, q2, q3)) 
00515     {
00516       
00517 
00518       res->Add(t1->id, t2->id);
00519     }
00520 #else
00521     PQP_REAL p[3], q[3];
00522 
00523     Tri *t1 = &o1->tris[-o1->child(b1)->first_child - 1];
00524     Tri *t2 = &o2->tris[-o2->child(b2)->first_child - 1];
00525 
00526     if (TriDistance(res->R,res->T,t1,t2,p,q) == 0.0)
00527     {
00528       
00529 
00530       res->Add(t1->id, t2->id);
00531     }
00532 #endif
00533 
00534     return;
00535   }
00536 
00537   
00538 
00539   PQP_REAL sz1 = o1->child(b1)->GetSize();
00540   PQP_REAL sz2 = o2->child(b2)->GetSize();
00541 
00542   PQP_REAL Rc[3][3],Tc[3],Ttemp[3];
00543     
00544   if (l2 || (!l1 && (sz1 > sz2)))
00545   {
00546     int c1 = o1->child(b1)->first_child;
00547     int c2 = c1 + 1;
00548 
00549     MTxM(Rc,o1->child(c1)->R,R);
00550 #if PQP_BV_TYPE & OBB_TYPE
00551     VmV(Ttemp,T,o1->child(c1)->To);
00552 #else
00553     VmV(Ttemp,T,o1->child(c1)->Tr);
00554 #endif
00555     MTxV(Tc,o1->child(c1)->R,Ttemp);
00556     CollideRecurse(res,Rc,Tc,o1,c1,o2,b2,flag);
00557 
00558     if ((flag == PQP_FIRST_CONTACT) && (res->num_pairs > 0)) return;
00559 
00560     MTxM(Rc,o1->child(c2)->R,R);
00561 #if PQP_BV_TYPE & OBB_TYPE
00562     VmV(Ttemp,T,o1->child(c2)->To);
00563 #else
00564     VmV(Ttemp,T,o1->child(c2)->Tr);
00565 #endif
00566     MTxV(Tc,o1->child(c2)->R,Ttemp);
00567     CollideRecurse(res,Rc,Tc,o1,c2,o2,b2,flag);
00568   }
00569   else 
00570   {
00571     int c1 = o2->child(b2)->first_child;
00572     int c2 = c1 + 1;
00573 
00574     MxM(Rc,R,o2->child(c1)->R);
00575 #if PQP_BV_TYPE & OBB_TYPE
00576     MxVpV(Tc,R,o2->child(c1)->To,T);
00577 #else
00578     MxVpV(Tc,R,o2->child(c1)->Tr,T);
00579 #endif
00580     CollideRecurse(res,Rc,Tc,o1,b1,o2,c1,flag);
00581 
00582     if ((flag == PQP_FIRST_CONTACT) && (res->num_pairs > 0)) return;
00583 
00584     MxM(Rc,R,o2->child(c2)->R);
00585 #if PQP_BV_TYPE & OBB_TYPE
00586     MxVpV(Tc,R,o2->child(c2)->To,T);
00587 #else
00588     MxVpV(Tc,R,o2->child(c2)->Tr,T);
00589 #endif
00590     CollideRecurse(res,Rc,Tc,o1,b1,o2,c2,flag);
00591   }
00592 }
00593 
00594 int 
00595 PQP_Collide(PQP_CollideResult *res,
00596             PQP_REAL R1[3][3], PQP_REAL T1[3], PQP_Model *o1,
00597             PQP_REAL R2[3][3], PQP_REAL T2[3], PQP_Model *o2,
00598             int flag)
00599 {
00600   double t1 = GetTime();
00601 
00602   
00603 
00604   if (o1->build_state != PQP_BUILD_STATE_PROCESSED) 
00605     return PQP_ERR_UNPROCESSED_MODEL;
00606   if (o2->build_state != PQP_BUILD_STATE_PROCESSED) 
00607     return PQP_ERR_UNPROCESSED_MODEL;
00608 
00609   
00610 
00611   res->num_bv_tests = 0;
00612   res->num_tri_tests = 0;
00613   
00614   
00615 
00616   res->num_pairs = 0;
00617   
00618   
00619   
00620   
00621 
00622   MTxM(res->R,R1,R2);
00623   PQP_REAL Ttemp[3];
00624   VmV(Ttemp, T2, T1);  
00625   MTxV(res->T, R1, Ttemp);
00626   
00627   
00628 
00629   PQP_REAL Rtemp[3][3], R[3][3], T[3];
00630 
00631   MxM(Rtemp,res->R,o2->child(0)->R);
00632   MTxM(R,o1->child(0)->R,Rtemp);
00633 
00634 #if PQP_BV_TYPE & OBB_TYPE
00635   MxVpV(Ttemp,res->R,o2->child(0)->To,res->T);
00636   VmV(Ttemp,Ttemp,o1->child(0)->To);
00637 #else
00638   MxVpV(Ttemp,res->R,o2->child(0)->Tr,res->T);
00639   VmV(Ttemp,Ttemp,o1->child(0)->Tr);
00640 #endif
00641 
00642   MTxV(T,o1->child(0)->R,Ttemp);
00643 
00644   
00645 
00646   CollideRecurse(res,R,T,o1,0,o2,0,flag);
00647   
00648   double t2 = GetTime();
00649   res->query_time_secs = t2 - t1;
00650   
00651   return PQP_OK; 
00652 }
00653 
00654 #if PQP_BV_TYPE & RSS_TYPE // distance/tolerance only available with RSS
00655                            
00656                            
00657 
00658 
00659 
00660 
00661 
00662 void
00663 DistanceRecurse(PQP_DistanceResult *res,
00664                 PQP_REAL R[3][3], PQP_REAL T[3], 
00665                 PQP_Model *o1, int b1,
00666                 PQP_Model *o2, int b2)
00667 {
00668   PQP_REAL sz1 = o1->child(b1)->GetSize();
00669   PQP_REAL sz2 = o2->child(b2)->GetSize();
00670   int l1 = o1->child(b1)->Leaf();
00671   int l2 = o2->child(b2)->Leaf();
00672 
00673   if (l1 && l2)
00674   {
00675     
00676 
00677     res->num_tri_tests++;
00678 
00679     PQP_REAL p[3], q[3];
00680 
00681     Tri *t1 = &o1->tris[-o1->child(b1)->first_child - 1];
00682     Tri *t2 = &o2->tris[-o2->child(b2)->first_child - 1];
00683 
00684     PQP_REAL d = TriDistance(res->R,res->T,t1,t2,p,q);
00685   
00686     if (d < res->distance) 
00687     {
00688       res->distance = d;
00689 
00690       VcV(res->p1, p);         
00691       VcV(res->p2, q);         
00692                                
00693       o1->last_tri = t1;
00694       o2->last_tri = t2;
00695     }
00696 
00697     return;
00698   }
00699 
00700   
00701   
00702   
00703 
00704   int a1,a2,c1,c2;  
00705   PQP_REAL R1[3][3], T1[3], R2[3][3], T2[3], Ttemp[3];
00706 
00707   if (l2 || (!l1 && (sz1 > sz2)))
00708   {
00709     
00710 
00711     a1 = o1->child(b1)->first_child;
00712     a2 = b2;
00713     c1 = o1->child(b1)->first_child+1;
00714     c2 = b2;
00715     
00716     MTxM(R1,o1->child(a1)->R,R);
00717 #if PQP_BV_TYPE & RSS_TYPE
00718     VmV(Ttemp,T,o1->child(a1)->Tr);
00719 #else
00720     VmV(Ttemp,T,o1->child(a1)->To);
00721 #endif
00722     MTxV(T1,o1->child(a1)->R,Ttemp);
00723 
00724     MTxM(R2,o1->child(c1)->R,R);
00725 #if PQP_BV_TYPE & RSS_TYPE
00726     VmV(Ttemp,T,o1->child(c1)->Tr);
00727 #else
00728     VmV(Ttemp,T,o1->child(c1)->To);
00729 #endif
00730     MTxV(T2,o1->child(c1)->R,Ttemp);
00731   }
00732   else 
00733   {
00734     
00735 
00736     a1 = b1;
00737     a2 = o2->child(b2)->first_child;
00738     c1 = b1;
00739     c2 = o2->child(b2)->first_child+1;
00740 
00741     MxM(R1,R,o2->child(a2)->R);
00742 #if PQP_BV_TYPE & RSS_TYPE
00743     MxVpV(T1,R,o2->child(a2)->Tr,T);
00744 #else
00745     MxVpV(T1,R,o2->child(a2)->To,T);
00746 #endif
00747 
00748     MxM(R2,R,o2->child(c2)->R);
00749 #if PQP_BV_TYPE & RSS_TYPE
00750     MxVpV(T2,R,o2->child(c2)->Tr,T);
00751 #else
00752     MxVpV(T2,R,o2->child(c2)->To,T);
00753 #endif
00754   }
00755 
00756   res->num_bv_tests += 2;
00757 
00758   PQP_REAL d1 = BV_Distance(R1, T1, o1->child(a1), o2->child(a2));
00759   PQP_REAL d2 = BV_Distance(R2, T2, o1->child(c1), o2->child(c2));
00760 
00761   if (d2 < d1)
00762   {
00763     if ((d2 < (res->distance - res->abs_err)) || 
00764         (d2*(1 + res->rel_err) < res->distance)) 
00765     {      
00766       DistanceRecurse(res, R2, T2, o1, c1, o2, c2);      
00767     }
00768 
00769     if ((d1 < (res->distance - res->abs_err)) || 
00770         (d1*(1 + res->rel_err) < res->distance)) 
00771     {      
00772       DistanceRecurse(res, R1, T1, o1, a1, o2, a2);
00773     }
00774   }
00775   else 
00776   {
00777     if ((d1 < (res->distance - res->abs_err)) || 
00778         (d1*(1 + res->rel_err) < res->distance)) 
00779     {      
00780       DistanceRecurse(res, R1, T1, o1, a1, o2, a2);
00781     }
00782 
00783     if ((d2 < (res->distance - res->abs_err)) || 
00784         (d2*(1 + res->rel_err) < res->distance)) 
00785     {      
00786       DistanceRecurse(res, R2, T2, o1, c1, o2, c2);      
00787     }
00788   }
00789 }
00790 
00791 void
00792 DistanceQueueRecurse(PQP_DistanceResult *res, 
00793                      PQP_REAL R[3][3], PQP_REAL T[3],
00794                      PQP_Model *o1, int b1,
00795                      PQP_Model *o2, int b2)
00796 {
00797   BVTQ bvtq(res->qsize);
00798 
00799   BVT min_test;
00800   min_test.b1 = b1;
00801   min_test.b2 = b2;
00802   McM(min_test.R,R);
00803   VcV(min_test.T,T);
00804 
00805   while(1) 
00806   {  
00807     int l1 = o1->child(min_test.b1)->Leaf();
00808     int l2 = o2->child(min_test.b2)->Leaf();
00809     
00810     if (l1 && l2) 
00811     {  
00812       
00813 
00814       res->num_tri_tests++;
00815 
00816       PQP_REAL p[3], q[3];
00817 
00818       Tri *t1 = &o1->tris[-o1->child(min_test.b1)->first_child - 1];
00819       Tri *t2 = &o2->tris[-o2->child(min_test.b2)->first_child - 1];
00820 
00821       PQP_REAL d = TriDistance(res->R,res->T,t1,t2,p,q);
00822   
00823       if (d < res->distance)
00824       {
00825         res->distance = d;
00826 
00827         VcV(res->p1, p);         
00828         VcV(res->p2, q);         
00829                                  
00830         o1->last_tri = t1;
00831         o2->last_tri = t2;
00832       }
00833     }            
00834     else if (bvtq.GetNumTests() == bvtq.GetSize() - 1) 
00835     {  
00836       
00837       
00838       DistanceQueueRecurse(res,min_test.R,min_test.T,
00839                            o1,min_test.b1,o2,min_test.b2);
00840     }
00841     else 
00842     {  
00843       
00844       
00845       PQP_REAL sz1 = o1->child(min_test.b1)->GetSize();
00846       PQP_REAL sz2 = o2->child(min_test.b2)->GetSize();
00847 
00848       res->num_bv_tests += 2;
00849  
00850       BVT bvt1,bvt2;
00851       PQP_REAL Ttemp[3];
00852 
00853       if (l2 || (!l1 && (sz1 > sz2)))   
00854       {  
00855         
00856         
00857       
00858         int c1 = o1->child(min_test.b1)->first_child;
00859         int c2 = c1 + 1;
00860 
00861         
00862 
00863         bvt1.b1 = c1;
00864         bvt1.b2 = min_test.b2;
00865         MTxM(bvt1.R,o1->child(c1)->R,min_test.R);
00866 #if PQP_BV_TYPE & RSS_TYPE
00867         VmV(Ttemp,min_test.T,o1->child(c1)->Tr);
00868 #else
00869         VmV(Ttemp,min_test.T,o1->child(c1)->To);
00870 #endif
00871         MTxV(bvt1.T,o1->child(c1)->R,Ttemp);
00872         bvt1.d = BV_Distance(bvt1.R,bvt1.T,
00873                             o1->child(bvt1.b1),o2->child(bvt1.b2));
00874 
00875         
00876 
00877         bvt2.b1 = c2;
00878         bvt2.b2 = min_test.b2;
00879         MTxM(bvt2.R,o1->child(c2)->R,min_test.R);
00880 #if PQP_BV_TYPE & RSS_TYPE
00881         VmV(Ttemp,min_test.T,o1->child(c2)->Tr);
00882 #else
00883         VmV(Ttemp,min_test.T,o1->child(c2)->To);
00884 #endif
00885         MTxV(bvt2.T,o1->child(c2)->R,Ttemp);
00886         bvt2.d = BV_Distance(bvt2.R,bvt2.T,
00887                             o1->child(bvt2.b1),o2->child(bvt2.b2));
00888       }
00889       else 
00890       {
00891         
00892         
00893       
00894         int c1 = o2->child(min_test.b2)->first_child;
00895         int c2 = c1 + 1;
00896 
00897         
00898 
00899         bvt1.b1 = min_test.b1;
00900         bvt1.b2 = c1;
00901         MxM(bvt1.R,min_test.R,o2->child(c1)->R);
00902 #if PQP_BV_TYPE & RSS_TYPE
00903         MxVpV(bvt1.T,min_test.R,o2->child(c1)->Tr,min_test.T);
00904 #else
00905         MxVpV(bvt1.T,min_test.R,o2->child(c1)->To,min_test.T);
00906 #endif
00907         bvt1.d = BV_Distance(bvt1.R,bvt1.T,
00908                             o1->child(bvt1.b1),o2->child(bvt1.b2));
00909 
00910         
00911 
00912         bvt2.b1 = min_test.b1;
00913         bvt2.b2 = c2;
00914         MxM(bvt2.R,min_test.R,o2->child(c2)->R);
00915 #if PQP_BV_TYPE & RSS_TYPE
00916         MxVpV(bvt2.T,min_test.R,o2->child(c2)->Tr,min_test.T);
00917 #else
00918         MxVpV(bvt2.T,min_test.R,o2->child(c2)->To,min_test.T);
00919 #endif
00920         bvt2.d = BV_Distance(bvt2.R,bvt2.T,
00921                             o1->child(bvt2.b1),o2->child(bvt2.b2));
00922       }
00923 
00924       bvtq.AddTest(bvt1);       
00925       bvtq.AddTest(bvt2);
00926     }
00927 
00928     if (bvtq.Empty())
00929     {
00930       break;
00931     }
00932     else
00933     {
00934       min_test = bvtq.ExtractMinTest();
00935 
00936       if ((min_test.d + res->abs_err >= res->distance) && 
00937          ((min_test.d * (1 + res->rel_err)) >= res->distance)) 
00938       {
00939         break;
00940       }
00941     }
00942   }  
00943 }       
00944 
00945 int 
00946 PQP_Distance(PQP_DistanceResult *res,
00947              PQP_REAL R1[3][3], PQP_REAL T1[3], PQP_Model *o1,
00948              PQP_REAL R2[3][3], PQP_REAL T2[3], PQP_Model *o2,
00949              PQP_REAL rel_err, PQP_REAL abs_err,
00950              int qsize)
00951 {
00952   
00953   double time1 = GetTime();
00954   
00955   
00956 
00957   if (o1->build_state != PQP_BUILD_STATE_PROCESSED) 
00958     return PQP_ERR_UNPROCESSED_MODEL;
00959   if (o2->build_state != PQP_BUILD_STATE_PROCESSED) 
00960     return PQP_ERR_UNPROCESSED_MODEL;
00961 
00962   
00963   
00964   
00965 
00966   MTxM(res->R,R1,R2);
00967   PQP_REAL Ttemp[3];
00968   VmV(Ttemp, T2, T1);  
00969   MTxV(res->T, R1, Ttemp);
00970   
00971   
00972   
00973 
00974   PQP_REAL p[3],q[3];
00975   res->distance = TriDistance(res->R,res->T,o1->last_tri,o2->last_tri,p,q);
00976   VcV(res->p1,p);
00977   VcV(res->p2,q);
00978 
00979   
00980 
00981   res->abs_err = abs_err;
00982   res->rel_err = rel_err;
00983   
00984   
00985 
00986   res->num_bv_tests = 0;
00987   res->num_tri_tests = 0;
00988   
00989   
00990 
00991   PQP_REAL Rtemp[3][3], R[3][3], T[3];
00992 
00993   MxM(Rtemp,res->R,o2->child(0)->R);
00994   MTxM(R,o1->child(0)->R,Rtemp);
00995   
00996 #if PQP_BV_TYPE & RSS_TYPE
00997   MxVpV(Ttemp,res->R,o2->child(0)->Tr,res->T);
00998   VmV(Ttemp,Ttemp,o1->child(0)->Tr);
00999 #else
01000   MxVpV(Ttemp,res->R,o2->child(0)->To,res->T);
01001   VmV(Ttemp,Ttemp,o1->child(0)->To);
01002 #endif
01003   MTxV(T,o1->child(0)->R,Ttemp);
01004 
01005   
01006   
01007   if (qsize <= 2)
01008   {
01009     DistanceRecurse(res,R,T,o1,0,o2,0);    
01010   }
01011   else 
01012   { 
01013     res->qsize = qsize;
01014 
01015     DistanceQueueRecurse(res,R,T,o1,0,o2,0);
01016   }
01017 
01018   
01019 
01020   PQP_REAL u[3];
01021   VmV(u, res->p2, res->T);
01022   MTxV(res->p2, res->R, u);
01023 
01024   double time2 = GetTime();
01025   res->query_time_secs = time2 - time1;  
01026 
01027   return PQP_OK;
01028 }
01029 
01030 
01031 
01032 
01033 void 
01034 ToleranceRecurse(PQP_ToleranceResult *res, 
01035                  PQP_REAL R[3][3], PQP_REAL T[3],
01036                  PQP_Model *o1, int b1, PQP_Model *o2, int b2)
01037 {
01038   PQP_REAL sz1 = o1->child(b1)->GetSize();
01039   PQP_REAL sz2 = o2->child(b2)->GetSize();
01040   int l1 = o1->child(b1)->Leaf();
01041   int l2 = o2->child(b2)->Leaf();
01042 
01043   if (l1 && l2) 
01044   {
01045     
01046     
01047     res->num_tri_tests++;
01048 
01049     PQP_REAL p[3], q[3];
01050 
01051     Tri *t1 = &o1->tris[-o1->child(b1)->first_child - 1];
01052     Tri *t2 = &o2->tris[-o2->child(b2)->first_child - 1];
01053 
01054     PQP_REAL d = TriDistance(res->R,res->T,t1,t2,p,q);
01055     
01056     if (d <= res->tolerance)  
01057     {  
01058       
01059 
01060       res->closer_than_tolerance = 1;
01061       res->distance = d;
01062       VcV(res->p1, p);         
01063       VcV(res->p2, q);         
01064                                
01065     }
01066 
01067     return;
01068   }
01069 
01070   int a1,a2,c1,c2;  
01071   PQP_REAL R1[3][3], T1[3], R2[3][3], T2[3], Ttemp[3];
01072 
01073   if (l2 || (!l1 && (sz1 > sz2)))
01074   {
01075     
01076 
01077     a1 = o1->child(b1)->first_child;
01078     a2 = b2;
01079     c1 = o1->child(b1)->first_child+1;
01080     c2 = b2;
01081     
01082     MTxM(R1,o1->child(a1)->R,R);
01083 #if PQP_BV_TYPE & RSS_TYPE
01084     VmV(Ttemp,T,o1->child(a1)->Tr);
01085 #else
01086     VmV(Ttemp,T,o1->child(a1)->To);
01087 #endif
01088     MTxV(T1,o1->child(a1)->R,Ttemp);
01089 
01090     MTxM(R2,o1->child(c1)->R,R);
01091 #if PQP_BV_TYPE & RSS_TYPE
01092     VmV(Ttemp,T,o1->child(c1)->Tr);
01093 #else
01094     VmV(Ttemp,T,o1->child(c1)->To);
01095 #endif
01096     MTxV(T2,o1->child(c1)->R,Ttemp);
01097   }
01098   else 
01099   {
01100     
01101 
01102     a1 = b1;
01103     a2 = o2->child(b2)->first_child;
01104     c1 = b1;
01105     c2 = o2->child(b2)->first_child+1;
01106 
01107     MxM(R1,R,o2->child(a2)->R);
01108 #if PQP_BV_TYPE & RSS_TYPE
01109     MxVpV(T1,R,o2->child(a2)->Tr,T);
01110 #else
01111     MxVpV(T1,R,o2->child(a2)->To,T);
01112 #endif
01113     MxM(R2,R,o2->child(c2)->R);
01114 #if PQP_BV_TYPE & RSS_TYPE
01115     MxVpV(T2,R,o2->child(c2)->Tr,T);
01116 #else
01117     MxVpV(T2,R,o2->child(c2)->To,T);
01118 #endif
01119   }
01120 
01121   res->num_bv_tests += 2;
01122 
01123   PQP_REAL d1 = BV_Distance(R1, T1, o1->child(a1), o2->child(a2));
01124   PQP_REAL d2 = BV_Distance(R2, T2, o1->child(c1), o2->child(c2));
01125 
01126   if (d2 < d1) 
01127   {
01128     if (d2 <= res->tolerance) ToleranceRecurse(res, R2, T2, o1, c1, o2, c2);
01129     if (res->closer_than_tolerance) return;
01130     if (d1 <= res->tolerance) ToleranceRecurse(res, R1, T1, o1, a1, o2, a2);
01131   }
01132   else 
01133   {
01134     if (d1 <= res->tolerance) ToleranceRecurse(res, R1, T1, o1, a1, o2, a2);
01135     if (res->closer_than_tolerance) return;
01136     if (d2 <= res->tolerance) ToleranceRecurse(res, R2, T2, o1, c1, o2, c2);
01137   }
01138 }
01139 
01140 void
01141 ToleranceQueueRecurse(PQP_ToleranceResult *res,
01142                       PQP_REAL R[3][3], PQP_REAL T[3],
01143                       PQP_Model *o1, int b1,
01144                       PQP_Model *o2, int b2)
01145 {
01146   BVTQ bvtq(res->qsize);
01147   BVT min_test;
01148   min_test.b1 = b1;
01149   min_test.b2 = b2;
01150   McM(min_test.R,R);
01151   VcV(min_test.T,T);
01152 
01153   while(1)
01154   {  
01155     int l1 = o1->child(min_test.b1)->Leaf();
01156     int l2 = o2->child(min_test.b2)->Leaf();
01157     
01158     if (l1 && l2) 
01159     {  
01160       
01161     
01162       res->num_tri_tests++;
01163 
01164       PQP_REAL p[3], q[3];
01165 
01166       Tri *t1 = &o1->tris[-o1->child(min_test.b1)->first_child - 1];
01167       Tri *t2 = &o2->tris[-o2->child(min_test.b2)->first_child - 1];
01168 
01169       PQP_REAL d = TriDistance(res->R,res->T,t1,t2,p,q);
01170     
01171       if (d <= res->tolerance)  
01172       {  
01173         
01174 
01175         res->closer_than_tolerance = 1;
01176         res->distance = d;
01177         VcV(res->p1, p);         
01178         VcV(res->p2, q);         
01179                                  
01180         return;
01181       }
01182     }
01183     else if (bvtq.GetNumTests() == bvtq.GetSize() - 1)
01184     {  
01185       
01186       
01187       ToleranceQueueRecurse(res,min_test.R,min_test.T,
01188                             o1,min_test.b1,o2,min_test.b2);
01189       if (res->closer_than_tolerance == 1) return;
01190     }
01191     else 
01192     {  
01193       
01194       
01195       PQP_REAL sz1 = o1->child(min_test.b1)->GetSize();
01196       PQP_REAL sz2 = o2->child(min_test.b2)->GetSize();
01197 
01198       res->num_bv_tests += 2;
01199       
01200       BVT bvt1,bvt2;
01201       PQP_REAL Ttemp[3];
01202 
01203       if (l2 || (!l1 && (sz1 > sz2)))   
01204       {
01205               
01206         
01207 
01208         int c1 = o1->child(min_test.b1)->first_child;
01209         int c2 = c1 + 1;
01210 
01211         
01212 
01213         bvt1.b1 = c1;
01214         bvt1.b2 = min_test.b2;
01215         MTxM(bvt1.R,o1->child(c1)->R,min_test.R);
01216 #if PQP_BV_TYPE & RSS_TYPE
01217         VmV(Ttemp,min_test.T,o1->child(c1)->Tr);
01218 #else
01219         VmV(Ttemp,min_test.T,o1->child(c1)->To);
01220 #endif
01221         MTxV(bvt1.T,o1->child(c1)->R,Ttemp);
01222         bvt1.d = BV_Distance(bvt1.R,bvt1.T,
01223                             o1->child(bvt1.b1),o2->child(bvt1.b2));
01224 
01225               
01226 
01227               bvt2.b1 = c2;
01228               bvt2.b2 = min_test.b2;
01229               MTxM(bvt2.R,o1->child(c2)->R,min_test.R);
01230 #if PQP_BV_TYPE & RSS_TYPE
01231               VmV(Ttemp,min_test.T,o1->child(c2)->Tr);
01232 #else
01233               VmV(Ttemp,min_test.T,o1->child(c2)->To);
01234 #endif
01235               MTxV(bvt2.T,o1->child(c2)->R,Ttemp);
01236         bvt2.d = BV_Distance(bvt2.R,bvt2.T,
01237                             o1->child(bvt2.b1),o2->child(bvt2.b2));
01238       }
01239       else 
01240       {
01241         
01242         
01243 
01244         int c1 = o2->child(min_test.b2)->first_child;
01245         int c2 = c1 + 1;
01246 
01247         
01248 
01249         bvt1.b1 = min_test.b1;
01250         bvt1.b2 = c1;
01251         MxM(bvt1.R,min_test.R,o2->child(c1)->R);
01252 #if PQP_BV_TYPE & RSS_TYPE
01253         MxVpV(bvt1.T,min_test.R,o2->child(c1)->Tr,min_test.T);
01254 #else
01255         MxVpV(bvt1.T,min_test.R,o2->child(c1)->To,min_test.T);
01256 #endif
01257         bvt1.d = BV_Distance(bvt1.R,bvt1.T,
01258                             o1->child(bvt1.b1),o2->child(bvt1.b2));
01259 
01260         
01261 
01262         bvt2.b1 = min_test.b1;
01263         bvt2.b2 = c2;
01264         MxM(bvt2.R,min_test.R,o2->child(c2)->R);
01265 #if PQP_BV_TYPE & RSS_TYPE
01266         MxVpV(bvt2.T,min_test.R,o2->child(c2)->Tr,min_test.T);
01267 #else
01268         MxVpV(bvt2.T,min_test.R,o2->child(c2)->To,min_test.T);
01269 #endif
01270         bvt2.d = BV_Distance(bvt2.R,bvt2.T,
01271                             o1->child(bvt2.b1),o2->child(bvt2.b2));
01272       }
01273 
01274       
01275 
01276       if (bvt1.d <= res->tolerance) bvtq.AddTest(bvt1);
01277       if (bvt2.d <= res->tolerance) bvtq.AddTest(bvt2);
01278     }
01279 
01280     if (bvtq.Empty() || (bvtq.MinTest() > res->tolerance)) 
01281     {
01282       res->closer_than_tolerance = 0;
01283       return;
01284     }
01285     else 
01286     {
01287       min_test = bvtq.ExtractMinTest();
01288     }
01289   }  
01290 }       
01291 
01292 int
01293 PQP_Tolerance(PQP_ToleranceResult *res,
01294               PQP_REAL R1[3][3], PQP_REAL T1[3], PQP_Model *o1,
01295               PQP_REAL R2[3][3], PQP_REAL T2[3], PQP_Model *o2,
01296               PQP_REAL tolerance,
01297               int qsize)
01298 {
01299   double time1 = GetTime();
01300 
01301   
01302 
01303   if (o1->build_state != PQP_BUILD_STATE_PROCESSED) 
01304     return PQP_ERR_UNPROCESSED_MODEL;
01305   if (o2->build_state != PQP_BUILD_STATE_PROCESSED) 
01306     return PQP_ERR_UNPROCESSED_MODEL;
01307   
01308   
01309   
01310 
01311   MTxM(res->R,R1,R2);
01312   PQP_REAL Ttemp[3];
01313   VmV(Ttemp, T2, T1);
01314   MTxV(res->T, R1, Ttemp);
01315 
01316   
01317 
01318   if (tolerance < 0.0) tolerance = 0.0;
01319   res->tolerance = tolerance;
01320   
01321   
01322 
01323   res->num_bv_tests = 0;
01324   res->num_tri_tests = 0;
01325 
01326   
01327 
01328   res->closer_than_tolerance = 0;
01329   
01330   
01331 
01332   PQP_REAL Rtemp[3][3], R[3][3], T[3];
01333 
01334   MxM(Rtemp,res->R,o2->child(0)->R);
01335   MTxM(R,o1->child(0)->R,Rtemp);
01336 #if PQP_BV_TYPE & RSS_TYPE
01337   MxVpV(Ttemp,res->R,o2->child(0)->Tr,res->T);
01338   VmV(Ttemp,Ttemp,o1->child(0)->Tr);
01339 #else
01340   MxVpV(Ttemp,res->R,o2->child(0)->To,res->T);
01341   VmV(Ttemp,Ttemp,o1->child(0)->To);
01342 #endif
01343   MTxV(T,o1->child(0)->R,Ttemp);
01344 
01345   
01346 
01347   PQP_REAL d = BV_Distance(R, T, o1->child(0), o2->child(0));
01348   
01349   if (d <= res->tolerance)
01350   {
01351     
01352 
01353     if (qsize <= 2) 
01354     {
01355       ToleranceRecurse(res, R, T, o1, 0, o2, 0);
01356     }
01357     else 
01358     {
01359       res->qsize = qsize;
01360       ToleranceQueueRecurse(res, R, T, o1, 0, o2, 0);
01361     }
01362   }
01363 
01364   
01365 
01366   PQP_REAL u[3];
01367   VmV(u, res->p2, res->T);
01368   MTxV(res->p2, res->R, u);
01369 
01370   double time2 = GetTime();
01371   res->query_time_secs = time2 - time1;
01372 
01373   return PQP_OK;
01374 }
01375 
01376 #endif