OpenVDB 9.0.0
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
21namespace 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.
41template<typename ValueT = float,
42 typename VoxelT = ValueT,
43 typename BufferT = HostBuffer>
44GridHandle<BufferT>
45createLevelSetSphere(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.
80template<typename ValueT = float,
81 typename VoxelT = ValueT,
82 typename BufferT = HostBuffer>
83GridHandle<BufferT>
84createFogVolumeSphere(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.
111template<typename ValueT = float,
112 typename BufferT = HostBuffer>
113inline GridHandle<BufferT>
114createPointSphere(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.
144template<typename ValueT = float,
145 typename VoxelT = ValueT,
146 typename BufferT = HostBuffer>
147GridHandle<BufferT>
148createLevelSetTorus(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.
185template<typename ValueT = float,
186 typename VoxelT = ValueT,
187 typename BufferT = HostBuffer>
188GridHandle<BufferT>
189createFogVolumeTorus(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.
218template<typename ValueT = float,
219 typename BufferT = HostBuffer>
220inline GridHandle<BufferT>
221createPointTorus(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.
253template<typename ValueT = float,
254 typename VoxelT = ValueT,
255 typename BufferT = HostBuffer>
256GridHandle<BufferT>
257createLevelSetBox(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.
296template<typename ValueT = float,
297 typename VoxelT = ValueT,
298 typename BufferT = HostBuffer>
299GridHandle<BufferT>
300createFogVolumeBox(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.
334template<typename ValueT = float,
335 typename VoxelT = ValueT,
336 typename BufferT = HostBuffer>
337GridHandle<BufferT>
338createLevelSetOctahedron(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.
373template<typename ValueT = float,
374 typename VoxelT = ValueT,
375 typename BufferT = HostBuffer>
376GridHandle<BufferT>
377createFogVolumeOctahedron(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.
412template<typename ValueT = float,
413 typename VoxelT = ValueT,
414 typename BufferT = HostBuffer>
415GridHandle<BufferT>
416createLevelSetBBox(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
447template<typename ValueT = float,
448 typename BufferT = HostBuffer>
449inline GridHandle<BufferT>
450createPointBox(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
471template<typename ValueT = float,
472 typename BufferT = HostBuffer>
473inline GridHandle<BufferT>
474createPointScatter(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
482namespace {
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.
492template<typename ValueT, typename VoxelT>
493std::shared_ptr<GridBuilder<ValueT, VoxelT>>
494initSphere(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
553template<typename ValueT, typename VoxelT>
554std::shared_ptr<GridBuilder<ValueT, VoxelT>>
555initTorus(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
616template<typename ValueT, typename VoxelT>
617std::shared_ptr<GridBuilder<ValueT, VoxelT>>
618initBox(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
691template<typename ValueT, typename VoxelT>
692std::shared_ptr<GridBuilder<ValueT, VoxelT>>
693initBBox(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
779template<typename ValueT, typename VoxelT>
780std::shared_ptr<GridBuilder<ValueT, VoxelT>>
781initOctahedron(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
864template<typename ValueT, typename VoxelT, typename BufferT>
865inline GridHandle<BufferT>
866createLevelSetSphere(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
891template<typename ValueT, typename VoxelT, typename BufferT>
892inline GridHandle<BufferT>
893createFogVolumeSphere(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
918template<typename ValueT, typename BufferT>
919inline GridHandle<BufferT>
920createPointSphere(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
941template<typename ValueT, typename VoxelT, typename BufferT>
942inline GridHandle<BufferT>
943createLevelSetTorus(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
969template<typename ValueT, typename VoxelT, typename BufferT>
970inline GridHandle<BufferT>
971createFogVolumeTorus(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
997template<typename ValueT, typename BufferT>
998inline GridHandle<BufferT>
999createPointTorus(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
1021template<typename ValueT, typename VoxelT, typename BufferT>
1022inline GridHandle<BufferT>
1023createLevelSetBox(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
1050template<typename ValueT, typename VoxelT, typename BufferT>
1051inline GridHandle<BufferT>
1052createLevelSetOctahedron(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
1077template<typename ValueT, typename VoxelT, typename BufferT>
1078inline GridHandle<BufferT>
1079createLevelSetBBox(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
1107template<typename ValueT, typename VoxelT, typename BufferT>
1108inline GridHandle<BufferT>
1109createFogVolumeBox(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
1136template<typename ValueT, typename VoxelT, typename BufferT>
1137inline GridHandle<BufferT>
1138createFogVolumeOctahedron(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
1163template<typename ValueT, typename BufferT>
1164inline GridHandle<BufferT>
1165createPointBox(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
1189template<typename ValueT, typename BufferT>
1190inline GridHandle<BufferT>
1191createPointScatter(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
Generates a NanoVDB grid from any volume or function.
ValueT value
Definition: GridBuilder.h:1287
Compression oracle based on absolute difference.
Definition: GridBuilder.h:39
Allows for the construction of NanoVDB grids without any dependecy.
Definition: GridBuilder.h:92
void setStats(StatsMode mode=StatsMode::Default)
Definition: GridBuilder.h:197
void setChecksum(ChecksumMode mode=ChecksumMode::Default)
Definition: GridBuilder.h:199
ValueAccessor getAccessor()
Definition: GridBuilder.h:180
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition: NanoVDB.h:2308
uint64_t activeVoxelCount() const
Return the total number of active voxels in this tree.
Definition: NanoVDB.h:2414
const TreeT & tree() const
Return a const reference to the tree.
Definition: NanoVDB.h:2344
const Map & map() const
Return a const reference to the Map for this grid.
Definition: NanoVDB.h:2356
bool hasBBox() const
Definition: NanoVDB.h:2428
bool isLevelSet() const
Definition: NanoVDB.h:2420
A simple vector class with three double components, similar to openvdb::math::Vec3.
Definition: NanoVDB.h:1044
Definition: Camera.h:16
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
LeafManager< GridT > createLeafMgr(GridT &grid)
creates a LeafManager from a grid. Move semantics is used.
Definition: NodeManager.h:394
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
int32_t Floor(float x)
Definition: NanoVDB.h:711
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
Type Min(Type a, Type b)
Definition: NanoVDB.h:651
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 > 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
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
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
float Sqrt(float x)
Return the square root of a floating-point value.
Definition: NanoVDB.h:795
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
BBox< Coord > CoordBBox
Definition: NanoVDB.h:1658
StatsMode
Grid flags which indicate what extra information is present in the grid buffer.
Definition: GridStats.h:32
void updateChecksum(NanoGrid< ValueT > &grid, ChecksumMode mode=ChecksumMode::Default)
Updates the checksum of a grid.
Definition: GridChecksum.h:272
Vec3< double > Vec3d
Definition: NanoVDB.h:1174
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
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
ChecksumMode
List of different modes for computing for a checksum.
Definition: GridChecksum.h:33
Type Max(Type a, Type b)
Definition: NanoVDB.h:672
T Abs(T x)
Definition: NanoVDB.h:747
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 > 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
int32_t Ceil(float x)
Definition: NanoVDB.h:720
T Pow2(T x)
Definition: NanoVDB.h:730
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,...
Definition: Primitives.h:1109
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:637
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
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
Definition: NanoVDB.h:2068
uint64_t mElementCount
Definition: NanoVDB.h:2071
static const int MaxNameSize
Definition: NanoVDB.h:2069
C++11 implementation of std::is_floating_point.
Definition: NanoVDB.h:356
static const bool value
Definition: NanoVDB.h:357