From d7d66c14ff988a49416f0ee891408dd88ae29e2c Mon Sep 17 00:00:00 2001
From: jpan <jpan@253336fb-580f-4252-a368-f3cef5a2a82b>
Date: Wed, 8 Aug 2012 01:47:45 +0000
Subject: [PATCH] mesh related cost

git-svn-id: https://kforge.ros.org/fcl/fcl_ros@160 253336fb-580f-4252-a368-f3cef5a2a82b
---
 .../broadphase/broadphase_dynamic_AABB_tree.h |  12 +-
 trunk/fcl/include/fcl/octree.h                |  31 ++-
 .../fcl/traversal/traversal_node_octree.h     | 177 ++++++++----
 .../broadphase_dynamic_AABB_tree.cpp          |  85 +++++-
 .../broadphase_dynamic_AABB_tree_array.cpp    |  87 +++++-
 trunk/fcl/src/collision_func_matrix.cpp       | 257 ++++++++++++------
 trunk/fcl/src/distance_func_matrix.cpp        |  93 +++----
 7 files changed, 533 insertions(+), 209 deletions(-)

diff --git a/trunk/fcl/include/fcl/broadphase/broadphase_dynamic_AABB_tree.h b/trunk/fcl/include/fcl/broadphase/broadphase_dynamic_AABB_tree.h
index 81ebdef3..2e44690d 100644
--- a/trunk/fcl/include/fcl/broadphase/broadphase_dynamic_AABB_tree.h
+++ b/trunk/fcl/include/fcl/broadphase/broadphase_dynamic_AABB_tree.h
@@ -125,12 +125,12 @@ public:
     {
     case GEOM_OCTREE:
       {
-        //if(!octree_as_geometry_collide)
-        //{
-        //  const OcTree* octree = static_cast<const OcTree*>(obj->getCollisionGeometry());
-        //  collisionRecurse(dtree.getRoot(), octree, octree->getRoot(), octree->getRootBV(), obj->getTransform(), cdata, callback); 
-        //}
-        //else
+        if(!octree_as_geometry_collide)
+        {
+          const OcTree* octree = static_cast<const OcTree*>(obj->getCollisionGeometry());
+          collisionRecurse(dtree.getRoot(), octree, octree->getRoot(), octree->getRootBV(), obj->getTransform(), cdata, callback); 
+        }
+        else
           collisionRecurse(dtree.getRoot(), obj, cdata, callback);
       }
       break;
diff --git a/trunk/fcl/include/fcl/octree.h b/trunk/fcl/include/fcl/octree.h
index d4ea5420..75c3c06e 100644
--- a/trunk/fcl/include/fcl/octree.h
+++ b/trunk/fcl/include/fcl/octree.h
@@ -54,6 +54,9 @@ class OcTree : public CollisionGeometry
 {
 private:
   boost::shared_ptr<const octomap::OcTree> tree;
+
+  FCL_REAL default_occupancy;
+
 public:
 
   /// @brief OcTreeNode must implement the following interfaces:
@@ -63,10 +66,16 @@ public:
   typedef octomap::OcTreeNode OcTreeNode;
 
   /// @brief construct octree with a given resolution
-  OcTree(FCL_REAL resolution) : tree(boost::shared_ptr<const octomap::OcTree>(new octomap::OcTree(resolution))) {}
+  OcTree(FCL_REAL resolution) : tree(boost::shared_ptr<const octomap::OcTree>(new octomap::OcTree(resolution)))                               
+  {
+    default_occupancy = tree->getOccupancyThres();
+  }
 
   /// @brief construct octree from octomap
-  OcTree(const boost::shared_ptr<const octomap::OcTree>& tree_) : tree(tree_) {}
+  OcTree(const boost::shared_ptr<const octomap::OcTree>& tree_) : tree(tree_)
+  {
+    default_occupancy = tree->getOccupancyThres();
+  }
 
   /// @brief compute the AABB for the octree in its local coordinate system
   void computeLocalAABB() 
@@ -135,12 +144,28 @@ public:
     return boxes;
   }
 
-  /// @brief the threshold used to decide whether one node is occupied
+  /// @brief the threshold used to decide whether one node is occupied, this is NOT the octree occupied_thresold
   FCL_REAL getOccupancyThres() const
   {
     return tree->getOccupancyThres();
   }
 
+  /// @brief the threshold used to decide whether one node is occupied, this is NOT the octree free_threshold
+  FCL_REAL getFreeThres() const
+  {
+    return 0.0;
+  }
+
+  FCL_REAL getDefaultOccupancy() const
+  {
+    return default_occupancy;
+  }
+
+  void setCellDefaultOccupancy(FCL_REAL d)
+  {
+    default_occupancy = d;
+  }
+
   /// @brief return object type, it is an octree
   OBJECT_TYPE getObjectType() const { return OT_OCTREE; }
 
diff --git a/trunk/fcl/include/fcl/traversal/traversal_node_octree.h b/trunk/fcl/include/fcl/traversal/traversal_node_octree.h
index 366f25c5..9cc1d50d 100644
--- a/trunk/fcl/include/fcl/traversal/traversal_node_octree.h
+++ b/trunk/fcl/include/fcl/traversal/traversal_node_octree.h
@@ -104,36 +104,12 @@ public:
                            const CollisionRequest& request_,
                            CollisionResult& result_) const
   {
-    if(request_.enable_cost && request_.use_approximate_cost)
-    {
-      CollisionRequest request_no_cost(request_);
-      request_no_cost.enable_cost = false;
-      
-      crequest = &request_no_cost;
-      cresult = &result_;
-
-      OcTreeMeshIntersectRecurse(tree1, tree1->getRoot(), tree1->getRootBV(),
-                                 tree2, 0,
-                                 tf1, tf2);
-
-      Box box;
-      Transform3f box_tf;
-      constructBox(tree2->getBV(0).bv, tf2, box, box_tf);
-      
-      OcTreeShapeIntersect(tree1, box,
-                           tf1, box_tf,
-                           request_,
-                           result_);
-    }
-    else
-    {
-      crequest = &request_;
-      cresult = &result_;
+    crequest = &request_;
+    cresult = &result_;
 
-      OcTreeMeshIntersectRecurse(tree1, tree1->getRoot(), tree1->getRootBV(),
-                                 tree2, 0,
-                                 tf1, tf2);
-    }
+    OcTreeMeshIntersectRecurse(tree1, tree1->getRoot(), tree1->getRootBV(),
+                               tree2, 0,
+                               tf1, tf2);
   }
 
   /// @brief distance between octree and mesh
