diff --git a/include/fcl/traversal/traversal_node_bvhs.h b/include/fcl/traversal/traversal_node_bvhs.h index 5e9dd63c0a34c2a8fdac4f753f243e2b56daaaef..2a943fa2855324f65e95dbd4ffef04542ffdcd46 100644 --- a/include/fcl/traversal/traversal_node_bvhs.h +++ b/include/fcl/traversal/traversal_node_bvhs.h @@ -662,7 +662,8 @@ public: struct ConservativeAdvancementStackData { - ConservativeAdvancementStackData(const Vec3f& P1_, const Vec3f& P2_, int c1_, int c2_, FCL_REAL d_) : P1(P1_), P2(P2_), c1(c1_), c2(c2_), d(d_) {} + ConservativeAdvancementStackData(const Vec3f& P1_, const Vec3f& P2_, int c1_, int c2_, FCL_REAL d_) + : P1(P1_), P2(P2_), c1(c1_), c2(c2_), d(d_) {} Vec3f P1; Vec3f P2; @@ -846,6 +847,9 @@ bool MeshConservativeAdvancementTraversalNode<OBB>::canStop(FCL_REAL c) const; template<> bool MeshConservativeAdvancementTraversalNode<RSS>::canStop(FCL_REAL c) const; +template<> +bool MeshConservativeAdvancementTraversalNode<OBBRSS>::canStop(FCL_REAL c) const; + class MeshConservativeAdvancementTraversalNodeRSS : public MeshConservativeAdvancementTraversalNode<RSS> { @@ -862,6 +866,20 @@ public: Vec3f T; }; +class MeshConservativeAdvancementTraversalNodeOBBRSS : public MeshConservativeAdvancementTraversalNode<OBBRSS> +{ +public: + MeshConservativeAdvancementTraversalNodeOBBRSS(FCL_REAL w_ = 1); + + FCL_REAL BVTesting(int b1, int b2) const; + + void leafTesting(int b1, int b2) const; + + bool canStop(FCL_REAL c) const; + + Matrix3f R; + Vec3f T; +}; } diff --git a/include/fcl/traversal/traversal_node_setup.h b/include/fcl/traversal/traversal_node_setup.h index b9ead423c3df35a5a2c71bef92233f7a0e46d868..fd73e34bea4291f364e2dd82ea842c46a9bfec26 100644 --- a/include/fcl/traversal/traversal_node_setup.h +++ b/include/fcl/traversal/traversal_node_setup.h @@ -1048,9 +1048,9 @@ bool initialize(MeshContinuousCollisionTraversalNode<BV>& node, /// @brief Initialize traversal node for conservative advancement computation between two meshes, given the current transforms template<typename BV> bool initialize(MeshConservativeAdvancementTraversalNode<BV>& node, - BVHModel<BV>& model1, - BVHModel<BV>& model2, - const Matrix3f& R1, const Vec3f& T1, const Matrix3f& R2, const Vec3f& T2, FCL_REAL w = 1, + BVHModel<BV>& model1, const Transform3f& tf1, + BVHModel<BV>& model2, const Transform3f& tf2, + FCL_REAL w = 1, bool use_refit = false, bool refit_bottomup = false) { if(model1.getModelType() != BVH_MODEL_TRIANGLES || model2.getModelType() != BVH_MODEL_TRIANGLES) @@ -1060,7 +1060,7 @@ bool initialize(MeshConservativeAdvancementTraversalNode<BV>& node, for(int i = 0; i < model1.num_vertices; ++i) { Vec3f& p = model1.vertices[i]; - Vec3f new_v = R1 * p + T1; + Vec3f new_v = tf1.transform(p); vertices_transformed1[i] = new_v; } @@ -1069,7 +1069,7 @@ bool initialize(MeshConservativeAdvancementTraversalNode<BV>& node, for(int i = 0; i < model2.num_vertices; ++i) { Vec3f& p = model2.vertices[i]; - Vec3f new_v = R2 * p + T2; + Vec3f new_v = tf2.transform(p); vertices_transformed2[i] = new_v; } @@ -1097,27 +1097,15 @@ bool initialize(MeshConservativeAdvancementTraversalNode<BV>& node, /// @brief Initialize traversal node for conservative advancement computation between two meshes, given the current transforms, specialized for RSS -inline bool initialize(MeshConservativeAdvancementTraversalNodeRSS& node, const BVHModel<RSS>& model1, const BVHModel<RSS>& model2, - const Matrix3f& R1, const Vec3f& T1, const Matrix3f& R2, const Vec3f& T2, FCL_REAL w = 1) -{ - if(model1.getModelType() != BVH_MODEL_TRIANGLES || model2.getModelType() != BVH_MODEL_TRIANGLES) - return false; - - node.model1 = &model1; - node.model2 = &model2; - - node.vertices1 = model1.vertices; - node.vertices2 = model2.vertices; - - node.tri_indices1 = model1.tri_indices; - node.tri_indices2 = model2.tri_indices; - - node.w = w; - - relativeTransform(R1, T1, R2, T2, node.R, node.T); +bool initialize(MeshConservativeAdvancementTraversalNodeRSS& node, + const BVHModel<RSS>& model1, const Transform3f& tf1, + const BVHModel<RSS>& model2, const Transform3f& tf2, + FCL_REAL w = 1); - return true; -} +bool initialize(MeshConservativeAdvancementTraversalNodeOBBRSS& node, + const BVHModel<OBBRSS>& model1, const Transform3f& tf1, + const BVHModel<OBBRSS>& model2, const Transform3f& tf2, + FCL_REAL w = 1); } diff --git a/src/ccd/conservative_advancement.cpp b/src/ccd/conservative_advancement.cpp index 298397b762ec4d888ca4b31c9fee262b1cde8c91..8899a256c89e76d678c01dcaa064a4d230064697 100644 --- a/src/ccd/conservative_advancement.cpp +++ b/src/ccd/conservative_advancement.cpp @@ -106,7 +106,7 @@ int conservativeAdvancement(const CollisionGeometry* o1, MeshConservativeAdvancementTraversalNodeRSS node; - initialize(node, *model1, *model2, tf1.getRotation(), tf1.getTranslation(), tf2.getRotation(), tf2.getTranslation()); + initialize(node, *model1, tf1, *model2, tf2); node.motion1 = motion1; node.motion2 = motion2; diff --git a/src/traversal/traversal_node_bvhs.cpp b/src/traversal/traversal_node_bvhs.cpp index b9f8a9d6068c3c0a1f3a92718af0dbee87990943..2c1eb5ea235dc87b49c571579db3c462b671196a 100644 --- a/src/traversal/traversal_node_bvhs.cpp +++ b/src/traversal/traversal_node_bvhs.cpp @@ -428,11 +428,33 @@ void MeshDistanceTraversalNodeOBBRSS::leafTesting(int b1, int b2) const } -/// for OBB and RSS, there is local coordinate of BV, so normal need to be transformed + +namespace details +{ + +template<typename BV> +const Vec3f& getBVAxis(const BV& bv, int i) +{ + return bv.axis[i]; +} + template<> -bool MeshConservativeAdvancementTraversalNode<OBB>::canStop(FCL_REAL c) const +const Vec3f& getBVAxis<OBBRSS>(const OBBRSS& bv, int i) { - if((c >= w * (this->min_distance - this->abs_err)) && (c * (1 + this->rel_err) >= w * this->min_distance)) + return bv.obb.axis[i]; +} + + +template<typename BV> +bool meshConservativeAdvancementTraversalNodeCanStop(FCL_REAL c, + FCL_REAL min_distance, + FCL_REAL abs_err, FCL_REAL rel_err, FCL_REAL w, + const BVHModel<BV>* model1, const BVHModel<BV>* model2, + const MotionBase<BV>* motion1, const MotionBase<BV>* motion2, + std::vector<ConservativeAdvancementStackData>& stack, + FCL_REAL& delta_t) +{ + if((c >= w * (min_distance - abs_err)) && (c * (1 + rel_err) >= w * min_distance)) { const ConservativeAdvancementStackData& data = stack.back(); FCL_REAL d = data.d; @@ -457,10 +479,13 @@ bool MeshConservativeAdvancementTraversalNode<OBB>::canStop(FCL_REAL c) const assert(c == d); - Vec3f n_transformed = model1->getBV(c1).bv.axis[0] * n[0] + model1->getBV(c1).bv.axis[1] * n[1] + model1->getBV(c1).bv.axis[2] * n[2]; + Vec3f n_transformed = + getBVAxis(model1->getBV(c1).bv, 0) * n[0] + + getBVAxis(model1->getBV(c1).bv, 1) * n[1] + + getBVAxis(model1->getBV(c1).bv, 2) * n[2]; - FCL_REAL bound1 = motion1->computeMotionBound(this->model1->getBV(c1).bv, n_transformed); - FCL_REAL bound2 = motion2->computeMotionBound(this->model2->getBV(c2).bv, n_transformed); + FCL_REAL bound1 = motion1->computeMotionBound(model1->getBV(c1).bv, n_transformed); + FCL_REAL bound2 = motion2->computeMotionBound(model2->getBV(c2).bv, n_transformed); FCL_REAL bound = bound1 + bound2; @@ -489,10 +514,53 @@ bool MeshConservativeAdvancementTraversalNode<OBB>::canStop(FCL_REAL c) const } } +} + +/// for OBB, RSS and OBBRSS, there is local coordinate of BV, so normal need to be transformed +template<> +bool MeshConservativeAdvancementTraversalNode<OBB>::canStop(FCL_REAL c) const +{ + return details::meshConservativeAdvancementTraversalNodeCanStop(c, this->min_distance, + this->abs_err, this->rel_err, w, + this->model1, this->model2, + motion1, motion2, + stack, delta_t); +} + template<> bool MeshConservativeAdvancementTraversalNode<RSS>::canStop(FCL_REAL c) const { - if((c >= w * (this->min_distance - this->abs_err)) && (c * (1 + this->rel_err) >= w * this->min_distance)) + return details::meshConservativeAdvancementTraversalNodeCanStop(c, this->min_distance, + this->abs_err, this->rel_err, w, + this->model1, this->model2, + motion1, motion2, + stack, delta_t); +} + +template<> +bool MeshConservativeAdvancementTraversalNode<OBBRSS>::canStop(FCL_REAL c) const +{ + return details::meshConservativeAdvancementTraversalNodeCanStop(c, this->min_distance, + this->abs_err, this->rel_err, w, + this->model1, this->model2, + motion1, motion2, + stack, delta_t); +} + + +namespace details +{ + +template<typename BV> +bool meshConservativeAdvancementOrientedNodeCanStop(FCL_REAL c, + FCL_REAL min_distance, + FCL_REAL abs_err, FCL_REAL rel_err, FCL_REAL w, + const BVHModel<BV>* model1, const BVHModel<BV>* model2, + const MotionBase<BV>* motion1, const MotionBase<BV>* motion2, + std::vector<ConservativeAdvancementStackData>& stack, + FCL_REAL& delta_t) +{ + if((c >= w * (min_distance - abs_err)) && (c * (1 + rel_err) >= w * min_distance)) { const ConservativeAdvancementStackData& data = stack.back(); FCL_REAL d = data.d; @@ -517,10 +585,18 @@ bool MeshConservativeAdvancementTraversalNode<RSS>::canStop(FCL_REAL c) const assert(c == d); - Vec3f n_transformed = model1->getBV(c1).bv.axis[0] * n[0] + model1->getBV(c1).bv.axis[1] * n[1] + model1->getBV(c1).bv.axis[2] * n[2]; + // n is in local frame of c1, so we need to turn n into the global frame + Vec3f n_transformed = + getBVAxis(model1->getBV(c1).bv, 0) * n[0] + + getBVAxis(model1->getBV(c1).bv, 1) * n[2] + + getBVAxis(model1->getBV(c1).bv, 2) * n[2]; + Matrix3f R0; + motion1->getCurrentRotation(R0); + n_transformed = R0 * n_transformed; + n_transformed.normalize(); - FCL_REAL bound1 = motion1->computeMotionBound(this->model1->getBV(c1).bv, n_transformed); - FCL_REAL bound2 = motion2->computeMotionBound(this->model2->getBV(c2).bv, n_transformed); + FCL_REAL bound1 = motion1->computeMotionBound(model1->getBV(c1).bv, n_transformed); + FCL_REAL bound2 = motion2->computeMotionBound(model2->getBV(c2).bv, -n_transformed); FCL_REAL bound = bound1 + bound2; @@ -549,31 +625,24 @@ bool MeshConservativeAdvancementTraversalNode<RSS>::canStop(FCL_REAL c) const } } - -MeshConservativeAdvancementTraversalNodeRSS::MeshConservativeAdvancementTraversalNodeRSS(FCL_REAL w_) : MeshConservativeAdvancementTraversalNode<RSS>(w_) -{ - R.setIdentity(); - // default T is 0 -} - -FCL_REAL MeshConservativeAdvancementTraversalNodeRSS::BVTesting(int b1, int b2) const -{ - if(enable_statistics) num_bv_tests++; - Vec3f P1, P2; - FCL_REAL d = distance(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv, &P1, &P2); - - stack.push_back(ConservativeAdvancementStackData(P1, P2, b1, b2, d)); - - return d; -} - - -void MeshConservativeAdvancementTraversalNodeRSS::leafTesting(int b1, int b2) const +template<typename BV> +void meshConservativeAdvancementOrientedNodeLeafTesting(int b1, int b2, + const BVHModel<BV>* model1, const BVHModel<BV>* model2, + const Triangle* tri_indices1, const Triangle* tri_indices2, + const Vec3f* vertices1, const Vec3f* vertices2, + const Matrix3f& R, const Vec3f& T, + const MotionBase<BV>* motion1, const MotionBase<BV>* motion2, + bool enable_statistics, + FCL_REAL& min_distance, + Vec3f& p1, Vec3f& p2, + int& last_tri_id1, int& last_tri_id2, + FCL_REAL& delta_t, + int& num_leaf_tests) { if(enable_statistics) num_leaf_tests++; - const BVNode<RSS>& node1 = model1->getBV(b1); - const BVNode<RSS>& node2 = model2->getBV(b2); + const BVNode<BV>& node1 = model1->getBV(b1); + const BVNode<BV>& node2 = model2->getBV(b2); int primitive_id1 = node1.primitiveId(); int primitive_id2 = node2.primitiveId(); @@ -628,68 +697,100 @@ void MeshConservativeAdvancementTraversalNodeRSS::leafTesting(int b1, int b2) co delta_t = cur_delta_t; } -bool MeshConservativeAdvancementTraversalNodeRSS::canStop(FCL_REAL c) const +} + + +MeshConservativeAdvancementTraversalNodeRSS::MeshConservativeAdvancementTraversalNodeRSS(FCL_REAL w_) + : MeshConservativeAdvancementTraversalNode<RSS>(w_) { - if((c >= w * (min_distance - abs_err)) && (c * (1 + rel_err) >= w * min_distance)) - { - const ConservativeAdvancementStackData& data = stack.back(); - FCL_REAL d = data.d; - Vec3f n; - int c1, c2; + R.setIdentity(); +} - if(d > c) - { - const ConservativeAdvancementStackData& data2 = stack[stack.size() - 2]; - d = data2.d; - n = data2.P2 - data2.P1; - c1 = data2.c1; - c2 = data2.c2; - stack[stack.size() - 2] = stack[stack.size() - 1]; - } - else - { - n = data.P2 - data.P1; - c1 = data.c1; - c2 = data.c2; - } +FCL_REAL MeshConservativeAdvancementTraversalNodeRSS::BVTesting(int b1, int b2) const +{ + if(enable_statistics) num_bv_tests++; + Vec3f P1, P2; + FCL_REAL d = distance(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv, &P1, &P2); - assert(c == d); + stack.push_back(ConservativeAdvancementStackData(P1, P2, b1, b2, d)); - // n is in local frame of RSS c1, so we need to turn n into the global frame - Vec3f n_transformed = model1->getBV(c1).bv.axis[0] * n[0] + model1->getBV(c1).bv.axis[1] * n[2] + model1->getBV(c1).bv.axis[2] * n[2]; - Matrix3f R0; - motion1->getCurrentRotation(R0); - n_transformed = R0 * n_transformed; - n_transformed.normalize(); + return d; +} - FCL_REAL bound1 = motion1->computeMotionBound(model1->getBV(c1).bv, n_transformed); - FCL_REAL bound2 = motion2->computeMotionBound(model2->getBV(c2).bv, -n_transformed); - FCL_REAL bound = bound1 + bound2; +void MeshConservativeAdvancementTraversalNodeRSS::leafTesting(int b1, int b2) const +{ + details::meshConservativeAdvancementOrientedNodeLeafTesting(b1, b2, + model1, model2, + tri_indices1, tri_indices2, + vertices1, vertices2, + R, T, + motion1, motion2, + enable_statistics, + min_distance, + p1, p2, + last_tri_id1, last_tri_id2, + delta_t, + num_leaf_tests); +} - FCL_REAL cur_delta_t; - if(bound <= c) cur_delta_t = 1; - else cur_delta_t = c / bound; +bool MeshConservativeAdvancementTraversalNodeRSS::canStop(FCL_REAL c) const +{ + return details::meshConservativeAdvancementOrientedNodeCanStop(c, + min_distance, + abs_err, rel_err, w, + model1, model2, + motion1, motion2, + stack, + delta_t); +} - if(cur_delta_t < delta_t) - delta_t = cur_delta_t; - stack.pop_back(); - return true; - } - else - { - const ConservativeAdvancementStackData& data = stack.back(); - FCL_REAL d = data.d; - if(d > c) - stack[stack.size() - 2] = stack[stack.size() - 1]; +MeshConservativeAdvancementTraversalNodeOBBRSS::MeshConservativeAdvancementTraversalNodeOBBRSS(FCL_REAL w_) + : MeshConservativeAdvancementTraversalNode<OBBRSS>(w_) +{ + R.setIdentity(); +} - stack.pop_back(); +FCL_REAL MeshConservativeAdvancementTraversalNodeOBBRSS::BVTesting(int b1, int b2) const +{ + if(enable_statistics) num_bv_tests++; + Vec3f P1, P2; + FCL_REAL d = distance(R, T, model1->getBV(b1).bv, model2->getBV(b2).bv, &P1, &P2); - return false; - } + stack.push_back(ConservativeAdvancementStackData(P1, P2, b1, b2, d)); + + return d; +} + + +void MeshConservativeAdvancementTraversalNodeOBBRSS::leafTesting(int b1, int b2) const +{ + details::meshConservativeAdvancementOrientedNodeLeafTesting(b1, b2, + model1, model2, + tri_indices1, tri_indices2, + vertices1, vertices2, + R, T, + motion1, motion2, + enable_statistics, + min_distance, + p1, p2, + last_tri_id1, last_tri_id2, + delta_t, + num_leaf_tests); +} + +bool MeshConservativeAdvancementTraversalNodeOBBRSS::canStop(FCL_REAL c) const +{ + return details::meshConservativeAdvancementOrientedNodeCanStop(c, + min_distance, + abs_err, rel_err, w, + model1, model2, + motion1, motion2, + stack, + delta_t); } diff --git a/src/traversal/traversal_node_setup.cpp b/src/traversal/traversal_node_setup.cpp index 88fc4de565174ea6fe9a9718db19b5fb971687e4..bd83d00f757a85f507aa1f43e050d83628dd4373 100644 --- a/src/traversal/traversal_node_setup.cpp +++ b/src/traversal/traversal_node_setup.cpp @@ -178,5 +178,56 @@ bool initialize(MeshDistanceTraversalNodeOBBRSS& node, return details::setupMeshDistanceOrientedNode(node, model1, tf1, model2, tf2, request, result); } +namespace details +{ + + +template<typename BV, typename OrientedDistanceNode> +static inline bool setupMeshConservativeAdvancementOrientedDistanceNode(OrientedDistanceNode& node, + const BVHModel<BV>& model1, const Transform3f& tf1, + const BVHModel<BV>& model2, const Transform3f& tf2, + FCL_REAL w) +{ + if(model1.getModelType() != BVH_MODEL_TRIANGLES || model2.getModelType() != BVH_MODEL_TRIANGLES) + return false; + + node.model1 = &model1; + node.model2 = &model2; + + node.vertices1 = model1.vertices; + node.vertices2 = model2.vertices; + + node.tri_indices1 = model1.tri_indices; + node.tri_indices2 = model2.tri_indices; + + node.w = w; + + relativeTransform(tf1.getRotation(), tf1.getTranslation(), tf2.getRotation(), tf2.getTranslation(), node.R, node.T); + + return true; +} + +} + + +bool initialize(MeshConservativeAdvancementTraversalNodeRSS& node, + const BVHModel<RSS>& model1, const Transform3f& tf1, + const BVHModel<RSS>& model2, const Transform3f& tf2, + FCL_REAL w) +{ + return details::setupMeshConservativeAdvancementOrientedDistanceNode(node, model1, tf1, model2, tf2, w); +} + + +bool initialize(MeshConservativeAdvancementTraversalNodeOBBRSS& node, + const BVHModel<OBBRSS>& model1, const Transform3f& tf1, + const BVHModel<OBBRSS>& model2, const Transform3f& tf2, + FCL_REAL w) +{ + return details::setupMeshConservativeAdvancementOrientedDistanceNode(node, model1, tf1, model2, tf2, w); +} + + + }