traversal_node_octree.h
Go to the documentation of this file.
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 #ifndef FCL_TRAVERSAL_NODE_OCTREE_H
00038 #define FCL_TRAVERSAL_NODE_OCTREE_H
00039 
00040 #include "fcl/collision_data.h"
00041 #include "fcl/traversal/traversal_node_base.h"
00042 #include "fcl/narrowphase/narrowphase.h"
00043 #include "fcl/shape/geometric_shapes_utility.h"
00044 #include "fcl/octree.h"
00045 #include "fcl/BVH/BVH_model.h"
00046 
00047 namespace fcl
00048 {
00049 
00051 template<typename NarrowPhaseSolver>
00052 class OcTreeSolver
00053 {
00054 private:
00055   const NarrowPhaseSolver* solver;
00056 
00057   mutable const CollisionRequest* crequest;
00058   mutable const DistanceRequest* drequest;
00059 
00060   mutable CollisionResult* cresult;
00061   mutable DistanceResult* dresult;
00062 
00063 public:
00064   OcTreeSolver(const NarrowPhaseSolver* solver_) : solver(solver_),
00065                                                    crequest(NULL),
00066                                                    drequest(NULL),
00067                                                    cresult(NULL),
00068                                                    dresult(NULL)
00069   {
00070   }
00071 
00073   void OcTreeIntersect(const OcTree* tree1, const OcTree* tree2,
00074                        const Transform3f& tf1, const Transform3f& tf2,
00075                        const CollisionRequest& request_,
00076                        CollisionResult& result_) const
00077   {
00078     crequest = &request_;
00079     cresult = &result_;
00080     
00081     OcTreeIntersectRecurse(tree1, tree1->getRoot(), tree1->getRootBV(), 
00082                            tree2, tree2->getRoot(), tree2->getRootBV(), 
00083                            tf1, tf2);
00084   }
00085 
00087   void OcTreeDistance(const OcTree* tree1, const OcTree* tree2,
00088                       const Transform3f& tf1, const Transform3f& tf2,
00089                       const DistanceRequest& request_,
00090                       DistanceResult& result_) const
00091   {
00092     drequest = &request_;
00093     dresult = &result_;
00094 
00095     OcTreeDistanceRecurse(tree1, tree1->getRoot(), tree1->getRootBV(), 
00096                           tree2, tree2->getRoot(), tree2->getRootBV(),
00097                           tf1, tf2);
00098   }
00099 
00101   template<typename BV>
00102   void OcTreeMeshIntersect(const OcTree* tree1, const BVHModel<BV>* tree2,
00103                            const Transform3f& tf1, const Transform3f& tf2,
00104                            const CollisionRequest& request_,
00105                            CollisionResult& result_) const
00106   {
00107     crequest = &request_;
00108     cresult = &result_;
00109 
00110     OcTreeMeshIntersectRecurse(tree1, tree1->getRoot(), tree1->getRootBV(),
00111                                tree2, 0,
00112                                tf1, tf2);
00113   }
00114 
00116   template<typename BV>
00117   void OcTreeMeshDistance(const OcTree* tree1, const BVHModel<BV>* tree2,
00118                           const Transform3f& tf1, const Transform3f& tf2,
00119                           const DistanceRequest& request_,
00120                           DistanceResult& result_) const
00121   {
00122     drequest = &request_;
00123     dresult = &result_;
00124 
00125     OcTreeMeshDistanceRecurse(tree1, tree1->getRoot(), tree1->getRootBV(),
00126                               tree2, 0,
00127                               tf1, tf2);
00128   }
00129 
00131   template<typename BV>
00132   void MeshOcTreeIntersect(const BVHModel<BV>* tree1, const OcTree* tree2,
00133                            const Transform3f& tf1, const Transform3f& tf2,
00134                            const CollisionRequest& request_,
00135                            CollisionResult& result_) const
00136   
00137   {
00138     crequest = &request_;
00139     cresult = &result_;
00140 
00141     OcTreeMeshIntersectRecurse(tree2, tree2->getRoot(), tree2->getRootBV(),
00142                                tree1, 0,
00143                                tf2, tf1);
00144   }
00145 
00147   template<typename BV>
00148   void MeshOcTreeDistance(const BVHModel<BV>* tree1, const OcTree* tree2,
00149                           const Transform3f& tf1, const Transform3f& tf2,
00150                           const DistanceRequest& request_,
00151                           DistanceResult& result_) const
00152   {
00153     drequest = &request_;
00154     dresult = &result_;
00155 
00156     OcTreeMeshDistanceRecurse(tree1, 0,
00157                               tree2, tree2->getRoot(), tree2->getRootBV(),
00158                               tf1, tf2);
00159   }
00160 
00162   template<typename S>
00163   void OcTreeShapeIntersect(const OcTree* tree, const S& s,
00164                             const Transform3f& tf1, const Transform3f& tf2,
00165                             const CollisionRequest& request_,
00166                             CollisionResult& result_) const
00167   {
00168     crequest = &request_;
00169     cresult = &result_;
00170 
00171     AABB bv2;
00172     computeBV<AABB>(s, Transform3f(), bv2);
00173     OBB obb2;
00174     convertBV(bv2, tf2, obb2);
00175     OcTreeShapeIntersectRecurse(tree, tree->getRoot(), tree->getRootBV(),
00176                                 s, obb2,
00177                                 tf1, tf2);
00178     
00179   }
00180 
00182   template<typename S>
00183   void ShapeOcTreeIntersect(const S& s, const OcTree* tree,
00184                             const Transform3f& tf1, const Transform3f& tf2,
00185                             const CollisionRequest& request_,
00186                             CollisionResult& result_) const
00187   {
00188     crequest = &request_;
00189     cresult = &result_;
00190 
00191     AABB bv1;
00192     computeBV<AABB>(s, Transform3f(), bv1);
00193     OBB obb1;
00194     convertBV(bv1, tf1, obb1);
00195     OcTreeShapeIntersectRecurse(tree, tree->getRoot(), tree->getRootBV(),
00196                                 s, obb1,
00197                                 tf2, tf1);
00198   }
00199 
00201   template<typename S>
00202   void OcTreeShapeDistance(const OcTree* tree, const S& s,
00203                            const Transform3f& tf1, const Transform3f& tf2,
00204                            const DistanceRequest& request_,
00205                            DistanceResult& result_) const
00206   {
00207     drequest = &request_;
00208     dresult = &result_;
00209 
00210     AABB aabb2;
00211     computeBV<AABB>(s, tf2, aabb2);
00212     OcTreeShapeDistanceRecurse(tree, tree->getRoot(), tree->getRootBV(),
00213                                s, aabb2,
00214                                tf1, tf2);
00215   }
00216 
00218   template<typename S>
00219   void ShapeOcTreeDistance(const S& s, const OcTree* tree,
00220                            const Transform3f& tf1, const Transform3f& tf2,
00221                            const DistanceRequest& request_,
00222                            DistanceResult& result_) const
00223   {
00224     drequest = &request_;
00225     dresult = &result_;
00226 
00227     AABB aabb1;
00228     computeBV<AABB>(s, tf1, aabb1);
00229     OcTreeShapeDistanceRecurse(tree, tree->getRoot(), tree->getRootBV(),
00230                                s, aabb1,
00231                                tf2, tf1);
00232   }
00233   
00234 
00235 private:
00236   template<typename S>
00237   bool OcTreeShapeDistanceRecurse(const OcTree* tree1, const OcTree::OcTreeNode* root1, const AABB& bv1,
00238                                   const S& s, const AABB& aabb2,
00239                                   const Transform3f& tf1, const Transform3f& tf2) const
00240   {
00241     if(!root1->hasChildren())
00242     {
00243       if(tree1->isNodeOccupied(root1))
00244       {
00245         Box box;
00246         Transform3f box_tf;
00247         constructBox(bv1, tf1, box, box_tf);
00248  
00249         FCL_REAL dist;
00250         solver->shapeDistance(box, box_tf, s, tf2, &dist);
00251         
00252         dresult->update(dist, tree1, &s, root1 - tree1->getRoot(), DistanceResult::NONE);
00253         
00254         return drequest->isSatisfied(*dresult);
00255       }
00256       else
00257         return false;
00258     }
00259 
00260     if(!tree1->isNodeOccupied(root1)) return false;
00261     
00262     for(unsigned int i = 0; i < 8; ++i)
00263     {
00264       if(root1->childExists(i))
00265       {
00266         const OcTree::OcTreeNode* child = root1->getChild(i);
00267         AABB child_bv;
00268         computeChildBV(bv1, i, child_bv);
00269         
00270         AABB aabb1;
00271         convertBV(child_bv, tf1, aabb1);
00272         FCL_REAL d = aabb1.distance(aabb2);
00273         if(d < dresult->min_distance)
00274         {
00275           if(OcTreeShapeDistanceRecurse(tree1, child, child_bv, s, aabb2, tf1, tf2))
00276             return true;
00277         }        
00278       }
00279     }
00280 
00281     return false;
00282   }
00283 
00284   template<typename S>
00285   bool OcTreeShapeIntersectRecurse(const OcTree* tree1, const OcTree::OcTreeNode* root1, const AABB& bv1,
00286                                    const S& s, const OBB& obb2,
00287                                    const Transform3f& tf1, const Transform3f& tf2) const
00288   {
00289     if(!root1)
00290     {
00291       OBB obb1;
00292       convertBV(bv1, tf1, obb1);
00293       if(obb1.overlap(obb2))
00294       {
00295         Box box;
00296         Transform3f box_tf;
00297         constructBox(bv1, tf1, box, box_tf);
00298 
00299         if(solver->shapeIntersect(box, box_tf, s, tf2, NULL, NULL, NULL))
00300         {
00301           AABB overlap_part;
00302           AABB aabb1, aabb2;
00303           computeBV<AABB, Box>(box, box_tf, aabb1);
00304           computeBV<AABB, S>(s, tf2, aabb2);
00305           aabb1.overlap(aabb2, overlap_part);
00306           cresult->addCostSource(CostSource(overlap_part, tree1->getOccupancyThres() * s.cost_density), crequest->num_max_cost_sources);          
00307         }
00308       }
00309 
00310       return false;
00311     }
00312     else if(!root1->hasChildren())
00313     {
00314       if(tree1->isNodeOccupied(root1) && s.isOccupied()) // occupied area
00315       {
00316         OBB obb1;
00317         convertBV(bv1, tf1, obb1);
00318         if(obb1.overlap(obb2))
00319         {
00320           Box box;
00321           Transform3f box_tf;
00322           constructBox(bv1, tf1, box, box_tf);
00323 
00324           bool is_intersect = false;
00325           if(!crequest->enable_contact)
00326           {
00327             if(solver->shapeIntersect(box, box_tf, s, tf2, NULL, NULL, NULL))
00328             {
00329               is_intersect = true;
00330               if(cresult->numContacts() < crequest->num_max_contacts)
00331                 cresult->addContact(Contact(tree1, &s, root1 - tree1->getRoot(), Contact::NONE));
00332             }
00333           }
00334           else
00335           {
00336             Vec3f contact;
00337             FCL_REAL depth;
00338             Vec3f normal;
00339 
00340             if(solver->shapeIntersect(box, box_tf, s, tf2, &contact, &depth, &normal))
00341             {
00342               is_intersect = true;
00343               if(cresult->numContacts() < crequest->num_max_contacts)
00344                 cresult->addContact(Contact(tree1, &s, root1 - tree1->getRoot(), Contact::NONE, contact, normal, depth));
00345             }
00346           }
00347 
00348           if(is_intersect && crequest->enable_cost)
00349           {
00350             AABB overlap_part;
00351             AABB aabb1, aabb2;
00352             computeBV<AABB, Box>(box, box_tf, aabb1);
00353             computeBV<AABB, S>(s, tf2, aabb2);
00354             aabb1.overlap(aabb2, overlap_part);
00355           }
00356 
00357           return crequest->isSatisfied(*cresult);
00358         }
00359         else return false;
00360       }
00361       else if(!tree1->isNodeFree(root1) && !s.isFree() && crequest->enable_cost) // uncertain area
00362       {
00363         OBB obb1;
00364         convertBV(bv1, tf1, obb1);
00365         if(obb1.overlap(obb2))
00366         {
00367           Box box;
00368           Transform3f box_tf;
00369           constructBox(bv1, tf1, box, box_tf);
00370 
00371           if(solver->shapeIntersect(box, box_tf, s, tf2, NULL, NULL, NULL))
00372           {
00373             AABB overlap_part;
00374             AABB aabb1, aabb2;
00375             computeBV<AABB, Box>(box, box_tf, aabb1);
00376             computeBV<AABB, S>(s, tf2, aabb2);
00377             aabb1.overlap(aabb2, overlap_part);
00378           }
00379         }
00380         
00381         return false;
00382       }
00383       else // free area
00384         return false;
00385     }
00386 
00390     if(tree1->isNodeFree(root1) || s.isFree()) return false;
00391     else if((tree1->isNodeUncertain(root1) || s.isUncertain()) && !crequest->enable_cost) return false;
00392     else
00393     {
00394       OBB obb1;
00395       convertBV(bv1, tf1, obb1);
00396       if(!obb1.overlap(obb2)) return false;
00397     }
00398 
00399     for(unsigned int i = 0; i < 8; ++i)
00400     {
00401       if(root1->childExists(i))
00402       {
00403         const OcTree::OcTreeNode* child = root1->getChild(i);
00404         AABB child_bv;
00405         computeChildBV(bv1, i, child_bv);
00406         
00407         if(OcTreeShapeIntersectRecurse(tree1, child, child_bv, s, obb2, tf1, tf2))
00408           return true;
00409       }
00410       else if(!s.isFree() && crequest->enable_cost)
00411       {
00412         AABB child_bv;
00413         computeChildBV(bv1, i, child_bv);
00414 
00415         if(OcTreeShapeIntersectRecurse(tree1, NULL, child_bv, s, obb2, tf1, tf2))
00416           return true;
00417       }
00418     }
00419 
00420     return false;    
00421   }
00422 
00423   template<typename BV>
00424   bool OcTreeMeshDistanceRecurse(const OcTree* tree1, const OcTree::OcTreeNode* root1, const AABB& bv1,
00425                                  const BVHModel<BV>* tree2, int root2,
00426                                  const Transform3f& tf1, const Transform3f& tf2) const
00427   {
00428     if(!root1->hasChildren() && tree2->getBV(root2).isLeaf())
00429     {
00430       if(tree1->isNodeOccupied(root1))
00431       {
00432         Box box;
00433         Transform3f box_tf;
00434         constructBox(bv1, tf1, box, box_tf);
00435 
00436         int primitive_id = tree2->getBV(root2).primitiveId();
00437         const Triangle& tri_id = tree2->tri_indices[primitive_id];
00438         const Vec3f& p1 = tree2->vertices[tri_id[0]];
00439         const Vec3f& p2 = tree2->vertices[tri_id[1]];
00440         const Vec3f& p3 = tree2->vertices[tri_id[2]];
00441         
00442         FCL_REAL dist;
00443         solver->shapeTriangleDistance(box, box_tf, p1, p2, p3, tf2, &dist);
00444 
00445         dresult->update(dist, tree1, tree2, root1 - tree1->getRoot(), primitive_id);
00446 
00447         return drequest->isSatisfied(*dresult);
00448       }
00449       else
00450         return false;
00451     }
00452 
00453     if(!tree1->isNodeOccupied(root1)) return false;
00454 
00455     if(tree2->getBV(root2).isLeaf() || (root1->hasChildren() && (bv1.size() > tree2->getBV(root2).bv.size())))
00456     {
00457       for(unsigned int i = 0; i < 8; ++i)
00458       {
00459         if(root1->childExists(i))
00460         {
00461           const OcTree::OcTreeNode* child = root1->getChild(i);
00462           AABB child_bv;
00463           computeChildBV(bv1, i, child_bv);
00464 
00465           FCL_REAL d;
00466           AABB aabb1, aabb2;
00467           convertBV(child_bv, tf1, aabb1);
00468           convertBV(tree2->getBV(root2).bv, tf2, aabb2);
00469           d = aabb1.distance(aabb2);
00470           
00471           if(d < dresult->min_distance)
00472           {
00473             if(OcTreeMeshDistanceRecurse(tree1, child, child_bv, tree2, root2, tf1, tf2))
00474               return true;
00475           }
00476         }
00477       }
00478     }
00479     else
00480     {
00481       FCL_REAL d;
00482       AABB aabb1, aabb2;
00483       convertBV(bv1, tf1, aabb1);
00484       int child = tree2->getBV(root2).leftChild();
00485       convertBV(tree2->getBV(child).bv, tf2, aabb2);
00486       d = aabb1.distance(aabb2);
00487 
00488       if(d < dresult->min_distance)
00489       {
00490         if(OcTreeMeshDistanceRecurse(tree1, root1, bv1, tree2, child, tf1, tf2))
00491           return true;
00492       }
00493 
00494       child = tree2->getBV(root2).rightChild();
00495       convertBV(tree2->getBV(child).bv, tf2, aabb2);
00496       d = aabb1.distance(aabb2);
00497       
00498       if(d < dresult->min_distance)
00499       {
00500         if(OcTreeMeshDistanceRecurse(tree1, root1, bv1, tree2, child, tf1, tf2))
00501           return true;      
00502       }
00503     }
00504 
00505     return false;
00506   }
00507 
00508 
00509   template<typename BV>
00510   bool OcTreeMeshIntersectRecurse(const OcTree* tree1, const OcTree::OcTreeNode* root1, const AABB& bv1,
00511                                   const BVHModel<BV>* tree2, int root2,
00512                                   const Transform3f& tf1, const Transform3f& tf2) const
00513   {
00514     if(!root1)
00515     {
00516       if(tree2->getBV(root2).isLeaf())
00517       {
00518         OBB obb1, obb2;
00519         convertBV(bv1, tf1, obb1);
00520         convertBV(tree2->getBV(root2).bv, tf2, obb2);
00521         if(obb1.overlap(obb2))
00522         {
00523           Box box;
00524           Transform3f box_tf;
00525           constructBox(bv1, tf1, box, box_tf);
00526 
00527           int primitive_id = tree2->getBV(root2).primitiveId();
00528           const Triangle& tri_id = tree2->tri_indices[primitive_id];
00529           const Vec3f& p1 = tree2->vertices[tri_id[0]];
00530           const Vec3f& p2 = tree2->vertices[tri_id[1]];
00531           const Vec3f& p3 = tree2->vertices[tri_id[2]];
00532         
00533           if(solver->shapeTriangleIntersect(box, box_tf, p1, p2, p3, tf2, NULL, NULL, NULL))
00534           {
00535             AABB overlap_part;
00536             AABB aabb1;
00537             computeBV<AABB, Box>(box, box_tf, aabb1);
00538             AABB aabb2(tf2.transform(p1), tf2.transform(p2), tf2.transform(p3));
00539             aabb1.overlap(aabb2, overlap_part);
00540             cresult->addCostSource(CostSource(overlap_part, tree1->getOccupancyThres() * tree2->cost_density), crequest->num_max_cost_sources);
00541           }
00542         }
00543 
00544         return false;
00545       }
00546       else
00547       {
00548         if(OcTreeMeshIntersectRecurse(tree1, root1, bv1, tree2, tree2->getBV(root2).leftChild(), tf1, tf2))
00549           return true;
00550 
00551         if(OcTreeMeshIntersectRecurse(tree1, root1, bv1, tree2, tree2->getBV(root2).rightChild(), tf1, tf2))
00552           return true;
00553 
00554         return false;
00555       }
00556     }
00557     else if(!root1->hasChildren() && tree2->getBV(root2).isLeaf())
00558     {
00559       if(tree1->isNodeOccupied(root1) && tree2->isOccupied())
00560       {
00561         OBB obb1, obb2;
00562         convertBV(bv1, tf1, obb1);
00563         convertBV(tree2->getBV(root2).bv, tf2, obb2);
00564         if(obb1.overlap(obb2))
00565         {
00566           Box box;
00567           Transform3f box_tf;
00568           constructBox(bv1, tf1, box, box_tf);
00569 
00570           int primitive_id = tree2->getBV(root2).primitiveId();
00571           const Triangle& tri_id = tree2->tri_indices[primitive_id];
00572           const Vec3f& p1 = tree2->vertices[tri_id[0]];
00573           const Vec3f& p2 = tree2->vertices[tri_id[1]];
00574           const Vec3f& p3 = tree2->vertices[tri_id[2]];
00575         
00576           bool is_intersect = false;
00577           if(!crequest->enable_contact)
00578           {
00579             if(solver->shapeTriangleIntersect(box, box_tf, p1, p2, p3, tf2, NULL, NULL, NULL))
00580             {
00581               is_intersect = true;
00582               if(cresult->numContacts() < crequest->num_max_contacts)
00583                 cresult->addContact(Contact(tree1, tree2, root1 - tree1->getRoot(), root2));
00584             }
00585           }
00586           else
00587           {
00588             Vec3f contact;
00589             FCL_REAL depth;
00590             Vec3f normal;
00591 
00592             if(solver->shapeTriangleIntersect(box, box_tf, p1, p2, p3, tf2, &contact, &depth, &normal))
00593             {
00594               is_intersect = true;
00595               if(cresult->numContacts() < crequest->num_max_contacts)
00596                 cresult->addContact(Contact(tree1, tree2, root1 - tree1->getRoot(), root2, contact, normal, depth));
00597             }
00598           }
00599 
00600           if(is_intersect && crequest->enable_cost)
00601           {
00602             AABB overlap_part;
00603             AABB aabb1;
00604             computeBV<AABB, Box>(box, box_tf, aabb1);
00605             AABB aabb2(tf2.transform(p1), tf2.transform(p2), tf2.transform(p3));
00606             aabb1.overlap(aabb2, overlap_part);
00607             cresult->addCostSource(CostSource(overlap_part, root1->getOccupancy() * tree2->cost_density), crequest->num_max_cost_sources);
00608           }
00609 
00610           return crequest->isSatisfied(*cresult);
00611         }
00612         else
00613           return false;
00614       }
00615       else if(!tree1->isNodeFree(root1) && !tree2->isFree() && crequest->enable_cost) // uncertain area
00616       {
00617         OBB obb1, obb2;
00618         convertBV(bv1, tf1, obb1);
00619         convertBV(tree2->getBV(root2).bv, tf2, obb2);
00620         if(obb1.overlap(obb2))
00621         {
00622           Box box;
00623           Transform3f box_tf;
00624           constructBox(bv1, tf1, box, box_tf);
00625 
00626           int primitive_id = tree2->getBV(root2).primitiveId();
00627           const Triangle& tri_id = tree2->tri_indices[primitive_id];
00628           const Vec3f& p1 = tree2->vertices[tri_id[0]];
00629           const Vec3f& p2 = tree2->vertices[tri_id[1]];
00630           const Vec3f& p3 = tree2->vertices[tri_id[2]];
00631         
00632           if(solver->shapeTriangleIntersect(box, box_tf, p1, p2, p3, tf2, NULL, NULL, NULL))
00633           {
00634             AABB overlap_part;
00635             AABB aabb1;
00636             computeBV<AABB, Box>(box, box_tf, aabb1);
00637             AABB aabb2(tf2.transform(p1), tf2.transform(p2), tf2.transform(p3));
00638             aabb1.overlap(aabb2, overlap_part);
00639             cresult->addCostSource(CostSource(overlap_part, root1->getOccupancy() * tree2->cost_density), crequest->num_max_cost_sources);
00640           }
00641         }
00642         
00643         return false;
00644       }
00645       else // free area
00646         return false;
00647     }
00648 
00652     if(tree1->isNodeFree(root1) || tree2->isFree()) return false;
00653     else if((tree1->isNodeUncertain(root1) || tree2->isUncertain()) && !crequest->enable_cost) return false;
00654     else
00655     {
00656       OBB obb1, obb2;
00657       convertBV(bv1, tf1, obb1);
00658       convertBV(tree2->getBV(root2).bv, tf2, obb2);
00659       if(!obb1.overlap(obb2)) return false;      
00660     }
00661    
00662     if(tree2->getBV(root2).isLeaf() || (root1->hasChildren() && (bv1.size() > tree2->getBV(root2).bv.size())))
00663     {
00664       for(unsigned int i = 0; i < 8; ++i)
00665       {
00666         if(root1->childExists(i))
00667         {
00668           const OcTree::OcTreeNode* child = root1->getChild(i);
00669           AABB child_bv;
00670           computeChildBV(bv1, i, child_bv);
00671           
00672           if(OcTreeMeshIntersectRecurse(tree1, child, child_bv, tree2, root2, tf1, tf2))
00673             return true;
00674         }
00675         else if(!tree2->isFree() && crequest->enable_cost)
00676         {
00677           AABB child_bv;
00678           computeChildBV(bv1, i, child_bv);
00679 
00680           if(OcTreeMeshIntersectRecurse(tree1, NULL, child_bv, tree2, root2, tf1, tf2))
00681             return true;
00682         }
00683       }
00684     }
00685     else
00686     {
00687       if(OcTreeMeshIntersectRecurse(tree1, root1, bv1, tree2, tree2->getBV(root2).leftChild(), tf1, tf2))
00688         return true;
00689 
00690       if(OcTreeMeshIntersectRecurse(tree1, root1, bv1, tree2, tree2->getBV(root2).rightChild(), tf1, tf2))
00691         return true;      
00692 
00693     }
00694 
00695     return false;
00696   }
00697 
00698   bool OcTreeDistanceRecurse(const OcTree* tree1, const OcTree::OcTreeNode* root1, const AABB& bv1,
00699                              const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& bv2,
00700                              const Transform3f& tf1, const Transform3f& tf2) const
00701   {
00702     if(!root1->hasChildren() && !root2->hasChildren())
00703     {
00704       if(tree1->isNodeOccupied(root1) && tree2->isNodeOccupied(root2))
00705       {
00706         Box box1, box2;
00707         Transform3f box1_tf, box2_tf;
00708         constructBox(bv1, tf1, box1, box1_tf);
00709         constructBox(bv2, tf2, box2, box2_tf);
00710 
00711         FCL_REAL dist;
00712         solver->shapeDistance(box1, box1_tf, box2, box2_tf, &dist);
00713 
00714         dresult->update(dist, tree1, tree2, root1 - tree1->getRoot(), root2 - tree2->getRoot());
00715         
00716         return drequest->isSatisfied(*dresult);
00717       }
00718       else
00719         return false;
00720     }
00721 
00722     if(!tree1->isNodeOccupied(root1) || !tree2->isNodeOccupied(root2)) return false;
00723 
00724     if(!root2->hasChildren() || (root1->hasChildren() && (bv1.size() > bv2.size())))
00725     {
00726       for(unsigned int i = 0; i < 8; ++i)
00727       {
00728         if(root1->childExists(i))
00729         {
00730           const OcTree::OcTreeNode* child = root1->getChild(i);
00731           AABB child_bv;
00732           computeChildBV(bv1, i, child_bv);
00733 
00734           FCL_REAL d;
00735           AABB aabb1, aabb2;
00736           convertBV(bv1, tf1, aabb1);
00737           convertBV(bv2, tf2, aabb2);
00738           d = aabb1.distance(aabb2);
00739 
00740           if(d < dresult->min_distance)
00741           {
00742           
00743             if(OcTreeDistanceRecurse(tree1, child, child_bv, tree2, root2, bv2, tf1, tf2))
00744               return true;
00745           }
00746         }
00747       }
00748     }
00749     else
00750     {
00751       for(unsigned int i = 0; i < 8; ++i)
00752       {
00753         if(root2->childExists(i))
00754         {
00755           const OcTree::OcTreeNode* child = root2->getChild(i);
00756           AABB child_bv;
00757           computeChildBV(bv2, i, child_bv);
00758 
00759           FCL_REAL d;
00760           AABB aabb1, aabb2;
00761           convertBV(bv1, tf1, aabb1);
00762           convertBV(bv2, tf2, aabb2);
00763           d = aabb1.distance(aabb2);
00764 
00765           if(d < dresult->min_distance)
00766           {
00767             if(OcTreeDistanceRecurse(tree1, root1, bv1, tree2, child, child_bv, tf1, tf2))
00768               return true;
00769           }
00770         }
00771       }
00772     }
00773     
00774     return false;
00775   }
00776 
00777 
00778   bool OcTreeIntersectRecurse(const OcTree* tree1, const OcTree::OcTreeNode* root1, const AABB& bv1,
00779                               const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& bv2,
00780                               const Transform3f& tf1, const Transform3f& tf2) const
00781   {
00782     if(!root1 && !root2)
00783     {
00784       OBB obb1, obb2;
00785       convertBV(bv1, tf1, obb1);
00786       convertBV(bv2, tf2, obb2);
00787 
00788       if(obb1.overlap(obb2))
00789       {
00790         Box box1, box2;
00791         Transform3f box1_tf, box2_tf;
00792         constructBox(bv1, tf1, box1, box1_tf);
00793         constructBox(bv2, tf2, box2, box2_tf);
00794         
00795         AABB overlap_part;
00796         AABB aabb1, aabb2;
00797         computeBV<AABB, Box>(box1, box1_tf, aabb1);
00798         computeBV<AABB, Box>(box2, box2_tf, aabb2);
00799         aabb1.overlap(aabb2, overlap_part);
00800         cresult->addCostSource(CostSource(overlap_part, tree1->getOccupancyThres() * tree2->getOccupancyThres()), crequest->num_max_cost_sources);
00801       }
00802 
00803       return false;
00804     }
00805     else if(!root1 && root2)
00806     {
00807       if(root2->hasChildren())
00808       {
00809         for(unsigned int i = 0; i < 8; ++i)
00810         {
00811           if(root2->childExists(i))
00812           {
00813             const OcTree::OcTreeNode* child = root2->getChild(i);
00814             AABB child_bv;
00815             computeChildBV(bv2, i, child_bv);
00816             if(OcTreeIntersectRecurse(tree1, NULL, bv1, tree2, child, child_bv, tf1, tf2))
00817               return true;
00818           }
00819           else 
00820           {
00821             AABB child_bv;
00822             computeChildBV(bv2, i, child_bv);
00823             if(OcTreeIntersectRecurse(tree1, NULL, bv1, tree2, NULL, child_bv, tf1, tf2))
00824               return true;
00825           }
00826         }
00827       }
00828       else
00829       {
00830         if(OcTreeIntersectRecurse(tree1, NULL, bv1, tree2, NULL, bv2, tf1, tf2))
00831           return true;
00832       }
00833       
00834       return false;
00835     }
00836     else if(root1 && !root2)
00837     {
00838       if(root1->hasChildren())
00839       {
00840         for(unsigned int i = 0; i < 8; ++i)
00841         {
00842           if(root1->childExists(i))
00843           {
00844             const OcTree::OcTreeNode* child = root1->getChild(i);
00845             AABB child_bv;
00846             computeChildBV(bv1, i,  child_bv);
00847             if(OcTreeIntersectRecurse(tree1, child, child_bv, tree2, NULL, bv2, tf1, tf2))
00848               return true;
00849           }
00850           else
00851           {
00852             AABB child_bv;
00853             computeChildBV(bv1, i, child_bv);
00854             if(OcTreeIntersectRecurse(tree1, NULL, child_bv, tree2, NULL, bv2, tf1, tf2))
00855               return true;
00856           }
00857         }
00858       }
00859       else
00860       {
00861         if(OcTreeIntersectRecurse(tree1, NULL, bv1, tree2, NULL, bv2, tf1, tf2))
00862           return true;
00863       }
00864       
00865       return false;
00866     }
00867     else if(!root1->hasChildren() && !root2->hasChildren())
00868     {
00869       if(tree1->isNodeOccupied(root1) && tree2->isNodeOccupied(root2)) // occupied area
00870       {
00871         bool is_intersect = false;
00872         if(!crequest->enable_contact)
00873         {
00874           OBB obb1, obb2;
00875           convertBV(bv1, tf1, obb1);
00876           convertBV(bv2, tf2, obb2);
00877           
00878           if(obb1.overlap(obb2))
00879           {
00880             is_intersect = true;
00881             if(cresult->numContacts() < crequest->num_max_contacts)
00882               cresult->addContact(Contact(tree1, tree2, root1 - tree1->getRoot(), root2 - tree2->getRoot()));
00883           }
00884         }
00885         else
00886         {
00887           Box box1, box2;
00888           Transform3f box1_tf, box2_tf;
00889           constructBox(bv1, tf1, box1, box1_tf);
00890           constructBox(bv2, tf2, box2, box2_tf);
00891 
00892           Vec3f contact;
00893           FCL_REAL depth;
00894           Vec3f normal;
00895           if(solver->shapeIntersect(box1, box1_tf, box2, box2_tf, &contact, &depth, &normal))
00896           {
00897             is_intersect = true;
00898             if(cresult->numContacts() < crequest->num_max_contacts)
00899               cresult->addContact(Contact(tree1, tree2, root1 - tree1->getRoot(), root2 - tree2->getRoot(), contact, normal, depth));
00900           }
00901         }
00902 
00903         if(is_intersect && crequest->enable_cost)
00904         {
00905           Box box1, box2;
00906           Transform3f box1_tf, box2_tf;
00907           constructBox(bv1, tf1, box1, box1_tf);
00908           constructBox(bv2, tf2, box2, box2_tf);
00909 
00910           AABB overlap_part;
00911           AABB aabb1, aabb2;
00912           computeBV<AABB, Box>(box1, box1_tf, aabb1);
00913           computeBV<AABB, Box>(box2, box2_tf, aabb2);
00914           aabb1.overlap(aabb2, overlap_part);
00915           cresult->addCostSource(CostSource(overlap_part, root1->getOccupancy() * root2->getOccupancy()), crequest->num_max_cost_sources);
00916         }
00917 
00918         return crequest->isSatisfied(*cresult);
00919       }
00920       else if(!tree1->isNodeFree(root1) && !tree2->isNodeFree(root2) && crequest->enable_cost) // uncertain area (here means both are uncertain or one uncertain and one occupied)
00921       {
00922         OBB obb1, obb2;
00923         convertBV(bv1, tf1, obb1);
00924         convertBV(bv2, tf2, obb2);
00925         
00926         if(obb1.overlap(obb2))
00927         {
00928           Box box1, box2;
00929           Transform3f box1_tf, box2_tf;
00930           constructBox(bv1, tf1, box1, box1_tf);
00931           constructBox(bv2, tf2, box2, box2_tf);
00932 
00933           AABB overlap_part;
00934           AABB aabb1, aabb2;
00935           computeBV<AABB, Box>(box1, box1_tf, aabb1);
00936           computeBV<AABB, Box>(box2, box2_tf, aabb2);
00937           aabb1.overlap(aabb2, overlap_part);
00938           cresult->addCostSource(CostSource(overlap_part, root1->getOccupancy() * root2->getOccupancy()), crequest->num_max_cost_sources);
00939         }
00940 
00941         return false;
00942       }
00943       else // free area (at least one node is free)
00944         return false;
00945     }
00946 
00950     if(tree1->isNodeFree(root1) || tree2->isNodeFree(root2)) return false;
00951     else if((tree1->isNodeUncertain(root1) || tree2->isNodeUncertain(root2)) && !crequest->enable_cost) return false;
00952     else 
00953     {
00954       OBB obb1, obb2;
00955       convertBV(bv1, tf1, obb1);
00956       convertBV(bv2, tf2, obb2);
00957       if(!obb1.overlap(obb2)) return false;
00958     }
00959 
00960     if(!root2->hasChildren() || (root1->hasChildren() && (bv1.size() > bv2.size())))
00961     {
00962       for(unsigned int i = 0; i < 8; ++i)
00963       {
00964         if(root1->childExists(i))
00965         {
00966           const OcTree::OcTreeNode* child = root1->getChild(i);
00967           AABB child_bv;
00968           computeChildBV(bv1, i, child_bv);
00969         
00970           if(OcTreeIntersectRecurse(tree1, child, child_bv, 
00971                                     tree2, root2, bv2,
00972                                     tf1, tf2))
00973             return true;
00974         }
00975         else if(!tree2->isNodeFree(root2) && crequest->enable_cost)
00976         {
00977           AABB child_bv;
00978           computeChildBV(bv1, i, child_bv);
00979           
00980           if(OcTreeIntersectRecurse(tree1, NULL, child_bv,
00981                                     tree2, root2, bv2,
00982                                     tf1, tf2))
00983             return true;
00984         }
00985       }
00986     }
00987     else
00988     {
00989       for(unsigned int i = 0; i < 8; ++i)
00990       {
00991         if(root2->childExists(i))
00992         {
00993           const OcTree::OcTreeNode* child = root2->getChild(i);
00994           AABB child_bv;
00995           computeChildBV(bv2, i, child_bv);
00996           
00997           if(OcTreeIntersectRecurse(tree1, root1, bv1,
00998                                     tree2, child, child_bv,
00999                                     tf1, tf2))
01000             return true;
01001         }
01002         else if(!tree1->isNodeFree(root1) && crequest->enable_cost)
01003         {
01004           AABB child_bv;
01005           computeChildBV(bv2, i, child_bv);
01006 
01007           if(OcTreeIntersectRecurse(tree1, root1, bv1,
01008                                     tree2, NULL, child_bv,
01009                                     tf1, tf2))
01010             return true;
01011         }
01012       }
01013     }
01014 
01015     return false;
01016   }
01017 };
01018 
01019 
01020 
01021 
01023 template<typename NarrowPhaseSolver>
01024 class OcTreeCollisionTraversalNode : public CollisionTraversalNodeBase
01025 {
01026 public:
01027   OcTreeCollisionTraversalNode()
01028   {
01029     model1 = NULL;
01030     model2 = NULL;
01031 
01032     otsolver = NULL;
01033   }
01034 
01035   bool BVTesting(int, int) const
01036   {
01037     return false;
01038   }
01039 
01040   void leafTesting(int, int) const
01041   {
01042     otsolver->OcTreeIntersect(model1, model2, tf1, tf2, request, *result);
01043   }
01044 
01045   const OcTree* model1;
01046   const OcTree* model2;
01047 
01048   Transform3f tf1, tf2;
01049 
01050   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01051 };
01052 
01054 template<typename NarrowPhaseSolver>
01055 class OcTreeDistanceTraversalNode : public DistanceTraversalNodeBase
01056 {
01057 public:
01058   OcTreeDistanceTraversalNode()
01059   {
01060     model1 = NULL;
01061     model2 = NULL;
01062 
01063     otsolver = NULL;
01064   }
01065 
01066 
01067   FCL_REAL BVTesting(int, int) const
01068   {
01069     return -1;
01070   }
01071 
01072   void leafTesting(int, int) const
01073   {
01074     otsolver->OcTreeDistance(model1, model2, tf1, tf2, request, *result);
01075   }
01076 
01077   const OcTree* model1;
01078   const OcTree* model2;
01079 
01080   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01081 };
01082 
01084 template<typename S, typename NarrowPhaseSolver>
01085 class ShapeOcTreeCollisionTraversalNode : public CollisionTraversalNodeBase
01086 {
01087 public:
01088   ShapeOcTreeCollisionTraversalNode()
01089   {
01090     model1 = NULL;
01091     model2 = NULL;
01092 
01093     otsolver = NULL;
01094   }
01095 
01096   bool BVTesting(int, int) const
01097   {
01098     return false;
01099   }
01100 
01101   void leafTesting(int, int) const
01102   {
01103     otsolver->OcTreeShapeIntersect(model2, *model1, tf2, tf1, request, *result);
01104   }
01105 
01106   const S* model1;
01107   const OcTree* model2;
01108 
01109   Transform3f tf1, tf2;
01110 
01111   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01112 };
01113 
01115 template<typename S, typename NarrowPhaseSolver>
01116 class OcTreeShapeCollisionTraversalNode : public CollisionTraversalNodeBase
01117 {
01118 public:
01119   OcTreeShapeCollisionTraversalNode()
01120   {
01121     model1 = NULL;
01122     model2 = NULL;
01123 
01124     otsolver = NULL;
01125   }
01126 
01127   bool BVTesting(int, int) const
01128   {
01129     return false;
01130   }
01131 
01132   void leafTesting(int, int) const
01133   {
01134     otsolver->OcTreeShapeIntersect(model1, *model2, tf1, tf2, request, *result);
01135   }
01136 
01137   const OcTree* model1;
01138   const S* model2;
01139 
01140   Transform3f tf1, tf2;
01141  
01142   const OcTreeSolver<NarrowPhaseSolver>* otsolver;  
01143 };
01144 
01146 template<typename S, typename NarrowPhaseSolver>
01147 class ShapeOcTreeDistanceTraversalNode : public DistanceTraversalNodeBase
01148 {
01149 public:
01150   ShapeOcTreeDistanceTraversalNode()
01151   {
01152     model1 = NULL;
01153     model2 = NULL;
01154     
01155     otsolver = NULL;
01156   }
01157 
01158   FCL_REAL BVTesting(int, int) const
01159   {
01160     return -1;
01161   }
01162 
01163   void leafTesting(int, int) const
01164   {
01165     otsolver->OcTreeShapeDistance(model2, *model1, tf2, tf1, request, *result);
01166   }
01167 
01168   const S* model1;
01169   const OcTree* model2;
01170 
01171   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01172 };
01173 
01175 template<typename S, typename NarrowPhaseSolver>
01176 class OcTreeShapeDistanceTraversalNode : public DistanceTraversalNodeBase
01177 {
01178 public:
01179   OcTreeShapeDistanceTraversalNode()
01180   {
01181     model1 = NULL;
01182     model2 = NULL;
01183     
01184     otsolver = NULL;
01185   }
01186 
01187   FCL_REAL BVTesting(int, int) const
01188   {
01189     return -1;
01190   }
01191 
01192   void leafTesting(int, int) const
01193   {
01194     otsolver->OcTreeShapeDistance(model1, *model2, tf1, tf2, request, *result);
01195   }
01196 
01197   const OcTree* model1;
01198   const S* model2;
01199 
01200   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01201 };
01202 
01204 template<typename BV, typename NarrowPhaseSolver>
01205 class MeshOcTreeCollisionTraversalNode : public CollisionTraversalNodeBase
01206 {
01207 public:
01208   MeshOcTreeCollisionTraversalNode()
01209   {
01210     model1 = NULL;
01211     model2 = NULL;
01212 
01213     otsolver = NULL;
01214   }
01215 
01216   bool BVTesting(int, int) const
01217   {
01218     return false;
01219   }
01220 
01221   void leafTesting(int, int) const
01222   {
01223     otsolver->OcTreeMeshIntersect(model2, model1, tf2, tf1, request, *result);
01224   }
01225 
01226   const BVHModel<BV>* model1;
01227   const OcTree* model2;
01228 
01229   Transform3f tf1, tf2;
01230     
01231   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01232 };
01233 
01235 template<typename BV, typename NarrowPhaseSolver>
01236 class OcTreeMeshCollisionTraversalNode : public CollisionTraversalNodeBase
01237 {
01238 public:
01239   OcTreeMeshCollisionTraversalNode()
01240   {
01241     model1 = NULL;
01242     model2 = NULL;
01243 
01244     otsolver = NULL;
01245   }
01246 
01247   bool BVTesting(int, int) const
01248   {
01249     return false;
01250   }
01251 
01252   void leafTesting(int, int) const
01253   {
01254     otsolver->OcTreeMeshIntersect(model1, model2, tf1, tf2, request, *result);
01255   }
01256 
01257   const OcTree* model1;
01258   const BVHModel<BV>* model2;
01259 
01260   Transform3f tf1, tf2;
01261     
01262   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01263 };
01264 
01266 template<typename BV, typename NarrowPhaseSolver>
01267 class MeshOcTreeDistanceTraversalNode : public DistanceTraversalNodeBase
01268 {
01269 public:
01270   MeshOcTreeDistanceTraversalNode()
01271   {
01272     model1 = NULL;
01273     model2 = NULL;
01274     
01275     otsolver = NULL;
01276   }
01277 
01278   FCL_REAL BVTesting(int, int) const
01279   {
01280     return -1;
01281   }
01282 
01283   void leafTesting(int, int) const
01284   {
01285     otsolver->OcTreeMeshDistance(model2, model1, tf2, tf1, request, *result);
01286   }
01287 
01288   const BVHModel<BV>* model1;
01289   const OcTree* model2;
01290 
01291   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01292 
01293 };
01294 
01296 template<typename BV, typename NarrowPhaseSolver>
01297 class OcTreeMeshDistanceTraversalNode : public DistanceTraversalNodeBase
01298 {
01299 public:
01300   OcTreeMeshDistanceTraversalNode()
01301   {
01302     model1 = NULL;
01303     model2 = NULL;
01304     
01305     otsolver = NULL;
01306   }
01307 
01308   FCL_REAL BVTesting(int, int) const
01309   {
01310     return -1;
01311   }
01312 
01313   void leafTesting(int, int) const
01314   {
01315     otsolver->OcTreeMeshDistance(model1, model2, tf1, tf2, request, *result);
01316   }
01317 
01318   const OcTree* model1;
01319   const BVHModel<BV>* model2;
01320 
01321   const OcTreeSolver<NarrowPhaseSolver>* otsolver;
01322 
01323 };
01324 
01325 
01326 
01327 }
01328 
01329 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


fcl
Author(s): Jia Pan
autogenerated on Tue Jan 15 2013 16:05:31