@@ -159,36 +135,12 @@ public:
                            CollisionResult& result_) const
   
   {
-    if(request_.enable_cost && request_.use_approximate_cost)
-    {
-      CollisionRequest request_no_cost(request_);
-      request_no_cost.enable_cost = false;
-      
-      crequest = &request_no_cost;
-      cresult = &result_;
-
-      OcTreeMeshIntersectRecurse(tree2, tree2->getRoot(), tree2->getRootBV(),
-                                 tree1, 0,
-                                 tf2, tf1);
-
-      Box box;
-      Transform3f box_tf;
-      constructBox(tree1->getBV(0).bv, tf1, box, box_tf);
-      
-      ShapeOcTreeIntersect(box, tree2, 
-                           box_tf, tf2,
-                           request_,
-                           result_);
-    }
-    else
-    {
-      crequest = &request_;
-      cresult = &result_;
+    crequest = &request_;
+    cresult = &result_;
 
-      OcTreeMeshIntersectRecurse(tree2, tree2->getRoot(), tree2->getRootBV(),
-                                 tree1, 0,
-                                 tf2, tf1);
-    }
+    OcTreeMeshIntersectRecurse(tree2, tree2->getRoot(), tree2->getRootBV(),
+                               tree1, 0,
+                               tf2, tf1);
   }
 
   /// @brief distance between mesh and octree
@@ -338,7 +290,7 @@ private:
     {
       OBB obb1;
       convertBV(bv1, tf1, obb1);
-      // if(obb1.overlap(obb2))
+      if(obb1.overlap(obb2))
       {
         Box box;
         Transform3f box_tf;
@@ -827,7 +779,92 @@ private:
                               const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& bv2,
                               const Transform3f& tf1, const Transform3f& tf2) const
   {
-    if(!root1->hasChildren() && !root2->hasChildren())
+    if(!root1 && !root2)
+    {
+      OBB obb1, obb2;
+      convertBV(bv1, tf1, obb1);
+      convertBV(bv2, tf2, obb2);
+
+      if(obb1.overlap(obb2))
+      {
+        Box box1, box2;
+        Transform3f box1_tf, box2_tf;
+        constructBox(bv1, tf1, box1, box1_tf);
+        constructBox(bv2, tf2, box2, box2_tf);
+        
+        AABB overlap_part;
+        AABB aabb1, aabb2;
+        computeBV<AABB, Box>(box1, box1_tf, aabb1);
+        computeBV<AABB, Box>(box2, box2_tf, aabb2);
+        aabb1.overlap(aabb2, overlap_part);
+        cresult->addCostSource(CostSource(overlap_part, tree1->getOccupancyThres() * tree2->getOccupancyThres()), crequest->num_max_cost_sources);
+      }
+
+      return false;
+    }
+    else if(!root1 && root2)
+    {
+      if(root2->hasChildren())
+      {
+        for(unsigned int i = 0; i < 8; ++i)
+        {
+          if(root2->childExists(i))
+          {
+            const OcTree::OcTreeNode* child = root2->getChild(i);
+            AABB child_bv;
+            computeChildBV(bv2, i, child_bv);
+            if(OcTreeIntersectRecurse(tree1, NULL, bv1, tree2, child, child_bv, tf1, tf2))
+              return true;
+          }
+          else 
+          {
+            AABB child_bv;
+            computeChildBV(bv2, i, child_bv);
+            if(OcTreeIntersectRecurse(tree1, NULL, bv1, tree2, NULL, child_bv, tf1, tf2))
+              return true;
+          }
+        }
+      }
+      else
+      {
+        if(OcTreeIntersectRecurse(tree1, NULL, bv1, tree2, NULL, bv2, tf1, tf2))
+          return true;
+      }
+      
+      return false;
+    }
+    else if(root1 && !root2)
+    {
+      if(root1->hasChildren())
+      {
+        for(unsigned int i = 0; i < 8; ++i)
+        {
+          if(root1->childExists(i))
+          {
+            const OcTree::OcTreeNode* child = root1->getChild(i);
+            AABB child_bv;
+            computeChildBV(bv1, i,  child_bv);
+            if(OcTreeIntersectRecurse(tree1, child, child_bv, tree2, NULL, bv2, tf1, tf2))
+              return true;
+          }
+          else
+          {
+            AABB child_bv;
+            computeChildBV(bv1, i, child_bv);
+            if(OcTreeIntersectRecurse(tree1, NULL, child_bv, tree2, NULL, bv2, tf1, tf2))
+              return true;
+          }
+        }
+      }
+      else
+      {
+        if(OcTreeIntersectRecurse(tree1, NULL, bv1, tree2, NULL, bv2, tf1, tf2))
+          return true;
+      }
+      
+      return false;
+    }
+    else if(!root1->hasChildren() && !root2->hasChildren())
     {
       if(tree1->isNodeOccupied(root1) && tree2->isNodeOccupied(root2)) // occupied area
       {
@@ -935,6 +972,16 @@ private:
                                     tf1, tf2))
             return true;
         }
+        else if(!tree2->isNodeFree(root2) && crequest->enable_cost)
+        {
+          AABB child_bv;
+          computeChildBV(bv1, i, child_bv);
+          
+          if(OcTreeIntersectRecurse(tree1, NULL, child_bv,
+                                    tree2, root2, bv2,
+                                    tf1, tf2))
+            return true;
+        }
       }
     }
     else
