2#include "Topology/LevelSet.h"
3#include <thrust/scan.h>
4#include <thrust/execution_policy.h>
9 IMPLEMENT_TCLASS(SdfSampler, TDataType)
11 __global__ void C_PointCount(
12 DArray3D<int> distance,
13 DArray<int> VerticesFlag)
15 uint i = threadIdx.x + blockDim.x * blockIdx.x;
16 uint j = threadIdx.y + blockDim.y * blockIdx.y;
17 uint k = threadIdx.z + blockDim.z * blockIdx.z;
19 uint nx = distance.nx();
20 uint ny = distance.ny();
21 uint nz = distance.nz();
23 if (i >= nx || j >= ny || k >= nz) return;
24 uint tId = i + j * nx + k * ny * nx;
25 //hexahedronFlag[tId] = 0;
27 if (i >= nx - 1 || j >= ny - 1 || k >= nz - 1) return;
30 if (distance(i, j, k) == 1 &&
31 distance(i + 1, j, k) == 1 &&
33 distance(i + 1, j + 1, k) == 1 &&
34 distance(i, j + 1, k) == 1 &&
36 distance(i, j, k + 1) == 1 &&
37 distance(i + 1, j, k + 1) == 1 &&
39 distance(i + 1, j + 1, k + 1) == 1 &&
40 distance(i, j + 1, k + 1) == 1) {
42 uint index1 = distance.index(i, j, k);
43 uint index2 = distance.index(i + 1, j, k);
45 uint index3 = distance.index(i + 1, j + 1, k);
46 uint index4 = distance.index(i, j + 1, k);
48 uint index5 = distance.index(i, j, k + 1);
49 uint index6 = distance.index(i + 1, j, k + 1);
51 uint index7 = distance.index(i + 1, j + 1, k + 1);
52 uint index8 = distance.index(i, j + 1, k + 1);
54 atomicExch(&VerticesFlag[index1], 1);
55 atomicExch(&VerticesFlag[index2], 1);
56 atomicExch(&VerticesFlag[index3], 1);
57 atomicExch(&VerticesFlag[index4], 1);
58 atomicExch(&VerticesFlag[index5], 1);
59 atomicExch(&VerticesFlag[index6], 1);
60 atomicExch(&VerticesFlag[index7], 1);
61 atomicExch(&VerticesFlag[index8], 1);
64 template<typename Coord>
65 __global__ void C_CalculatePoints(
66 DArray<Coord> vertices,
67 DArray<Coord> allVertices,
68 DArray<int> VerticesFlag,
69 DArray<int> VerticesFlagScan)
71 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
72 if (pId >= allVertices.size()) return;
74 if (VerticesFlag[pId] == 1) {
75 vertices[VerticesFlagScan[pId] - 1] = allVertices[pId];
79 template<typename TDataType, typename Real, typename Coord>
80 __global__ void C_reconstructSDF(
81 DistanceField3D<TDataType> inputSDF,
82 DArray3D<int> distance,
84 DArray<Coord> vertices,
87 DArray<int> VerticesFlag,
91 int i = threadIdx.x + (blockIdx.x * blockDim.x);
92 int j = threadIdx.y + (blockIdx.y * blockDim.y);
93 int k = threadIdx.z + (blockIdx.z * blockDim.z);
95 uint nx = distance.nx();
96 uint ny = distance.ny();
97 uint nz = distance.nz();
99 if (i >= nx || j >= ny || k >= nz) return;
100 distance(i, j, k) = 0;
101 VerticesFlag[i + j * nx + k * nx * ny] = 0;
103 float theta = (90.0f - cubeTilt[0]) / 180.0f * M_PI;
104 float phi = (90.0f - cubeTilt[1]) / 180.0f * M_PI;
105 float psi = (90.0f - cubeTilt[2]) / 180.0f * M_PI;
108 Coord point = minPoint + Coord(i * dx, j * dx, k * dx);
112 inputSDF.getDistance(point, a, normal);
115 atomicExch(&distance(i, j, k), 1);
120 point = minPoint + Coord(i * dx + (j * dx) / tan(theta),
121 j * dx + (i * dx) / tan(phi), k * dx + (j * dx) / tan(psi));
122 vertices[i + j * nx + k * nx * ny] = Rotation * cubeRotation * point;
125 template<typename TDataType>
126 SdfSampler<TDataType>::SdfSampler()
127 : Sampler<TDataType>()
129 this->varSpacing()->setRange(0.02, 1);
130 this->varCubeTilt()->setRange(0, 80);
131 this->varX()->setRange(0.001, 5);
132 this->varY()->setRange(0.001, 5);
133 this->varZ()->setRange(0.001, 5);
135 this->varAlpha()->setRange(0, 360);
136 this->varBeta()->setRange(0, 360);
137 this->varGamma()->setRange(0, 360);
139 this->statePointSet()->promoteOuput();
142 template<typename TDataType>
143 SdfSampler<TDataType>::~SdfSampler()
148 template<typename Real, typename Coord>
149 __global__ void VS_SetupNodes(
151 DArray3D<Real> distances,
155 uint i = threadIdx.x + blockDim.x * blockIdx.x;
156 uint j = threadIdx.y + blockDim.y * blockIdx.y;
157 uint k = threadIdx.z + blockDim.z * blockIdx.z;
159 uint nx = distances.nx();
160 uint ny = distances.ny();
161 uint nz = distances.nz();
163 if (i >= nx || j >= ny || k >= nz) return;
165 Coord p = origin + h * Coord(i, j, k);
166 nodes[distances.index(i, j, k)] = p;
170 template<typename Real>
171 __global__ void VS_SetupSDFValues(
172 DArray3D<Real> values,
173 DArray<Real> distances)
175 uint i = threadIdx.x + blockDim.x * blockIdx.x;
176 uint j = threadIdx.y + blockDim.y * blockIdx.y;
177 uint k = threadIdx.z + blockDim.z * blockIdx.z;
179 uint nx = values.nx();
180 uint ny = values.ny();
181 uint nz = values.nz();
183 if (i >= nx || j >= ny || k >= nz) return;
185 values(i, j, k) = distances[values.index(i, j, k)];
188 template<typename TDataType>
189 std::shared_ptr<dyno::DistanceField3D<TDataType>> SdfSampler<TDataType>::convert2Uniform(
190 VolumeOctree<TDataType>* volume,
193 Coord lo = volume->lowerBound();
194 Coord hi = volume->upperBound();
196 int nx = (hi[0] - lo[0]) / h;
197 int ny = (hi[1] - lo[1]) / h;
198 int nz = (hi[2] - lo[2]) / h;
200 auto levelset = std::make_shared<DistanceField3D<TDataType>>();
201 levelset->setSpace(lo, hi, h);
203 auto& distances = levelset->distances();
205 DArray<Coord> nodes(distances.size());
207 cuExecute3D(make_uint3(distances.nx(), distances.ny(), distances.nz()),
214 DArray<Real> sdfValues;
215 DArray<Coord> normals;
217 volume->stateSDFTopology()->constDataPtr()->getSignDistance(nodes, sdfValues, normals);
219 cuExecute3D(make_uint3(distances.nx(), distances.ny(), distances.nz()),
231 template<typename TDataType>
232 void SdfSampler<TDataType>::resetStates()
234 auto vol = this->getVolume();
235 Real dx = this->varSpacing()->getData();
237 //Adaptive mesh to uniform mesh
238 auto inputSDF = this->convert2Uniform(vol, dx);
241 if (this->statePointSet()->isEmpty()) {
242 auto pts = std::make_shared<PointSet<TDataType>>();
243 this->statePointSet()->setDataPtr(pts);
246 Coord minPoint = inputSDF->lowerBound();
247 Coord maxPoint = inputSDF->upperBound();
249 Vec3f cubeTilt = this->varCubeTilt()->getData();
250 Vec3f Xax = this->varX()->getData();
251 Vec3f Yax = this->varY()->getData();
252 Vec3f Zax = this->varZ()->getData();
253 Mat3f cubeRotation(Xax, Yax, Zax);
254 cubeRotation = cubeRotation.transpose();
256 uint ni = std::floor((maxPoint[0] - minPoint[0]) / dx) + 1;
257 uint nj = std::floor((maxPoint[1] - minPoint[1]) / dx) + 1;
258 uint nk = std::floor((maxPoint[2] - minPoint[2]) / dx) + 1;
260 DArray3D<int> distance(ni + 1, nj + 1, nk + 1);
261 DArray<Coord> allVertices((ni + 1) * (nj + 1) * (nk + 1));
262 DArray<int> VerticesFlag((ni + 1) * (nj + 1) * (nk + 1));
264 float Alpha = this->varAlpha()->getData() / 180.0f * M_PI;
265 float Beta = this->varBeta()->getData() / 180.0f * M_PI;
266 float Gamma = this->varGamma()->getData() / 180.0f * M_PI;
267 Mat3f Rotation(cos(Alpha) * cos(Beta), cos(Alpha) * sin(Beta) * sin(Gamma) - sin(Alpha) * cos(Gamma), cos(Alpha) * sin(Beta) * cos(Gamma) + sin(Alpha) * sin(Gamma),
268 sin(Alpha) * cos(Beta), sin(Alpha) * sin(Beta) * sin(Gamma) + cos(Alpha) * cos(Gamma), sin(Alpha) * sin(Beta) * cos(Gamma) - cos(Alpha) * sin(Gamma),
269 -sin(Beta), cos(Beta) * sin(Gamma), cos(Beta) * cos(Gamma));
271 cuExecute3D(make_uint3(distance.nx(), distance.ny(), distance.nz()),
283 cuExecute3D(make_uint3(distance.nx(), distance.ny(), distance.nz()),
289 CArray<int> CVerticesFlag;
290 CVerticesFlag.assign(VerticesFlag);
292 CArray3D<int> Cdistance;
293 Cdistance.assign(distance);
295 Reduction<int> reduce;
296 int verticesNum = reduce.accumulate(VerticesFlag.begin(), VerticesFlag.size());
297 DArray<Coord> vertices;
298 vertices.resize(verticesNum);
299 DArray<int> VerticesFlagScan;
300 VerticesFlagScan.assign(VerticesFlag);
301 thrust::inclusive_scan(thrust::device, VerticesFlagScan.begin(), VerticesFlagScan.begin() + VerticesFlagScan.size(), VerticesFlagScan.begin()); // in-place scan
302 cuExecute(allVertices.size(),
309 if (vertices.size() >= 0) {
310 auto topo = this->statePointSet()->getDataPtr();
311 topo->setPoints(vertices);
316 template<typename TDataType>
317 bool dyno::SdfSampler<TDataType>::validateInputs()
319 return this->getVolume() != nullptr;
322 DEFINE_CLASS(SdfSampler);