OpenVDB  9.0.1
Primitives.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /*!
5  \file Primitives.h
6 
7  \author Ken Museth
8 
9  \date June 26, 2020
10 
11  \brief Generates volumetric primitives, e.g. sphere, torus etc, as NanoVDB grid.
12 
13  \note This has no dependency on openvdb.
14 */
15 
16 #ifndef NANOVDB_PRIMITIVES_H_HAS_BEEN_INCLUDED
17 #define NANOVDB_PRIMITIVES_H_HAS_BEEN_INCLUDED
18 
19 #include "GridBuilder.h"
20 
21 namespace nanovdb {
22 
23 /// @brief Returns a handle to a narrow-band level set of a sphere
24 ///
25 /// @param radius Radius of sphere in world units
26 /// @param center Center of sphere in world units
27 /// @param voxelSize Size of a voxel in world units
28 /// @param halfWidth Half-width of narrow band in voxel units
29 /// @param origin Origin of grid in world units
30 /// @param name Name of the grid
31 /// @param sMode Mode of computation for the statistics.
32 /// @param cMode Mode of computation for the checksum.
33 /// @param tolerance Global error tolerance use when VoxelT = FpN
34 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
35 /// @param buffer Buffer used for memory allocation by the handle
36 ///
37 /// @details The @c ValueT template parameter must be float (default) or double.
38 /// The @c VoxelT template parameter must be one of the following:
39 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
40 /// argument is only used when VoxelT is set to FpN.
41 template<typename ValueT = float,
42  typename VoxelT = ValueT,
43  typename BufferT = HostBuffer>
44 GridHandle<BufferT>
45 createLevelSetSphere(ValueT radius = 100,
46  const Vec3<ValueT>& center = Vec3<ValueT>(0),
47  double voxelSize = 1.0,
48  double halfWidth = 3.0,
49  const Vec3d& origin = Vec3d(0),
50  const std::string& name = "sphere_ls",
53  float tolerance = -1.0f,
54  bool ditherOn = false,
55  const BufferT& buffer = BufferT());
56 
57 //================================================================================================
58 
59 /// @brief Returns a handle to a sparse fog volume of a sphere such
60 /// that the exterior is 0 and inactive, the interior is active
61 /// with values varying smoothly from 0 at the surface of the
62 /// sphere to 1 at the halfWidth and interior of the sphere.
63 ///
64 /// @param radius Radius of sphere in world units
65 /// @param center Center of sphere in world units
66 /// @param voxelSize Size of a voxel in world units
67 /// @param halfWidth Half-width of narrow band in voxel units
68 /// @param origin Origin of grid in world units
69 /// @param name Name of the grid
70 /// @param sMode Mode of computation for the statistics.
71 /// @param cMode Mode of computation for the checksum.
72 /// @param tolerance Global error tolerance use when VoxelT = FpN
73 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
74 /// @param buffer Buffer used for memory allocation by the handle
75 ///
76 /// @details The @c ValueT template parameter must be float (default) or double.
77 /// The @c VoxelT template parameter must be one of the following:
78 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
79 /// argument is only used when VoxelT is set to FpN.
80 template<typename ValueT = float,
81  typename VoxelT = ValueT,
82  typename BufferT = HostBuffer>
83 GridHandle<BufferT>
84 createFogVolumeSphere(ValueT radius = 100.0f,
85  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
86  double voxelSize = 1.0f,
87  double halfWidth = 3.0f,
88  const Vec3d& origin = Vec3d(0.0),
89  const std::string& name = "sphere_fog",
92  float tolerance = -1.0f,
93  bool ditherOn = false,
94  const BufferT& buffer = BufferT());
95 
96 //================================================================================================
97 
98 /// @brief Returns a handle to a PointDataGrid containing points scattered
99 /// on the surface of a sphere.
100 ///
101 /// @param pointsPerVoxel Number of point per voxel on on the surface
102 /// @param radius Radius of sphere in world units
103 /// @param center Center of sphere in world units
104 /// @param voxelSize Size of a voxel in world units
105 /// @param origin Origin of grid in world units
106 /// @param name Name of the grid
107 /// @param mode Mode of computation for the checksum.
108 /// @param buffer Buffer used for memory allocation by the handle
109 ///
110 /// @details The @c ValueT template parameter must be float (default) or double.
111 template<typename ValueT = float,
112  typename BufferT = HostBuffer>
113 inline GridHandle<BufferT>
114 createPointSphere(int pointsPerVoxel = 1,
115  ValueT radius = 100.0f,
116  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
117  double voxelSize = 1.0f,
118  const Vec3d& origin = Vec3d(0.0),
119  const std::string& name = "sphere_points",
121  const BufferT& buffer = BufferT());
122 
123 //================================================================================================
124 
125 /// @brief Returns a handle to a narrow-band level set of a torus in the xz-plane
126 ///
127 /// @param majorRadius Major radius of torus in world units
128 /// @param minorRadius Minor radius of torus in world units
129 /// @param center Center of torus in world units
130 /// @param voxelSize Size of a voxel in world units
131 /// @param halfWidth Half-width of narrow band in voxel units
132 /// @param origin Origin of grid in world units
133 /// @param name Name of the grid
134 /// @param sMode Mode of computation for the statistics.
135 /// @param cMode Mode of computation for the checksum.
136 /// @param tolerance Global error tolerance use when VoxelT = FpN
137 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
138 /// @param buffer Buffer used for memory allocation by the handle
139 ///
140 /// @details The @c ValueT template parameter must be float (default) or double.
141 /// The @c VoxelT template parameter must be one of the following:
142 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
143 /// argument is only used when VoxelT is set to FpN.
144 template<typename ValueT = float,
145  typename VoxelT = ValueT,
146  typename BufferT = HostBuffer>
147 GridHandle<BufferT>
148 createLevelSetTorus(ValueT majorRadius = 100.0f,
149  ValueT minorRadius = 50.0f,
150  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
151  double voxelSize = 1.0,
152  double halfWidth = 3.0,
153  const Vec3d& origin = Vec3d(0.0),
154  const std::string& name = "torus_ls",
157  float tolerance = -1.0f,
158  bool ditherOn = false,
159  const BufferT& buffer = BufferT());
160 
161 //================================================================================================
162 
163 /// @brief Returns a handle to a sparse fog volume of a torus in the xz-plane such
164 /// that the exterior is 0 and inactive, the interior is active
165 /// with values varying smoothly from 0 at the surface of the
166 /// torus to 1 at the halfWidth and interior of the torus.
167 ///
168 /// @param majorRadius Major radius of torus in world units
169 /// @param minorRadius Minor radius of torus in world units
170 /// @param center Center of torus in world units
171 /// @param voxelSize Size of a voxel in world units
172 /// @param halfWidth Half-width of narrow band in voxel units
173 /// @param origin Origin of grid in world units
174 /// @param name Name of the grid
175 /// @param sMode Mode of computation for the statistics.
176 /// @param cMode Mode of computation for the checksum.
177 /// @param tolerance Global error tolerance use when VoxelT = FpN
178 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
179 /// @param buffer Buffer used for memory allocation by the handle
180 ///
181 /// @details The @c ValueT template parameter must be float (default) or double.
182 /// The @c VoxelT template parameter must be one of the following:
183 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
184 /// argument is only used when VoxelT is set to FpN.
185 template<typename ValueT = float,
186  typename VoxelT = ValueT,
187  typename BufferT = HostBuffer>
188 GridHandle<BufferT>
189 createFogVolumeTorus(ValueT majorRadius = 100.0f,
190  ValueT minorRadius = 50.0f,
191  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
192  double voxelSize = 1.0,
193  double halfWidth = 3.0,
194  const Vec3d& origin = Vec3d(0),
195  const std::string& name = "torus_fog",
198  float tolerance = -1.0f,
199  bool ditherOn = false,
200  const BufferT& buffer = BufferT());
201 
202 //================================================================================================
203 
204 /// @brief Returns a handle to a PointDataGrid containing points scattered
205 /// on the surface of a torus.
206 ///
207 /// @param pointsPerVoxel Number of point per voxel on on the surface
208 /// @param majorRadius Major radius of torus in world units
209 /// @param minorRadius Minor radius of torus in world units
210 /// @param center Center of torus in world units
211 /// @param voxelSize Size of a voxel in world units
212 /// @param origin Origin of grid in world units
213 /// @param name Name of the grid
214 /// @param cMode Mode of computation for the checksum.
215 /// @param buffer Buffer used for memory allocation by the handle
216 //
217 /// @details The @c ValueT template parameter must be float (default) or double.
218 template<typename ValueT = float,
219  typename BufferT = HostBuffer>
220 inline GridHandle<BufferT>
221 createPointTorus(int pointsPerVoxel = 1, // half-width of narrow band in voxel units
222  ValueT majorRadius = 100.0f, // major radius of torus in world units
223  ValueT minorRadius = 50.0f, // minor radius of torus in world units
224  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f), //center of torus in world units
225  double voxelSize = 1.0, // size of a voxel in world units
226  const Vec3d& origin = Vec3d(0.0f), // origin of grid in world units
227  const std::string& name = "torus_points", // name of grid
229  const BufferT& buffer = BufferT());
230 
231 //================================================================================================
232 
233 /// @brief Returns a handle to a narrow-band level set of a box
234 ///
235 /// @param width Width of box in world units
236 /// @param height Height of box in world units
237 /// @param depth Depth of box in world units
238 /// @param center Center of box in world units
239 /// @param voxelSize Size of a voxel in world units
240 /// @param halfWidth Half-width of narrow band in voxel units
241 /// @param origin Origin of grid in world units
242 /// @param name Name of the grid
243 /// @param sMode Mode of computation for the statistics.
244 /// @param cMode Mode of computation for the checksum.
245 /// @param tolerance Global error tolerance use when VoxelT = FpN
246 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
247 /// @param buffer Buffer used for memory allocation by the handle
248 ///
249 //// @details The @c ValueT template parameter must be float (default) or double.
250 /// The @c VoxelT template parameter must be one of the following:
251 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
252 /// argument is only used when VoxelT is set to FpN.
253 template<typename ValueT = float,
254  typename VoxelT = ValueT,
255  typename BufferT = HostBuffer>
256 GridHandle<BufferT>
257 createLevelSetBox(ValueT width = 40.0f,
258  ValueT height = 60.0f,
259  ValueT depth = 100.0f,
260  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
261  double voxelSize = 1.0,
262  double halfWidth = 3.0,
263  const Vec3d& origin = Vec3d(0.0),
264  const std::string& name = "box_ls",
267  float tolerance = -1.0f,
268  bool ditherOn = false,
269  const BufferT& buffer = BufferT());
270 
271 //================================================================================================
272 
273 /// @brief Returns a handle to a sparse fog volume of a box such
274 /// that the exterior is 0 and inactive, the interior is active
275 /// with values varying smoothly from 0 at the surface of the
276 /// box to 1 at the halfWidth and interior of the box.
277 ///
278 /// @param width Width of box in world units
279 /// @param height Height of box in world units
280 /// @param depth Depth of box in world units
281 /// @param center Center of box in world units
282 /// @param voxelSize Size of a voxel in world units
283 /// @param halfWidth Half-width of narrow band in voxel units
284 /// @param origin Origin of grid in world units
285 /// @param name Name of the grid
286 /// @param sMode Mode of computation for the statistics.
287 /// @param cMode Mode of computation for the checksum.
288 /// @param tolerance Global error tolerance use when VoxelT = FpN
289 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
290 /// @param buffer Buffer used for memory allocation by the handle
291 ///
292 /// @details The @c ValueT template parameter must be float (default) or double.
293 /// The @c VoxelT template parameter must be one of the following:
294 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
295 /// argument is only used when VoxelT is set to FpN.
296 template<typename ValueT = float,
297  typename VoxelT = ValueT,
298  typename BufferT = HostBuffer>
299 GridHandle<BufferT>
300 createFogVolumeBox(ValueT width = 40.0f,
301  ValueT height = 60.0f,
302  ValueT depth = 100.0f,
303  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
304  double voxelSize = 1.0,
305  double halfWidth = 3.0,
306  const Vec3d& origin = Vec3d(0.0),
307  const std::string& name = "box_fog",
310  float tolerance = -1.0f,
311  bool ditherOn = false,
312  const BufferT& buffer = BufferT());
313 
314 //================================================================================================
315 
316 /// @brief Returns a handle to a narrow-band level set of a octahedron
317 ///
318 /// @param scale Scale of octahedron in world units
319 /// @param center Center of octahedron in world units
320 /// @param voxelSize Size of a voxel in world units
321 /// @param halfWidth Half-width of narrow band in voxel units
322 /// @param origin Origin of grid in world units
323 /// @param name Name of the grid
324 /// @param sMode Mode of computation for the statistics.
325 /// @param cMode Mode of computation for the checksum.
326 /// @param tolerance Global error tolerance use when VoxelT = FpN
327 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
328 /// @param buffer Buffer used for memory allocation by the handle
329 ///
330 /// @details The @c ValueT template parameter must be float (default) or double.
331 /// The @c VoxelT template parameter must be one of the following:
332 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
333 /// argument is only used when VoxelT is set to FpN.
334 template<typename ValueT = float,
335  typename VoxelT = ValueT,
336  typename BufferT = HostBuffer>
337 GridHandle<BufferT>
338 createLevelSetOctahedron(ValueT scale = 100.0f,
339  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
340  double voxelSize = 1.0,
341  double halfWidth = 3.0,
342  const Vec3d& origin = Vec3d(0.0),
343  const std::string& name = "octadedron_ls",
346  float tolerance = -1.0f,
347  bool ditherOn = false,
348  const BufferT& buffer = BufferT());
349 
350 //================================================================================================
351 
352 /// @brief Returns a handle to a sparse fog volume of an octahedron such
353 /// that the exterior is 0 and inactive, the interior is active
354 /// with values varying smoothly from 0 at the surface of the
355 /// octahedron to 1 at the halfWidth and interior of the octahedron.
356 ///
357 /// @param scale Scale of octahedron in world units
358 /// @param center Center of box in world units
359 /// @param voxelSize Size of a voxel in world units
360 /// @param halfWidth Half-width of narrow band in voxel units
361 /// @param origin Origin of grid in world units
362 /// @param name Name of the grid
363 /// @param sMode Mode of computation for the statistics.
364 /// @param cMode Mode of computation for the checksum.
365 /// @param tolerance Global error tolerance use when VoxelT = FpN
366 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
367 /// @param buffer Buffer used for memory allocation by the handle
368 ///
369 /// @details The @c ValueT template parameter must be float (default) or double.
370 /// The @c VoxelT template parameter must be one of the following:
371 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
372 /// argument is only used when VoxelT is set to FpN.
373 template<typename ValueT = float,
374  typename VoxelT = ValueT,
375  typename BufferT = HostBuffer>
376 GridHandle<BufferT>
377 createFogVolumeOctahedron(ValueT scale = 100.0f,
378  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
379  double voxelSize = 1.0,
380  double halfWidth = 3.0,
381  const Vec3d& origin = Vec3d(0.0),
382  const std::string& name = "octadedron_fog",
385  float tolerance = -1.0f,
386  bool ditherOn = false,
387  const BufferT& buffer = BufferT());
388 
389 //================================================================================================
390 
391 /// @brief Returns a handle to a narrow-band level set of a bounding-box (= wireframe of a box)
392 ///
393 /// @param width Width of box in world units
394 /// @param height Height of box in world units
395 /// @param depth Depth of box in world units
396 /// @param thickness Thickness of the wire in world units
397 /// @param center Center of bbox in world units
398 /// @param voxelSize Size of a voxel in world units
399 /// @param halfWidth Half-width of narrow band in voxel units
400 /// @param origin Origin of grid in world units
401 /// @param name Name of the grid
402 /// @param sMode Mode of computation for the statistics.
403 /// @param cMode Mode of computation for the checksum.
404 /// @param tolerance Global error tolerance use when VoxelT = FpN
405 /// @param ditherOn If true dithering will be applied when VoxelT = {Fp4,Fp8,Fp16,FpN}
406 /// @param buffer Buffer used for memory allocation by the handle
407 ///
408 /// @details The @c ValueT template parameter must be float (default) or double.
409 /// The @c VoxelT template parameter must be one of the following:
410 /// float (default), double, Fp4, Fp8, Fp16 or FpN. The @c tolerance
411 /// argument is only used when VoxelT is set to FpN.
412 template<typename ValueT = float,
413  typename VoxelT = ValueT,
414  typename BufferT = HostBuffer>
415 GridHandle<BufferT>
416 createLevelSetBBox(ValueT width = 40.0f,
417  ValueT height = 60.0f,
418  ValueT depth = 100.0f,
419  ValueT thickness = 10.0f,
420  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f),
421  double voxelSize = 1.0,
422  double halfWidth = 3.0,
423  const Vec3d& origin = Vec3d(0.0),
424  const std::string& name = "bbox_ls",
427  float tolerance = -1.0f,
428  bool ditherOn = false,
429  const BufferT& buffer = BufferT());
430 
431 
432 //================================================================================================
433 
434 /// @brief Returns a handle to a PointDataGrid containing points scattered
435 /// on the surface of a box.
436 ///
437 /// @param pointsPerVoxel Number of point per voxel on on the surface
438 /// @param width Width of box in world units
439 /// @param height Height of box in world units
440 /// @param depth Depth of box in world units
441 /// @param center Center of box in world units
442 /// @param voxelSize Size of a voxel in world units
443 /// @param origin Origin of grid in world units
444 /// @param name Name of the grid
445 /// @param mode Mode of computation for the checksum.
446 /// @param buffer Buffer used for memory allocation by the handle
447 template<typename ValueT = float,
448  typename BufferT = HostBuffer>
449 inline GridHandle<BufferT>
450 createPointBox(int pointsPerVoxel = 1, // half-width of narrow band in voxel units
451  ValueT width = 40.0f, // width of box in world units
452  ValueT height = 60.0f, // height of box in world units
453  ValueT depth = 100.0f, // depth of box in world units
454  const Vec3<ValueT>& center = Vec3<ValueT>(0.0f), //center of box in world units
455  double voxelSize = 1.0, // size of a voxel in world units
456  const Vec3d& origin = Vec3d(0.0), // origin of grid in world units
457  const std::string& name = "box_points", // name of grid
459  const BufferT& buffer = BufferT());
460 
461 //================================================================================================
462 
463 /// @brief Given an input NanoVDB voxel grid this methods returns a GridHandle to another NanoVDB
464 /// PointDataGrid with points scattered in the active leaf voxels of in input grid.
465 ///
466 /// @param srcGrid Const input grid used to determine the active voxels to scatter points into
467 /// @param pointsPerVoxel Number of point per voxel on on the surface
468 /// @param name Name of the grid
469 /// @param mode Mode of computation for the checksum.
470 /// @param buffer Buffer used for memory allocation by the handle
471 template<typename ValueT = float,
472  typename BufferT = HostBuffer>
473 inline GridHandle<BufferT>
474 createPointScatter(const NanoGrid<ValueT>& srcGrid, // origin of grid in world units
475  int pointsPerVoxel = 1, // half-width of narrow band in voxel units
476  const std::string& name = "point_scatter", // name of grid
478  const BufferT& buffer = BufferT());
479 
480 //================================================================================================
481 
482 namespace {
483 
484 /// @brief Returns a shared pointer to a GridBuilder with narrow-band SDF values for a sphere
485 ///
486 /// @brief Note, this is not (yet) a valid level set SDF field since values inside sphere (and outside
487 /// the narrow band) are still undefined. Call GridBuilder::sdfToLevelSet() to set those
488 /// values or alternatively call GridBuilder::sdfToFog to generate a FOG volume.
489 ///
490 /// @details The @c VoxelT template parameter must be one of the following:
491 /// float (default), Fp4, Fp8, Fp16 or FpN.
492 template<typename ValueT, typename VoxelT>
493 std::shared_ptr<GridBuilder<ValueT, VoxelT>>
494 initSphere(ValueT radius, // radius of sphere in world units
495  const Vec3<ValueT>& center, //center of sphere in world units
496  double voxelSize, // size of a voxel in world units
497  double halfWidth, // half-width of narrow band in voxel units
498  const Vec3d& origin) // origin of grid in world units
499 {
500  static_assert(is_floating_point<ValueT>::value, "initSphere: expect floating point");
501  static_assert(is_floating_point<typename BuildToValueMap<VoxelT>::Type>::value, "initSphere: expect floating point");
502  if (!(radius > 0))
503  throw std::runtime_error("Sphere: radius must be positive!");
504  if (!(voxelSize > 0))
505  throw std::runtime_error("Sphere: voxelSize must be positive!");
506  if (!(halfWidth > 0))
507  throw std::runtime_error("Sphere: halfWidth must be positive!");
508 
509  auto builder = std::make_shared<GridBuilder<ValueT, VoxelT>>(ValueT(halfWidth * voxelSize));
510  auto acc = builder->getAccessor();
511 
512  // Define radius of sphere with narrow-band in voxel units
513  const ValueT r0 = radius / voxelSize, rmax = r0 + halfWidth;
514 
515  // Radius below the Nyquist frequency
516  if (r0 < ValueT(1.5f)) {
517  return builder;
518  }
519 
520  // Define center of sphere in voxel units
521  const Vec3<ValueT> c(ValueT(center[0] - origin[0]) / voxelSize,
522  ValueT(center[1] - origin[1]) / voxelSize,
523  ValueT(center[2] - origin[2]) / voxelSize);
524 
525  // Define bounds of the voxel coordinates
526  const int imin = Floor(c[0] - rmax), imax = Ceil(c[0] + rmax);
527  const int jmin = Floor(c[1] - rmax), jmax = Ceil(c[1] + rmax);
528  const int kmin = Floor(c[2] - rmax), kmax = Ceil(c[2] + rmax);
529 
530  Coord ijk;
531  int & i = ijk[0], &j = ijk[1], &k = ijk[2], m = 1;
532  // Compute signed distances to sphere using leapfrogging in k
533  for (i = imin; i <= imax; ++i) {
534  const auto x2 = Pow2(ValueT(i) - c[0]);
535  for (j = jmin; j <= jmax; ++j) {
536  const auto x2y2 = Pow2(ValueT(j) - c[1]) + x2;
537  for (k = kmin; k <= kmax; k += m) {
538  m = 1;
539  const auto v = Sqrt(x2y2 + Pow2(ValueT(k) - c[2])) - r0; // Distance in voxel units
540  const auto d = v < 0 ? -v : v;
541  if (d < halfWidth) { // inside narrow band
542  acc.setValue(ijk, voxelSize * v); // distance in world units
543  } else { // outside narrow band
544  m += Floor(d - halfWidth); // leapfrog
545  }
546  } //end leapfrog over k
547  } //end loop over j
548  } //end loop over i
549 
550  return builder;
551 } // initSphere
552 
553 template<typename ValueT, typename VoxelT>
554 std::shared_ptr<GridBuilder<ValueT, VoxelT>>
555 initTorus(ValueT radius1, // major radius of torus in world units
556  ValueT radius2, // minor radius of torus in world units
557  const Vec3<ValueT>& center, //center of torus in world units
558  double voxelSize, // size of a voxel in world units
559  double halfWidth, // half-width of narrow band in voxel units
560  const Vec3d& origin) // origin of grid in world units
561 {
562  static_assert(is_floating_point<ValueT>::value, "initTorus: expect floating point");
563  static_assert(is_floating_point<typename BuildToValueMap<VoxelT>::Type>::value, "initTorus: expect floating point");
564  if (!(radius2 > 0))
565  throw std::runtime_error("Torus: radius2 must be positive!");
566  if (!(radius1 > radius2))
567  throw std::runtime_error("Torus: radius1 must be larger than radius2!");
568  if (!(voxelSize > 0))
569  throw std::runtime_error("Torus: voxelSize must be positive!");
570  if (!(halfWidth > 0))
571  throw std::runtime_error("Torus: halfWidth must be positive!");
572 
573  auto builder = std::make_shared<GridBuilder<ValueT, VoxelT>>(ValueT(halfWidth * voxelSize));
574  auto acc = builder->getAccessor();
575 
576  // Define size of torus with narrow-band in voxel units
577  const ValueT r1 = radius1 / voxelSize, r2 = radius2 / voxelSize, rmax1 = r1 + r2 + halfWidth, rmax2 = r2 + halfWidth;
578 
579  // Radius below the Nyquist frequency
580  if (r2 < ValueT(1.5))
581  return builder;
582 
583  // Define center of torus in voxel units
584  const Vec3<ValueT> c(ValueT(center[0] - origin[0]) / voxelSize,
585  ValueT(center[1] - origin[1]) / voxelSize,
586  ValueT(center[2] - origin[2]) / voxelSize);
587 
588  // Define bounds of the voxel coordinates
589  const int imin = Floor(c[0] - rmax1), imax = Ceil(c[0] + rmax1);
590  const int jmin = Floor(c[1] - rmax2), jmax = Ceil(c[1] + rmax2);
591  const int kmin = Floor(c[2] - rmax1), kmax = Ceil(c[2] + rmax1);
592 
593  Coord ijk;
594  int & i = ijk[0], &j = ijk[1], &k = ijk[2], m = 1;
595  // Compute signed distances to torus using leapfrogging in k
596  for (i = imin; i <= imax; ++i) {
597  const auto x2 = Pow2(ValueT(i) - c[0]);
598  for (k = kmin; k <= kmax; ++k) {
599  const auto x2z2 = Pow2(Sqrt(Pow2(ValueT(k) - c[2]) + x2) - r1);
600  for (j = jmin; j <= jmax; j += m) {
601  m = 1;
602  const auto v = Sqrt(x2z2 + Pow2(ValueT(j) - c[1])) - r2; // Distance in voxel units
603  const auto d = v < 0 ? -v : v;
604  if (d < halfWidth) { // inside narrow band
605  acc.setValue(ijk, voxelSize * v); // distance in world units
606  } else { // outside narrow band
607  m += Floor(d - halfWidth); // leapfrog
608  }
609  } //end leapfrog over k
610  } //end loop over j
611  } //end loop over i
612 
613  return builder;
614 } // initTorus
615 
616 template<typename ValueT, typename VoxelT>
617 std::shared_ptr<GridBuilder<ValueT, VoxelT>>
618 initBox(ValueT width, // major radius of torus in world units
619  ValueT height, // minor radius of torus in world units
620  ValueT depth,
621  const Vec3<ValueT>& center, //center of box in world units
622  double voxelSize, // size of a voxel in world units
623  double halfWidth, // half-width of narrow band in voxel units
624  const Vec3d& origin) // origin of grid in world units
625 {
626  static_assert(is_floating_point<ValueT>::value, "initBox: expect floating point");
627  static_assert(is_floating_point<typename BuildToValueMap<VoxelT>::Type>::value, "initBox: expect floating point");
628  using Vec3T = Vec3<ValueT>;
629  if (!(width > 0))
630  throw std::runtime_error("Box: width must be positive!");
631  if (!(height > 0))
632  throw std::runtime_error("Box: height must be positive!");
633  if (!(depth > 0))
634  throw std::runtime_error("Box: depth must be positive!");
635 
636  if (!(voxelSize > 0))
637  throw std::runtime_error("Box: voxelSize must be positive!");
638  if (!(halfWidth > 0))
639  throw std::runtime_error("Box: halfWidth must be positive!");
640 
641  auto builder = std::make_shared<GridBuilder<ValueT, VoxelT>>(ValueT(halfWidth * voxelSize));
642  auto acc = builder->getAccessor();
643 
644  // Define size of box with narrow-band in voxel units
645  const Vec3T r(width / (2 * voxelSize), height / (2 * voxelSize), depth / (2 * voxelSize));
646 
647  // Below the Nyquist frequency
648  if (r.min() < ValueT(1.5))
649  return builder;
650 
651  // Define center of box in voxel units
652  const Vec3T c(ValueT(center[0] - origin[0]) / voxelSize,
653  ValueT(center[1] - origin[1]) / voxelSize,
654  ValueT(center[2] - origin[2]) / voxelSize);
655 
656  // Define utility functions
657  auto Pos = [](ValueT x) { return x > 0 ? x : 0; };
658  auto Neg = [](ValueT x) { return x < 0 ? x : 0; };
659 
660  // Define bounds of the voxel coordinates
661  const BBox<Vec3T> b(c - r - Vec3T(halfWidth), c + r + Vec3T(halfWidth));
662  const CoordBBox bbox(Coord(Floor(b[0][0]), Floor(b[0][1]), Floor(b[0][2])),
663  Coord(Ceil(b[1][0]), Ceil(b[1][1]), Ceil(b[1][2])));
664 
665  // Compute signed distances to box using leapfrogging in k
666  int m = 1;
667  for (Coord p = bbox[0]; p[0] <= bbox[1][0]; ++p[0]) {
668  const auto q1 = Abs(ValueT(p[0]) - c[0]) - r[0];
669  const auto x2 = Pow2(Pos(q1));
670  for (p[1] = bbox[0][1]; p[1] <= bbox[1][1]; ++p[1]) {
671  const auto q2 = Abs(ValueT(p[1]) - c[1]) - r[1];
672  const auto q0 = Max(q1, q2);
673  const auto x2y2 = x2 + Pow2(Pos(q2));
674  for (p[2] = bbox[0][2]; p[2] <= bbox[1][2]; p[2] += m) {
675  m = 1;
676  const auto q3 = Abs(ValueT(p[2]) - c[2]) - r[2];
677  const auto v = Sqrt(x2y2 + Pow2(Pos(q3))) + Neg(Max(q0, q3)); // Distance in voxel units
678  const auto d = Abs(v);
679  if (d < halfWidth) { // inside narrow band
680  acc.setValue(p, voxelSize * v); // distance in world units
681  } else { // outside narrow band
682  m += Floor(d - halfWidth); // leapfrog
683  }
684  } //end leapfrog over k
685  } //end loop over j
686  } //end loop over i
687 
688  return builder;
689 } // initBox
690 
691 template<typename ValueT, typename VoxelT>
692 std::shared_ptr<GridBuilder<ValueT, VoxelT>>
693 initBBox(ValueT width, // width of the bbox in world units
694  ValueT height, // height of the bbox in world units
695  ValueT depth, // depth of the bbox in world units
696  ValueT thickness, // thickness of the wire in world units
697  const Vec3<ValueT>& center, //center of bbox in world units
698  double voxelSize, // size of a voxel in world units
699  double halfWidth, // half-width of narrow band in voxel units
700  const Vec3d& origin) // origin of grid in world units
701 {
702  static_assert(is_floating_point<ValueT>::value, "initBBox: expect floating point");
703  static_assert(is_floating_point<typename BuildToValueMap<VoxelT>::Type>::value, "initBBox: expect floating point");
704  using Vec3T = Vec3<ValueT>;
705  if (!(width > 0))
706  throw std::runtime_error("BBox: width must be positive!");
707  if (!(height > 0))
708  throw std::runtime_error("BBox: height must be positive!");
709  if (!(depth > 0))
710  throw std::runtime_error("BBox: depth must be positive!");
711  if (!(thickness > 0))
712  throw std::runtime_error("BBox: thickness must be positive!");
713  if (!(voxelSize > 0.0))
714  throw std::runtime_error("BBox: voxelSize must be positive!");
715 
716  auto builder = std::make_shared<GridBuilder<ValueT, VoxelT>>(ValueT(halfWidth * voxelSize));
717  auto acc = builder->getAccessor();
718 
719  // Define size of bbox with narrow-band in voxel units
720  const Vec3T r(width / (2 * voxelSize), height / (2 * voxelSize), depth / (2 * voxelSize));
721  const ValueT e = thickness / voxelSize;
722 
723  // Below the Nyquist frequency
724  if (r.min() < ValueT(1.5) || e < ValueT(1.5))
725  return builder;
726 
727  // Define center of bbox in voxel units
728  const Vec3T c(ValueT(center[0] - origin[0]) / voxelSize,
729  ValueT(center[1] - origin[1]) / voxelSize,
730  ValueT(center[2] - origin[2]) / voxelSize);
731 
732  // Define utility functions
733  auto Pos = [](ValueT x) { return x > 0 ? x : 0; };
734  auto Neg = [](ValueT x) { return x < 0 ? x : 0; };
735 
736  // Define bounds of the voxel coordinates
737  const BBox<Vec3T> b(c - r - Vec3T(e + halfWidth), c + r + Vec3T(e + halfWidth));
738  const CoordBBox bbox(Coord(Floor(b[0][0]), Floor(b[0][1]), Floor(b[0][2])),
739  Coord(Ceil(b[1][0]), Ceil(b[1][1]), Ceil(b[1][2])));
740 
741  // Compute signed distances to bbox using leapfrogging in k
742  int m = 1;
743  for (Coord p = bbox[0]; p[0] <= bbox[1][0]; ++p[0]) {
744  const ValueT px = Abs(ValueT(p[0]) - c[0]) - r[0];
745  const ValueT qx = Abs(ValueT(px) + e) - e;
746  const ValueT px2 = Pow2(Pos(px));
747  const ValueT qx2 = Pow2(Pos(qx));
748  for (p[1] = bbox[0][1]; p[1] <= bbox[1][1]; ++p[1]) {
749  const ValueT py = Abs(ValueT(p[1]) - c[1]) - r[1];
750  const ValueT qy = Abs(ValueT(py) + e) - e;
751  const ValueT qy2 = Pow2(Pos(qy));
752  ;
753  const ValueT px2qy2 = px2 + qy2;
754  const ValueT qx2py2 = qx2 + Pow2(Pos(py));
755  const ValueT qx2qy2 = qx2 + qy2;
756  const ValueT a[3] = {Max(px, qy), Max(qx, py), Max(qx, qy)};
757  for (p[2] = bbox[0][2]; p[2] <= bbox[1][2]; p[2] += m) {
758  m = 1;
759  const ValueT pz = Abs(ValueT(p[2]) - c[2]) - r[2];
760  const ValueT qz = Abs(ValueT(pz) + e) - e;
761  const ValueT qz2 = Pow2(Pos(qz));
762  const ValueT s1 = Sqrt(px2qy2 + qz2) + Neg(Max(a[0], qz));
763  const ValueT s2 = Sqrt(qx2py2 + qz2) + Neg(Max(a[1], qz));
764  const ValueT s3 = Sqrt(qx2qy2 + Pow2(Pos(pz))) + Neg(Max(a[2], pz));
765  const ValueT v = Min(s1, Min(s2, s3)); // Distance in voxel units
766  const ValueT d = Abs(v);
767  if (d < halfWidth) { // inside narrow band
768  acc.setValue(p, voxelSize * v); // distance in world units
769  } else { // outside narrow band
770  m += Floor(d - halfWidth); // leapfrog
771  }
772  } //end leapfrog over k
773  } //end loop over j
774  } //end loop over i
775 
776  return builder;
777 } // initBBox
778 
779 template<typename ValueT, typename VoxelT>
780 std::shared_ptr<GridBuilder<ValueT, VoxelT>>
781 initOctahedron(ValueT scale, // scale of the octahedron in world units
782  const Vec3<ValueT>& center, //center of octahedron in world units
783  double voxelSize, // size of a voxel in world units
784  double halfWidth, // half-width of narrow band in voxel units
785  const Vec3d& origin) // origin of grid in world units
786 {
787  static_assert(is_floating_point<ValueT>::value, "initOctahedron: expect floating point");
788  static_assert(is_floating_point<typename BuildToValueMap<VoxelT>::Type>::value, "initOctahedron: expect floating point");
789  using Vec3T = Vec3<ValueT>;
790  if (!(scale > 0))
791  throw std::runtime_error("Octahedron: width must be positive!");
792  if (!(voxelSize > 0))
793  throw std::runtime_error("Octahedron: voxelSize must be positive!");
794 
795  auto builder = std::make_shared<GridBuilder<ValueT>>(halfWidth * voxelSize);
796  auto acc = builder->getAccessor();
797 
798  // Define size of octahedron with narrow-band in voxel units
799  const ValueT s = scale / (2 * voxelSize);
800 
801  // Below the Nyquist frequency
802  if ( s < ValueT(1.5) )
803  return builder;
804 
805  // Define center of octahedron in voxel units
806  const Vec3T c(ValueT(center[0] - origin[0]) / voxelSize,
807  ValueT(center[1] - origin[1]) / voxelSize,
808  ValueT(center[2] - origin[2]) / voxelSize);
809 
810  // Define utility functions
811  auto sdf = [&s](ValueT x, ValueT y, ValueT z) {
812  const ValueT d = ValueT(0.5)*(z - y + s);
813  if (d < ValueT(0)) {
814  return Vec3T(x, y - s, z).length();
815  } else if (d > s) {
816  return Vec3T(x, y, z - s).length();
817  }
818  return Vec3T(x, y - s + d, z - d).length();
819  };
820 
821  // Define bounds of the voxel coordinates
822  const BBox<Vec3T> b(c - Vec3T(s + halfWidth), c + Vec3T(s + halfWidth));
823  const CoordBBox bbox(Coord(Floor(b[0][0]), Floor(b[0][1]), Floor(b[0][2])),
824  Coord(Ceil(b[1][0]), Ceil(b[1][1]), Ceil(b[1][2])));
825 
826  // Compute signed distances to octahedron using leapfrogging in k
827  int m = 1;
828  static const ValueT a = Sqrt(ValueT(1)/ValueT(3));
829  for (Coord p = bbox[0]; p[0] <= bbox[1][0]; ++p[0]) {
830  const ValueT px = Abs(ValueT(p[0]) - c[0]);
831  for (p[1] = bbox[0][1]; p[1] <= bbox[1][1]; ++p[1]) {
832  const ValueT py = Abs(ValueT(p[1]) - c[1]);
833  for (p[2] = bbox[0][2]; p[2] <= bbox[1][2]; p[2] += m) {
834  m = 1;
835  const ValueT pz = Abs(ValueT(p[2]) - c[2]);
836  ValueT d = px + py + pz - s;
837  ValueT v;
838  if (ValueT(3)*px < d) {
839  v = sdf(px, py, pz);
840  } else if (ValueT(3)*py < d) {
841  v = sdf(py, pz, px);
842  } else if (ValueT(3)*pz < d) {
843  v = sdf(pz, px, py);
844  } else {
845  v = a * d;
846  }
847  d = Abs(v);
848  if (d < halfWidth) { // inside narrow band
849  acc.setValue(p, voxelSize * v); // distance in world units
850  } else { // outside narrow band
851  m += Floor(d - halfWidth); // leapfrog
852  }
853  } //end leapfrog over k
854  } //end loop over j
855  } //end loop over i
856 
857  return builder;
858 } // initOctahedron
859 
860 } // unnamed namespace
861 
862 //================================================================================================
863 
864 template<typename ValueT, typename VoxelT, typename BufferT>
865 inline GridHandle<BufferT>
866 createLevelSetSphere(ValueT radius, // radius of sphere in world units
867  const Vec3<ValueT>& center, //center of sphere in world units
868  double voxelSize, // size of a voxel in world units
869  double halfWidth, // half-width of narrow band in voxel units
870  const Vec3d& origin, // origin of grid in world units
871  const std::string& name, // name of grid
872  StatsMode sMode, // mode of computation for the statistics
873  ChecksumMode cMode, // mode of computation for the checksum
874  float tolerance,// only used if VoxelT = FpN
875  bool ditherOn,
876  const BufferT& buffer)
877 {
878  auto builder = initSphere<ValueT, VoxelT>(radius, center, voxelSize, halfWidth, origin);
879  builder->sdfToLevelSet();
880  builder->setStats(sMode);
881  builder->setChecksum(cMode);
882  builder->enableDithering(ditherOn);
883  AbsDiff oracle(tolerance);
884  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
885  assert(handle);
886  return handle;
887 } // createLevelSetSphere
888 
889 //================================================================================================
890 
891 template<typename ValueT, typename VoxelT, typename BufferT>
892 inline GridHandle<BufferT>
893 createFogVolumeSphere(ValueT radius, // radius of sphere in world units
894  const Vec3<ValueT>& center, //center of sphere in world units
895  double voxelSize, // size of a voxel in world units
896  double halfWidth, // half-width of narrow band in voxel units
897  const Vec3d& origin, // origin of grid in world units
898  const std::string& name, // name of grid
899  StatsMode sMode, // mode of computation for the statistics
900  ChecksumMode cMode, // mode of computation for the checksum
901  float tolerance,// only used if VoxelT = FpN
902  bool ditherOn,
903  const BufferT& buffer)
904 {
905  auto builder = initSphere<ValueT, VoxelT>(radius, center, voxelSize, halfWidth, origin);
906  builder->sdfToFog();
907  builder->setStats(sMode);
908  builder->setChecksum(cMode);
909  builder->enableDithering(ditherOn);
910  AbsDiff oracle(tolerance);
911  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
912  assert(handle);
913  return handle;
914 } // createFogVolumeSphere
915 
916 //================================================================================================
917 
918 template<typename ValueT, typename BufferT>
919 inline GridHandle<BufferT>
920 createPointSphere(int pointsPerVoxel, // half-width of narrow band in voxel units
921  ValueT radius, // radius of sphere in world units
922  const Vec3<ValueT>& center, //center of sphere in world units
923  double voxelSize, // size of a voxel in world units
924  const Vec3d& origin, // origin of grid in world units
925  const std::string& name, // name of grid
926  ChecksumMode cMode, // mode of computation for the checksum
927  const BufferT& buffer)
928 {
929  auto sphereHandle = createLevelSetSphere(radius, center, voxelSize, 0.5, origin, "dummy",
930  StatsMode::BBox, ChecksumMode::Disable, -1.0f, false, buffer);
931  assert(sphereHandle);
932  auto* sphereGrid = sphereHandle.template grid<ValueT>();
933  assert(sphereGrid);
934  auto pointHandle = createPointScatter(*sphereGrid, pointsPerVoxel, name, cMode, buffer);
935  assert(pointHandle);
936  return pointHandle;
937 } // createPointSphere
938 
939 //================================================================================================
940 
941 template<typename ValueT, typename VoxelT, typename BufferT>
942 inline GridHandle<BufferT>
943 createLevelSetTorus(ValueT majorRadius, // major radius of torus in world units
944  ValueT minorRadius, // minor radius of torus in world units
945  const Vec3<ValueT>& center, //center of torus in world units
946  double voxelSize, // size of a voxel in world units
947  double halfWidth, // half-width of narrow band in voxel units
948  const Vec3d& origin, // origin of grid in world units
949  const std::string& name, // name of grid
950  StatsMode sMode, // mode of computation for the statistics
951  ChecksumMode cMode, // mode of computation for the checksum
952  float tolerance,
953  bool ditherOn,
954  const BufferT& buffer)
955 {
956  auto builder = initTorus<ValueT, VoxelT>(majorRadius, minorRadius, center, voxelSize, halfWidth, origin);
957  builder->sdfToLevelSet();
958  builder->setStats(sMode);
959  builder->setChecksum(cMode);
960  builder->enableDithering(ditherOn);
961  AbsDiff oracle(tolerance);
962  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
963  assert(handle);
964  return handle;
965 } // createLevelSetTorus
966 
967 //================================================================================================
968 
969 template<typename ValueT, typename VoxelT, typename BufferT>
970 inline GridHandle<BufferT>
971 createFogVolumeTorus(ValueT majorRadius, // major radius of torus in world units
972  ValueT minorRadius, // minor radius of torus in world units
973  const Vec3<ValueT>& center, //center of torus in world units
974  double voxelSize, // size of a voxel in world units
975  double halfWidth, // half-width of narrow band in voxel units
976  const Vec3d& origin, // origin of grid in world units
977  const std::string& name, // name of grid
978  StatsMode sMode, // mode of computation for the statistics
979  ChecksumMode cMode, // mode of computation for the checksum
980  float tolerance,
981  bool ditherOn,
982  const BufferT& buffer)
983 {
984  auto builder = initTorus<ValueT, VoxelT>(majorRadius, minorRadius, center, voxelSize, halfWidth, origin);
985  builder->sdfToFog();
986  builder->setStats(sMode);
987  builder->setChecksum(cMode);
988  builder->enableDithering(ditherOn);
989  AbsDiff oracle(tolerance);
990  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
991  assert(handle);
992  return handle;
993 } // createFogVolumeTorus
994 
995 //================================================================================================
996 
997 template<typename ValueT, typename BufferT>
998 inline GridHandle<BufferT>
999 createPointTorus(int pointsPerVoxel, // half-width of narrow band in voxel units
1000  ValueT majorRadius, // major radius of torus in world units
1001  ValueT minorRadius, // minor radius of torus in world units
1002  const Vec3<ValueT>& center, //center of torus in world units
1003  double voxelSize, // size of a voxel in world units
1004  const Vec3d& origin, // origin of grid in world units
1005  const std::string& name, // name of grid
1006  ChecksumMode cMode, // mode of computation for the checksum
1007  const BufferT& buffer)
1008 {
1009  auto torusHandle = createLevelSetTorus(majorRadius, minorRadius, center, voxelSize, 0.5f, origin,
1010  "dummy", StatsMode::BBox, ChecksumMode::Disable, -1.0f, false, buffer);
1011  assert(torusHandle);
1012  auto* torusGrid = torusHandle.template grid<ValueT>();
1013  assert(torusGrid);
1014  auto pointHandle = createPointScatter(*torusGrid, pointsPerVoxel, name, cMode, buffer);
1015  assert(pointHandle);
1016  return pointHandle;
1017 } // createPointTorus
1018 
1019 //================================================================================================
1020 
1021 template<typename ValueT, typename VoxelT, typename BufferT>
1022 inline GridHandle<BufferT>
1023 createLevelSetBox(ValueT width, // width of box in world units
1024  ValueT height, // height of box in world units
1025  ValueT depth, // depth of box in world units
1026  const Vec3<ValueT>& center, //center of box in world units
1027  double voxelSize, // size of a voxel in world units
1028  double halfWidth, // half-width of narrow band in voxel units
1029  const Vec3d& origin, // origin of grid in world units
1030  const std::string& name, // name of grid
1031  StatsMode sMode, // mode of computation for the statistics
1032  ChecksumMode cMode, // mode of computation for the checksum
1033  float tolerance,
1034  bool ditherOn,
1035  const BufferT& buffer)
1036 {
1037  auto builder = initBox<ValueT, VoxelT>(width, height, depth, center, voxelSize, halfWidth, origin);
1038  builder->sdfToLevelSet();
1039  builder->setStats(sMode);
1040  builder->setChecksum(cMode);
1041  builder->enableDithering(ditherOn);
1042  AbsDiff oracle(tolerance);
1043  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
1044  assert(handle);
1045  return handle;
1046 } // createLevelSetBox
1047 
1048 //================================================================================================
1049 
1050 template<typename ValueT, typename VoxelT, typename BufferT>
1051 inline GridHandle<BufferT>
1052 createLevelSetOctahedron(ValueT scale, // scale of the octahedron in world units
1053  const Vec3<ValueT>& center, //center of box in world units
1054  double voxelSize, // size of a voxel in world units
1055  double halfWidth, // half-width of narrow band in voxel units
1056  const Vec3d& origin, // origin of grid in world units
1057  const std::string& name, // name of grid
1058  StatsMode sMode, // mode of computation for the statistics
1059  ChecksumMode cMode, // mode of computation for the checksum
1060  float tolerance,
1061  bool ditherOn,
1062  const BufferT& buffer)
1063 {
1064  auto builder = initOctahedron<ValueT, VoxelT>(scale, center, voxelSize, halfWidth, origin);
1065  builder->sdfToLevelSet();
1066  builder->setStats(sMode);
1067  builder->setChecksum(cMode);
1068  builder->enableDithering(ditherOn);
1069  AbsDiff oracle(tolerance);
1070  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
1071  assert(handle);
1072  return handle;
1073 } // createLevelSetOctahedron
1074 
1075 //================================================================================================
1076 
1077 template<typename ValueT, typename VoxelT, typename BufferT>
1078 inline GridHandle<BufferT>
1079 createLevelSetBBox(ValueT width, // width of bbox in world units
1080  ValueT height, // height of bbox in world units
1081  ValueT depth, // depth of bbox in world units
1082  ValueT thickness, // thickness of the wire in world units
1083  const Vec3<ValueT>& center, //center of bbox in world units
1084  double voxelSize, // size of a voxel in world units
1085  double halfWidth, // half-width of narrow band in voxel units
1086  const Vec3d& origin, // origin of grid in world units
1087  const std::string& name, // name of grid
1088  StatsMode sMode, // mode of computation for the statistics
1089  ChecksumMode cMode, // mode of computation for the checksum
1090  float tolerance,
1091  bool ditherOn,
1092  const BufferT& buffer)
1093 {
1094  auto builder = initBBox<ValueT, VoxelT>(width, height, depth, thickness, center, voxelSize, halfWidth, origin);
1095  builder->sdfToLevelSet();
1096  builder->setStats(sMode);
1097  builder->setChecksum(cMode);
1098  builder->enableDithering(ditherOn);
1099  AbsDiff oracle(tolerance);
1100  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
1101  assert(handle);
1102  return handle;
1103 } // createLevelSetBBox
1104 
1105 //================================================================================================
1106 
1107 template<typename ValueT, typename VoxelT, typename BufferT>
1108 inline GridHandle<BufferT>
1109 createFogVolumeBox(ValueT width, // width of box in world units
1110  ValueT height, // height of box in world units
1111  ValueT depth, // depth of box in world units
1112  const Vec3<ValueT>& center, //center of box in world units
1113  double voxelSize, // size of a voxel in world units
1114  double halfWidth, // half-width of narrow band in voxel units
1115  const Vec3d& origin, // origin of grid in world units
1116  const std::string& name, // name of grid
1117  StatsMode sMode, // mode of computation for the statistics
1118  ChecksumMode cMode, // mode of computation for the checksum
1119  float tolerance,
1120  bool ditherOn,
1121  const BufferT& buffer)
1122 {
1123  auto builder = initBox<ValueT, VoxelT>(width, height, depth, center, voxelSize, halfWidth, origin);
1124  builder->sdfToFog();
1125  builder->setStats(sMode);
1126  builder->setChecksum(cMode);
1127  builder->enableDithering(ditherOn);
1128  AbsDiff oracle(tolerance);
1129  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
1130  assert(handle);
1131  return handle;
1132 } // createFogVolumeBox
1133 
1134 //================================================================================================
1135 
1136 template<typename ValueT, typename VoxelT, typename BufferT>
1137 inline GridHandle<BufferT>
1138 createFogVolumeOctahedron(ValueT scale, // scale of octahedron in world units
1139  const Vec3<ValueT>& center, //center of box in world units
1140  double voxelSize, // size of a voxel in world units
1141  double halfWidth, // half-width of narrow band in voxel units
1142  const Vec3d& origin, // origin of grid in world units
1143  const std::string& name, // name of grid
1144  StatsMode sMode, // mode of computation for the statistics
1145  ChecksumMode cMode, // mode of computation for the checksum
1146  float tolerance,
1147  bool ditherOn,
1148  const BufferT& buffer)
1149 {
1150  auto builder = initOctahedron<ValueT, VoxelT>(scale, center, voxelSize, halfWidth, origin);
1151  builder->sdfToFog();
1152  builder->setStats(sMode);
1153  builder->setChecksum(cMode);
1154  builder->enableDithering(ditherOn);
1155  AbsDiff oracle(tolerance);
1156  auto handle = builder->template getHandle<AbsDiff, BufferT>(voxelSize, origin, name, oracle, buffer);
1157  assert(handle);
1158  return handle;
1159 } // createFogVolumeOctahedron
1160 
1161 //================================================================================================
1162 
1163 template<typename ValueT, typename BufferT>
1164 inline GridHandle<BufferT>
1165 createPointBox(int pointsPerVoxel, // half-width of narrow band in voxel units
1166  ValueT width, // width of box in world units
1167  ValueT height, // height of box in world units
1168  ValueT depth, // depth of box in world units
1169  const Vec3<ValueT>& center, //center of box in world units
1170  double voxelSize, // size of a voxel in world units
1171  const Vec3d& origin, // origin of grid in world units
1172  const std::string& name, // name of grid
1173  ChecksumMode cMode, // mode of computation for the checksum
1174  const BufferT& buffer)
1175 {
1176  auto boxHandle = createLevelSetBox(width, height, depth, center, voxelSize, 0.5, origin, "dummy",
1177  StatsMode::BBox, ChecksumMode::Disable, -1.0f, false, buffer);
1178  assert(boxHandle);
1179  auto* boxGrid = boxHandle.template grid<ValueT>();
1180  assert(boxGrid);
1181  auto pointHandle = createPointScatter(*boxGrid, pointsPerVoxel, name, cMode, buffer);
1182  assert(pointHandle);
1183  return pointHandle;
1184 
1185 } // createPointBox
1186 
1187 //================================================================================================
1188 
1189 template<typename ValueT, typename BufferT>
1190 inline GridHandle<BufferT>
1191 createPointScatter(const NanoGrid<ValueT>& srcGrid, // origin of grid in world units
1192  int pointsPerVoxel, // half-width of narrow band in voxel units
1193  const std::string& name, // name of grid
1194  ChecksumMode cMode, // mode of computation for the checksum
1195  const BufferT& buffer)
1196 {
1197  static_assert(is_floating_point<ValueT>::value, "createPointScatter: expect floating point");
1198  using Vec3T = Vec3<ValueT>;
1199  if (pointsPerVoxel < 1) {
1200  throw std::runtime_error("createPointScatter: Expected at least one point per voxel");
1201  }
1202  if (!srcGrid.isLevelSet()) {
1203  throw std::runtime_error("createPointScatter: Expected a level set grid");
1204  }
1205  if (!srcGrid.hasBBox()) {
1206  throw std::runtime_error("createPointScatter: ActiveVoxelCount is required");
1207  }
1208  const uint64_t pointCount = pointsPerVoxel * srcGrid.activeVoxelCount();
1209  const uint64_t pointSize = AlignUp<NANOVDB_DATA_ALIGNMENT>(pointCount * sizeof(Vec3T));
1210  if (pointCount == 0) {
1211  throw std::runtime_error("createPointScatter: No particles to scatter");
1212  }
1213  std::vector<Vec3T> xyz;
1214  xyz.reserve(pointCount);
1216  auto dstAcc = builder.getAccessor();
1217  std::srand(1234);
1218  const ValueT s = 1 / (1 + ValueT(RAND_MAX)); // scale so s*rand() is in ] 0, 1 [
1219  // return a point with random local voxel coordinates (-0.5 to +0.5)
1220  auto randomPoint = [&s]() {
1221  return s * Vec3T(rand(), rand(), rand()) - Vec3T(0.5);
1222  };
1223  const auto& srcTree = srcGrid.tree();
1224  auto srcMgr = createLeafMgr(srcGrid);
1225  for (uint32_t i = 0, end = srcTree.nodeCount(0); i < end; ++i) {
1226  auto* srcLeaf = srcMgr[i];
1227  auto* dstLeaf = dstAcc.setValue(srcLeaf->origin(), pointsPerVoxel); // allocates leaf node
1228  dstLeaf->mValueMask = srcLeaf->valueMask();
1229  for (uint32_t j = 0, m = 0; j < 512; ++j) {
1230  if (dstLeaf->mValueMask.isOn(j)) {
1231  for (int n = 0; n < pointsPerVoxel; ++n, ++m) {
1232  xyz.push_back(randomPoint());
1233  }
1234  }
1235  dstLeaf->mValues[j] = m;
1236  }
1237  }
1238  assert(pointCount == xyz.size());
1239  builder.setStats(StatsMode::MinMax);
1241  const AbsDiff dummy;
1242  auto handle = builder.template getHandle<AbsDiff, BufferT>(srcGrid.map(), name, dummy, buffer);
1243  assert(handle);
1244  auto* dstGrid = handle.template grid<uint32_t>();
1245  assert(dstGrid);
1246  auto& dstTree = dstGrid->tree();
1247  if (dstTree.nodeCount(0) == 0) {
1248  throw std::runtime_error("Expect leaf nodes!");
1249  }
1250  auto dstMgr = createLeafMgr(*dstGrid);
1251  auto* leafData = dstMgr[0]->data();
1252  leafData[0].mMinimum = 0; // start of prefix sum
1253  for (uint32_t i = 1, n = dstTree.nodeCount(0); i < n; ++i) {
1254  leafData[i].mMinimum = leafData[i - 1].mMinimum + leafData[i - 1].mMaximum;
1255  }
1256  auto& meta = const_cast<GridBlindMetaData&>(dstGrid->blindMetaData(0u));
1257 
1258  meta.mElementCount = xyz.size();
1259  meta.mFlags = 0;
1260  meta.mDataClass = GridBlindDataClass::AttributeArray;
1261  meta.mSemantic = GridBlindDataSemantic::PointPosition;
1262  if (name.length() + 1 > GridBlindMetaData::MaxNameSize) {
1263  std::stringstream ss;
1264  ss << "Point attribute name \"" << name << "\" is more then "
1265  << nanovdb::GridBlindMetaData::MaxNameSize << " characters";
1266  throw std::runtime_error(ss.str());
1267  }
1268  memcpy(meta.mName, name.c_str(), name.size() + 1);
1269  if (std::is_same<ValueT, float>::value) { // resolved at compiletime
1270  meta.mDataType = GridType::Vec3f;
1272  meta.mDataType = GridType::Vec3d;
1273  } else {
1274  throw std::runtime_error("Unsupported value type");
1275  }
1276  if (const auto *p = dstGrid->blindData(0)) {
1277  memcpy(const_cast<void*>(p), xyz.data(), xyz.size() * sizeof(Vec3T));
1278  } else {
1279  throw std::runtime_error("Blind data pointer was NULL");
1280  }
1281  updateChecksum(*dstGrid, cMode);
1282  return handle;
1283 } // createPointScatter
1284 
1285 } // namespace nanovdb
1286 
1287 #endif // NANOVDB_PRIMITIVES_H_HAS_BEEN_INCLUDED
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:88
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition: NanoVDB.h:2307
GridHandle< BufferT > createPointTorus(int pointsPerVoxel=1, ValueT majorRadius=100.0f, ValueT minorRadius=50.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, const Vec3d &origin=Vec3d(0.0f), const std::string &name="torus_points", ChecksumMode cMode=ChecksumMode::Default, const BufferT &buffer=BufferT())
Returns a handle to a PointDataGrid containing points scattered on the surface of a torus...
Definition: Primitives.h:999
GridHandle< BufferT > createPointBox(int pointsPerVoxel=1, ValueT width=40.0f, ValueT height=60.0f, ValueT depth=100.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, const Vec3d &origin=Vec3d(0.0), const std::string &name="box_points", ChecksumMode mode=ChecksumMode::Default, const BufferT &buffer=BufferT())
Returns a handle to a PointDataGrid containing points scattered on the surface of a box...
Definition: Primitives.h:1165
GridHandle< BufferT > createFogVolumeTorus(ValueT majorRadius=100.0f, ValueT minorRadius=50.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, double halfWidth=3.0, const Vec3d &origin=Vec3d(0), const std::string &name="torus_fog", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a sparse fog volume of a torus in the xz-plane such that the exterior is 0 and in...
Definition: Primitives.h:971
bool isLevelSet() const
Definition: NanoVDB.h:2420
ChecksumMode
List of different modes for computing for a checksum.
Definition: GridChecksum.h:33
static const bool value
Definition: NanoVDB.h:357
T Type
Definition: NanoVDB.h:384
GridHandle< BufferT > createPointScatter(const NanoGrid< ValueT > &srcGrid, int pointsPerVoxel=1, const std::string &name="point_scatter", ChecksumMode mode=ChecksumMode::Default, const BufferT &buffer=BufferT())
Given an input NanoVDB voxel grid this methods returns a GridHandle to another NanoVDB PointDataGrid ...
Definition: Primitives.h:1191
const TreeT & tree() const
Return a const reference to the tree.
Definition: NanoVDB.h:2344
static const int MaxNameSize
Definition: NanoVDB.h:2069
Type Max(Type a, Type b)
Definition: NanoVDB.h:672
Type Min(Type a, Type b)
Definition: NanoVDB.h:651
uint64_t activeVoxelCount() const
Return the total number of active voxels in this tree.
Definition: NanoVDB.h:2414
int32_t Ceil(float x)
Definition: NanoVDB.h:720
Allows for the construction of NanoVDB grids without any dependecy.
Definition: GridBuilder.h:91
This class serves to manage a raw memory buffer of a NanoVDB Grid.
Definition: GridHandle.h:70
GridHandle< BufferT > createLevelSetOctahedron(ValueT scale=100.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, double halfWidth=3.0, const Vec3d &origin=Vec3d(0.0), const std::string &name="octadedron_ls", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a narrow-band level set of a octahedron.
Definition: Primitives.h:1052
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
Definition: NanoVDB.h:184
GridHandle< BufferT > createLevelSetSphere(ValueT radius=100, const Vec3< ValueT > &center=Vec3< ValueT >(0), double voxelSize=1.0, double halfWidth=3.0, const Vec3d &origin=Vec3d(0), const std::string &name="sphere_ls", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a narrow-band level set of a sphere.
Definition: Primitives.h:866
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
A simple vector class with three double components, similar to openvdb::math::Vec3.
Definition: NanoVDB.h:856
GridHandle< BufferT > createLevelSetTorus(ValueT majorRadius=100.0f, ValueT minorRadius=50.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, double halfWidth=3.0, const Vec3d &origin=Vec3d(0.0), const std::string &name="torus_ls", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a narrow-band level set of a torus in the xz-plane.
Definition: Primitives.h:943
ValueAccessor getAccessor()
Definition: GridBuilder.h:180
int32_t Floor(float x)
Definition: NanoVDB.h:711
const Map & map() const
Return a const reference to the Map for this grid.
Definition: NanoVDB.h:2356
T Abs(T x)
Definition: NanoVDB.h:747
Definition: NanoVDB.h:2067
Generates a NanoVDB grid from any volume or function.
void setStats(StatsMode mode=StatsMode::Default)
Definition: GridBuilder.h:197
ValueT value
Definition: GridBuilder.h:1287
void updateChecksum(NanoGrid< ValueT > &grid, ChecksumMode mode=ChecksumMode::Default)
Updates the checksum of a grid.
Definition: GridChecksum.h:272
GridHandle< BufferT > createFogVolumeBox(ValueT width=40.0f, ValueT height=60.0f, ValueT depth=100.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, double halfWidth=3.0, const Vec3d &origin=Vec3d(0.0), const std::string &name="box_fog", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a sparse fog volume of a box such that the exterior is 0 and inactive, the interior is active with values varying smoothly from 0 at the surface of the box to 1 at the halfWidth and interior of the box.
Definition: Primitives.h:1109
GridHandle< BufferT > createPointSphere(int pointsPerVoxel=1, ValueT radius=100.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0f, const Vec3d &origin=Vec3d(0.0), const std::string &name="sphere_points", ChecksumMode mode=ChecksumMode::Default, const BufferT &buffer=BufferT())
Returns a handle to a PointDataGrid containing points scattered on the surface of a sphere...
Definition: Primitives.h:920
Compression oracle based on absolute difference.
Definition: GridBuilder.h:38
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
bool hasBBox() const
Definition: NanoVDB.h:2428
uint64_t mElementCount
Definition: NanoVDB.h:2071
GridHandle< BufferT > createLevelSetBox(ValueT width=40.0f, ValueT height=60.0f, ValueT depth=100.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, double halfWidth=3.0, const Vec3d &origin=Vec3d(0.0), const std::string &name="box_ls", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a narrow-band level set of a box.
Definition: Primitives.h:1023
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: NanoVDB.h:795
StatsMode
Grid flags which indicate what extra information is present in the grid buffer.
Definition: GridStats.h:32
GridHandle< BufferT > createLevelSetBBox(ValueT width=40.0f, ValueT height=60.0f, ValueT depth=100.0f, ValueT thickness=10.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, double halfWidth=3.0, const Vec3d &origin=Vec3d(0.0), const std::string &name="bbox_ls", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a narrow-band level set of a bounding-box (= wireframe of a box) ...
Definition: Primitives.h:1079
void setChecksum(ChecksumMode mode=ChecksumMode::Default)
Definition: GridBuilder.h:199
Vec3< double > Vec3d
Definition: NanoVDB.h:1174
T Pow2(T x)
Definition: NanoVDB.h:730
GridHandle< BufferT > createFogVolumeSphere(ValueT radius=100.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0f, double halfWidth=3.0f, const Vec3d &origin=Vec3d(0.0), const std::string &name="sphere_fog", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a sparse fog volume of a sphere such that the exterior is 0 and inactive...
Definition: Primitives.h:893
GridHandle< BufferT > createFogVolumeOctahedron(ValueT scale=100.0f, const Vec3< ValueT > &center=Vec3< ValueT >(0.0f), double voxelSize=1.0, double halfWidth=3.0, const Vec3d &origin=Vec3d(0.0), const std::string &name="octadedron_fog", StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, float tolerance=-1.0f, bool ditherOn=false, const BufferT &buffer=BufferT())
Returns a handle to a sparse fog volume of an octahedron such that the exterior is 0 and inactive...
Definition: Primitives.h:1138
LeafManager< GridT > createLeafMgr(GridT &grid)
creates a LeafManager from a grid. Move semantics is used.
Definition: NodeManager.h:394
C++11 implementation of std::is_floating_point.
Definition: NanoVDB.h:355