@@ -952,6 +999,16 @@ private:
                                     tf1, tf2))
             return true;
         }
+        else if(!tree1->isNodeFree(root1) && crequest->enable_cost)
+        {
+          AABB child_bv;
+          computeChildBV(bv2, i, child_bv);
+
+          if(OcTreeIntersectRecurse(tree1, root1, bv1,
+                                    tree2, NULL, child_bv,
+                                    tf1, tf2))
+            return true;
+        }
       }
     }
 
diff --git a/trunk/fcl/src/broadphase/broadphase_dynamic_AABB_tree.cpp b/trunk/fcl/src/broadphase/broadphase_dynamic_AABB_tree.cpp
index cb106a5d..1d10bd37 100644
--- a/trunk/fcl/src/broadphase/broadphase_dynamic_AABB_tree.cpp
+++ b/trunk/fcl/src/broadphase/broadphase_dynamic_AABB_tree.cpp
@@ -351,7 +351,42 @@ bool DynamicAABBTreeCollisionManager::selfDistanceRecurse(DynamicAABBNode* root,
 
 bool collisionRecurse_(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Transform3f& tf2, void* cdata, CollisionCallBack callback)
 {
-  if(root1->isLeaf() && !root2->hasChildren())
+  if(!root2)
+  {
+    if(root1->isLeaf())
+    {
+      CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
+
+      if(!obj1->isFree())
+      {
+        OBB obb1, obb2;
+        convertBV(root1->bv, Transform3f(), obb1);
+        convertBV(root2_bv, tf2, obb2);
+      
+        if(obb1.overlap(obb2))
+        {
+          Box* box = new Box();
+          Transform3f box_tf;
+          constructBox(root2_bv, tf2, *box, box_tf);
+
+          box->cost_density = tree2->getDefaultOccupancy();
+          
+          CollisionObject obj2(boost::shared_ptr<CollisionGeometry>(box), box_tf);
+          return callback(obj1, &obj2, cdata);
+        }
+      }
+    }
+    else
+    {
+      if(collisionRecurse_(root1->children[0], tree2, NULL, root2_bv, tf2, cdata, callback))
+        return true;
+      if(collisionRecurse_(root1->children[1], tree2, NULL, root2_bv, tf2, cdata, callback))
+        return true;
+    }
+    
+    return false;
+  }
+  else if(root1->isLeaf() && !root2->hasChildren())
   {
     CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
 
@@ -404,6 +439,13 @@ bool collisionRecurse_(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1,
         if(collisionRecurse_(root1, tree2, child, child_bv, tf2, cdata, callback))
           return true;
       }
+      else
+      {
+        AABB child_bv;
+        computeChildBV(root2_bv, i, child_bv);
+        if(collisionRecurse_(root1, tree2, NULL, child_bv, tf2, cdata, callback))
+          return true;
+      }
     }
   }
   return false;
@@ -411,7 +453,39 @@ bool collisionRecurse_(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1,
 
 bool collisionRecurse_(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Vec3f& tf2, void* cdata, CollisionCallBack callback)
 {
-  if(root1->isLeaf() && !root2->hasChildren())
+  if(!root2)
+  {
+    if(root1->isLeaf())
+    {
+      CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
+  
+      if(!obj1->isFree())
+      {      
+        const AABB& root2_bv_t = translate(root2_bv, tf2);
+        if(root1->bv.overlap(root2_bv_t))
+        {
+          Box* box = new Box();
+          Transform3f box_tf;
+          constructBox(root2_bv, tf2, *box, box_tf);
+
+          box->cost_density = tree2->getOccupancyThres(); // thresholds are 0, 1, so uncertain
+
+          CollisionObject obj2(boost::shared_ptr<CollisionGeometry>(box), box_tf);
+          return callback(obj1, &obj2, cdata);
+        }
+      }
+    }
+    else
+    {
+      if(collisionRecurse_(root1->children[0], tree2, NULL, root2_bv, tf2, cdata, callback))
+        return true;
+      if(collisionRecurse_(root1->children[1], tree2, NULL, root2_bv, tf2, cdata, callback))
+        return true;
+    }
+
+    return false;
+  }
+  else if(root1->isLeaf() && !root2->hasChildren())
   {
     CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
   
@@ -458,6 +532,13 @@ bool collisionRecurse_(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1,
         if(collisionRecurse_(root1, tree2, child, child_bv, tf2, cdata, callback))
           return true;
       }
+      else
+      {
+        AABB child_bv;
+        computeChildBV(root2_bv, i, child_bv);
+        if(collisionRecurse_(root1, tree2, NULL, child_bv, tf2, cdata, callback))
+          return true;
+      }
     }
   }
   return false;
diff --git a/trunk/fcl/src/broadphase/broadphase_dynamic_AABB_tree_array.cpp b/trunk/fcl/src/broadphase/broadphase_dynamic_AABB_tree_array.cpp
index 0d21379e..23374d92 100644
--- a/trunk/fcl/src/broadphase/broadphase_dynamic_AABB_tree_array.cpp
+++ b/trunk/fcl/src/broadphase/broadphase_dynamic_AABB_tree_array.cpp
@@ -362,7 +362,42 @@ bool DynamicAABBTreeCollisionManager_Array::selfDistanceRecurse(DynamicAABBNode*
 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)
 {
   DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* root1 = nodes1 + root1_id;
-  if(root1->isLeaf() && !root2->hasChildren())
+  if(!root2)
+  {
+    if(root1->isLeaf())
+    {
+      CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
+
+      if(!obj1->isFree())
+      {
+        OBB obb1, obb2;
+        convertBV(root1->bv, Transform3f(), obb1);
+        convertBV(root2_bv, tf2, obb2);
+      
+        if(obb1.overlap(obb2))
+        {
+          Box* box = new Box();
+          Transform3f box_tf;
+          constructBox(root2_bv, tf2, *box, box_tf);
+        
+          box->cost_density = tree2->getDefaultOccupancy();
+
+          CollisionObject obj2(boost::shared_ptr<CollisionGeometry>(box), box_tf);
+          return callback(obj1, &obj2, cdata);
+        }
+      }
+    }
+    else
+    {
+      if(collisionRecurse_(nodes1, root1->children[0], tree2, NULL, root2_bv, tf2, cdata, callback))
+        return true;
+      if(collisionRecurse_(nodes1, root1->children[1], tree2, NULL, root2_bv, tf2, cdata, callback))
+        return true;
+    }
+
+    return false;
+  }
+  else if(root1->isLeaf() && !root2->hasChildren())
   {
     CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
     if(!tree2->isNodeFree(root2) && !obj1->isFree())
@@ -414,6 +449,13 @@ bool collisionRecurse_(DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* n
         if(collisionRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback))
           return true;
       }
+      else
+      {
+        AABB child_bv;
+        computeChildBV(root2_bv, i, child_bv);
+        if(collisionRecurse_(nodes1, root1_id, tree2, NULL, child_bv, tf2, cdata, callback))
+          return true;
+      }
     }
   }
 
@@ -423,10 +465,42 @@ bool collisionRecurse_(DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* n
 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)
 {
   DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* root1 = nodes1 + root1_id;
-  if(root1->isLeaf() && !root2->hasChildren())
+  if(!root2)
+  {
+    if(root1->isLeaf())
+    {
+      CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
+
+      if(!obj1->isFree())
+      {
+        const AABB& root_bv_t = translate(root2_bv, tf2);
+        if(root1->bv.overlap(root_bv_t))
+        {
+          Box* box = new Box();
+          Transform3f box_tf;
+          constructBox(root2_bv, tf2, *box, box_tf);
+
+          box->cost_density = tree2->getDefaultOccupancy();
+
+          CollisionObject obj2(boost::shared_ptr<CollisionGeometry>(box), box_tf);
+          return callback(obj1, &obj2, cdata);
+        }
+      }
+    }
+    else
+    {
+      if(collisionRecurse_(nodes1, root1->children[0], tree2, NULL, root2_bv, tf2, cdata, callback))
+        return true;
+      if(collisionRecurse_(nodes1, root1->children[1], tree2, NULL, root2_bv, tf2, cdata, callback))
+        return true;
+    }
+
+    return false;
+  }
+  else if(root1->isLeaf() && !root2->hasChildren())
   {
     CollisionObject* obj1 = static_cast<CollisionObject*>(root1->data);
-    if(!tree2->isNodeFree(root2))
+    if(!tree2->isNodeFree(root2) && !obj1->isFree())
     {
       const AABB& root_bv_t = translate(root2_bv, tf2);
       if(root1->bv.overlap(root_bv_t))
@@ -469,6 +543,13 @@ bool collisionRecurse_(DynamicAABBTreeCollisionManager_Array::DynamicAABBNode* n
         if(collisionRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback))
           return true;
       }
+      else
+      {
+        AABB child_bv;
+        computeChildBV(root2_bv, i, child_bv);
+        if(collisionRecurse_(nodes1, root1_id, tree2, NULL, child_bv, tf2, cdata, callback))
+          return true;
+      }
     }
   }
 
diff --git a/trunk/fcl/src/collision_func_matrix.cpp b/trunk/fcl/src/collision_func_matrix.cpp
index 742ef826..1219eeb0 100644
--- a/trunk/fcl/src/collision_func_matrix.cpp
+++ b/trunk/fcl/src/collision_func_matrix.cpp
@@ -106,13 +106,40 @@ std::size_t OcTreeBVHCollide(const CollisionGeometry* o1, const Transform3f& tf1
 {
   if(request.isSatisfied(result)) return result.numContacts();
 
-  OcTreeMeshCollisionTraversalNode<T_BVH, NarrowPhaseSolver> node;
-  const OcTree* obj1 = static_cast<const OcTree*>(o1);
-  const BVHModel<T_BVH>* obj2 = static_cast<const BVHModel<T_BVH>*>(o2);
-  OcTreeSolver<NarrowPhaseSolver> otsolver(nsolver);
+  if(request.enable_cost && request.use_approximate_cost)
+  {
+    CollisionRequest no_cost_request(request); // request remove cost to avoid the exact but expensive cost computation between mesh and octree
+    no_cost_request.enable_cost = false; // disable cost computation
 
-  initialize(node, *obj1, tf1, *obj2, tf2, &otsolver, request, result);
-  collide(&node);
+    OcTreeMeshCollisionTraversalNode<T_BVH, NarrowPhaseSolver> node;
+    const OcTree* obj1 = static_cast<const OcTree*>(o1);
+    const BVHModel<T_BVH>* obj2 = static_cast<const BVHModel<T_BVH>*>(o2);
+    OcTreeSolver<NarrowPhaseSolver> otsolver(nsolver);
+
+    initialize(node, *obj1, tf1, *obj2, tf2, &otsolver, no_cost_request, result);
+    collide(&node);
+
+    Box box;
+    Transform3f box_tf;
+    constructBox(obj2->getBV(0).bv, tf2, box, box_tf); // compute the box for BVH's root node
+
+    box.cost_density = obj2->cost_density;
+    box.threshold_occupied = obj2->threshold_occupied;
+    box.threshold_free = obj2->threshold_free;
+
+    CollisionRequest only_cost_request(result.numContacts(), false, request.num_max_cost_sources, true, false); // additional cost request, no contacts
+    OcTreeShapeCollide<Box, NarrowPhaseSolver>(o1, tf1, &box, box_tf, nsolver, only_cost_request, result);
+  }
+  else
+  {
+    OcTreeMeshCollisionTraversalNode<T_BVH, NarrowPhaseSolver> node;
+    const OcTree* obj1 = static_cast<const OcTree*>(o1);
+    const BVHModel<T_BVH>* obj2 = static_cast<const BVHModel<T_BVH>*>(o2);
+    OcTreeSolver<NarrowPhaseSolver> otsolver(nsolver);
+
+    initialize(node, *obj1, tf1, *obj2, tf2, &otsolver, request, result);
+    collide(&node);
+  }
   
   return result.numContacts();
 }
@@ -123,14 +150,41 @@ std::size_t BVHOcTreeCollide(const CollisionGeometry* o1, const Transform3f& tf1
                              const CollisionRequest& request, CollisionResult& result)
 {
   if(request.isSatisfied(result)) return result.numContacts();
+ 
+  if(request.enable_cost && request.use_approximate_cost)
+  {
+    CollisionRequest no_cost_request(request); // request remove cost to avoid the exact but expensive cost computation between mesh and octree
+    no_cost_request.enable_cost = false; // disable cost computation
 
-  MeshOcTreeCollisionTraversalNode<T_BVH, NarrowPhaseSolver> node;
-  const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>*>(o1);
-  const OcTree* obj2 = static_cast<const OcTree*>(o2);
-  OcTreeSolver<NarrowPhaseSolver> otsolver(nsolver);
+    MeshOcTreeCollisionTraversalNode<T_BVH, NarrowPhaseSolver> node;
+    const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>*>(o1);
+    const OcTree* obj2 = static_cast<const OcTree*>(o2);
+    OcTreeSolver<NarrowPhaseSolver> otsolver(nsolver);
 
-  initialize(node, *obj1, tf1, *obj2, tf2, &otsolver, request, result);
-  collide(&node);
+    initialize(node, *obj1, tf1, *obj2, tf2, &otsolver, no_cost_request, result);
+    collide(&node);
+
+    Box box;
+    Transform3f box_tf;
+    constructBox(obj1->getBV(0).bv, tf1, box, box_tf);
+
+    box.cost_density = obj1->cost_density;
+    box.threshold_occupied = obj1->threshold_occupied;
+    box.threshold_free = obj1->threshold_free;
+
+    CollisionRequest only_cost_request(result.numContacts(), false, request.num_max_cost_sources, true, false);
+    ShapeOcTreeCollide<Box, NarrowPhaseSolver>(&box, box_tf, o2, tf2, nsolver, only_cost_request, result);
+  }
+  else
+  {
+    MeshOcTreeCollisionTraversalNode<T_BVH, NarrowPhaseSolver> node;
+    const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>*>(o1);
+    const OcTree* obj2 = static_cast<const OcTree*>(o2);
+    OcTreeSolver<NarrowPhaseSolver> otsolver(nsolver);
+
+    initialize(node, *obj1, tf1, *obj2, tf2, &otsolver, request, result);
+    collide(&node);
+  }
   
   return result.numContacts();
 }
@@ -162,19 +216,98 @@ struct BVHShapeCollider
   {
     if(request.isSatisfied(result)) return result.numContacts();
 
-    MeshShapeCollisionTraversalNode<T_BVH, T_SH, NarrowPhaseSolver> node;
+    if(request.enable_cost && request.use_approximate_cost)
+    {
+      CollisionRequest no_cost_request(request);
+      no_cost_request.enable_cost = false;
+      
+      MeshShapeCollisionTraversalNode<T_BVH, T_SH, NarrowPhaseSolver> node;
+      const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>* >(o1);
+      BVHModel<T_BVH>* obj1_tmp = new BVHModel<T_BVH>(*obj1);
+      Transform3f tf1_tmp = tf1;
+      const T_SH* obj2 = static_cast<const T_SH*>(o2);
+
+      initialize(node, *obj1_tmp, tf1_tmp, *obj2, tf2, nsolver, no_cost_request, result);
+      fcl::collide(&node);
+
+      delete obj1_tmp;
+
+      Box box;
+      Transform3f box_tf;
+      constructBox(obj1->getBV(0).bv, tf1, box, box_tf);
+
+      box.cost_density = obj1->cost_density;
+      box.threshold_occupied = obj1->threshold_occupied;
+      box.threshold_free = obj1->threshold_free;
+      
+      CollisionRequest only_cost_request(result.numContacts(), false, request.num_max_cost_sources, true, false);
+      ShapeShapeCollide<Box, T_SH>(&box, box_tf, o2, tf2, nsolver, only_cost_request, result);
+    }
+    else
+    {
+      MeshShapeCollisionTraversalNode<T_BVH, T_SH, NarrowPhaseSolver> node;
+      const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>* >(o1);
+      BVHModel<T_BVH>* obj1_tmp = new BVHModel<T_BVH>(*obj1);
+      Transform3f tf1_tmp = tf1;
+      const T_SH* obj2 = static_cast<const T_SH*>(o2);
+
+      initialize(node, *obj1_tmp, tf1_tmp, *obj2, tf2, nsolver, request, result);
+      fcl::collide(&node);
+
+      delete obj1_tmp;
+    }
+
+    return result.numContacts();
+  }
+};
+
+namespace details
+{
+
+template<typename OrientMeshShapeCollisionTraveralNode, typename T_BVH, typename T_SH, typename NarrowPhaseSolver>
+std::size_t orientedBVHShapeCollide(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, 
+                                    const NarrowPhaseSolver* nsolver,
+                                    const CollisionRequest& request, CollisionResult& result)
+{
+  if(request.isSatisfied(result)) return result.numContacts();
+
+  if(request.enable_cost && request.use_approximate_cost)
+  {
+    CollisionRequest no_cost_request(request);
+    no_cost_request.enable_cost = false;
+
+    OrientMeshShapeCollisionTraveralNode node;
     const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>* >(o1);
-    BVHModel<T_BVH>* obj1_tmp = new BVHModel<T_BVH>(*obj1);
-    Transform3f tf1_tmp = tf1;
     const T_SH* obj2 = static_cast<const T_SH*>(o2);
 
-    initialize(node, *obj1_tmp, tf1_tmp, *obj2, tf2, nsolver, request, result);
+    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, no_cost_request, result);
     fcl::collide(&node);
+   
+    Box box;
+    Transform3f box_tf;
+    constructBox(obj1->getBV(0).bv, tf1, box, box_tf);
+
+    box.cost_density = obj1->cost_density;
+    box.threshold_occupied = obj1->threshold_occupied;
+    box.threshold_free = obj1->threshold_free;
+      
+    CollisionRequest only_cost_request(result.numContacts(), false, request.num_max_cost_sources, true, false);
+    ShapeShapeCollide<Box, T_SH>(&box, box_tf, o2, tf2, nsolver, only_cost_request, result);     
+  }
+  else
+  {
+    OrientMeshShapeCollisionTraveralNode node;
+    const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>* >(o1);
+    const T_SH* obj2 = static_cast<const T_SH*>(o2);
 
-    delete obj1_tmp;
-    return result.numContacts();
+    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
+    fcl::collide(&node);
   }
-};
+
+  return result.numContacts();
+}
+
+}
 
 
 template<typename T_SH, typename NarrowPhaseSolver>
