6#include <thrust/sort.h>
11 template<typename TDataType>
12 QuadSet<TDataType>::QuadSet()
13 : EdgeSet<TDataType>()
17 template<typename TDataType>
18 QuadSet<TDataType>::~QuadSet()
25 template<typename Quad>
26 __global__ void QS_CountQuads(
30 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
31 if (tId >= quads.size()) return;
35 atomicAdd(&counter[q[0]], 1);
36 atomicAdd(&counter[q[1]], 1);
37 atomicAdd(&counter[q[2]], 1);
38 atomicAdd(&counter[q[3]], 1);
41 template<typename Quad>
42 __global__ void QS_SetupQuadIds(
43 DArrayList<int> quadIds,
46 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
47 if (tId >= quads.size()) return;
51 quadIds[q[0]].atomicInsert(tId);
52 quadIds[q[1]].atomicInsert(tId);
53 quadIds[q[2]].atomicInsert(tId);
54 quadIds[q[3]].atomicInsert(tId);
57 template<typename TDataType>
58 DArrayList<int>& QuadSet<TDataType>::getVertex2Quads()
60 DArray<uint> counter(this->mCoords.size());
63 cuExecute(mQuads.size(),
68 mVer2Quad.resize(counter);
71 cuExecute(mQuads.size(),
81 template<typename EKey, typename Quad>
82 __global__ void QS_SetupKeys(
87 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
88 if (tId >= quads.size()) return;
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]);
97 ids[4 * tId + 1] = tId;
98 ids[4 * tId + 2] = tId;
99 ids[4 * tId + 3] = tId;
102 template<typename EKey>
103 __global__ void QS_CountEdgeNumber(
107 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
108 if (tId >= keys.size()) return;
110 if (tId == 0 || keys[tId] != keys[tId - 1])
116 template<typename Edge, typename Edg2Quad, typename EKey>
117 __global__ void QS_SetupEdges(
119 DArray<Edg2Quad> edg2Quad,
124 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
125 if (tId >= keys.size()) return;
127 int shift = counter[tId];
128 if (tId == 0 || keys[tId] != keys[tId - 1])
130 EKey key = keys[tId];
131 edges[shift] = Edge(key[0], key[1]);
133 Edg2Quad e2Q(EMPTY, EMPTY);
134 e2Q[0] = quadIds[tId];
136 if (tId + 1 < keys.size() && keys[tId + 1] == key)
137 e2Q[1] = quadIds[tId + 1];
139 edg2Quad[shift] = e2Q;
141 //printf("T2T %d: %d %d \n", shift, t2T[0], t2T[1]);
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]);
148 template<typename TDataType>
149 void QuadSet<TDataType>::updateEdges()
151 uint quadSize = mQuads.size();
155 keys.resize(4 * quadSize);
156 quadIds.resize(4 * quadSize);
164 thrust::sort_by_key(thrust::device, keys.begin(), keys.begin() + keys.size(), quadIds.begin());
167 counter.resize(4 * quadSize);
169 cuExecute(keys.size(),
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());
177 mEdg2Quad.resize(edgeNum);
179 auto& pEdges = this->getEdges();
180 pEdges.resize(edgeNum);
181 cuExecute(keys.size(),
194 template<typename TDataType>
195 void QuadSet<TDataType>::setQuads(std::vector<Quad>& quads)
197 mQuads.assign(quads);
200 template<typename TDataType>
201 void QuadSet<TDataType>::setQuads(DArray<Quad>& quads)
203 mQuads.assign(quads);
206 template<typename TDataType>
207 void QuadSet<TDataType>::copyFrom(QuadSet<TDataType>& quadSet)
209 mVer2Quad.assign(quadSet.mVer2Quad);
211 mQuads.resize(quadSet.mQuads.size());
212 mQuads.assign(quadSet.mQuads);
214 mEdg2Quad.resize(quadSet.mEdg2Quad.size());
215 mEdg2Quad.assign(quadSet.mEdg2Quad);
217 EdgeSet<TDataType>::copyFrom(quadSet);
220 template<typename TDataType>
221 bool QuadSet<TDataType>::isEmpty()
223 return mQuads.size() == 0 && EdgeSet<TDataType>::isEmpty();
226 template<typename Coord, typename Quad>
227 __global__ void QS_SetupVertexNormals(
228 DArray<Coord> normals,
229 DArray<Coord> vertices,
231 DArrayList<int> quadIds)
233 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
234 if (tId >= normals.size()) return;
236 List<int>& list_i = quadIds[tId];
237 int quadSize = list_i.size();
240 for (int ne = 0; ne < quadSize; ne++)
245 Coord v0 = vertices[t[0]];
246 Coord v1 = vertices[t[1]];
247 Coord v2 = vertices[t[2]];
248 Coord v3 = vertices[t[3]];
250 N += (v1 - v0).cross(v2 - v0);
258 template<typename TDataType>
259 void QuadSet<TDataType>::updateTopology()
263 EdgeSet<TDataType>::updateTopology();
266 template<typename TDataType>
267 void QuadSet<TDataType>::updateVertexNormal()
269 if (this->outVertexNormal()->isEmpty())
270 this->outVertexNormal()->allocate();
272 auto& vn = this->outVertexNormal()->getData();
274 uint vertSize = this->mCoords.size();
276 if (vn.size() != vertSize) {
280 auto& vert2Quad = getVertex2Quads();
283 QS_SetupVertexNormals,
290 DEFINE_CLASS(QuadSet);