37 #ifndef HPP_FCL_TRAVERSAL_NODE_BVH_HFIELD_H 
   38 #define HPP_FCL_TRAVERSAL_NODE_BVH_HFIELD_H 
   66 template <
typename BV1, 
typename BV2,
 
   67           int _Options = RelativeTransformationIsIdentity>
 
   68 class MeshHeightFieldCollisionTraversalNode
 
   69     : 
public CollisionTraversalNodeBase {
 
   73     RTIsIdentity = _Options & RelativeTransformationIsIdentity
 
   76   MeshHeightFieldCollisionTraversalNode(
const CollisionRequest& request)
 
   77       : CollisionTraversalNodeBase(request) {
 
   83     query_time_seconds = 0.0;
 
   90   bool isFirstNodeLeaf(
unsigned int b)
 const {
 
   91     assert(model1 != NULL && 
"model1 is NULL");
 
   92     return model1->getBV(
b).isLeaf();
 
   96   bool isSecondNodeLeaf(
unsigned int b)
 const {
 
   97     assert(model2 != NULL && 
"model2 is NULL");
 
   98     return model2->getBV(
b).isLeaf();
 
  102   bool firstOverSecond(
unsigned int b1, 
unsigned int b2)
 const {
 
  103     FCL_REAL sz1 = model1->getBV(b1).bv.size();
 
  104     FCL_REAL sz2 = model2->getBV(b2).bv.size();
 
  106     bool l1 = model1->getBV(b1).isLeaf();
 
  107     bool l2 = model2->getBV(b2).isLeaf();
 
  109     if (l2 || (!l1 && (sz1 > sz2))) 
return true;
 
  114   int getFirstLeftChild(
unsigned int b)
 const {
 
  115     return model1->getBV(
b).leftChild();
 
  119   int getFirstRightChild(
unsigned int b)
 const {
 
  120     return model1->getBV(
b).rightChild();
 
  124   int getSecondLeftChild(
unsigned int b)
 const {
 
  125     return model2->getBV(
b).leftChild();
 
  129   int getSecondRightChild(
unsigned int b)
 const {
 
  130     return model2->getBV(
b).rightChild();
 
  134   bool BVDisjoints(
unsigned int b1, 
unsigned int b2)
 const {
 
  135     if (this->enable_statistics) this->num_bv_tests++;
 
  137       return !this->model1->getBV(b1).overlap(this->model2->getBV(b2));
 
  139       return !
overlap(RT._R(), RT._T(), this->model1->getBV(b1).bv,
 
  140                       this->model2->getBV(b2).bv);
 
  147   bool BVDisjoints(
unsigned int b1, 
unsigned int b2,
 
  148                    FCL_REAL& sqrDistLowerBound)
 const {
 
  149     if (this->enable_statistics) this->num_bv_tests++;
 
  151       return !this->model1->getBV(b1).overlap(this->model2->getBV(b2),
 
  152                                               this->request, sqrDistLowerBound);
 
  154       bool res = !
overlap(RT._R(), RT._T(), this->model1->getBV(b1).bv,
 
  155                           this->model2->getBV(b2).bv, this->request,
 
  157       assert(!res || sqrDistLowerBound > 0);
 
  176   void leafCollides(
unsigned int b1, 
unsigned int b2,
 
  177                     FCL_REAL& sqrDistLowerBound)
 const {
 
  178     if (this->enable_statistics) this->num_leaf_tests++;
 
  180     const BVNode<BV1>& node1 = this->model1->getBV(b1);
 
  181     const HeightFieldNode<BV2>& node2 = this->model2->getBV(b2);
 
  183     int primitive_id1 = node1.primitiveId();
 
  184     const Triangle& tri_id1 = tri_indices1[primitive_id1];
 
  186     const Vec3f& 
P1 = vertices1[tri_id1[0]];
 
  187     const Vec3f& 
P2 = vertices1[tri_id1[1]];
 
  188     const Vec3f& 
P3 = vertices1[tri_id1[2]];
 
  190     TriangleP tri1(
P1, 
P2, 
P3);
 
  192     typedef Convex<Triangle> ConvexTriangle;
 
  193     ConvexTriangle convex1, convex2;
 
  194     details::buildConvexTriangles(node2, *this->model2, convex2, convex2);
 
  201     solver.shapeDistance(tri1, this->
tf1, tri2, this->
tf2, distance, 
p1, p2,
 
  205     if (distToCollision <= 0) {  
 
  208       if (this->result->numContacts() < this->request.num_max_contacts) {
 
  213           normal = (p2 - 
p1).normalized();
 
  216         this->result->addContact(Contact(this->model1, this->model2,
 
  217                                          primitive_id1, primitive_id2, p,
 
  218                                          normal, penetrationDepth));
 
  224   const BVHModel<BV1>* model1;
 
  226   const HeightField<BV2>* model2;
 
  229   mutable int num_bv_tests;
 
  230   mutable int num_leaf_tests;
 
  231   mutable FCL_REAL query_time_seconds;
 
  233   Vec3f* vertices1 Triangle* tri_indices1;
 
  235   details::RelativeTransformation<!bool(RTIsIdentity)> RT;
 
  240 typedef MeshHeightFieldCollisionTraversalNode<OBB, 0>
 
  241     MeshHeightFieldCollisionTraversalNodeOBB;
 
  242 typedef MeshHeightFieldCollisionTraversalNode<RSS, 0>
 
  243     MeshHeightFieldCollisionTraversalNodeRSS;
 
  244 typedef MeshHeightFieldCollisionTraversalNode<kIOS, 0>
 
  245     MeshHeightFieldCollisionTraversalNodekIOS;
 
  246 typedef MeshHeightFieldCollisionTraversalNode<OBBRSS, 0>
 
  247     MeshHeightFieldCollisionTraversalNodeOBBRSS;
 
  252 template <
typename BV>
 
  253 struct DistanceTraversalBVDistanceLowerBound_impl {
 
  254   static FCL_REAL run(
const BVNode<BV>& b1, 
const BVNode<BV>& b2) {
 
  255     return b1.distance(b2);
 
  258                       const BVNode<BV>& b2) {
 
  259     return distance(R, T, b1.bv, b2.bv);
 
  264 struct DistanceTraversalBVDistanceLowerBound_impl<OBB> {
 
  265   static FCL_REAL run(
const BVNode<OBB>& b1, 
const BVNode<OBB>& b2) {
 
  269     if (b1.overlap(b2, request, sqrDistLowerBound)) {
 
  273     return sqrt(sqrDistLowerBound);
 
  276                       const BVNode<OBB>& b2) {
 
  280     if (
overlap(R, T, b1.bv, b2.bv, request, sqrDistLowerBound)) {
 
  284     return sqrt(sqrDistLowerBound);
 
  289 struct DistanceTraversalBVDistanceLowerBound_impl<AABB> {
 
  290   static FCL_REAL run(
const BVNode<AABB>& b1, 
const BVNode<AABB>& b2) {
 
  294     if (b1.overlap(b2, request, sqrDistLowerBound)) {
 
  298     return sqrt(sqrDistLowerBound);
 
  301                       const BVNode<AABB>& b2) {
 
  305     if (
overlap(R, T, b1.bv, b2.bv, request, sqrDistLowerBound)) {
 
  309     return sqrt(sqrDistLowerBound);
 
  318 template <
typename BV>
 
  319 class BVHDistanceTraversalNode : 
public DistanceTraversalNodeBase {
 
  321   BVHDistanceTraversalNode() : DistanceTraversalNodeBase() {
 
  327     query_time_seconds = 0.0;
 
  331   bool isFirstNodeLeaf(
unsigned int b)
 const {
 
  332     return model1->getBV(
b).isLeaf();
 
  336   bool isSecondNodeLeaf(
unsigned int b)
 const {
 
  337     return model2->getBV(
b).isLeaf();
 
  341   bool firstOverSecond(
unsigned int b1, 
unsigned int b2)
 const {
 
  342     FCL_REAL sz1 = model1->getBV(b1).bv.size();
 
  343     FCL_REAL sz2 = model2->getBV(b2).bv.size();
 
  345     bool l1 = model1->getBV(b1).isLeaf();
 
  346     bool l2 = model2->getBV(b2).isLeaf();
 
  348     if (l2 || (!l1 && (sz1 > sz2))) 
return true;
 
  353   int getFirstLeftChild(
unsigned int b)
 const {
 
  354     return model1->getBV(
b).leftChild();
 
  358   int getFirstRightChild(
unsigned int b)
 const {
 
  359     return model1->getBV(
b).rightChild();
 
  363   int getSecondLeftChild(
unsigned int b)
 const {
 
  364     return model2->getBV(
b).leftChild();
 
  368   int getSecondRightChild(
unsigned int b)
 const {
 
  369     return model2->getBV(
b).rightChild();
 
  373   const BVHModel<BV>* model1;
 
  375   const BVHModel<BV>* model2;
 
  378   mutable int num_bv_tests;
 
  379   mutable int num_leaf_tests;
 
  380   mutable FCL_REAL query_time_seconds;
 
  384 template <
typename BV, 
int _Options = RelativeTransformationIsIdentity>
 
  385 class MeshDistanceTraversalNode : 
public BVHDistanceTraversalNode<BV> {
 
  389     RTIsIdentity = _Options & RelativeTransformationIsIdentity
 
  392   using BVHDistanceTraversalNode<BV>::enable_statistics;
 
  393   using BVHDistanceTraversalNode<BV>::request;
 
  394   using BVHDistanceTraversalNode<BV>::result;
 
  396   using BVHDistanceTraversalNode<BV>::model1;
 
  397   using BVHDistanceTraversalNode<BV>::model2;
 
  398   using BVHDistanceTraversalNode<BV>::num_bv_tests;
 
  399   using BVHDistanceTraversalNode<BV>::num_leaf_tests;
 
  401   MeshDistanceTraversalNode() : BVHDistanceTraversalNode<BV>() {
 
  407     rel_err = this->request.rel_err;
 
  408     abs_err = this->request.abs_err;
 
  412     if (!RTIsIdentity) preprocessOrientedNode();
 
  416     if (!RTIsIdentity) postprocessOrientedNode();
 
  420   FCL_REAL BVDistanceLowerBound(
unsigned int b1, 
unsigned int b2)
 const {
 
  421     if (enable_statistics) num_bv_tests++;
 
  424           model1->getBV(b1), model2->getBV(b2));
 
  427           RT._R(), RT._T(), model1->getBV(b1), model2->getBV(b2));
 
  431   void leafComputeDistance(
unsigned int b1, 
unsigned int b2)
 const {
 
  432     if (this->enable_statistics) this->num_leaf_tests++;
 
  434     const BVNode<BV>& node1 = this->model1->getBV(b1);
 
  435     const BVNode<BV>& node2 = this->model2->getBV(b2);
 
  437     int primitive_id1 = node1.primitiveId();
 
  438     int primitive_id2 = node2.primitiveId();
 
  440     const Triangle& tri_id1 = tri_indices1[primitive_id1];
 
  441     const Triangle& tri_id2 = tri_indices2[primitive_id2];
 
  443     const Vec3f& t11 = vertices1[tri_id1[0]];
 
  444     const Vec3f& t12 = vertices1[tri_id1[1]];
 
  445     const Vec3f& t13 = vertices1[tri_id1[2]];
 
  447     const Vec3f& t21 = vertices2[tri_id2[0]];
 
  448     const Vec3f& t22 = vertices2[tri_id2[1]];
 
  449     const Vec3f& t23 = vertices2[tri_id2[2]];
 
  456       d2 = TriangleDistance::sqrTriDistance(t11, t12, t13, t21, t22, t23, 
P1,
 
  459       d2 = TriangleDistance::sqrTriDistance(t11, t12, t13, t21, t22, t23,
 
  460                                             RT._R(), RT._T(), 
P1, 
P2);
 
  463     this->result->update(d, this->model1, this->model2, primitive_id1,
 
  464                          primitive_id2, 
P1, 
P2, normal);
 
  469     if ((c >= this->result->min_distance - abs_err) &&
 
  470         (c * (1 + rel_err) >= this->result->min_distance))
 
  478   Triangle* tri_indices1;
 
  479   Triangle* tri_indices2;
 
  485   details::RelativeTransformation<!bool(RTIsIdentity)> RT;
 
  488   void preprocessOrientedNode() {
 
  489     const int init_tri_id1 = 0, init_tri_id2 = 0;
 
  490     const Triangle& init_tri1 = tri_indices1[init_tri_id1];
 
  491     const Triangle& init_tri2 = tri_indices2[init_tri_id2];
 
  493     Vec3f init_tri1_points[3];
 
  494     Vec3f init_tri2_points[3];
 
  496     init_tri1_points[0] = vertices1[init_tri1[0]];
 
  497     init_tri1_points[1] = vertices1[init_tri1[1]];
 
  498     init_tri1_points[2] = vertices1[init_tri1[2]];
 
  500     init_tri2_points[0] = vertices2[init_tri2[0]];
 
  501     init_tri2_points[1] = vertices2[init_tri2[1]];
 
  502     init_tri2_points[2] = vertices2[init_tri2[2]];
 
  506         init_tri1_points[0], init_tri1_points[1], init_tri1_points[2],
 
  507         init_tri2_points[0], init_tri2_points[1], init_tri2_points[2], RT._R(),
 
  510     result->update(
distance, model1, model2, init_tri_id1, init_tri_id2, 
p1, p2,
 
  513   void postprocessOrientedNode() {
 
  517     if (request.enable_nearest_points && (result->o1 == model1) &&
 
  518         (result->o2 == model2)) {
 
  519       result->nearest_points[0] = 
tf1.transform(result->nearest_points[0]);
 
  520       result->nearest_points[1] = 
tf1.transform(result->nearest_points[1]);
 
  527 typedef MeshDistanceTraversalNode<RSS, 0> MeshDistanceTraversalNodeRSS;
 
  528 typedef MeshDistanceTraversalNode<kIOS, 0> MeshDistanceTraversalNodekIOS;
 
  529 typedef MeshDistanceTraversalNode<OBBRSS, 0> MeshDistanceTraversalNodeOBBRSS;
 
  537 template <
typename BV>
 
  538 inline const Matrix3f& getBVAxes(
const BV& bv) {
 
  543 inline const Matrix3f& getBVAxes<OBBRSS>(
const OBBRSS& bv) {