@@ -184,16 +317,7 @@ struct BVHShapeCollider<OBB, T_SH, NarrowPhaseSolver>
                              const NarrowPhaseSolver* nsolver,
                              const CollisionRequest& request, CollisionResult& result)
   {
-    if(request.isSatisfied(result)) return result.numContacts();
-
-    MeshShapeCollisionTraversalNodeOBB<T_SH, NarrowPhaseSolver> node;
-    const BVHModel<OBB>* obj1 = static_cast<const BVHModel<OBB>* >(o1);
-    const T_SH* obj2 = static_cast<const T_SH*>(o2);
-
-    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
-    fcl::collide(&node);
-
-    return result.numContacts();
+    return details::orientedBVHShapeCollide<MeshShapeCollisionTraversalNodeOBB<T_SH, NarrowPhaseSolver>, OBB, T_SH, NarrowPhaseSolver>(o1, tf1, o2, tf2, nsolver, request, result);
   } 
 };
 
@@ -205,16 +329,7 @@ struct BVHShapeCollider<RSS, T_SH, NarrowPhaseSolver>
                              const NarrowPhaseSolver* nsolver,
                              const CollisionRequest& request, CollisionResult& result)
   {
-    if(request.isSatisfied(result)) return result.numContacts();
-
-    MeshShapeCollisionTraversalNodeRSS<T_SH, NarrowPhaseSolver> node;
-    const BVHModel<RSS>* obj1 = static_cast<const BVHModel<RSS>* >(o1);
-    const T_SH* obj2 = static_cast<const T_SH*>(o2);
-
-    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
-    fcl::collide(&node);
-
-    return result.numContacts();
+    return details::orientedBVHShapeCollide<MeshShapeCollisionTraversalNodeRSS<T_SH, NarrowPhaseSolver>, RSS, T_SH, NarrowPhaseSolver>(o1, tf1, o2, tf2, nsolver, request, result);
   } 
 };
 
