All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends

broadphase_dynamic_AABB_tree_array.cpp

00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2011, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  */
00034 
00037 #include "fcl/broadphase/broadphase_dynamic_AABB_tree_array.h"
00038 
00039 namespace fcl
00040 {
00041 
00042 void DynamicAABBTreeCollisionManager_Array::registerObjects(const std::vector<CollisionObject*>& other_objs)
00043 {
00044   if(size() > 0)
00045   {
00046     BroadPhaseCollisionManager::registerObjects(other_objs);
00047   }
00048   else
00049   {
00050     DynamicAABBNode* leaves = new DynamicAABBNode[other_objs.size()];
00051     table.rehash(other_objs.size());
00052     for(size_t i = 0, size = other_objs.size(); i < size; ++i)
00053     {
00054       leaves[i].bv = other_objs[i]->getAABB();
00055       leaves[i].parent = dtree.NULL_NODE;
00056       leaves[i].children[1] = dtree.NULL_NODE;
00057       leaves[i].data = other_objs[i];
00058       table[other_objs[i]] = i;
00059     }
00060    
00061     int n_leaves = other_objs.size();
00062 
00063     dtree.init(leaves, n_leaves, tree_init_level);
00064    
00065     setup_ = true;
00066   }
00067 }
00068 
00069 void DynamicAABBTreeCollisionManager_Array::registerObject(CollisionObject* obj)
00070 {
00071   size_t node = dtree.insert(obj->getAABB(), obj);
00072   table[obj] = node;
00073 }
00074 
00075 void DynamicAABBTreeCollisionManager_Array::unregisterObject(CollisionObject* obj)
00076 {
00077   size_t node = table[obj];
00078   table.erase(obj);
00079   dtree.remove(node);
00080 }
00081 
00082 void DynamicAABBTreeCollisionManager_Array::setup()
00083 {
00084   if(!setup_)
00085   {
00086     int num = dtree.size();
00087     if(num == 0) 
00088     {
00089       setup_ = true;
00090       return;
00091     }
00092 
00093     int height = dtree.getMaxHeight();
00094 
00095     
00096     if(height - std::log((FCL_REAL)num) / std::log(2.0) < max_tree_nonbalanced_level)
00097       dtree.balanceIncremental(tree_incremental_balance_pass);
00098     else
00099       dtree.balanceTopdown();
00100 
00101     setup_ = true;
00102   }
00103 }
00104 
00105 
00106 void DynamicAABBTreeCollisionManager_Array::update()
00107 { 
00108   for(DynamicAABBTable::const_iterator it = table.begin(), end = table.end(); it != end; ++it)
00109   {
00110     CollisionObject* obj = it->first;
00111     size_t node = it->second;
00112     dtree.getNodes()[node].bv = obj->getAABB();
00113   }
00114 
00115   dtree.refit();
00116   setup_ = false;
00117 
00118   setup();
00119 }
00120 
00121 void DynamicAABBTreeCollisionManager_Array::update_(CollisionObject* updated_obj)
00122 {
00123   DynamicAABBTable::const_iterator it = table.find(updated_obj);
00124   if(it != table.end())
00125   {
00126     size_t node = it->second;
00127     if(!dtree.getNodes()[node].bv.equal(updated_obj->getAABB()))
00128       dtree.update(node, updated_obj->getAABB());
00129   }
00130   setup_ = false;
00131 }
00132 
00133 void DynamicAABBTreeCollisionManager_Array::update(CollisionObject* updated_obj)
00134 {
00135   update_(updated_obj);
00136   setup();
00137 }
00138 
00139 void DynamicAABBTreeCollisionManager_Array::update(const std::vector<CollisionObject*>& updated_objs)
00140 {
00141   for(size_t i = 0, size = updated_objs.size(); i < size; ++i)
00142     update_(updated_objs[i]);
00143   setup();
00144 }
00145 
00146 bool DynamicAABBTreeCollisionManager_Array::collisionRecurse(DynamicAABBNode* nodes1, size_t root1_id, 
00147                                                         DynamicAABBNode* nodes2, size_t root2_id, 
00148                                                         void* cdata, CollisionCallBack callback) const
00149 {
00150   DynamicAABBNode* root1 = nodes1 + root1_id;
00151   DynamicAABBNode* root2 = nodes2 + root2_id;
00152   if(root1->isLeaf() && root2->isLeaf())
00153   {
00154     if(!root1->bv.overlap(root2->bv)) return false;
00155     return callback(static_cast<CollisionObject*>(root1->data), static_cast<CollisionObject*>(root2->data), cdata);
00156   }
00157     
00158   if(!root1->bv.overlap(root2->bv)) return false;
00159     
00160   if(root2->isLeaf() || (!root1->isLeaf() && (root1->bv.size() > root2->bv.size())))
00161   {
00162     if(collisionRecurse(nodes1, root1->children[0], nodes2, root2_id, cdata, callback))
00163       return true;
00164     if(collisionRecurse(nodes1, root1->children[1], nodes2, root2_id, cdata, callback))
00165       return true;
00166   }
00167   else
00168   {
00169     if(collisionRecurse(nodes1, root1_id, nodes2, root2->children[0], cdata, callback))
00170       return true;
00171     if(collisionRecurse(nodes1, root1_id, nodes2, root2->children[1], cdata, callback))
00172       return true;
00173   }
00174   return false;
00175 }
00176 
00177 bool DynamicAABBTreeCollisionManager_Array::collisionRecurse(DynamicAABBNode* nodes, size_t root_id, CollisionObject* query, void* cdata, CollisionCallBack callback) const
00178 {
00179   DynamicAABBNode* root = nodes + root_id;
00180   if(root->isLeaf())
00181   {
00182     if(!root->bv.overlap(query->getAABB())) return false;
00183     return callback(static_cast<CollisionObject*>(root->data), query, cdata);
00184   }
00185     
00186   if(!root->bv.overlap(query->getAABB())) return false;
00187 
00188   int select_res = implementation_array::select(query->getAABB(), root->children[0], root->children[1], nodes);
00189     
00190   if(collisionRecurse(nodes, root->children[select_res], query, cdata, callback))
00191     return true;
00192     
00193   if(collisionRecurse(nodes, root->children[1-select_res], query, cdata, callback))
00194     return true;
00195 
00196   return false;
00197 }
00198 
00199 bool DynamicAABBTreeCollisionManager_Array::selfCollisionRecurse(DynamicAABBNode* nodes, size_t root_id, void* cdata, CollisionCallBack callback) const
00200 {
00201   DynamicAABBNode* root = nodes + root_id;
00202   if(root->isLeaf()) return false;
00203 
00204   if(selfCollisionRecurse(nodes, root->children[0], cdata, callback))
00205     return true;
00206 
00207   if(selfCollisionRecurse(nodes, root->children[1], cdata, callback))
00208     return true;
00209 
00210   if(collisionRecurse(nodes, root->children[0], nodes, root->children[1], cdata, callback))
00211     return true;
00212 
00213   return false;
00214 }
00215 
00216 bool DynamicAABBTreeCollisionManager_Array::distanceRecurse(DynamicAABBNode* nodes1, size_t root1_id, 
00217                                                        DynamicAABBNode* nodes2, size_t root2_id, 
00218                                                        void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const
00219 {
00220   DynamicAABBNode* root1 = nodes1 + root1_id;
00221   DynamicAABBNode* root2 = nodes2 + root2_id;
00222   if(root1->isLeaf() && root2->isLeaf())
00223   {
00224     CollisionObject* root1_obj = static_cast<CollisionObject*>(root1->data);
00225     CollisionObject* root2_obj = static_cast<CollisionObject*>(root2->data);
00226     return callback(root1_obj, root2_obj, cdata, min_dist);
00227   }
00228 
00229   if(root2->isLeaf() || (!root1->isLeaf() && (root1->bv.size() > root2->bv.size())))
00230   {
00231     FCL_REAL d1 = root2->bv.distance((nodes1 + root1->children[0])->bv);
00232     FCL_REAL d2 = root2->bv.distance((nodes1 + root1->children[1])->bv);
00233       
00234     if(d2 < d1)
00235     {
00236       if(d2 < min_dist)
00237       {
00238         if(distanceRecurse(nodes1, root1->children[1], nodes2, root2_id, cdata, callback, min_dist))
00239           return true;
00240       }
00241         
00242       if(d1 < min_dist)
00243       {
00244         if(distanceRecurse(nodes1, root1->children[0], nodes2, root2_id, cdata, callback, min_dist))
00245           return true;
00246       }
00247     }
00248     else
00249     {
00250       if(d1 < min_dist)
00251       {
00252         if(distanceRecurse(nodes1, root1->children[0], nodes2, root2_id, cdata, callback, min_dist))
00253           return true;
00254       }
00255 
00256       if(d2 < min_dist)
00257       {
00258         if(distanceRecurse(nodes1, root1->children[1], nodes2, root2_id, cdata, callback, min_dist))
00259           return true;
00260       }
00261     }
00262   }
00263   else
00264   {
00265     FCL_REAL d1 = root1->bv.distance((nodes2 + root2->children[0])->bv);
00266     FCL_REAL d2 = root1->bv.distance((nodes2 + root2->children[1])->bv);
00267       
00268     if(d2 < d1)
00269     {
00270       if(d2 < min_dist)
00271       {
00272         if(distanceRecurse(nodes1, root1_id, nodes2, root2->children[1], cdata, callback, min_dist))
00273           return true;
00274       }
00275         
00276       if(d1 < min_dist)
00277       {
00278         if(distanceRecurse(nodes1, root1_id, nodes2, root2->children[0], cdata, callback, min_dist))
00279           return true;
00280       }
00281     }
00282     else
00283     {
00284       if(d1 < min_dist)
00285       {
00286         if(distanceRecurse(nodes1, root1_id, nodes2, root2->children[0], cdata, callback, min_dist))
00287           return true;
00288       }
00289 
00290       if(d2 < min_dist)
00291       {
00292         if(distanceRecurse(nodes1, root1_id, nodes2, root2->children[1], cdata, callback, min_dist))
00293           return true;
00294       }
00295     }
00296   }
00297 
00298   return false;
00299 }
00300 
00301 bool DynamicAABBTreeCollisionManager_Array::distanceRecurse(DynamicAABBNode* nodes, size_t root_id, CollisionObject* query, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const
00302 { 
00303   DynamicAABBNode* root = nodes + root_id;
00304   if(root->isLeaf())
00305   {
00306     CollisionObject* root_obj = static_cast<CollisionObject*>(root->data);
00307     return callback(root_obj, query, cdata, min_dist); 
00308   }
00309 
00310   FCL_REAL d1 = query->getAABB().distance((nodes + root->children[0])->bv);
00311   FCL_REAL d2 = query->getAABB().distance((nodes + root->children[1])->bv);
00312     
00313   if(d2 < d1)
00314   {
00315     if(d2 < min_dist)
00316     {
00317       if(distanceRecurse(nodes, root->children[1], query, cdata, callback, min_dist))
00318         return true;
00319     }
00320 
00321     if(d1 < min_dist)
00322     {
00323       if(distanceRecurse(nodes, root->children[0], query, cdata, callback, min_dist))
00324         return true;
00325     }
00326   }
00327   else
00328   {
00329     if(d1 < min_dist)
00330     {
00331       if(distanceRecurse(nodes, root->children[0], query, cdata, callback, min_dist))
00332         return true;
00333     }
00334 
00335     if(d2 < min_dist)
00336     {
00337       if(distanceRecurse(nodes, root->children[1], query, cdata, callback, min_dist))
00338         return true;
00339     }
00340   }
00341 
00342   return false;
00343 }
00344 
00345 bool DynamicAABBTreeCollisionManager_Array::selfDistanceRecurse(DynamicAABBNode* nodes, size_t root_id, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const
00346 {
00347   DynamicAABBNode* root = nodes + root_id;
00348   if(root->isLeaf()) return false;
00349 
00350   if(selfDistanceRecurse(nodes, root->children[0], cdata, callback, min_dist))
00351     return true;
00352 
00353   if(selfDistanceRecurse(nodes, root->children[1], cdata, callback, min_dist))
00354     return true;
00355 
00356   if(distanceRecurse(nodes, root->children[0], nodes, root->children[1], cdata, callback, min_dist))
00357     return true;
00358 
00359   return false;
00360 }
00361 
00362 bool collisionRecurse_(DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Transform3f& tf2, void* cdata, CollisionCallBack callback)
00363 {
00364   DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* root1 = nodes1 + root1_id;
00365   if(root1->isLeaf() && !root2->hasChildren())
00366   {
00367     CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
00368     if(!tree2->isNodeFree(root2) && !obj1->isFree())
00369     {
00370       OBB obb1, obb2;
00371       convertBV(root1->bv, Transform3f(), obb1);
00372       convertBV(root2_bv, tf2, obb2);
00373       
00374       if(obb1.overlap(obb2))
00375       {
00376         Box* box = new Box();
00377         Transform3f box_tf;
00378         constructBox(root2_bv, tf2, *box, box_tf);
00379         
00380         box->cost_density = root2->getOccupancy();
00381         box->threshold_occupied = tree2->getOccupancyThres();
00382 
00383         CollisionObject obj2(boost::shared_ptr<CollisionGeometry>(box), box_tf);
00384         return callback(obj1, &obj2, cdata);
00385       }
00386       else return false;
00387     }
00388     else return false;
00389   }
00390 
00391   OBB obb1, obb2;
00392   convertBV(root1->bv, Transform3f(), obb1);
00393   convertBV(root2_bv, tf2, obb2);
00394   
00395   if(tree2->isNodeFree(root2) || !obb1.overlap(obb2)) return false;
00396 
00397   if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size())))
00398   {
00399     if(collisionRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback))
00400       return true;
00401     if(collisionRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback))
00402       return true;
00403   }
00404   else
00405   {
00406     for(unsigned int i = 0; i < 8; ++i)
00407     {
00408       if(root2->childExists(i))
00409       {
00410         const OcTree::OcTreeNode* child = root2->getChild(i);
00411         AABB child_bv;
00412         computeChildBV(root2_bv, i, child_bv);
00413 
00414         if(collisionRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback))
00415           return true;
00416       }
00417     }
00418   }
00419 
00420   return false;
00421 }
00422 
00423 bool collisionRecurse_(DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Vec3f& tf2, void* cdata, CollisionCallBack callback)
00424 {
00425   DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* root1 = nodes1 + root1_id;
00426   if(root1->isLeaf() && !root2->hasChildren())
00427   {
00428     CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
00429     if(!tree2->isNodeFree(root2))
00430     {
00431       const AABB& root_bv_t = translate(root2_bv, tf2);
00432       if(root1->bv.overlap(root_bv_t))
00433       {
00434         Box* box = new Box();
00435         Transform3f box_tf;
00436         constructBox(root2_bv, tf2, *box, box_tf);
00437 
00438         box->cost_density = root2->getOccupancy();
00439         box->threshold_occupied = tree2->getOccupancyThres();
00440 
00441         CollisionObject obj2(boost::shared_ptr<CollisionGeometry>(box), box_tf);
00442         return callback(obj1, &obj2, cdata);
00443       }
00444       else return false;
00445     }
00446     else return false;
00447   }
00448 
00449   const AABB& root_bv_t = translate(root2_bv, tf2);
00450   if(tree2->isNodeFree(root2) || !root1->bv.overlap(root_bv_t)) return false;
00451 
00452   if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size())))
00453   {
00454     if(collisionRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback))
00455       return true;
00456     if(collisionRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback))
00457       return true;
00458   }
00459   else
00460   {
00461     for(unsigned int i = 0; i < 8; ++i)
00462     {
00463       if(root2->childExists(i))
00464       {
00465         const OcTree::OcTreeNode* child = root2->getChild(i);
00466         AABB child_bv;
00467         computeChildBV(root2_bv, i, child_bv);
00468 
00469         if(collisionRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback))
00470           return true;
00471       }
00472     }
00473   }
00474 
00475   return false;
00476 }
00477 
00478 
00479 
00480 bool DynamicAABBTreeCollisionManager_Array::collisionRecurse(DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Transform3f& tf2, void* cdata, CollisionCallBack callback) const
00481 {
00482   if(tf2.getQuatRotation().isIdentity())
00483     return collisionRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2.getTranslation(), cdata, callback);
00484   else
00485     return collisionRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2, cdata, callback);
00486 }
00487 
00488 
00489 bool distanceRecurse_(DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Transform3f& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist)
00490 {
00491   DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* root1 = nodes1 + root1_id;
00492   if(root1->isLeaf() && !root2->hasChildren())
00493   {
00494     if(tree2->isNodeOccupied(root2))
00495     {
00496       Box* box = new Box();
00497       Transform3f box_tf;
00498       constructBox(root2_bv, tf2, *box, box_tf);
00499       CollisionObject obj(boost::shared_ptr<CollisionGeometry>(box), box_tf);
00500       return callback(static_cast<CollisionObject*>(root1->data), &obj, cdata, min_dist);
00501     }
00502     else return false;
00503   }
00504 
00505   if(!tree2->isNodeOccupied(root2)) return false;
00506 
00507   if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size())))
00508   {
00509     AABB aabb2;
00510     convertBV(root2_bv, tf2, aabb2);
00511 
00512     FCL_REAL d1 = aabb2.distance((nodes1 + root1->children[0])->bv);
00513     FCL_REAL d2 = aabb2.distance((nodes1 + root1->children[1])->bv);
00514       
00515     if(d2 < d1)
00516     {
00517       if(d2 < min_dist)
00518       {
00519         if(distanceRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
00520           return true;
00521       }
00522         
00523       if(d1 < min_dist)
00524       {
00525         if(distanceRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
00526           return true;
00527       }
00528     }
00529     else
00530     {
00531       if(d1 < min_dist)
00532       {
00533         if(distanceRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
00534           return true;
00535       }
00536 
00537       if(d2 < min_dist)
00538       {
00539         if(distanceRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
00540           return true;
00541       }
00542     }
00543   }
00544   else
00545   {
00546     for(unsigned int i = 0; i < 8; ++i)
00547     {
00548       if(root2->childExists(i))
00549       {
00550         const OcTree::OcTreeNode* child = root2->getChild(i);
00551         AABB child_bv;
00552         computeChildBV(root2_bv, i, child_bv);
00553 
00554         AABB aabb2;
00555         convertBV(child_bv, tf2, aabb2);
00556         FCL_REAL d = root1->bv.distance(aabb2);
00557         
00558         if(d < min_dist)
00559         {
00560           if(distanceRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback, min_dist))
00561             return true;
00562         }
00563       }
00564     }
00565   }
00566   
00567   return false;
00568 }
00569 
00570 
00571 bool distanceRecurse_(DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Vec3f& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist)
00572 {
00573   DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* root1 = nodes1 + root1_id;
00574   if(root1->isLeaf() && !root2->hasChildren())
00575   {
00576     if(tree2->isNodeOccupied(root2))
00577     {
00578       Box* box = new Box();
00579       Transform3f box_tf;
00580       constructBox(root2_bv, tf2, *box, box_tf);
00581       CollisionObject obj(boost::shared_ptr<CollisionGeometry>(box), box_tf);
00582       return callback(static_cast<CollisionObject*>(root1->data), &obj, cdata, min_dist);
00583     }
00584     else return false;
00585   }
00586 
00587   if(!tree2->isNodeOccupied(root2)) return false;
00588 
00589   if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size())))
00590   {
00591     const AABB& aabb2 = translate(root2_bv, tf2);
00592 
00593     FCL_REAL d1 = aabb2.distance((nodes1 + root1->children[0])->bv);
00594     FCL_REAL d2 = aabb2.distance((nodes1 + root1->children[1])->bv);
00595       
00596     if(d2 < d1)
00597     {
00598       if(d2 < min_dist)
00599       {
00600         if(distanceRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
00601           return true;
00602       }
00603         
00604       if(d1 < min_dist)
00605       {
00606         if(distanceRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
00607           return true;
00608       }
00609     }
00610     else
00611     {
00612       if(d1 < min_dist)
00613       {
00614         if(distanceRecurse_(nodes1, root1->children[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
00615           return true;
00616       }
00617 
00618       if(d2 < min_dist)
00619       {
00620         if(distanceRecurse_(nodes1, root1->children[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist))
00621           return true;
00622       }
00623     }
00624   }
00625   else
00626   {
00627     for(unsigned int i = 0; i < 8; ++i)
00628     {
00629       if(root2->childExists(i))
00630       {
00631         const OcTree::OcTreeNode* child = root2->getChild(i);
00632         AABB child_bv;
00633         computeChildBV(root2_bv, i, child_bv);
00634 
00635         const AABB& aabb2 = translate(child_bv, tf2);
00636         FCL_REAL d = root1->bv.distance(aabb2);
00637         
00638         if(d < min_dist)
00639         {
00640           if(distanceRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback, min_dist))
00641             return true;
00642         }
00643       }
00644     }
00645   }
00646   
00647   return false;
00648 }
00649 
00650 bool DynamicAABBTreeCollisionManager_Array::distanceRecurse(DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Transform3f& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const
00651 {
00652   if(tf2.getQuatRotation().isIdentity())
00653     return distanceRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2.getTranslation(), cdata, callback, min_dist);
00654   else
00655     return distanceRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2, cdata, callback, min_dist);
00656 }
00657 
00658 
00659 }