diff --git a/trunk/fcl/include/fcl/BVH_model.h b/trunk/fcl/include/fcl/BVH_model.h index 2eef52b66ee12ef9985a508164b64550e740fcae..a1489bb0590eb4d5b16e132d95301818c9f8d06b 100644 --- a/trunk/fcl/include/fcl/BVH_model.h +++ b/trunk/fcl/include/fcl/BVH_model.h @@ -223,6 +223,11 @@ public: /** \brief Check the number of memory used */ int memUsage(int msg) const; + void makeParentRelative() + { + makeParentRelativeRecurse(0, Matrix3f::getIdentity(), Vec3f()); + } + private: /** \brief Bounding volume hierarchy */ @@ -249,6 +254,23 @@ private: /** \brief Recursive kernel for bottomup refitting */ int recursiveRefitTree_bottomup(int bv_id); + void makeParentRelativeRecurse(int bv_id, const Matrix3f& parentR, const Vec3f& parentT) + { + if(!bvs[bv_id].isLeaf()) + { + makeParentRelativeRecurse(bvs[bv_id].first_child, bvs[bv_id].getOrientation(), bvs[bv_id].getCenter()); + + makeParentRelativeRecurse(bvs[bv_id].first_child + 1, bvs[bv_id].getOrientation(), bvs[bv_id].getCenter()); + } + + // make self parent relative + Matrix3f Rpc = parentR.transposeTimes(bvs[bv_id].getOrientation()); + bvs[bv_id].setOrientation(Rpc); + + Vec3f Tpc = bvs[bv_id].getCenter() - parentT; + bvs[bv_id].setCenter(parentR.transposeTimes(Tpc)); + } + }; diff --git a/trunk/fcl/include/fcl/BV_node.h b/trunk/fcl/include/fcl/BV_node.h index 26268e04734f2c0e63a36cb6c37766cf4ca2875e..0058275a7919a88e5ea6df9cc1b6ad376b87393a 100644 --- a/trunk/fcl/include/fcl/BV_node.h +++ b/trunk/fcl/include/fcl/BV_node.h @@ -38,17 +38,18 @@ #ifndef FCL_BV_NODE_H #define FCL_BV_NODE_H +#include "fcl/vec_3f.h" +#include "fcl/matrix_3f.h" + +#include "fcl/OBB.h" +#include "fcl/RSS.h" + /** \brief Main namespace */ namespace fcl { -/** \brief A class describing a bounding volume node */ -template<typename BV> -struct BVNode +struct BVNodeBase { - /** \brief A bounding volume */ - BV bv; - /** \brief An index for first child node or primitive * If the value is positive, it is the index of the first child bv node * If the value is negative, it is -(primitive index + 1) @@ -65,16 +66,24 @@ struct BVNode int num_primitives; /** \brief Whether current node is a leaf node (i.e. contains a primitive index */ - bool isLeaf() const { return first_child < 0; } + inline bool isLeaf() const { return first_child < 0; } /** \brief Return the primitive index. The index is referred to the original data (i.e. vertices or tri_indices) in BVHModel */ - int primitiveId() const { return -(first_child + 1); } + inline int primitiveId() const { return -(first_child + 1); } /** \brief Return the index of the first child. The index is referred to the bounding volume array (i.e. bvs) in BVHModel */ - int leftChild() const { return first_child; } + inline int leftChild() const { return first_child; } /** \brief Return the index of the second child. The index is referred to the bounding volume array (i.e. bvs) in BVHModel */ - int rightChild() const { return first_child + 1; } + inline int rightChild() const { return first_child + 1; } +}; + +/** \brief A class describing a bounding volume node */ +template<typename BV> +struct BVNode : public BVNodeBase +{ + /** \brief A bounding volume */ + BV bv; /** \brief Check whether two BVNode collide */ bool overlap(const BVNode& other) const @@ -87,6 +96,79 @@ struct BVNode return bv.distance(other.bv, P1, P2); } + Vec3f getCenter() const { return Vec3f(); } + void setCenter(const Vec3f& v) {} + Matrix3f getOrientation() const { return Matrix3f::getIdentity(); } + void setOrientation(const Matrix3f& m) {} +}; + +template<> +struct BVNode<OBB> : public BVNodeBase +{ + /** \brief A bounding volume */ + OBB bv; + + /** \brief Check whether two BVNode collide */ + bool overlap(const BVNode& other) const + { + return bv.overlap(other.bv); + } + + BVH_REAL distance(const BVNode& other, Vec3f* P1 = NULL, Vec3f* P2 = NULL) const + { + return bv.distance(other.bv, P1, P2); + } + + Vec3f getCenter() const { return bv.To; } + void setCenter(const Vec3f& v) { bv.To = v; } + Matrix3f getOrientation() const + { + Matrix3f m(bv.axis[0][0], bv.axis[1][0], bv.axis[2][0], + bv.axis[0][1], bv.axis[1][1], bv.axis[2][1], + bv.axis[0][2], bv.axis[1][2], bv.axis[2][2]); + return m; + } + void setOrientation(const Matrix3f& m) + { + bv.axis[0].setValue(m[0][0], m[1][0], m[2][0]); + bv.axis[1].setValue(m[0][1], m[1][1], m[2][1]); + bv.axis[2].setValue(m[0][2], m[1][2], m[2][2]); + } +}; + +template<> +struct BVNode<RSS> : public BVNodeBase +{ + /** \brief A bounding volume */ + RSS bv; + + /** \brief Check whether two BVNode collide */ + bool overlap(const BVNode& other) const + { + return bv.overlap(other.bv); + } + + BVH_REAL distance(const BVNode& other, Vec3f* P1 = NULL, Vec3f* P2 = NULL) const + { + return bv.distance(other.bv, P1, P2); + } + + Vec3f getCenter() const { return bv.Tr; } + void setCenter(const Vec3f& v) { bv.Tr = v; } + Matrix3f getOrientation() const + { + Matrix3f m(bv.axis[0][0], bv.axis[1][0], bv.axis[2][0], + bv.axis[0][1], bv.axis[1][1], bv.axis[2][1], + bv.axis[0][2], bv.axis[1][2], bv.axis[2][2]); + return m; + } + + void setOrientation(const Matrix3f& m) + { + bv.axis[0].setValue(m[0][0], m[1][0], m[2][0]); + bv.axis[1].setValue(m[0][1], m[1][1], m[2][1]); + bv.axis[2].setValue(m[0][2], m[1][2], m[2][2]); + } }; } diff --git a/trunk/fcl/include/fcl/RSS.h b/trunk/fcl/include/fcl/RSS.h index 08c069b27092baee871132038a51a20bd749f8d0..61c435731928ed552cc95e56bb5e44dd82a1839a 100644 --- a/trunk/fcl/include/fcl/RSS.h +++ b/trunk/fcl/include/fcl/RSS.h @@ -126,6 +126,7 @@ public: return Tr; } + /** \brief the distance between two RSS */ BVH_REAL distance(const RSS& other, Vec3f* P = NULL, Vec3f* Q = NULL) const; diff --git a/trunk/fcl/include/fcl/collision_node.h b/trunk/fcl/include/fcl/collision_node.h index 00d3137707bef565fbb6035cb46a5b002fef1e77..29f8a46cf585ea71aab0b747a8a26229e2e4a3b6 100644 --- a/trunk/fcl/include/fcl/collision_node.h +++ b/trunk/fcl/include/fcl/collision_node.h @@ -47,6 +47,10 @@ namespace fcl void collide(CollisionTraversalNodeBase* node, BVHFrontList* front_list = NULL); +void collide2(MeshCollisionTraversalNodeOBB* node, BVHFrontList* front_list = NULL); + +void collide2(MeshCollisionTraversalNodeRSS* node, BVHFrontList* front_list = NULL); + void selfCollide(CollisionTraversalNodeBase* node, BVHFrontList* front_list = NULL); void distance(DistanceTraversalNodeBase* node, BVHFrontList* front_list = NULL, int qsize = 2); diff --git a/trunk/fcl/include/fcl/matrix_3f.h b/trunk/fcl/include/fcl/matrix_3f.h index 88ef63a11747228ab9d3338999b657e23c4db500..c72b61fe097179f6cc61053c7a8fb10f854a4d3b 100644 --- a/trunk/fcl/include/fcl/matrix_3f.h +++ b/trunk/fcl/include/fcl/matrix_3f.h @@ -58,6 +58,13 @@ namespace fcl zx, zy, zz); } + Matrix3f(const Vec3f& v1, const Vec3f& v2, const Vec3f& v3) + { + v_[0] = v1; + v_[1] = v2; + v_[2] = v3; + } + Matrix3f(const Matrix3f& other) { v_[0] = other.v_[0]; diff --git a/trunk/fcl/include/fcl/traversal_node_bvhs.h b/trunk/fcl/include/fcl/traversal_node_bvhs.h index 726b5f073f0de9901b19deaf994e7f2cc6d95a03..84f999361f11f14787a08c6c13b1bf4004833fce 100644 --- a/trunk/fcl/include/fcl/traversal_node_bvhs.h +++ b/trunk/fcl/include/fcl/traversal_node_bvhs.h @@ -275,6 +275,10 @@ public: void leafTesting(int b1, int b2) const; + bool BVTesting(int b1, int b2, const Matrix3f& Rc, const Vec3f& Tc) const; + + void leafTesting(int b1, int b2, const Matrix3f& Rc, const Vec3f& Tc) const; + Matrix3f R; Vec3f T; }; @@ -289,6 +293,10 @@ public: void leafTesting(int b1, int b2) const; + bool BVTesting(int b1, int b2, const Matrix3f& Rc, const Vec3f& Tc) const; + + void leafTesting(int b1, int b2, const Matrix3f& Rc, const Vec3f& Tc) const; + Matrix3f R; Vec3f T; }; diff --git a/trunk/fcl/include/fcl/traversal_recurse.h b/trunk/fcl/include/fcl/traversal_recurse.h index ca5838835619ee1db43e400cb328f9b298ee27e0..604258a104c09cd645a25895a399430f9d4712f4 100644 --- a/trunk/fcl/include/fcl/traversal_recurse.h +++ b/trunk/fcl/include/fcl/traversal_recurse.h @@ -39,6 +39,7 @@ #define FCL_TRAVERSAL_RECURSE_H #include "fcl/traversal_node_base.h" +#include "fcl/traversal_node_bvhs.h" #include "fcl/BVH_front.h" #include <queue> @@ -52,6 +53,9 @@ inline void updateFrontList(BVHFrontList* front_list, int b1, int b2) void collisionRecurse(CollisionTraversalNodeBase* node, int b1, int b2, BVHFrontList* front_list); +void collisionRecurse(MeshCollisionTraversalNodeOBB* node, int b1, int b2, const Matrix3f& R, const Vec3f& T, BVHFrontList* front_list); +void collisionRecurse(MeshCollisionTraversalNodeRSS* node, int b1, int b2, const Matrix3f& R, const Vec3f& T, BVHFrontList* front_list); + /** Recurse function for self collision * Make sure node is set correctly so that the first and second tree are the same */ diff --git a/trunk/fcl/src/collision_node.cpp b/trunk/fcl/src/collision_node.cpp index 3bd1b07125f8bbb42539eb3a8a34bdfe5012fe59..70d1775fb87a241d2d8cb2c8d351302be95cc1b9 100644 --- a/trunk/fcl/src/collision_node.cpp +++ b/trunk/fcl/src/collision_node.cpp @@ -53,6 +53,39 @@ void collide(CollisionTraversalNodeBase* node, BVHFrontList* front_list) } } +void collide2(MeshCollisionTraversalNodeOBB* node, BVHFrontList* front_list) +{ + if(front_list && front_list->size() > 0) + { + propagateBVHFrontListCollisionRecurse(node, front_list); + } + else + { + Matrix3f Rtemp, R; + Vec3f Ttemp, T; + Rtemp = node->R * node->model2->getBV(0).getOrientation(); + R = node->model1->getBV(0).getOrientation().transposeTimes(Rtemp); + Ttemp = node->R * node->model2->getBV(0).getCenter() + node->T; + Ttemp -= node->model1->getBV(0).getCenter(); + T = node->model1->getBV(0).getOrientation().transposeTimes(Ttemp); + + collisionRecurse(node, 0, 0, R, T, front_list); + } +} + +void collide2(MeshCollisionTraversalNodeRSS* node, BVHFrontList* front_list) +{ + if(front_list && front_list->size() > 0) + { + propagateBVHFrontListCollisionRecurse(node, front_list); + } + else + { + collisionRecurse(node, 0, 0, node->R, node->T, front_list); + } +} + + void selfCollide(CollisionTraversalNodeBase* node, BVHFrontList* front_list) { diff --git a/trunk/fcl/src/traversal_node_bvhs.cpp b/trunk/fcl/src/traversal_node_bvhs.cpp index 6c00681e02fa65baafc15fd9954effd475662d64..32bcccdfdb9a348d009c2042afbe72790a61d364 100644 --- a/trunk/fcl/src/traversal_node_bvhs.cpp +++ b/trunk/fcl/src/traversal_node_bvhs.cpp @@ -102,6 +102,63 @@ void MeshCollisionTraversalNodeOBB::leafTesting(int b1, int b2) const } +bool MeshCollisionTraversalNodeOBB::BVTesting(int b1, int b2, const Matrix3f& Rc, const Vec3f& Tc) const +{ + if(enable_statistics) num_bv_tests++; + return OBB::obbDisjoint(Rc, Tc, model1->getBV(b1).bv.extent, model2->getBV(b2).bv.extent); +} + +void MeshCollisionTraversalNodeOBB::leafTesting(int b1, int b2, const Matrix3f& Rc, const Vec3f& Tc) const +{ + if(enable_statistics) num_leaf_tests++; + + const BVNode<OBB>& node1 = model1->getBV(b1); + const BVNode<OBB>& node2 = model2->getBV(b2); + + int primitive_id1 = node1.primitiveId(); + int primitive_id2 = node2.primitiveId(); + + const Triangle& tri_id1 = tri_indices1[primitive_id1]; + const Triangle& tri_id2 = tri_indices2[primitive_id2]; + + const Vec3f& p1 = vertices1[tri_id1[0]]; + const Vec3f& p2 = vertices1[tri_id1[1]]; + const Vec3f& p3 = vertices1[tri_id1[2]]; + const Vec3f& q1 = vertices2[tri_id2[0]]; + const Vec3f& q2 = vertices2[tri_id2[1]]; + const Vec3f& q3 = vertices2[tri_id2[2]]; + + BVH_REAL penetration; + Vec3f normal; + int n_contacts; + Vec3f contacts[2]; + + + if(!enable_contact) // only interested in collision or not + { + if(Intersect::intersect_Triangle(p1, p2, p3, q1, q2, q3, R, T)) + pairs.push_back(BVHCollisionPair(primitive_id1, primitive_id2)); + } + else // need compute the contact information + { + if(Intersect::intersect_Triangle(p1, p2, p3, q1, q2, q3, + R, T, + contacts, + (unsigned int*)&n_contacts, + &penetration, + &normal)) + { + for(int i = 0; i < n_contacts; ++i) + { + if((!exhaustive) && (num_max_contacts <= (int)pairs.size())) break; + pairs.push_back(BVHCollisionPair(primitive_id1, primitive_id2, contacts[i], normal, penetration)); + } + } + } +} + + + MeshCollisionTraversalNodeRSS::MeshCollisionTraversalNodeRSS() : MeshCollisionTraversalNode<RSS>() { R.setIdentity(); diff --git a/trunk/fcl/src/traversal_recurse.cpp b/trunk/fcl/src/traversal_recurse.cpp index 8c0f2f7a2ddc18a535917e5f63383523d57a8376..590e61b1eadf4e0579ae640712e6dceaa1c0af9b 100644 --- a/trunk/fcl/src/traversal_recurse.cpp +++ b/trunk/fcl/src/traversal_recurse.cpp @@ -86,6 +86,91 @@ void collisionRecurse(CollisionTraversalNodeBase* node, int b1, int b2, BVHFront } } +void collisionRecurse(MeshCollisionTraversalNodeOBB* node, int b1, int b2, const Matrix3f& R, const Vec3f& T, BVHFrontList* front_list) +{ + bool l1 = node->isFirstNodeLeaf(b1); + bool l2 = node->isSecondNodeLeaf(b2); + + if(l1 && l2) + { + updateFrontList(front_list, b1, b2); + + if(node->BVTesting(b1, b2, R, T)) return; + + node->leafTesting(b1, b2, R, T); + return; + } + + if(node->BVTesting(b1, b2, R, T)) + { + updateFrontList(front_list, b1, b2); + return; + } + + Vec3f temp; + + if(node->firstOverSecond(b1, b2)) + { + int c1 = node->getFirstLeftChild(b1); + int c2 = node->getFirstRightChild(b1); + + const OBB& bv1 = node->model1->getBV(c1).bv; + + Matrix3f Rc(R.transposeTimes(bv1.axis[0]), R.transposeTimes(bv1.axis[1]), R.transposeTimes(bv1.axis[2])); + temp = T - bv1.To; + Vec3f Tc(temp.dot(bv1.axis[0]), temp.dot(bv1.axis[1]), temp.dot(bv1.axis[2])); + + collisionRecurse(node, c1, b2, Rc, Tc, front_list); + + // early stop is disabled is front_list is used + if(node->canStop() && !front_list) return; + + const OBB& bv2 = node->model1->getBV(c2).bv; + + Rc = Matrix3f(R.transposeTimes(bv2.axis[0]), R.transposeTimes(bv2.axis[1]), R.transposeTimes(bv2.axis[2])); + temp = T - bv2.To; + Tc.setValue(temp.dot(bv2.axis[0]), temp.dot(bv2.axis[1]), temp.dot(bv2.axis[2])); + + collisionRecurse(node, c2, b2, Rc, Tc, front_list); + } + else + { + int c1 = node->getSecondLeftChild(b2); + int c2 = node->getSecondRightChild(b2); + + const OBB& bv1 = node->model2->getBV(c1).bv; + Matrix3f Rc; + temp = R * bv1.axis[0]; + Rc[0][0] = temp[0]; Rc[1][0] = temp[1]; Rc[2][0] = temp[2]; + temp = R * bv1.axis[1]; + Rc[0][1] = temp[0]; Rc[1][1] = temp[1]; Rc[2][1] = temp[2]; + temp = R * bv1.axis[2]; + Rc[0][2] = temp[0]; Rc[1][2] = temp[1]; Rc[2][2] = temp[2]; + Vec3f Tc = R * bv1.To + T; + + collisionRecurse(node, b1, c1, Rc, Tc, front_list); + + // early stop is disabled is front_list is used + if(node->canStop() && !front_list) return; + + const OBB& bv2 = node->model2->getBV(c2).bv; + temp = R * bv2.axis[0]; + Rc[0][0] = temp[0]; Rc[1][0] = temp[1]; Rc[2][0] = temp[2]; + temp = R * bv2.axis[1]; + Rc[0][1] = temp[0]; Rc[1][1] = temp[1]; Rc[2][1] = temp[2]; + temp = R * bv2.axis[2]; + Rc[0][2] = temp[0]; Rc[1][2] = temp[1]; Rc[2][2] = temp[2]; + Tc = R * bv2.To + T; + + collisionRecurse(node, b1, c2, Rc, Tc, front_list); + } +} + +void collisionRecurse(MeshCollisionTraversalNodeRSS* node, int b1, int b2, const Matrix3f& R, const Vec3f& T, BVHFrontList* front_list) +{ + +} + /** Recurse function for self collision * Make sure node is set correctly so that the first and second tree are the same */ diff --git a/trunk/fcl/test/timing_test.cpp b/trunk/fcl/test/timing_test.cpp index f52fce2d52ec7b43fcf0ec1fb64fd157b4ef5861..051ff046c7bc68ea9df030945b6a0c06e9faf2a2 100644 --- a/trunk/fcl/test/timing_test.cpp +++ b/trunk/fcl/test/timing_test.cpp @@ -62,6 +62,59 @@ int main() generateRandomTransform(extents, transforms, transforms2, delta_trans, 0.005 * 2 * 3.1415, n); + std::cout << "FCL timing 2" << std::endl; + { + double t_fcl = 0; + + BVHModel<OBB> m1; + BVHModel<OBB> m2; + SplitMethodType split_method = SPLIT_METHOD_MEAN; + m1.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + m2.bv_splitter.reset(new BVSplitter<OBB>(split_method)); + + m1.beginModel(); + m1.addSubModel(vertices1, triangles1); + m1.endModel(); + m1.makeParentRelative(); + + m2.beginModel(); + m2.addSubModel(vertices2, triangles2); + m2.endModel(); + m2.makeParentRelative(); + + + Matrix3f R2; + R2.setIdentity(); + Vec3f T2; + + for(unsigned int i = 0; i < transforms.size(); ++i) + { + Transform& tf = transforms[i]; + m1.setTransform(tf.R, tf.T); + m2.setTransform(R2, T2); + + MeshCollisionTraversalNodeOBB node; + if(!initialize(node, (const BVHModel<OBB>&)m1, (const BVHModel<OBB>&)m2)) + std::cout << "initialize error" << std::endl; + + node.enable_statistics = false; + node.num_max_contacts = -1; + node.exhaustive = false; + node.enable_contact = false; + + Timer timer; + timer.start(); + collide2(&node); + timer.stop(); + t_fcl += timer.getElapsedTime(); + + //std::cout << node.pairs.size() << std::endl; + } + + std::cout << "fcl timing " << t_fcl << " ms" << std::endl; + } + + std::cout << "PQP timing" << std::endl; #if USE_PQP { @@ -89,6 +142,7 @@ int main() } m1.EndModel(); + m2.BeginModel(); for(unsigned int i = 0; i < triangles2.size(); ++i) { @@ -191,6 +245,7 @@ int main() } + return 1; }