@@ -226,16 +341,7 @@ struct BVHShapeCollider<kIOS, T_SH, NarrowPhaseSolver>
                              const NarrowPhaseSolver* nsolver,
                              const CollisionRequest& request, CollisionResult& result)
   {
-    if(request.isSatisfied(result)) return result.numContacts();
-
-    MeshShapeCollisionTraversalNodekIOS<T_SH, NarrowPhaseSolver> node;
-    const BVHModel<kIOS>* obj1 = static_cast<const BVHModel<kIOS>* >(o1);
-    const T_SH* obj2 = static_cast<const T_SH*>(o2);
-
-    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
-    fcl::collide(&node);
-
-    return result.numContacts();
+    return details::orientedBVHShapeCollide<MeshShapeCollisionTraversalNodekIOS<T_SH, NarrowPhaseSolver>, kIOS, T_SH, NarrowPhaseSolver>(o1, tf1, o2, tf2, nsolver, request, result);
   } 
 };
 
@@ -247,16 +353,7 @@ struct BVHShapeCollider<OBBRSS, T_SH, NarrowPhaseSolver>
                              const NarrowPhaseSolver* nsolver,
                              const CollisionRequest& request, CollisionResult& result)
   {
-    if(request.isSatisfied(result)) return result.numContacts();
-
-    MeshShapeCollisionTraversalNodeOBBRSS<T_SH, NarrowPhaseSolver> node;
-    const BVHModel<OBBRSS>* obj1 = static_cast<const BVHModel<OBBRSS>* >(o1);
-    const T_SH* obj2 = static_cast<const T_SH*>(o2);
-
-    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
-    fcl::collide(&node);
-
-    return result.numContacts();
+    return details::orientedBVHShapeCollide<MeshShapeCollisionTraversalNodeOBBRSS<T_SH, NarrowPhaseSolver>, OBBRSS, T_SH, NarrowPhaseSolver>(o1, tf1, o2, tf2, nsolver, request, result);
   } 
 };
 
