1#include "CollisionDetectionBroadPhase.h"
3#include "Topology/SparseOctree.h"
4#include "Topology/LinearBVH.h"
8#include <thrust/sort.h>
12 void print(DArray<int> arr)
15 h_arr.resize(arr.size());
19 for (uint i = 0; i < h_arr.size(); i++)
21 printf("%d: %d \n", i, h_arr[i]);
27 void print(DArray<PKey> arr)
30 h_arr.resize(arr.size());
34 for (uint i = 0; i < h_arr.size(); i++)
36 int id = h_arr[i] & UINT_MAX;
37 printf("%d: %d \n", i, id);
43 template<typename TDataType>
44 CollisionDetectionBroadPhase<TDataType>::CollisionDetectionBroadPhase()
47 this->varGridSizeLimit()->setValue(0.01);
50 template<typename TDataType>
51 CollisionDetectionBroadPhase<TDataType>::~CollisionDetectionBroadPhase()
66 template<typename Real, typename Coord>
67 __global__ void CDBP_SetupCorners(
73 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
75 if (tId >= bbox.size()) return;
82 h[tId] = max(box.v1[0] - box.v0[0], max(box.v1[1] - box.v0[1], box.v1[2] - box.v0[2]));
86 template<typename Real>
87 __global__ void CDBP_ComputeAABBSize(
89 DArray<AABB> boundingBox)
91 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
93 if (tId >= boundingBox.size()) return;
95 AABB box = boundingBox[tId];
97 h[tId] = max(box.v1[0] - box.v0[0], max(box.v1[1] - box.v0[1], box.v1[2] - box.v0[2]));
100 template<typename TDataType>
101 __global__ void CDBP_RequestIntersectionNumber(
103 DArray<AABB> boundingBox,
104 SparseOctree<TDataType> octree)
106 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
107 if (tId >= boundingBox.size()) return;
109 count[tId] = octree.requestIntersectionNumberFromBottom(boundingBox[tId]);
112 template<typename TDataType>
113 __global__ void CDBP_RequestIntersectionIds(
116 DArray<AABB> boundingBox,
117 SparseOctree<TDataType> octree)
119 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
120 if (tId >= boundingBox.size()) return;
122 octree.reqeustIntersectionIdsFromBottom(ids.begin() + count[tId], boundingBox[tId]);
127 template<typename TDataType>
128 __global__ void CDBP_RequestIntersectionNumber(
130 DArray<AABB> boundingBox,
131 SparseOctree<TDataType> octree,
134 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
135 if (tId >= boundingBox.size()) return;
137 count[tId] = octree.requestIntersectionNumberFromBottom(boundingBox[tId]);
139 count[tId] = octree.requestIntersectionNumberFromLevel(boundingBox[tId], octree.requestLevelNumber(boundingBox[tId]));
142 template<typename TDataType>
143 __global__ void CDBP_RequestIntersectionIds(
146 DArray<AABB> boundingBox,
147 SparseOctree<TDataType> octree,
150 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
151 if (tId >= boundingBox.size()) return;
154 octree.reqeustIntersectionIdsFromBottom(ids.begin() + count[tId], boundingBox[tId]);
156 octree.reqeustIntersectionIdsFromLevel(ids.begin() + count[tId], boundingBox[tId], octree.requestLevelNumber(boundingBox[tId]));
159 template<typename TDataType>
160 __global__ void CDBP_RequestIntersectionNumberRemove(
162 DArray<AABB> boundingBox_src,
163 DArray<AABB> boundingBox_tar,
164 SparseOctree<TDataType> octree,
167 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
168 if (tId >= boundingBox_src.size()) return;
170 count[tId] = octree.requestIntersectionNumberFromLevel(boundingBox_src[tId], boundingBox_tar.begin(), octree.requestLevelNumber(boundingBox_src[tId]));
172 count[tId] = octree.requestIntersectionNumberFromBottom(boundingBox_src[tId], boundingBox_tar.begin());
175 template<typename TDataType>
176 __global__ void CDBP_RequestIntersectionIdsRemove(
179 DArray<AABB> boundingBox_src,
180 DArray<AABB> boundingBox_tar,
181 SparseOctree<TDataType> octree,
185 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
186 if (tId >= boundingBox_src.size()) return;
188 octree.reqeustIntersectionIdsFromLevel(ids.begin() + count[tId], boundingBox_src[tId], boundingBox_tar.begin(), octree.requestLevelNumber(boundingBox_src[tId]));
190 octree.reqeustIntersectionIdsFromBottom(ids.begin() + count[tId], boundingBox_src[tId], boundingBox_tar.begin());
193 __global__ void CDBP_SetupKeys(
198 uint tId = threadIdx.x + (blockIdx.x * blockDim.x);
199 if (tId >= count.size()) return;
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;
205 for (int i = 0; i < n; i++)
207 uint id = ids[shift + i];
210 keys[shift + i] = key_hi << 32 | key_lo;
214 template<typename TDataType>
215 __global__ void CDBP_CountDuplicativeIds(
216 DArray<uint> new_count,
219 DArray<AABB> boundingBox,
220 SparseOctree<TDataType> octree)
222 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
223 if (tId >= boundingBox.size()) return;
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;
231 for (int i = 0; i < n; i++)
233 uint B_id = ids[shift + i] & UINT_MAX;
234 if (i == 0 || B_id != (ids[shift + i - 1] & UINT_MAX))
240 new_count[tId] = col_num;
242 template<typename TDataType>
243 __global__ void CDBP_CountDuplicativeIds(
244 DArray<uint> new_count,
247 DArray<AABB> boundingBox,
248 SparseOctree<TDataType> octree,
251 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
252 if (tId >= boundingBox.size()) return;
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;
260 for (int i = 0; i < n; i++)
262 uint B_id = ids[shift + i] & UINT_MAX;
263 if (i == 0 || B_id != (ids[shift + i - 1] & UINT_MAX))
269 if (octree.requestLevelNumber(boundingBox[tId]) == octree.requestLevelNumber(boundingBox[B_id]))
283 new_count[tId] = col_num;
286 template<typename TDataType>
287 __global__ void CDBP_RemoveDuplicativeIds(
289 DArray<uint> new_count,
292 DArray<AABB> boundingBox,
293 SparseOctree<TDataType> octree)
295 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
296 if (tId >= boundingBox.size()) return;
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;
304 int shift_new = new_count[tId];
306 for (int i = 0; i < n; i++)
308 uint B_id = ids[shift + i] & UINT_MAX;
309 if (i == 0 || B_id != (ids[shift + i - 1] & UINT_MAX))
311 new_ids[shift_new + col_num] = B_id;
317 template<typename TDataType>
318 __global__ void CDBP_RemoveDuplicativeIds(
319 DArrayList<int> contactLists,
322 DArray<AABB> boundingBox,
323 SparseOctree<TDataType> octree,
326 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
327 if (tId >= boundingBox.size()) return;
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;
333 List<int>& cList_i = contactLists[tId];
335 for (int i = 0; i < n; i++)
337 uint B_id = ids[shift + i] & UINT_MAX;
338 if (i == 0 || B_id != (ids[shift + i - 1] & UINT_MAX))
345 if (octree.requestLevelNumber(boundingBox[tId]) == octree.requestLevelNumber(boundingBox[B_id]))
350 cList_i.insert(B_id);
355 cList_i.insert(B_id);
361 cList_i.insert(B_id);
368 __global__ void CDBP_RevertIds(
369 DArray<int> elements)
371 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
372 if (tId >= elements.size()) return;
375 int id = elements[tId];
376 elements[tId] = -id - 1;
379 template<typename TDataType>
380 void CollisionDetectionBroadPhase<TDataType>::compute()
382 auto type = this->varAccelerationStructure()->getDataPtr()->currentKey();
385 case EStructure::BVH:
386 doCollisionWithLinearBVH();
388 case EStructure::Octree:
389 doCollisionWithSparseOctree();
396 template<typename TDataType>
397 void CollisionDetectionBroadPhase<TDataType>::doCollisionWithSparseOctree()
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();
404 if (this->outContactList()->isEmpty()) {
405 this->outContactList()->allocate();
408 auto& contacts = this->outContactList()->getData();
410 mV0.resize(aabb_tar.size());
411 mV1.resize(aabb_tar.size());
412 mH.resize(aabb_tar.size());
414 cuExecute(aabb_tar.size(),
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());
425 min_val = max(min_val, this->varGridSizeLimit()->getData());
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);
431 mCounter.resize(aabb_src.size());
432 cuExecute(aabb_src.size(),
433 CDBP_RequestIntersectionNumberRemove,
438 this->varSelfCollision()->getValue()
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());
444 mIds.resize(total_node_num);
446 cuExecute(aabb_src.size(),
447 CDBP_RequestIntersectionIds,
454 cuExecute(aabb_src.size(),
455 CDBP_RequestIntersectionIdsRemove,
461 this->varSelfCollision()->getValue());
466 mKeys.resize(mIds.size());
468 //remove duplicative ids and self id
469 cuExecute(mCounter.size(),
475 thrust::sort(thrust::device, mKeys.begin(), mKeys.begin() + mKeys.size());
477 mNewCounter.resize(mCounter.size());
478 cuExecute(aabb_src.size(),
479 CDBP_CountDuplicativeIds,
485 this->varSelfCollision()->getValue());
487 contacts.resize(mNewCounter);
489 cuExecute(aabb_src.size(),
490 CDBP_RemoveDuplicativeIds,
496 this->varSelfCollision()->getValue());
498 CArrayList<int> hContacts;
499 hContacts.assign(contacts);
504 template<typename TDataType, typename AABB>
505 __global__ void CDBP_RequestIntersectionNumberBVH(
508 LinearBVH<TDataType> bvh,
511 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
512 if (tId >= aabbs.size()) return;
515 count[tId] = bvh.requestIntersectionNumber(aabbs[tId], tId);
517 count[tId] = bvh.requestIntersectionNumber(aabbs[tId]);
521 template<typename TDataType, typename AABB>
522 __global__ void CDBP_RequestIntersectionIdsBVH(
523 DArrayList<int> idLists,
525 LinearBVH<TDataType> bvh,
528 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
529 if (tId >= aabbs.size()) return;
532 bvh.requestIntersectionIds(idLists[tId], aabbs[tId], tId);
534 bvh.requestIntersectionIds(idLists[tId], aabbs[tId]);
537 template<typename TDataType>
538 void CollisionDetectionBroadPhase<TDataType>::doCollisionWithLinearBVH()
540 auto& aabb_src = this->inSource()->constData();
542 if (this->inTarget()->isModified()) {
543 bvh.construct(this->inTarget()->constData());
546 if (this->outContactList()->isEmpty()) {
547 this->outContactList()->allocate();
550 auto& contacts = this->outContactList()->getData();
552 mCounter.resize(aabb_src.size());
553 cuExecute(aabb_src.size(),
554 CDBP_RequestIntersectionNumberBVH,
558 this->varSelfCollision()->getValue());
560 contacts.resize(mCounter);
562 cuExecute(aabb_src.size(),
563 CDBP_RequestIntersectionIdsBVH,
567 this->varSelfCollision()->getValue());
570 DEFINE_CLASS(CollisionDetectionBroadPhase);