diff --git a/include/hpp/fcl/traversal/traversal_node_bvh_shape.h b/include/hpp/fcl/traversal/traversal_node_bvh_shape.h index 322d4f15ae3f8b1d7e664a7bdb63a26ac4056e58..27ec3f9afed15285cdb311fff127bab9028e824e 100644 --- a/include/hpp/fcl/traversal/traversal_node_bvh_shape.h +++ b/include/hpp/fcl/traversal/traversal_node_bvh_shape.h @@ -135,24 +135,6 @@ public: return model2->getBV(b).rightChild(); } - /// BV test between b1 and b2 - /// \param b1, b2 Bounding volumes to test, - bool BVTesting(int b1, int b2) const - { - if(this->enable_statistics) num_bv_tests++; - return !model2->getBV(b2).bv.overlap(model1_bv); - } - - /// BV test between b1 and b2 - /// \param b1, b2 Bounding volumes to test, - /// \retval sqrDistLowerBound square of a lower bound of the minimal - /// distance between bounding volumes. - bool BVTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const - { - if(this->enable_statistics) num_bv_tests++; - return !model2->getBV(b2).bv.overlap(model1_bv, sqrDistLowerBound); - } - const S* model1; const BVHModel<BV>* model2; BV model1_bv; @@ -277,56 +259,6 @@ public: const NarrowPhaseSolver* nsolver; }; -/// @cond IGNORE -namespace details -{ -template<typename BV, typename S, typename NarrowPhaseSolver> -static inline void meshShapeCollisionOrientedNodeLeafTesting - (int b1, int /*b2*/, const BVHModel<BV>* model1, const S& model2, - Vec3f* vertices, Triangle* tri_indices, const Transform3f& tf1, - const Transform3f& tf2, const NarrowPhaseSolver* nsolver, - bool enable_statistics, int& num_leaf_tests, - const CollisionRequest& request, CollisionResult& result, - FCL_REAL& sqrDistLowerBound) -{ - if(enable_statistics) num_leaf_tests++; - const BVNode<BV>& node = model1->getBV(b1); - - int primitive_id = node.primitiveId(); - - const Triangle& tri_id = tri_indices[primitive_id]; - - const Vec3f& P1 = vertices[tri_id[0]]; - const Vec3f& P2 = vertices[tri_id[1]]; - const Vec3f& P3 = vertices[tri_id[2]]; - - FCL_REAL distance; - Vec3f normal; - Vec3f p1, p2; // closest points - - if(nsolver->shapeTriangleInteraction(model2, tf2, P1, P2, P3, tf1, - distance, p1, p2, normal)) - { - if(request.num_max_contacts > result.numContacts()) - result.addContact(Contact(model1, &model2, primitive_id, Contact::NONE, - p1, -normal, -distance)); - assert (result.isCollision ()); - return; - } - sqrDistLowerBound = distance * distance; - assert (distance > 0); - if (request.security_margin == 0) return; - if (distance <= request.security_margin) { - result.addContact(Contact(model1, &model2, primitive_id, Contact::NONE, - .5*(p1+p2), (p2-p1).normalized (), -distance)); - } -} - -} - -/// @endcond - - /// @brief Traversal node for mesh and shape, when mesh BVH is one of the oriented node (OBB, RSS, OBBRSS, kIOS) template<typename S, typename NarrowPhaseSolver> class MeshShapeCollisionTraversalNodeOBB : public MeshShapeCollisionTraversalNode<OBB, S, NarrowPhaseSolver, 0> @@ -375,10 +307,16 @@ public: /// @brief Traversal node for collision between shape and mesh -template<typename S, typename BV, typename NarrowPhaseSolver> +template<typename S, typename BV, typename NarrowPhaseSolver, + int _Options = RelativeTransformationIsIdentity> class ShapeMeshCollisionTraversalNode : public ShapeBVHCollisionTraversalNode<S, BV> { public: + enum { + Options = _Options, + RTIsIdentity = _Options & RelativeTransformationIsIdentity + }; + ShapeMeshCollisionTraversalNode() : ShapeBVHCollisionTraversalNode<S, BV>() { vertices = NULL; @@ -387,8 +325,37 @@ public: nsolver = NULL; } + /// BV test between b1 and b2 + /// \param b2 Bounding volumes to test, + bool BVTesting(int /*b1*/, int b2) const + { + if(this->enable_statistics) this->num_bv_tests++; + if (RTIsIdentity) + return !this->model2->getBV(b2).bv.overlap(this->model1_bv); + else + return !overlap(this->tf2.getRotation(), this->tf2.getTranslation(), this->model1_bv, this->model2->getBV(b2).bv); + } + + /// BV test between b1 and b2 + /// \param b2 Bounding volumes to test, + /// \retval sqrDistLowerBound square of a lower bound of the minimal + /// distance between bounding volumes. + bool BVTesting(int /*b1*/, int b2, FCL_REAL& sqrDistLowerBound) const + { + if(this->enable_statistics) this->num_bv_tests++; + bool res; + if (RTIsIdentity) + res = !this->model2->getBV(b2).bv.overlap(this->model1_bv, sqrDistLowerBound); + else + res = !overlap(this->tf2.getRotation(), this->tf2.getTranslation(), + this->model1_bv, this->model2->getBV(b2).bv, + sqrDistLowerBound); + assert (!res || sqrDistLowerBound > 0); + return res; + } + /// @brief Intersection testing between leaves (one shape and one triangle) - void leafTesting(int b1, int b2) const + void leafTesting(int /*b1*/, int b2, FCL_REAL& sqrDistLowerBound) const { if(this->enable_statistics) this->num_leaf_tests++; const BVNode<BV>& node = this->model2->getBV(b2); @@ -397,33 +364,47 @@ public: const Triangle& tri_id = tri_indices[primitive_id]; - const Vec3f& P1 = vertices[tri_id[0]]; - const Vec3f& P2 = vertices[tri_id[1]]; - const Vec3f& P3 = vertices[tri_id[2]]; + const Vec3f& p1 = vertices[tri_id[0]]; + const Vec3f& p2 = vertices[tri_id[1]]; + const Vec3f& p3 = vertices[tri_id[2]]; FCL_REAL distance; Vec3f normal; - Vec3f p1, p2; // closest points + Vec3f c1, c2; // closest points - if(nsolver->shapeTriangleInteraction(*(this->model1), this->tf1, P1, P2, P3, - Transform3f (), p1, p2, distance, - normal)) - { + bool collision; + if (RTIsIdentity) { + static const Transform3f Id; + collision = + nsolver->shapeTriangleInteraction(*(this->model1), this->tf1, p1, p2, p3, + Id , c1, c2, distance, normal); + } else { + collision = + nsolver->shapeTriangleInteraction(*(this->model1), this->tf1, p1, p2, p3, + this->tf2, c1, c2, distance, normal); + } + + if (collision) { if(this->request.num_max_contacts > this->result->numContacts()) { - this->result->addContact - (Contact(this->model1, this->model2, primitive_id, - Contact::NONE, p1, -normal, -distance)); + this->result->addContact (Contact(this->model1 , this->model2, + Contact::NONE, primitive_id, + c1, normal, -distance)); + assert (this->result->isCollision ()); + return; } } + sqrDistLowerBound = distance * distance; assert (distance > 0); - if (this->request.security_margin == 0) return; - if (distance <= this->request.security_margin) + if ( this->request.security_margin == 0 + && distance <= this->request.security_margin) { - this->result.addContact - (Contact(this->model1, this->model2, primitive_id, Contact::NONE, - .5 * (p1+p2), (p2-p1).normalized (), -distance)); + this->result.addContact (Contact(this->model1 , this->model2, + Contact::NONE, primitive_id, + .5 * (c1+c2), (c2-c1).normalized (), + -distance)); } + assert (!this->result->isCollision () || sqrDistLowerBound > 0); } /// @brief Whether the traversal process can stop early @@ -440,118 +421,42 @@ public: /// @brief Traversal node for shape and mesh, when mesh BVH is one of the oriented node (OBB, RSS, OBBRSS, kIOS) template<typename S, typename NarrowPhaseSolver> -class ShapeMeshCollisionTraversalNodeOBB : public ShapeMeshCollisionTraversalNode<S, OBB, NarrowPhaseSolver> +class ShapeMeshCollisionTraversalNodeOBB : public ShapeMeshCollisionTraversalNode<S, OBB, NarrowPhaseSolver, 0> { public: ShapeMeshCollisionTraversalNodeOBB() : ShapeMeshCollisionTraversalNode<S, OBB, NarrowPhaseSolver>() { } - - bool BVTesting(int b1, int b2) const - { - if(this->enable_statistics) this->num_bv_tests++; - return !overlap(this->tf2.getRotation(), this->tf2.getTranslation(), this->model1_bv, this->model2->getBV(b2).bv); - } - - void leafTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const - { - details::meshShapeCollisionOrientedNodeLeafTesting - (b2, b1, *(this->model2), this->model1, this->vertices, this->tri_indices, - this->tf2, this->tf1, this->nsolver, this->enable_statistics, - this->num_leaf_tests, this->request,*(this->request), sqrDistLowerBound); - - // may need to change the order in pairs - } }; template<typename S, typename NarrowPhaseSolver> -class ShapeMeshCollisionTraversalNodeRSS : public ShapeMeshCollisionTraversalNode<S, RSS, NarrowPhaseSolver> +class ShapeMeshCollisionTraversalNodeRSS : public ShapeMeshCollisionTraversalNode<S, RSS, NarrowPhaseSolver, 0> { public: ShapeMeshCollisionTraversalNodeRSS() : ShapeMeshCollisionTraversalNode<S, RSS, NarrowPhaseSolver>() { } - - bool BVTesting(int b1, int b2) const - { - if(this->enable_statistics) this->num_bv_tests++; - return !overlap(this->tf2.getRotation(), this->tf2.getTranslation(), this->model1_bv, this->model2->getBV(b2).bv); - } - - void leafTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const - { - details::meshShapeCollisionOrientedNodeLeafTesting - (b2, b1, *(this->model2), this->model1, this->vertices, this->tri_indices, - this->tf2, this->tf1, this->nsolver, this->enable_statistics, - this->num_leaf_tests, this->request, *(this->request)); - - // may need to change the order in pairs - } - }; template<typename S, typename NarrowPhaseSolver> -class ShapeMeshCollisionTraversalNodekIOS : public ShapeMeshCollisionTraversalNode<S, kIOS, NarrowPhaseSolver> +class ShapeMeshCollisionTraversalNodekIOS : public ShapeMeshCollisionTraversalNode<S, kIOS, NarrowPhaseSolver, 0> { public: ShapeMeshCollisionTraversalNodekIOS() : ShapeMeshCollisionTraversalNode<S, kIOS, NarrowPhaseSolver>() { } - - bool BVTesting(int b1, int b2) const - { - if(this->enable_statistics) this->num_bv_tests++; - return !overlap(this->tf2.getRotation(), this->tf2.getTranslation(), this->model1_bv, this->model2->getBV(b2).bv); - } - - void leafTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const - { - details::meshShapeCollisionOrientedNodeLeafTesting - (b2, b1, *(this->model2), this->model1, this->vertices, this->tri_indices, - this->tf2, this->tf1, this->nsolver, this->enable_statistics, - this->num_leaf_tests, this->request,*(this->request), sqrDistLowerBound); - - // may need to change the order in pairs - } - }; template<typename S, typename NarrowPhaseSolver> -class ShapeMeshCollisionTraversalNodeOBBRSS : public ShapeMeshCollisionTraversalNode<S, OBBRSS, NarrowPhaseSolver> +class ShapeMeshCollisionTraversalNodeOBBRSS : public ShapeMeshCollisionTraversalNode<S, OBBRSS, NarrowPhaseSolver, 0> { public: ShapeMeshCollisionTraversalNodeOBBRSS() : ShapeMeshCollisionTraversalNode<S, OBBRSS, NarrowPhaseSolver>() { } - - bool BVTesting(int b1, int b2) const - { - if(this->enable_statistics) this->num_bv_tests++; - return !overlap(this->tf2.getRotation(), this->tf2.getTranslation(), this->model1_bv, this->model2->getBV(b2).bv); - } - - bool BVTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const - { - if(this->enable_statistics) this->num_bv_tests++; - return !overlap(this->tf2.getRotation(), this->tf2.getTranslation(), - this->model1_bv, this->model2->getBV(b2).bv, - sqrDistLowerBound); - } - - void leafTesting(int b1, int b2, FCL_REAL& sqrDistLowerBound) const - { - details::meshShapeCollisionOrientedNodeLeafTesting - (b2, b1, *(this->model2), this->model1, this->vertices, - this->tri_indices, this->tf2, this->tf1, this->nsolver, - this->enable_statistics, this->num_leaf_tests, - this->request, *(this->request), sqrDistLowerBound); - - // may need to change the order in pairs - } - }; /// @brief Traversal node for distance computation between BVH and shape