32#ifndef OPENVDB_TOOLS_RAYINTERSECTOR_HAS_BEEN_INCLUDED
33#define OPENVDB_TOOLS_RAYINTERSECTOR_HAS_BEEN_INCLUDED
54template<
typename Gr
idT,
int Iterations = 0,
typename RealT =
double>
55class LinearSearchImpl;
78template<
typename GridT,
79 typename SearchImplT = LinearSearchImpl<GridT>,
80 int NodeLevel = GridT::TreeType::RootNodeType::ChildNodeType::LEVEL,
81 typename RayT = math::Ray<Real> >
89 using ValueT =
typename GridT::ValueType;
90 using TreeT =
typename GridT::TreeType;
92 static_assert(NodeLevel >= -1 && NodeLevel < int(TreeT::DEPTH)-1,
"NodeLevel out of range");
93 static_assert(std::is_floating_point<ValueT>::value,
94 "level set grids must have scalar, floating-point value types");
100 : mTester(grid, isoValue)
102 if (!grid.hasUniformVoxels() ) {
103 OPENVDB_THROW(RuntimeError,
104 "LevelSetRayIntersector only supports uniform voxels!");
107 OPENVDB_THROW(RuntimeError,
108 "LevelSetRayIntersector only supports level sets!"
109 "\nUse Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
120 if (!mTester.setIndexRay(iRay))
return false;
130 if (!mTester.setIndexRay(iRay))
return false;
131 iTime = mTester.getIndexTime();
141 if (!mTester.setIndexRay(iRay))
return false;
143 mTester.getIndexPos(xyz);
155 if (!mTester.setIndexRay(iRay))
return false;
157 mTester.getIndexPos(xyz);
158 iTime = mTester.getIndexTime();
166 if (!mTester.setWorldRay(wRay))
return false;
176 if (!mTester.setWorldRay(wRay))
return false;
177 wTime = mTester.getWorldTime();
187 if (!mTester.setWorldRay(wRay))
return false;
189 mTester.getWorldPos(world);
201 if (!mTester.setWorldRay(wRay))
return false;
203 mTester.getWorldPos(world);
204 wTime = mTester.getWorldTime();
216 if (!mTester.setWorldRay(wRay))
return false;
218 mTester.getWorldPosAndNml(world, normal);
232 if (!mTester.setWorldRay(wRay))
return false;
234 mTester.getWorldPosAndNml(world, normal);
235 wTime = mTester.getWorldTime();
241 mutable SearchImplT mTester;
274template<
typename GridT,
275 int NodeLevel = GridT::TreeType::RootNodeType::ChildNodeType::LEVEL,
283 using RootType =
typename GridT::TreeType::RootNodeType;
286 static_assert(NodeLevel >= 0 && NodeLevel < int(TreeT::DEPTH)-1,
"NodeLevel out of range");
302 if (!grid.hasUniformVoxels() ) {
303 OPENVDB_THROW(RuntimeError,
304 "VolumeRayIntersector only supports uniform voxels!");
306 if ( grid.empty() ) {
307 OPENVDB_THROW(RuntimeError,
"LinearSearchImpl does not supports empty grids");
311 tools::dilateActiveValues(*mTree, dilationCount, tools::NN_FACE, tools::IGNORE_TILES);
313 mTree->root().evalActiveBoundingBox(mBBox,
false);
315 mBBox.max().offset(1);
332 if (!grid.hasUniformVoxels() ) {
333 OPENVDB_THROW(RuntimeError,
334 "VolumeRayIntersector only supports uniform voxels!");
336 if ( grid.empty() ) {
337 OPENVDB_THROW(RuntimeError,
"LinearSearchImpl does not supports empty grids");
368 const bool hit = mRay.clip(mBBox);
369 if (hit) mTmax = mRay.t1();
386 return this->setIndexRay(wRay.worldToIndex(*mGrid));
389 inline typename RayT::TimeSpan
march()
391 const typename RayT::TimeSpan t = mHDDA.march(mRay, mAccessor);
412 const typename RayT::TimeSpan t = this->march();
425 template <
typename ListType>
426 inline void hits(ListType& list)
428 mHDDA.hits(mRay, mAccessor, list);
441 return time*mGrid->transform().baseMap()->applyJacobian(mRay.dir()).length();
445 const GridT&
grid()
const {
return *mGrid; }
458 void print(std::ostream& os = std::cout,
int verboseLevel = 1)
460 if (verboseLevel>0) {
461 os <<
"BBox: " << mBBox << std::endl;
462 if (verboseLevel==2) {
464 }
else if (verboseLevel>2) {
473 const bool mIsMaster;
511template<
typename Gr
idT,
int Iterations,
typename RealT>
517 using ValueT =
typename GridT::ValueType;
527 mMinValue(isoValue -
ValueT(2 * grid.voxelSize()[0])),
528 mMaxValue(isoValue +
ValueT(2 * grid.voxelSize()[0]))
530 if ( grid.empty() ) {
531 OPENVDB_THROW(RuntimeError,
"LinearSearchImpl does not supports empty grids");
533 if (mIsoValue<= -grid.background() ||
534 mIsoValue>= grid.background() ){
535 OPENVDB_THROW(ValueError,
"The iso-value must be inside the narrow-band!");
537 grid.tree().root().evalActiveBoundingBox(mBBox,
false);
549 return mRay.
clip(mBBox);
558 return mRay.
clip(mBBox);
567 inline void getWorldPos(
VecT& xyz)
const { xyz = mStencil.grid().indexToWorld(mRay(mTime)); }
574 this->getIndexPos(xyz);
575 mStencil.moveTo(xyz);
576 nml = mStencil.gradient(xyz);
578 xyz = mStencil.grid().indexToWorld(xyz);
587 return mTime*mStencil.grid().transform().baseMap()->applyJacobian(mRay.dir()).length();
594 inline void init(RealT t0)
597 mV[0] =
static_cast<ValueT
>(this->interpValue(t0));
600 inline void setRange(RealT t0, RealT t1) { mRay.setTimes(t0, t1); }
603 inline const RayT& ray()
const {
return mRay; }
606 template <
typename NodeT>
607 inline bool hasNode(
const Coord& ijk)
609 return mStencil.accessor().template probeConstNode<NodeT>(ijk) !=
nullptr;
617 inline bool operator()(
const Coord& ijk, RealT time)
620 if (mStencil.accessor().probeValue(ijk, V) &&
621 V>mMinValue && V<mMaxValue) {
623 mV[1] =
static_cast<ValueT
>(this->interpValue(time));
624 if (math::ZeroCrossing(mV[0], mV[1])) {
625 mTime = this->interpTime();
627 for (
int n=0; Iterations>0 && n<Iterations; ++n) {
628 V =
static_cast<ValueT
>(this->interpValue(mTime));
629 const int m = math::ZeroCrossing(mV[0], V) ? 1 : 0;
632 mTime = this->interpTime();
643 inline RealT interpTime()
645 assert( math::isApproxLarger(mT[1], mT[0], RealT(1e-6) ) );
646 return mT[0]+(mT[1]-mT[0])*mV[0]/(mV[0]-mV[1]);
649 inline RealT interpValue(RealT time)
651 const VecT pos = mRay(time);
652 mStencil.moveTo(pos);
653 return mStencil.interpolation(pos) - mIsoValue;
663 const ValueT mIsoValue, mMinValue, mMaxValue;
Digital Differential Analyzers specialized for VDB.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Implementation of morphological dilation and erosion.
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition Types.h:683
Definition Stencils.h:301
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:251
Ray worldToIndex(const GridType &grid) const
Return a new ray in the index space of the specified grid, assuming the existing ray is represented i...
Definition Ray.h:171
bool clip(const Vec3T ¢er, RealT radius)
Return true if this ray intersects the specified sphere.
Definition Ray.h:217
bool normalize(T eps=T(1.0e-7))
this = normalized this
Definition Vec3.h:362
Helper class that implements Hierarchical Digital Differential Analyzers for ray intersections agains...
Definition DDA.h:188
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
Definition ValueAccessor.h:367
@ GRID_LEVEL_SET
Definition Types.h:455
Definition Exceptions.h:13
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
Delta for small floating-point offsets.
Definition Math.h:155
Helper class that implements Hierarchical Digital Differential Analyzers and is specialized for ray i...
Definition DDA.h:145
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:212