PeriDyno 1.0.0
Loading...
Searching...
No Matches
CollistionDetectionTriangleSet.cu
Go to the documentation of this file.
1#include "CollistionDetectionTriangleSet.h"
2
3#include "Primitive/Primitive3D.h"
4#include "Topology/DiscreteElements.h"
5
6namespace dyno
7{
8 template<typename TDataType>
9 CollistionDetectionTriangleSet<TDataType>::CollistionDetectionTriangleSet()
10 : ComputeModule()
11 {
12 mBroadPhaseCD = std::make_shared<CollisionDetectionBroadPhase<TDataType>>();
13 }
14
15 template<typename TDataType>
16 CollistionDetectionTriangleSet<TDataType>::~CollistionDetectionTriangleSet()
17 {
18
19 }
20
21 template<typename Coord, typename AABB>
22 __global__ void CDTS_SetupAABBs(
23 DArray<AABB> aabbs,
24 DArray<Coord> vertices,
25 DArray<TopologyModule::Triangle> indices)
26 {
27 uint tId = threadIdx.x + (blockIdx.x * blockDim.x);
28 if (tId >= indices.size()) return;
29
30 TopologyModule::Triangle index = indices[tId];
31
32 Coord v0 = vertices[index[0]];
33 Coord v1 = vertices[index[1]];
34 Coord v2 = vertices[index[2]];
35
36 aabbs[tId] = TTriangle3D<Real>(v0, v1, v2).aabb();
37 }
38
39 template<typename AABB, typename Box3D>
40 __global__ void CDTS_SetupAABBForRigidBodies(
41 DArray<AABB> boundingBox,
42 DArray<Box3D> boxes,
43 DArray<Sphere3D> spheres,
44 DArray<Tet3D> tets,
45 DArray<Capsule3D> caps,
46 ElementOffset elementOffset)
47 {
48 uint tId = threadIdx.x + (blockIdx.x * blockDim.x);
49 if (tId >= boundingBox.size()) return;
50
51 ElementType eleType = elementOffset.checkElementType(tId);
52
53 AABB box;
54 switch (eleType)
55 {
56 case ET_SPHERE:
57 {
58 box = spheres[tId].aabb();
59 break;
60 }
61 case ET_BOX:
62 {
63 box = boxes[tId - elementOffset.boxIndex()].aabb();
64 break;
65 }
66 case ET_TET:
67 {
68 box = tets[tId - elementOffset.tetIndex()].aabb();
69 break;
70 }
71 case ET_CAPSULE:
72 {
73 box = caps[tId - elementOffset.capsuleIndex()].aabb();
74 break;
75 }
76 default:
77 break;
78 }
79
80 boundingBox[tId] = box;
81 }
82
83 template<typename Coord, typename Box3D, typename ContactPair>
84 __global__ void CDTS_CountContacts(
85 DArray<int> count,
86 DArray<ContactPair> nbr_cons,
87 DArray<Box3D> boxes,
88 DArray<Sphere3D> spheres,
89 DArray<Tet3D> tets,
90 DArray<Capsule3D> capsules,
91 DArray<Coord> vertices, //triangle vertices
92 DArray<TopologyModule::Triangle> indices, //triangle indices
93 DArrayList<int> contactListBroadPhase,
94 DArray<Pair<uint, uint>> mapping,
95 ElementOffset elementOffset)
96 {
97 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
98 if (tId >= count.size()) return;
99
100 auto& list_i = contactListBroadPhase[tId];
101
102 ElementType eleType = elementOffset.checkElementType(tId);
103
104 uint num = 0;
105 Real d_hat = 0;
106 Coord points[8];
107
108 if (eleType == ET_BOX)
109 {
110 num = 8;
111 Box3D box = boxes[tId - elementOffset.boxIndex()];
112 Coord center = box.center;
113 Coord u = box.u;
114 Coord v = box.v;
115 Coord w = box.w;
116 Coord extent = box.extent;
117
118 d_hat = 0;
119 points[0] = center - u * extent[0] - v * extent[1] - w * extent[2];
120 points[1] = center - u * extent[0] - v * extent[1] + w * extent[2];
121 points[2] = center - u * extent[0] + v * extent[1] - w * extent[2];
122 points[3] = center - u * extent[0] + v * extent[1] + w * extent[2];
123 points[4] = center + u * extent[0] - v * extent[1] - w * extent[2];
124 points[5] = center + u * extent[0] - v * extent[1] + w * extent[2];
125 points[6] = center + u * extent[0] + v * extent[1] - w * extent[2];
126 points[7] = center + u * extent[0] + v * extent[1] + w * extent[2];
127 }
128 else if (eleType == ET_SPHERE)
129 {
130 num = 1;
131 Sphere3D sp = spheres[tId - elementOffset.sphereIndex()];
132
133 d_hat = sp.radius;
134 points[0] = sp.center;
135 }
136 else if (eleType == ET_CAPSULE)
137 {
138 num = 2;
139
140 Capsule3D cap = capsules[tId - elementOffset.capsuleIndex()];
141
142 d_hat = cap.radius;
143 points[0] = cap.startPoint();
144 points[1] = cap.endPoint();
145 }
146 else if (eleType == ET_TET)
147 {
148 num = 4;
149 Tet3D tet = tets[tId - elementOffset.tetIndex()];
150
151 d_hat = 0;
152 points[0] = tet.v[0];
153 points[1] = tet.v[1];
154 points[2] = tet.v[2];
155 points[3] = tet.v[3];
156 }
157
158 auto PROJECT_INSIDE = [](const TPoint3D<Real> p, const TTriangle3D<Real> triangle) -> bool
159 {
160 Real epsilon = Real(0.00001);
161 TPlane3D<Real> plane(triangle.v[0], triangle.normal());
162
163 TPoint3D<Real> proj = p.project(plane);
164
165 typename TTriangle3D<Real>::Param tParam;
166 bool bValid = triangle.computeBarycentrics(proj.origin, tParam);
167 if (bValid)
168 {
169 return tParam.u > Real(0) - epsilon && tParam.u < Real(1) + epsilon && tParam.v > Real(0) - epsilon && tParam.v < Real(1) + epsilon && tParam.w > Real(0) - epsilon && tParam.w < Real(1) + epsilon;
170 }
171 else
172 {
173 return false;
174 }
175 };
176
177 uint cnt = 0;
178 for (uint i = 0; i < num; i++)
179 {
180 bool intersected = false;
181 Real d_min = -REAL_MAX;
182 Coord proj_min;
183 Coord normal_min;
184
185 TPoint3D<Real> pi = TPoint3D<Real>(points[i]);
186 for (uint j = 0; j < list_i.size(); j++)
187 {
188 TopologyModule::Triangle index = indices[list_i[j]];
189 TTriangle3D<Real> tj(vertices[index[0]], vertices[index[1]], vertices[index[2]]);
190
191 Coord nj = tj.normal();
192
193 if (PROJECT_INSIDE(pi, tj))
194 {
195 TPoint3D<Real> proj = pi.project(tj);
196 Real d = nj.dot(pi.origin - proj.origin) - d_hat;
197
198 if (d < 0)
199 {
200 //Find the closest triangle
201 if (d > d_min)
202 {
203 d_min = d;
204 proj_min = proj.origin;
205 normal_min = nj;
206
207 intersected = true;
208 }
209 }
210 }
211 }
212
213 if (intersected)
214 {
215 ContactPair contact;
216 contact.bodyId1 = mapping[tId].second;
217 contact.bodyId2 = -1;
218 contact.normal1 = normal_min;
219 contact.pos1 = proj_min + normal_min * d_min;
220 contact.contactType = ContactType::CT_BOUDNARY;
221 contact.interpenetration = -d_min;
222
223 nbr_cons[8 * tId + cnt] = contact;
224
225 cnt++;
226 }
227 }
228
229 count[tId] = cnt;
230 }
231
232 template<typename ContactPair>
233 __global__ void CDTS_Narrow_Set(
234 DArray<ContactPair> nbr_cons,
235 DArray<ContactPair> nbr_cons_all,
236 DArray<int> prefix,
237 DArray<int> counter)
238 {
239 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
240 if (tId >= counter.size()) return;
241
242 int offset = prefix[tId];
243 int size = counter[tId];
244 for (int n = 0; n < size; n++)
245 {
246 nbr_cons[offset + n] = nbr_cons_all[8 * tId + n];
247 }
248 }
249
250 template<typename TDataType>
251 void CollistionDetectionTriangleSet<TDataType>::compute()
252 {
253 //Initialize AABBs of discrete elements
254 auto de = this->inDiscreteElements()->constDataPtr();
255
256 int num = de->totalSize();
257
258 if (mQueryAABB.size() != num)
259 mQueryAABB.resize(num);
260
261 DArray<Box3D>& boxInGlobal = de->boxesInGlobal();
262 DArray<Sphere3D>& sphereInGlobal = de->spheresInGlobal();
263 DArray<Tet3D>& tetInGlobal = de->tetsInGlobal();
264 DArray<Capsule3D>& capsuleInGlobal = de->capsulesInGlobal();
265
266 ElementOffset elementOffset = de->calculateElementOffset();
267
268 cuExecute(num,
269 CDTS_SetupAABBForRigidBodies,
270 mQueryAABB,
271 boxInGlobal,
272 sphereInGlobal,
273 tetInGlobal,
274 capsuleInGlobal,
275 elementOffset);
276
277 mBroadPhaseCD->inSource()->assign(mQueryAABB);
278
279 auto ts = this->inTriangleSet()->constDataPtr();
280
281 auto& vertices = ts->getPoints();
282 auto& indices = ts->getTriangles();
283
284 //Initialize AABBs of the triangle set
285 if (this->inTriangleSet()->isModified())
286 {
287 if (mTriangleAABB.size() != indices.size())
288 mTriangleAABB.resize(indices.size());
289
290 cuExecute(indices.size(),
291 CDTS_SetupAABBs,
292 mTriangleAABB,
293 vertices,
294 indices);
295
296 mBroadPhaseCD->inTarget()->assign(mTriangleAABB);
297 }
298 mBroadPhaseCD->update();
299
300 auto& contactList = mBroadPhaseCD->outContactList()->constData();
301
302 mBoundaryContactCounter.resize(num);
303 mContactBuffer.resize(8 * num);
304
305 cuExecute(num,
306 CDTS_CountContacts,
307 mBoundaryContactCounter,
308 mContactBuffer,
309 boxInGlobal,
310 sphereInGlobal,
311 tetInGlobal,
312 capsuleInGlobal,
313 vertices,
314 indices,
315 contactList,
316 de->shape2RigidBodyMapping(),
317 elementOffset);
318
319 mBoundaryContactCpy.assign(mBoundaryContactCounter);
320
321 uint sum = mReduce.accumulate(mBoundaryContactCounter.begin(), mBoundaryContactCounter.size());
322 mScan.exclusive(mBoundaryContactCounter, true);
323
324 this->outContacts()->resize(sum);
325
326 cuExecute(num,
327 CDTS_Narrow_Set,
328 this->outContacts()->getData(),
329 mContactBuffer,
330 mBoundaryContactCounter,
331 mBoundaryContactCpy);
332 }
333
334 DEFINE_CLASS(CollistionDetectionTriangleSet);
335}