10 #ifndef NANOVDB_HDDA_H_HAS_BEEN_INCLUDED
11 #define NANOVDB_HDDA_H_HAS_BEEN_INCLUDED
14 #define ENFORCE_FORWARD_STEPPING
28 template<
typename RayT,
typename CoordT = Coord>
47 assert(startTime <= 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)) {
57 }
else if (inv[axis] > 0) {
59 mNext[axis] = mT0 + (mVoxel[axis] + dim - pos[axis]) * inv[axis];
60 mDelta[axis] = inv[axis];
63 mNext[axis] = mT0 + (mVoxel[axis] - pos[axis]) * inv[axis];
64 mDelta[axis] = -inv[axis];
78 const Vec3T &pos = ray(mT0), &inv = ray.invDir();
79 mVoxel = RoundDown<CoordT>(pos) & (~(dim - 1));
80 for (
int axis = 0; axis < 3; ++axis) {
83 mNext[axis] = mT0 + (mVoxel[axis] - pos[axis]) * inv[axis];
85 mNext[axis] += dim * inv[axis];
109 mNext[axis] += mDim * mDelta[axis];
110 mVoxel[axis] += mDim * mStep[axis];
137 #if 1 //def __CUDA_ARCH__
138 return fminf(mT1, fminf(mNext[0], fminf(mNext[1], mNext[2])));
149 #ifdef ENFORCE_FORWARD_STEPPING
152 if (mNext[axis] <= mT0) {
153 mNext[axis] += mT0 - 0.999999f * mNext[axis] + 1.0e-6
f;
157 mNext[ axis] += mDim * mDelta[axis];
158 mVoxel[axis] += mDim * mStep[ axis];
164 CoordT mVoxel, mStep;
175 template<
typename RayT,
typename AccT>
178 if (!ray.clip(acc.root().bbox()) || ray.t1() > 1e20)
180 static const float Delta = 1.0001f;
181 ijk = RoundDown<Coord>(ray.start());
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))
189 while (hdda.step() && acc.isActive(hdda.voxel())) {
190 v = acc.getValue(hdda.voxel());
209 template<
typename RayT,
typename CoordT = Coord,
int Dim = 1>
212 static_assert(Dim >= 1,
"Dim must be >= 1");
230 assert(startTime <= 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)) {
239 }
else if (inv[axis] > 0) {
241 mNext[axis] = (mT0 + (mVoxel[axis] + Dim - pos[axis]) * inv[axis]);
242 mDelta[axis] = inv[axis];
245 mNext[axis] = mT0 + (mVoxel[axis] - pos[axis]) * inv[axis];
246 mDelta[axis] = -inv[axis];
269 #ifdef ENFORCE_FORWARD_STEPPING
270 if (mNext[axis] <= mT0) {
271 mNext[axis] += mT0 - 0.999999f * mNext[axis] + 1.0e-6
f;
275 mNext[axis] += mDelta[axis];
276 mVoxel[axis] += mStep[axis];
303 return Min(mT1,
Min(mNext[0],
Min(mNext[1], mNext[2])));
316 #ifdef ENFORCE_FORWARD_STEPPING
317 if (mNext[axis] <= mT0) {
318 mNext[axis] += mT0 - 0.999999f * mNext[axis] + 1.0e-6
f;
322 mNext[axis] += mDelta[axis];
323 mVoxel[axis] += mStep[axis];
328 CoordT mVoxel, mStep;
334 template<
typename RayT,
typename NodeT>
339 if (!ray.clip(node.bbox())) {
343 const float t0 = ray.t0();
345 static const float Delta = 1.0001f;
355 if (bbox.isInside(ijk) ==
false)
358 v = node.getValue(ijk);
373 template<
typename RayT,
typename AccT>
376 if (!ray.clip(acc.root().bbox()) || ray.t1() > 1e20) {
379 static const float Delta = 1.0001f;
381 ijk = RoundDown<Coord>(ray.start());
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;
384 t = hdda.time() + Delta;
385 ijk = RoundDown<Coord>( ray(t) );
394 template<
typename NodeT,
typename RayT,
typename AccT,
typename CoordT = Coord>
398 using ChildT =
typename NodeT::ChildNodeType;
412 if (!mRay.clip(mAcc.root().bbox()))
417 static const float Eps = 0.000001f;
418 const float t0 = mRay.t0() + Eps;
419 const float t1 = mRay.t1() - Eps;
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()));
427 mT0 = (dim <= ChildT::dim()) ? mHdda.time() : -1;
439 static const float Delta = 0.01f;
445 auto currentNode = mAcc.template getNode<NodeT>();
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;
455 t1 =
Min(mTmax, mHdda.time());
458 if (t0 >= t1 || currentNode ==
nullptr)
465 }
while (hddaIsValid);
489 template<
typename AccT,
typename RayT,
typename CoordT = Coord>
510 #endif // NANOVDB_HDDA_HAS_BEEN_INCLUDED
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
__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...
__hostdev__ RealType maxTime() const
Return the maximum time (parameterized along the Ray).
__hostdev__ bool init(const RayT &indexRay)
Initialize the TreeMarcher with an index-space ray.
__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...
A Digital Differential Analyzer. Unlike HDDA (defined above) this DDA uses a fixed step-size defined ...
__hostdev__ void init(const RayT &ray)
Simular to init above except it uses the bounds of the input ray.
typename LeafNode< AccT::ValueType >::ChildNodeType ChildT
__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...
__hostdev__ bool step()
Increment the voxel index to next intersected voxel or node and returns true if the step in time does...
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
typename RayT::RealType RealType
__hostdev__ PointTreeMarcher(AccT &acc)
__hostdev__ const RayT & ray() const
__hostdev__ RealType time() const
Return the time (parameterized along the Ray) of the first hit of a tree node of size 2^Log2Dim...
__hostdev__ Type Min(Type a, Type b)
HDDA()=default
Default ctor.
Implements a light-weight self-contained VDB data-structure in a single file! In other words...
__hostdev__ HDDA(const RayT &ray, int dim)
ctor from ray and dimension at which the DDA marches
__hostdev__ const CoordT & voxel() const
Return the index coordinates of the next node or voxel intersected by the ray. If Log2Dim = 0 the ret...
__hostdev__ bool step()
Increment the voxel index to next intersected voxel or node and returns true if the step in time does...
typename RayT::RealType RealType
__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^...
typename RayT::Vec3Type Vec3Type
__hostdev__ bool init(RayT ray)
Initiates this instance with a ray in index space.
__hostdev__ bool ZeroCrossingNode(RayT &ray, const NodeT &node, float v0, nanovdb::Coord &ijk, float &v, float &t)
A Digital Differential Analyzer specialized for OpenVDB grids.
__hostdev__ RealType time() const
Return the time (parameterized along the Ray) of the first hit of a tree node of size 2^Log2Dim...
__hostdev__ int MinIndex(const Vec3T &v)
DDA()=default
Default ctor.
__hostdev__ DDA(const RayT &ray)
ctor from ray and dimension at which the DDA marches
__hostdev__ int dim() const
__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^...
__hostdev__ bool update(const RayT &ray, int dim)
Updates the HDDA to march with the specified dimension.
__hostdev__ Type Max(Type a, Type b)
__hostdev__ TreeMarcher(AccT &acc)
Delta for small floating-point offsets.
__hostdev__ RealType maxTime() const
Return the maximum time (parameterized along the Ray).
__hostdev__ void init(const RayT &ray, int dim)
Simular to init above except it uses the bounds of the input ray.
A Tree Marcher for Generic Grids.
__hostdev__ void init(const RayT &ray, RealT startTime, RealT maxTime)
Re-initializes the DDA.
static __hostdev__ Coord Floor(const Vec3T &xyz)
Return the largest integer coordinates that are not greater than xyz (node centered conversion)...
__hostdev__ int nextAxis() const
__hostdev__ void init(const RayT &ray, RealT startTime, RealT maxTime, int dim)
Re-initializes the HDDA.
__hostdev__ const CoordT & voxel() const
Return the index coordinates of the next node or voxel intersected by the ray. If Log2Dim = 0 the ret...
typename RayT::Vec3Type Vec3Type
typename RayT::RealType RealType
A Tree Marcher for Point Grids.