OpenVDB 12.0.0
 
Loading...
Searching...
No Matches
Interpolation.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/// @file Interpolation.h
5///
6/// Sampler classes such as PointSampler and BoxSampler that are intended for use
7/// with tools::GridTransformer should operate in voxel space and must adhere to
8/// the interface described in the example below:
9/// @code
10/// struct MySampler
11/// {
12/// // Return a short name that can be used to identify this sampler
13/// // in error messages and elsewhere.
14/// const char* name() { return "mysampler"; }
15///
16/// // Return the radius of the sampling kernel in voxels, not including
17/// // the center voxel. This is the number of voxels of padding that
18/// // are added to all sides of a volume as a result of resampling.
19/// int radius() { return 2; }
20///
21/// // Return true if scaling by a factor smaller than 0.5 (along any axis)
22/// // should be handled via a mipmapping-like scheme of successive halvings
23/// // of a grid's resolution, until the remaining scale factor is
24/// // greater than or equal to 1/2. Set this to false only when high-quality
25/// // scaling is not required.
26/// bool mipmap() { return true; }
27///
28/// // Specify if sampling at a location that is collocated with a grid point
29/// // is guaranteed to return the exact value at that grid point.
30/// // For most sampling kernels, this should be false.
31/// bool consistent() { return false; }
32///
33/// // Sample the tree at the given coordinates and return the result in val.
34/// // Return true if the sampled value is active.
35/// template<class TreeT>
36/// bool sample(const TreeT& tree, const Vec3R& coord, typename TreeT::ValueType& val);
37/// };
38/// @endcode
39
40#ifndef OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
41#define OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
42
43#include <openvdb/version.h> // for OPENVDB_VERSION_NAME
44#include <openvdb/Platform.h> // for round()
45#include <openvdb/math/Math.h>// for SmoothUnitStep
46#include <openvdb/math/Transform.h> // for Transform
47#include <openvdb/Grid.h>
49#include <openvdb/util/Assert.h>
50#include <cmath>
51#include <type_traits>
52
53namespace openvdb {
55namespace OPENVDB_VERSION_NAME {
56namespace tools {
57
58/// @brief Provises a unified interface for sampling, i.e. interpolation.
59/// @details Order = 0: closest point
60/// Order = 1: tri-linear
61/// Order = 2: tri-quadratic
62/// Staggered: Set to true for MAC grids
63template <size_t Order, bool Staggered = false>
64struct Sampler
65{
66 static_assert(Order < 3, "Samplers of order higher than 2 are not supported");
67 static const char* name();
68 static int radius();
69 static bool mipmap();
70 static bool consistent();
71 static bool staggered();
72 static size_t order();
73
74 /// @brief Sample @a inTree at the floating-point index coordinate @a inCoord
75 /// and store the result in @a result.
76 ///
77 /// @return @c true if the sampled value is active.
78 template<class TreeT>
79 static bool sample(const TreeT& inTree, const Vec3R& inCoord,
80 typename TreeT::ValueType& result);
81
82 /// @brief Sample @a inTree at the floating-point index coordinate @a inCoord.
83 ///
84 /// @return the reconstructed value
85 template<class TreeT>
86 static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
87};
88
89//////////////////////////////////////// Non-Staggered Samplers
90
91// The following samplers operate in voxel space.
92// When the samplers are applied to grids holding vector or other non-scalar data,
93// the data is assumed to be collocated. For example, using the BoxSampler on a grid
94// with ValueType Vec3f assumes that all three elements in a vector can be assigned
95// the same physical location. Consider using the GridSampler below instead.
96
98{
99 static const char* name() { return "point"; }
100 static int radius() { return 0; }
101 static bool mipmap() { return false; }
102 static bool consistent() { return true; }
103 static bool staggered() { return false; }
104 static size_t order() { return 0; }
105
106 /// @brief Sample @a inTree at the nearest neighbor to @a inCoord
107 /// and store the result in @a result.
108 /// @return @c true if the sampled value is active.
109 template<class TreeT>
110 static bool sample(const TreeT& inTree, const Vec3R& inCoord,
111 typename TreeT::ValueType& result);
112
113 /// @brief Sample @a inTree at the nearest neighbor to @a inCoord
114 /// @return the reconstructed value
115 template<class TreeT>
116 static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
117};
118
119
121{
122 static const char* name() { return "box"; }
123 static int radius() { return 1; }
124 static bool mipmap() { return true; }
125 static bool consistent() { return true; }
126 static bool staggered() { return false; }
127 static size_t order() { return 1; }
128
129 /// @brief Trilinearly reconstruct @a inTree at @a inCoord
130 /// and store the result in @a result.
131 /// @return @c true if any one of the sampled values is active.
132 template<class TreeT>
133 static bool sample(const TreeT& inTree, const Vec3R& inCoord,
134 typename TreeT::ValueType& result);
135
136 /// @brief Trilinearly reconstruct @a inTree at @a inCoord.
137 /// @return the reconstructed value
138 template<class TreeT>
139 static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
140
141 /// @brief Import all eight values from @a inTree to support
142 /// tri-linear interpolation.
143 template<class ValueT, class TreeT, size_t N>
144 static inline void getValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk);
145
146 /// @brief Import all eight values from @a inTree to support
147 /// tri-linear interpolation.
148 /// @return @c true if any of the eight values are active
149 template<class ValueT, class TreeT, size_t N>
150 static inline bool probeValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk);
151
152 /// @brief Find the minimum and maximum values of the eight cell
153 /// values in @ data.
154 template<class ValueT, size_t N>
155 static inline void extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT& vMax);
156
157 /// @return the tri-linear interpolation with the unit cell coordinates @a uvw
158 template<class ValueT, size_t N>
159 static inline ValueT trilinearInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw);
160};
161
162
164{
165 static const char* name() { return "quadratic"; }
166 static int radius() { return 1; }
167 static bool mipmap() { return true; }
168 static bool consistent() { return false; }
169 static bool staggered() { return false; }
170 static size_t order() { return 2; }
171
172 /// @brief Triquadratically reconstruct @a inTree at @a inCoord
173 /// and store the result in @a result.
174 /// @return @c true if any one of the sampled values is active.
175 template<class TreeT>
176 static bool sample(const TreeT& inTree, const Vec3R& inCoord,
177 typename TreeT::ValueType& result);
178
179 /// @brief Triquadratically reconstruct @a inTree at to @a inCoord.
180 /// @return the reconstructed value
181 template<class TreeT>
182 static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
183
184 template<class ValueT, size_t N>
185 static inline ValueT triquadraticInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw);
186};
187
188
189//////////////////////////////////////// Staggered Samplers
190
191
192// The following samplers operate in voxel space and are designed for Vec3
193// staggered grid data (e.g., fluid simulations using the Marker-and-Cell approach
194// associate elements of the velocity vector with different physical locations:
195// the faces of a cube).
196
198{
199 static const char* name() { return "point"; }
200 static int radius() { return 0; }
201 static bool mipmap() { return false; }
202 static bool consistent() { return false; }
203 static bool staggered() { return true; }
204 static size_t order() { return 0; }
205
206 /// @brief Sample @a inTree at the nearest neighbor to @a inCoord
207 /// and store the result in @a result.
208 /// @return true if the sampled value is active.
209 template<class TreeT>
210 static bool sample(const TreeT& inTree, const Vec3R& inCoord,
211 typename TreeT::ValueType& result);
212
213 /// @brief Sample @a inTree at the nearest neighbor to @a inCoord
214 /// @return the reconstructed value
215 template<class TreeT>
216 static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
217};
218
219
221{
222 static const char* name() { return "box"; }
223 static int radius() { return 1; }
224 static bool mipmap() { return true; }
225 static bool consistent() { return false; }
226 static bool staggered() { return true; }
227 static size_t order() { return 1; }
228
229 /// @brief Trilinearly reconstruct @a inTree at @a inCoord
230 /// and store the result in @a result.
231 /// @return true if any one of the sampled value is active.
232 template<class TreeT>
233 static bool sample(const TreeT& inTree, const Vec3R& inCoord,
234 typename TreeT::ValueType& result);
235
236 /// @brief Trilinearly reconstruct @a inTree at @a inCoord.
237 /// @return the reconstructed value
238 template<class TreeT>
239 static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
240};
241
242
244{
245 static const char* name() { return "quadratic"; }
246 static int radius() { return 1; }
247 static bool mipmap() { return true; }
248 static bool consistent() { return false; }
249 static bool staggered() { return true; }
250 static size_t order() { return 2; }
251
252 /// @brief Triquadratically reconstruct @a inTree at @a inCoord
253 /// and store the result in @a result.
254 /// @return true if any one of the sampled values is active.
255 template<class TreeT>
256 static bool sample(const TreeT& inTree, const Vec3R& inCoord,
257 typename TreeT::ValueType& result);
258
259 /// @brief Triquadratically reconstruct @a inTree at to @a inCoord.
260 /// @return the reconstructed value
261 template<class TreeT>
262 static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
263};
264
265
266//////////////////////////////////////// GridSampler
267
268
269/// @brief Class that provides the interface for continuous sampling
270/// of values in a tree.
271///
272/// @details Since trees support only discrete voxel sampling, TreeSampler
273/// must be used to sample arbitrary continuous points in (world or
274/// index) space.
275///
276/// @warning This implementation of the GridSampler stores a pointer
277/// to a Tree for value access. While this is thread-safe it is
278/// uncached and hence slow compared to using a
279/// ValueAccessor. Consequently it is normally advisable to use the
280/// template specialization below that employs a
281/// ValueAccessor. However, care must be taken when dealing with
282/// multi-threading (see warning below).
283template<typename GridOrTreeType, typename SamplerType>
285{
286public:
288 using ValueType = typename GridOrTreeType::ValueType;
292
293 /// @param grid a grid to be sampled
294 explicit GridSampler(const GridType& grid)
295 : mTree(&(grid.tree())), mTransform(&(grid.transform())) {}
296
297 /// @param tree a tree to be sampled, or a ValueAccessor for the tree
298 /// @param transform is used when sampling world space locations.
300 : mTree(&tree), mTransform(&transform) {}
301
302 const math::Transform& transform() const { return *mTransform; }
303
304 /// @brief Sample a point in index space in the grid.
305 /// @param x Fractional x-coordinate of point in index-coordinates of grid
306 /// @param y Fractional y-coordinate of point in index-coordinates of grid
307 /// @param z Fractional z-coordinate of point in index-coordinates of grid
308 template<typename RealType>
309 ValueType sampleVoxel(const RealType& x, const RealType& y, const RealType& z) const
310 {
311 return this->isSample(Vec3d(x,y,z));
312 }
313
314 /// @brief Sample value in integer index space
315 /// @param i Integer x-coordinate in index space
316 /// @param j Integer y-coordinate in index space
317 /// @param k Integer x-coordinate in index space
319 typename Coord::ValueType j,
320 typename Coord::ValueType k) const
321 {
322 return this->isSample(Coord(i,j,k));
323 }
324
325 /// @brief Sample value in integer index space
326 /// @param ijk the location in index space
327 ValueType isSample(const Coord& ijk) const { return mTree->getValue(ijk); }
328
329 /// @brief Sample in fractional index space
330 /// @param ispoint the location in index space
331 ValueType isSample(const Vec3d& ispoint) const
332 {
333 ValueType result = zeroVal<ValueType>();
334 SamplerType::sample(*mTree, ispoint, result);
335 return result;
336 }
337
338 /// @brief Sample in world space
339 /// @param wspoint the location in world space
340 ValueType wsSample(const Vec3d& wspoint) const
341 {
342 ValueType result = zeroVal<ValueType>();
343 SamplerType::sample(*mTree, mTransform->worldToIndex(wspoint), result);
344 return result;
345 }
346
347private:
348 const TreeType* mTree;
349 const math::Transform* mTransform;
350}; // class GridSampler
351
352
353/// @brief Specialization of GridSampler for construction from a ValueAccessor type
354///
355/// @note This version should normally be favored over the one above
356/// that takes a Grid or Tree. The reason is this version uses a
357/// ValueAccessor that performs fast (cached) access where the
358/// tree-based flavor performs slower (uncached) access.
359///
360/// @warning Since this version stores a pointer to an (externally
361/// allocated) value accessor it is not threadsafe. Hence each thread
362/// should have its own instance of a GridSampler constructed from a
363/// local ValueAccessor. Alternatively the Grid/Tree-based GridSampler
364/// is threadsafe, but also slower.
365template<typename TreeT, typename SamplerType>
366class GridSampler<tree::ValueAccessor<TreeT>, SamplerType>
367{
368public:
370 using ValueType = typename TreeT::ValueType;
371 using TreeType = TreeT;
374
375 /// @param acc a ValueAccessor to be sampled
376 /// @param transform is used when sampling world space locations.
379 : mAccessor(&acc), mTransform(&transform) {}
380
381 const math::Transform& transform() const { return *mTransform; }
382
383 /// @brief Sample a point in index space in the grid.
384 /// @param x Fractional x-coordinate of point in index-coordinates of grid
385 /// @param y Fractional y-coordinate of point in index-coordinates of grid
386 /// @param z Fractional z-coordinate of point in index-coordinates of grid
387 template<typename RealType>
388 ValueType sampleVoxel(const RealType& x, const RealType& y, const RealType& z) const
389 {
390 return this->isSample(Vec3d(x,y,z));
391 }
392
393 /// @brief Sample value in integer index space
394 /// @param i Integer x-coordinate in index space
395 /// @param j Integer y-coordinate in index space
396 /// @param k Integer x-coordinate in index space
398 typename Coord::ValueType j,
399 typename Coord::ValueType k) const
400 {
401 return this->isSample(Coord(i,j,k));
402 }
403
404 /// @brief Sample value in integer index space
405 /// @param ijk the location in index space
406 ValueType isSample(const Coord& ijk) const { return mAccessor->getValue(ijk); }
407
408 /// @brief Sample in fractional index space
409 /// @param ispoint the location in index space
410 ValueType isSample(const Vec3d& ispoint) const
411 {
412 ValueType result = zeroVal<ValueType>();
413 SamplerType::sample(*mAccessor, ispoint, result);
414 return result;
415 }
416
417 /// @brief Sample in world space
418 /// @param wspoint the location in world space
419 ValueType wsSample(const Vec3d& wspoint) const
420 {
421 ValueType result = zeroVal<ValueType>();
422 SamplerType::sample(*mAccessor, mTransform->worldToIndex(wspoint), result);
423 return result;
424 }
425
426private:
427 const AccessorType* mAccessor;//not thread-safe!
428 const math::Transform* mTransform;
429};//Specialization of GridSampler
430
431
432//////////////////////////////////////// DualGridSampler
433
434
435/// @brief This is a simple convenience class that allows for sampling
436/// from a source grid into the index space of a target grid. At
437/// construction the source and target grids are checked for alignment
438/// which potentially renders interpolation unnecessary. Else
439/// interpolation is performed according to the templated Sampler
440/// type.
441///
442/// @warning For performance reasons the check for alignment of the
443/// two grids is only performed at construction time!
444template<typename GridOrTreeT,
445 typename SamplerT>
447{
448public:
449 using ValueType = typename GridOrTreeT::ValueType;
453
454 /// @brief Grid and transform constructor.
455 /// @param sourceGrid Source grid.
456 /// @param targetXform Transform of the target grid.
457 DualGridSampler(const GridType& sourceGrid,
458 const math::Transform& targetXform)
459 : mSourceTree(&(sourceGrid.tree()))
460 , mSourceXform(&(sourceGrid.transform()))
461 , mTargetXform(&targetXform)
462 , mAligned(targetXform == *mSourceXform)
463 {
464 }
465 /// @brief Tree and transform constructor.
466 /// @param sourceTree Source tree.
467 /// @param sourceXform Transform of the source grid.
468 /// @param targetXform Transform of the target grid.
469 DualGridSampler(const TreeType& sourceTree,
470 const math::Transform& sourceXform,
471 const math::Transform& targetXform)
472 : mSourceTree(&sourceTree)
473 , mSourceXform(&sourceXform)
474 , mTargetXform(&targetXform)
475 , mAligned(targetXform == sourceXform)
476 {
477 }
478 /// @brief Return the value of the source grid at the index
479 /// coordinates, ijk, relative to the target grid (or its tranform).
480 inline ValueType operator()(const Coord& ijk) const
481 {
482 if (mAligned) return mSourceTree->getValue(ijk);
483 const Vec3R world = mTargetXform->indexToWorld(ijk);
484 return SamplerT::sample(*mSourceTree, mSourceXform->worldToIndex(world));
485 }
486 /// @brief Return true if the two grids are aligned.
487 inline bool isAligned() const { return mAligned; }
488private:
489 const TreeType* mSourceTree;
490 const math::Transform* mSourceXform;
491 const math::Transform* mTargetXform;
492 const bool mAligned;
493};// DualGridSampler
494
495/// @brief Specialization of DualGridSampler for construction from a ValueAccessor type.
496template<typename TreeT,
497 typename SamplerT>
498class DualGridSampler<tree::ValueAccessor<TreeT>, SamplerT>
499{
500 public:
501 using ValueType = typename TreeT::ValueType;
502 using TreeType = TreeT;
505
506 /// @brief ValueAccessor and transform constructor.
507 /// @param sourceAccessor ValueAccessor into the source grid.
508 /// @param sourceXform Transform for the source grid.
509 /// @param targetXform Transform for the target grid.
510 DualGridSampler(const AccessorType& sourceAccessor,
511 const math::Transform& sourceXform,
512 const math::Transform& targetXform)
513 : mSourceAcc(&sourceAccessor)
514 , mSourceXform(&sourceXform)
515 , mTargetXform(&targetXform)
516 , mAligned(targetXform == sourceXform)
517 {
518 }
519 /// @brief Return the value of the source grid at the index
520 /// coordinates, ijk, relative to the target grid.
521 inline ValueType operator()(const Coord& ijk) const
522 {
523 if (mAligned) return mSourceAcc->getValue(ijk);
524 const Vec3R world = mTargetXform->indexToWorld(ijk);
525 return SamplerT::sample(*mSourceAcc, mSourceXform->worldToIndex(world));
526 }
527 /// @brief Return true if the two grids are aligned.
528 inline bool isAligned() const { return mAligned; }
529private:
530 const AccessorType* mSourceAcc;
531 const math::Transform* mSourceXform;
532 const math::Transform* mTargetXform;
533 const bool mAligned;
534};//Specialization of DualGridSampler
535
536//////////////////////////////////////// AlphaMask
537
538
539// Class to derive the normalized alpha mask
540template <typename GridT,
541 typename MaskT,
542 typename SamplerT = tools::BoxSampler,
543 typename FloatT = float>
545{
546public:
547 static_assert(std::is_floating_point<FloatT>::value,
548 "AlphaMask requires a floating-point value type");
549 using GridType = GridT;
550 using MaskType = MaskT;
551 using SamlerType = SamplerT;
552 using FloatType = FloatT;
553
554 AlphaMask(const GridT& grid, const MaskT& mask, FloatT min, FloatT max, bool invert)
555 : mAcc(mask.tree())
556 , mSampler(mAcc, mask.transform() , grid.transform())
557 , mMin(min)
558 , mInvNorm(1/(max-min))
559 , mInvert(invert)
560 {
561 OPENVDB_ASSERT(min < max);
562 }
563
564 inline bool operator()(const Coord& xyz, FloatT& a, FloatT& b) const
565 {
566 a = math::SmoothUnitStep( (mSampler(xyz) - mMin) * mInvNorm );//smooth mapping to 0->1
567 b = 1 - a;
568 if (mInvert) std::swap(a,b);
569 return a>0;
570 }
571
572protected:
573 using AccT = typename MaskType::ConstAccessor;
576 const FloatT mMin, mInvNorm;
577 const bool mInvert;
578};// AlphaMask
579
580////////////////////////////////////////
581
582namespace local_util {
583
584inline Vec3i
586{
587 return Vec3i(int(std::floor(v(0))), int(std::floor(v(1))), int(std::floor(v(2))));
588}
589
590
591inline Vec3i
593{
594 return Vec3i(int(std::ceil(v(0))), int(std::ceil(v(1))), int(std::ceil(v(2))));
595}
596
597
598inline Vec3i
600{
601 return Vec3i(int(::round(v(0))), int(::round(v(1))), int(::round(v(2))));
602}
603
604} // namespace local_util
605
606
607//////////////////////////////////////// PointSampler
608
609
610template<class TreeT>
611inline bool
612PointSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
613 typename TreeT::ValueType& result)
614{
615 return inTree.probeValue(Coord(local_util::roundVec3(inCoord)), result);
616}
617
618template<class TreeT>
619inline typename TreeT::ValueType
620PointSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
621{
622 return inTree.getValue(Coord(local_util::roundVec3(inCoord)));
623}
624
625
626//////////////////////////////////////// BoxSampler
627
628template<class ValueT, class TreeT, size_t N>
629inline void
630BoxSampler::getValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk)
631{
632 data[0][0][0] = inTree.getValue(ijk); // i, j, k
633
634 ijk[2] += 1;
635 data[0][0][1] = inTree.getValue(ijk); // i, j, k + 1
636
637 ijk[1] += 1;
638 data[0][1][1] = inTree.getValue(ijk); // i, j+1, k + 1
639
640 ijk[2] -= 1;
641 data[0][1][0] = inTree.getValue(ijk); // i, j+1, k
642
643 ijk[0] += 1;
644 ijk[1] -= 1;
645 data[1][0][0] = inTree.getValue(ijk); // i+1, j, k
646
647 ijk[2] += 1;
648 data[1][0][1] = inTree.getValue(ijk); // i+1, j, k + 1
649
650 ijk[1] += 1;
651 data[1][1][1] = inTree.getValue(ijk); // i+1, j+1, k + 1
652
653 ijk[2] -= 1;
654 data[1][1][0] = inTree.getValue(ijk); // i+1, j+1, k
655}
656
657template<class ValueT, class TreeT, size_t N>
658inline bool
659BoxSampler::probeValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk)
660{
661 bool hasActiveValues = false;
662 hasActiveValues |= inTree.probeValue(ijk, data[0][0][0]); // i, j, k
663
664 ijk[2] += 1;
665 hasActiveValues |= inTree.probeValue(ijk, data[0][0][1]); // i, j, k + 1
666
667 ijk[1] += 1;
668 hasActiveValues |= inTree.probeValue(ijk, data[0][1][1]); // i, j+1, k + 1
669
670 ijk[2] -= 1;
671 hasActiveValues |= inTree.probeValue(ijk, data[0][1][0]); // i, j+1, k
672
673 ijk[0] += 1;
674 ijk[1] -= 1;
675 hasActiveValues |= inTree.probeValue(ijk, data[1][0][0]); // i+1, j, k
676
677 ijk[2] += 1;
678 hasActiveValues |= inTree.probeValue(ijk, data[1][0][1]); // i+1, j, k + 1
679
680 ijk[1] += 1;
681 hasActiveValues |= inTree.probeValue(ijk, data[1][1][1]); // i+1, j+1, k + 1
682
683 ijk[2] -= 1;
684 hasActiveValues |= inTree.probeValue(ijk, data[1][1][0]); // i+1, j+1, k
685
686 return hasActiveValues;
687}
688
689template<class ValueT, size_t N>
690inline void
691BoxSampler::extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT &vMax)
692{
693 vMin = vMax = data[0][0][0];
694 vMin = math::Min(vMin, data[0][0][1]);
695 vMax = math::Max(vMax, data[0][0][1]);
696 vMin = math::Min(vMin, data[0][1][0]);
697 vMax = math::Max(vMax, data[0][1][0]);
698 vMin = math::Min(vMin, data[0][1][1]);
699 vMax = math::Max(vMax, data[0][1][1]);
700 vMin = math::Min(vMin, data[1][0][0]);
701 vMax = math::Max(vMax, data[1][0][0]);
702 vMin = math::Min(vMin, data[1][0][1]);
703 vMax = math::Max(vMax, data[1][0][1]);
704 vMin = math::Min(vMin, data[1][1][0]);
705 vMax = math::Max(vMax, data[1][1][0]);
706 vMin = math::Min(vMin, data[1][1][1]);
707 vMax = math::Max(vMax, data[1][1][1]);
708}
709
710
711template<class ValueT, size_t N>
712inline ValueT
713BoxSampler::trilinearInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw)
714{
715 auto _interpolate = [](const ValueT& a, const ValueT& b, double weight)
716 {
718 const auto temp = (b - a) * weight;
720 return static_cast<ValueT>(a + ValueT(temp));
721 };
722
723 // Trilinear interpolation:
724 // The eight surrounding latice values are used to construct the result. \n
725 // result(x,y,z) =
726 // v000 (1-x)(1-y)(1-z) + v001 (1-x)(1-y)z + v010 (1-x)y(1-z) + v011 (1-x)yz
727 // + v100 x(1-y)(1-z) + v101 x(1-y)z + v110 xy(1-z) + v111 xyz
728
729 return _interpolate(
730 _interpolate(
731 _interpolate(data[0][0][0], data[0][0][1], uvw[2]),
732 _interpolate(data[0][1][0], data[0][1][1], uvw[2]),
733 uvw[1]),
734 _interpolate(
735 _interpolate(data[1][0][0], data[1][0][1], uvw[2]),
736 _interpolate(data[1][1][0], data[1][1][1], uvw[2]),
737 uvw[1]),
738 uvw[0]);
739}
740
741
742template<class TreeT>
743inline bool
744BoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
745 typename TreeT::ValueType& result)
746{
747 using ValueT = typename TreeT::ValueType;
748
749 const Vec3i inIdx = local_util::floorVec3(inCoord);
750 const Vec3R uvw = inCoord - inIdx;
751
752 // Retrieve the values of the eight voxels surrounding the
753 // fractional source coordinates.
754 ValueT data[2][2][2];
755
756 const bool hasActiveValues = BoxSampler::probeValues(data, inTree, Coord(inIdx));
757
758 result = BoxSampler::trilinearInterpolation(data, uvw);
759
760 return hasActiveValues;
761}
762
763
764template<class TreeT>
765inline typename TreeT::ValueType
766BoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
767{
768 using ValueT = typename TreeT::ValueType;
769
770 const Vec3i inIdx = local_util::floorVec3(inCoord);
771 const Vec3R uvw = inCoord - inIdx;
772
773 // Retrieve the values of the eight voxels surrounding the
774 // fractional source coordinates.
775 ValueT data[2][2][2];
776
777 BoxSampler::getValues(data, inTree, Coord(inIdx));
778
779 return BoxSampler::trilinearInterpolation(data, uvw);
780}
781
782
783//////////////////////////////////////// QuadraticSampler
784
785template<class ValueT, size_t N>
786inline ValueT
787QuadraticSampler::triquadraticInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw)
788{
789 auto _interpolate = [](const ValueT* value, double weight)
790 {
792 const ValueT
793 a = static_cast<ValueT>(0.5 * (value[0] + value[2]) - value[1]),
794 b = static_cast<ValueT>(0.5 * (value[2] - value[0])),
795 c = static_cast<ValueT>(value[1]);
796 const auto temp = weight * (weight * a + b) + c;
798 return static_cast<ValueT>(temp);
799 };
800
801 /// @todo For vector types, interpolate over each component independently.
802 ValueT vx[3];
803 for (int dx = 0; dx < 3; ++dx) {
804 ValueT vy[3];
805 for (int dy = 0; dy < 3; ++dy) {
806 // Fit a parabola to three contiguous samples in z
807 // (at z=-1, z=0 and z=1), then evaluate the parabola at z',
808 // where z' is the fractional part of inCoord.z, i.e.,
809 // inCoord.z - inIdx.z. The coefficients come from solving
810 //
811 // | (-1)^2 -1 1 || a | | v0 |
812 // | 0 0 1 || b | = | v1 |
813 // | 1^2 1 1 || c | | v2 |
814 //
815 // for a, b and c.
816 const ValueT* vz = &data[dx][dy][0];
817 vy[dy] = _interpolate(vz, uvw.z());
818 }//loop over y
819 // Fit a parabola to three interpolated samples in y, then
820 // evaluate the parabola at y', where y' is the fractional
821 // part of inCoord.y.
822 vx[dx] = _interpolate(vy, uvw.y());
823 }//loop over x
824 // Fit a parabola to three interpolated samples in x, then
825 // evaluate the parabola at the fractional part of inCoord.x.
826 return _interpolate(vx, uvw.x());
827}
828
829template<class TreeT>
830inline bool
831QuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
832 typename TreeT::ValueType& result)
833{
834 using ValueT = typename TreeT::ValueType;
835
836 const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx - Vec3i(1, 1, 1);
837 const Vec3R uvw = inCoord - inIdx;
838
839 // Retrieve the values of the 27 voxels surrounding the
840 // fractional source coordinates.
841 bool active = false;
842 ValueT data[3][3][3];
843 for (int dx = 0, ix = inLoIdx.x(); dx < 3; ++dx, ++ix) {
844 for (int dy = 0, iy = inLoIdx.y(); dy < 3; ++dy, ++iy) {
845 for (int dz = 0, iz = inLoIdx.z(); dz < 3; ++dz, ++iz) {
846 if (inTree.probeValue(Coord(ix, iy, iz), data[dx][dy][dz])) active = true;
847 }
848 }
849 }
850
852
853 return active;
854}
855
856template<class TreeT>
857inline typename TreeT::ValueType
858QuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
859{
860 using ValueT = typename TreeT::ValueType;
861
862 const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx - Vec3i(1, 1, 1);
863 const Vec3R uvw = inCoord - inIdx;
864
865 // Retrieve the values of the 27 voxels surrounding the
866 // fractional source coordinates.
867 ValueT data[3][3][3];
868 for (int dx = 0, ix = inLoIdx.x(); dx < 3; ++dx, ++ix) {
869 for (int dy = 0, iy = inLoIdx.y(); dy < 3; ++dy, ++iy) {
870 for (int dz = 0, iz = inLoIdx.z(); dz < 3; ++dz, ++iz) {
871 data[dx][dy][dz] = inTree.getValue(Coord(ix, iy, iz));
872 }
873 }
874 }
875
877}
878
879
880//////////////////////////////////////// StaggeredPointSampler
881
882
883template<class TreeT>
884inline bool
885StaggeredPointSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
886 typename TreeT::ValueType& result)
887{
888 using ValueType = typename TreeT::ValueType;
889
890 ValueType tempX, tempY, tempZ;
891 bool active = false;
892
893 active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
894 active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
895 active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
896
897 result.x() = tempX.x();
898 result.y() = tempY.y();
899 result.z() = tempZ.z();
900
901 return active;
902}
903
904template<class TreeT>
905inline typename TreeT::ValueType
906StaggeredPointSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
907{
908 using ValueT = typename TreeT::ValueType;
909
910 const ValueT tempX = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
911 const ValueT tempY = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
912 const ValueT tempZ = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
913
914 return ValueT(tempX.x(), tempY.y(), tempZ.z());
915}
916
917
918//////////////////////////////////////// StaggeredBoxSampler
919
920
921template<class TreeT>
922inline bool
923StaggeredBoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
924 typename TreeT::ValueType& result)
925{
926 using ValueType = typename TreeT::ValueType;
927
928 ValueType tempX, tempY, tempZ;
929 tempX = tempY = tempZ = zeroVal<ValueType>();
930 bool active = false;
931
932 active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
933 active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
934 active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
935
936 result.x() = tempX.x();
937 result.y() = tempY.y();
938 result.z() = tempZ.z();
939
940 return active;
941}
942
943template<class TreeT>
944inline typename TreeT::ValueType
945StaggeredBoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
946{
947 using ValueT = typename TreeT::ValueType;
948
949 const ValueT tempX = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
950 const ValueT tempY = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
951 const ValueT tempZ = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
952
953 return ValueT(tempX.x(), tempY.y(), tempZ.z());
954}
955
956
957//////////////////////////////////////// StaggeredQuadraticSampler
958
959
960template<class TreeT>
961inline bool
962StaggeredQuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
963 typename TreeT::ValueType& result)
964{
965 using ValueType = typename TreeT::ValueType;
966
967 ValueType tempX, tempY, tempZ;
968 bool active = false;
969
970 active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
971 active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
972 active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
973
974 result.x() = tempX.x();
975 result.y() = tempY.y();
976 result.z() = tempZ.z();
977
978 return active;
979}
980
981template<class TreeT>
982inline typename TreeT::ValueType
983StaggeredQuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
984{
985 using ValueT = typename TreeT::ValueType;
986
987 const ValueT tempX = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
988 const ValueT tempY = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
989 const ValueT tempZ = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
990
991 return ValueT(tempX.x(), tempY.y(), tempZ.z());
992}
993
994//////////////////////////////////////// Sampler
995
996template <>
997struct Sampler<0, false> : public PointSampler {};
998
999template <>
1000struct Sampler<1, false> : public BoxSampler {};
1001
1002template <>
1003struct Sampler<2, false> : public QuadraticSampler {};
1004
1005template <>
1006struct Sampler<0, true> : public StaggeredPointSampler {};
1007
1008template <>
1009struct Sampler<1, true> : public StaggeredBoxSampler {};
1010
1011template <>
1012struct Sampler<2, true> : public StaggeredQuadraticSampler {};
1013
1014} // namespace tools
1015} // namespace OPENVDB_VERSION_NAME
1016} // namespace openvdb
1017
1018#endif // OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN
Bracket code with OPENVDB_NO_TYPE_CONVERSION_WARNING_BEGIN/_END, to inhibit warnings about type conve...
Definition Platform.h:221
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition Platform.h:222
ValueAccessors are designed to help accelerate accesses into the OpenVDB Tree structures by storing c...
Int32 ValueType
Definition Coord.h:33
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Definition Transform.h:40
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition Vec3.h:86
T & y()
Definition Vec3.h:87
T & z()
Definition Vec3.h:88
const FloatT mMin
Definition Interpolation.h:576
tools::DualGridSampler< AccT, SamplerT > mSampler
Definition Interpolation.h:575
SamplerT SamlerType
Definition Interpolation.h:551
AlphaMask(const GridT &grid, const MaskT &mask, FloatT min, FloatT max, bool invert)
Definition Interpolation.h:554
FloatT FloatType
Definition Interpolation.h:552
const FloatT mInvNorm
Definition Interpolation.h:576
typename MaskType::ConstAccessor AccT
Definition Interpolation.h:573
const bool mInvert
Definition Interpolation.h:577
MaskT MaskType
Definition Interpolation.h:550
AccT mAcc
Definition Interpolation.h:574
bool operator()(const Coord &xyz, FloatT &a, FloatT &b) const
Definition Interpolation.h:564
GridT GridType
Definition Interpolation.h:549
DualGridSampler(const AccessorType &sourceAccessor, const math::Transform &sourceXform, const math::Transform &targetXform)
ValueAccessor and transform constructor.
Definition Interpolation.h:510
typename TreeT::ValueType ValueType
Definition Interpolation.h:501
bool isAligned() const
Return true if the two grids are aligned.
Definition Interpolation.h:528
typename tree::ValueAccessor< TreeT > AccessorType
Definition Interpolation.h:504
ValueType operator()(const Coord &ijk) const
Return the value of the source grid at the index coordinates, ijk, relative to the target grid.
Definition Interpolation.h:521
This is a simple convenience class that allows for sampling from a source grid into the index space o...
Definition Interpolation.h:447
typename GridOrTreeT::ValueType ValueType
Definition Interpolation.h:449
typename TreeAdapter< GridOrTreeT >::GridType GridType
Definition Interpolation.h:450
bool isAligned() const
Return true if the two grids are aligned.
Definition Interpolation.h:487
DualGridSampler(const GridType &sourceGrid, const math::Transform &targetXform)
Grid and transform constructor.
Definition Interpolation.h:457
DualGridSampler(const TreeType &sourceTree, const math::Transform &sourceXform, const math::Transform &targetXform)
Tree and transform constructor.
Definition Interpolation.h:469
typename TreeAdapter< GridOrTreeT >::TreeType TreeType
Definition Interpolation.h:451
typename TreeAdapter< GridType >::AccessorType AccessorType
Definition Interpolation.h:452
ValueType operator()(const Coord &ijk) const
Return the value of the source grid at the index coordinates, ijk, relative to the target grid (or it...
Definition Interpolation.h:480
typename TreeT::ValueType ValueType
Definition Interpolation.h:370
ValueType isSample(const Coord &ijk) const
Sample value in integer index space.
Definition Interpolation.h:406
typename tree::ValueAccessor< TreeT > AccessorType
Definition Interpolation.h:373
ValueType sampleVoxel(const RealType &x, const RealType &y, const RealType &z) const
Sample a point in index space in the grid.
Definition Interpolation.h:388
ValueType wsSample(const Vec3d &wspoint) const
Sample in world space.
Definition Interpolation.h:419
GridSampler(const AccessorType &acc, const math::Transform &transform)
Definition Interpolation.h:377
SharedPtr< GridSampler > Ptr
Definition Interpolation.h:369
const math::Transform & transform() const
Definition Interpolation.h:381
ValueType sampleVoxel(typename Coord::ValueType i, typename Coord::ValueType j, typename Coord::ValueType k) const
Sample value in integer index space.
Definition Interpolation.h:397
ValueType isSample(const Vec3d &ispoint) const
Sample in fractional index space.
Definition Interpolation.h:410
typename TreeAdapter< GridOrTreeType >::TreeType TreeType
Definition Interpolation.h:290
GridSampler(const GridType &grid)
Definition Interpolation.h:294
typename GridOrTreeType::ValueType ValueType
Definition Interpolation.h:288
ValueType isSample(const Coord &ijk) const
Definition Interpolation.h:327
typename TreeAdapter< GridOrTreeType >::GridType GridType
Definition Interpolation.h:289
ValueType sampleVoxel(const RealType &x, const RealType &y, const RealType &z) const
Sample a point in index space in the grid.
Definition Interpolation.h:309
GridSampler(const TreeType &tree, const math::Transform &transform)
Definition Interpolation.h:299
ValueType wsSample(const Vec3d &wspoint) const
Sample in world space.
Definition Interpolation.h:340
typename TreeAdapter< GridOrTreeType >::AccessorType AccessorType
Definition Interpolation.h:291
SharedPtr< GridSampler > Ptr
Definition Interpolation.h:287
const math::Transform & transform() const
Definition Interpolation.h:302
ValueType sampleVoxel(typename Coord::ValueType i, typename Coord::ValueType j, typename Coord::ValueType k) const
Sample value in integer index space.
Definition Interpolation.h:318
ValueType isSample(const Vec3d &ispoint) const
Sample in fractional index space.
Definition Interpolation.h:331
Type SmoothUnitStep(Type x)
Return 0 if x < 0, 1 if x > 1 or else (3 − 2 x) x².
Definition Math.h:287
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition Math.h:595
Vec3< double > Vec3d
Definition Vec3.h:665
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition Math.h:656
Vec3< int32_t > Vec3i
Definition Vec3.h:662
Definition GridTransformer.h:272
Vec3i ceilVec3(const Vec3R &v)
Definition Interpolation.h:592
Vec3i roundVec3(const Vec3R &v)
Definition Interpolation.h:599
Vec3i floorVec3(const Vec3R &v)
Definition Interpolation.h:585
math::Extrema extrema(const IterT &iter, bool threaded=true)
Iterate over a scalar grid and compute extrema (min/max) of the values of the voxels that are visited...
Definition Statistics.h:354
Definition PointDataGrid.h:170
ValueAccessorImpl< TreeType, IsSafe, MutexType, openvdb::make_index_sequence< CacheLevels > > ValueAccessor
Default alias for a ValueAccessor. This is simply a helper alias for the generic definition but takes...
Definition ValueAccessor.h:86
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
math::Vec3< Real > Vec3R
Definition Types.h:72
std::shared_ptr< T > SharedPtr
Definition Types.h:114
Definition Exceptions.h:13
_TreeType TreeType
Definition Grid.h:1061
Grid< NonConstTreeType > GridType
Definition Grid.h:1066
typename tree::ValueAccessor< TreeType > AccessorType
Definition Grid.h:1072
Definition Interpolation.h:121
static bool staggered()
Definition Interpolation.h:126
static void getValues(ValueT(&data)[N][N][N], const TreeT &inTree, Coord ijk)
Import all eight values from inTree to support tri-linear interpolation.
Definition Interpolation.h:630
static bool probeValues(ValueT(&data)[N][N][N], const TreeT &inTree, Coord ijk)
Import all eight values from inTree to support tri-linear interpolation.
Definition Interpolation.h:659
static size_t order()
Definition Interpolation.h:127
static int radius()
Definition Interpolation.h:123
static bool mipmap()
Definition Interpolation.h:124
static const char * name()
Definition Interpolation.h:122
static ValueT trilinearInterpolation(ValueT(&data)[N][N][N], const Vec3R &uvw)
Definition Interpolation.h:713
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Trilinearly reconstruct inTree at inCoord and store the result in result.
Definition Interpolation.h:744
static void extrema(ValueT(&data)[N][N][N], ValueT &vMin, ValueT &vMax)
Find the minimum and maximum values of the eight cell values in @ data.
Definition Interpolation.h:691
static bool consistent()
Definition Interpolation.h:125
Definition Interpolation.h:98
static bool staggered()
Definition Interpolation.h:103
static size_t order()
Definition Interpolation.h:104
static int radius()
Definition Interpolation.h:100
static bool mipmap()
Definition Interpolation.h:101
static const char * name()
Definition Interpolation.h:99
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Sample inTree at the nearest neighbor to inCoord and store the result in result.
Definition Interpolation.h:612
static bool consistent()
Definition Interpolation.h:102
Definition Interpolation.h:164
static bool staggered()
Definition Interpolation.h:169
static ValueT triquadraticInterpolation(ValueT(&data)[N][N][N], const Vec3R &uvw)
Definition Interpolation.h:787
static size_t order()
Definition Interpolation.h:170
static int radius()
Definition Interpolation.h:166
static bool mipmap()
Definition Interpolation.h:167
static const char * name()
Definition Interpolation.h:165
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Triquadratically reconstruct inTree at inCoord and store the result in result.
Definition Interpolation.h:831
static bool consistent()
Definition Interpolation.h:168
Provises a unified interface for sampling, i.e. interpolation.
Definition Interpolation.h:65
static const char * name()
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Sample inTree at the floating-point index coordinate inCoord and store the result in result.
static TreeT::ValueType sample(const TreeT &inTree, const Vec3R &inCoord)
Sample inTree at the floating-point index coordinate inCoord.
Definition Interpolation.h:221
static bool staggered()
Definition Interpolation.h:226
static size_t order()
Definition Interpolation.h:227
static int radius()
Definition Interpolation.h:223
static bool mipmap()
Definition Interpolation.h:224
static const char * name()
Definition Interpolation.h:222
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Trilinearly reconstruct inTree at inCoord and store the result in result.
Definition Interpolation.h:923
static bool consistent()
Definition Interpolation.h:225
Definition Interpolation.h:198
static bool staggered()
Definition Interpolation.h:203
static size_t order()
Definition Interpolation.h:204
static int radius()
Definition Interpolation.h:200
static bool mipmap()
Definition Interpolation.h:201
static const char * name()
Definition Interpolation.h:199
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Sample inTree at the nearest neighbor to inCoord and store the result in result.
Definition Interpolation.h:885
static bool consistent()
Definition Interpolation.h:202
static bool staggered()
Definition Interpolation.h:249
static size_t order()
Definition Interpolation.h:250
static int radius()
Definition Interpolation.h:246
static bool mipmap()
Definition Interpolation.h:247
static const char * name()
Definition Interpolation.h:245
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Triquadratically reconstruct inTree at inCoord and store the result in result.
Definition Interpolation.h:962
static bool consistent()
Definition Interpolation.h:248
#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:218