traversal_recurse.cpp
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 
00038 #include "fcl/traversal/traversal_recurse.h"
00039 
00040 namespace fcl
00041 {
00042 void collisionRecurse(CollisionTraversalNodeBase* node, int b1, int b2, BVHFrontList* front_list)
00043 {
00044   bool l1 = node->isFirstNodeLeaf(b1);
00045   bool l2 = node->isSecondNodeLeaf(b2);
00046 
00047   if(l1 && l2)
00048   {
00049     updateFrontList(front_list, b1, b2);
00050 
00051     if(node->BVTesting(b1, b2)) return;
00052 
00053     node->leafTesting(b1, b2);
00054     return;
00055   }
00056 
00057   if(node->BVTesting(b1, b2))
00058   {
00059     updateFrontList(front_list, b1, b2);
00060     return;
00061   }
00062 
00063   if(node->firstOverSecond(b1, b2))
00064   {
00065     int c1 = node->getFirstLeftChild(b1);
00066     int c2 = node->getFirstRightChild(b1);
00067 
00068     collisionRecurse(node, c1, b2, front_list);
00069 
00070     // early stop is disabled is front_list is used
00071     if(node->canStop() && !front_list) return;
00072 
00073     collisionRecurse(node, c2, b2, front_list);
00074   }
00075   else
00076   {
00077     int c1 = node->getSecondLeftChild(b2);
00078     int c2 = node->getSecondRightChild(b2);
00079 
00080     collisionRecurse(node, b1, c1, front_list);
00081 
00082     // early stop is disabled is front_list is used
00083     if(node->canStop() && !front_list) return;
00084 
00085     collisionRecurse(node, b1, c2, front_list);
00086   }
00087 }
00088 
00089 void collisionRecurse(MeshCollisionTraversalNodeOBB* node, int b1, int b2, const Matrix3f& R, const Vec3f& T, BVHFrontList* front_list)
00090 {
00091   bool l1 = node->isFirstNodeLeaf(b1);
00092   bool l2 = node->isSecondNodeLeaf(b2);
00093 
00094   if(l1 && l2)
00095   {
00096     updateFrontList(front_list, b1, b2);
00097 
00098     if(node->BVTesting(b1, b2, R, T)) return;
00099 
00100     node->leafTesting(b1, b2, R, T);
00101     return;
00102   }
00103 
00104   if(node->BVTesting(b1, b2, R, T))
00105   {
00106     updateFrontList(front_list, b1, b2);
00107     return;
00108   }
00109 
00110   Vec3f temp;
00111 
00112   if(node->firstOverSecond(b1, b2))
00113   {
00114     int c1 = node->getFirstLeftChild(b1);
00115     int c2 = node->getFirstRightChild(b1);
00116 
00117     const OBB& bv1 = node->model1->getBV(c1).bv;
00118 
00119     Matrix3f Rc(R.transposeTimes(bv1.axis[0]), R.transposeTimes(bv1.axis[1]), R.transposeTimes(bv1.axis[2]));
00120     temp = T - bv1.To;
00121     Vec3f Tc(temp.dot(bv1.axis[0]), temp.dot(bv1.axis[1]), temp.dot(bv1.axis[2]));
00122 
00123     collisionRecurse(node, c1, b2, Rc, Tc, front_list);
00124 
00125     // early stop is disabled is front_list is used
00126     if(node->canStop() && !front_list) return;
00127 
00128     const OBB& bv2 = node->model1->getBV(c2).bv;
00129 
00130     Rc = Matrix3f(R.transposeTimes(bv2.axis[0]), R.transposeTimes(bv2.axis[1]), R.transposeTimes(bv2.axis[2]));
00131     temp = T - bv2.To;
00132     Tc.setValue(temp.dot(bv2.axis[0]), temp.dot(bv2.axis[1]), temp.dot(bv2.axis[2]));
00133 
00134     collisionRecurse(node, c2, b2, Rc, Tc, front_list);
00135   }
00136   else
00137   {
00138     int c1 = node->getSecondLeftChild(b2);
00139     int c2 = node->getSecondRightChild(b2);
00140 
00141     const OBB& bv1 = node->model2->getBV(c1).bv;
00142     Matrix3f Rc;
00143     temp = R * bv1.axis[0];
00144     Rc(0, 0) = temp[0]; Rc(1, 0) = temp[1]; Rc(2, 0) = temp[2];
00145     temp = R * bv1.axis[1];
00146     Rc(0, 1) = temp[0]; Rc(1, 1) = temp[1]; Rc(2, 1) = temp[2];
00147     temp = R * bv1.axis[2];
00148     Rc(0, 2) = temp[0]; Rc(1, 2) = temp[1]; Rc(2, 2) = temp[2];
00149     Vec3f Tc = R * bv1.To + T;
00150 
00151     collisionRecurse(node, b1, c1, Rc, Tc, front_list);
00152 
00153     // early stop is disabled is front_list is used
00154     if(node->canStop() && !front_list) return;
00155 
00156     const OBB& bv2 = node->model2->getBV(c2).bv;
00157     temp = R * bv2.axis[0];
00158     Rc(0, 0) = temp[0]; Rc(1, 0) = temp[1]; Rc(2, 0) = temp[2];
00159     temp = R * bv2.axis[1];
00160     Rc(0, 1) = temp[0]; Rc(1, 1) = temp[1]; Rc(2, 1) = temp[2];
00161     temp = R * bv2.axis[2];
00162     Rc(0, 2) = temp[0]; Rc(1, 2) = temp[1]; Rc(2, 2) = temp[2];
00163     Tc = R * bv2.To + T;
00164 
00165     collisionRecurse(node, b1, c2, Rc, Tc, front_list);
00166   }
00167 }
00168 
00169 void collisionRecurse(MeshCollisionTraversalNodeRSS* node, int b1, int b2, const Matrix3f& R, const Vec3f& T, BVHFrontList* front_list)
00170 {
00171 
00172 }
00173 
00177 void selfCollisionRecurse(CollisionTraversalNodeBase* node, int b, BVHFrontList* front_list)
00178 {
00179   bool l = node->isFirstNodeLeaf(b);
00180 
00181   if(l) return;
00182 
00183   int c1 = node->getFirstLeftChild(b);
00184   int c2 = node->getFirstRightChild(b);
00185 
00186   selfCollisionRecurse(node, c1, front_list);
00187   if(node->canStop() && !front_list) return;
00188 
00189   selfCollisionRecurse(node, c2, front_list);
00190   if(node->canStop() && !front_list) return;
00191 
00192   collisionRecurse(node, c1, c2, front_list);
00193 }
00194 
00195 void distanceRecurse(DistanceTraversalNodeBase* node, int b1, int b2, BVHFrontList* front_list)
00196 {
00197   bool l1 = node->isFirstNodeLeaf(b1);
00198   bool l2 = node->isSecondNodeLeaf(b2);
00199 
00200   if(l1 && l2)
00201   {
00202     updateFrontList(front_list, b1, b2);
00203 
00204     node->leafTesting(b1, b2);
00205     return;
00206   }
00207 
00208   int a1, a2, c1, c2;
00209 
00210   if(node->firstOverSecond(b1, b2))
00211   {
00212     a1 = node->getFirstLeftChild(b1);
00213     a2 = b2;
00214     c1 = node->getFirstRightChild(b1);
00215     c2 = b2;
00216   }
00217   else
00218   {
00219     a1 = b1;
00220     a2 = node->getSecondLeftChild(b2);
00221     c1 = b1;
00222     c2 = node->getSecondRightChild(b2);
00223   }
00224 
00225   FCL_REAL d1 = node->BVTesting(a1, a2);
00226   FCL_REAL d2 = node->BVTesting(c1, c2);
00227 
00228   if(d2 < d1)
00229   {
00230     if(!node->canStop(d2))
00231       distanceRecurse(node, c1, c2, front_list);
00232     else
00233       updateFrontList(front_list, c1, c2);
00234 
00235     if(!node->canStop(d1))
00236       distanceRecurse(node, a1, a2, front_list);
00237     else
00238       updateFrontList(front_list, a1, a2);
00239   }
00240   else
00241   {
00242     if(!node->canStop(d1))
00243       distanceRecurse(node, a1, a2, front_list);
00244     else
00245       updateFrontList(front_list, a1, a2);
00246 
00247     if(!node->canStop(d2))
00248       distanceRecurse(node, c1, c2, front_list);
00249     else
00250       updateFrontList(front_list, c1, c2);
00251   }
00252 }
00253 
00254 
00256 struct BVT
00257 {
00259   FCL_REAL d;
00260 
00262   int b1, b2;
00263 };
00264 
00266 struct BVT_Comparer
00267 {
00268   bool operator() (const BVT& lhs, const BVT& rhs) const
00269   {
00270     return lhs.d > rhs.d;
00271   }
00272 };
00273 
00274 struct BVTQ
00275 {
00276   BVTQ() : qsize(2) {}
00277 
00278   bool empty() const
00279   {
00280     return pq.empty();
00281   }
00282 
00283   size_t size() const
00284   {
00285     return pq.size();
00286   }
00287 
00288   const BVT& top() const
00289   {
00290     return pq.top();
00291   }
00292 
00293   void push(const BVT& x)
00294   {
00295     pq.push(x);
00296   }
00297 
00298   void pop()
00299   {
00300     pq.pop();
00301   }
00302 
00303   bool full() const
00304   {
00305     return (pq.size() + 1 >= qsize);
00306   }
00307 
00308   std::priority_queue<BVT, std::vector<BVT>, BVT_Comparer> pq;
00309 
00311   int qsize;
00312 };
00313 
00314 
00315 void distanceQueueRecurse(DistanceTraversalNodeBase* node, int b1, int b2, BVHFrontList* front_list, int qsize)
00316 {
00317   BVTQ bvtq;
00318   bvtq.qsize = qsize;
00319 
00320   BVT min_test;
00321   min_test.b1 = b1;
00322   min_test.b2 = b2;
00323 
00324   while(1)
00325   {
00326     bool l1 = node->isFirstNodeLeaf(min_test.b1);
00327     bool l2 = node->isSecondNodeLeaf(min_test.b2);
00328 
00329     if(l1 && l2)
00330     {
00331       updateFrontList(front_list, min_test.b1, min_test.b2);
00332 
00333       node->leafTesting(min_test.b1, min_test.b2);
00334     }
00335     else if(bvtq.full())
00336     {
00337       // queue should not get two more tests, recur
00338 
00339       distanceQueueRecurse(node, min_test.b1, min_test.b2, front_list, qsize);
00340     }
00341     else
00342     {
00343       // queue capacity is not full yet
00344       BVT bvt1, bvt2;
00345 
00346       if(node->firstOverSecond(min_test.b1, min_test.b2))
00347       {
00348         int c1 = node->getFirstLeftChild(min_test.b1);
00349         int c2 = node->getFirstRightChild(min_test.b1);
00350         bvt1.b1 = c1;
00351         bvt1.b2 = min_test.b2;
00352         bvt1.d = node->BVTesting(bvt1.b1, bvt1.b2);
00353 
00354         bvt2.b1 = c2;
00355         bvt2.b2 = min_test.b2;
00356         bvt2.d = node->BVTesting(bvt2.b1, bvt2.b2);
00357       }
00358       else
00359       {
00360         int c1 = node->getSecondLeftChild(min_test.b2);
00361         int c2 = node->getSecondRightChild(min_test.b2);
00362         bvt1.b1 = min_test.b1;
00363         bvt1.b2 = c1;
00364         bvt1.d = node->BVTesting(bvt1.b1, bvt1.b2);
00365 
00366         bvt2.b1 = min_test.b1;
00367         bvt2.b2 = c2;
00368         bvt2.d = node->BVTesting(bvt2.b1, bvt2.b2);
00369       }
00370 
00371       bvtq.push(bvt1);
00372       bvtq.push(bvt2);
00373     }
00374 
00375     if(bvtq.empty())
00376       break;
00377     else
00378     {
00379       min_test = bvtq.top();
00380       bvtq.pop();
00381 
00382       if(node->canStop(min_test.d))
00383       {
00384         updateFrontList(front_list, min_test.b1, min_test.b2);
00385         break;
00386       }
00387     }
00388   }
00389 }
00390 
00391 void propagateBVHFrontListCollisionRecurse(CollisionTraversalNodeBase* node, BVHFrontList* front_list)
00392 {
00393   BVHFrontList::iterator front_iter;
00394   BVHFrontList append;
00395   for(front_iter = front_list->begin(); front_iter != front_list->end(); ++front_iter)
00396   {
00397     int b1 = front_iter->left;
00398     int b2 = front_iter->right;
00399     bool l1 = node->isFirstNodeLeaf(b1);
00400     bool l2 = node->isSecondNodeLeaf(b2);
00401 
00402     if(l1 & l2)
00403     {
00404       front_iter->valid = false; // the front node is no longer valid, in collideRecurse will add again.
00405       collisionRecurse(node, b1, b2, &append);
00406     }
00407     else
00408     {
00409       if(!node->BVTesting(b1, b2))
00410       {
00411         front_iter->valid = false;
00412 
00413         if(node->firstOverSecond(b1, b2))
00414         {
00415           int c1 = node->getFirstLeftChild(b1);
00416           int c2 = node->getFirstRightChild(b2);
00417 
00418           collisionRecurse(node, c1, b2, front_list);
00419           collisionRecurse(node, c2, b2, front_list);
00420         }
00421         else
00422         {
00423           int c1 = node->getSecondLeftChild(b2);
00424           int c2 = node->getSecondRightChild(b2);
00425 
00426           collisionRecurse(node, b1, c1, front_list);
00427           collisionRecurse(node, b1, c2, front_list);
00428         }
00429       }
00430     }
00431   }
00432 
00433 
00434   // clean the old front list (remove invalid node)
00435   for(front_iter = front_list->begin(); front_iter != front_list->end();)
00436   {
00437     if(!front_iter->valid)
00438       front_iter = front_list->erase(front_iter);
00439     else
00440       ++front_iter;
00441   }
00442 
00443   for(front_iter = append.begin(); front_iter != append.end(); ++front_iter)
00444   {
00445     front_list->push_back(*front_iter);
00446   }
00447 }
00448 
00449 
00450 }
 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