GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/hpp/fcl/internal/traversal_node_bvhs.h Lines: 179 186 96.2 %
Date: 2024-02-09 12:57:42 Branches: 73 134 54.5 %

Line Branch Exec Source
1
/*
2
 * Software License Agreement (BSD License)
3
 *
4
 *  Copyright (c) 2011-2014, Willow Garage, Inc.
5
 *  Copyright (c) 2014-2015, Open Source Robotics Foundation
6
 *  All rights reserved.
7
 *
8
 *  Redistribution and use in source and binary forms, with or without
9
 *  modification, are permitted provided that the following conditions
10
 *  are met:
11
 *
12
 *   * Redistributions of source code must retain the above copyright
13
 *     notice, this list of conditions and the following disclaimer.
14
 *   * Redistributions in binary form must reproduce the above
15
 *     copyright notice, this list of conditions and the following
16
 *     disclaimer in the documentation and/or other materials provided
17
 *     with the distribution.
18
 *   * Neither the name of Open Source Robotics Foundation nor the names of its
19
 *     contributors may be used to endorse or promote products derived
20
 *     from this software without specific prior written permission.
21
 *
22
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
 *  POSSIBILITY OF SUCH DAMAGE.
34
 */
35
36
/** \author Jia Pan */
37
38
#ifndef HPP_FCL_TRAVERSAL_NODE_MESHES_H
39
#define HPP_FCL_TRAVERSAL_NODE_MESHES_H
40
41
/// @cond INTERNAL
42
43
#include <hpp/fcl/collision_data.h>
44
#include <hpp/fcl/internal/traversal_node_base.h>
45
#include <hpp/fcl/BV/BV_node.h>
46
#include <hpp/fcl/BV/BV.h>
47
#include <hpp/fcl/BVH/BVH_model.h>
48
#include <hpp/fcl/internal/intersect.h>
49
#include <hpp/fcl/shape/geometric_shapes.h>
50
#include <hpp/fcl/narrowphase/narrowphase.h>
51
#include <hpp/fcl/internal/traversal.h>
52
53
#include <limits>
54
#include <vector>
55
#include <cassert>
56
57
namespace hpp {
58
namespace fcl {
59
60
/// @addtogroup Traversal_For_Collision
61
/// @{
62
63
/// @brief Traversal node for collision between BVH models
64
template <typename BV>
65
class BVHCollisionTraversalNode : public CollisionTraversalNodeBase {
66
 public:
67
20631
  BVHCollisionTraversalNode(const CollisionRequest& request)
68
20631
      : CollisionTraversalNodeBase(request) {
69
20631
    model1 = NULL;
70
20631
    model2 = NULL;
71
72
20631
    num_bv_tests = 0;
73
20631
    num_leaf_tests = 0;
74
20631
    query_time_seconds = 0.0;
75
20631
  }
76
77
  /// @brief Whether the BV node in the first BVH tree is leaf
78
116958527
  bool isFirstNodeLeaf(unsigned int b) const {
79
116958527
    assert(model1 != NULL && "model1 is NULL");
80
116958527
    return model1->getBV(b).isLeaf();
81
  }
82
83
  /// @brief Whether the BV node in the second BVH tree is leaf
84
116958527
  bool isSecondNodeLeaf(unsigned int b) const {
85
116958527
    assert(model2 != NULL && "model2 is NULL");
86
116958527
    return model2->getBV(b).isLeaf();
87
  }
88
89
  /// @brief Determine the traversal order, is the first BVTT subtree better
90
41563421
  bool firstOverSecond(unsigned int b1, unsigned int b2) const {
91
41563421
    FCL_REAL sz1 = model1->getBV(b1).bv.size();
92
41563421
    FCL_REAL sz2 = model2->getBV(b2).bv.size();
93
94
41563421
    bool l1 = model1->getBV(b1).isLeaf();
95
41563421
    bool l2 = model2->getBV(b2).isLeaf();
96
97

41563421
    if (l2 || (!l1 && (sz1 > sz2))) return true;
98
16060292
    return false;
99
  }
100
101
  /// @brief Obtain the left child of BV node in the first BVH
102
25503129
  int getFirstLeftChild(unsigned int b) const {
103
25503129
    return model1->getBV(b).leftChild();
104
  }
105
106
  /// @brief Obtain the right child of BV node in the first BVH
107
25503129
  int getFirstRightChild(unsigned int b) const {
108
25503129
    return model1->getBV(b).rightChild();
109
  }
110
111
  /// @brief Obtain the left child of BV node in the second BVH
112
16060292
  int getSecondLeftChild(unsigned int b) const {
113
16060292
    return model2->getBV(b).leftChild();
114
  }
115
116
  /// @brief Obtain the right child of BV node in the second BVH
117
16060292
  int getSecondRightChild(unsigned int b) const {
118
16060292
    return model2->getBV(b).rightChild();
119
  }
120
121
  /// @brief The first BVH model
122
  const BVHModel<BV>* model1;
123
  /// @brief The second BVH model
124
  const BVHModel<BV>* model2;
125
126
  /// @brief statistical information
127
  mutable int num_bv_tests;
128
  mutable int num_leaf_tests;
129
  mutable FCL_REAL query_time_seconds;
130
};
131
132
/// @brief Traversal node for collision between two meshes
133
template <typename BV, int _Options = RelativeTransformationIsIdentity>
134
class MeshCollisionTraversalNode : public BVHCollisionTraversalNode<BV> {
135
 public:
136
  enum {
137
    Options = _Options,
138
    RTIsIdentity = _Options & RelativeTransformationIsIdentity
139
  };
140
141
20631
  MeshCollisionTraversalNode(const CollisionRequest& request)
142
20631
      : BVHCollisionTraversalNode<BV>(request) {
143
20631
    vertices1 = NULL;
144
20631
    vertices2 = NULL;
145
20631
    tri_indices1 = NULL;
146
20631
    tri_indices2 = NULL;
147
20631
  }
148
149
  /// BV test between b1 and b2
150
  /// @param b1, b2 Bounding volumes to test,
151
  /// @retval sqrDistLowerBound square of a lower bound of the minimal
152
  ///         distance between bounding volumes.
153
41708925
  bool BVDisjoints(unsigned int b1, unsigned int b2,
154
                   FCL_REAL& sqrDistLowerBound) const {
155
41708925
    if (this->enable_statistics) this->num_bv_tests++;
156
    bool disjoint;
157
    if (RTIsIdentity)
158
83175980
      disjoint = !this->model1->getBV(b1).overlap(
159
41587990
          this->model2->getBV(b2), this->request, sqrDistLowerBound);
160
    else {
161
120935
      disjoint = !overlap(RT._R(), RT._T(), this->model2->getBV(b2).bv,
162
120935
                          this->model1->getBV(b1).bv, this->request,
163
                          sqrDistLowerBound);
164
    }
165
41708925
    if (disjoint)
166
145504
      internal::updateDistanceLowerBoundFromBV(this->request, *this->result,
167
                                               sqrDistLowerBound);
168
41708925
    return disjoint;
169
  }
170
171
  /// Intersection testing between leaves (two triangles)
172
  ///
173
  /// @param b1, b2 id of primitive in bounding volume hierarchy
174
  /// @retval sqrDistLowerBound squared lower bound of distance between
175
  ///         primitives if they are not in collision.
176
  ///
177
  /// This method supports a security margin. If the distance between
178
  /// the primitives is less than the security margin, the objects are
179
  /// considered as in collision. in this case a contact point is
180
  /// returned in the CollisionResult.
181
  ///
182
  /// @note If the distance between objects is less than the security margin,
183
  ///       and the object are not colliding, the penetration depth is
184
  ///       negative.
185
58356268
  void leafCollides(unsigned int b1, unsigned int b2,
186
                    FCL_REAL& sqrDistLowerBound) const {
187
58356268
    if (this->enable_statistics) this->num_leaf_tests++;
188
189
58356268
    const BVNode<BV>& node1 = this->model1->getBV(b1);
190
58356268
    const BVNode<BV>& node2 = this->model2->getBV(b2);
191
192
58356268
    int primitive_id1 = node1.primitiveId();
193
58356268
    int primitive_id2 = node2.primitiveId();
194
195
58356268
    const Triangle& tri_id1 = tri_indices1[primitive_id1];
196
58356268
    const Triangle& tri_id2 = tri_indices2[primitive_id2];
197
198
58356268
    const Vec3f& P1 = vertices1[tri_id1[0]];
199
58356268
    const Vec3f& P2 = vertices1[tri_id1[1]];
200
58356268
    const Vec3f& P3 = vertices1[tri_id1[2]];
201
58356268
    const Vec3f& Q1 = vertices2[tri_id2[0]];
202
58356268
    const Vec3f& Q2 = vertices2[tri_id2[1]];
203
58356268
    const Vec3f& Q3 = vertices2[tri_id2[2]];
204
205
116712536
    TriangleP tri1(P1, P2, P3);
206
116712536
    TriangleP tri2(Q1, Q2, Q3);
207
58356268
    GJKSolver solver;
208
58356268
    Vec3f p1,
209
58356268
        p2;  // closest points if no collision contact points if collision.
210
58356268
    Vec3f normal;
211
    FCL_REAL distance;
212
58356268
    solver.shapeDistance(tri1, this->tf1, tri2, this->tf2, distance, p1, p2,
213
                         normal);
214
215
58356268
    const FCL_REAL distToCollision = distance - this->request.security_margin;
216
58356268
    if (distToCollision <=
217
58356268
        this->request.collision_distance_threshold) {  // collision
218
30705
      sqrDistLowerBound = 0;
219
30705
      Vec3f p(p1);  // contact point
220
30705
      if (this->result->numContacts() < this->request.num_max_contacts) {
221
        // How much (Q1, Q2, Q3) should be moved so that all vertices are
222
        // above (P1, P2, P3).
223
30705
        if (distance > 0) {
224
          normal = (p2 - p1).normalized();
225
          p = .5 * (p1 + p2);
226
        }
227

30705
        this->result->addContact(Contact(this->model1, this->model2,
228
                                         primitive_id1, primitive_id2, p,
229
                                         normal, -distance));
230
      }
231
    } else
232
58325563
      sqrDistLowerBound = distToCollision * distToCollision;
233
234
58356268
    internal::updateDistanceLowerBoundFromLeaf(this->request, *this->result,
235
                                               distToCollision, p1, p2);
236
58356268
  }
237
238
  Vec3f* vertices1;
239
  Vec3f* vertices2;
240
241
  Triangle* tri_indices1;
242
  Triangle* tri_indices2;
243
244
  details::RelativeTransformation<!bool(RTIsIdentity)> RT;
245
};
246
247
/// @brief Traversal node for collision between two meshes if their underlying
248
/// BVH node is oriented node (OBB, RSS, OBBRSS, kIOS)
249
typedef MeshCollisionTraversalNode<OBB, 0> MeshCollisionTraversalNodeOBB;
250
typedef MeshCollisionTraversalNode<RSS, 0> MeshCollisionTraversalNodeRSS;
251
typedef MeshCollisionTraversalNode<kIOS, 0> MeshCollisionTraversalNodekIOS;
252
typedef MeshCollisionTraversalNode<OBBRSS, 0> MeshCollisionTraversalNodeOBBRSS;
253
254
/// @}
255
256
namespace details {
257
template <typename BV>
258
struct DistanceTraversalBVDistanceLowerBound_impl {
259
5556
  static FCL_REAL run(const BVNode<BV>& b1, const BVNode<BV>& b2) {
260
5556
    return b1.distance(b2);
261
  }
262
2962522
  static FCL_REAL run(const Matrix3f& R, const Vec3f& T, const BVNode<BV>& b1,
263
                      const BVNode<BV>& b2) {
264
2965116
    return distance(R, T, b1.bv, b2.bv);
265
  }
266
};
267
268
template <>
269
struct DistanceTraversalBVDistanceLowerBound_impl<OBB> {
270
15564
  static FCL_REAL run(const BVNode<OBB>& b1, const BVNode<OBB>& b2) {
271
    FCL_REAL sqrDistLowerBound;
272
15564
    CollisionRequest request(DISTANCE_LOWER_BOUND, 0);
273
    // request.break_distance = ?
274

15564
    if (b1.overlap(b2, request, sqrDistLowerBound)) {
275
      // TODO A penetration upper bound should be computed.
276
10494
      return -1;
277
    }
278
5070
    return sqrt(sqrDistLowerBound);
279
  }
280
  static FCL_REAL run(const Matrix3f& R, const Vec3f& T, const BVNode<OBB>& b1,
281
                      const BVNode<OBB>& b2) {
282
    FCL_REAL sqrDistLowerBound;
283
    CollisionRequest request(DISTANCE_LOWER_BOUND, 0);
284
    // request.break_distance = ?
285
    if (overlap(R, T, b1.bv, b2.bv, request, sqrDistLowerBound)) {
286
      // TODO A penetration upper bound should be computed.
287
      return -1;
288
    }
289
    return sqrt(sqrDistLowerBound);
290
  }
291
};
292
293
template <>
294
struct DistanceTraversalBVDistanceLowerBound_impl<AABB> {
295
  static FCL_REAL run(const BVNode<AABB>& b1, const BVNode<AABB>& b2) {
296
    FCL_REAL sqrDistLowerBound;
297
    CollisionRequest request(DISTANCE_LOWER_BOUND, 0);
298
    // request.break_distance = ?
299
    if (b1.overlap(b2, request, sqrDistLowerBound)) {
300
      // TODO A penetration upper bound should be computed.
301
      return -1;
302
    }
303
    return sqrt(sqrDistLowerBound);
304
  }
305
  static FCL_REAL run(const Matrix3f& R, const Vec3f& T, const BVNode<AABB>& b1,
306
                      const BVNode<AABB>& b2) {
307
    FCL_REAL sqrDistLowerBound;
308
    CollisionRequest request(DISTANCE_LOWER_BOUND, 0);
309
    // request.break_distance = ?
310
    if (overlap(R, T, b1.bv, b2.bv, request, sqrDistLowerBound)) {
311
      // TODO A penetration upper bound should be computed.
312
      return -1;
313
    }
314
    return sqrt(sqrDistLowerBound);
315
  }
316
};
317
}  // namespace details
318
319
/// @addtogroup Traversal_For_Distance
320
/// @{
321
322
/// @brief Traversal node for distance computation between BVH models
323
template <typename BV>
324
class BVHDistanceTraversalNode : public DistanceTraversalNodeBase {
325
 public:
326
12946
  BVHDistanceTraversalNode() : DistanceTraversalNodeBase() {
327
12946
    model1 = NULL;
328
12946
    model2 = NULL;
329
330
12946
    num_bv_tests = 0;
331
12946
    num_leaf_tests = 0;
332
12946
    query_time_seconds = 0.0;
333
12946
  }
334
335
  /// @brief Whether the BV node in the first BVH tree is leaf
336
2152944
  bool isFirstNodeLeaf(unsigned int b) const {
337
2152944
    return model1->getBV(b).isLeaf();
338
  }
339
340
  /// @brief Whether the BV node in the second BVH tree is leaf
341
2152944
  bool isSecondNodeLeaf(unsigned int b) const {
342
2152944
    return model2->getBV(b).isLeaf();
343
  }
344
345
  /// @brief Determine the traversal order, is the first BVTT subtree better
346
1500900
  bool firstOverSecond(unsigned int b1, unsigned int b2) const {
347
1500900
    FCL_REAL sz1 = model1->getBV(b1).bv.size();
348
1500900
    FCL_REAL sz2 = model2->getBV(b2).bv.size();
349
350
1500900
    bool l1 = model1->getBV(b1).isLeaf();
351
1500900
    bool l2 = model2->getBV(b2).isLeaf();
352
353

1500900
    if (l2 || (!l1 && (sz1 > sz2))) return true;
354
422418
    return false;
355
  }
356
357
  /// @brief Obtain the left child of BV node in the first BVH
358
1078482
  int getFirstLeftChild(unsigned int b) const {
359
1078482
    return model1->getBV(b).leftChild();
360
  }
361
362
  /// @brief Obtain the right child of BV node in the first BVH
363
1078482
  int getFirstRightChild(unsigned int b) const {
364
1078482
    return model1->getBV(b).rightChild();
365
  }
366
367
  /// @brief Obtain the left child of BV node in the second BVH
368
422418
  int getSecondLeftChild(unsigned int b) const {
369
422418
    return model2->getBV(b).leftChild();
370
  }
371
372
  /// @brief Obtain the right child of BV node in the second BVH
373
422418
  int getSecondRightChild(unsigned int b) const {
374
422418
    return model2->getBV(b).rightChild();
375
  }
376
377
  /// @brief The first BVH model
378
  const BVHModel<BV>* model1;
379
  /// @brief The second BVH model
380
  const BVHModel<BV>* model2;
381
382
  /// @brief statistical information
383
  mutable int num_bv_tests;
384
  mutable int num_leaf_tests;
385
  mutable FCL_REAL query_time_seconds;
386
};
387
388
/// @brief Traversal node for distance computation between two meshes
389
template <typename BV, int _Options = RelativeTransformationIsIdentity>
390
class MeshDistanceTraversalNode : public BVHDistanceTraversalNode<BV> {
391
 public:
392
  enum {
393
    Options = _Options,
394
    RTIsIdentity = _Options & RelativeTransformationIsIdentity
395
  };
396
397
  using BVHDistanceTraversalNode<BV>::enable_statistics;
398
  using BVHDistanceTraversalNode<BV>::request;
399
  using BVHDistanceTraversalNode<BV>::result;
400
  using BVHDistanceTraversalNode<BV>::tf1;
401
  using BVHDistanceTraversalNode<BV>::model1;
402
  using BVHDistanceTraversalNode<BV>::model2;
403
  using BVHDistanceTraversalNode<BV>::num_bv_tests;
404
  using BVHDistanceTraversalNode<BV>::num_leaf_tests;
405
406
12946
  MeshDistanceTraversalNode() : BVHDistanceTraversalNode<BV>() {
407
12946
    vertices1 = NULL;
408
12946
    vertices2 = NULL;
409
12946
    tri_indices1 = NULL;
410
12946
    tri_indices2 = NULL;
411
412
12946
    rel_err = this->request.rel_err;
413
12946
    abs_err = this->request.abs_err;
414
12946
  }
415
416
12946
  void preprocess() {
417
12898
    if (!RTIsIdentity) preprocessOrientedNode();
418
12946
  }
419
420
12946
  void postprocess() {
421
12898
    if (!RTIsIdentity) postprocessOrientedNode();
422
12946
  }
423
424
  /// @brief BV culling test in one BVTT node
425
3001800
  FCL_REAL BVDistanceLowerBound(unsigned int b1, unsigned int b2) const {
426
3001800
    if (enable_statistics) num_bv_tests++;
427
    if (RTIsIdentity)
428
36684
      return details::DistanceTraversalBVDistanceLowerBound_impl<BV>::run(
429
73368
          model1->getBV(b1), model2->getBV(b2));
430
    else
431
2965116
      return details::DistanceTraversalBVDistanceLowerBound_impl<BV>::run(
432
5930232
          RT._R(), RT._T(), model1->getBV(b1), model2->getBV(b2));
433
  }
434
435
  /// @brief Distance testing between leaves (two triangles)
436
650868
  void leafComputeDistance(unsigned int b1, unsigned int b2) const {
437
650868
    if (this->enable_statistics) this->num_leaf_tests++;
438
439
650868
    const BVNode<BV>& node1 = this->model1->getBV(b1);
440
650868
    const BVNode<BV>& node2 = this->model2->getBV(b2);
441
442
650868
    int primitive_id1 = node1.primitiveId();
443
650868
    int primitive_id2 = node2.primitiveId();
444
445
650868
    const Triangle& tri_id1 = tri_indices1[primitive_id1];
446
650868
    const Triangle& tri_id2 = tri_indices2[primitive_id2];
447
448
650868
    const Vec3f& t11 = vertices1[tri_id1[0]];
449
650868
    const Vec3f& t12 = vertices1[tri_id1[1]];
450
650868
    const Vec3f& t13 = vertices1[tri_id1[2]];
451
452
650868
    const Vec3f& t21 = vertices2[tri_id2[0]];
453
650868
    const Vec3f& t22 = vertices2[tri_id2[1]];
454
650868
    const Vec3f& t23 = vertices2[tri_id2[2]];
455
456
    // nearest point pair
457

650868
    Vec3f P1, P2, normal;
458
459
    FCL_REAL d2;
460
    if (RTIsIdentity)
461
7202
      d2 = TriangleDistance::sqrTriDistance(t11, t12, t13, t21, t22, t23, P1,
462
                                            P2);
463
    else
464
643666
      d2 = TriangleDistance::sqrTriDistance(t11, t12, t13, t21, t22, t23,
465
                                            RT._R(), RT._T(), P1, P2);
466
650868
    FCL_REAL d = sqrt(d2);
467
468
650868
    this->result->update(d, this->model1, this->model2, primitive_id1,
469
                         primitive_id2, P1, P2, normal);
470
650868
  }
471
472
  /// @brief Whether the traversal process can stop early
473
2995702
  bool canStop(FCL_REAL c) const {
474
2995702
    if ((c >= this->result->min_distance - abs_err) &&
475
856880
        (c * (1 + rel_err) >= this->result->min_distance))
476
856880
      return true;
477
2138822
    return false;
478
  }
479
480
  Vec3f* vertices1;
481
  Vec3f* vertices2;
482
483
  Triangle* tri_indices1;
484
  Triangle* tri_indices2;
485
486
  /// @brief relative and absolute error, default value is 0.01 for both terms
487
  FCL_REAL rel_err;
488
  FCL_REAL abs_err;
489
490
  details::RelativeTransformation<!bool(RTIsIdentity)> RT;
491
492
 private:
493
12898
  void preprocessOrientedNode() {
494
12898
    const int init_tri_id1 = 0, init_tri_id2 = 0;
495
12898
    const Triangle& init_tri1 = tri_indices1[init_tri_id1];
496
12898
    const Triangle& init_tri2 = tri_indices2[init_tri_id2];
497
498

51592
    Vec3f init_tri1_points[3];
499

51592
    Vec3f init_tri2_points[3];
500
501
12898
    init_tri1_points[0] = vertices1[init_tri1[0]];
502
12898
    init_tri1_points[1] = vertices1[init_tri1[1]];
503
12898
    init_tri1_points[2] = vertices1[init_tri1[2]];
504
505
12898
    init_tri2_points[0] = vertices2[init_tri2[0]];
506
12898
    init_tri2_points[1] = vertices2[init_tri2[1]];
507
12898
    init_tri2_points[2] = vertices2[init_tri2[2]];
508
509

12898
    Vec3f p1, p2, normal;
510
12898
    FCL_REAL distance = sqrt(TriangleDistance::sqrTriDistance(
511
        init_tri1_points[0], init_tri1_points[1], init_tri1_points[2],
512
        init_tri2_points[0], init_tri2_points[1], init_tri2_points[2], RT._R(),
513
        RT._T(), p1, p2));
514
515
12898
    result->update(distance, model1, model2, init_tri_id1, init_tri_id2, p1, p2,
516
                   normal);
517
12898
  }
518
6449
  void postprocessOrientedNode() {
519
    /// the points obtained by triDistance are not in world space: both are in
520
    /// object1's local coordinate system, so we need to convert them into the
521
    /// world space.
522

12898
    if (request.enable_nearest_points && (result->o1 == model1) &&
523
36
        (result->o2 == model2)) {
524
36
      result->nearest_points[0] = tf1.transform(result->nearest_points[0]);
525
36
      result->nearest_points[1] = tf1.transform(result->nearest_points[1]);
526
    }
527
12898
  }
528
};
529
530
/// @brief Traversal node for distance computation between two meshes if their
531
/// underlying BVH node is oriented node (RSS, OBBRSS, kIOS)
532
typedef MeshDistanceTraversalNode<RSS, 0> MeshDistanceTraversalNodeRSS;
533
typedef MeshDistanceTraversalNode<kIOS, 0> MeshDistanceTraversalNodekIOS;
534
typedef MeshDistanceTraversalNode<OBBRSS, 0> MeshDistanceTraversalNodeOBBRSS;
535
536
/// @}
537
538
/// @brief for OBB and RSS, there is local coordinate of BV, so normal need to
539
/// be transformed
540
namespace details {
541
542
template <typename BV>
543
inline const Matrix3f& getBVAxes(const BV& bv) {
544
  return bv.axes;
545
}
546
547
template <>
548
inline const Matrix3f& getBVAxes<OBBRSS>(const OBBRSS& bv) {
549
  return bv.obb.axes;
550
}
551
552
}  // namespace details
553
554
}  // namespace fcl
555
556
}  // namespace hpp
557
558
/// @endcond
559
560
#endif