32 #ifndef OPENVDB_TOOLS_RAYINTERSECTOR_HAS_BEEN_INCLUDED
33 #define OPENVDB_TOOLS_RAYINTERSECTOR_HAS_BEEN_INCLUDED
43 #include <type_traits>
54 template<
typename Gr
idT,
int Iterations = 0,
typename RealT =
double>
78 template<
typename GridT,
80 int NodeLevel = GridT::TreeType::RootNodeType::ChildNodeType::LEVEL,
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");
94 "level set grids must have scalar, floating-point value types");
100 : mTester(grid, isoValue)
102 if (!grid.hasUniformVoxels() ) {
104 "LevelSetRayIntersector only supports uniform voxels!");
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;
274 template<
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() ) {
304 "VolumeRayIntersector only supports uniform voxels!");
306 if ( grid.empty() ) {
307 OPENVDB_THROW(RuntimeError,
"LinearSearchImpl does not supports empty grids");
313 mTree->
root().evalActiveBoundingBox(mBBox,
false);
315 mBBox.
max().offset(1);
332 if (!grid.hasUniformVoxels() ) {
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;
511 template<
typename Gr
idT,
int Iterations,
typename RealT>
512 class LinearSearchImpl
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);
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)
621 V>mMinValue && V<mMaxValue) {
623 mV[1] =
static_cast<ValueT>(this->interpValue(time));
625 mTime = this->interpTime();
627 for (
int n=0; Iterations>0 &&
n<Iterations; ++
n) {
628 V =
static_cast<ValueT>(this->interpValue(mTime));
632 mTime = this->interpTime();
643 inline RealT interpTime()
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);
663 const ValueT mIsoValue, mMinValue, mMaxValue;
671 #endif // OPENVDB_TOOLS_RAYINTERSECTOR_HAS_BEEN_INCLUDED
void setTimes(RealT t0=math::Delta< RealT >::value(), RealT t1=std::numeric_limits< RealT >::max())
bool clip(const Vec3T ¢er, RealT radius)
Return true if this ray intersects the specified sphere.
bool ZeroCrossing(const Type &a, const Type &b)
Return true if the interval [a, b] includes zero, i.e., if either a or b is zero or if they have diff...
bool normalize(T eps=T(1.0e-7))
this = normalized this
GT_API const UT_StringHolder time
GLsizei const GLfloat * value
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...
static bool test(TesterT &tester)
GLuint GLsizei GLsizei * length
RootNodeType & root()
Return this tree's root node.
#define OPENVDB_USE_VERSION_NAMESPACE
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
math::Vec3< ValueType > gradient(const math::Vec3< ValueType > &xyz) const
Return the gradient in world space of the trilinear interpolation kernel.
const AccessorType & accessor() const
Return a const reference to the ValueAccessor associated with this Stencil.
bool probeValue(const Coord &xyz, ValueType &value) const
Return the active state of the value at a given coordinate as well as its value.
void print(std::ostream &os=std::cout, int verboseLevel=1) const override
Print statistics, memory usage and other information about this tree.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Delta for small floating-point offsets.
const Coord & max() const
Axis-aligned bounding box of signed integer coordinates.
void moveTo(const Coord &ijk)
Initialize the stencil buffer with the values of voxel (i, j, k) and its neighbors.
ValueType interpolation(const math::Vec3< ValueType > &xyz) const
Return the trilinear interpolation at the normalized position.
Helper class that implements Hierarchical Digital Differential Analyzers and is specialized for ray i...
const GridType & grid() const
Return a const reference to the grid from which this stencil was constructed.
const Vec3T & dir() const
Implementation of morphological dilation and erosion.
Defines various finite difference stencils by means of the "curiously recurring template pattern" on ...
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Digital Differential Analyzers specialized for VDB.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Helper class that implements Hierarchical Digital Differential Analyzers for ray intersections agains...
#define OPENVDB_THROW(exception, message)
bool isApproxLarger(const Type &a, const Type &b, const Type &tolerance)
Return true if a is larger than b to within the given tolerance, i.e., if b - a < tolerance...