diff --git a/trunk/fcl/include/fcl/BV.h b/trunk/fcl/include/fcl/BV.h index 9b84c478d82ac77c35603aacb89a920db8f9427a..94361a952aa83690aba8207d4764ac5312d567da 100644 --- a/trunk/fcl/include/fcl/BV.h +++ b/trunk/fcl/include/fcl/BV.h @@ -61,22 +61,6 @@ private: } }; -template<typename BV1> -class Converter<BV1, AABB> -{ -public: - static void convert(const BV1& bv1, const SimpleTransform& tf1, AABB& bv2) - { - const Vec3f& center = bv1.center(); - FCL_REAL r = Vec3f(bv1.width(), bv1.height(), bv1.depth()).length() * 0.5; - Vec3f delta(r, r, r); - Vec3f center2 = tf1.transform(center); - bv2.min_ = center2 - delta; - bv2.max_ = center2 + delta; - } -}; - - template<> class Converter<AABB, AABB> { @@ -107,6 +91,72 @@ public: } }; +template<> +class Converter<OBB, OBB> +{ +public: + static void convert(const OBB& bv1, const SimpleTransform& tf1, OBB& bv2) + { + bv2.extent = bv1.extent; + bv2.To = tf1.transform(bv1.To); + bv2.axis[0] = tf1.transform(bv1.axis[0]); + bv2.axis[1] = tf1.transform(bv1.axis[1]); + bv2.axis[2] = tf1.transform(bv1.axis[2]); + } +}; + +template<> +class Converter<OBBRSS, OBB> +{ +public: + static void convert(const OBBRSS& bv1, const SimpleTransform& tf1, OBB& bv2) + { + Converter<OBB, OBB>::convert(bv1.obb, tf1, bv2); + } +}; + +template<> +class Converter<RSS, OBB> +{ +public: + static void convert(const RSS& bv1, const SimpleTransform& tf1, OBB& bv2) + { + bv2.extent = Vec3f(bv1.l[0] * 0.5 + bv1.r, bv1.l[1] * 0.5 + bv1.r, bv1.r); + bv2.To = tf1.transform(bv1.Tr); + bv2.axis[0] = tf1.transform(bv1.axis[0]); + bv2.axis[1] = tf1.transform(bv1.axis[1]); + bv2.axis[2] = tf1.transform(bv1.axis[2]); + } +}; + + +template<typename BV1> +class Converter<BV1, AABB> +{ +public: + static void convert(const BV1& bv1, const SimpleTransform& tf1, AABB& bv2) + { + const Vec3f& center = bv1.center(); + FCL_REAL r = Vec3f(bv1.width(), bv1.height(), bv1.depth()).length() * 0.5; + Vec3f delta(r, r, r); + Vec3f center2 = tf1.transform(center); + bv2.min_ = center2 - delta; + bv2.max_ = center2 + delta; + } +}; + +template<typename BV1> +class Converter<BV1, OBB> +{ +public: + static void convert(const BV1& bv1, const SimpleTransform& tf1, OBB& bv2) + { + AABB bv; + Converter<BV1, AABB>::convert(bv1, SimpleTransform(), bv); + Converter<AABB, OBB>::convert(bv, tf1, bv2); + } +}; + diff --git a/trunk/fcl/include/fcl/BV/AABB.h b/trunk/fcl/include/fcl/BV/AABB.h index 248d2c1364d2f918066b9e2617bb4f5f2846a9cd..4370118fd6f32c69ac5d17715f55b62fd6e4e9ff 100644 --- a/trunk/fcl/include/fcl/BV/AABB.h +++ b/trunk/fcl/include/fcl/BV/AABB.h @@ -208,11 +208,17 @@ public: min_ = min_ * ratio - core.min_; max_ = max_ * ratio - core.max_; return *this; - } - - + } }; +static inline AABB translate(const AABB& aabb, const Vec3f& t) +{ + AABB res(aabb); + res.min_ += t; + res.max_ += t; + return res; +} + } #endif diff --git a/trunk/fcl/include/fcl/octree.h b/trunk/fcl/include/fcl/octree.h index e598dbe2a332c5c5fc584778ef8966b8f42cdcaf..a88813b68a53ee955ed12a36f94f96dedca42c0b 100644 --- a/trunk/fcl/include/fcl/octree.h +++ b/trunk/fcl/include/fcl/octree.h @@ -64,6 +64,13 @@ public: OcTree(FCL_REAL resolution) : tree(boost::shared_ptr<octomap::OcTree>(new octomap::OcTree(resolution))) {} OcTree(const boost::shared_ptr<octomap::OcTree>& tree_) : tree(tree_) {} + void computeLocalAABB() + { + aabb_local = getRootBV(); + aabb_center = aabb_local.center(); + aabb_radius = (aabb_local.min_ - aabb_center).length(); + } + inline AABB getRootBV() const { FCL_REAL delta = (1 << tree->getTreeDepth()) * tree->getResolution() / 2; @@ -109,11 +116,6 @@ public: OBJECT_TYPE getObjectType() const { return OT_OCTREE; } NODE_TYPE getNodeType() const { return GEOM_OCTREE; } - void computeLocalAABB() - { - aabb_center = Vec3f(); - aabb_radius = (1 << tree->getTreeDepth()) * tree->getResolution() / 2; - } }; static inline void computeChildBV(const AABB& root_bv, unsigned int i, AABB& child_bv) diff --git a/trunk/fcl/include/fcl/traversal_node_octree.h b/trunk/fcl/include/fcl/traversal_node_octree.h index 41368bc5dc64be7c36d381110a1eeadac79b7688..a6dc192235242f987fcf2b4f851ae9b7d5016cd2 100644 --- a/trunk/fcl/include/fcl/traversal_node_octree.h +++ b/trunk/fcl/include/fcl/traversal_node_octree.h @@ -227,11 +227,10 @@ public: AABB bv2; computeBV<AABB>(s, SimpleTransform(), bv2); - Box box2; - SimpleTransform box2_tf; - constructBox(bv2, tf2, box2, box2_tf); + OBB obb2; + convertBV(bv2, tf2, obb2); OcTreeShapeIntersectRecurse(tree, tree->getRoot(), tree->getRootBV(), - s, box2, box2_tf, + s, obb2, tf1, tf2, pairs); } @@ -248,11 +247,10 @@ public: AABB bv1; computeBV<AABB>(s, SimpleTransform(), bv1); - Box box1; - SimpleTransform box1_tf; - constructBox(bv1, tf1, box1, box1_tf); + OBB obb1; + convertBV(bv1, tf1, obb1); OcTreeShapeIntersectRecurse(tree, tree->getRoot(), tree->getRootBV(), - s, box1, box1_tf, + s, obb1, tf2, tf1, pairs); } @@ -260,16 +258,12 @@ public: FCL_REAL OcTreeShapeDistance(const OcTree* tree, const S& s, const SimpleTransform& tf1, const SimpleTransform& tf2) const { - AABB bv2; - computeBV<AABB>(s, SimpleTransform(), bv2); - Box box2; - SimpleTransform box2_tf; - constructBox(bv2, tf2, box2, box2_tf); - + AABB aabb2; + computeBV<AABB>(s, tf2, aabb2); FCL_REAL min_dist = std::numeric_limits<FCL_REAL>::max(); OcTreeShapeDistanceRecurse(tree, tree->getRoot(), tree->getRootBV(), - s, box2, box2_tf, + s, aabb2, tf1, tf2, min_dist); return min_dist; } @@ -278,16 +272,12 @@ public: FCL_REAL ShapeOcTreeDistance(const S& s, const OcTree* tree, const SimpleTransform& tf1, const SimpleTransform& tf2) const { - AABB bv1; - computeBV<AABB>(s, SimpleTransform(), bv1); - Box box1; - SimpleTransform box1_tf; - constructBox(bv1, tf1, box1, box1_tf); - + AABB aabb1; + computeBV<AABB>(s, tf1, aabb1); FCL_REAL min_dist = std::numeric_limits<FCL_REAL>::max(); OcTreeShapeDistanceRecurse(tree, tree->getRoot(), tree->getRootBV(), - s, box1, box1_tf, + s, aabb1, tf2, tf1, min_dist); return min_dist; @@ -297,7 +287,7 @@ public: private: template<typename S> bool OcTreeShapeDistanceRecurse(const OcTree* tree1, const OcTree::OcTreeNode* root1, const AABB& bv1, - const S& s, const Box& box2, const SimpleTransform& box2_tf, + const S& s, const AABB& aabb2, const SimpleTransform& tf1, const SimpleTransform& tf2, FCL_REAL& min_dist) const { @@ -308,7 +298,7 @@ private: Box box; SimpleTransform box_tf; constructBox(bv1, tf1, box, box_tf); - + FCL_REAL dist; solver->shapeDistance(box, box_tf, s, tf2, &dist); if(dist < min_dist) min_dist = dist; @@ -328,15 +318,13 @@ private: const OcTree::OcTreeNode* child = root1->getChild(i); AABB child_bv; computeChildBV(bv1, i, child_bv); - - Box box1; - SimpleTransform box1_tf; - constructBox(child_bv, tf1, box1, box1_tf); - FCL_REAL d; - solver->shapeDistance(box1, box1_tf, box2, box2_tf, &d); + + AABB aabb1; + convertBV(child_bv, tf1, aabb1); + FCL_REAL d = aabb1.distance(aabb2); if(d < min_dist) { - if(OcTreeShapeDistanceRecurse(tree1, child, child_bv, s, box2, box2_tf, tf1, tf2, min_dist)) + if(OcTreeShapeDistanceRecurse(tree1, child, child_bv, s, aabb2, tf1, tf2, min_dist)) return true; } } @@ -347,7 +335,7 @@ private: template<typename S> bool OcTreeShapeIntersectRecurse(const OcTree* tree1, const OcTree::OcTreeNode* root1, const AABB& bv1, - const S& s, const Box& box2, const SimpleTransform& box2_tf, + const S& s, const OBB& obb2, const SimpleTransform& tf1, const SimpleTransform& tf2, std::vector<OcTreeShapeCollisionPair>& pairs) const { @@ -355,38 +343,40 @@ private: { if(tree1->isNodeOccupied(root1)) { - Box box; - SimpleTransform box_tf; - constructBox(bv1, tf1, box, box_tf); - - if(!enable_contact) - { - if(solver->shapeIntersect(box, box_tf, s, tf2, NULL, NULL, NULL)) - pairs.push_back(OcTreeShapeCollisionPair(root1)); - } - else + OBB obb1; + convertBV(bv1, tf1, obb1); + if(obb1.overlap(obb2)) { - Vec3f contact; - FCL_REAL depth; - Vec3f normal; + Box box; + SimpleTransform box_tf; + constructBox(bv1, tf1, box, box_tf); - if(solver->shapeIntersect(box, box_tf, s, tf2, &contact, &depth, &normal)) - pairs.push_back(OcTreeShapeCollisionPair(root1, contact, normal, depth)); - } + if(!enable_contact) + { + if(solver->shapeIntersect(box, box_tf, s, tf2, NULL, NULL, NULL)) + pairs.push_back(OcTreeShapeCollisionPair(root1)); + } + else + { + Vec3f contact; + FCL_REAL depth; + Vec3f normal; + + if(solver->shapeIntersect(box, box_tf, s, tf2, &contact, &depth, &normal)) + pairs.push_back(OcTreeShapeCollisionPair(root1, contact, normal, depth)); + } - return ((pairs.size() >= num_max_contacts) && !exhaustive); + return ((pairs.size() >= num_max_contacts) && !exhaustive); + } + else return false; } else return false; } - - Box box1; - SimpleTransform box1_tf; - - constructBox(bv1, tf1, box1, box1_tf); - - if(!tree1->isNodeOccupied(root1) || !solver->shapeIntersect(box1, box1_tf, box2, box2_tf, NULL, NULL, NULL)) return false; + OBB obb1; + convertBV(bv1, tf1, obb1); + if(!tree1->isNodeOccupied(root1) || !obb1.overlap(obb2)) return false; for(unsigned int i = 0; i < 8; ++i) { @@ -396,7 +386,7 @@ private: AABB child_bv; computeChildBV(bv1, i, child_bv); - if(OcTreeShapeIntersectRecurse(tree1, child, child_bv, s, box2, box2_tf, tf1, tf2, pairs)) + if(OcTreeShapeIntersectRecurse(tree1, child, child_bv, s, obb2, tf1, tf2, pairs)) return true; } } @@ -444,14 +434,13 @@ private: AABB child_bv; computeChildBV(bv1, i, child_bv); - Box box1, box2; - SimpleTransform box1_tf, box2_tf; - constructBox(child_bv, tf1, box1, box1_tf); - constructBox(tree2->getBV(root2).bv, tf2, box2, box2_tf); + FCL_REAL d; + AABB aabb1, aabb2; + convertBV(child_bv, tf1, aabb1); + convertBV(tree2->getBV(root2).bv, tf2, aabb2); + d = aabb1.distance(aabb2); - FCL_REAL dist; - solver->shapeDistance(box1, box1_tf, box2, box2_tf, &dist); - if(dist < min_dist) + if(d < min_dist) { if(OcTreeMeshDistanceRecurse(tree1, child, child_bv, tree2, root2, tf1, tf2, min_dist)) return true; @@ -461,25 +450,24 @@ private: } else { - Box box1, box2; - SimpleTransform box1_tf, box2_tf; - constructBox(bv1, tf1, box1, box1_tf); - - FCL_REAL dist; - + FCL_REAL d; + AABB aabb1, aabb2; + convertBV(bv1, tf1, aabb1); int child = tree2->getBV(root2).leftChild(); - constructBox(tree2->getBV(child).bv, tf2, box2, box2_tf); - solver->shapeDistance(box1, box1_tf, box2, box2_tf, &dist); - if(dist < min_dist) + convertBV(tree2->getBV(child).bv, tf2, aabb2); + d = aabb1.distance(aabb2); + + if(d < min_dist) { if(OcTreeMeshDistanceRecurse(tree1, root1, bv1, tree2, child, tf1, tf2, min_dist)) return true; } child = tree2->getBV(root2).rightChild(); - constructBox(tree2->getBV(child).bv, tf2, box2, box2_tf); - solver->shapeDistance(box1, box1_tf, box2, box2_tf, &dist); - if(dist < min_dist) + convertBV(tree2->getBV(child).bv, tf2, aabb2); + d = aabb1.distance(aabb2); + + if(d < min_dist) { if(OcTreeMeshDistanceRecurse(tree1, root1, bv1, tree2, child, tf1, tf2, min_dist)) return true; @@ -500,45 +488,50 @@ private: { if(tree1->isNodeOccupied(root1)) { - Box box; - SimpleTransform box_tf; - constructBox(bv1, tf1, box, box_tf); - - int primitive_id = tree2->getBV(root2).primitiveId(); - const Triangle& tri_id = tree2->tri_indices[primitive_id]; - const Vec3f& p1 = tree2->vertices[tri_id[0]]; - const Vec3f& p2 = tree2->vertices[tri_id[1]]; - const Vec3f& p3 = tree2->vertices[tri_id[2]]; + OBB obb1, obb2; + convertBV(bv1, tf1, obb1); + convertBV(tree2->getBV(root2).bv, tf2, obb2); + if(obb1.overlap(obb2)) + { + Box box; + SimpleTransform box_tf; + constructBox(bv1, tf1, box, box_tf); + + int primitive_id = tree2->getBV(root2).primitiveId(); + const Triangle& tri_id = tree2->tri_indices[primitive_id]; + const Vec3f& p1 = tree2->vertices[tri_id[0]]; + const Vec3f& p2 = tree2->vertices[tri_id[1]]; + const Vec3f& p3 = tree2->vertices[tri_id[2]]; + if(!enable_contact) + { + if(solver->shapeTriangleIntersect(box, box_tf, p1, p2, p3, tf2.getRotation(), tf2.getTranslation(), NULL, NULL, NULL)) + pairs.push_back(OcTreeMeshCollisionPair(root1, root2)); + } + else + { + Vec3f contact; + FCL_REAL depth; + Vec3f normal; - if(!enable_contact) - { - if(solver->shapeTriangleIntersect(box, box_tf, p1, p2, p3, tf2.getRotation(), tf2.getTranslation(), NULL, NULL, NULL)) - pairs.push_back(OcTreeMeshCollisionPair(root1, root2)); - } - else - { - Vec3f contact; - FCL_REAL depth; - Vec3f normal; + if(solver->shapeTriangleIntersect(box, box_tf, p1, p2, p3, tf2.getRotation(), tf2.getTranslation(), &contact, &depth, &normal)) + pairs.push_back(OcTreeMeshCollisionPair(root1, root2, contact, normal, depth)); + } - if(solver->shapeTriangleIntersect(box, box_tf, p1, p2, p3, tf2.getRotation(), tf2.getTranslation(), &contact, &depth, &normal)) - pairs.push_back(OcTreeMeshCollisionPair(root1, root2, contact, normal, depth)); + return ((pairs.size() >= num_max_contacts) && !exhaustive); } - - return ((pairs.size() >= num_max_contacts) && !exhaustive); + else + return false; } else return false; } - Box box1, box2; - SimpleTransform box1_tf, box2_tf; - - constructBox(bv1, tf1, box1, box1_tf); - constructBox(tree2->getBV(root2).bv, tf2, box2, box2_tf); - if(!tree1->isNodeOccupied(root1) || !solver->shapeIntersect(box1, box1_tf, box2, box2_tf, NULL, NULL, NULL)) return false; + OBB obb1, obb2; + convertBV(bv1, tf1, obb1); + convertBV(tree2->getBV(root2).bv, tf2, obb2); + if(!tree1->isNodeOccupied(root1) || !obb1.overlap(obb2)) return false; if(tree2->getBV(root2).isLeaf() || (root1->hasChildren() && (bv1.size() > tree2->getBV(root2).bv.size()))) { @@ -605,11 +598,11 @@ private: computeChildBV(bv1, i, child_bv); FCL_REAL d; - Box box1, box2; - SimpleTransform box1_tf, box2_tf; - constructBox(child_bv, tf1, box1, box1_tf); - constructBox(bv2, tf2, box2, box2_tf); - solver->shapeDistance(box1, box2_tf, box2, box2_tf, &d); + AABB aabb1, aabb2; + convertBV(bv1, tf1, aabb1); + convertBV(bv2, tf2, aabb2); + d = aabb1.distance(aabb2); + if(d < min_dist) { @@ -630,11 +623,10 @@ private: computeChildBV(bv2, i, child_bv); FCL_REAL d; - Box box1, box2; - SimpleTransform box1_tf, box2_tf; - constructBox(bv1, tf1, box1, box1_tf); - constructBox(child_bv, tf2, box2, box2_tf); - solver->shapeDistance(box1, box2_tf, box2, box2_tf, &d); + AABB aabb1, aabb2; + convertBV(bv1, tf1, aabb1); + convertBV(bv2, tf2, aabb2); + d = aabb1.distance(aabb2); if(d < min_dist) { @@ -658,18 +650,22 @@ private: { if(tree1->isNodeOccupied(root1) && tree2->isNodeOccupied(root2)) { - Box box1, box2; - SimpleTransform box1_tf, box2_tf; - constructBox(bv1, tf1, box1, box1_tf); - constructBox(bv2, tf2, box2, box2_tf); - if(!enable_contact) { - if(solver->shapeIntersect(box1, box1_tf, box2, box2_tf, NULL, NULL, NULL)) + OBB obb1, obb2; + convertBV(bv1, tf1, obb1); + convertBV(bv2, tf2, obb2); + + if(obb1.overlap(obb2)) pairs.push_back(OcTreeCollisionPair(root1, root2)); } else { + Box box1, box2; + SimpleTransform box1_tf, box2_tf; + constructBox(bv1, tf1, box1, box1_tf); + constructBox(bv2, tf2, box2, box2_tf); + Vec3f contact; FCL_REAL depth; Vec3f normal; @@ -685,6 +681,11 @@ private: if(!tree1->isNodeOccupied(root1) || !tree2->isNodeOccupied(root2)) return false; + OBB obb1, obb2; + convertBV(bv1, tf1, obb1); + convertBV(bv2, tf2, obb2); + if(!obb1.overlap(obb2)) return false; + if(!root2->hasChildren() || (root1->hasChildren() && (bv1.size() > bv2.size()))) { for(unsigned int i = 0; i < 8; ++i) diff --git a/trunk/fcl/src/broad_phase_collision.cpp b/trunk/fcl/src/broad_phase_collision.cpp index 45699ea632ceca3e11315ddc99b82bacb51ab3d7..1d01ea4dcab5c9b226b6ed0f38417711006c8e58 100644 --- a/trunk/fcl/src/broad_phase_collision.cpp +++ b/trunk/fcl/src/broad_phase_collision.cpp @@ -2343,7 +2343,8 @@ bool DynamicAABBTreeCollisionManager::selfDistanceRecurse(DynamicAABBNode* root, return false; } -bool DynamicAABBTreeCollisionManager::collisionRecurse(DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, CollisionCallBack callback) const + +bool collisionRecurse_(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, CollisionCallBack callback) { if(root1->isLeaf() && !root2->hasChildren()) { @@ -2374,9 +2375,9 @@ bool DynamicAABBTreeCollisionManager::collisionRecurse(DynamicAABBNode* root1, c if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size()))) { - if(collisionRecurse(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback)) + if(collisionRecurse_(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback)) return true; - if(collisionRecurse(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback)) + if(collisionRecurse_(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback)) return true; } else @@ -2389,7 +2390,7 @@ bool DynamicAABBTreeCollisionManager::collisionRecurse(DynamicAABBNode* root1, c AABB child_bv; computeChildBV(root2_bv, i, child_bv); - if(collisionRecurse(root1, tree2, child, child_bv, tf2, cdata, callback)) + if(collisionRecurse_(root1, tree2, child, child_bv, tf2, cdata, callback)) return true; } } @@ -2397,7 +2398,144 @@ bool DynamicAABBTreeCollisionManager::collisionRecurse(DynamicAABBNode* root1, c return false; } -bool DynamicAABBTreeCollisionManager::distanceRecurse(DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const +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(tree2->isNodeOccupied(root2)) + { + const AABB& root2_bv_t = translate(root2_bv, tf2); + if(root1->bv.overlap(root2_bv_t)) + { + Box* box = new Box(); + SimpleTransform box_tf; + constructBox(root2_bv, tf2, *box, box_tf); + CollisionObject obj(boost::shared_ptr<CollisionGeometry>(box), box_tf); + return callback(static_cast<CollisionObject*>(root1->data), &obj, cdata); + } + else return false; + } + else return false; + } + + const AABB& root2_bv_t = translate(root2_bv, tf2); + if(!tree2->isNodeOccupied(root2) || !root1->bv.overlap(root2_bv_t)) return false; + + if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size()))) + { + if(collisionRecurse_(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback)) + return true; + if(collisionRecurse_(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback)) + return true; + } + else + { + for(unsigned int i = 0; i < 8; ++i) + { + if(root2->childExists(i)) + { + const OcTree::OcTreeNode* child = root2->getChild(i); + AABB child_bv; + computeChildBV(root2_bv, i, child_bv); + + if(collisionRecurse_(root1, tree2, child, child_bv, tf2, cdata, callback)) + return true; + } + } + } + return false; +} + + + +bool DynamicAABBTreeCollisionManager::collisionRecurse(DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, CollisionCallBack callback) const +{ + if(tf2.getQuatRotation().isIdentity()) + return collisionRecurse_(root1, tree2, root2, root2_bv, tf2.getTranslation(), cdata, callback); + else // has rotation + return collisionRecurse_(root1, tree2, root2, root2_bv, tf2, cdata, callback); +} + + +bool distanceRecurse_(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Vec3f& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) +{ + if(root1->isLeaf() && !root2->hasChildren()) + { + if(tree2->isNodeOccupied(root2)) + { + Box* box = new Box(); + SimpleTransform box_tf; + constructBox(root2_bv, tf2, *box, box_tf); + CollisionObject obj(boost::shared_ptr<CollisionGeometry>(box), box_tf); + return callback(static_cast<CollisionObject*>(root1->data), &obj, cdata, min_dist); + } + else return false; + } + + if(!tree2->isNodeOccupied(root2)) return false; + + if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size()))) + { + const AABB& aabb2 = translate(root2_bv, tf2); + FCL_REAL d1 = aabb2.distance(root1->childs[0]->bv); + FCL_REAL d2 = aabb2.distance(root1->childs[1]->bv); + + if(d2 < d1) + { + if(d2 < min_dist) + { + if(distanceRecurse_(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + return true; + } + + if(d1 < min_dist) + { + if(distanceRecurse_(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + return true; + } + } + else + { + if(d1 < min_dist) + { + if(distanceRecurse_(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + return true; + } + + if(d2 < min_dist) + { + if(distanceRecurse_(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + return true; + } + } + } + else + { + for(unsigned int i = 0; i < 8; ++i) + { + if(root2->childExists(i)) + { + const OcTree::OcTreeNode* child = root2->getChild(i); + AABB child_bv; + computeChildBV(root2_bv, i, child_bv); + const AABB& aabb2 = translate(child_bv, tf2); + + FCL_REAL d = root1->bv.distance(aabb2); + + if(d < min_dist) + { + if(distanceRecurse_(root1, tree2, child, child_bv, tf2, cdata, callback, min_dist)) + return true; + } + } + } + } + + return false; +} + + +bool distanceRecurse_(DynamicAABBTreeCollisionManager::DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) { if(root1->isLeaf() && !root2->hasChildren()) { @@ -2426,13 +2564,13 @@ bool DynamicAABBTreeCollisionManager::distanceRecurse(DynamicAABBNode* root1, co { if(d2 < min_dist) { - if(distanceRecurse(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) return true; } if(d1 < min_dist) { - if(distanceRecurse(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) return true; } } @@ -2440,13 +2578,13 @@ bool DynamicAABBTreeCollisionManager::distanceRecurse(DynamicAABBNode* root1, co { if(d1 < min_dist) { - if(distanceRecurse(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) return true; } if(d2 < min_dist) { - if(distanceRecurse(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) return true; } } @@ -2467,7 +2605,7 @@ bool DynamicAABBTreeCollisionManager::distanceRecurse(DynamicAABBNode* root1, co if(d < min_dist) { - if(distanceRecurse(root1, tree2, child, child_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(root1, tree2, child, child_bv, tf2, cdata, callback, min_dist)) return true; } } @@ -2477,10 +2615,13 @@ bool DynamicAABBTreeCollisionManager::distanceRecurse(DynamicAABBNode* root1, co return false; } - - - - +bool DynamicAABBTreeCollisionManager::distanceRecurse(DynamicAABBNode* root1, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const +{ + if(tf2.getQuatRotation().isIdentity()) + return distanceRecurse_(root1, tree2, root2, root2_bv, tf2.getTranslation(), cdata, callback, min_dist); + else + return distanceRecurse_(root1, tree2, root2, root2_bv, tf2, cdata, callback, min_dist); +} @@ -2806,11 +2947,9 @@ bool DynamicAABBTreeCollisionManager2::selfDistanceRecurse(DynamicAABBNode* node return false; } - - -bool DynamicAABBTreeCollisionManager2::collisionRecurse(DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, CollisionCallBack callback) const +bool collisionRecurse_(DynamicAABBTreeCollisionManager2::DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, CollisionCallBack callback) { - DynamicAABBNode* root1 = nodes1 + root1_id; + DynamicAABBTreeCollisionManager2::DynamicAABBNode* root1 = nodes1 + root1_id; if(root1->isLeaf() && !root2->hasChildren()) { if(tree2->isNodeOccupied(root2)) @@ -2840,9 +2979,9 @@ bool DynamicAABBTreeCollisionManager2::collisionRecurse(DynamicAABBNode* nodes1, if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size()))) { - if(collisionRecurse(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback)) + if(collisionRecurse_(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback)) return true; - if(collisionRecurse(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback)) + if(collisionRecurse_(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback)) return true; } else @@ -2855,7 +2994,7 @@ bool DynamicAABBTreeCollisionManager2::collisionRecurse(DynamicAABBNode* nodes1, AABB child_bv; computeChildBV(root2_bv, i, child_bv); - if(collisionRecurse(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback)) + if(collisionRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback)) return true; } } @@ -2864,9 +3003,70 @@ bool DynamicAABBTreeCollisionManager2::collisionRecurse(DynamicAABBNode* nodes1, return false; } -bool DynamicAABBTreeCollisionManager2::distanceRecurse(DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const +bool collisionRecurse_(DynamicAABBTreeCollisionManager2::DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Vec3f& tf2, void* cdata, CollisionCallBack callback) { - DynamicAABBNode* root1 = nodes1 + root1_id; + DynamicAABBTreeCollisionManager2::DynamicAABBNode* root1 = nodes1 + root1_id; + if(root1->isLeaf() && !root2->hasChildren()) + { + if(tree2->isNodeOccupied(root2)) + { + const AABB& root_bv_t = translate(root2_bv, tf2); + if(root1->bv.overlap(root_bv_t)) + { + Box* box = new Box(); + SimpleTransform box_tf; + constructBox(root2_bv, tf2, *box, box_tf); + CollisionObject obj(boost::shared_ptr<CollisionGeometry>(box), box_tf); + return callback(static_cast<CollisionObject*>(root1->data), &obj, cdata); + } + else return false; + } + else return false; + } + + const AABB& root_bv_t = translate(root2_bv, tf2); + if(!tree2->isNodeOccupied(root2) || !root1->bv.overlap(root_bv_t)) return false; + + if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size()))) + { + if(collisionRecurse_(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback)) + return true; + if(collisionRecurse_(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback)) + return true; + } + else + { + for(unsigned int i = 0; i < 8; ++i) + { + if(root2->childExists(i)) + { + const OcTree::OcTreeNode* child = root2->getChild(i); + AABB child_bv; + computeChildBV(root2_bv, i, child_bv); + + if(collisionRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback)) + return true; + } + } + } + + return false; +} + + + +bool DynamicAABBTreeCollisionManager2::collisionRecurse(DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, CollisionCallBack callback) const +{ + if(tf2.getQuatRotation().isIdentity()) + return collisionRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2.getTranslation(), cdata, callback); + else + return collisionRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2, cdata, callback); +} + + +bool distanceRecurse_(DynamicAABBTreeCollisionManager2::DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) +{ + DynamicAABBTreeCollisionManager2::DynamicAABBNode* root1 = nodes1 + root1_id; if(root1->isLeaf() && !root2->hasChildren()) { if(tree2->isNodeOccupied(root2)) @@ -2894,13 +3094,13 @@ bool DynamicAABBTreeCollisionManager2::distanceRecurse(DynamicAABBNode* nodes1, { if(d2 < min_dist) { - if(distanceRecurse(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) return true; } if(d1 < min_dist) { - if(distanceRecurse(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) return true; } } @@ -2908,13 +3108,13 @@ bool DynamicAABBTreeCollisionManager2::distanceRecurse(DynamicAABBNode* nodes1, { if(d1 < min_dist) { - if(distanceRecurse(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) return true; } if(d2 < min_dist) { - if(distanceRecurse(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) return true; } } @@ -2935,7 +3135,7 @@ bool DynamicAABBTreeCollisionManager2::distanceRecurse(DynamicAABBNode* nodes1, if(d < min_dist) { - if(distanceRecurse(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback, min_dist)) + if(distanceRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback, min_dist)) return true; } } @@ -2945,4 +3145,92 @@ bool DynamicAABBTreeCollisionManager2::distanceRecurse(DynamicAABBNode* nodes1, return false; } + +bool distanceRecurse_(DynamicAABBTreeCollisionManager2::DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const Vec3f& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) +{ + DynamicAABBTreeCollisionManager2::DynamicAABBNode* root1 = nodes1 + root1_id; + if(root1->isLeaf() && !root2->hasChildren()) + { + if(tree2->isNodeOccupied(root2)) + { + Box* box = new Box(); + SimpleTransform box_tf; + constructBox(root2_bv, tf2, *box, box_tf); + CollisionObject obj(boost::shared_ptr<CollisionGeometry>(box), box_tf); + return callback(static_cast<CollisionObject*>(root1->data), &obj, cdata, min_dist); + } + else return false; + } + + if(!tree2->isNodeOccupied(root2)) return false; + + if(!root2->hasChildren() || (!root1->isLeaf() && (root1->bv.size() > root2_bv.size()))) + { + const AABB& aabb2 = translate(root2_bv, tf2); + + FCL_REAL d1 = aabb2.distance((nodes1 + root1->childs[0])->bv); + FCL_REAL d2 = aabb2.distance((nodes1 + root1->childs[1])->bv); + + if(d2 < d1) + { + if(d2 < min_dist) + { + if(distanceRecurse_(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + return true; + } + + if(d1 < min_dist) + { + if(distanceRecurse_(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + return true; + } + } + else + { + if(d1 < min_dist) + { + if(distanceRecurse_(nodes1, root1->childs[0], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + return true; + } + + if(d2 < min_dist) + { + if(distanceRecurse_(nodes1, root1->childs[1], tree2, root2, root2_bv, tf2, cdata, callback, min_dist)) + return true; + } + } + } + else + { + for(unsigned int i = 0; i < 8; ++i) + { + if(root2->childExists(i)) + { + const OcTree::OcTreeNode* child = root2->getChild(i); + AABB child_bv; + computeChildBV(root2_bv, i, child_bv); + + const AABB& aabb2 = translate(child_bv, tf2); + FCL_REAL d = root1->bv.distance(aabb2); + + if(d < min_dist) + { + if(distanceRecurse_(nodes1, root1_id, tree2, child, child_bv, tf2, cdata, callback, min_dist)) + return true; + } + } + } + } + + return false; +} + +bool DynamicAABBTreeCollisionManager2::distanceRecurse(DynamicAABBNode* nodes1, size_t root1_id, const OcTree* tree2, const OcTree::OcTreeNode* root2, const AABB& root2_bv, const SimpleTransform& tf2, void* cdata, DistanceCallBack callback, FCL_REAL& min_dist) const +{ + if(tf2.getQuatRotation().isIdentity()) + return distanceRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2.getTranslation(), cdata, callback, min_dist); + else + return distanceRecurse_(nodes1, root1_id, tree2, root2, root2_bv, tf2, cdata, callback, min_dist); +} + }