@@ -283,14 +380,16 @@ std::size_t BVHCollide(const CollisionGeometry* o1, const Transform3f& tf1, cons
   return result.numContacts();
 }
 
-template<>
-std::size_t BVHCollide<OBB>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const CollisionRequest& request, CollisionResult& result)
+namespace details
+{
+template<typename OrientedMeshCollisionTraversalNode, typename T_BVH>
+std::size_t orientedMeshCollide(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const CollisionRequest& request, CollisionResult& result)
 {
   if(request.isSatisfied(result)) return result.numContacts();
 
-  MeshCollisionTraversalNodeOBB node;
-  const BVHModel<OBB>* obj1 = static_cast<const BVHModel<OBB>* >(o1);
-  const BVHModel<OBB>* obj2 = static_cast<const BVHModel<OBB>* >(o2);
+  OrientedMeshCollisionTraversalNode node;
+  const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>* >(o1);
+  const BVHModel<T_BVH>* obj2 = static_cast<const BVHModel<T_BVH>* >(o2);
 
   initialize(node, *obj1, tf1, *obj2, tf2, request, result);
   collide(&node);
@@ -298,35 +397,25 @@ std::size_t BVHCollide<OBB>(const CollisionGeometry* o1, const Transform3f& tf1,
   return result.numContacts();
 }
 
+}
+
 template<>
-std::size_t BVHCollide<OBBRSS>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const CollisionRequest& request, CollisionResult& result)
+std::size_t BVHCollide<OBB>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const CollisionRequest& request, CollisionResult& result)
 {
-  if(request.isSatisfied(result)) return result.numContacts();
-
-  MeshCollisionTraversalNodeOBBRSS node;
-  const BVHModel<OBBRSS>* obj1 = static_cast<const BVHModel<OBBRSS>* >(o1);
-  const BVHModel<OBBRSS>* obj2 = static_cast<const BVHModel<OBBRSS>* >(o2);
-
-  initialize(node, *obj1, tf1, *obj2, tf2, request, result);
-  collide(&node);
+  return details::orientedMeshCollide<MeshCollisionTraversalNodeOBB, OBB>(o1, tf1, o2, tf2, request, result);
+}
 
