32 #ifndef OPENVDB_TOOLS_RAYINTERSECTOR_HAS_BEEN_INCLUDED
33 #define OPENVDB_TOOLS_RAYINTERSECTOR_HAS_BEEN_INCLUDED
44 #include <type_traits>
55 template<
typename Gr
idT,
int Iterations = 0,
typename RealT =
double>
79 template<
typename GridT,
81 int NodeLevel = GridT::TreeType::RootNodeType::ChildNodeType::LEVEL,
91 using TreeT =
typename GridT::TreeType;
93 static_assert(NodeLevel >= -1 && NodeLevel <
int(TreeT::DEPTH)-1,
"NodeLevel out of range");
95 "level set grids must have scalar, floating-point value types");
101 : mTester(grid, isoValue)
103 if (!grid.hasUniformVoxels() ) {
105 "LevelSetRayIntersector only supports uniform voxels!");
109 "LevelSetRayIntersector only supports level sets!"
110 "\nUse Grid::setGridClass(openvdb::GRID_LEVEL_SET)");
121 if (!mTester.setIndexRay(iRay))
return false;
131 if (!mTester.setIndexRay(iRay))
return false;
132 iTime = mTester.getIndexTime();
142 if (!mTester.setIndexRay(iRay))
return false;
144 mTester.getIndexPos(xyz);
156 if (!mTester.setIndexRay(iRay))
return false;
158 mTester.getIndexPos(xyz);
159 iTime = mTester.getIndexTime();
167 if (!mTester.setWorldRay(wRay))
return false;
177 if (!mTester.setWorldRay(wRay))
return false;
178 wTime = mTester.getWorldTime();
188 if (!mTester.setWorldRay(wRay))
return false;
190 mTester.getWorldPos(world);
202 if (!mTester.setWorldRay(wRay))
return false;
204 mTester.getWorldPos(world);
205 wTime = mTester.getWorldTime();
217 if (!mTester.setWorldRay(wRay))
return false;
219 mTester.getWorldPosAndNml(world, normal);
233 if (!mTester.setWorldRay(wRay))
return false;
235 mTester.getWorldPosAndNml(world, normal);
236 wTime = mTester.getWorldTime();
242 mutable SearchImplT mTester;
275 template<
typename GridT,
276 int NodeLevel = GridT::TreeType::RootNodeType::ChildNodeType::LEVEL,
284 using RootType =
typename GridT::TreeType::RootNodeType;
287 static_assert(NodeLevel >= 0 && NodeLevel <
int(
TreeT::DEPTH)-1,
"NodeLevel out of range");
303 if (!grid.hasUniformVoxels() ) {
305 "VolumeRayIntersector only supports uniform voxels!");
307 if ( grid.empty() ) {
308 OPENVDB_THROW(RuntimeError,
"LinearSearchImpl does not supports empty grids");
314 mTree->
root().evalActiveBoundingBox(mBBox,
false);
316 mBBox.
max().offset(1);
333 if (!grid.hasUniformVoxels() ) {
335 "VolumeRayIntersector only supports uniform voxels!");
337 if ( grid.empty() ) {
338 OPENVDB_THROW(RuntimeError,
"LinearSearchImpl does not supports empty grids");
369 const bool hit = mRay.clip(mBBox);
370 if (hit) mTmax = mRay.t1();
387 return this->
setIndexRay(wRay.worldToIndex(*mGrid));
390 inline typename RayT::TimeSpan
march()
392 const typename RayT::TimeSpan
t = mHDDA.march(mRay, mAccessor);
413 const typename RayT::TimeSpan
t = this->
march();
426 template <
typename ListType>
427 inline void hits(ListType& list)
429 mHDDA.hits(mRay, mAccessor, list);
442 return time*mGrid->transform().baseMap()->applyJacobian(mRay.dir()).
length();
446 const GridT&
grid()
const {
return *mGrid; }
459 void print(std::ostream& os = std::cout,
int verboseLevel = 1)
461 if (verboseLevel>0) {
462 os <<
"BBox: " << mBBox << std::endl;
463 if (verboseLevel==2) {
465 }
else if (verboseLevel>2) {
474 const bool mIsMaster;
512 template<
typename Gr
idT,
int Iterations,
typename RealT>
513 class LinearSearchImpl
528 mMinValue(isoValue -
ValueT(2 * grid.voxelSize()[0])),
529 mMaxValue(isoValue +
ValueT(2 * grid.voxelSize()[0]))
531 if ( grid.empty() ) {
532 OPENVDB_THROW(RuntimeError,
"LinearSearchImpl does not supports empty grids");
534 if (mIsoValue<= -grid.background() ||
535 mIsoValue>= grid.background() ){
536 OPENVDB_THROW(ValueError,
"The iso-value must be inside the narrow-band!");
538 grid.tree().root().evalActiveBoundingBox(mBBox,
false);
550 return mRay.
clip(mBBox);
559 return mRay.
clip(mBBox);
579 xyz = mStencil.
grid().indexToWorld(xyz);
588 return mTime*mStencil.
grid().transform().baseMap()->applyJacobian(mRay.
dir()).
length();
595 inline void init(RealT t0)
598 mV[0] =
static_cast<ValueT>(this->interpValue(t0));
601 inline void setRange(RealT t0, RealT t1) { mRay.
setTimes(t0, t1); }
604 inline const RayT& ray()
const {
return mRay; }
607 template <
typename NodeT>
608 inline bool hasNode(
const Coord& ijk)
610 return mStencil.
accessor().template probeConstNode<NodeT>(ijk) !=
nullptr;
618 inline bool operator()(
const Coord& ijk, RealT
time)
622 V>mMinValue && V<mMaxValue) {
624 mV[1] =
static_cast<ValueT>(this->interpValue(time));
626 mTime = this->interpTime();
628 for (
int n=0; Iterations>0 &&
n<Iterations; ++
n) {
629 V =
static_cast<ValueT>(this->interpValue(mTime));
633 mTime = this->interpTime();
644 inline RealT interpTime()
647 return mT[0]+(mT[1]-mT[0])*mV[0]/(mV[0]-mV[1]);
650 inline RealT interpValue(RealT time)
652 const VecT pos = mRay(time);
664 const ValueT mIsoValue, mMinValue, mMaxValue;
672 #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.
#define OPENVDB_ASSERT(X)
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.
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...