38 #ifndef COAL_TRAVERSAL_NODE_MESH_SHAPE_H
39 #define COAL_TRAVERSAL_NODE_MESH_SHAPE_H
58 template <
typename BV,
typename S>
59 class BVHShapeCollisionTraversalNode :
public CollisionTraversalNodeBase {
61 BVHShapeCollisionTraversalNode(
const CollisionRequest& request)
62 : CollisionTraversalNodeBase(request) {
68 query_time_seconds = 0.0;
72 bool isFirstNodeLeaf(
unsigned int b)
const {
73 return model1->getBV(
b).isLeaf();
77 int getFirstLeftChild(
unsigned int b)
const {
78 return model1->getBV(
b).leftChild();
82 int getFirstRightChild(
unsigned int b)
const {
83 return model1->getBV(
b).rightChild();
86 const BVHModel<BV>* model1;
90 mutable int num_bv_tests;
91 mutable int num_leaf_tests;
96 template <
typename BV,
typename S,
97 int _Options = RelativeTransformationIsIdentity>
98 class MeshShapeCollisionTraversalNode
99 :
public BVHShapeCollisionTraversalNode<BV, S> {
103 RTIsIdentity = _Options & RelativeTransformationIsIdentity
106 MeshShapeCollisionTraversalNode(
const CollisionRequest& request)
107 : BVHShapeCollisionTraversalNode<BV, S>(request) {
119 bool BVDisjoints(
unsigned int b1,
unsigned int ,
121 if (this->enable_statistics) this->num_bv_tests++;
124 disjoint = !this->model1->getBV(b1).bv.overlap(
125 this->model2_bv, this->request, sqrDistLowerBound);
127 disjoint = !
overlap(this->
tf1.getRotation(), this->tf1.getTranslation(),
128 this->model1->getBV(b1).bv, this->model2_bv,
129 this->request, sqrDistLowerBound);
133 assert(!disjoint || sqrDistLowerBound > 0);
138 void leafCollides(
unsigned int b1,
unsigned int ,
140 if (this->enable_statistics) this->num_leaf_tests++;
141 const BVNode<BV>& node = this->model1->getBV(b1);
143 int primitive_id = node.primitiveId();
145 const Triangle& tri_id = this->tri_indices[primitive_id];
146 const TriangleP tri(this->vertices[tri_id[0]], this->vertices[tri_id[1]],
147 this->vertices[tri_id[2]]);
154 const bool compute_penetration =
155 this->request.enable_contact || (this->request.security_margin < 0);
160 static const Transform3s Id;
161 distance = internal::ShapeShapeDistance<TriangleP, S>(
162 &tri, Id, this->model2, this->
tf2, this->nsolver, compute_penetration,
165 distance = internal::ShapeShapeDistance<TriangleP, S>(
166 &tri, this->
tf1, this->model2, this->
tf2, this->nsolver,
167 compute_penetration, c1, c2, normal);
172 distToCollision, c1, c2, normal);
174 if (distToCollision <= this->request.collision_distance_threshold) {
175 sqrDistLowerBound = 0;
176 if (this->result->numContacts() < this->request.num_max_contacts) {
177 this->result->addContact(Contact(this->model1, this->model2,
180 assert(this->result->isCollision());
183 sqrDistLowerBound = distToCollision * distToCollision;
186 assert(this->result->isCollision() || sqrDistLowerBound > 0);
190 Triangle* tri_indices;
192 const GJKSolver* nsolver;
201 template <
typename BV,
typename S>
202 class BVHShapeDistanceTraversalNode :
public DistanceTraversalNodeBase {
204 BVHShapeDistanceTraversalNode() : DistanceTraversalNodeBase() {
210 query_time_seconds = 0.0;
214 bool isFirstNodeLeaf(
unsigned int b)
const {
215 return model1->getBV(
b).isLeaf();
219 int getFirstLeftChild(
unsigned int b)
const {
220 return model1->getBV(
b).leftChild();
224 int getFirstRightChild(
unsigned int b)
const {
225 return model1->getBV(
b).rightChild();
229 CoalScalar BVDistanceLowerBound(
unsigned int b1,
unsigned int )
const {
230 return model1->getBV(b1).bv.distance(model2_bv);
233 const BVHModel<BV>* model1;
237 mutable int num_bv_tests;
238 mutable int num_leaf_tests;
243 template <
typename S,
typename BV>
244 class ShapeBVHDistanceTraversalNode :
public DistanceTraversalNodeBase {
246 ShapeBVHDistanceTraversalNode() : DistanceTraversalNodeBase() {
252 query_time_seconds = 0.0;
256 bool isSecondNodeLeaf(
unsigned int b)
const {
257 return model2->getBV(
b).isLeaf();
261 int getSecondLeftChild(
unsigned int b)
const {
262 return model2->getBV(
b).leftChild();
266 int getSecondRightChild(
unsigned int b)
const {
267 return model2->getBV(
b).rightChild();
271 CoalScalar BVDistanceLowerBound(
unsigned int ,
unsigned int b2)
const {
272 return model1_bv.distance(model2->getBV(b2).bv);
276 const BVHModel<BV>* model2;
279 mutable int num_bv_tests;
280 mutable int num_leaf_tests;
285 template <
typename BV,
typename S>
286 class MeshShapeDistanceTraversalNode
287 :
public BVHShapeDistanceTraversalNode<BV, S> {
289 MeshShapeDistanceTraversalNode() : BVHShapeDistanceTraversalNode<BV, S>() {
300 void leafComputeDistance(
unsigned int b1,
unsigned int )
const {
301 if (this->enable_statistics) this->num_leaf_tests++;
303 const BVNode<BV>& node = this->model1->getBV(b1);
305 int primitive_id = node.primitiveId();
307 const Triangle& tri_id = tri_indices[primitive_id];
308 const TriangleP tri(this->vertices[tri_id[0]], this->vertices[tri_id[1]],
309 this->vertices[tri_id[2]]);
313 &tri, this->
tf1, this->model2, this->
tf2, this->nsolver,
314 this->request.enable_signed_distance,
p1, p2, normal);
316 this->result->update(
distance, this->model1, this->model2, primitive_id,
322 if ((c >= this->result->min_distance - abs_err) &&
323 (c * (1 + rel_err) >= this->result->min_distance))
329 Triangle* tri_indices;
334 const GJKSolver* nsolver;
340 template <
typename BV,
typename S>
341 void meshShapeDistanceOrientedNodeleafComputeDistance(
342 unsigned int b1,
unsigned int ,
const BVHModel<BV>* model1,
343 const S& model2,
Vec3s* vertices, Triangle* tri_indices,
344 const Transform3s&
tf1,
const Transform3s&
tf2,
const GJKSolver* nsolver,
345 bool enable_statistics,
int& num_leaf_tests,
const DistanceRequest& request,
346 DistanceResult& result) {
347 if (enable_statistics) num_leaf_tests++;
349 const BVNode<BV>& node = model1->getBV(b1);
350 int primitive_id = node.primitiveId();
352 const Triangle& tri_id = tri_indices[primitive_id];
353 const TriangleP tri(vertices[tri_id[0]], vertices[tri_id[1]],
354 vertices[tri_id[2]]);
358 &tri,
tf1, &model2,
tf2, nsolver, request.enable_signed_distance,
p1, p2,
365 template <
typename BV,
typename S>
366 static inline void distancePreprocessOrientedNode(
367 const BVHModel<BV>* model1,
Vec3s* vertices, Triangle* tri_indices,
368 int init_tri_id,
const S& model2,
const Transform3s&
tf1,
369 const Transform3s&
tf2,
const GJKSolver* nsolver,
370 const DistanceRequest& request, DistanceResult& result) {
371 const Triangle& tri_id = tri_indices[init_tri_id];
372 const TriangleP tri(vertices[tri_id[0]], vertices[tri_id[1]],
373 vertices[tri_id[2]]);
377 &tri,
tf1, &model2,
tf2, nsolver, request.enable_signed_distance,
p1, p2,
389 template <
typename S>
391 :
public MeshShapeDistanceTraversalNode<RSS, S> {
394 : MeshShapeDistanceTraversalNode<RSS, S>() {}
397 details::distancePreprocessOrientedNode(
398 this->model1, this->vertices, this->tri_indices, 0, *(this->model2),
399 this->tf1, this->tf2, this->nsolver, this->request, *(this->result));
405 if (this->enable_statistics) this->num_bv_tests++;
406 return distance(this->tf1.getRotation(), this->tf1.getTranslation(),
407 this->model2_bv, this->model1->getBV(b1).bv);
411 details::meshShapeDistanceOrientedNodeleafComputeDistance(
412 b1, b2, this->model1, *(this->model2), this->vertices,
413 this->tri_indices, this->tf1, this->tf2, this->nsolver,
414 this->enable_statistics, this->num_leaf_tests, this->request,
419 template <
typename S>
421 :
public MeshShapeDistanceTraversalNode<kIOS, S> {
424 : MeshShapeDistanceTraversalNode<kIOS, S>() {}
427 details::distancePreprocessOrientedNode(
428 this->model1, this->vertices, this->tri_indices, 0, *(this->model2),
429 this->tf1, this->tf2, this->nsolver, this->request, *(this->result));
435 if (this->enable_statistics) this->num_bv_tests++;
436 return distance(this->tf1.getRotation(), this->tf1.getTranslation(),
437 this->model2_bv, this->model1->getBV(b1).bv);
441 details::meshShapeDistanceOrientedNodeleafComputeDistance(
442 b1, b2, this->model1, *(this->model2), this->vertices,
443 this->tri_indices, this->tf1, this->tf2, this->nsolver,
444 this->enable_statistics, this->num_leaf_tests, this->request,
449 template <
typename S>
451 :
public MeshShapeDistanceTraversalNode<OBBRSS, S> {
454 : MeshShapeDistanceTraversalNode<OBBRSS, S>() {}
457 details::distancePreprocessOrientedNode(
458 this->model1, this->vertices, this->tri_indices, 0, *(this->model2),
459 this->tf1, this->tf2, this->nsolver, this->request, *(this->result));
465 if (this->enable_statistics) this->num_bv_tests++;
466 return distance(this->tf1.getRotation(), this->tf1.getTranslation(),
467 this->model2_bv, this->model1->getBV(b1).bv);
471 details::meshShapeDistanceOrientedNodeleafComputeDistance(
472 b1, b2, this->model1, *(this->model2), this->vertices,
473 this->tri_indices, this->tf1, this->tf2, this->nsolver,
474 this->enable_statistics, this->num_leaf_tests, this->request,