PeriDyno 1.0.0
Loading...
Searching...
No Matches
CollisionDetectionBroadPhase.cu
Go to the documentation of this file.
1#include "CollisionDetectionBroadPhase.h"
2
3#include "Topology/SparseOctree.h"
4#include "Topology/LinearBVH.h"
5
6#include "Timer.h"
7
8#include <thrust/sort.h>
9
10namespace dyno
11{
12 void print(DArray<int> arr)
13 {
14 CArray<int> h_arr;
15 h_arr.resize(arr.size());
16
17 h_arr.assign(arr);
18
19 for (uint i = 0; i < h_arr.size(); i++)
20 {
21 printf("%d: %d \n", i, h_arr[i]);
22 }
23
24 h_arr.clear();
25 };
26
27 void print(DArray<PKey> arr)
28 {
29 CArray<PKey> h_arr;
30 h_arr.resize(arr.size());
31
32 h_arr.assign(arr);
33
34 for (uint i = 0; i < h_arr.size(); i++)
35 {
36 int id = h_arr[i] & UINT_MAX;
37 printf("%d: %d \n", i, id);
38 }
39
40 h_arr.clear();
41 };
42
43 template<typename TDataType>
44 CollisionDetectionBroadPhase<TDataType>::CollisionDetectionBroadPhase()
45 : ComputeModule()
46 {
47 this->varGridSizeLimit()->setValue(0.01);
48 }
49
50 template<typename TDataType>
51 CollisionDetectionBroadPhase<TDataType>::~CollisionDetectionBroadPhase()
52 {
53 mH.clear();
54 mV0.clear();
55 mV1.clear();
56
57 mCounter.clear();
58 mNewCounter.clear();
59
60 mIds.clear();
61 mKeys.clear();
62
63 bvh.release();
64 }
65
66 template<typename Real, typename Coord>
67 __global__ void CDBP_SetupCorners(
68 DArray<Real> h,
69 DArray<Coord> v0,
70 DArray<Coord> v1,
71 DArray<AABB> bbox)
72 {
73 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
74
75 if (tId >= bbox.size()) return;
76
77 AABB box = bbox[tId];
78
79 v0[tId] = box.v0;
80 v1[tId] = box.v1;
81
82 h[tId] = max(box.v1[0] - box.v0[0], max(box.v1[1] - box.v0[1], box.v1[2] - box.v0[2]));
83 }
84
85
86 template<typename Real>
87 __global__ void CDBP_ComputeAABBSize(
88 DArray<Real> h,
89 DArray<AABB> boundingBox)
90 {
91 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
92
93 if (tId >= boundingBox.size()) return;
94
95 AABB box = boundingBox[tId];
96
97 h[tId] = max(box.v1[0] - box.v0[0], max(box.v1[1] - box.v0[1], box.v1[2] - box.v0[2]));
98 }
99
100 template<typename TDataType>
101 __global__ void CDBP_RequestIntersectionNumber(
102 DArray<int> count,
103 DArray<AABB> boundingBox,
104 SparseOctree<TDataType> octree)
105 {
106 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
107 if (tId >= boundingBox.size()) return;
108
109 count[tId] = octree.requestIntersectionNumberFromBottom(boundingBox[tId]);
110 }
111
112 template<typename TDataType>
113 __global__ void CDBP_RequestIntersectionIds(
114 DArray<int> ids,
115 DArray<int> count,
116 DArray<AABB> boundingBox,
117 SparseOctree<TDataType> octree)
118 {
119 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
120 if (tId >= boundingBox.size()) return;
121
122 octree.reqeustIntersectionIdsFromBottom(ids.begin() + count[tId], boundingBox[tId]);
123 }
124
125
126
127 template<typename TDataType>
128 __global__ void CDBP_RequestIntersectionNumber(
129 DArray<int> count,
130 DArray<AABB> boundingBox,
131 SparseOctree<TDataType> octree,
132 bool self_collision)
133 {
134 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
135 if (tId >= boundingBox.size()) return;
136 if (!self_collision)
137 count[tId] = octree.requestIntersectionNumberFromBottom(boundingBox[tId]);
138 else
139 count[tId] = octree.requestIntersectionNumberFromLevel(boundingBox[tId], octree.requestLevelNumber(boundingBox[tId]));
140 }
141
142 template<typename TDataType>
143 __global__ void CDBP_RequestIntersectionIds(
144 DArray<int> ids,
145 DArray<int> count,
146 DArray<AABB> boundingBox,
147 SparseOctree<TDataType> octree,
148 bool self_collision)
149 {
150 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
151 if (tId >= boundingBox.size()) return;
152
153 if (!self_collision)
154 octree.reqeustIntersectionIdsFromBottom(ids.begin() + count[tId], boundingBox[tId]);
155 else
156 octree.reqeustIntersectionIdsFromLevel(ids.begin() + count[tId], boundingBox[tId], octree.requestLevelNumber(boundingBox[tId]));
157 }
158
159 template<typename TDataType>
160 __global__ void CDBP_RequestIntersectionNumberRemove(
161 DArray<uint> count,
162 DArray<AABB> boundingBox_src,
163 DArray<AABB> boundingBox_tar,
164 SparseOctree<TDataType> octree,
165 int self_collision)
166 {
167 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
168 if (tId >= boundingBox_src.size()) return;
169 if (self_collision)
170 count[tId] = octree.requestIntersectionNumberFromLevel(boundingBox_src[tId], boundingBox_tar.begin(), octree.requestLevelNumber(boundingBox_src[tId]));
171 else
172 count[tId] = octree.requestIntersectionNumberFromBottom(boundingBox_src[tId], boundingBox_tar.begin());
173 }
174
175 template<typename TDataType>
176 __global__ void CDBP_RequestIntersectionIdsRemove(
177 DArray<int> ids,
178 DArray<uint> count,
179 DArray<AABB> boundingBox_src,
180 DArray<AABB> boundingBox_tar,
181 SparseOctree<TDataType> octree,
182 int self_collision
183 )
184 {
185 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
186 if (tId >= boundingBox_src.size()) return;
187 if (self_collision)
188 octree.reqeustIntersectionIdsFromLevel(ids.begin() + count[tId], boundingBox_src[tId], boundingBox_tar.begin(), octree.requestLevelNumber(boundingBox_src[tId]));
189 else
190 octree.reqeustIntersectionIdsFromBottom(ids.begin() + count[tId], boundingBox_src[tId], boundingBox_tar.begin());
191 }
192
193 __global__ void CDBP_SetupKeys(
194 DArray<PKey> keys,
195 DArray<int> ids,
196 DArray<uint> count)
197 {
198 uint tId = threadIdx.x + (blockIdx.x * blockDim.x);
199 if (tId >= count.size()) return;
200
201 int shift = count[tId];
202 int total_num = count.size();
203 int n = tId == total_num - 1 ? ids.size() - shift : count[tId + 1] - shift;
204
205 for (int i = 0; i < n; i++)
206 {
207 uint id = ids[shift + i];
208 PKey key_hi = tId;
209 PKey key_lo = id;
210 keys[shift + i] = key_hi << 32 | key_lo;
211 }
212 }
213
214 template<typename TDataType>
215 __global__ void CDBP_CountDuplicativeIds(
216 DArray<uint> new_count,
217 DArray<PKey> ids,
218 DArray<uint> count,
219 DArray<AABB> boundingBox,
220 SparseOctree<TDataType> octree)
221 {
222 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
223 if (tId >= boundingBox.size()) return;
224
225 int total_num = boundingBox.size();
226 int shift = count[tId];
227 int n = tId == total_num - 1 ? ids.size() - count[total_num - 1] : count[tId + 1] - shift;
228
229 int col_num = 0;
230
231 for (int i = 0; i < n; i++)
232 {
233 uint B_id = ids[shift + i] & UINT_MAX;
234 if (i == 0 || B_id != (ids[shift + i - 1] & UINT_MAX))
235 {
236 col_num++;
237 }
238 }
239
240 new_count[tId] = col_num;
241 }
242 template<typename TDataType>
243 __global__ void CDBP_CountDuplicativeIds(
244 DArray<uint> new_count,
245 DArray<PKey> ids,
246 DArray<uint> count,
247 DArray<AABB> boundingBox,
248 SparseOctree<TDataType> octree,
249 bool self_collision)
250 {
251 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
252 if (tId >= boundingBox.size()) return;
253
254 int total_num = boundingBox.size();
255 int shift = count[tId];
256 int n = tId == total_num - 1 ? ids.size() - count[total_num - 1] : count[tId + 1] - shift;
257
258 int col_num = 0;
259
260 for (int i = 0; i < n; i++)
261 {
262 uint B_id = ids[shift + i] & UINT_MAX;
263 if (i == 0 || B_id != (ids[shift + i - 1] & UINT_MAX))
264 {
265 if (self_collision)
266 {
267 if (B_id != tId)
268 {
269 if (octree.requestLevelNumber(boundingBox[tId]) == octree.requestLevelNumber(boundingBox[B_id]))
270 {
271 if (B_id > tId)
272 col_num++;
273 }
274 else
275 col_num++;
276 }
277 }
278 else
279 col_num++;
280 }
281 }
282
283 new_count[tId] = col_num;
284 }
285
286 template<typename TDataType>
287 __global__ void CDBP_RemoveDuplicativeIds(
288 DArray<int> new_ids,
289 DArray<uint> new_count,
290 DArray<PKey> ids,
291 DArray<uint> count,
292 DArray<AABB> boundingBox,
293 SparseOctree<TDataType> octree)
294 {
295 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
296 if (tId >= boundingBox.size()) return;
297
298 int total_num = boundingBox.size();
299 int shift = count[tId];
300 int n = tId == total_num - 1 ? ids.size() - count[total_num - 1] : count[tId + 1] - shift;
301
302 int col_num = 0;
303
304 int shift_new = new_count[tId];
305
306 for (int i = 0; i < n; i++)
307 {
308 uint B_id = ids[shift + i] & UINT_MAX;
309 if (i == 0 || B_id != (ids[shift + i - 1] & UINT_MAX))
310 {
311 new_ids[shift_new + col_num] = B_id;
312 col_num++;
313 }
314 }
315 }
316
317 template<typename TDataType>
318 __global__ void CDBP_RemoveDuplicativeIds(
319 DArrayList<int> contactLists,
320 DArray<PKey> ids,
321 DArray<uint> count,
322 DArray<AABB> boundingBox,
323 SparseOctree<TDataType> octree,
324 bool self_collision)
325 {
326 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
327 if (tId >= boundingBox.size()) return;
328
329 int total_num = boundingBox.size();
330 int shift = count[tId];
331 int n = tId == total_num - 1 ? ids.size() - count[total_num - 1] : count[tId + 1] - shift;
332
333 List<int>& cList_i = contactLists[tId];
334
335 for (int i = 0; i < n; i++)
336 {
337 uint B_id = ids[shift + i] & UINT_MAX;
338 if (i == 0 || B_id != (ids[shift + i - 1] & UINT_MAX))
339 {
340 if (self_collision)
341 {
342 if (B_id != tId)
343 {
344
345 if (octree.requestLevelNumber(boundingBox[tId]) == octree.requestLevelNumber(boundingBox[B_id]))
346 {
347
348 if (B_id > tId)
349 {
350 cList_i.insert(B_id);
351 }
352 }
353 else
354 {
355 cList_i.insert(B_id);
356 }
357 }
358 }
359 else
360 {
361 cList_i.insert(B_id);
362 }
363 }
364 }
365 }
366
367
368 __global__ void CDBP_RevertIds(
369 DArray<int> elements)
370 {
371 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
372 if (tId >= elements.size()) return;
373
374
375 int id = elements[tId];
376 elements[tId] = -id - 1;
377 }
378
379 template<typename TDataType>
380 void CollisionDetectionBroadPhase<TDataType>::compute()
381 {
382 auto type = this->varAccelerationStructure()->getDataPtr()->currentKey();
383 switch (type)
384 {
385 case EStructure::BVH:
386 doCollisionWithLinearBVH();
387 break;
388 case EStructure::Octree:
389 doCollisionWithSparseOctree();
390 break;
391 default:
392 break;
393 }
394 }
395
396 template<typename TDataType>
397 void CollisionDetectionBroadPhase<TDataType>::doCollisionWithSparseOctree()
398 {
399 auto& aabb_src = this->inSource()->getData();
400 auto& aabb_tar = this->inTarget()->getData();
401 //:dyno::Array<:dyno::AABB, GPU>& aabb_src = this->inSource()->getData();
402 //:dyno::Array<:dyno::AABB, GPU>& aabb_tar = this->inTarget()->getData();
403
404 if (this->outContactList()->isEmpty()) {
405 this->outContactList()->allocate();
406 }
407
408 auto& contacts = this->outContactList()->getData();
409
410 mV0.resize(aabb_tar.size());
411 mV1.resize(aabb_tar.size());
412 mH.resize(aabb_tar.size());
413
414 cuExecute(aabb_tar.size(),
415 CDBP_SetupCorners,
416 mH,
417 mV0,
418 mV1,
419 aabb_tar);
420
421 auto min_val = m_reduce_real.minimum(mH.begin(), mH.size());
422 auto min_v0 = m_reduce_coord.minimum(mV0.begin(), mV0.size());
423 auto max_v1 = m_reduce_coord.maximum(mV1.begin(), mV1.size());
424
425 min_val = max(min_val, this->varGridSizeLimit()->getData());
426
427 SparseOctree<TDataType> octree;
428 octree.setSpace(min_v0 - min_val, min_val, max(max_v1[0] - min_v0[0], max(max_v1[1] - min_v0[1], max_v1[2] - min_v0[2])) + 2.0f * min_val);
429 octree.construct(aabb_tar);
430
431 mCounter.resize(aabb_src.size());
432 cuExecute(aabb_src.size(),
433 CDBP_RequestIntersectionNumberRemove,
434 mCounter,
435 aabb_src,
436 aabb_tar,
437 octree,
438 this->varSelfCollision()->getValue()
439 );
440
441 int total_node_num = thrust::reduce(thrust::device, mCounter.begin(), mCounter.begin() + mCounter.size(), (int)0, thrust::plus<int>());
442 thrust::exclusive_scan(thrust::device, mCounter.begin(), mCounter.begin() + mCounter.size(), mCounter.begin());
443
444 mIds.resize(total_node_num);
445 /*
446 cuExecute(aabb_src.size(),
447 CDBP_RequestIntersectionIds,
448 ids,
449 counter,
450 aabb_src,
451 octree,
452 self_collision);
453 */
454 cuExecute(aabb_src.size(),
455 CDBP_RequestIntersectionIdsRemove,
456 mIds,
457 mCounter,
458 aabb_src,
459 aabb_tar,
460 octree,
461 this->varSelfCollision()->getValue());
462
463 // print(counter);
464 // print(ids);
465
466 mKeys.resize(mIds.size());
467
468 //remove duplicative ids and self id
469 cuExecute(mCounter.size(),
470 CDBP_SetupKeys,
471 mKeys,
472 mIds,
473 mCounter);
474
475 thrust::sort(thrust::device, mKeys.begin(), mKeys.begin() + mKeys.size());
476
477 mNewCounter.resize(mCounter.size());
478 cuExecute(aabb_src.size(),
479 CDBP_CountDuplicativeIds,
480 mNewCounter,
481 mKeys,
482 mCounter,
483 aabb_src,
484 octree,
485 this->varSelfCollision()->getValue());
486
487 contacts.resize(mNewCounter);
488
489 cuExecute(aabb_src.size(),
490 CDBP_RemoveDuplicativeIds,
491 contacts,
492 mKeys,
493 mCounter,
494 aabb_src,
495 octree,
496 this->varSelfCollision()->getValue());
497
498 CArrayList<int> hContacts;
499 hContacts.assign(contacts);
500
501 octree.release();
502 }
503
504 template<typename TDataType, typename AABB>
505 __global__ void CDBP_RequestIntersectionNumberBVH(
506 DArray<uint> count,
507 DArray<AABB> aabbs,
508 LinearBVH<TDataType> bvh,
509 bool self_collision)
510 {
511 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
512 if (tId >= aabbs.size()) return;
513
514 if (self_collision)
515 count[tId] = bvh.requestIntersectionNumber(aabbs[tId], tId);
516 else
517 count[tId] = bvh.requestIntersectionNumber(aabbs[tId]);
518 }
519
520
521 template<typename TDataType, typename AABB>
522 __global__ void CDBP_RequestIntersectionIdsBVH(
523 DArrayList<int> idLists,
524 DArray<AABB> aabbs,
525 LinearBVH<TDataType> bvh,
526 bool self_collision)
527 {
528 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
529 if (tId >= aabbs.size()) return;
530
531 if (self_collision)
532 bvh.requestIntersectionIds(idLists[tId], aabbs[tId], tId);
533 else
534 bvh.requestIntersectionIds(idLists[tId], aabbs[tId]);
535 }
536
537 template<typename TDataType>
538 void CollisionDetectionBroadPhase<TDataType>::doCollisionWithLinearBVH()
539 {
540 auto& aabb_src = this->inSource()->constData();
541
542 if (this->inTarget()->isModified()) {
543 bvh.construct(this->inTarget()->constData());
544 }
545
546 if (this->outContactList()->isEmpty()) {
547 this->outContactList()->allocate();
548 }
549
550 auto& contacts = this->outContactList()->getData();
551
552 mCounter.resize(aabb_src.size());
553 cuExecute(aabb_src.size(),
554 CDBP_RequestIntersectionNumberBVH,
555 mCounter,
556 aabb_src,
557 bvh,
558 this->varSelfCollision()->getValue());
559
560 contacts.resize(mCounter);
561
562 cuExecute(aabb_src.size(),
563 CDBP_RequestIntersectionIdsBVH,
564 contacts,
565 aabb_src,
566 bvh,
567 this->varSelfCollision()->getValue());
568 }
569
570 DEFINE_CLASS(CollisionDetectionBroadPhase);
571}