PeriDyno 1.0.0
Loading...
Searching...
No Matches
QuadSet.cu
Go to the documentation of this file.
1#include "QuadSet.h"
2#include <fstream>
3#include <iostream>
4#include <sstream>
5
6#include <thrust/sort.h>
7
8namespace dyno
9{
10
11 template<typename TDataType>
12 QuadSet<TDataType>::QuadSet()
13 : EdgeSet<TDataType>()
14 {
15 }
16
17 template<typename TDataType>
18 QuadSet<TDataType>::~QuadSet()
19 {
20 mQuads.clear();
21 mVer2Quad.clear();
22 mEdg2Quad.clear();
23 }
24
25 template<typename Quad>
26 __global__ void QS_CountQuads(
27 DArray<uint> counter,
28 DArray<Quad> quads)
29 {
30 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
31 if (tId >= quads.size()) return;
32
33 Quad q = quads[tId];
34
35 atomicAdd(&counter[q[0]], 1);
36 atomicAdd(&counter[q[1]], 1);
37 atomicAdd(&counter[q[2]], 1);
38 atomicAdd(&counter[q[3]], 1);
39 }
40
41 template<typename Quad>
42 __global__ void QS_SetupQuadIds(
43 DArrayList<int> quadIds,
44 DArray<Quad> quads)
45 {
46 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
47 if (tId >= quads.size()) return;
48
49 Quad q = quads[tId];
50
51 quadIds[q[0]].atomicInsert(tId);
52 quadIds[q[1]].atomicInsert(tId);
53 quadIds[q[2]].atomicInsert(tId);
54 quadIds[q[3]].atomicInsert(tId);
55 }
56
57 template<typename TDataType>
58 DArrayList<int>& QuadSet<TDataType>::getVertex2Quads()
59 {
60 DArray<uint> counter(this->mCoords.size());
61 counter.reset();
62
63 cuExecute(mQuads.size(),
64 QS_CountQuads,
65 counter,
66 mQuads);
67
68 mVer2Quad.resize(counter);
69
70 counter.reset();
71 cuExecute(mQuads.size(),
72 QS_SetupQuadIds,
73 mVer2Quad,
74 mQuads);
75
76 counter.clear();
77
78 return mVer2Quad;
79 }
80
81 template<typename EKey, typename Quad>
82 __global__ void QS_SetupKeys(
83 DArray<EKey> keys,
84 DArray<int> ids,
85 DArray<Quad> quads)
86 {
87 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
88 if (tId >= quads.size()) return;
89
90 Quad quad = quads[tId];
91 keys[4 * tId] = EKey(quad[0], quad[1]);
92 keys[4 * tId + 1] = EKey(quad[1], quad[2]);
93 keys[4 * tId + 2] = EKey(quad[2], quad[3]);
94 keys[4 * tId + 3] = EKey(quad[3], quad[0]);
95
96 ids[4 * tId] = tId;
97 ids[4 * tId + 1] = tId;
98 ids[4 * tId + 2] = tId;
99 ids[4 * tId + 3] = tId;
100 }
101
102 template<typename EKey>
103 __global__ void QS_CountEdgeNumber(
104 DArray<int> counter,
105 DArray<EKey> keys)
106 {
107 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
108 if (tId >= keys.size()) return;
109
110 if (tId == 0 || keys[tId] != keys[tId - 1])
111 counter[tId] = 1;
112 else
113 counter[tId] = 0;
114 }
115
116 template<typename Edge, typename Edg2Quad, typename EKey>
117 __global__ void QS_SetupEdges(
118 DArray<Edge> edges,
119 DArray<Edg2Quad> edg2Quad,
120 DArray<EKey> keys,
121 DArray<int> counter,
122 DArray<int> quadIds)
123 {
124 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
125 if (tId >= keys.size()) return;
126
127 int shift = counter[tId];
128 if (tId == 0 || keys[tId] != keys[tId - 1])
129 {
130 EKey key = keys[tId];
131 edges[shift] = Edge(key[0], key[1]);
132
133 Edg2Quad e2Q(EMPTY, EMPTY);
134 e2Q[0] = quadIds[tId];
135
136 if (tId + 1 < keys.size() && keys[tId + 1] == key)
137 e2Q[1] = quadIds[tId + 1];
138
139 edg2Quad[shift] = e2Q;
140
141 //printf("T2T %d: %d %d \n", shift, t2T[0], t2T[1]);
142
143 //printf("Tri %d: %d %d %d; Tet: %d \n", shift, keys[tId][0], keys[tId][1], keys[tId][2], tetIds[tId]);
144 //printf("Counter: %d \n", shift, counter[tId]);
145 }
146 }
147
148 template<typename TDataType>
149 void QuadSet<TDataType>::updateEdges()
150 {
151 uint quadSize = mQuads.size();
152 DArray<EKey> keys;
153 DArray<int> quadIds;
154
155 keys.resize(4 * quadSize);
156 quadIds.resize(4 * quadSize);
157
158 cuExecute(quadSize,
159 QS_SetupKeys,
160 keys,
161 quadIds,
162 mQuads);
163
164 thrust::sort_by_key(thrust::device, keys.begin(), keys.begin() + keys.size(), quadIds.begin());
165
166 DArray<int> counter;
167 counter.resize(4 * quadSize);
168
169 cuExecute(keys.size(),
170 QS_CountEdgeNumber,
171 counter,
172 keys);
173
174 int edgeNum = thrust::reduce(thrust::device, counter.begin(), counter.begin() + counter.size());
175 thrust::exclusive_scan(thrust::device, counter.begin(), counter.begin() + counter.size(), counter.begin());
176
177 mEdg2Quad.resize(edgeNum);
178
179 auto& pEdges = this->getEdges();
180 pEdges.resize(edgeNum);
181 cuExecute(keys.size(),
182 QS_SetupEdges,
183 pEdges,
184 mEdg2Quad,
185 keys,
186 counter,
187 quadIds);
188
189 counter.clear();
190 quadIds.clear();
191 keys.clear();
192 }
193
194 template<typename TDataType>
195 void QuadSet<TDataType>::setQuads(std::vector<Quad>& quads)
196 {
197 mQuads.assign(quads);
198 }
199
200 template<typename TDataType>
201 void QuadSet<TDataType>::setQuads(DArray<Quad>& quads)
202 {
203 mQuads.assign(quads);
204 }
205
206 template<typename TDataType>
207 void QuadSet<TDataType>::copyFrom(QuadSet<TDataType>& quadSet)
208 {
209 mVer2Quad.assign(quadSet.mVer2Quad);
210
211 mQuads.resize(quadSet.mQuads.size());
212 mQuads.assign(quadSet.mQuads);
213
214 mEdg2Quad.resize(quadSet.mEdg2Quad.size());
215 mEdg2Quad.assign(quadSet.mEdg2Quad);
216
217 EdgeSet<TDataType>::copyFrom(quadSet);
218 }
219
220 template<typename TDataType>
221 bool QuadSet<TDataType>::isEmpty()
222 {
223 return mQuads.size() == 0 && EdgeSet<TDataType>::isEmpty();
224 }
225
226 template<typename Coord, typename Quad>
227 __global__ void QS_SetupVertexNormals(
228 DArray<Coord> normals,
229 DArray<Coord> vertices,
230 DArray<Quad> quads,
231 DArrayList<int> quadIds)
232 {
233 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
234 if (tId >= normals.size()) return;
235
236 List<int>& list_i = quadIds[tId];
237 int quadSize = list_i.size();
238
239 Coord N = Coord(0);
240 for (int ne = 0; ne < quadSize; ne++)
241 {
242 int j = list_i[ne];
243 Quad t = quads[j];
244
245 Coord v0 = vertices[t[0]];
246 Coord v1 = vertices[t[1]];
247 Coord v2 = vertices[t[2]];
248 Coord v3 = vertices[t[3]];
249
250 N += (v1 - v0).cross(v2 - v0);
251 }
252
253 N.normalize();
254
255 normals[tId] = N;
256 }
257
258 template<typename TDataType>
259 void QuadSet<TDataType>::updateTopology()
260 {
261 this->updateQuads();
262
263 EdgeSet<TDataType>::updateTopology();
264 }
265
266 template<typename TDataType>
267 void QuadSet<TDataType>::updateVertexNormal()
268 {
269 if (this->outVertexNormal()->isEmpty())
270 this->outVertexNormal()->allocate();
271
272 auto& vn = this->outVertexNormal()->getData();
273
274 uint vertSize = this->mCoords.size();
275
276 if (vn.size() != vertSize) {
277 vn.resize(vertSize);
278 }
279
280 auto& vert2Quad = getVertex2Quads();
281
282 cuExecute(vertSize,
283 QS_SetupVertexNormals,
284 vn,
285 this->mCoords,
286 mQuads,
287 vert2Quad);
288 }
289
290 DEFINE_CLASS(QuadSet);
291}