1#include "CollistionDetectionBoundingBox.h"
3#include "Primitive/Primitive3D.h"
4#include "Topology/DiscreteElements.h"
8 typedef typename ::dyno::TOrientedBox3D<Real> Box3D;
10 template<typename TDataType>
11 CollistionDetectionBoundingBox<TDataType>::CollistionDetectionBoundingBox()
16 template<typename TDataType>
17 CollistionDetectionBoundingBox<TDataType>::~CollistionDetectionBoundingBox()
22 template <typename Coord>
23 __global__ void CountContactsWithBoundary(
24 DArray<Sphere3D> sphere,
27 DArray<Capsule3D> cap,
31 ElementOffset elementOffset)
33 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
34 if (pId >= count.size()) return;
36 ElementType eleType = elementOffset.checkElementType(pId);
38 if (eleType == ET_SPHERE)//sphere
42 Sphere3D sp = sphere[pId - elementOffset.sphereIndex()];
44 Real radius = sp.radius;
45 Coord center = sp.center;
47 if (center.x + radius >= hi.x)
51 if (center.x - radius <= lo.x)
56 if (center.y + radius >= hi.y)
60 if (center.y - radius <= lo.y)
65 if (center.z + radius >= hi.z)
69 if (center.z - radius <= lo.z)
76 else if (eleType == ET_BOX)//box
78 //int idx = pId - start_box;
81 Coord center = box[pId - elementOffset.boxIndex()].center;
82 Coord u = box[pId - elementOffset.boxIndex()].u;
83 Coord v = box[pId - elementOffset.boxIndex()].v;
84 Coord w = box[pId - elementOffset.boxIndex()].w;
85 Coord extent = box[pId - elementOffset.boxIndex()].extent;
87 p[0] = Point3D(center - u * extent[0] - v * extent[1] - w * extent[2]);
88 p[1] = Point3D(center - u * extent[0] - v * extent[1] + w * extent[2]);
89 p[2] = Point3D(center - u * extent[0] + v * extent[1] - w * extent[2]);
90 p[3] = Point3D(center - u * extent[0] + v * extent[1] + w * extent[2]);
91 p[4] = Point3D(center + u * extent[0] - v * extent[1] - w * extent[2]);
92 p[5] = Point3D(center + u * extent[0] - v * extent[1] + w * extent[2]);
93 p[6] = Point3D(center + u * extent[0] + v * extent[1] - w * extent[2]);
94 p[7] = Point3D(center + u * extent[0] + v * extent[1] + w * extent[2]);
95 bool c1, c2, c3, c4, c5, c6;
96 c1 = c2 = c3 = c4 = c5 = c6 = true;
97 for (int i = 0; i < 8; i++)
99 Coord pos = p[i].origin;
100 if (pos[0] > hi[0] && c1)
105 if (pos[1] > hi[1] && c2)
110 if (pos[2] > hi[2] && c3)
115 if (pos[0] < lo[0] && c4)
120 if (pos[1] < lo[1] && c5)
125 if (pos[2] < lo[2] && c6)
133 else if (eleType == ET_TET) // tets
136 int start_i = count[pId];
138 Tet3D tet_i = tet[pId - elementOffset.tetIndex()];
140 for (int i = 0; i < 4; i++)
142 Coord vertex = tet_i.v[i];
143 if (vertex.x >= hi.x)
147 if (vertex.x <= lo.x)
152 if (vertex.y >= hi.y)
156 if (vertex.y <= lo.y)
161 if (vertex.z >= hi.z)
165 if (vertex.z <= lo.z)
173 else if (eleType == ET_CAPSULE)//segments
177 Capsule3D cap_i = cap[pId - elementOffset.capsuleIndex()];
179 Coord v0 = cap_i.startPoint();
180 Coord v1 = cap_i.endPoint();
182 Real radius = cap_i.radius;
184 if (v0.x + radius >= hi.x)
188 if (v0.x - radius <= lo.x)
193 if (v0.y + radius >= hi.y)
197 if (v0.y - radius <= lo.y)
202 if (v0.z + radius >= hi.z)
206 if (v0.z - radius <= lo.z)
213 if (v1.x + radius >= hi.x)
217 if (v1.x - radius <= lo.x)
222 if (v1.y + radius >= hi.y)
226 if (v1.y - radius <= lo.y)
231 if (v1.z + radius >= hi.z)
235 if (v1.z - radius <= lo.z)
244 template <typename Coord, typename ContactPair>
245 __global__ void SetupContactsWithBoundary(
246 DArray<Sphere3D> sphere,
249 DArray<Capsule3D> cap,
251 DArray<ContactPair> nbq,
252 DArray<Pair<uint, uint>> mapping,
255 ElementOffset elementOffset)
257 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
258 if (pId >= count.size()) return;
260 ElementType eleType = elementOffset.checkElementType(pId);
262 uint rbId = mapping[pId].second;
264 if (eleType == ET_SPHERE)//sphere
267 int start_i = count[pId];
269 Sphere3D sp = sphere[pId - elementOffset.sphereIndex()];
271 Real radius = sp.radius;
272 Coord center = sp.center;
274 if (center.x + radius >= hi.x)
276 nbq[cnt + start_i].bodyId1 = rbId;
277 nbq[cnt + start_i].bodyId2 = -1;
278 nbq[cnt + start_i].normal1 = Coord(-1, 0, 0);
279 nbq[cnt + start_i].pos1 = center + Coord(radius, 0, 0);
280 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
281 nbq[cnt + start_i].interpenetration = center.x + radius - hi.x;
284 if (center.x - radius <= lo.x)
286 nbq[cnt + start_i].bodyId1 = rbId;
287 nbq[cnt + start_i].bodyId2 = -1;
288 nbq[cnt + start_i].normal1 = Coord(1, 0, 0);
289 nbq[cnt + start_i].pos1 = center - Coord(radius, 0, 0);
290 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
291 nbq[cnt + start_i].interpenetration = lo.x - (center.x - radius);
295 if (center.y + radius >= hi.y)
297 nbq[cnt + start_i].bodyId1 = rbId;
298 nbq[cnt + start_i].bodyId2 = -1;
299 nbq[cnt + start_i].normal1 = Coord(0, -1, 0);
300 nbq[cnt + start_i].pos1 = center + Coord(0, radius, 0);
301 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
302 nbq[cnt + start_i].interpenetration = center.y + radius - hi.y;
305 if (center.y - radius <= lo.y)
307 nbq[cnt + start_i].bodyId1 = rbId;
308 nbq[cnt + start_i].bodyId2 = -1;
309 nbq[cnt + start_i].normal1 = Coord(0, 1, 0);
310 nbq[cnt + start_i].pos1 = center - Coord(0, radius, 0);
311 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
312 nbq[cnt + start_i].interpenetration = lo.y - (center.y - radius);
316 if (center.z + radius >= hi.z)
318 nbq[cnt + start_i].bodyId1 = rbId;
319 nbq[cnt + start_i].bodyId2 = -1;
320 nbq[cnt + start_i].normal1 = Coord(0, 0, -1);
321 nbq[cnt + start_i].pos1 = center + Coord(0, 0, radius);
322 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
323 nbq[cnt + start_i].interpenetration = center.z + radius - hi.z;
326 if (center.z - radius <= lo.z)
328 nbq[cnt + start_i].bodyId1 = rbId;
329 nbq[cnt + start_i].bodyId2 = -1;
330 nbq[cnt + start_i].normal1 = Coord(0, 0, 1);
331 nbq[cnt + start_i].pos1 = center - Coord(0, 0, radius);
332 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
333 nbq[cnt + start_i].interpenetration = lo.z - (center.z - radius);
337 else if (eleType == ET_BOX)//box
339 //int idx = pId - start_box;
341 int start_i = count[pId];
342 Coord center = box[pId - elementOffset.boxIndex()].center;
343 Coord u = box[pId - elementOffset.boxIndex()].u;
344 Coord v = box[pId - elementOffset.boxIndex()].v;
345 Coord w = box[pId - elementOffset.boxIndex()].w;
346 Coord extent = box[pId - elementOffset.boxIndex()].extent;
348 p[0] = Point3D(center - u * extent[0] - v * extent[1] - w * extent[2]);
349 p[1] = Point3D(center - u * extent[0] - v * extent[1] + w * extent[2]);
350 p[2] = Point3D(center - u * extent[0] + v * extent[1] - w * extent[2]);
351 p[3] = Point3D(center - u * extent[0] + v * extent[1] + w * extent[2]);
352 p[4] = Point3D(center + u * extent[0] - v * extent[1] - w * extent[2]);
353 p[5] = Point3D(center + u * extent[0] - v * extent[1] + w * extent[2]);
354 p[6] = Point3D(center + u * extent[0] + v * extent[1] - w * extent[2]);
355 p[7] = Point3D(center + u * extent[0] + v * extent[1] + w * extent[2]);
356 bool c1, c2, c3, c4, c5, c6;
357 c1 = c2 = c3 = c4 = c5 = c6 = true;
358 for (int i = 0; i < 8; i++)
360 Coord pos = p[i].origin;
361 if (pos[0] > hi[0] && c1)
364 nbq[cnt + start_i].bodyId1 = rbId;
365 nbq[cnt + start_i].bodyId2 = -1;
366 nbq[cnt + start_i].normal1 = Coord(-1, 0, 0);
367 nbq[cnt + start_i].pos1 = pos;
368 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
369 nbq[cnt + start_i].interpenetration = pos[0] - hi[0];
372 if (pos[1] > hi[1] && c2)
375 nbq[cnt + start_i].bodyId1 = rbId;
376 nbq[cnt + start_i].bodyId2 = -1;
377 nbq[cnt + start_i].normal1 = Coord(0, -1, 0);
378 nbq[cnt + start_i].pos1 = pos;
379 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
380 nbq[cnt + start_i].interpenetration = pos[1] - hi[1];
383 if (pos[2] > hi[2] && c3)
386 nbq[cnt + start_i].bodyId1 = rbId;
387 nbq[cnt + start_i].bodyId2 = -1;
388 nbq[cnt + start_i].normal1 = Coord(0, 0, -1);
389 nbq[cnt + start_i].pos1 = pos;
390 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
391 nbq[cnt + start_i].interpenetration = pos[2] - hi[2];
394 if (pos[0] < lo[0] && c4)
397 nbq[cnt + start_i].bodyId1 = rbId;
398 nbq[cnt + start_i].bodyId2 = -1;
399 nbq[cnt + start_i].normal1 = Coord(1, 0, 0);
400 nbq[cnt + start_i].pos1 = pos;
401 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
402 nbq[cnt + start_i].interpenetration = lo[0] - pos[0];
405 if (pos[1] < lo[1] && c5)
408 nbq[cnt + start_i].bodyId1 = rbId;
409 nbq[cnt + start_i].bodyId2 = -1;
410 nbq[cnt + start_i].normal1 = Coord(0, 1, 0);
411 nbq[cnt + start_i].pos1 = pos;
412 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
413 nbq[cnt + start_i].interpenetration = lo[1] - pos[1];
416 if (pos[2] < lo[2] && c6)
419 nbq[cnt + start_i].bodyId1 = rbId;
420 nbq[cnt + start_i].bodyId2 = -1;
421 nbq[cnt + start_i].normal1 = Coord(0, 0, 1);
422 nbq[cnt + start_i].pos1 = pos;
423 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
424 nbq[cnt + start_i].interpenetration = lo[2] - pos[2];
430 else if (eleType == ET_TET) // tets
433 int start_i = count[pId];
435 Tet3D tet_i = tet[pId - elementOffset.tetIndex()];
437 for (int i = 0; i < 4; i++)
439 Coord vertex = tet_i.v[i];
440 if (vertex.x >= hi.x)
442 nbq[cnt + start_i].bodyId1 = rbId;
443 nbq[cnt + start_i].bodyId2 = -1;
444 nbq[cnt + start_i].normal1 = Coord(-1, 0, 0);
445 nbq[cnt + start_i].pos1 = vertex;
446 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
447 nbq[cnt + start_i].interpenetration = vertex.x - hi.x;
450 if (vertex.x <= lo.x)
452 nbq[cnt + start_i].bodyId1 = rbId;
453 nbq[cnt + start_i].bodyId2 = -1;
454 nbq[cnt + start_i].normal1 = Coord(1, 0, 0);
455 nbq[cnt + start_i].pos1 = vertex;
456 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
457 nbq[cnt + start_i].interpenetration = lo.x - (vertex.x);
461 if (vertex.y >= hi.y)
463 nbq[cnt + start_i].bodyId1 = rbId;
464 nbq[cnt + start_i].bodyId2 = -1;
465 nbq[cnt + start_i].normal1 = Coord(0, -1, 0);
466 nbq[cnt + start_i].pos1 = vertex;
467 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
468 nbq[cnt + start_i].interpenetration = vertex.y - hi.y;
471 if (vertex.y <= lo.y)
473 nbq[cnt + start_i].bodyId1 = rbId;
474 nbq[cnt + start_i].bodyId2 = -1;
475 nbq[cnt + start_i].normal1 = Coord(0, 1, 0);
476 nbq[cnt + start_i].pos1 = vertex;
477 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
478 nbq[cnt + start_i].interpenetration = lo.y - (vertex.y);
482 if (vertex.z >= hi.z)
484 nbq[cnt + start_i].bodyId1 = rbId;
485 nbq[cnt + start_i].bodyId2 = -1;
486 nbq[cnt + start_i].normal1 = Coord(0, 0, -1);
487 nbq[cnt + start_i].pos1 = vertex;
488 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
489 nbq[cnt + start_i].interpenetration = vertex.z - hi.z;
492 if (vertex.z <= lo.z)
494 nbq[cnt + start_i].bodyId1 = rbId;
495 nbq[cnt + start_i].bodyId2 = -1;
496 nbq[cnt + start_i].normal1 = Coord(0, 0, 1);
497 nbq[cnt + start_i].pos1 = vertex;
498 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
499 nbq[cnt + start_i].interpenetration = lo.z - (vertex.z);
504 else if (eleType == ET_CAPSULE)
507 int start_i = count[pId];
509 Capsule3D cap_i = cap[pId - elementOffset.capsuleIndex()];
511 Coord v0 = cap_i.startPoint();
512 Coord v1 = cap_i.endPoint();
514 Real radius = cap_i.radius;
517 if (v0.x + radius >= hi.x)
519 nbq[cnt + start_i].bodyId1 = rbId;
520 nbq[cnt + start_i].bodyId2 = -1;
521 nbq[cnt + start_i].normal1 = Coord(-1, 0, 0);
522 nbq[cnt + start_i].pos1 = v0 + Coord(radius, 0, 0);
523 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
524 nbq[cnt + start_i].interpenetration = v0.x + radius - hi.x;
527 if (v0.x - radius <= lo.x)
529 nbq[cnt + start_i].bodyId1 = rbId;
530 nbq[cnt + start_i].bodyId2 = -1;
531 nbq[cnt + start_i].normal1 = Coord(1, 0, 0);
532 nbq[cnt + start_i].pos1 = v0 - Coord(radius, 0, 0);
533 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
534 nbq[cnt + start_i].interpenetration = lo.x - (v0.x - radius);
538 if (v0.y + radius >= hi.y)
540 nbq[cnt + start_i].bodyId1 = rbId;
541 nbq[cnt + start_i].bodyId2 = -1;
542 nbq[cnt + start_i].normal1 = Coord(0, -1, 0);
543 nbq[cnt + start_i].pos1 = v0 + Coord(0, radius, 0);
544 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
545 nbq[cnt + start_i].interpenetration = v0.y + radius - hi.y;
548 if (v0.y - radius <= lo.y)
550 nbq[cnt + start_i].bodyId1 = rbId;
551 nbq[cnt + start_i].bodyId2 = -1;
552 nbq[cnt + start_i].normal1 = Coord(0, 1, 0);
553 nbq[cnt + start_i].pos1 = v0 - Coord(0, radius, 0);
554 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
555 nbq[cnt + start_i].interpenetration = lo.y - (v0.y - radius);
559 if (v0.z + radius >= hi.z)
561 nbq[cnt + start_i].bodyId1 = rbId;
562 nbq[cnt + start_i].bodyId2 = -1;
563 nbq[cnt + start_i].normal1 = Coord(0, 0, -1);
564 nbq[cnt + start_i].pos1 = v0 + Coord(0, 0, radius);
565 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
566 nbq[cnt + start_i].interpenetration = v0.z + radius - hi.z;
569 if (v0.z - radius <= lo.z)
571 nbq[cnt + start_i].bodyId1 = rbId;
572 nbq[cnt + start_i].bodyId2 = -1;
573 nbq[cnt + start_i].normal1 = Coord(0, 0, 1);
574 nbq[cnt + start_i].pos1 = v0 - Coord(0, 0, radius);
575 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
576 nbq[cnt + start_i].interpenetration = lo.z - (v0.z - radius);
581 if (v1.x + radius >= hi.x)
583 nbq[cnt + start_i].bodyId1 = rbId;
584 nbq[cnt + start_i].bodyId2 = -1;
585 nbq[cnt + start_i].normal1 = Coord(-1, 0, 0);
586 nbq[cnt + start_i].pos1 = v1 + Coord(radius, 0, 0);
587 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
588 nbq[cnt + start_i].interpenetration = v1.x + radius - hi.x;
591 if (v1.x - radius <= lo.x)
593 nbq[cnt + start_i].bodyId1 = rbId;
594 nbq[cnt + start_i].bodyId2 = -1;
595 nbq[cnt + start_i].normal1 = Coord(1, 0, 0);
596 nbq[cnt + start_i].pos1 = v1 - Coord(radius, 0, 0);
597 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
598 nbq[cnt + start_i].interpenetration = lo.x - (v1.x - radius);
602 if (v1.y + radius >= hi.y)
604 nbq[cnt + start_i].bodyId1 = rbId;
605 nbq[cnt + start_i].bodyId2 = -1;
606 nbq[cnt + start_i].normal1 = Coord(0, -1, 0);
607 nbq[cnt + start_i].pos1 = v1 + Coord(0, radius, 0);
608 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
609 nbq[cnt + start_i].interpenetration = v1.y + radius - hi.y;
612 if (v1.y - radius <= lo.y)
614 nbq[cnt + start_i].bodyId1 = rbId;
615 nbq[cnt + start_i].bodyId2 = -1;
616 nbq[cnt + start_i].normal1 = Coord(0, 1, 0);
617 nbq[cnt + start_i].pos1 = v1 - Coord(0, radius, 0);
618 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
619 nbq[cnt + start_i].interpenetration = lo.y - (v1.y - radius);
623 if (v1.z + radius >= hi.z)
625 nbq[cnt + start_i].bodyId1 = rbId;
626 nbq[cnt + start_i].bodyId2 = -1;
627 nbq[cnt + start_i].normal1 = Coord(0, 0, -1);
628 nbq[cnt + start_i].pos1 = v1 + Coord(0, 0, radius);
629 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
630 nbq[cnt + start_i].interpenetration = v1.z + radius - hi.z;
633 if (v1.z - radius <= lo.z)
635 nbq[cnt + start_i].bodyId1 = rbId;
636 nbq[cnt + start_i].bodyId2 = -1;
637 nbq[cnt + start_i].normal1 = Coord(0, 0, 1);
638 nbq[cnt + start_i].pos1 = v1 - Coord(0, 0, radius);
639 nbq[cnt + start_i].contactType = ContactType::CT_BOUDNARY;
640 nbq[cnt + start_i].interpenetration = lo.z - (v1.z - radius);
646 template<typename TDataType>
647 void CollistionDetectionBoundingBox<TDataType>::compute()
651 auto upperBound = this->varUpperBound()->getData();
652 auto lowerBound = this->varLowerBound()->getData();
654 auto discreteSet = this->inDiscreteElements()->getDataPtr();
655 uint totalSize = discreteSet->totalSize();
657 DArray<Box3D>& boxInGlobal = discreteSet->boxesInGlobal();
658 DArray<Sphere3D>& sphereInGlobal = discreteSet->spheresInGlobal();
659 DArray<Tet3D>& tetInGlobal = discreteSet->tetsInGlobal();
660 DArray<Capsule3D>& capsuleInGlobal = discreteSet->capsulesInGlobal();
662 ElementOffset offset = discreteSet->calculateElementOffset();
664 mBoundaryContactCounter.resize(discreteSet->totalSize());
665 mBoundaryContactCounter.reset();
666 if (discreteSet->totalSize() > 0)
669 CountContactsWithBoundary,
674 mBoundaryContactCounter,
679 sum += mReduce.accumulate(mBoundaryContactCounter.begin(), mBoundaryContactCounter.size());
680 mScan.exclusive(mBoundaryContactCounter, true);
682 this->outContacts()->resize(sum);
686 SetupContactsWithBoundary,
691 mBoundaryContactCounter,
692 this->outContacts()->getData(),
693 discreteSet->shape2RigidBodyMapping(),
700 this->outContacts()->resize(0);
703 DEFINE_CLASS(CollistionDetectionBoundingBox);