2#include "DistanceField3D.h"
8 template <typename Coord>
9 __device__ float DistanceToPlane(const Coord &p, const Coord &o, const Coord &n) {
10 return fabs((p - o, n).length());
13 template <typename Coord>
14 __device__ Real DistanceToSegment(Coord& pos, Coord& lo, Coord& hi)
16 typedef typename Coord::VarType Real;
18 Coord edge1 = pos - lo;
19 Coord edge2 = pos - hi;
20 if (edge1.dot(seg) < 0.0f)
24 if (edge2.dot(-seg) < 0.0f)
28 Real length1 = edge1.dot(edge1);
30 Real length2 = edge1.dot(seg);
31 return std::sqrt(length1 - length2*length2);
34 template <typename Coord>
35 __device__ Real DistanceToSqure(Coord& pos, Coord& lo, Coord& hi, int axis)
37 typedef typename Coord::VarType Real;
39 Coord corner1, corner2, corner3, corner4;
40 Coord loCorner, hiCorner, p;
44 corner1 = Coord(lo[0], lo[1], lo[2]);
45 corner2 = Coord(lo[0], hi[1], lo[2]);
46 corner3 = Coord(lo[0], hi[1], hi[2]);
47 corner4 = Coord(lo[0], lo[1], hi[2]);
48 n = Coord(1.0, 0.0, 0.0);
50 loCorner = Coord(lo[1], lo[2], 0.0);
51 hiCorner = Coord(hi[1], hi[2], 0.0);
52 p = Coord(pos[1], pos[2], 0.0f);
55 corner1 = Coord(lo[0], lo[1], lo[2]);
56 corner2 = Coord(lo[0], lo[1], hi[2]);
57 corner3 = Coord(hi[0], lo[1], hi[2]);
58 corner4 = Coord(hi[0], lo[1], lo[2]);
59 n = Coord(0.0f, 1.0f, 0.0f);
61 loCorner = Coord(lo[0], lo[2], 0.0f);
62 hiCorner = Coord(hi[0], hi[2], 0.0f);
63 p = Coord(pos[0], pos[2], 0.0f);
66 corner1 = Coord(lo[0], lo[1], lo[2]);
67 corner2 = Coord(hi[0], lo[1], lo[2]);
68 corner3 = Coord(hi[0], hi[1], lo[2]);
69 corner4 = Coord(lo[0], hi[1], lo[2]);
70 n = Coord(0.0f, 0.0f, 1.0f);
72 loCorner = Coord(lo[0], lo[1], 0.0);
73 hiCorner = Coord(hi[0], hi[1], 0.0);
74 p = Coord(pos[0], pos[1], 0.0f);
78 Real dist1 = DistanceToSegment(pos, corner1, corner2);
79 Real dist2 = DistanceToSegment(pos, corner2, corner3);
80 Real dist3 = DistanceToSegment(pos, corner3, corner4);
81 Real dist4 = DistanceToSegment(pos, corner4, corner1);
82 Real dist5 = abs(n.dot(pos - corner1));
83 if (p[0] < hiCorner[0] && p[0] > loCorner[0] && p[1] < hiCorner[1] && p[1] > loCorner[1])
86 return min(min(dist1, dist2), min(dist3, dist4));
89 template <typename Coord>
90 __device__ Real DistanceToBox(Coord& pos, Coord& lo, Coord& hi)
92 typedef typename Coord::VarType Real;
93 Coord corner0(lo[0], lo[1], lo[2]);
94 Coord corner1(hi[0], lo[1], lo[2]);
95 Coord corner2(hi[0], hi[1], lo[2]);
96 Coord corner3(lo[0], hi[1], lo[2]);
97 Coord corner4(lo[0], lo[1], hi[2]);
98 Coord corner5(hi[0], lo[1], hi[2]);
99 Coord corner6(hi[0], hi[1], hi[2]);
100 Coord corner7(lo[0], hi[1], hi[2]);
101 Real dist0 = (pos - corner0).norm();
102 Real dist1 = (pos - corner1).norm();
103 Real dist2 = (pos - corner2).norm();
104 Real dist3 = (pos - corner3).norm();
105 Real dist4 = (pos - corner4).norm();
106 Real dist5 = (pos - corner5).norm();
107 Real dist6 = (pos - corner6).norm();
108 Real dist7 = (pos - corner7).norm();
109 if (pos[0] < hi[0] && pos[0] > lo[0] && pos[1] < hi[1] && pos[1] > lo[1] && pos[2] < hi[2] && pos[2] > lo[2])
111 Real distx = min(abs(pos[0] - hi[0]), abs(pos[0] - lo[0]));
112 Real disty = min(abs(pos[1] - hi[1]), abs(pos[1] - lo[1]));
113 Real distz = min(abs(pos[2] - hi[2]), abs(pos[2] - lo[2]));
114 Real mindist = min(distx, disty);
115 mindist = min(mindist, distz);
120 Real distx1 = DistanceToSqure(pos, corner0, corner7, 0);
121 Real distx2 = DistanceToSqure(pos, corner1, corner6, 0);
122 Real disty1 = DistanceToSqure(pos, corner0, corner5, 1);
123 Real disty2 = DistanceToSqure(pos, corner3, corner6, 1);
124 Real distz1 = DistanceToSqure(pos, corner0, corner2, 2);
125 Real distz2 = DistanceToSqure(pos, corner4, corner6, 2);
126 return -min(min(min(distx1, distx2), min(disty1, disty2)), min(distz1, distz2));
130 template <typename Real, typename Coord>
131 __device__ Real DistanceToCylinder(Coord& pos, Coord& center, Real radius, Real height, int axis)
138 distH = abs(pos[0] - center[0]);
139 distR = Coord(0.0, pos[1] - center[1], pos[2] - center[2]).norm();
142 distH = abs(pos[1] - center[1]);
143 distR = Coord(pos[0] - center[0], 0.0, pos[2] - center[2]).norm();
146 distH = abs(pos[2] - center[2]);
147 distR = Coord(pos[0] - center[0], pos[1] - center[1], 0.0).norm();
151 Real halfH = height / 2.0f;
152 if (distH <= halfH && distR <= radius)
154 return -min(halfH - distH, radius - distR);
156 else if (distH > halfH && distR <= radius)
158 return distH - halfH;
160 else if (distH <= halfH && distR > radius)
162 return distR - radius;
166// Real l1 = distR - radius;
167// Real l2 = distH - halfH;
168// return sqrt(l1*l1 + l2*l2);
169 return Vector<Real, 2>(distR - radius, distH - halfH).norm();
175 template <typename Real, typename Coord>
176 __device__ Real DistanceToSphere(Coord& pos, Coord& center, Real radius)
178 return (pos - center).length() - radius;
181 template<typename TDataType>
182 DistanceField3D<TDataType>::DistanceField3D()
186 template<typename TDataType>
187 DistanceField3D<TDataType>::DistanceField3D(std::string filename)
192 template<typename TDataType>
193 void DistanceField3D<TDataType>::setSpace(const Coord p0, const Coord p1, Real h)
198 uint nbx = std::ceil((p1.x - p0.x) / h);
199 uint nby = std::ceil((p1.y - p0.y) / h);
200 uint nbz = std::ceil((p1.z - p0.z) / h);
202 mDistances.resize(nbx+1, nby+1, nbz+1);
205 template<typename TDataType>
206 DistanceField3D<TDataType>::~DistanceField3D()
210 template<typename TDataType>
211 void DistanceField3D<TDataType>::translate(const Coord &t) {
215 template <typename Real>
216 __global__ void K_Scale(DArray3D<Real> distance, float s)
218 int i = threadIdx.x + (blockIdx.x * blockDim.x);
219 int j = threadIdx.y + (blockIdx.y * blockDim.y);
220 int k = threadIdx.z + (blockIdx.z * blockDim.z);
222 if (i >= distance.nx()) return;
223 if (j >= distance.ny()) return;
224 if (k >= distance.nz()) return;
226 distance(i, j, k) = s*distance(i, j, k);
229 template<typename TDataType>
230 void DistanceField3D<TDataType>::scale(const Real s) {
236 dim3 blockSize = make_uint3(8, 8, 8);
237 dim3 gridDims = cudaGridSize3D(make_uint3(mDistances.nx(), mDistances.ny(), mDistances.nz()), blockSize);
239 K_Scale << <gridDims, blockSize >> >(mDistances, s);
242 template<typename Real>
243 __global__ void K_Invert(DArray3D<Real> distance)
245 int i = threadIdx.x + (blockIdx.x * blockDim.x);
246 int j = threadIdx.y + (blockIdx.y * blockDim.y);
247 int k = threadIdx.z + (blockIdx.z * blockDim.z);
249 if (i >= distance.nx()) return;
250 if (j >= distance.ny()) return;
251 if (k >= distance.nz()) return;
253 distance(i, j, k) = -distance(i, j, k);
256 template<typename TDataType>
257 void DistanceField3D<TDataType>::invertSDF()
259 dim3 blockSize = make_uint3(8, 8, 8);
260 dim3 gridDims = cudaGridSize3D(make_uint3(mDistances.nx(), mDistances.ny(), mDistances.nz()), blockSize);
262 K_Invert << <gridDims, blockSize >> >(mDistances);
265 template <typename Real, typename Coord>
266 __global__ void K_DistanceFieldToBox(DArray3D<Real> distance, Coord start, Real h, Coord lo, Coord hi, bool inverted)
268 int i = threadIdx.x + (blockIdx.x * blockDim.x);
269 int j = threadIdx.y + (blockIdx.y * blockDim.y);
270 int k = threadIdx.z + (blockIdx.z * blockDim.z);
272 if (i >= distance.nx()) return;
273 if (j >= distance.ny()) return;
274 if (k >= distance.nz()) return;
276 int sign = inverted ? 1.0f : -1.0f;
277 Coord p = start + Coord(i, j, k) * h;
279 distance(i, j, k) = sign*DistanceToBox(p, lo, hi);
282 template<typename TDataType>
283 void DistanceField3D<TDataType>::loadBox(Coord& lo, Coord& hi, bool inverted)
285 mInverted = inverted;
287 dim3 blockSize = make_uint3(4, 4, 4);
288 dim3 gridDims = cudaGridSize3D(make_uint3(mDistances.nx(), mDistances.ny(), mDistances.nz()), blockSize);
290 K_DistanceFieldToBox << <gridDims, blockSize >> >(mDistances, mOrigin, mH, lo, hi, inverted);
293 template <typename Real, typename Coord>
294 __global__ void K_DistanceFieldToCylinder(DArray3D<Real> distance, Coord start, Real h, Coord center, Real radius, Real height, int axis, bool inverted)
296 int i = threadIdx.x + (blockIdx.x * blockDim.x);
297 int j = threadIdx.y + (blockIdx.y * blockDim.y);
298 int k = threadIdx.z + (blockIdx.z * blockDim.z);
300 if (i >= distance.nx()) return;
301 if (j >= distance.ny()) return;
302 if (k >= distance.nz()) return;
304 int sign = inverted ? -1.0f : 1.0f;
306 Coord p = start + Coord(i, j, k)*h;
308 distance(i, j, k) = sign*DistanceToCylinder(p, center, radius, height, axis);
311 template<typename TDataType>
312 void DistanceField3D<TDataType>::loadCylinder(Coord& center, Real radius, Real height, int axis, bool inverted)
314 mInverted = inverted;
316 dim3 blockSize = make_uint3(8, 8, 8);
317 dim3 gridDims = cudaGridSize3D(make_uint3(mDistances.nx(), mDistances.ny(), mDistances.nz()), blockSize);
319 K_DistanceFieldToCylinder << <gridDims, blockSize >> >(mDistances, mOrigin, mH, center, radius, height, axis, inverted);
322 template <typename Real, typename Coord>
323 __global__ void K_DistanceFieldToSphere(DArray3D<Real> distance, Coord start, Real h, Coord center, Real radius, bool inverted)
325 int i = threadIdx.x + (blockIdx.x * blockDim.x);
326 int j = threadIdx.y + (blockIdx.y * blockDim.y);
327 int k = threadIdx.z + (blockIdx.z * blockDim.z);
329 if (i >= distance.nx()) return;
330 if (j >= distance.ny()) return;
331 if (k >= distance.nz()) return;
333 int sign = inverted ? -1.0f : 1.0f;
335 Coord p = start + Coord(i, j, k) * h;
337 Coord dir = p - center;
339 distance(i, j, k) = sign*(dir.norm()-radius);
342 template<typename TDataType>
343 void DistanceField3D<TDataType>::loadSphere(Coord& center, Real radius, bool inverted)
345 mInverted = inverted;
347 dim3 blockSize = make_uint3(8, 8, 8);
348 dim3 gridDims = cudaGridSize3D(make_uint3(mDistances.nx(), mDistances.ny(), mDistances.nz()), blockSize);
350 K_DistanceFieldToSphere << <gridDims, blockSize >> >(mDistances, mOrigin, mH, center, radius, inverted);
353 template<typename TDataType>
354 void DistanceField3D<TDataType>::loadSDF(std::string filename, bool inverted)
356 std::ifstream input(filename.c_str(), std::ios::in);
357 if (!input.is_open())
359 std::cout << "Reading file " << filename << " error!" << std::endl;
377 std::cout << "SDF: " << xx << ", " << yy << ", " << zz << std::endl;
378 std::cout << "SDF: " << mOrigin[0] << ", " << mOrigin[1] << ", " << mOrigin[2] << std::endl;
379 std::cout << "SDF: " << mOrigin[0] + t_h*xx << ", " << mOrigin[1] + t_h*yy << ", " << mOrigin[2] + t_h*zz << std::endl;
386 CArray3D<Real> distances(nbx, nby, nbz);
387 for (int k = 0; k < zz; k++) {
388 for (int j = 0; j < yy; j++) {
389 for (int i = 0; i < xx; i++) {
392 distances(i, j, k) = dist;
398 mDistances.resize(nbx, nby, nbz);
399 mDistances.assign(distances);
401 mInverted = inverted;
407 std::cout << "read data successful" << std::endl;
410 template<typename TDataType>
411 void DistanceField3D<TDataType>::release()
416 template class DistanceField3D<DataType3f>;
417 template class DistanceField3D<DataType3d>;