PeriDyno 1.0.0
Loading...
Searching...
No Matches
PolygonSet.cu
Go to the documentation of this file.
1#include "PolygonSet.h"
2
3#include <thrust/sort.h>
4
5namespace dyno
6{
7 template<typename TDataType>
8 PolygonSet<TDataType>::PolygonSet()
9 : EdgeSet<TDataType>()
10 {
11 }
12
13 template<typename TDataType>
14 PolygonSet<TDataType>::~PolygonSet()
15 {
16 mPolygonIndex.clear();
17 }
18
19 template<typename TDataType>
20 void PolygonSet<TDataType>::setPolygons(const CArrayList<uint>& indices)
21 {
22 mPolygonIndex.assign(indices);
23 }
24
25 template<typename TDataType>
26 void PolygonSet<TDataType>::setPolygons(const DArrayList<uint>& indices)
27 {
28 mPolygonIndex.assign(indices);
29 }
30
31 template<typename TDataType>
32 void PolygonSet<TDataType>::copyFrom(PolygonSet<TDataType>& polygons)
33 {
34 PointSet<TDataType>::copyFrom(polygons);
35
36 mPolygonIndex.assign(polygons.mPolygonIndex);
37 }
38
39 template<typename TDataType>
40 bool PolygonSet<TDataType>::isEmpty()
41 {
42 bool empty = true;
43 empty |= mPolygonIndex.size() == 0;
44
45 return empty;
46 }
47
48 __global__ void PolygonSet_CountPolygonNumber(
49 DArray<uint> counter,
50 DArrayList<uint> polygonIndices)
51 {
52 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
53 if (tId >= polygonIndices.size()) return;
54
55 auto& index = polygonIndices[tId];
56
57 int N = index.size();
58 for (int i = 0; i < N; i++)
59 {
60 uint v0 = index[i];
61 atomicAdd(&counter[v0], 1);
62 }
63 }
64
65 __global__ void PolygonSet_SetupVertex2Polygon(
66 DArrayList<uint> vert2Poly,
67 DArrayList<uint> polygonIndices)
68 {
69 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
70 if (tId >= polygonIndices.size()) return;
71
72 auto& index = polygonIndices[tId];
73
74 int N = index.size();
75 for (int i = 0; i < N; i++)
76 {
77 uint v0 = index[i];
78 index.atomicInsert(v0);
79 }
80 }
81
82 template<typename TDataType>
83 void PolygonSet<TDataType>::updateTopology()
84 {
85 uint vNum = PointSet<TDataType>::mCoords.size();
86
87 //Update the vertex to polygon mapping
88 DArray<uint> counter(vNum);
89 counter.reset();
90
91 cuExecute(vNum,
92 PolygonSet_CountPolygonNumber,
93 counter,
94 mPolygonIndex);
95
96 mVer2Poly.resize(counter);
97
98 cuExecute(vNum,
99 PolygonSet_SetupVertex2Polygon,
100 mVer2Poly,
101 mPolygonIndex);
102
103 counter.clear();
104
105 EdgeSet<TDataType>::updateTopology();
106 }
107
108 __global__ void PolygonSet_CountEdgeNumber(
109 DArray<uint> counter,
110 DArrayList<uint> polygonIndices)
111 {
112 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
113 if (tId >= counter.size()) return;
114
115 counter[tId] = polygonIndices[tId].size();
116 }
117
118 __global__ void PolygonSet_SetupEdgeKeys(
119 DArray<EKey> keys,
120 DArray<uint> polyIds,
121 DArrayList<uint> polygonIndices,
122 DArray<uint> radix)
123 {
124 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
125 if (tId >= radix.size()) return;
126
127 uint offset = radix[tId];
128
129 auto& index = polygonIndices[tId];
130
131 int N = index.size();
132 for (int i = 0; i < N; i++)
133 {
134 uint v0 = index[i];
135 uint v1 = index[(i + 1) % N];
136 keys[offset + i] = EKey(v0, v1);
137 polyIds[offset + i] = tId;
138 }
139 }
140
141 __global__ void PolygonSet_CountUniqueEdge(
142 DArray<uint> counter,
143 DArray<EKey> keys)
144 {
145 uint tId = threadIdx.x + (blockIdx.x * blockDim.x);
146 if (tId >= keys.size()) return;
147
148 if (tId == 0 || keys[tId] != keys[tId - 1])
149 counter[tId] = 1;
150 else
151 counter[tId] = 0;
152 }
153
154 template<typename Edge, typename Edg2Poly>
155 __global__ void PolygonSet_SetupEdgeIndices(
156 DArray<Edge> edges,
157 DArrayList<uint> poly2Edge,
158 DArray<Edg2Poly> edg2Poly,
159 DArray<EKey> edgeKeys,
160 DArray<uint> polyIds,
161 DArray<uint> radix)
162 {
163 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
164 if (tId >= edgeKeys.size()) return;
165
166 uint edgeId = radix[tId];
167 uint polyId = polyIds[tId];
168 poly2Edge[polyId].atomicInsert(edgeId);
169 if (tId == 0 || edgeKeys[tId] != edgeKeys[tId - 1])
170 {
171 EKey key = edgeKeys[tId];
172 edges[edgeId] = Edge(key[0], key[1]);
173
174 Edg2Poly e2p(EMPTY, EMPTY);
175 e2p[0] = polyIds[tId];
176
177 if (tId + 1 < edgeKeys.size() && edgeKeys[tId + 1] == key)
178 e2p[1] = polyIds[tId + 1];
179
180 edg2Poly[edgeId] = e2p;
181 }
182 }
183
184 template<typename TDataType>
185 void PolygonSet<TDataType>::updateEdges()
186 {
187 uint polyNum = mPolygonIndex.size();
188
189 DArray<uint> radix(polyNum);
190
191 cuExecute(polyNum,
192 PolygonSet_CountEdgeNumber,
193 radix,
194 mPolygonIndex);
195
196 mPoly2Edg.resize(radix);
197
198 int eNum = thrust::reduce(thrust::device, radix.begin(), radix.begin() + radix.size());
199 thrust::exclusive_scan(thrust::device, radix.begin(), radix.begin() + radix.size(), radix.begin());
200
201 DArray<EKey> edgeKeys(eNum);
202 DArray<uint> polyIds(eNum);
203
204 cuExecute(polyNum,
205 PolygonSet_SetupEdgeKeys,
206 edgeKeys,
207 polyIds,
208 mPolygonIndex,
209 radix);
210
211 DArray<uint> uniqueEdgeCounter(eNum);
212
213 thrust::sort_by_key(thrust::device, edgeKeys.begin(), edgeKeys.begin() + edgeKeys.size(), polyIds.begin());
214
215 cuExecute(edgeKeys.size(),
216 PolygonSet_CountUniqueEdge,
217 uniqueEdgeCounter,
218 edgeKeys);
219
220 int uniqueNum = thrust::reduce(thrust::device, uniqueEdgeCounter.begin(), uniqueEdgeCounter.begin() + uniqueEdgeCounter.size());
221 thrust::exclusive_scan(thrust::device, uniqueEdgeCounter.begin(), uniqueEdgeCounter.begin() + uniqueEdgeCounter.size(), uniqueEdgeCounter.begin());
222
223 EdgeSet<TDataType>::mEdges.resize(uniqueNum);
224 mEdg2Poly.resize(uniqueNum);
225
226 cuExecute(edgeKeys.size(),
227 PolygonSet_SetupEdgeIndices,
228 EdgeSet<TDataType>::mEdges,
229 mPoly2Edg,
230 mEdg2Poly,
231 edgeKeys,
232 polyIds,
233 uniqueEdgeCounter);
234
235 radix.clear();
236 polyIds.clear();
237 edgeKeys.clear();
238 uniqueEdgeCounter.clear();
239 }
240
241 template<typename TDataType>
242 void PolygonSet<TDataType>::extractEdgeSet(EdgeSet<TDataType>& es)
243 {
244 es.setPoints(PointSet<TDataType>::mCoords);
245 es.setEdges(EdgeSet<TDataType>::mEdges);
246
247 es.update();
248 }
249
250 __global__ void PolygonSet_ExtractTriangleNumber(
251 DArray<uint> counter,
252 DArrayList<uint> polygonIndices)
253 {
254 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
255 if (tId >= counter.size()) return;
256
257 counter[tId] = polygonIndices[tId].size() == 3 ? 1 : 0;
258 }
259
260 template<typename Triangle>
261 __global__ void PolygonSet_ExtractTriangleIndices(
262 DArray<Triangle> triangles,
263 DArrayList<uint> polygonIndices,
264 DArray<uint> radix)
265 {
266 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
267 if (tId >= radix.size()) return;
268
269 uint offset = radix[tId];
270
271 auto& index = polygonIndices[tId];
272
273 if (index.size() == 3)
274 {
275 uint v0 = index[0];
276 uint v1 = index[1];
277 uint v2 = index[2];
278 triangles[offset] = Triangle(v0, v1, v2);
279 }
280 }
281
282 template<typename TDataType>
283 void PolygonSet<TDataType>::extractTriangleSet(TriangleSet<TDataType>& ts)
284 {
285 ts.clear();
286
287 uint polyNum = mPolygonIndex.size();
288
289 DArray<uint> radix(polyNum);
290
291 cuExecute(polyNum,
292 PolygonSet_ExtractTriangleNumber,
293 radix,
294 mPolygonIndex);
295
296 int tNum = thrust::reduce(thrust::device, radix.begin(), radix.begin() + radix.size());
297 thrust::exclusive_scan(thrust::device, radix.begin(), radix.begin() + radix.size(), radix.begin());
298
299 DArray<Triangle> triangleIndices(tNum);
300
301 //TODO: remove duplicative vertices
302 cuExecute(polyNum,
303 PolygonSet_ExtractTriangleIndices,
304 triangleIndices,
305 mPolygonIndex,
306 radix);
307
308 ts.setPoints(PointSet<TDataType>::mCoords);
309 ts.setTriangles(triangleIndices);
310 ts.update();
311
312 radix.clear();
313 triangleIndices.clear();
314 }
315
316 __global__ void PolygonSet_ExtractQuadNumber(
317 DArray<uint> counter,
318 DArrayList<uint> polygonIndices)
319 {
320 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
321 if (tId >= counter.size()) return;
322
323 counter[tId] = polygonIndices[tId].size() == 4 ? 1 : 0;
324 }
325
326 template<typename Quad>
327 __global__ void PolygonSet_ExtractQuadIndices(
328 DArray<Quad> quads,
329 DArrayList<uint> polygonIndices,
330 DArray<uint> radix)
331 {
332 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
333 if (tId >= radix.size()) return;
334
335 uint offset = radix[tId];
336
337 auto& index = polygonIndices[tId];
338
339 if (index.size() == 4)
340 {
341 uint v0 = index[0];
342 uint v1 = index[1];
343 uint v2 = index[2];
344 uint v3 = index[3];
345 quads[offset] = Quad(v0, v1, v2, v3);
346 }
347 }
348
349 template<typename TDataType>
350 void PolygonSet<TDataType>::extractQuadSet(QuadSet<TDataType>& qs)
351 {
352 qs.clear();
353
354 uint polyNum = mPolygonIndex.size();
355
356 DArray<uint> radix(polyNum);
357
358 cuExecute(polyNum,
359 PolygonSet_ExtractQuadNumber,
360 radix,
361 mPolygonIndex);
362
363 int tNum = thrust::reduce(thrust::device, radix.begin(), radix.begin() + radix.size());
364 thrust::exclusive_scan(thrust::device, radix.begin(), radix.begin() + radix.size(), radix.begin());
365
366 DArray<Quad> quadIndices(tNum);
367
368 //TODO: remove duplicative vertices
369 cuExecute(polyNum,
370 PolygonSet_ExtractQuadIndices,
371 quadIndices,
372 mPolygonIndex,
373 radix);
374
375 qs.setPoints(PointSet<TDataType>::mCoords);
376 qs.setQuads(quadIndices);
377 qs.update();
378
379 radix.clear();
380 quadIndices.clear();
381 }
382
383 __global__ void PolygonSet_CountTriangleNumber(
384 DArray<uint> counter,
385 DArrayList<uint> polygonIndices)
386 {
387 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
388 if (tId >= counter.size()) return;
389
390 counter[tId] = polygonIndices[tId].size() - 2;
391 }
392
393 template<typename Triangle>
394 __global__ void PolygonSet_SetupTriangleIndices(
395 DArray<Triangle> triangles,
396 DArrayList<uint> polygonIndices,
397 DArray<uint> radix)
398 {
399 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
400 if (tId >= radix.size()) return;
401
402 uint offset = radix[tId];
403
404 auto& index = polygonIndices[tId];
405
406 int N = index.size();
407 for (int i = 0; i < N - 2; i++)
408 {
409 uint v0 = index[0];
410 uint v1 = index[i + 1];
411 uint v2 = index[i + 2];
412 triangles[offset + i] = Triangle(v0, v1, v2);
413 }
414 }
415
416 template<typename TDataType>
417 void PolygonSet<TDataType>::turnIntoTriangleSet(TriangleSet<TDataType>& ts)
418 {
419 ts.clear();
420
421 uint polyNum = mPolygonIndex.size();
422
423 DArray<uint> radix(polyNum);
424
425 cuExecute(polyNum,
426 PolygonSet_CountTriangleNumber,
427 radix,
428 mPolygonIndex);
429
430 int tNum = thrust::reduce(thrust::device, radix.begin(), radix.begin() + radix.size());
431 thrust::exclusive_scan(thrust::device, radix.begin(), radix.begin() + radix.size(), radix.begin());
432
433 DArray<Triangle> triangleIndex(tNum);
434
435 cuExecute(polyNum,
436 PolygonSet_SetupTriangleIndices,
437 triangleIndex,
438 mPolygonIndex,
439 radix);
440
441 ts.setPoints(PointSet<TDataType>::mCoords);
442 ts.setTriangles(triangleIndex);
443 ts.update();
444
445 radix.clear();
446 triangleIndex.clear();
447 }
448
449 template<typename TDataType>
450 void PolygonSet<TDataType>::triangleSetToPolygonSet(TriangleSet<TDataType>& ts)
451 {
452 this->setPoints(ts.getPoints());
453
454 this->mPolygonIndex.resize(ts.getTriangles().size(),3);
455
456 cuExecute(ts.getTriangles().size(),
457 triSet2PolygonSet,
458 ts.getTriangles(),
459 this->mPolygonIndex
460 );
461
462 this->update();
463
464 }
465
466
467 template<typename Triangle>
468 __global__ void triSet2PolygonSet(
469 DArray<Triangle> triangles,
470 DArrayList<uint> polygons
471 )
472 {
473 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
474 if (tId >= triangles.size()) return;
475
476 auto& index = polygons[tId];
477 for (int i = 0; i < 3; i++)
478 index.insert(triangles[tId][i]);
479
480 }
481
482 DEFINE_CLASS(PolygonSet);
483}