-  return result.numContacts();
+template<>
+std::size_t BVHCollide<OBBRSS>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const CollisionRequest& request, CollisionResult& result)
+{
+  return details::orientedMeshCollide<MeshCollisionTraversalNodeOBBRSS, OBBRSS>(o1, tf1, o2, tf2, request, result);
 }
 
 
 template<>
 std::size_t BVHCollide<kIOS>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const CollisionRequest& request, CollisionResult& result)
 {
-  if(request.isSatisfied(result)) return result.numContacts();
-
-  MeshCollisionTraversalNodekIOS node;
-  const BVHModel<kIOS>* obj1 = static_cast<const BVHModel<kIOS>* >(o1);
-  const BVHModel<kIOS>* obj2 = static_cast<const BVHModel<kIOS>* >(o2);
-
-  initialize(node, *obj1, tf1, *obj2, tf2, request, result);
-  collide(&node);
-
-  return result.numContacts();
+  return details::orientedMeshCollide<MeshCollisionTraversalNodekIOS, kIOS>(o1, tf1, o2, tf2, request, result);
 }
 
 
diff --git a/trunk/fcl/src/distance_func_matrix.cpp b/trunk/fcl/src/distance_func_matrix.cpp
index d5a55095..b85401b2 100644
--- a/trunk/fcl/src/distance_func_matrix.cpp
+++ b/trunk/fcl/src/distance_func_matrix.cpp
@@ -161,21 +161,33 @@ struct BVHShapeDistancer
   }
 };
 
+namespace details
+{
+
+template<typename OrientedMeshShapeDistanceTraversalNode, typename T_BVH, typename T_SH, typename NarrowPhaseSolver>
+FCL_REAL orientedBVHShapeDistance(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const NarrowPhaseSolver* nsolver,
+                                  const DistanceRequest& request, DistanceResult& result)
+{
+  if(request.isSatisfied(result)) return result.min_distance;
+  OrientedMeshShapeDistanceTraversalNode node;
+  const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>* >(o1);
+  const T_SH* obj2 = static_cast<const T_SH*>(o2);
+
+  initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
+  fcl::distance(&node);
+
+  return result.min_distance;  
+}
+
+}
+
 template<typename T_SH, typename NarrowPhaseSolver>
 struct BVHShapeDistancer<RSS, T_SH, NarrowPhaseSolver>
 {
   static FCL_REAL distance(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const NarrowPhaseSolver* nsolver,
                            const DistanceRequest& request, DistanceResult& result)
   {
-    if(request.isSatisfied(result)) return result.min_distance;
-    MeshShapeDistanceTraversalNodeRSS<T_SH, NarrowPhaseSolver> node;
-    const BVHModel<RSS>* obj1 = static_cast<const BVHModel<RSS>* >(o1);
-    const T_SH* obj2 = static_cast<const T_SH*>(o2);
-
-    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
-    fcl::distance(&node);
-
-    return result.min_distance;
+    return details::orientedBVHShapeDistance<MeshShapeDistanceTraversalNodeRSS<T_SH, NarrowPhaseSolver>, RSS, T_SH, NarrowPhaseSolver>(o1, tf1, o2, tf2, nsolver, request, result);
   }
 };
 
