OpenVDB  6.2.0
Interpolation.h
Go to the documentation of this file.
1 //
3 // Copyright (c) DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 
66 
67 #ifndef OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
68 #define OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
69 
70 #include <openvdb/version.h> // for OPENVDB_VERSION_NAME
71 #include <openvdb/Platform.h> // for round()
72 #include <openvdb/math/Math.h>// for SmoothUnitStep
73 #include <openvdb/math/Transform.h> // for Transform
74 #include <openvdb/Grid.h>
76 #include <cmath>
77 #include <type_traits>
78 
79 namespace openvdb {
81 namespace OPENVDB_VERSION_NAME {
82 namespace tools {
83 
89 template <size_t Order, bool Staggered = false>
90 struct Sampler
91 {
92  static_assert(Order < 3, "Samplers of order higher than 2 are not supported");
93  static const char* name();
94  static int radius();
95  static bool mipmap();
96  static bool consistent();
97  static bool staggered();
98  static size_t order();
99 
104  template<class TreeT>
105  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
106  typename TreeT::ValueType& result);
107 
111  template<class TreeT>
112  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
113 };
114 
116 
117 // The following samplers operate in voxel space.
118 // When the samplers are applied to grids holding vector or other non-scalar data,
119 // the data is assumed to be collocated. For example, using the BoxSampler on a grid
120 // with ValueType Vec3f assumes that all three elements in a vector can be assigned
121 // the same physical location. Consider using the GridSampler below instead.
122 
124 {
125  static const char* name() { return "point"; }
126  static int radius() { return 0; }
127  static bool mipmap() { return false; }
128  static bool consistent() { return true; }
129  static bool staggered() { return false; }
130  static size_t order() { return 0; }
131 
135  template<class TreeT>
136  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
137  typename TreeT::ValueType& result);
138 
141  template<class TreeT>
142  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
143 };
144 
145 
147 {
148  static const char* name() { return "box"; }
149  static int radius() { return 1; }
150  static bool mipmap() { return true; }
151  static bool consistent() { return true; }
152  static bool staggered() { return false; }
153  static size_t order() { return 1; }
154 
158  template<class TreeT>
159  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
160  typename TreeT::ValueType& result);
161 
164  template<class TreeT>
165  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
166 
169  template<class ValueT, class TreeT, size_t N>
170  static inline void getValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk);
171 
175  template<class ValueT, class TreeT, size_t N>
176  static inline bool probeValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk);
177 
180  template<class ValueT, size_t N>
181  static inline void extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT& vMax);
182 
184  template<class ValueT, size_t N>
185  static inline ValueT trilinearInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw);
186 };
187 
188 
190 {
191  static const char* name() { return "quadratic"; }
192  static int radius() { return 1; }
193  static bool mipmap() { return true; }
194  static bool consistent() { return false; }
195  static bool staggered() { return false; }
196  static size_t order() { return 2; }
197 
201  template<class TreeT>
202  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
203  typename TreeT::ValueType& result);
204 
207  template<class TreeT>
208  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
209 
210  template<class ValueT, size_t N>
211  static inline ValueT triquadraticInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw);
212 };
213 
214 
216 
217 
218 // The following samplers operate in voxel space and are designed for Vec3
219 // staggered grid data (e.g., fluid simulations using the Marker-and-Cell approach
220 // associate elements of the velocity vector with different physical locations:
221 // the faces of a cube).
222 
224 {
225  static const char* name() { return "point"; }
226  static int radius() { return 0; }
227  static bool mipmap() { return false; }
228  static bool consistent() { return false; }
229  static bool staggered() { return true; }
230  static size_t order() { return 0; }
231 
235  template<class TreeT>
236  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
237  typename TreeT::ValueType& result);
238 
241  template<class TreeT>
242  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
243 };
244 
245 
247 {
248  static const char* name() { return "box"; }
249  static int radius() { return 1; }
250  static bool mipmap() { return true; }
251  static bool consistent() { return false; }
252  static bool staggered() { return true; }
253  static size_t order() { return 1; }
254 
258  template<class TreeT>
259  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
260  typename TreeT::ValueType& result);
261 
264  template<class TreeT>
265  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
266 };
267 
268 
270 {
271  static const char* name() { return "quadratic"; }
272  static int radius() { return 1; }
273  static bool mipmap() { return true; }
274  static bool consistent() { return false; }
275  static bool staggered() { return true; }
276  static size_t order() { return 2; }
277 
281  template<class TreeT>
282  static bool sample(const TreeT& inTree, const Vec3R& inCoord,
283  typename TreeT::ValueType& result);
284 
287  template<class TreeT>
288  static typename TreeT::ValueType sample(const TreeT& inTree, const Vec3R& inCoord);
289 };
290 
291 
293 
294 
309 template<typename GridOrTreeType, typename SamplerType>
311 {
312 public:
314  using ValueType = typename GridOrTreeType::ValueType;
318 
320  explicit GridSampler(const GridType& grid)
321  : mTree(&(grid.tree())), mTransform(&(grid.transform())) {}
322 
325  GridSampler(const TreeType& tree, const math::Transform& transform)
326  : mTree(&tree), mTransform(&transform) {}
327 
328  const math::Transform& transform() const { return *mTransform; }
329 
334  template<typename RealType>
335  ValueType sampleVoxel(const RealType& x, const RealType& y, const RealType& z) const
336  {
337  return this->isSample(Vec3d(x,y,z));
338  }
339 
344  ValueType sampleVoxel(typename Coord::ValueType i,
345  typename Coord::ValueType j,
346  typename Coord::ValueType k) const
347  {
348  return this->isSample(Coord(i,j,k));
349  }
350 
353  ValueType isSample(const Coord& ijk) const { return mTree->getValue(ijk); }
354 
357  ValueType isSample(const Vec3d& ispoint) const
358  {
359  ValueType result = zeroVal<ValueType>();
360  SamplerType::sample(*mTree, ispoint, result);
361  return result;
362  }
363 
366  ValueType wsSample(const Vec3d& wspoint) const
367  {
368  ValueType result = zeroVal<ValueType>();
369  SamplerType::sample(*mTree, mTransform->worldToIndex(wspoint), result);
370  return result;
371  }
372 
373 private:
374  const TreeType* mTree;
375  const math::Transform* mTransform;
376 }; // class GridSampler
377 
378 
391 template<typename TreeT, typename SamplerType>
392 class GridSampler<tree::ValueAccessor<TreeT>, SamplerType>
393 {
394 public:
396  using ValueType = typename TreeT::ValueType;
397  using TreeType = TreeT;
400 
404  const math::Transform& transform)
405  : mAccessor(&acc), mTransform(&transform) {}
406 
407  const math::Transform& transform() const { return *mTransform; }
408 
413  template<typename RealType>
414  ValueType sampleVoxel(const RealType& x, const RealType& y, const RealType& z) const
415  {
416  return this->isSample(Vec3d(x,y,z));
417  }
418 
423  ValueType sampleVoxel(typename Coord::ValueType i,
424  typename Coord::ValueType j,
425  typename Coord::ValueType k) const
426  {
427  return this->isSample(Coord(i,j,k));
428  }
429 
432  ValueType isSample(const Coord& ijk) const { return mAccessor->getValue(ijk); }
433 
436  ValueType isSample(const Vec3d& ispoint) const
437  {
438  ValueType result = zeroVal<ValueType>();
439  SamplerType::sample(*mAccessor, ispoint, result);
440  return result;
441  }
442 
445  ValueType wsSample(const Vec3d& wspoint) const
446  {
447  ValueType result = zeroVal<ValueType>();
448  SamplerType::sample(*mAccessor, mTransform->worldToIndex(wspoint), result);
449  return result;
450  }
451 
452 private:
453  const AccessorType* mAccessor;//not thread-safe!
454  const math::Transform* mTransform;
455 };//Specialization of GridSampler
456 
457 
459 
460 
470 template<typename GridOrTreeT,
471  typename SamplerT>
473 {
474 public:
475  using ValueType = typename GridOrTreeT::ValueType;
479 
483  DualGridSampler(const GridType& sourceGrid,
484  const math::Transform& targetXform)
485  : mSourceTree(&(sourceGrid.tree()))
486  , mSourceXform(&(sourceGrid.transform()))
487  , mTargetXform(&targetXform)
488  , mAligned(targetXform == *mSourceXform)
489  {
490  }
495  DualGridSampler(const TreeType& sourceTree,
496  const math::Transform& sourceXform,
497  const math::Transform& targetXform)
498  : mSourceTree(&sourceTree)
499  , mSourceXform(&sourceXform)
500  , mTargetXform(&targetXform)
501  , mAligned(targetXform == sourceXform)
502  {
503  }
506  inline ValueType operator()(const Coord& ijk) const
507  {
508  if (mAligned) return mSourceTree->getValue(ijk);
509  const Vec3R world = mTargetXform->indexToWorld(ijk);
510  return SamplerT::sample(*mSourceTree, mSourceXform->worldToIndex(world));
511  }
513  inline bool isAligned() const { return mAligned; }
514 private:
515  const TreeType* mSourceTree;
516  const math::Transform* mSourceXform;
517  const math::Transform* mTargetXform;
518  const bool mAligned;
519 };// DualGridSampler
520 
522 template<typename TreeT,
523  typename SamplerT>
524 class DualGridSampler<tree::ValueAccessor<TreeT>, SamplerT>
525 {
526  public:
527  using ValueType = typename TreeT::ValueType;
528  using TreeType = TreeT;
531 
536  DualGridSampler(const AccessorType& sourceAccessor,
537  const math::Transform& sourceXform,
538  const math::Transform& targetXform)
539  : mSourceAcc(&sourceAccessor)
540  , mSourceXform(&sourceXform)
541  , mTargetXform(&targetXform)
542  , mAligned(targetXform == sourceXform)
543  {
544  }
547  inline ValueType operator()(const Coord& ijk) const
548  {
549  if (mAligned) return mSourceAcc->getValue(ijk);
550  const Vec3R world = mTargetXform->indexToWorld(ijk);
551  return SamplerT::sample(*mSourceAcc, mSourceXform->worldToIndex(world));
552  }
554  inline bool isAligned() const { return mAligned; }
555 private:
556  const AccessorType* mSourceAcc;
557  const math::Transform* mSourceXform;
558  const math::Transform* mTargetXform;
559  const bool mAligned;
560 };//Specialization of DualGridSampler
561 
563 
564 
565 // Class to derive the normalized alpha mask
566 template <typename GridT,
567  typename MaskT,
568  typename SamplerT = tools::BoxSampler,
569  typename FloatT = float>
571 {
572 public:
573  static_assert(std::is_floating_point<FloatT>::value,
574  "AlphaMask requires a floating-point value type");
575  using GridType = GridT;
576  using MaskType = MaskT;
577  using SamlerType = SamplerT;
578  using FloatType = FloatT;
579 
580  AlphaMask(const GridT& grid, const MaskT& mask, FloatT min, FloatT max, bool invert)
581  : mAcc(mask.tree())
582  , mSampler(mAcc, mask.transform() , grid.transform())
583  , mMin(min)
584  , mInvNorm(1/(max-min))
585  , mInvert(invert)
586  {
587  assert(min < max);
588  }
589 
590  inline bool operator()(const Coord& xyz, FloatT& a, FloatT& b) const
591  {
592  a = math::SmoothUnitStep( (mSampler(xyz) - mMin) * mInvNorm );//smooth mapping to 0->1
593  b = 1 - a;
594  if (mInvert) std::swap(a,b);
595  return a>0;
596  }
597 
598 protected:
599  using AccT = typename MaskType::ConstAccessor;
602  const FloatT mMin, mInvNorm;
603  const bool mInvert;
604 };// AlphaMask
605 
607 
608 namespace local_util {
609 
610 inline Vec3i
611 floorVec3(const Vec3R& v)
612 {
613  return Vec3i(int(std::floor(v(0))), int(std::floor(v(1))), int(std::floor(v(2))));
614 }
615 
616 
617 inline Vec3i
618 ceilVec3(const Vec3R& v)
619 {
620  return Vec3i(int(std::ceil(v(0))), int(std::ceil(v(1))), int(std::ceil(v(2))));
621 }
622 
623 
624 inline Vec3i
625 roundVec3(const Vec3R& v)
626 {
627  return Vec3i(int(::round(v(0))), int(::round(v(1))), int(::round(v(2))));
628 }
629 
630 } // namespace local_util
631 
632 
634 
635 
636 template<class TreeT>
637 inline bool
638 PointSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
639  typename TreeT::ValueType& result)
640 {
641  return inTree.probeValue(Coord(local_util::roundVec3(inCoord)), result);
642 }
643 
644 template<class TreeT>
645 inline typename TreeT::ValueType
646 PointSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
647 {
648  return inTree.getValue(Coord(local_util::roundVec3(inCoord)));
649 }
650 
651 
653 
654 template<class ValueT, class TreeT, size_t N>
655 inline void
656 BoxSampler::getValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk)
657 {
658  data[0][0][0] = inTree.getValue(ijk); // i, j, k
659 
660  ijk[2] += 1;
661  data[0][0][1] = inTree.getValue(ijk); // i, j, k + 1
662 
663  ijk[1] += 1;
664  data[0][1][1] = inTree.getValue(ijk); // i, j+1, k + 1
665 
666  ijk[2] -= 1;
667  data[0][1][0] = inTree.getValue(ijk); // i, j+1, k
668 
669  ijk[0] += 1;
670  ijk[1] -= 1;
671  data[1][0][0] = inTree.getValue(ijk); // i+1, j, k
672 
673  ijk[2] += 1;
674  data[1][0][1] = inTree.getValue(ijk); // i+1, j, k + 1
675 
676  ijk[1] += 1;
677  data[1][1][1] = inTree.getValue(ijk); // i+1, j+1, k + 1
678 
679  ijk[2] -= 1;
680  data[1][1][0] = inTree.getValue(ijk); // i+1, j+1, k
681 }
682 
683 template<class ValueT, class TreeT, size_t N>
684 inline bool
685 BoxSampler::probeValues(ValueT (&data)[N][N][N], const TreeT& inTree, Coord ijk)
686 {
687  bool hasActiveValues = false;
688  hasActiveValues |= inTree.probeValue(ijk, data[0][0][0]); // i, j, k
689 
690  ijk[2] += 1;
691  hasActiveValues |= inTree.probeValue(ijk, data[0][0][1]); // i, j, k + 1
692 
693  ijk[1] += 1;
694  hasActiveValues |= inTree.probeValue(ijk, data[0][1][1]); // i, j+1, k + 1
695 
696  ijk[2] -= 1;
697  hasActiveValues |= inTree.probeValue(ijk, data[0][1][0]); // i, j+1, k
698 
699  ijk[0] += 1;
700  ijk[1] -= 1;
701  hasActiveValues |= inTree.probeValue(ijk, data[1][0][0]); // i+1, j, k
702 
703  ijk[2] += 1;
704  hasActiveValues |= inTree.probeValue(ijk, data[1][0][1]); // i+1, j, k + 1
705 
706  ijk[1] += 1;
707  hasActiveValues |= inTree.probeValue(ijk, data[1][1][1]); // i+1, j+1, k + 1
708 
709  ijk[2] -= 1;
710  hasActiveValues |= inTree.probeValue(ijk, data[1][1][0]); // i+1, j+1, k
711 
712  return hasActiveValues;
713 }
714 
715 template<class ValueT, size_t N>
716 inline void
717 BoxSampler::extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT &vMax)
718 {
719  vMin = vMax = data[0][0][0];
720  vMin = math::Min(vMin, data[0][0][1]);
721  vMax = math::Max(vMax, data[0][0][1]);
722  vMin = math::Min(vMin, data[0][1][0]);
723  vMax = math::Max(vMax, data[0][1][0]);
724  vMin = math::Min(vMin, data[0][1][1]);
725  vMax = math::Max(vMax, data[0][1][1]);
726  vMin = math::Min(vMin, data[1][0][0]);
727  vMax = math::Max(vMax, data[1][0][0]);
728  vMin = math::Min(vMin, data[1][0][1]);
729  vMax = math::Max(vMax, data[1][0][1]);
730  vMin = math::Min(vMin, data[1][1][0]);
731  vMax = math::Max(vMax, data[1][1][0]);
732  vMin = math::Min(vMin, data[1][1][1]);
733  vMax = math::Max(vMax, data[1][1][1]);
734 }
735 
736 
737 template<class ValueT, size_t N>
738 inline ValueT
739 BoxSampler::trilinearInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw)
740 {
741  auto _interpolate = [](const ValueT& a, const ValueT& b, double weight)
742  {
744  const auto temp = (b - a) * weight;
746  return static_cast<ValueT>(a + ValueT(temp));
747  };
748 
749  // Trilinear interpolation:
750  // The eight surrounding latice values are used to construct the result. \n
751  // result(x,y,z) =
752  // v000 (1-x)(1-y)(1-z) + v001 (1-x)(1-y)z + v010 (1-x)y(1-z) + v011 (1-x)yz
753  // + v100 x(1-y)(1-z) + v101 x(1-y)z + v110 xy(1-z) + v111 xyz
754 
755  return _interpolate(
756  _interpolate(
757  _interpolate(data[0][0][0], data[0][0][1], uvw[2]),
758  _interpolate(data[0][1][0], data[0][1][1], uvw[2]),
759  uvw[1]),
760  _interpolate(
761  _interpolate(data[1][0][0], data[1][0][1], uvw[2]),
762  _interpolate(data[1][1][0], data[1][1][1], uvw[2]),
763  uvw[1]),
764  uvw[0]);
765 }
766 
767 
768 template<class TreeT>
769 inline bool
770 BoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
771  typename TreeT::ValueType& result)
772 {
773  using ValueT = typename TreeT::ValueType;
774 
775  const Vec3i inIdx = local_util::floorVec3(inCoord);
776  const Vec3R uvw = inCoord - inIdx;
777 
778  // Retrieve the values of the eight voxels surrounding the
779  // fractional source coordinates.
780  ValueT data[2][2][2];
781 
782  const bool hasActiveValues = BoxSampler::probeValues(data, inTree, Coord(inIdx));
783 
784  result = BoxSampler::trilinearInterpolation(data, uvw);
785 
786  return hasActiveValues;
787 }
788 
789 
790 template<class TreeT>
791 inline typename TreeT::ValueType
792 BoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
793 {
794  using ValueT = typename TreeT::ValueType;
795 
796  const Vec3i inIdx = local_util::floorVec3(inCoord);
797  const Vec3R uvw = inCoord - inIdx;
798 
799  // Retrieve the values of the eight voxels surrounding the
800  // fractional source coordinates.
801  ValueT data[2][2][2];
802 
803  BoxSampler::getValues(data, inTree, Coord(inIdx));
804 
805  return BoxSampler::trilinearInterpolation(data, uvw);
806 }
807 
808 
810 
811 template<class ValueT, size_t N>
812 inline ValueT
813 QuadraticSampler::triquadraticInterpolation(ValueT (&data)[N][N][N], const Vec3R& uvw)
814 {
815  auto _interpolate = [](const ValueT* value, double weight)
816  {
818  const ValueT
819  a = static_cast<ValueT>(0.5 * (value[0] + value[2]) - value[1]),
820  b = static_cast<ValueT>(0.5 * (value[2] - value[0])),
821  c = static_cast<ValueT>(value[1]);
822  const auto temp = weight * (weight * a + b) + c;
824  return static_cast<ValueT>(temp);
825  };
826 
828  ValueT vx[3];
829  for (int dx = 0; dx < 3; ++dx) {
830  ValueT vy[3];
831  for (int dy = 0; dy < 3; ++dy) {
832  // Fit a parabola to three contiguous samples in z
833  // (at z=-1, z=0 and z=1), then evaluate the parabola at z',
834  // where z' is the fractional part of inCoord.z, i.e.,
835  // inCoord.z - inIdx.z. The coefficients come from solving
836  //
837  // | (-1)^2 -1 1 || a | | v0 |
838  // | 0 0 1 || b | = | v1 |
839  // | 1^2 1 1 || c | | v2 |
840  //
841  // for a, b and c.
842  const ValueT* vz = &data[dx][dy][0];
843  vy[dy] = _interpolate(vz, uvw.z());
844  }//loop over y
845  // Fit a parabola to three interpolated samples in y, then
846  // evaluate the parabola at y', where y' is the fractional
847  // part of inCoord.y.
848  vx[dx] = _interpolate(vy, uvw.y());
849  }//loop over x
850  // Fit a parabola to three interpolated samples in x, then
851  // evaluate the parabola at the fractional part of inCoord.x.
852  return _interpolate(vx, uvw.x());
853 }
854 
855 template<class TreeT>
856 inline bool
857 QuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
858  typename TreeT::ValueType& result)
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  bool active = false;
868  ValueT data[3][3][3];
869  for (int dx = 0, ix = inLoIdx.x(); dx < 3; ++dx, ++ix) {
870  for (int dy = 0, iy = inLoIdx.y(); dy < 3; ++dy, ++iy) {
871  for (int dz = 0, iz = inLoIdx.z(); dz < 3; ++dz, ++iz) {
872  if (inTree.probeValue(Coord(ix, iy, iz), data[dx][dy][dz])) active = true;
873  }
874  }
875  }
876 
877  result = QuadraticSampler::triquadraticInterpolation(data, uvw);
878 
879  return active;
880 }
881 
882 template<class TreeT>
883 inline typename TreeT::ValueType
884 QuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
885 {
886  using ValueT = typename TreeT::ValueType;
887 
888  const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx - Vec3i(1, 1, 1);
889  const Vec3R uvw = inCoord - inIdx;
890 
891  // Retrieve the values of the 27 voxels surrounding the
892  // fractional source coordinates.
893  ValueT data[3][3][3];
894  for (int dx = 0, ix = inLoIdx.x(); dx < 3; ++dx, ++ix) {
895  for (int dy = 0, iy = inLoIdx.y(); dy < 3; ++dy, ++iy) {
896  for (int dz = 0, iz = inLoIdx.z(); dz < 3; ++dz, ++iz) {
897  data[dx][dy][dz] = inTree.getValue(Coord(ix, iy, iz));
898  }
899  }
900  }
901 
902  return QuadraticSampler::triquadraticInterpolation(data, uvw);
903 }
904 
905 
907 
908 
909 template<class TreeT>
910 inline bool
911 StaggeredPointSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
912  typename TreeT::ValueType& result)
913 {
914  using ValueType = typename TreeT::ValueType;
915 
916  ValueType tempX, tempY, tempZ;
917  bool active = false;
918 
919  active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
920  active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
921  active = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
922 
923  result.x() = tempX.x();
924  result.y() = tempY.y();
925  result.z() = tempZ.z();
926 
927  return active;
928 }
929 
930 template<class TreeT>
931 inline typename TreeT::ValueType
932 StaggeredPointSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
933 {
934  using ValueT = typename TreeT::ValueType;
935 
936  const ValueT tempX = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
937  const ValueT tempY = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
938  const ValueT tempZ = PointSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
939 
940  return ValueT(tempX.x(), tempY.y(), tempZ.z());
941 }
942 
943 
945 
946 
947 template<class TreeT>
948 inline bool
949 StaggeredBoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
950  typename TreeT::ValueType& result)
951 {
952  using ValueType = typename TreeT::ValueType;
953 
954  ValueType tempX, tempY, tempZ;
955  tempX = tempY = tempZ = zeroVal<ValueType>();
956  bool active = false;
957 
958  active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
959  active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
960  active = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
961 
962  result.x() = tempX.x();
963  result.y() = tempY.y();
964  result.z() = tempZ.z();
965 
966  return active;
967 }
968 
969 template<class TreeT>
970 inline typename TreeT::ValueType
971 StaggeredBoxSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
972 {
973  using ValueT = typename TreeT::ValueType;
974 
975  const ValueT tempX = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
976  const ValueT tempY = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
977  const ValueT tempZ = BoxSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
978 
979  return ValueT(tempX.x(), tempY.y(), tempZ.z());
980 }
981 
982 
984 
985 
986 template<class TreeT>
987 inline bool
988 StaggeredQuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord,
989  typename TreeT::ValueType& result)
990 {
991  using ValueType = typename TreeT::ValueType;
992 
993  ValueType tempX, tempY, tempZ;
994  bool active = false;
995 
996  active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0, 0), tempX) || active;
997  active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0.5, 0), tempY) || active;
998  active = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0, 0, 0.5), tempZ) || active;
999 
1000  result.x() = tempX.x();
1001  result.y() = tempY.y();
1002  result.z() = tempZ.z();
1003 
1004  return active;
1005 }
1006 
1007 template<class TreeT>
1008 inline typename TreeT::ValueType
1009 StaggeredQuadraticSampler::sample(const TreeT& inTree, const Vec3R& inCoord)
1010 {
1011  using ValueT = typename TreeT::ValueType;
1012 
1013  const ValueT tempX = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.5, 0.0, 0.0));
1014  const ValueT tempY = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.5, 0.0));
1015  const ValueT tempZ = QuadraticSampler::sample<TreeT>(inTree, inCoord + Vec3R(0.0, 0.0, 0.5));
1016 
1017  return ValueT(tempX.x(), tempY.y(), tempZ.z());
1018 }
1019 
1021 
1022 template <>
1023 struct Sampler<0, false> : public PointSampler {};
1024 
1025 template <>
1026 struct Sampler<1, false> : public BoxSampler {};
1027 
1028 template <>
1029 struct Sampler<2, false> : public QuadraticSampler {};
1030 
1031 template <>
1032 struct Sampler<0, true> : public StaggeredPointSampler {};
1033 
1034 template <>
1035 struct Sampler<1, true> : public StaggeredBoxSampler {};
1036 
1037 template <>
1038 struct Sampler<2, true> : public StaggeredQuadraticSampler {};
1039 
1040 } // namespace tools
1041 } // namespace OPENVDB_VERSION_NAME
1042 } // namespace openvdb
1043 
1044 #endif // OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
1045 
1046 // Copyright (c) DreamWorks Animation LLC
1047 // All rights reserved. This software is distributed under the
1048 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
static const char * name()
Definition: Interpolation.h:225
#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:223
static bool staggered()
Definition: Interpolation.h:129
GridSampler(const GridType &grid)
Definition: Interpolation.h:320
typename TreeAdapter< GridOrTreeType >::AccessorType AccessorType
Definition: Interpolation.h:317
const Type & Max(const Type &a, const Type &b)
Return the maximum of two values.
Definition: Math.h:569
Definition: Interpolation.h:123
FloatT FloatType
Definition: Interpolation.h:578
ValueType wsSample(const Vec3d &wspoint) const
Sample in world space.
Definition: Interpolation.h:366
GridT GridType
Definition: Interpolation.h:575
Definition: Interpolation.h:246
static bool staggered()
Definition: Interpolation.h:152
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
typename TreeT::ValueType ValueType
Definition: Interpolation.h:396
Provises a unified interface for sampling, i.e. interpolation.
Definition: Interpolation.h:90
static bool consistent()
Definition: Interpolation.h:151
bool isAligned() const
Return true if the two grids are aligned.
Definition: Interpolation.h:513
typename TreeAdapter< AccT >::TreeType TreeType
Definition: Interpolation.h:477
MaskT MaskType
Definition: Interpolation.h:576
ValueType sampleVoxel(const RealType &x, const RealType &y, const RealType &z) const
Sample a point in index space in the grid.
Definition: Interpolation.h:335
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
static int radius()
Definition: Interpolation.h:272
static int radius()
Definition: Interpolation.h:226
static size_t order()
Definition: Interpolation.h:253
typename AccT::ValueType ValueType
Definition: Interpolation.h:475
GridSampler(const TreeType &tree, const math::Transform &transform)
Definition: Interpolation.h:325
typename TreeAdapter< GridType >::AccessorType AccessorType
Definition: Interpolation.h:478
math::Vec3< Real > Vec3R
Definition: Types.h:79
typename GridOrTreeType::ValueType ValueType
Definition: Interpolation.h:314
static bool consistent()
Definition: Interpolation.h:274
typename MaskType::ConstAccessor AccT
Definition: Interpolation.h:599
ValueType isSample(const Coord &ijk) const
Sample value in integer index space.
Definition: Interpolation.h:353
static bool consistent()
Definition: Interpolation.h:251
SharedPtr< GridSampler > Ptr
Definition: Interpolation.h:395
std::shared_ptr< T > SharedPtr
Definition: Types.h:139
const math::Transform & transform() const
Definition: Interpolation.h:328
Vec3< int32_t > Vec3i
Definition: Vec3.h:686
static size_t order()
Definition: Interpolation.h:196
SamplerT SamlerType
Definition: Interpolation.h:577
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:55
static bool staggered()
Definition: Interpolation.h:229
static bool consistent()
Definition: Interpolation.h:194
#define OPENVDB_NO_TYPE_CONVERSION_WARNING_END
Definition: Platform.h:224
_TreeType TreeType
Definition: Grid.h:1078
bool isAligned() const
Return true if the two grids are aligned.
Definition: Interpolation.h:554
static const char * name()
Definition: Interpolation.h:125
Vec3< double > Vec3d
Definition: Vec3.h:689
static const char * name()
Definition: Interpolation.h:191
GridSampler(const AccessorType &acc, const math::Transform &transform)
Definition: Interpolation.h:403
Vec3i ceilVec3(const Vec3R &v)
Definition: Interpolation.h:618
static bool mipmap()
Definition: Interpolation.h:250
static bool mipmap()
Definition: Interpolation.h:227
static bool staggered()
Definition: Interpolation.h:195
typename tree::ValueAccessor< TreeType > AccessorType
Definition: Grid.h:1089
Class that provides the interface for continuous sampling of values in a tree.
Definition: Interpolation.h:310
static const char * name()
Definition: Interpolation.h:148
static size_t order()
Definition: Interpolation.h:153
Definition: Interpolation.h:223
Vec3i roundVec3(const Vec3R &v)
Definition: Interpolation.h:625
const FloatT mMin
Definition: Interpolation.h:602
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:128
ValueType sampleVoxel(typename Coord::ValueType i, typename Coord::ValueType j, typename Coord::ValueType k) const
Sample value in integer index space.
Definition: Interpolation.h:344
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:547
typename TreeAdapter< AccT >::GridType GridType
Definition: Interpolation.h:476
static size_t order()
Definition: Interpolation.h:230
ValueType isSample(const Vec3d &ispoint) const
Sample in fractional index space.
Definition: Interpolation.h:436
static bool mipmap()
Definition: Interpolation.h:127
static const char * name()
Definition: Interpolation.h:271
typename TreeAdapter< GridOrTreeType >::TreeType TreeType
Definition: Interpolation.h:316
static bool staggered()
Definition: Interpolation.h:275
typename tree::ValueAccessor< TreeT > AccessorType
Definition: Interpolation.h:530
ValueType isSample(const Vec3d &ispoint) const
Sample in fractional index space.
Definition: Interpolation.h:357
Definition: Interpolation.h:146
typename tree::ValueAccessor< TreeT > AccessorType
Definition: Interpolation.h:399
T & z()
Definition: Vec3.h:112
AlphaMask(const GridT &grid, const MaskT &mask, FloatT min, FloatT max, bool invert)
Definition: Interpolation.h:580
SharedPtr< GridSampler > Ptr
Definition: Interpolation.h:313
T & y()
Definition: Vec3.h:111
Definition: Exceptions.h:40
static bool mipmap()
Definition: Interpolation.h:273
static int radius()
Definition: Interpolation.h:149
const bool mInvert
Definition: Interpolation.h:603
static bool mipmap()
Definition: Interpolation.h:193
static int radius()
Definition: Interpolation.h:249
bool operator()(const Coord &xyz, FloatT &a, FloatT &b) const
Definition: Interpolation.h:590
const math::Transform & transform() const
Definition: Interpolation.h:407
ValueType isSample(const Coord &ijk) const
Sample value in integer index space.
Definition: Interpolation.h:432
Library and file format version numbers.
static bool consistent()
Definition: Interpolation.h:128
DualGridSampler(const AccessorType &sourceAccessor, const math::Transform &sourceXform, const math::Transform &targetXform)
ValueAccessor and transform constructor.
Definition: Interpolation.h:536
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:129
static size_t order()
Definition: Interpolation.h:276
Vec3i floorVec3(const Vec3R &v)
Definition: Interpolation.h:611
tools::DualGridSampler< AccT, SamplerT > mSampler
Definition: Interpolation.h:601
static size_t order()
Definition: Interpolation.h:130
ValueType sampleVoxel(const RealType &x, const RealType &y, const RealType &z) const
Sample a point in index space in the grid.
Definition: Interpolation.h:414
Definition: Interpolation.h:189
ValueType sampleVoxel(typename Coord::ValueType i, typename Coord::ValueType j, typename Coord::ValueType k) const
Sample value in integer index space.
Definition: Interpolation.h:423
Definition: Transform.h:66
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:379
typename TreeAdapter< GridOrTreeType >::GridType GridType
Definition: Interpolation.h:315
static int radius()
Definition: Interpolation.h:192
static int radius()
Definition: Interpolation.h:126
const Type & Min(const Type &a, const Type &b)
Return the minimum of two values.
Definition: Math.h:630
This is a simple convenience class that allows for sampling from a source grid into the index space o...
Definition: Interpolation.h:472
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:506
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:180
Definition: Interpolation.h:570
DualGridSampler(const GridType &sourceGrid, const math::Transform &targetXform)
Grid and transform constructor.
Definition: Interpolation.h:483
DualGridSampler(const TreeType &sourceTree, const math::Transform &sourceXform, const math::Transform &targetXform)
Tree and transform constructor.
Definition: Interpolation.h:495
typename TreeT::ValueType ValueType
Definition: Interpolation.h:527
AccT mAcc
Definition: Interpolation.h:600
static bool mipmap()
Definition: Interpolation.h:150
static bool consistent()
Definition: Interpolation.h:228
static const char * name()
Definition: Interpolation.h:248
static bool staggered()
Definition: Interpolation.h:252
Type SmoothUnitStep(Type x)
Return 0 if x < 0, 1 if x > 1 or else (3 − 2 x) x².
Definition: Math.h:256
ValueType wsSample(const Vec3d &wspoint) const
Sample in world space.
Definition: Interpolation.h:445
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:110