1#include "NeighborElementQuery.h"
2#include "CollisionDetectionAlgorithm.h"
4#include "Collision/CollisionDetectionBroadPhase.h"
6#include "Primitive/Primitive3D.h"
12 IMPLEMENT_TCLASS(NeighborElementQuery, TDataType)
16 int bodyId1 = INVLIDA_ID;
17 int bodyId2 = INVLIDA_ID;
20 template<typename TDataType>
21 NeighborElementQuery<TDataType>::NeighborElementQuery()
24 this->inCollisionMask()->tagOptional(true);
26 this->inAttribute()->tagOptional(true);
28 mBroadPhaseCD = std::make_shared<CollisionDetectionBroadPhase<TDataType>>();
30 this->varGridSizeLimit()->attach(
31 std::make_shared<FCallBackFunc>(
33 mBroadPhaseCD->varGridSizeLimit()->setValue(this->varGridSizeLimit()->getValue());
37 this->varSelfCollision()->attach(
38 std::make_shared<FCallBackFunc>(
40 mBroadPhaseCD->varSelfCollision()->setValue(this->varSelfCollision()->getValue());
44 this->varGridSizeLimit()->setValue(Real(0.011));
45 this->varSelfCollision()->setValue(true);
48 template<typename TDataType>
49 NeighborElementQuery<TDataType>::~NeighborElementQuery()
53 template<typename Real, typename Coord>
54 __global__ void NEQ_SetupAABB(
55 DArray<AABB> boundingBox,
56 DArray<Coord> position,
59 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
60 if (pId >= position.size()) return;
63 Coord p = position[pId];
67 boundingBox[pId] = box;
70 template<typename Box3D>
71 __global__ void NEQ_SetupAABB(
72 DArray<AABB> boundingBox,
74 DArray<Sphere3D> spheres,
76 DArray<Capsule3D> caps,
77 DArray<Triangle3D> tris,
78 ElementOffset elementOffset,
81 uint tId = threadIdx.x + (blockIdx.x * blockDim.x);
82 if (tId >= boundingBox.size()) return;
84 ElementType eleType = elementOffset.checkElementType(tId);
91 box = spheres[tId].aabb();
96 box = boxes[tId - elementOffset.boxIndex()].aabb();
101 box = tets[tId - elementOffset.tetIndex()].aabb();
106 box = caps[tId - elementOffset.capsuleIndex()].aabb();
111 boundary_expand = 0.01;
112 box = tris[tId - elementOffset.triangleIndex()].aabb();
119 box.v0 -= boundary_expand;
120 box.v1 += boundary_expand;
122 boundingBox[tId] = box;
125 __device__ inline bool checkCollision(CollisionMask cType0, CollisionMask cType1, ElementType eleType0, ElementType eleType1)
127 bool canCollide = (cType0 & eleType1) != 0 && (cType1 & eleType0) > 0;
134 template<typename Box3D, typename ContactPair>
135 __global__ void NEQ_Narrow_Count(
137 DArray<ContactPair> nbr_cons,
138 DArray<ContactId> nbr,
139 DArray<CollisionMask> mask,
141 DArray<Sphere3D> spheres,
143 DArray<Real> tets_sdf,
144 DArray<int> tet_body_ids,
145 DArray<TopologyModule::Tetrahedron> tet_element_ids,
146 DArray<Capsule3D> caps,
147 DArray<Triangle3D> triangles,
148 DArray<Attribute> attribute,
149 DArray<Pair<uint, uint>> shape2RigidBodyMapping,
150 ElementOffset elementOffset,
152 bool enableSelfCollision,
153 bool enableCollisionMask)
155 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
156 if (tId >= nbr.size()) return;
158 ContactId ids = nbr[tId];
159 ElementType eleType_i = elementOffset.checkElementType(ids.bodyId1);
160 ElementType eleType_j = elementOffset.checkElementType(ids.bodyId2);
162 TManifold<Real> manifold;
164 // Convert primitive id into rigid body id
165 int mappedId1 = ids.bodyId1 == INVALID ? ids.bodyId1 : shape2RigidBodyMapping[ids.bodyId1].second;
166 int mappedId2 = ids.bodyId2 == INVALID ? ids.bodyId2 : shape2RigidBodyMapping[ids.bodyId2].second;
168 // TODO: check whether it is plausible to define collision mask on rigid bodies
169 CollisionMask mask_i = enableCollisionMask ? mask[mappedId1] : CollisionMask::CT_AllObjects;
170 CollisionMask mask_j = enableCollisionMask ? mask[mappedId2] : CollisionMask::CT_AllObjects;
172 // If two primitives belong to the same rigid body, disable collision detection
173 if (mappedId1 == mappedId2)
176 if (!enableSelfCollision)
178 Attribute att_i = attribute[mappedId1];
179 Attribute att_j = attribute[mappedId2];
181 if (att_i.objectId() == att_j.objectId())
185 if (eleType_i == ET_BOX && eleType_j == ET_BOX && checkCollision(mask_i, mask_j, ET_BOX, ET_BOX))
187 auto boxA = boxes[ids.bodyId1 - elementOffset.boxIndex()];
188 auto boxB = boxes[ids.bodyId2 - elementOffset.boxIndex()];
193 CollisionDetection<Real>::request(manifold, boxA, boxB);
194 //CollisionDetection<Real>::request(manifold, boxA, boxB, dHat, dHat);
195 //printf("Box - Box dHat:%f\n", dHat);
196 //printf("Collision: %d\n", manifold.contactCount);
197 //for (int i = 0; i < manifold.contactCount; i++)
199 // printf("dep: %f\n", manifold.contacts[i].penetration);
202 else if (eleType_i == ET_SPHERE && eleType_j == ET_BOX && checkCollision(mask_i, mask_j, ET_SPHERE, ET_BOX))
204 auto sphere = spheres[ids.bodyId1];
205 auto box = boxes[ids.bodyId2 - elementOffset.boxIndex()];
207 //sphere.radius += dHat;
208 //box.extent += dHat;
209 //CollisionDetection<Real>::request(manifold, sphere, box);
210 CollisionDetection<Real>::request(manifold, sphere, box, dHat, dHat);
212 //printf("SPhere - Box dHat:%f\n", dHat);
213 //printf("Collision: %d\n", manifold.contactCount);
214 //for (int i = 0; i < manifold.contactCount; i++)
216 // printf("dep: %f\n", manifold.contacts[i].penetration);
219 else if (eleType_i == ET_BOX && eleType_j == ET_SPHERE && checkCollision(mask_i, mask_j, ET_BOX, ET_SPHERE))
221 auto box = boxes[ids.bodyId1 - elementOffset.boxIndex()];
222 auto sphere = spheres[ids.bodyId2];
224 //box.extent += dHat;
225 //sphere.radius += dHat;
226 //CollisionDetection<Real>::request(manifold, box, sphere);
227 CollisionDetection<Real>::request(manifold, box, sphere, dHat, dHat);
229 //printf("Box - SPhere dHat:%f\n", dHat);
230 //printf("Collision: %d\n", manifold.contactCount);
231 //for (int i = 0; i < manifold.contactCount; i++)
233 // printf("dep: %f\n", manifold.contacts[i].penetration);
236 else if (eleType_i == ET_SPHERE && eleType_j == ET_SPHERE && checkCollision(mask_i, mask_j, ET_SPHERE, ET_SPHERE))
238 auto sphereA = spheres[ids.bodyId1];
239 auto sphereB = spheres[ids.bodyId2];
241 sphereA.radius += dHat;
242 sphereB.radius += dHat;
244 //CollisionDetection<Real>::request(manifold, sphereA, sphereB);
245 CollisionDetection<Real>::request(manifold, sphereA, sphereB, dHat, dHat);
247 else if(eleType_i == ET_TET && eleType_j == ET_TET && checkCollision(mask_i, mask_j, ET_TET, ET_TET))
249 //TODO: consider dHat
250 auto tetA = tets[ids.bodyId1 - elementOffset.tetIndex()];
251 auto tetB = tets[ids.bodyId2 - elementOffset.tetIndex()];
252 //CollisionDetection<Real>::request(manifold, tetA, tetB);
254 CollisionDetection<Real>::request(manifold, tetA, tetB, dHat, dHat);
256 else if (eleType_i == ET_TET && eleType_j == ET_BOX && checkCollision(mask_i, mask_j, ET_TET, ET_BOX))
258 //TODO: consider dHat
259 auto tetA = tets[ids.bodyId1 - elementOffset.tetIndex()];
260 auto boxB = boxes[ids.bodyId2 - elementOffset.boxIndex()];
261 //CollisionDetection<Real>::request(manifold, tetA, boxB);
263 CollisionDetection<Real>::request(manifold, tetA, boxB, dHat, dHat);
265 else if (eleType_i == ET_BOX && eleType_j == ET_TET && checkCollision(mask_i, mask_j, ET_BOX, ET_TET))
267 //TODO: consider dHat
268 auto boxA = boxes[ids.bodyId1 - elementOffset.boxIndex()];
269 auto tetB = tets[ids.bodyId2 - elementOffset.tetIndex()];
270 //CollisionDetection<Real>::request(manifold, boxA, tetB);
272 CollisionDetection<Real>::request(manifold, boxA, tetB, dHat, dHat);
274 else if (eleType_i == ET_SPHERE && eleType_j == ET_TET && checkCollision(mask_i, mask_j, ET_SPHERE, ET_TET))
276 //TODO: consider dHat
277 auto sphere = spheres[ids.bodyId1];
278 auto tet = tets[ids.bodyId2 - elementOffset.tetIndex()];
279 //CollisionDetection<Real>::request(manifold, sphere, tet);
281 CollisionDetection<Real>::request(manifold, sphere, tet, dHat, dHat);
283 else if (eleType_i == ET_TET && eleType_j == ET_SPHERE && checkCollision(mask_i, mask_j, ET_TET, ET_SPHERE))
285 //TODO: consider dHat
286 auto tet = tets[ids.bodyId1 - elementOffset.tetIndex()];
287 auto sphere = spheres[ids.bodyId2];
288 //CollisionDetection<Real>::request(manifold, tet, sphere);
290 CollisionDetection<Real>::request(manifold, tet, sphere, dHat, dHat);
292 else if (eleType_i == ET_TRI && eleType_j == ET_SPHERE && checkCollision(mask_i, mask_j, ET_TRI, ET_SPHERE))
294 //TODO: consider dHat
295 auto tri = triangles[ids.bodyId1 - elementOffset.triangleIndex()];
296 auto sphere = spheres[ids.bodyId2];
297 sphere.radius += 0.01f;
298 //CollisionDetection<Real>::request(manifold, sphere, tri);
300 CollisionDetection<Real>::request(manifold, sphere, tri, dHat, dHat);
302 else if (eleType_i == ET_SPHERE && eleType_j == ET_TRI && checkCollision(mask_i, mask_j, ET_SPHERE, ET_TRI))
304 //TODO: consider dHat
305 auto tri = triangles[ids.bodyId2 - elementOffset.triangleIndex()];
306 auto sphere = spheres[ids.bodyId1];
307 sphere.radius += 0.01f;
308 //CollisionDetection<Real>::request(manifold, sphere, tri);
310 CollisionDetection<Real>::request(manifold, sphere, tri, dHat, dHat);
312 else if (eleType_i == ET_TET && eleType_j == ET_TRI && checkCollision(mask_i, mask_j, ET_TET, ET_TRI))
314 //TODO: consider dHat
315 auto tri = triangles[ids.bodyId2 - elementOffset.triangleIndex()];
316 auto tet = tets[ids.bodyId1 - elementOffset.tetIndex()];
317 //CollisionDetection<Real>::request(manifold, tet, tri);
319 CollisionDetection<Real>::request(manifold, tet, tri, dHat, dHat);
321 else if (eleType_i == ET_TRI && eleType_j == ET_TET && checkCollision(mask_i, mask_j, ET_TRI, ET_TET))
323 //TODO: consider dHat
324 auto tri = triangles[ids.bodyId1 - elementOffset.triangleIndex()];
325 auto tet = tets[ids.bodyId2 - elementOffset.tetIndex()];
326 //CollisionDetection<Real>::request(manifold, tri, tet);
328 CollisionDetection<Real>::request(manifold, tri, tet, dHat, dHat);
331 //Capsule with other primitives
332 else if (eleType_i == ET_TET && eleType_j == ET_CAPSULE && checkCollision(mask_i, mask_j, ET_TET, ET_CAPSULE)) //tet-capsule
334 //TODO: consider dHat
335 auto cap = caps[ids.bodyId2 - elementOffset.capsuleIndex()];
336 auto tet = tets[ids.bodyId1 - elementOffset.tetIndex()];
337 //CollisionDetection<Real>::request(manifold, tet, cap);
339 Segment3D seg = cap.centerline();
340 Real radius = cap.radius;
341 CollisionDetection<Real>::request(manifold, tet, seg, dHat, radius + dHat);
343 else if (eleType_j == ET_TET && eleType_i == ET_CAPSULE && checkCollision(mask_i, mask_j, ET_CAPSULE, ET_TET))
345 //TODO: consider dHat
346 auto cap = caps[ids.bodyId1 - elementOffset.capsuleIndex()];
347 auto tet = tets[ids.bodyId2 - elementOffset.tetIndex()];
348 //CollisionDetection<Real>::request(manifold, cap, tet);
350 Segment3D seg = cap.centerline();
351 Real radius = cap.radius;
352 CollisionDetection<Real>::request(manifold, seg, tet, radius + dHat, dHat);
354 else if (eleType_i == ET_CAPSULE && eleType_j == ET_CAPSULE && checkCollision(mask_i, mask_j, ET_CAPSULE, ET_CAPSULE)) //capsule-capsule
356 auto cap1 = caps[ids.bodyId1 - elementOffset.capsuleIndex()];
357 auto cap2 = caps[ids.bodyId2 - elementOffset.capsuleIndex()];
359 //cap1.radius += dHat;
360 //cap2.radius += dHat;
361 //CollisionDetection<Real>::request(manifold, cap1, cap2);
363 Segment3D seg1 = cap1.centerline(); Real radius1 = cap1.radius;
364 Segment3D seg2 = cap2.centerline(); Real radius2 = cap2.radius;
365 CollisionDetection<Real>::request(manifold, seg1, seg2, radius1 + dHat, radius2 + dHat);
368 else if (eleType_i == ET_BOX && eleType_j == ET_CAPSULE && checkCollision(mask_i, mask_j, ET_BOX, ET_CAPSULE)) //box-capsule
370 auto cap = caps[ids.bodyId2 - elementOffset.capsuleIndex()];
371 auto box = boxes[ids.bodyId1 - elementOffset.boxIndex()];
373 //cap.radius += dHat;
374 //box.extent += dHat;
375 //CollisionDetection<Real>::request(manifold, box, cap);
377 Segment3D seg = cap.centerline();
378 Real radius = cap.radius;
379 CollisionDetection<Real>::request(manifold, box, seg, dHat, radius + dHat);
381 else if (eleType_j == ET_BOX && eleType_i == ET_CAPSULE && checkCollision(mask_i, mask_j, ET_CAPSULE, ET_BOX))
383 auto cap = caps[ids.bodyId1 - elementOffset.capsuleIndex()];
384 auto box = boxes[ids.bodyId2 - elementOffset.boxIndex()];
386 //cap.radius += dHat;
387 //box.extent += dHat;
388 //CollisionDetection<Real>::request(manifold, cap, box);
390 Segment3D seg = cap.centerline();
391 Real radius = cap.radius;
392 CollisionDetection<Real>::request(manifold, seg, box, radius + dHat, dHat);
394 else if (eleType_i == ET_SPHERE && eleType_j == ET_CAPSULE && checkCollision(mask_i, mask_j, ET_SPHERE, ET_CAPSULE)) //sphere-capsule
396 auto cap = caps[ids.bodyId2 - elementOffset.capsuleIndex()];
397 auto sphere = spheres[ids.bodyId1 - elementOffset.sphereIndex()];
399 //cap.radius += dHat;
400 //sphere.radius += dHat;
401 //CollisionDetection<Real>::request(manifold, sphere, cap);
403 Segment3D seg = cap.centerline();
404 Real radius = cap.radius;
405 CollisionDetection<Real>::request(manifold, sphere, seg, dHat, radius + dHat);
408 else if (eleType_j == ET_SPHERE && eleType_i == ET_CAPSULE && checkCollision(mask_i, mask_j, ET_CAPSULE, ET_SPHERE))
410 auto cap = caps[ids.bodyId1 - elementOffset.capsuleIndex()];
411 auto sphere = spheres[ids.bodyId2 - elementOffset.sphereIndex()];
413 //cap.radius += dHat;
414 //sphere.radius += dHat;
415 //CollisionDetection<Real>::request(manifold, cap, sphere);
417 Segment3D seg = cap.centerline();
418 Real radius = cap.radius;
419 CollisionDetection<Real>::request(manifold, seg, sphere, radius + dHat, dHat);
422 count[tId] = manifold.contactCount;
424 //printf("%d %d; num: %d \n", mappedId1, mappedId2, manifold.contactCount);
426 int offset = 8 * tId;
427 for (int n = 0; n < manifold.contactCount; n++)
430 //cp.pos1 = manifold.contacts[n].position + dHat * manifold.normal;
431 //cp.pos2 = manifold.contacts[n].position + dHat * manifold.normal;
432 cp.pos1 = manifold.contacts[n].position;
433 cp.pos2 = manifold.contacts[n].position;
434 cp.normal1 = -manifold.normal;
435 cp.normal2 = manifold.normal;
436 cp.bodyId1 = mappedId1;
437 cp.bodyId2 = mappedId2;
438 cp.contactType = ContactType::CT_NONPENETRATION;
439 //cp.interpenetration = -manifold.contacts[n].penetration - 2 * dHat;
440 cp.interpenetration = -manifold.contacts[n].penetration;
441 nbr_cons[offset + n] = cp;
445 template<typename ContactPair>
446 __global__ void NEQ_Narrow_Set(
447 DArray<ContactPair> nbr_cons,
448 DArray<ContactPair> nbr_cons_all,
449 DArray<ContactId> nbr,
453 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
454 if (tId >= nbr.size()) return;
456 ContactId ids = nbr[tId];
458 int offset = prefix[tId];
460 for (int n = 0; n < size; n++)
462 nbr_cons[offset + n] = nbr_cons_all[8 * tId + n];
466 __global__ void CCL_CountListSize(
468 DArrayList<int> contactList)
470 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
471 if (tId >= contactList.size()) return;
473 num[tId] = contactList[tId].size();
476 __global__ void CCL_SetupContactIds(
477 DArray<ContactId> ids,
479 DArrayList<int> contactList)
481 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
482 if (tId >= contactList.size()) return;
484 int base = index[tId];
486 auto& list_i = contactList[tId];
487 for (int j = 0; j < list_i.size(); j++)
491 id.bodyId2 = list_i[j];
497 template<typename TDataType>
498 void NeighborElementQuery<TDataType>::compute()
500 auto inTopo = this->inDiscreteElements()->getDataPtr();
502 if (this->outContacts()->isEmpty())
503 this->outContacts()->allocate();
505 this->outContacts()->clear();
507 int t_num = inTopo->totalSize();
511 auto& contacts = this->outContacts()->getData();
516 if (mQueriedAABB.size() != t_num){
517 mQueriedAABB.resize(t_num);
520 if (mQueryAABB.size() != t_num){
521 mQueryAABB.resize(t_num);
523 //printf("=========== ============= INSIDE SELF COLLISION %d\n", t_num);
524 ElementOffset elementOffset = inTopo->calculateElementOffset();
526 Real dHat = this->varDHead()->getValue();
528 auto& position = inTopo->position();
529 auto& rotation = inTopo->rotation();
531 DArray<Box3D>& boxInGlobal = inTopo->boxesInGlobal();
532 DArray<Sphere3D>& sphereInGlobal = inTopo->spheresInGlobal();
533 DArray<Tet3D>& tetInGlobal = inTopo->tetsInGlobal();
534 DArray<Capsule3D>& capsuleInGlobal = inTopo->capsulesInGlobal();
535 DArray<Triangle3D>& triangleInGlobal = inTopo->trianglesInGlobal();
548 mQueryAABB.assign(mQueriedAABB);
550 mBroadPhaseCD->inSource()->assign(mQueryAABB);
551 mBroadPhaseCD->inTarget()->assign(mQueriedAABB);
553 mBroadPhaseCD->update();
555 auto& contactList = mBroadPhaseCD->outContactList()->getData();
556 if (contactList.elementSize() == 0) {
560 DArray<int> count(contactList.size());
561 cuExecute(contactList.size(),
566 int totalSize = mReduce.accumulate(count.begin(), count.size());
568 if (totalSize <= 0) {
569 this->outContacts()->clear();
573 mScan.exclusive(count);
575 DArray<ContactId> deviceIds(totalSize);
577 cuExecute(contactList.size(),
587 DArray<int> contactNum;
588 DArray<int> contactNumCpy;
590 contactNum.resize(deviceIds.size());
592 contactNumCpy.resize(deviceIds.size());
593 contactNumCpy.reset();
595 DArray<TContactPair<Real>> nbr_cons_tmp;
596 nbr_cons_tmp.resize(deviceIds.size() * 8);
597 nbr_cons_tmp.reset();
599 if (this->inCollisionMask()->isEmpty())
601 DArray<CollisionMask> dummyCollisionMask;
602 if (!this->varSelfCollision()->getValue() && !this->inAttribute()->isEmpty())
604 cuExecute(deviceIds.size(),
614 inTopo->getTetBodyMapping(),
615 inTopo->getTetElementMapping(),
618 this->inAttribute()->getData(),
619 inTopo->shape2RigidBodyMapping(),
627 DArray<Attribute> dummyAttribute;
628 cuExecute(deviceIds.size(),
638 inTopo->getTetBodyMapping(),
639 inTopo->getTetElementMapping(),
643 inTopo->shape2RigidBodyMapping(),
653 if (!this->varSelfCollision()->getValue() && !this->inAttribute()->isEmpty())
655 cuExecute(deviceIds.size(),
660 this->inCollisionMask()->getData(),
665 inTopo->getTetBodyMapping(),
666 inTopo->getTetElementMapping(),
669 this->inAttribute()->getData(),
670 inTopo->shape2RigidBodyMapping(),
678 DArray<Attribute> dummyAttribute;
679 cuExecute(deviceIds.size(),
684 this->inCollisionMask()->getData(),
689 inTopo->getTetBodyMapping(),
690 inTopo->getTetElementMapping(),
694 inTopo->shape2RigidBodyMapping(),
702 contactNumCpy.assign(contactNum);
704 int sum = mReduce.accumulate(contactNum.begin(), contactNum.size());
706 auto& contacts = this->outContacts()->getData();
707 mScan.exclusive(contactNum, true);
708 contacts.resize(sum);
712 cuExecute(deviceIds.size(),
721 contactNumCpy.clear();
724 nbr_cons_tmp.clear();
727 DEFINE_CLASS(NeighborElementQuery);