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) {