67 #ifndef OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
68 #define OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
77 #include <type_traits>
89 template <
size_t Order,
bool Staggered = false>
92 static_assert(Order < 3,
"Samplers of order higher than 2 are not supported");
93 static const char* name();
96 static bool consistent();
97 static bool staggered();
98 static size_t order();
104 template<
class TreeT>
105 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
106 typename TreeT::ValueType& result);
111 template<
class TreeT>
112 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
125 static const char*
name() {
return "point"; }
135 template<
class TreeT>
136 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
137 typename TreeT::ValueType& result);
141 template<
class TreeT>
142 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
148 static const char*
name() {
return "box"; }
158 template<
class TreeT>
159 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
160 typename TreeT::ValueType& result);
164 template<
class TreeT>
165 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
169 template<
class ValueT,
class TreeT,
size_t N>
170 static inline void getValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk);
175 template<
class ValueT,
class TreeT,
size_t N>
176 static inline bool probeValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk);
180 template<
class ValueT,
size_t N>
181 static inline void extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT& vMax);
184 template<
class ValueT,
size_t N>
185 static inline ValueT trilinearInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw);
191 static const char*
name() {
return "quadratic"; }
201 template<
class TreeT>
202 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
203 typename TreeT::ValueType& result);
207 template<
class TreeT>
208 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
210 template<
class ValueT,
size_t N>
211 static inline ValueT triquadraticInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw);
225 static const char*
name() {
return "point"; }
235 template<
class TreeT>
236 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
237 typename TreeT::ValueType& result);
241 template<
class TreeT>
242 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
248 static const char*
name() {
return "box"; }
258 template<
class TreeT>
259 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
260 typename TreeT::ValueType& result);
264 template<
class TreeT>
265 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
271 static const char*
name() {
return "quadratic"; }
281 template<
class TreeT>
282 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
283 typename TreeT::ValueType& result);
287 template<
class TreeT>
288 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
309 template<
typename Gr
idOrTreeType,
typename SamplerType>
321 : mTree(&(grid.tree())), mTransform(&(grid.transform())) {}
326 : mTree(&tree), mTransform(&transform) {}
334 template<
typename RealType>
337 return this->isSample(
Vec3d(x,y,z));
348 return this->isSample(
Coord(i,j,k));
360 SamplerType::sample(*mTree, ispoint, result);
369 SamplerType::sample(*mTree, mTransform->worldToIndex(wspoint), result);
374 const TreeType* mTree;
391 template<
typename TreeT,
typename SamplerType>
405 : mAccessor(&acc), mTransform(&transform) {}
413 template<
typename RealType>
416 return this->isSample(
Vec3d(x,y,z));
427 return this->isSample(
Coord(i,j,k));
439 SamplerType::sample(*mAccessor, ispoint, result);
448 SamplerType::sample(*mAccessor, mTransform->worldToIndex(wspoint), result);
453 const AccessorType* mAccessor;
470 template<
typename GridOrTreeT,
485 : mSourceTree(&(sourceGrid.tree()))
486 , mSourceXform(&(sourceGrid.transform()))
487 , mTargetXform(&targetXform)
488 , mAligned(targetXform == *mSourceXform)
498 : mSourceTree(&sourceTree)
499 , mSourceXform(&sourceXform)
500 , mTargetXform(&targetXform)
501 , mAligned(targetXform == sourceXform)
508 if (mAligned)
return mSourceTree->getValue(ijk);
509 const Vec3R world = mTargetXform->indexToWorld(ijk);
510 return SamplerT::sample(*mSourceTree, mSourceXform->worldToIndex(world));
515 const TreeType* mSourceTree;
522 template<
typename TreeT,
539 : mSourceAcc(&sourceAccessor)
540 , mSourceXform(&sourceXform)
541 , mTargetXform(&targetXform)
542 , mAligned(targetXform == sourceXform)
549 if (mAligned)
return mSourceAcc->getValue(ijk);
550 const Vec3R world = mTargetXform->indexToWorld(ijk);
551 return SamplerT::sample(*mSourceAcc, mSourceXform->worldToIndex(world));
556 const AccessorType* mSourceAcc;
566 template <
typename GridT,
569 typename FloatT =
float>
573 static_assert(std::is_floating_point<FloatT>::value,
574 "AlphaMask requires a floating-point value type");
582 , mSampler(mAcc, mask.transform() , grid.transform())
594 if (mInvert) std::swap(a,b);
599 using AccT =
typename MaskType::ConstAccessor;
608 namespace local_util {
613 return Vec3i(
int(std::floor(v(0))),
int(std::floor(v(1))),
int(std::floor(v(2))));
620 return Vec3i(
int(std::ceil(v(0))),
int(std::ceil(v(1))),
int(std::ceil(v(2))));
627 return Vec3i(
int(::round(v(0))),
int(::round(v(1))),
int(::round(v(2))));
636 template<
class TreeT>
638 PointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
639 typename TreeT::ValueType& result)
644 template<
class TreeT>
645 inline typename TreeT::ValueType
646 PointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
654 template<
class ValueT,
class TreeT,
size_t N>
656 BoxSampler::getValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk)
658 data[0][0][0] = inTree.getValue(ijk);
661 data[0][0][1] = inTree.getValue(ijk);
664 data[0][1][1] = inTree.getValue(ijk);
667 data[0][1][0] = inTree.getValue(ijk);
671 data[1][0][0] = inTree.getValue(ijk);
674 data[1][0][1] = inTree.getValue(ijk);
677 data[1][1][1] = inTree.getValue(ijk);
680 data[1][1][0] = inTree.getValue(ijk);
683 template<
class ValueT,
class TreeT,
size_t N>
685 BoxSampler::probeValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk)
687 bool hasActiveValues =
false;
688 hasActiveValues |= inTree.probeValue(ijk, data[0][0][0]);
691 hasActiveValues |= inTree.probeValue(ijk, data[0][0][1]);
694 hasActiveValues |= inTree.probeValue(ijk, data[0][1][1]);
697 hasActiveValues |= inTree.probeValue(ijk, data[0][1][0]);
701 hasActiveValues |= inTree.probeValue(ijk, data[1][0][0]);
704 hasActiveValues |= inTree.probeValue(ijk, data[1][0][1]);
707 hasActiveValues |= inTree.probeValue(ijk, data[1][1][1]);
710 hasActiveValues |= inTree.probeValue(ijk, data[1][1][0]);
712 return hasActiveValues;
715 template<
class ValueT,
size_t N>
719 vMin = vMax = data[0][0][0];
737 template<
class ValueT,
size_t N>
739 BoxSampler::trilinearInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw)
741 auto _interpolate = [](
const ValueT& a,
const ValueT& b,
double weight)
744 const auto temp = (b - a) * weight;
746 return static_cast<ValueT
>(a + ValueT(temp));
757 _interpolate(data[0][0][0], data[0][0][1], uvw[2]),
758 _interpolate(data[0][1][0], data[0][1][1], uvw[2]),
761 _interpolate(data[1][0][0], data[1][0][1], uvw[2]),
762 _interpolate(data[1][1][0], data[1][1][1], uvw[2]),
768 template<
class TreeT>
770 BoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
771 typename TreeT::ValueType& result)
773 using ValueT =
typename TreeT::ValueType;
776 const Vec3R uvw = inCoord - inIdx;
780 ValueT data[2][2][2];
782 const bool hasActiveValues = BoxSampler::probeValues(data, inTree,
Coord(inIdx));
784 result = BoxSampler::trilinearInterpolation(data, uvw);
786 return hasActiveValues;
790 template<
class TreeT>
791 inline typename TreeT::ValueType
792 BoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
794 using ValueT =
typename TreeT::ValueType;
797 const Vec3R uvw = inCoord - inIdx;
801 ValueT data[2][2][2];
803 BoxSampler::getValues(data, inTree,
Coord(inIdx));
805 return BoxSampler::trilinearInterpolation(data, uvw);
811 template<
class ValueT,
size_t N>
813 QuadraticSampler::triquadraticInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw)
815 auto _interpolate = [](
const ValueT* value,
double weight)
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);
829 for (
int dx = 0; dx < 3; ++dx) {
831 for (
int dy = 0; dy < 3; ++dy) {
842 const ValueT* vz = &data[dx][dy][0];
843 vy[dy] = _interpolate(vz, uvw.
z());
848 vx[dx] = _interpolate(vy, uvw.
y());
852 return _interpolate(vx, uvw.
x());
855 template<
class TreeT>
857 QuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
858 typename TreeT::ValueType& result)
860 using ValueT =
typename TreeT::ValueType;
863 const Vec3R uvw = inCoord - inIdx;
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;
877 result = QuadraticSampler::triquadraticInterpolation(data, uvw);
882 template<
class TreeT>
883 inline typename TreeT::ValueType
884 QuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
886 using ValueT =
typename TreeT::ValueType;
889 const Vec3R uvw = inCoord - inIdx;
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));
902 return QuadraticSampler::triquadraticInterpolation(data, uvw);
909 template<
class TreeT>
911 StaggeredPointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
912 typename TreeT::ValueType& result)
914 using ValueType =
typename TreeT::ValueType;
916 ValueType tempX, tempY, tempZ;
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;
923 result.x() = tempX.x();
924 result.y() = tempY.y();
925 result.z() = tempZ.z();
930 template<
class TreeT>
931 inline typename TreeT::ValueType
932 StaggeredPointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
934 using ValueT =
typename TreeT::ValueType;
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));
940 return ValueT(tempX.x(), tempY.y(), tempZ.z());
947 template<
class TreeT>
949 StaggeredBoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
950 typename TreeT::ValueType& result)
952 using ValueType =
typename TreeT::ValueType;
954 ValueType tempX, tempY, tempZ;
955 tempX = tempY = tempZ = zeroVal<ValueType>();
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;
962 result.x() = tempX.x();
963 result.y() = tempY.y();
964 result.z() = tempZ.z();
969 template<
class TreeT>
970 inline typename TreeT::ValueType
971 StaggeredBoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
973 using ValueT =
typename TreeT::ValueType;
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));
979 return ValueT(tempX.x(), tempY.y(), tempZ.z());
986 template<
class TreeT>
988 StaggeredQuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
989 typename TreeT::ValueType& result)
991 using ValueType =
typename TreeT::ValueType;
993 ValueType tempX, tempY, tempZ;
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;
1000 result.x() = tempX.x();
1001 result.y() = tempY.y();
1002 result.z() = tempZ.z();
1007 template<
class TreeT>
1008 inline typename TreeT::ValueType
1009 StaggeredQuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
1011 using ValueT =
typename TreeT::ValueType;
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));
1017 return ValueT(tempX.x(), tempY.y(), tempZ.z());
1044 #endif // OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED