1#include "TriangleSet.h"
6#include <thrust/sort.h>
7#define TINYOBJLOADER_IMPLEMENTATION
8#include "tinyobjloader/tiny_obj_loader.h"
12 template<typename TDataType>
13 TriangleSet<TDataType>::TriangleSet()
14 : EdgeSet<TDataType>()
18 template<typename TDataType>
19 TriangleSet<TDataType>::~TriangleSet()
21 mTriangleIndex.clear();
22 mVertexNormal.clear();
28 template<typename Triangle>
29 __global__ void TS_CountTriangles(
31 DArray<Triangle> triangles)
33 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
34 if (tId >= triangles.size()) return;
36 Triangle t = triangles[tId];
38 atomicAdd(&counter[t[0]], 1);
39 atomicAdd(&counter[t[1]], 1);
40 atomicAdd(&counter[t[2]], 1);
43 template<typename Triangle>
44 __global__ void TS_SetupTriIds(
45 DArrayList<int> triIds,
46 DArray<Triangle> triangles)
48 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
49 if (tId >= triangles.size()) return;
51 Triangle t = triangles[tId];
53 triIds[t[0]].atomicInsert(tId);
54 triIds[t[1]].atomicInsert(tId);
55 triIds[t[2]].atomicInsert(tId);
58 template<typename TDataType>
59 DArrayList<int>& TriangleSet<TDataType>::getVertex2Triangles()
61 DArray<uint> counter(this->mCoords.size());
64 cuExecute(mTriangleIndex.size(),
69 mVer2Tri.resize(counter);
72 cuExecute(mTriangleIndex.size(),
82 template<typename Edg2Tri>
83 __global__ void TS_setupIds(
86 DArray<Edg2Tri> edg2Tri)
88 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
89 if (tId >= edg2Tri.size()) return;
91 Edg2Tri e = edg2Tri[tId];
93 triIds[2 * tId] = e[0];
94 triIds[2 * tId + 1] = e[1];
96 edgIds[2 * tId] = tId;
97 edgIds[2 * tId + 1] = tId;
100 template<typename Tri2Edg, typename Edge, typename Triangle>
101 __global__ void TS_SetupTri2Edg(
102 DArray<Tri2Edg> tri2Edg,
106 DArray<Triangle> triangles)
108 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
109 if (tId >= triIds.size()) return;
111 if (tId == 0 || triIds[tId] != triIds[tId - 1])
113 Tri2Edg t2E(EMPTY, EMPTY, EMPTY);
115 EKey te0(triangles[triIds[tId]][0], triangles[triIds[tId]][1]);
116 EKey te1(triangles[triIds[tId]][1], triangles[triIds[tId]][2]);
117 EKey te2(triangles[triIds[tId]][2], triangles[triIds[tId]][0]);
119 EKey e0(edges[edgIds[tId]][0], edges[edgIds[tId]][1]);
120 EKey e1(edges[edgIds[tId + 1]][0], edges[edgIds[tId + 1]][1]);
121 EKey e2(edges[edgIds[tId + 2]][0], edges[edgIds[tId + 2]][1]);
124 t2E[0] = edgIds[tId];
126 t2E[0] = edgIds[tId + 1];
128 t2E[0] = edgIds[tId + 2];
131 t2E[1] = edgIds[tId];
133 t2E[1] = edgIds[tId + 1];
135 t2E[1] = edgIds[tId + 2];
138 t2E[2] = edgIds[tId];
140 t2E[2] = edgIds[tId + 1];
142 t2E[2] = edgIds[tId + 2];
145 tri2Edg[shift] = t2E;
147 //printf("tri2Edg: %d, %d %d %d, %d %d %d \n", shift, triangles[triIds[tId]][0], triangles[triIds[tId]][1], triangles[triIds[tId]][2],tri2Edg[shift][0], tri2Edg[shift][1], tri2Edg[shift][2]);
151 template<typename TDataType>
152 void TriangleSet<TDataType>::updateTriangle2Edge()
154 if (mEdg2Tri.size() == 0)
157 uint edgSize = mEdg2Tri.size();
159 DArray<int> triIds, edgIds;
160 triIds.resize(2 * edgSize);
161 edgIds.resize(2 * edgSize);
169 thrust::sort_by_key(thrust::device, triIds.begin(), triIds.begin() + triIds.size(), edgIds.begin());
171 auto& pEdges = this->getEdges();
173 mTri2Edg.resize(mTriangleIndex.size());
174 cuExecute(triIds.size(),
186 template<typename EKey, typename Triangle>
187 __global__ void TS_SetupKeys(
190 DArray<Triangle> triangles)
192 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
193 if (tId >= triangles.size()) return;
195 Triangle tri = triangles[tId];
196 keys[3 * tId] = EKey(tri[0], tri[1]);
197 keys[3 * tId + 1] = EKey(tri[1], tri[2]);
198 keys[3 * tId + 2] = EKey(tri[2], tri[0]);
201 ids[3 * tId + 1] = tId;
202 ids[3 * tId + 2] = tId;
205 template<typename EKey>
206 __global__ void TS_CountEdgeNumber(
210 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
211 if (tId >= keys.size()) return;
213 if (tId == 0 || keys[tId] != keys[tId - 1])
219 template<typename Edge, typename Edg2Tri, typename EKey>
220 __global__ void TS_SetupEdges(
222 DArray<Edg2Tri> edg2Tri,
227 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
228 if (tId >= keys.size()) return;
230 int shift = counter[tId];
231 if (tId == 0 || keys[tId] != keys[tId - 1])
233 EKey key = keys[tId];
234 edges[shift] = Edge(key[0], key[1]);
236 Edg2Tri e2T(EMPTY, EMPTY);
237 e2T[0] = triIds[tId];
239 if (tId + 1 < keys.size() && keys[tId + 1] == key)
240 e2T[1] = triIds[tId + 1];
242 edg2Tri[shift] = e2T;
246 template<typename TDataType>
247 void TriangleSet<TDataType>::updateEdges()
249 uint triSize = mTriangleIndex.size();
254 keys.resize(3 * triSize);
255 triIds.resize(3 * triSize);
263 thrust::sort_by_key(thrust::device, keys.begin(), keys.begin() + keys.size(), triIds.begin());
266 counter.resize(3 * triSize);
268 cuExecute(keys.size(),
273 int edgeNum = thrust::reduce(thrust::device, counter.begin(), counter.begin() + counter.size());
274 thrust::exclusive_scan(thrust::device, counter.begin(), counter.begin() + counter.size(), counter.begin());
276 mEdg2Tri.resize(edgeNum);
278 auto& pEdges = this->getEdges();
279 pEdges.resize(edgeNum);
280 cuExecute(keys.size(),
293 template<typename TDataType>
294 void TriangleSet<TDataType>::setTriangles(std::vector<Triangle>& triangles)
296 mTriangleIndex.resize(triangles.size());
297 mTriangleIndex.assign(triangles);
300 template<typename TDataType>
301 void TriangleSet<TDataType>::setTriangles(DArray<Triangle>& triangles)
303 mTriangleIndex.resize(triangles.size());
304 mTriangleIndex.assign(triangles);
307 template<typename TDataType>
308 bool TriangleSet<TDataType>::loadObjFile(std::string filename)
310 std::vector<Coord> vertList;
311 std::vector<Triangle> faceList;
313 tinyobj::attrib_t myattrib;
314 std::vector <tinyobj::shape_t> myshape;
315 std::vector <tinyobj::material_t> mymat;
319 char* fname = (char*)filename.c_str();
321 bool succeed = tinyobj::LoadObj(&myattrib, &myshape, &mymat, &mywarn, &myerr, fname, nullptr ,true, true);
325 for (int i = 0; i < myattrib.GetVertices().size() / 3; i++)
327 vertList.push_back(Coord(myattrib.GetVertices()[3 * i], myattrib.GetVertices()[3 * i + 1], myattrib.GetVertices()[3 * i + 2]));
330 for (int i = 0;i < myshape.size();i++)
332 for (int s = 0;s < myshape[i].mesh.indices.size()/3; s++)
334 faceList.push_back(Triangle(myshape[i].mesh.indices[3 * s].vertex_index, myshape[i].mesh.indices[3 * s + 1].vertex_index, myshape[i].mesh.indices[3 * s + 2].vertex_index));
337 this->setPoints(vertList);
338 this->setTriangles(faceList);
349 template<typename TDataType>
350 void TriangleSet<TDataType>::copyFrom(TriangleSet<TDataType>& triangleSet)
352 mVer2Tri.assign(triangleSet.mVer2Tri);
354 mTriangleIndex.resize(triangleSet.mTriangleIndex.size());
355 mTriangleIndex.assign(triangleSet.mTriangleIndex);
357 mEdg2Tri.resize(triangleSet.mEdg2Tri.size());
358 mEdg2Tri.assign(triangleSet.mEdg2Tri);
360 EdgeSet<TDataType>::copyFrom(triangleSet);
363 template<typename Triangle>
364 __global__ void TS_UpdateIndex(
365 DArray<Triangle> indices,
369 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
370 if (tId >= indices.size() - indexOffset) return;
372 Triangle t = indices[indexOffset + tId];
373 t[0] += vertexOffset;
374 t[1] += vertexOffset;
375 t[2] += vertexOffset;
377 indices[indexOffset + tId] = t;
380 template<typename TDataType>
381 std::shared_ptr<TriangleSet<TDataType>> TriangleSet<TDataType>::merge(TriangleSet<TDataType>& ts)
383 auto ret = std::make_shared<TriangleSet<TDataType>>();
385 auto& vertices = ret->getPoints();
386 auto& indices = ret->getTriangles();
388 uint vNum0 = PointSet<TDataType>::mCoords.size();
389 uint vNum1 = ts.getPoints().size();
391 uint tNum0 = mTriangleIndex.size();
392 uint tNum1 = ts.getTriangles().size();
394 vertices.resize(vNum0 + vNum1);
395 indices.resize(tNum0 + tNum1);
397 vertices.assign(PointSet<TDataType>::mCoords, vNum0, 0, 0);
398 vertices.assign(ts.getPoints(), vNum1, vNum0, 0);
400 indices.assign(mTriangleIndex, tNum0, 0, 0);
401 indices.assign(ts.getTriangles(), tNum1, tNum0, 0);
412 template<typename TDataType>
413 bool TriangleSet<TDataType>::isEmpty()
415 return mTriangleIndex.size() == 0 && EdgeSet<TDataType>::isEmpty();
418 template<typename TDataType>
419 void TriangleSet<TDataType>::clear()
421 mTriangleIndex.clear();
426 mVertexNormal.clear();
428 EdgeSet<TDataType>::clear();
431 template<typename Coord, typename Triangle>
432 __global__ void TS_SetupVertexNormals(
433 DArray<Coord> normals,
434 DArray<Coord> vertices,
435 DArray<Triangle> triangles,
436 DArrayList<int> triIds)
438 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
439 if (tId >= normals.size()) return;
441 List<int>& list_i = triIds[tId];
442 int triSize = list_i.size();
445 for (int ne = 0; ne < triSize; ne++)
448 Triangle t = triangles[j];
450 Coord v0 = vertices[t[0]];
451 Coord v1 = vertices[t[1]];
452 Coord v2 = vertices[t[2]];
454 N += (v1 - v0).cross(v2 - v0);
462 template<typename TDataType>
463 void TriangleSet<TDataType>::setNormals(DArray<Coord>& normals)
465 mVertexNormal.assign(normals);
468 template<typename TDataType>
469 void TriangleSet<TDataType>::updateVertexNormal()
471 uint vertSize = this->mCoords.size();
476 if (mVertexNormal.size() != vertSize) {
477 mVertexNormal.resize(vertSize);
480 auto& vert2Tri = getVertex2Triangles();
482 TS_SetupVertexNormals,
489 template<typename Coord, typename Triangle>
490 __global__ void TS_SetupAngleWeightedVertexNormals(
491 DArray<Coord> normals,
492 DArray<Coord> vertices,
493 DArray<Triangle> triangles,
494 DArrayList<int> triIds)
496 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
497 if (tId >= normals.size()) return;
499 List<int>& list_i = triIds[tId];
500 int triSize = list_i.size();
503 for (int ne = 0; ne < triSize; ne++)
506 Triangle t = triangles[j];
508 Coord v0 = vertices[t[0]];
509 Coord v1 = vertices[t[1]];
510 Coord v2 = vertices[t[2]];
512 Real e0 = (v1 - v2).norm();
513 Real e1 = (v2 - v0).norm();
514 Real e2 = (v1 - v0).norm();
518 cosangle = (e1 * e1 + e2 * e2 - e0 * e0) / (2.0 * e1 * e2);
519 else if (t[1] == tId)
520 cosangle = (e0 * e0 + e2 * e2 - e1 * e1) / (2.0 * e0 * e2);
521 else if (t[2] == tId)
522 cosangle = (e1 * e1 + e0 * e0 - e2 * e2) / (2.0 * e1 * e0);
524 Real angle = acos(cosangle);
525 Coord norm = (v1 - v0).cross(v2 - v0);
529 //printf("vertex normal: %d, %f %f %f, %d %f, %f %f %f, %f %f %f \n", tId, vertices[tId][0], vertices[tId][1], vertices[tId][2],
530 // j, angle, norm[0], norm[1], norm[2], N[0], N[1], N[2]);
538 template<typename TDataType>
539 void TriangleSet<TDataType>::updateAngleWeightedVertexNormal(DArray<Coord>& vertexNormal)
541 uint vertSize = this->mCoords.size();
543 vertexNormal.resize(vertSize);
545 auto& vert2Tri = getVertex2Triangles();
548 TS_SetupAngleWeightedVertexNormals,
555 template<typename Coord, typename Triangle, typename Edg2Tri>
556 __global__ void TS_SetupEdgeNormals(
557 DArray<Coord> normals,
558 DArray<Coord> vertices,
559 DArray<Triangle> triangles,
560 DArray<Edg2Tri> triIds)
562 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
563 if (tId >= normals.size()) return;
565 Edg2Tri& edge = triIds[tId];
568 for (int ne = 0; ne < 2; ne++)
571 Triangle t = triangles[j];
573 Coord v0 = vertices[t[0]];
574 Coord v1 = vertices[t[1]];
575 Coord v2 = vertices[t[2]];
577 Coord norm = (v1 - v0).cross(v2 - v0);
587 template<typename TDataType>
588 void TriangleSet<TDataType>::updateEdgeNormal(DArray<Coord>& edgeNormal)
590 if (mEdg2Tri.size() == 0)
593 edgeNormal.resize(mEdg2Tri.size());
595 cuExecute(mEdg2Tri.size(),
603 template<typename TDataType>
604 void TriangleSet<TDataType>::updateTopology()
606 this->updateTriangles();
608 if(bAutoUpdateNormal)
609 this->updateVertexNormal();
611 this->EdgeSet<TDataType>::updateTopology();
614 template <typename Real, typename Coord>
615 __global__ void PS_RotateNormal(
616 DArray<Coord> normals,
619 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
620 if (pId >= normals.size()) return;
621 SquareMatrix<Real, 3> rot = q.toMatrix3x3();
623 normals[pId] = rot * normals[pId];
626 template<typename TDataType>
627 void TriangleSet<TDataType>::rotate(const Coord angle)
629 EdgeSet<TDataType>::rotate(angle);
632 template<typename TDataType>
633 void TriangleSet<TDataType>::rotate(const Quat<Real> q)
635 EdgeSet<TDataType>::rotate(q);
637 cuExecute(mVertexNormal.size(), PS_RotateNormal, mVertexNormal, q);
640 DEFINE_CLASS(TriangleSet);