OpenVDB 11.0.0
Loading...
Searching...
No Matches
HDDA.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/// @file HDDA.h
5///
6/// @author Ken Museth
7///
8/// @brief Hierarchical Digital Differential Analyzers specialized for VDB.
9
10#ifndef NANOVDB_HDDA_H_HAS_BEEN_INCLUDED
11#define NANOVDB_HDDA_H_HAS_BEEN_INCLUDED
12
13// Comment out to disable this explicit round-off check
14#define ENFORCE_FORWARD_STEPPING
15
16#include <nanovdb/NanoVDB.h> // only dependency
17
18namespace nanovdb {
19
20/// @brief A Digital Differential Analyzer specialized for OpenVDB grids
21/// @note Conceptually similar to Bresenham's line algorithm applied
22/// to a 3D Ray intersecting OpenVDB nodes or voxels. Log2Dim = 0
23/// corresponds to a voxel and Log2Dim a tree node of size 2^Log2Dim.
24///
25/// @note The Ray template class is expected to have the following
26/// methods: test(time), t0(), t1(), invDir(), and operator()(time).
27/// See the example Ray class above for their definition.
28template<typename RayT, typename CoordT = Coord>
29class HDDA
30{
31public:
32 using RealType = typename RayT::RealType;
33 using RealT = RealType;
34 using Vec3Type = typename RayT::Vec3Type;
35 using Vec3T = Vec3Type;
36 using CoordType = CoordT;
37
38 /// @brief Default ctor
39 HDDA() = default;
40
41 /// @brief ctor from ray and dimension at which the DDA marches
42 __hostdev__ HDDA(const RayT& ray, int dim) { this->init(ray, dim); }
43
44 /// @brief Re-initializes the HDDA
45 __hostdev__ void init(const RayT& ray, RealT startTime, RealT maxTime, int dim)
46 {
47 assert(startTime <= maxTime);
48 mDim = dim;
49 mT0 = startTime;
50 mT1 = maxTime;
51 const Vec3T &pos = ray(mT0), &dir = ray.dir(), &inv = ray.invDir();
52 mVoxel = RoundDown<CoordT>(pos) & (~(dim - 1));
53 for (int axis = 0; axis < 3; ++axis) {
54 if (dir[axis] == RealT(0)) { //handles dir = +/- 0
55 mNext[axis] = Maximum<RealT>::value(); //i.e. disabled!
56 mStep[axis] = 0;
57 } else if (inv[axis] > 0) {
58 mStep[axis] = 1;
59 mNext[axis] = mT0 + (mVoxel[axis] + dim - pos[axis]) * inv[axis];
60 mDelta[axis] = inv[axis];
61 } else {
62 mStep[axis] = -1;
63 mNext[axis] = mT0 + (mVoxel[axis] - pos[axis]) * inv[axis];
64 mDelta[axis] = -inv[axis];
65 }
66 }
67 }
68
69 /// @brief Simular to init above except it uses the bounds of the input ray
70 __hostdev__ void init(const RayT& ray, int dim) { this->init(ray, ray.t0(), ray.t1(), dim); }
71
72 /// @brief Updates the HDDA to march with the specified dimension
73 __hostdev__ bool update(const RayT& ray, int dim)
74 {
75 if (mDim == dim)
76 return false;
77 mDim = dim;
78 const Vec3T &pos = ray(mT0), &inv = ray.invDir();
79 mVoxel = RoundDown<CoordT>(pos) & (~(dim - 1));
80 for (int axis = 0; axis < 3; ++axis) {
81 if (mStep[axis] == 0)
82 continue;
83 mNext[axis] = mT0 + (mVoxel[axis] - pos[axis]) * inv[axis];
84 if (mStep[axis] > 0)
85 mNext[axis] += dim * inv[axis];
86 }
87
88 return true;
89 }
90
91 __hostdev__ int dim() const { return mDim; }
92
93 /// @brief Increment the voxel index to next intersected voxel or node
94 /// and returns true if the step in time does not exceed maxTime.
96 {
97 const int axis = MinIndex(mNext);
98#if 1
99 switch (axis) {
100 case 0:
101 return step<0>();
102 case 1:
103 return step<1>();
104 default:
105 return step<2>();
106 }
107#else
108 mT0 = mNext[axis];
109 mNext[axis] += mDim * mDelta[axis];
110 mVoxel[axis] += mDim * mStep[axis];
111 return mT0 <= mT1;
112#endif
113 }
114
115 /// @brief Return the index coordinates of the next node or voxel
116 /// intersected by the ray. If Log2Dim = 0 the return value is the
117 /// actual signed coordinate of the voxel, else it is the origin
118 /// of the corresponding VDB tree node or tile.
119 /// @note Incurs no computational overhead.
120 __hostdev__ const CoordT& voxel() const { return mVoxel; }
121
122 /// @brief Return the time (parameterized along the Ray) of the
123 /// first hit of a tree node of size 2^Log2Dim.
124 /// @details This value is initialized to startTime or ray.t0()
125 /// depending on the constructor used.
126 /// @note Incurs no computational overhead.
127 __hostdev__ RealType time() const { return mT0; }
128
129 /// @brief Return the maximum time (parameterized along the Ray).
130 __hostdev__ RealType maxTime() const { return mT1; }
131
132 /// @brief Return the time (parameterized along the Ray) of the
133 /// second (i.e. next) hit of a tree node of size 2^Log2Dim.
134 /// @note Incurs a (small) computational overhead.
136 {
137#if 1 //def __CUDA_ARCH__
138 return fminf(mT1, fminf(mNext[0], fminf(mNext[1], mNext[2])));
139#else
140 return std::min(mT1, std::min(mNext[0], std::min(mNext[1], mNext[2])));
141#endif
142 }
143
144private:
145 // helper to implement the general form
146 template<int axis>
147 __hostdev__ bool step()
148 {
149#ifdef ENFORCE_FORWARD_STEPPING
150 //if (mNext[axis] <= mT0) mNext[axis] += mT0 - mNext[axis] + fmaxf(mNext[axis]*1.0e-6f, 1.0e-6f);
151 //if (mNext[axis] <= mT0) mNext[axis] += mT0 - mNext[axis] + (mNext[axis] + 1.0f)*1.0e-6f;
152 if (mNext[axis] <= mT0) {
153 mNext[axis] += mT0 - 0.999999f * mNext[axis] + 1.0e-6f;
154 }
155#endif
156 mT0 = mNext[axis];
157 mNext[ axis] += mDim * mDelta[axis];
158 mVoxel[axis] += mDim * mStep[ axis];
159 return mT0 <= mT1;
160 }
161
162 int32_t mDim;
163 RealT mT0, mT1; // min and max allowed times
164 CoordT mVoxel, mStep; // current voxel location and step to next voxel location
165 Vec3T mDelta, mNext; // delta time and next time
166}; // class HDDA
167
168/////////////////////////////////////////// ZeroCrossing ////////////////////////////////////////////
169
170/// @brief returns true if the ray intersects a zero-crossing at the voxel level of the grid in the accessor
171/// The empty-space ray-marching is performed at all levels of the tree using an
172/// HDDA. If an intersection is detected, then ijk is updated with the index coordinate of the closest
173/// voxel after the intersection point, v contains the grid values at ijk, and t is set to the time of
174/// the intersection along the ray.
175template<typename RayT, typename AccT>
176inline __hostdev__ bool ZeroCrossing(RayT& ray, AccT& acc, Coord& ijk, typename AccT::ValueType& v, float& t)
177{
178 if (!ray.clip(acc.root().bbox()) || ray.t1() > 1e20)
179 return false; // clip ray to bbox
180 static const float Delta = 1.0001f;
181 ijk = RoundDown<Coord>(ray.start()); // first hit of bbox
182 HDDA<RayT, Coord> hdda(ray, acc.getDim(ijk, ray));
183 const auto v0 = acc.getValue(ijk);
184 while (hdda.step()) {
185 ijk = RoundDown<Coord>(ray(hdda.time() + Delta));
186 hdda.update(ray, acc.getDim(ijk, ray));
187 if (hdda.dim() > 1 || !acc.isActive(ijk))
188 continue; // either a tile value or an inactive voxel
189 while (hdda.step() && acc.isActive(hdda.voxel())) { // in the narrow band
190 v = acc.getValue(hdda.voxel());
191 if (v * v0 < 0) { // zero crossing
192 ijk = hdda.voxel();
193 t = hdda.time();
194 return true;
195 }
196 }
197 }
198 return false;
199}
200
201/////////////////////////////////////////// DDA ////////////////////////////////////////////
202
203/// @brief A Digital Differential Analyzer. Unlike HDDA (defined above) this DDA
204/// uses a fixed step-size defined by the template parameter Dim!
205///
206/// @note The Ray template class is expected to have the following
207/// methods: test(time), t0(), t1(), invDir(), and operator()(time).
208/// See the example Ray class above for their definition.
209template<typename RayT, typename CoordT = Coord, int Dim = 1>
210class DDA
211{
212 static_assert(Dim >= 1, "Dim must be >= 1");
213
214public:
215 using RealType = typename RayT::RealType;
217 using Vec3Type = typename RayT::Vec3Type;
219 using CoordType = CoordT;
220
221 /// @brief Default ctor
222 DDA() = default;
223
224 /// @brief ctor from ray and dimension at which the DDA marches
225 __hostdev__ DDA(const RayT& ray) { this->init(ray); }
226
227 /// @brief Re-initializes the DDA
228 __hostdev__ void init(const RayT& ray, RealT startTime, RealT maxTime)
229 {
230 assert(startTime <= maxTime);
231 mT0 = startTime;
232 mT1 = maxTime;
233 const Vec3T &pos = ray(mT0), &dir = ray.dir(), &inv = ray.invDir();
234 mVoxel = RoundDown<CoordT>(pos) & (~(Dim - 1));
235 for (int axis = 0; axis < 3; ++axis) {
236 if (dir[axis] == RealT(0)) { //handles dir = +/- 0
237 mNext[axis] = Maximum<RealT>::value(); //i.e. disabled!
238 mStep[axis] = 0;
239 } else if (inv[axis] > 0) {
240 mStep[axis] = Dim;
241 mNext[axis] = (mT0 + (mVoxel[axis] + Dim - pos[axis]) * inv[axis]);
242 mDelta[axis] = inv[axis];
243 } else {
244 mStep[axis] = -Dim;
245 mNext[axis] = mT0 + (mVoxel[axis] - pos[axis]) * inv[axis];
246 mDelta[axis] = -inv[axis];
247 }
248 }
249 }
250
251 /// @brief Simular to init above except it uses the bounds of the input ray
252 __hostdev__ void init(const RayT& ray) { this->init(ray, ray.t0(), ray.t1()); }
253
254 /// @brief Increment the voxel index to next intersected voxel or node
255 /// and returns true if the step in time does not exceed maxTime.
257 {
258 const int axis = MinIndex(mNext);
259#if 1
260 switch (axis) {
261 case 0:
262 return step<0>();
263 case 1:
264 return step<1>();
265 default:
266 return step<2>();
267 }
268#else
269#ifdef ENFORCE_FORWARD_STEPPING
270 if (mNext[axis] <= mT0) {
271 mNext[axis] += mT0 - 0.999999f * mNext[axis] + 1.0e-6f;
272 }
273#endif
274 mT0 = mNext[axis];
275 mNext[axis] += mDelta[axis];
276 mVoxel[axis] += mStep[axis];
277 return mT0 <= mT1;
278#endif
279 }
280
281 /// @brief Return the index coordinates of the next node or voxel
282 /// intersected by the ray. If Log2Dim = 0 the return value is the
283 /// actual signed coordinate of the voxel, else it is the origin
284 /// of the corresponding VDB tree node or tile.
285 /// @note Incurs no computational overhead.
286 __hostdev__ const CoordT& voxel() const { return mVoxel; }
287
288 /// @brief Return the time (parameterized along the Ray) of the
289 /// first hit of a tree node of size 2^Log2Dim.
290 /// @details This value is initialized to startTime or ray.t0()
291 /// depending on the constructor used.
292 /// @note Incurs no computational overhead.
293 __hostdev__ RealType time() const { return mT0; }
294
295 /// @brief Return the maximum time (parameterized along the Ray).
296 __hostdev__ RealType maxTime() const { return mT1; }
297
298 /// @brief Return the time (parameterized along the Ray) of the
299 /// second (i.e. next) hit of a tree node of size 2^Log2Dim.
300 /// @note Incurs a (small) computational overhead.
302 {
303 return Min(mT1, Min(mNext[0], Min(mNext[1], mNext[2])));
304 }
305
307 {
308 return nanovdb::MinIndex(mNext);
309 }
310
311private:
312 // helper to implement the general form
313 template<int axis>
314 __hostdev__ bool step()
315 {
316#ifdef ENFORCE_FORWARD_STEPPING
317 if (mNext[axis] <= mT0) {
318 mNext[axis] += mT0 - 0.999999f * mNext[axis] + 1.0e-6f;
319 }
320#endif
321 mT0 = mNext[axis];
322 mNext[axis] += mDelta[axis];
323 mVoxel[axis] += mStep[axis];
324 return mT0 <= mT1;
325 }
326
327 RealT mT0, mT1; // min and max allowed times
328 CoordT mVoxel, mStep; // current voxel location and step to next voxel location
329 Vec3T mDelta, mNext; // delta time and next time
330}; // class DDA
331
332/////////////////////////////////////////// ZeroCrossingNode ////////////////////////////////////////////
333
334template<typename RayT, typename NodeT>
335inline __hostdev__ bool ZeroCrossingNode(RayT& ray, const NodeT& node, float v0, nanovdb::Coord& ijk, float& v, float& t)
336{
337 BBox<Coord> bbox(node.origin(), node.origin() + Coord(node.dim() - 1));
338
339 if (!ray.clip(node.bbox())) {
340 return false;
341 }
342
343 const float t0 = ray.t0();
344
345 static const float Delta = 1.0001f;
346 ijk = Coord::Floor(ray(ray.t0() + Delta));
347
348 t = t0;
349 v = 0;
350
352 while (dda.step()) {
353 ijk = dda.voxel();
354
355 if (bbox.isInside(ijk) == false)
356 return false;
357
358 v = node.getValue(ijk);
359 if (v * v0 < 0) {
360 t = dda.time();
361 return true;
362 }
363 }
364 return false;
365}
366
367/////////////////////////////////////////// TreeMarcher ////////////////////////////////////////////
368
369/// @brief returns true if the ray intersects an active value at any level of the grid in the accessor.
370/// The empty-space ray-marching is performed at all levels of the tree using an
371/// HDDA. If an intersection is detected, then ijk is updated with the index coordinate of the first
372/// active voxel or tile, and t is set to the time of its intersection along the ray.
373template<typename RayT, typename AccT>
374inline __hostdev__ bool firstActive(RayT& ray, AccT& acc, Coord &ijk, float& t)
375{
376 if (!ray.clip(acc.root().bbox()) || ray.t1() > 1e20) {// clip ray to bbox
377 return false;// missed or undefined bbox
378 }
379 static const float Delta = 1.0001f;// forward step-size along the ray to avoid getting stuck
380 t = ray.t0();// initiate time
381 ijk = RoundDown<Coord>(ray.start()); // first voxel inside bbox
382 for (HDDA<RayT, Coord> hdda(ray, acc.getDim(ijk, ray)); !acc.isActive(ijk); hdda.update(ray, acc.getDim(ijk, ray))) {
383 if (!hdda.step()) return false;// leap-frog HDDA and exit if ray bound is exceeded
384 t = hdda.time() + Delta;// update time
385 ijk = RoundDown<Coord>( ray(t) );// update ijk
386 }
387 return true;
388}
389
390/////////////////////////////////////////// TreeMarcher ////////////////////////////////////////////
391
392/// @brief A Tree Marcher for Generic Grids
393
394template<typename NodeT, typename RayT, typename AccT, typename CoordT = Coord>
396{
397public:
398 using ChildT = typename NodeT::ChildNodeType;
399 using RealType = typename RayT::RealType;
401 using CoordType = CoordT;
402
403 inline __hostdev__ TreeMarcher(AccT& acc)
404 : mAcc(acc)
405 {
406 }
407
408 /// @brief Initialize the TreeMarcher with an index-space ray.
409 inline __hostdev__ bool init(const RayT& indexRay)
410 {
411 mRay = indexRay;
412 if (!mRay.clip(mAcc.root().bbox()))
413 return false; // clip ray to bbox
414
415 // tweak the intersection span into the bbox.
416 // CAVEAT: this will potentially clip some tiny corner intersections.
417 static const float Eps = 0.000001f;
418 const float t0 = mRay.t0() + Eps;
419 const float t1 = mRay.t1() - Eps;
420 if (t0 > t1)
421 return false;
422
423 const CoordT ijk = RoundDown<Coord>(mRay(t0));
424 const uint32_t dim = mAcc.getDim(ijk, mRay);
425 mHdda.init(mRay, t0, t1, nanovdb::Max(dim, NodeT::dim()));
426
427 mT0 = (dim <= ChildT::dim()) ? mHdda.time() : -1; // potentially begin a span.
428 mTmax = t1;
429 return true;
430 }
431
432 /// @brief step the ray through the tree. If the ray hits a node then
433 /// populate t0 & t1, and the node.
434 /// @return true when a node of type NodeT is intersected, false otherwise.
435 inline __hostdev__ bool step(const NodeT** node, float& t0, float& t1)
436 {
437 // CAVEAT: if Delta is too large then it will clip corners of nodes in a visible way.
438 // but it has to be quite large when very far from the grid (due to fp32 rounding)
439 static const float Delta = 0.01f;
440 bool hddaIsValid;
441
442 do {
443 t0 = mT0;
444
445 auto currentNode = mAcc.template getNode<NodeT>();
446
447 // get next node intersection...
448 hddaIsValid = mHdda.step();
449 const CoordT nextIjk = RoundDown<Coord>(mRay(mHdda.time() + Delta));
450 const auto nextDim = mAcc.getDim(nextIjk, mRay);
451 mHdda.update(mRay, (int)Max(nextDim, NodeT::dim()));
452 mT0 = (nextDim <= ChildT::dim()) ? mHdda.time() : -1; // potentially begin a span.
453
454 if (t0 >= 0) { // we are in a span.
455 t1 = Min(mTmax, mHdda.time());
456
457 // TODO: clean this up!
458 if (t0 >= t1 || currentNode == nullptr)
459 continue;
460
461 *node = currentNode;
462 return true;
463 }
464
465 } while (hddaIsValid);
466
467 return false;
468 }
469
470 inline __hostdev__ const RayT& ray() const { return mRay; }
471
472 inline __hostdev__ RayT& ray() { return mRay; }
473
474private:
475 AccT& mAcc;
476 RayT mRay;
477 HDDA<RayT, Coord> mHdda;
478 float mT0;
479 float mTmax;
480};// TreeMarcher
481
482/////////////////////////////////////////// PointTreeMarcher ////////////////////////////////////////////
483
484/// @brief A Tree Marcher for Point Grids
485///
486/// @note This class will handle correctly offseting the ray by 0.5 to ensure that
487/// the underlying HDDA will intersect with the grid-cells. See details below.
488
489template<typename AccT, typename RayT, typename CoordT = Coord>
490class PointTreeMarcher : public TreeMarcher<LeafNode<typename AccT::ValueType>, RayT, AccT, CoordT>
491{
492 using BaseT = TreeMarcher<LeafNode<typename AccT::ValueType>, RayT, AccT, CoordT>;
493public:
494 __hostdev__ PointTreeMarcher(AccT& acc) : BaseT(acc) {}
495
496 /// @brief Initiates this instance with a ray in index space.
497 ///
498 /// @details An offset by 0.5 is applied to the ray to account for the fact that points in vdb
499 /// grids are bucketed into so-called grid cell, which are centered round grid voxels,
500 /// whereas the DDA is based on so-called grid nodes, which are coincident with grid
501 /// voxels. So, rather than offsettting the points by 0.5 to bring them into a grid
502 /// node representation this method offsets the eye of the ray by 0.5, which effectively
503 /// ensures that the DDA operates on grid cells as oppose to grid nodes. This subtle
504 /// but important offset by 0.5 is explined in more details in our online documentation.
505 __hostdev__ bool init(RayT ray) { return BaseT::init(ray.offsetEye(0.5)); }
506};// PointTreeMarcher
507
508} // namespace nanovdb
509
510#endif // NANOVDB_HDDA_HAS_BEEN_INCLUDED
Implements a light-weight self-contained VDB data-structure in a single file! In other words,...
#define __hostdev__
Definition NanoVDB.h:213
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition NanoVDB.h:1302
static Coord Floor(const Vec3T &xyz)
Return the largest integer coordinates that are not greater than xyz (node centered conversion).
Definition NanoVDB.h:1499
A Digital Differential Analyzer. Unlike HDDA (defined above) this DDA uses a fixed step-size defined ...
Definition HDDA.h:211
__hostdev__ const CoordT & voxel() const
Return the index coordinates of the next node or voxel intersected by the ray. If Log2Dim = 0 the ret...
Definition HDDA.h:286
CoordT CoordType
Definition HDDA.h:219
__hostdev__ RealType maxTime() const
Return the maximum time (parameterized along the Ray).
Definition HDDA.h:296
__hostdev__ RealType time() const
Return the time (parameterized along the Ray) of the first hit of a tree node of size 2^Log2Dim.
Definition HDDA.h:293
__hostdev__ int nextAxis() const
Definition HDDA.h:306
__hostdev__ RealType next() const
Return the time (parameterized along the Ray) of the second (i.e. next) hit of a tree node of size 2^...
Definition HDDA.h:301
__hostdev__ DDA(const RayT &ray)
ctor from ray and dimension at which the DDA marches
Definition HDDA.h:225
__hostdev__ bool step()
Increment the voxel index to next intersected voxel or node and returns true if the step in time does...
Definition HDDA.h:256
DDA()=default
Default ctor.
RealType RealT
Definition HDDA.h:216
Vec3Type Vec3T
Definition HDDA.h:218
__hostdev__ void init(const RayT &ray)
Simular to init above except it uses the bounds of the input ray.
Definition HDDA.h:252
__hostdev__ void init(const RayT &ray, RealT startTime, RealT maxTime)
Re-initializes the DDA.
Definition HDDA.h:228
typename RayT::Vec3Type Vec3Type
Definition HDDA.h:217
typename RayT::RealType RealType
Definition HDDA.h:215
A Digital Differential Analyzer specialized for OpenVDB grids.
Definition HDDA.h:30
__hostdev__ const CoordT & voxel() const
Return the index coordinates of the next node or voxel intersected by the ray. If Log2Dim = 0 the ret...
Definition HDDA.h:120
CoordT CoordType
Definition HDDA.h:36
__hostdev__ RealType maxTime() const
Return the maximum time (parameterized along the Ray).
Definition HDDA.h:130
__hostdev__ void init(const RayT &ray, int dim)
Simular to init above except it uses the bounds of the input ray.
Definition HDDA.h:70
__hostdev__ HDDA(const RayT &ray, int dim)
ctor from ray and dimension at which the DDA marches
Definition HDDA.h:42
__hostdev__ RealType time() const
Return the time (parameterized along the Ray) of the first hit of a tree node of size 2^Log2Dim.
Definition HDDA.h:127
__hostdev__ RealType next() const
Return the time (parameterized along the Ray) of the second (i.e. next) hit of a tree node of size 2^...
Definition HDDA.h:135
__hostdev__ void init(const RayT &ray, RealT startTime, RealT maxTime, int dim)
Re-initializes the HDDA.
Definition HDDA.h:45
__hostdev__ int dim() const
Definition HDDA.h:91
__hostdev__ bool step()
Increment the voxel index to next intersected voxel or node and returns true if the step in time does...
Definition HDDA.h:95
RealType RealT
Definition HDDA.h:33
Vec3Type Vec3T
Definition HDDA.h:35
typename RayT::Vec3Type Vec3Type
Definition HDDA.h:34
HDDA()=default
Default ctor.
typename RayT::RealType RealType
Definition HDDA.h:32
__hostdev__ bool update(const RayT &ray, int dim)
Updates the HDDA to march with the specified dimension.
Definition HDDA.h:73
A Tree Marcher for Point Grids.
Definition HDDA.h:491
__hostdev__ PointTreeMarcher(AccT &acc)
Definition HDDA.h:494
__hostdev__ bool init(RayT ray)
Initiates this instance with a ray in index space.
Definition HDDA.h:505
A Tree Marcher for Generic Grids.
Definition HDDA.h:396
CoordT CoordType
Definition HDDA.h:401
__hostdev__ bool step(const NodeT **node, float &t0, float &t1)
step the ray through the tree. If the ray hits a node then populate t0 & t1, and the node.
Definition HDDA.h:435
__hostdev__ const RayT & ray() const
Definition HDDA.h:470
typename NodeT::ChildNodeType ChildT
Definition HDDA.h:398
__hostdev__ RayT & ray()
Definition HDDA.h:472
RealType RealT
Definition HDDA.h:400
__hostdev__ bool init(const RayT &indexRay)
Initialize the TreeMarcher with an index-space ray.
Definition HDDA.h:409
__hostdev__ TreeMarcher(AccT &acc)
Definition HDDA.h:403
typename RayT::RealType RealType
Definition HDDA.h:399
Convert a base-pointer to an openvdb grid, denoted srcGrid, to a nanovdb grid of the same type,...
Definition NanoVDB.h:247
int MinIndex(const Vec3T &v)
Definition NanoVDB.h:1251
Type Min(Type a, Type b)
Definition NanoVDB.h:1089
__hostdev__ bool ZeroCrossing(RayT &ray, AccT &acc, Coord &ijk, typename AccT::ValueType &v, float &t)
returns true if the ray intersects a zero-crossing at the voxel level of the grid in the accessor The...
Definition HDDA.h:176
__hostdev__ bool firstActive(RayT &ray, AccT &acc, Coord &ijk, float &t)
returns true if the ray intersects an active value at any level of the grid in the accessor....
Definition HDDA.h:374
Type Max(Type a, Type b)
Definition NanoVDB.h:1110
__hostdev__ bool ZeroCrossingNode(RayT &ray, const NodeT &node, float v0, nanovdb::Coord &ijk, float &v, float &t)
Definition HDDA.h:335
Definition NanoVDB.h:2295
Delta for small floating-point offsets.
Definition NanoVDB.h:1035
static T value()
Definition NanoVDB.h:1077