38 #ifndef HPP_FCL_TRAVERSAL_NODE_MESHES_H
39 #define HPP_FCL_TRAVERSAL_NODE_MESHES_H
63 template <
typename BV>
64 class BVHCollisionTraversalNode :
public CollisionTraversalNodeBase {
66 BVHCollisionTraversalNode(
const CollisionRequest& request)
67 : CollisionTraversalNodeBase(request) {
73 query_time_seconds = 0.0;
77 bool isFirstNodeLeaf(
unsigned int b)
const {
78 assert(model1 != NULL &&
"model1 is NULL");
79 return model1->getBV(b).isLeaf();
83 bool isSecondNodeLeaf(
unsigned int b)
const {
84 assert(model2 != NULL &&
"model2 is NULL");
85 return model2->getBV(b).isLeaf();
89 bool firstOverSecond(
unsigned int b1,
unsigned int b2)
const {
90 FCL_REAL sz1 = model1->getBV(b1).bv.size();
91 FCL_REAL sz2 = model2->getBV(b2).bv.size();
93 bool l1 = model1->getBV(b1).isLeaf();
94 bool l2 = model2->getBV(b2).isLeaf();
96 if (l2 || (!l1 && (sz1 > sz2)))
return true;
101 int getFirstLeftChild(
unsigned int b)
const {
102 return model1->getBV(b).leftChild();
106 int getFirstRightChild(
unsigned int b)
const {
107 return model1->getBV(b).rightChild();
111 int getSecondLeftChild(
unsigned int b)
const {
112 return model2->getBV(b).leftChild();
116 int getSecondRightChild(
unsigned int b)
const {
117 return model2->getBV(b).rightChild();
121 const BVHModel<BV>* model1;
123 const BVHModel<BV>* model2;
126 mutable int num_bv_tests;
127 mutable int num_leaf_tests;
128 mutable FCL_REAL query_time_seconds;
132 template <
typename BV,
int _Options = RelativeTransformationIsIdentity>
133 class MeshCollisionTraversalNode :
public BVHCollisionTraversalNode<BV> {
137 RTIsIdentity = _Options & RelativeTransformationIsIdentity
140 MeshCollisionTraversalNode(
const CollisionRequest& request)
141 : BVHCollisionTraversalNode<BV>(request) {
152 bool BVDisjoints(
unsigned int b1,
unsigned int b2,
153 FCL_REAL& sqrDistLowerBound)
const {
154 if (this->enable_statistics) this->num_bv_tests++;
157 disjoint = !this->model1->getBV(b1).overlap(
158 this->model2->getBV(b2), this->request, sqrDistLowerBound);
160 disjoint = !
overlap(RT._R(), RT._T(), this->model2->getBV(b2).bv,
161 this->model1->getBV(b1).bv, this->request,
184 void leafCollides(
unsigned int b1,
unsigned int b2,
185 FCL_REAL& sqrDistLowerBound)
const {
186 if (this->enable_statistics) this->num_leaf_tests++;
188 const BVNode<BV>& node1 = this->model1->getBV(b1);
189 const BVNode<BV>& node2 = this->model2->getBV(b2);
191 int primitive_id1 = node1.primitiveId();
192 int primitive_id2 = node2.primitiveId();
194 const Triangle& tri_id1 = tri_indices1[primitive_id1];
195 const Triangle& tri_id2 = tri_indices2[primitive_id2];
197 const Vec3f& P1 = vertices1[tri_id1[0]];
198 const Vec3f& P2 = vertices1[tri_id1[1]];
199 const Vec3f& P3 = vertices1[tri_id1[2]];
200 const Vec3f& Q1 = vertices2[tri_id2[0]];
201 const Vec3f& Q2 = vertices2[tri_id2[1]];
202 const Vec3f& Q3 = vertices2[tri_id2[2]];
204 TriangleP tri1(P1, P2, P3);
205 TriangleP tri2(Q1, Q2, Q3);
208 GJKSolver solver(this->request);
210 const bool compute_penetration =
211 this->request.enable_contact || (this->request.security_margin < 0);
212 Vec3f p1, p2, normal;
213 DistanceResult distanceResult;
215 &tri1, this->tf1, &tri2, this->tf2, &solver, compute_penetration, p1,
221 distToCollision, p1, p2, normal);
223 if (distToCollision <=
224 this->request.collision_distance_threshold) {
225 sqrDistLowerBound = 0;
226 if (this->result->numContacts() < this->request.num_max_contacts) {
227 this->result->addContact(Contact(this->model1, this->model2,
228 primitive_id1, primitive_id2, p1, p2,
232 sqrDistLowerBound = distToCollision * distToCollision;
238 Triangle* tri_indices1;
239 Triangle* tri_indices2;
241 details::RelativeTransformation<!bool(RTIsIdentity)> RT;
246 typedef MeshCollisionTraversalNode<OBB, 0> MeshCollisionTraversalNodeOBB;
247 typedef MeshCollisionTraversalNode<RSS, 0> MeshCollisionTraversalNodeRSS;
248 typedef MeshCollisionTraversalNode<kIOS, 0> MeshCollisionTraversalNodekIOS;
249 typedef MeshCollisionTraversalNode<OBBRSS, 0> MeshCollisionTraversalNodeOBBRSS;
254 template <
typename BV>
255 struct DistanceTraversalBVDistanceLowerBound_impl {
256 static FCL_REAL run(
const BVNode<BV>& b1,
const BVNode<BV>& b2) {
257 return b1.distance(b2);
260 const BVNode<BV>& b2) {
261 return distance(R, T, b1.bv, b2.bv);
266 struct DistanceTraversalBVDistanceLowerBound_impl<OBB> {
267 static FCL_REAL run(
const BVNode<OBB>& b1,
const BVNode<OBB>& b2) {
271 if (b1.overlap(b2, request, sqrDistLowerBound)) {
275 return sqrt(sqrDistLowerBound);
278 const BVNode<OBB>& b2) {
282 if (
overlap(R, T, b1.bv, b2.bv, request, sqrDistLowerBound)) {
286 return sqrt(sqrDistLowerBound);
291 struct DistanceTraversalBVDistanceLowerBound_impl<AABB> {
292 static FCL_REAL run(
const BVNode<AABB>& b1,
const BVNode<AABB>& b2) {
296 if (b1.overlap(b2, request, sqrDistLowerBound)) {
300 return sqrt(sqrDistLowerBound);
303 const BVNode<AABB>& b2) {
307 if (
overlap(R, T, b1.bv, b2.bv, request, sqrDistLowerBound)) {
311 return sqrt(sqrDistLowerBound);
320 template <
typename BV>
321 class BVHDistanceTraversalNode :
public DistanceTraversalNodeBase {
323 BVHDistanceTraversalNode() : DistanceTraversalNodeBase() {
329 query_time_seconds = 0.0;
333 bool isFirstNodeLeaf(
unsigned int b)
const {
334 return model1->getBV(b).isLeaf();
338 bool isSecondNodeLeaf(
unsigned int b)
const {
339 return model2->getBV(b).isLeaf();
343 bool firstOverSecond(
unsigned int b1,
unsigned int b2)
const {
344 FCL_REAL sz1 = model1->getBV(b1).bv.size();
345 FCL_REAL sz2 = model2->getBV(b2).bv.size();
347 bool l1 = model1->getBV(b1).isLeaf();
348 bool l2 = model2->getBV(b2).isLeaf();
350 if (l2 || (!l1 && (sz1 > sz2)))
return true;
355 int getFirstLeftChild(
unsigned int b)
const {
356 return model1->getBV(b).leftChild();
360 int getFirstRightChild(
unsigned int b)
const {
361 return model1->getBV(b).rightChild();
365 int getSecondLeftChild(
unsigned int b)
const {
366 return model2->getBV(b).leftChild();
370 int getSecondRightChild(
unsigned int b)
const {
371 return model2->getBV(b).rightChild();
375 const BVHModel<BV>* model1;
377 const BVHModel<BV>* model2;
380 mutable int num_bv_tests;
381 mutable int num_leaf_tests;
382 mutable FCL_REAL query_time_seconds;
386 template <
typename BV,
int _Options = RelativeTransformationIsIdentity>
387 class MeshDistanceTraversalNode :
public BVHDistanceTraversalNode<BV> {
391 RTIsIdentity = _Options & RelativeTransformationIsIdentity
394 using BVHDistanceTraversalNode<BV>::enable_statistics;
395 using BVHDistanceTraversalNode<BV>::request;
396 using BVHDistanceTraversalNode<BV>::result;
397 using BVHDistanceTraversalNode<BV>::tf1;
398 using BVHDistanceTraversalNode<BV>::model1;
399 using BVHDistanceTraversalNode<BV>::model2;
400 using BVHDistanceTraversalNode<BV>::num_bv_tests;
401 using BVHDistanceTraversalNode<BV>::num_leaf_tests;
403 MeshDistanceTraversalNode() : BVHDistanceTraversalNode<BV>() {
409 rel_err = this->request.rel_err;
410 abs_err = this->request.abs_err;
414 if (!RTIsIdentity) preprocessOrientedNode();
418 if (!RTIsIdentity) postprocessOrientedNode();
422 FCL_REAL BVDistanceLowerBound(
unsigned int b1,
unsigned int b2)
const {
423 if (enable_statistics) num_bv_tests++;
425 return details::DistanceTraversalBVDistanceLowerBound_impl<BV>::run(
426 model1->getBV(b1), model2->getBV(b2));
428 return details::DistanceTraversalBVDistanceLowerBound_impl<BV>::run(
429 RT._R(), RT._T(), model1->getBV(b1), model2->getBV(b2));
433 void leafComputeDistance(
unsigned int b1,
unsigned int b2)
const {
434 if (this->enable_statistics) this->num_leaf_tests++;
436 const BVNode<BV>& node1 = this->model1->getBV(b1);
437 const BVNode<BV>& node2 = this->model2->getBV(b2);
439 int primitive_id1 = node1.primitiveId();
440 int primitive_id2 = node2.primitiveId();
442 const Triangle& tri_id1 = tri_indices1[primitive_id1];
443 const Triangle& tri_id2 = tri_indices2[primitive_id2];
445 const Vec3f& t11 = vertices1[tri_id1[0]];
446 const Vec3f& t12 = vertices1[tri_id1[1]];
447 const Vec3f& t13 = vertices1[tri_id1[2]];
449 const Vec3f& t21 = vertices2[tri_id2[0]];
450 const Vec3f& t22 = vertices2[tri_id2[1]];
451 const Vec3f& t23 = vertices2[tri_id2[2]];
454 Vec3f P1, P2, normal;
458 d2 = TriangleDistance::sqrTriDistance(t11, t12, t13, t21, t22, t23, P1,
461 d2 = TriangleDistance::sqrTriDistance(t11, t12, t13, t21, t22, t23,
462 RT._R(), RT._T(), P1, P2);
465 this->result->update(d, this->model1, this->model2, primitive_id1,
466 primitive_id2, P1, P2, normal);
471 if ((c >= this->result->min_distance - abs_err) &&
472 (c * (1 + rel_err) >= this->result->min_distance))
480 Triangle* tri_indices1;
481 Triangle* tri_indices2;
487 details::RelativeTransformation<!bool(RTIsIdentity)> RT;
490 void preprocessOrientedNode() {
491 const int init_tri_id1 = 0, init_tri_id2 = 0;
492 const Triangle& init_tri1 = tri_indices1[init_tri_id1];
493 const Triangle& init_tri2 = tri_indices2[init_tri_id2];
495 Vec3f init_tri1_points[3];
496 Vec3f init_tri2_points[3];
498 init_tri1_points[0] = vertices1[init_tri1[0]];
499 init_tri1_points[1] = vertices1[init_tri1[1]];
500 init_tri1_points[2] = vertices1[init_tri1[2]];
502 init_tri2_points[0] = vertices2[init_tri2[0]];
503 init_tri2_points[1] = vertices2[init_tri2[1]];
504 init_tri2_points[2] = vertices2[init_tri2[2]];
506 Vec3f p1, p2, normal;
508 init_tri1_points[0], init_tri1_points[1], init_tri1_points[2],
509 init_tri2_points[0], init_tri2_points[1], init_tri2_points[2], RT._R(),
512 result->update(
distance, model1, model2, init_tri_id1, init_tri_id2, p1, p2,
515 void postprocessOrientedNode() {
519 if (request.enable_nearest_points && (result->o1 == model1) &&
520 (result->o2 == model2)) {
521 result->nearest_points[0] = tf1.transform(result->nearest_points[0]);
522 result->nearest_points[1] = tf1.transform(result->nearest_points[1]);
529 typedef MeshDistanceTraversalNode<RSS, 0> MeshDistanceTraversalNodeRSS;
530 typedef MeshDistanceTraversalNode<kIOS, 0> MeshDistanceTraversalNodekIOS;
531 typedef MeshDistanceTraversalNode<OBBRSS, 0> MeshDistanceTraversalNodeOBBRSS;
539 template <
typename BV>
540 inline const Matrix3f& getBVAxes(
const BV& bv) {
545 inline const Matrix3f& getBVAxes<OBBRSS>(
const OBBRSS& bv) {
FCL_REAL distance(const Matrix3f &R0, const Vec3f &T0, const kIOS &b1, const kIOS &b2, Vec3f *P=NULL, Vec3f *Q=NULL)
Approximate distance between two kIOS bounding volumes.
bool overlap(const Matrix3f &R0, const Vec3f &T0, const AABB &b1, const AABB &b2)
Check collision between two aabbs, b1 is in configuration (R0, T0) and b2 is in identity.
void updateDistanceLowerBoundFromLeaf(const CollisionRequest &, CollisionResult &res, const FCL_REAL &distance, const Vec3f &p0, const Vec3f &p1, const Vec3f &normal)
Definition: collision_data.h:1186
void updateDistanceLowerBoundFromBV(const CollisionRequest &, CollisionResult &res, const FCL_REAL sqrDistLowerBound)
Definition: collision_data.h:1177
Eigen::Matrix< FCL_REAL, 3, 3 > Matrix3f
Definition: data_types.h:71
Eigen::Matrix< FCL_REAL, 3, 1 > Vec3f
Definition: data_types.h:67
@ DISTANCE_LOWER_BOUND
Definition: collision_data.h:307
double FCL_REAL
Definition: data_types.h:66
Main namespace.
Definition: broadphase_bruteforce.h:44