37 #ifndef COAL_TRAVERSAL_NODE_BVH_HFIELD_H
38 #define COAL_TRAVERSAL_NODE_BVH_HFIELD_H
65 template <
typename BV1,
typename BV2,
66 int _Options = RelativeTransformationIsIdentity>
67 class MeshHeightFieldCollisionTraversalNode
68 :
public CollisionTraversalNodeBase {
72 RTIsIdentity = _Options & RelativeTransformationIsIdentity
75 MeshHeightFieldCollisionTraversalNode(
const CollisionRequest& request)
76 : CollisionTraversalNodeBase(request) {
82 query_time_seconds = 0.0;
89 bool isFirstNodeLeaf(
unsigned int b)
const {
90 assert(model1 != NULL &&
"model1 is NULL");
91 return model1->getBV(
b).isLeaf();
95 bool isSecondNodeLeaf(
unsigned int b)
const {
96 assert(model2 != NULL &&
"model2 is NULL");
97 return model2->getBV(
b).isLeaf();
101 bool firstOverSecond(
unsigned int b1,
unsigned int b2)
const {
105 bool l1 = model1->getBV(b1).isLeaf();
106 bool l2 = model2->getBV(b2).isLeaf();
108 if (l2 || (!l1 && (sz1 > sz2)))
return true;
113 int getFirstLeftChild(
unsigned int b)
const {
114 return model1->getBV(
b).leftChild();
118 int getFirstRightChild(
unsigned int b)
const {
119 return model1->getBV(
b).rightChild();
123 int getSecondLeftChild(
unsigned int b)
const {
124 return model2->getBV(
b).leftChild();
128 int getSecondRightChild(
unsigned int b)
const {
129 return model2->getBV(
b).rightChild();
133 bool BVDisjoints(
unsigned int b1,
unsigned int b2)
const {
134 if (this->enable_statistics) this->num_bv_tests++;
136 return !this->model1->getBV(b1).overlap(this->model2->getBV(b2));
138 return !
overlap(RT._R(), RT._T(), this->model1->getBV(b1).bv,
139 this->model2->getBV(b2).bv);
146 bool BVDisjoints(
unsigned int b1,
unsigned int b2,
148 if (this->enable_statistics) this->num_bv_tests++;
150 return !this->model1->getBV(b1).overlap(this->model2->getBV(b2),
151 this->request, sqrDistLowerBound);
153 bool res = !
overlap(RT._R(), RT._T(), this->model1->getBV(b1).bv,
154 this->model2->getBV(b2).bv, this->request,
156 assert(!res || sqrDistLowerBound > 0);
175 void leafCollides(
unsigned int b1,
unsigned int b2,
177 if (this->enable_statistics) this->num_leaf_tests++;
179 const BVNode<BV1>& node1 = this->model1->getBV(b1);
180 const HeightFieldNode<BV2>& node2 = this->model2->getBV(b2);
182 int primitive_id1 = node1.primitiveId();
183 const Triangle& tri_id1 = tri_indices1[primitive_id1];
185 const Vec3s&
P1 = vertices1[tri_id1[0]];
186 const Vec3s&
P2 = vertices1[tri_id1[1]];
187 const Vec3s&
P3 = vertices1[tri_id1[2]];
189 TriangleP tri1(
P1,
P2,
P3);
191 typedef Convex<Triangle> ConvexTriangle;
192 ConvexTriangle convex1, convex2;
193 details::buildConvexTriangles(node2, *this->model2, convex2, convex2);
200 solver.shapeDistance(tri1, this->
tf1, tri2, this->
tf2, distance,
p1, p2,
204 if (distToCollision <= 0) {
207 if (this->result->numContacts() < this->request.num_max_contacts) {
212 normal = (p2 -
p1).normalized();
215 this->result->addContact(Contact(this->model1, this->model2,
216 primitive_id1, primitive_id2, p,
217 normal, penetrationDepth));
223 const BVHModel<BV1>* model1;
225 const HeightField<BV2>* model2;
228 mutable int num_bv_tests;
229 mutable int num_leaf_tests;
232 Vec3s* vertices1 Triangle* tri_indices1;
234 details::RelativeTransformation<!bool(RTIsIdentity)> RT;
239 typedef MeshHeightFieldCollisionTraversalNode<OBB, 0>
240 MeshHeightFieldCollisionTraversalNodeOBB;
241 typedef MeshHeightFieldCollisionTraversalNode<RSS, 0>
242 MeshHeightFieldCollisionTraversalNodeRSS;
243 typedef MeshHeightFieldCollisionTraversalNode<kIOS, 0>
244 MeshHeightFieldCollisionTraversalNodekIOS;
245 typedef MeshHeightFieldCollisionTraversalNode<OBBRSS, 0>
246 MeshHeightFieldCollisionTraversalNodeOBBRSS;
251 template <
typename BV>
252 struct DistanceTraversalBVDistanceLowerBound_impl {
253 static CoalScalar run(
const BVNode<BV>& b1,
const BVNode<BV>& b2) {
254 return b1.distance(b2);
257 const BVNode<BV>& b2) {
258 return distance(R, T, b1.bv, b2.bv);
263 struct DistanceTraversalBVDistanceLowerBound_impl<OBB> {
264 static CoalScalar run(
const BVNode<OBB>& b1,
const BVNode<OBB>& b2) {
268 if (b1.overlap(b2, request, sqrDistLowerBound)) {
272 return sqrt(sqrDistLowerBound);
275 const BVNode<OBB>& b1,
const BVNode<OBB>& b2) {
279 if (
overlap(R, T, b1.bv, b2.bv, request, sqrDistLowerBound)) {
283 return sqrt(sqrDistLowerBound);
288 struct DistanceTraversalBVDistanceLowerBound_impl<AABB> {
289 static CoalScalar run(
const BVNode<AABB>& b1,
const BVNode<AABB>& b2) {
293 if (b1.overlap(b2, request, sqrDistLowerBound)) {
297 return sqrt(sqrDistLowerBound);
300 const BVNode<AABB>& b1,
const BVNode<AABB>& b2) {
304 if (
overlap(R, T, b1.bv, b2.bv, request, sqrDistLowerBound)) {
308 return sqrt(sqrDistLowerBound);
317 template <
typename BV>
318 class BVHDistanceTraversalNode :
public DistanceTraversalNodeBase {
320 BVHDistanceTraversalNode() : DistanceTraversalNodeBase() {
326 query_time_seconds = 0.0;
330 bool isFirstNodeLeaf(
unsigned int b)
const {
331 return model1->getBV(
b).isLeaf();
335 bool isSecondNodeLeaf(
unsigned int b)
const {
336 return model2->getBV(
b).isLeaf();
340 bool firstOverSecond(
unsigned int b1,
unsigned int b2)
const {
344 bool l1 = model1->getBV(b1).isLeaf();
345 bool l2 = model2->getBV(b2).isLeaf();
347 if (l2 || (!l1 && (sz1 > sz2)))
return true;
352 int getFirstLeftChild(
unsigned int b)
const {
353 return model1->getBV(
b).leftChild();
357 int getFirstRightChild(
unsigned int b)
const {
358 return model1->getBV(
b).rightChild();
362 int getSecondLeftChild(
unsigned int b)
const {
363 return model2->getBV(
b).leftChild();
367 int getSecondRightChild(
unsigned int b)
const {
368 return model2->getBV(
b).rightChild();
372 const BVHModel<BV>* model1;
374 const BVHModel<BV>* model2;
377 mutable int num_bv_tests;
378 mutable int num_leaf_tests;
383 template <
typename BV,
int _Options = RelativeTransformationIsIdentity>
384 class MeshDistanceTraversalNode :
public BVHDistanceTraversalNode<BV> {
388 RTIsIdentity = _Options & RelativeTransformationIsIdentity
391 using BVHDistanceTraversalNode<BV>::enable_statistics;
392 using BVHDistanceTraversalNode<BV>::request;
393 using BVHDistanceTraversalNode<BV>::result;
395 using BVHDistanceTraversalNode<BV>::model1;
396 using BVHDistanceTraversalNode<BV>::model2;
397 using BVHDistanceTraversalNode<BV>::num_bv_tests;
398 using BVHDistanceTraversalNode<BV>::num_leaf_tests;
400 MeshDistanceTraversalNode() : BVHDistanceTraversalNode<BV>() {
406 rel_err = this->request.rel_err;
407 abs_err = this->request.abs_err;
411 if (!RTIsIdentity) preprocessOrientedNode();
415 if (!RTIsIdentity) postprocessOrientedNode();
419 CoalScalar BVDistanceLowerBound(
unsigned int b1,
unsigned int b2)
const {
420 if (enable_statistics) num_bv_tests++;
423 model1->getBV(b1), model2->getBV(b2));
426 RT._R(), RT._T(), model1->getBV(b1), model2->getBV(b2));
430 void leafComputeDistance(
unsigned int b1,
unsigned int b2)
const {
431 if (this->enable_statistics) this->num_leaf_tests++;
433 const BVNode<BV>& node1 = this->model1->getBV(b1);
434 const BVNode<BV>& node2 = this->model2->getBV(b2);
436 int primitive_id1 = node1.primitiveId();
437 int primitive_id2 = node2.primitiveId();
439 const Triangle& tri_id1 = tri_indices1[primitive_id1];
440 const Triangle& tri_id2 = tri_indices2[primitive_id2];
442 const Vec3s& t11 = vertices1[tri_id1[0]];
443 const Vec3s& t12 = vertices1[tri_id1[1]];
444 const Vec3s& t13 = vertices1[tri_id1[2]];
446 const Vec3s& t21 = vertices2[tri_id2[0]];
447 const Vec3s& t22 = vertices2[tri_id2[1]];
448 const Vec3s& t23 = vertices2[tri_id2[2]];
455 d2 = TriangleDistance::sqrTriDistance(t11, t12, t13, t21, t22, t23,
P1,
458 d2 = TriangleDistance::sqrTriDistance(t11, t12, t13, t21, t22, t23,
459 RT._R(), RT._T(),
P1,
P2);
462 this->result->update(d, this->model1, this->model2, primitive_id1,
463 primitive_id2,
P1,
P2, normal);
468 if ((c >= this->result->min_distance - abs_err) &&
469 (c * (1 + rel_err) >= this->result->min_distance))
477 Triangle* tri_indices1;
478 Triangle* tri_indices2;
484 details::RelativeTransformation<!bool(RTIsIdentity)> RT;
487 void preprocessOrientedNode() {
488 const int init_tri_id1 = 0, init_tri_id2 = 0;
489 const Triangle& init_tri1 = tri_indices1[init_tri_id1];
490 const Triangle& init_tri2 = tri_indices2[init_tri_id2];
492 Vec3s init_tri1_points[3];
493 Vec3s init_tri2_points[3];
495 init_tri1_points[0] = vertices1[init_tri1[0]];
496 init_tri1_points[1] = vertices1[init_tri1[1]];
497 init_tri1_points[2] = vertices1[init_tri1[2]];
499 init_tri2_points[0] = vertices2[init_tri2[0]];
500 init_tri2_points[1] = vertices2[init_tri2[1]];
501 init_tri2_points[2] = vertices2[init_tri2[2]];
505 init_tri1_points[0], init_tri1_points[1], init_tri1_points[2],
506 init_tri2_points[0], init_tri2_points[1], init_tri2_points[2], RT._R(),
509 result->update(
distance, model1, model2, init_tri_id1, init_tri_id2,
p1, p2,
512 void postprocessOrientedNode() {
516 if (request.enable_nearest_points && (result->o1 == model1) &&
517 (result->o2 == model2)) {
518 result->nearest_points[0] =
tf1.transform(result->nearest_points[0]);
519 result->nearest_points[1] =
tf1.transform(result->nearest_points[1]);
526 typedef MeshDistanceTraversalNode<RSS, 0> MeshDistanceTraversalNodeRSS;
527 typedef MeshDistanceTraversalNode<kIOS, 0> MeshDistanceTraversalNodekIOS;
528 typedef MeshDistanceTraversalNode<OBBRSS, 0> MeshDistanceTraversalNodeOBBRSS;
536 template <
typename BV>
537 inline const Matrix3s& getBVAxes(
const BV& bv) {
542 inline const Matrix3s& getBVAxes<OBBRSS>(
const OBBRSS& bv) {