@@ -186,15 +198,7 @@ struct BVHShapeDistancer<kIOS, T_SH, NarrowPhaseSolver>
   static FCL_REAL distance(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const NarrowPhaseSolver* nsolver,
                        const DistanceRequest& request, DistanceResult& result)
   {
-    if(request.isSatisfied(result)) return result.min_distance;
-    MeshShapeDistanceTraversalNodekIOS<T_SH, NarrowPhaseSolver> node;
-    const BVHModel<kIOS>* obj1 = static_cast<const BVHModel<kIOS>* >(o1);
-    const T_SH* obj2 = static_cast<const T_SH*>(o2);
-
-    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
-    fcl::distance(&node);
-
-    return result.min_distance;
+    return details::orientedBVHShapeDistance<MeshShapeDistanceTraversalNodekIOS<T_SH, NarrowPhaseSolver>, kIOS, T_SH, NarrowPhaseSolver>(o1, tf1, o2, tf2, nsolver, request, result);
   }
 };
 
@@ -204,15 +208,7 @@ struct BVHShapeDistancer<OBBRSS, T_SH, NarrowPhaseSolver>
   static FCL_REAL distance(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2, const NarrowPhaseSolver* nsolver,
                            const DistanceRequest& request, DistanceResult& result)
   {
-    if(request.isSatisfied(result)) return result.min_distance;
-    MeshShapeDistanceTraversalNodeOBBRSS<T_SH, NarrowPhaseSolver> node;
-    const BVHModel<OBBRSS>* obj1 = static_cast<const BVHModel<OBBRSS>* >(o1);
-    const T_SH* obj2 = static_cast<const T_SH*>(o2);
-
-    initialize(node, *obj1, tf1, *obj2, tf2, nsolver, request, result);
-    fcl::distance(&node);
-
-    return result.min_distance;
+    return details::orientedBVHShapeDistance<MeshShapeDistanceTraversalNodeOBBRSS<T_SH, NarrowPhaseSolver>, OBBRSS, T_SH, NarrowPhaseSolver>(o1, tf1, o2, tf2, nsolver, request, result);
   }
 };
 
@@ -236,14 +232,16 @@ FCL_REAL BVHDistance(const CollisionGeometry* o1, const Transform3f& tf1, const
   return result.min_distance;
 }
 
-template<>
-FCL_REAL BVHDistance<RSS>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2,
-                          const DistanceRequest& request, DistanceResult& result)
+namespace details
+{
+template<typename OrientedMeshDistanceTraversalNode, typename T_BVH>
+FCL_REAL orientedMeshDistance(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2,
+                              const DistanceRequest& request, DistanceResult& result)
 {
   if(request.isSatisfied(result)) return result.min_distance;
-  MeshDistanceTraversalNodeRSS node;
-  const BVHModel<RSS>* obj1 = static_cast<const BVHModel<RSS>* >(o1);
-  const BVHModel<RSS>* obj2 = static_cast<const BVHModel<RSS>* >(o2);
+  OrientedMeshDistanceTraversalNode node;
+  const BVHModel<T_BVH>* obj1 = static_cast<const BVHModel<T_BVH>* >(o1);
+  const BVHModel<T_BVH>* obj2 = static_cast<const BVHModel<T_BVH>* >(o2);
 
   initialize(node, *obj1, tf1, *obj2, tf2, request, result);
   distance(&node);
@@ -251,19 +249,20 @@ FCL_REAL BVHDistance<RSS>(const CollisionGeometry* o1, const Transform3f& tf1, c
   return result.min_distance;
 }
 
+}
+
+template<>
+FCL_REAL BVHDistance<RSS>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2,
+                          const DistanceRequest& request, DistanceResult& result)
+{
+  return details::orientedMeshDistance<MeshDistanceTraversalNodeRSS, RSS>(o1, tf1, o2, tf2, request, result);
+}
+
 template<>
 FCL_REAL BVHDistance<kIOS>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2,
                            const DistanceRequest& request, DistanceResult& result)
 {
-  if(request.isSatisfied(result)) return result.min_distance;
-  MeshDistanceTraversalNodekIOS node;
-  const BVHModel<kIOS>* obj1 = static_cast<const BVHModel<kIOS>* >(o1);
-  const BVHModel<kIOS>* obj2 = static_cast<const BVHModel<kIOS>* >(o2);
-
-  initialize(node, *obj1, tf1, *obj2, tf2, request, result);
-  distance(&node);
-
-  return result.min_distance;
+  return details::orientedMeshDistance<MeshDistanceTraversalNodekIOS, kIOS>(o1, tf1, o2, tf2, request, result);
 }
 
 
@@ -271,15 +270,7 @@ template<>
 FCL_REAL BVHDistance<OBBRSS>(const CollisionGeometry* o1, const Transform3f& tf1, const CollisionGeometry* o2, const Transform3f& tf2,
                              const DistanceRequest& request, DistanceResult& result)
 {
-  if(request.isSatisfied(result)) return result.min_distance;
-  MeshDistanceTraversalNodeOBBRSS node;
-  const BVHModel<OBBRSS>* obj1 = static_cast<const BVHModel<OBBRSS>* >(o1);
-  const BVHModel<OBBRSS>* obj2 = static_cast<const BVHModel<OBBRSS>* >(o2);
-
-  initialize(node, *obj1, tf1, *obj2, tf2, request, result);
-  distance(&node);
-
-  return result.min_distance;
+  return details::orientedMeshDistance<MeshDistanceTraversalNodeOBBRSS, OBBRSS>(o1, tf1, o2, tf2, request, result);
 }
 
 
-- 
GitLab