40#ifndef OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
41#define OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
43#include <openvdb/version.h>
63template <
size_t Order,
bool Staggered = false>
66 static_assert(Order < 3,
"Samplers of order higher than 2 are not supported");
80 typename TreeT::ValueType& result);
86 static typename TreeT::ValueType
sample(
const TreeT& inTree,
const Vec3R& inCoord);
99 static const char*
name() {
return "point"; }
109 template<
class TreeT>
110 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
111 typename TreeT::ValueType& result);
115 template<
class TreeT>
116 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
122 static const char*
name() {
return "box"; }
132 template<
class TreeT>
133 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
134 typename TreeT::ValueType& result);
138 template<
class TreeT>
139 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
143 template<
class ValueT,
class TreeT,
size_t N>
144 static inline void getValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk);
149 template<
class ValueT,
class TreeT,
size_t N>
150 static inline bool probeValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk);
154 template<
class ValueT,
size_t N>
155 static inline void extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT& vMax);
158 template<
class ValueT,
size_t N>
159 static inline ValueT trilinearInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw);
165 static const char*
name() {
return "quadratic"; }
175 template<
class TreeT>
176 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
177 typename TreeT::ValueType& result);
181 template<
class TreeT>
182 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
184 template<
class ValueT,
size_t N>
185 static inline ValueT triquadraticInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw);
199 static const char*
name() {
return "point"; }
209 template<
class TreeT>
210 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
211 typename TreeT::ValueType& result);
215 template<
class TreeT>
216 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
222 static const char*
name() {
return "box"; }
232 template<
class TreeT>
233 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
234 typename TreeT::ValueType& result);
238 template<
class TreeT>
239 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
245 static const char*
name() {
return "quadratic"; }
255 template<
class TreeT>
256 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
257 typename TreeT::ValueType& result);
261 template<
class TreeT>
262 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
283template<
typename Gr
idOrTreeType,
typename SamplerType>
295 : mTree(&(grid.tree())), mTransform(&(grid.transform())) {}
300 : mTree(&tree), mTransform(&transform) {}
308 template<
typename RealType>
311 return this->isSample(
Vec3d(x,y,z));
322 return this->isSample(
Coord(i,j,k));
334 SamplerType::sample(*mTree, ispoint, result);
343 SamplerType::sample(*mTree, mTransform->worldToIndex(wspoint), result);
348 const TreeType* mTree;
365template<
typename TreeT,
typename SamplerType>
379 : mAccessor(&acc), mTransform(&transform) {}
387 template<
typename RealType>
390 return this->isSample(
Vec3d(x,y,z));
401 return this->isSample(
Coord(i,j,k));
413 SamplerType::sample(*mAccessor, ispoint, result);
422 SamplerType::sample(*mAccessor, mTransform->worldToIndex(wspoint), result);
427 const AccessorType* mAccessor;
444template<
typename GridOrTreeT,
459 : mSourceTree(&(sourceGrid.tree()))
460 , mSourceXform(&(sourceGrid.transform()))
461 , mTargetXform(&targetXform)
462 , mAligned(targetXform == *mSourceXform)
472 : mSourceTree(&sourceTree)
473 , mSourceXform(&sourceXform)
474 , mTargetXform(&targetXform)
475 , mAligned(targetXform == sourceXform)
482 if (mAligned)
return mSourceTree->getValue(ijk);
483 const Vec3R world = mTargetXform->indexToWorld(ijk);
484 return SamplerT::sample(*mSourceTree, mSourceXform->worldToIndex(world));
489 const TreeType* mSourceTree;
496template<
typename TreeT,
513 : mSourceAcc(&sourceAccessor)
514 , mSourceXform(&sourceXform)
515 , mTargetXform(&targetXform)
516 , mAligned(targetXform == sourceXform)
523 if (mAligned)
return mSourceAcc->getValue(ijk);
524 const Vec3R world = mTargetXform->indexToWorld(ijk);
525 return SamplerT::sample(*mSourceAcc, mSourceXform->worldToIndex(world));
530 const AccessorType* mSourceAcc;
540template <
typename GridT,
543 typename FloatT =
float>
547 static_assert(std::is_floating_point<FloatT>::value,
548 "AlphaMask requires a floating-point value type");
554 AlphaMask(
const GridT& grid,
const MaskT& mask, FloatT min, FloatT max,
bool invert)
556 , mSampler(mAcc, mask.transform() , grid.transform())
558 , mInvNorm(1/(max-min))
566 a = math::SmoothUnitStep( (mSampler(xyz) - mMin) * mInvNorm );
568 if (mInvert) std::swap(a,b);
573 using AccT =
typename MaskType::ConstAccessor;
582namespace local_util {
587 return Vec3i(
int(std::floor(v(0))),
int(std::floor(v(1))),
int(std::floor(v(2))));
594 return Vec3i(
int(std::ceil(v(0))),
int(std::ceil(v(1))),
int(std::ceil(v(2))));
601 return Vec3i(
int(::round(v(0))),
int(::round(v(1))),
int(::round(v(2))));
612PointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
613 typename TreeT::ValueType& result)
615 return inTree.probeValue(
Coord(local_util::roundVec3(inCoord)), result);
619inline typename TreeT::ValueType
620PointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
622 return inTree.getValue(
Coord(local_util::roundVec3(inCoord)));
628template<
class ValueT,
class TreeT,
size_t N>
630BoxSampler::getValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk)
632 data[0][0][0] = inTree.getValue(ijk);
635 data[0][0][1] = inTree.getValue(ijk);
638 data[0][1][1] = inTree.getValue(ijk);
641 data[0][1][0] = inTree.getValue(ijk);
645 data[1][0][0] = inTree.getValue(ijk);
648 data[1][0][1] = inTree.getValue(ijk);
651 data[1][1][1] = inTree.getValue(ijk);
654 data[1][1][0] = inTree.getValue(ijk);
657template<
class ValueT,
class TreeT,
size_t N>
659BoxSampler::probeValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk)
661 bool hasActiveValues =
false;
662 hasActiveValues |= inTree.probeValue(ijk, data[0][0][0]);
665 hasActiveValues |= inTree.probeValue(ijk, data[0][0][1]);
668 hasActiveValues |= inTree.probeValue(ijk, data[0][1][1]);
671 hasActiveValues |= inTree.probeValue(ijk, data[0][1][0]);
675 hasActiveValues |= inTree.probeValue(ijk, data[1][0][0]);
678 hasActiveValues |= inTree.probeValue(ijk, data[1][0][1]);
681 hasActiveValues |= inTree.probeValue(ijk, data[1][1][1]);
684 hasActiveValues |= inTree.probeValue(ijk, data[1][1][0]);
686 return hasActiveValues;
689template<
class ValueT,
size_t N>
691BoxSampler::extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT &vMax)
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]);
711template<
class ValueT,
size_t N>
713BoxSampler::trilinearInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw)
715 auto _interpolate = [](
const ValueT& a,
const ValueT& b,
double weight)
718 const auto temp = (b - a) * weight;
720 return static_cast<ValueT
>(a + ValueT(temp));
731 _interpolate(data[0][0][0], data[0][0][1], uvw[2]),
732 _interpolate(data[0][1][0], data[0][1][1], uvw[2]),
735 _interpolate(data[1][0][0], data[1][0][1], uvw[2]),
736 _interpolate(data[1][1][0], data[1][1][1], uvw[2]),
744BoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
745 typename TreeT::ValueType& result)
747 using ValueT =
typename TreeT::ValueType;
749 const Vec3i inIdx = local_util::floorVec3(inCoord);
750 const Vec3R uvw = inCoord - inIdx;
754 ValueT data[2][2][2];
756 const bool hasActiveValues = BoxSampler::probeValues(data, inTree,
Coord(inIdx));
758 result = BoxSampler::trilinearInterpolation(data, uvw);
760 return hasActiveValues;
765inline typename TreeT::ValueType
766BoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
768 using ValueT =
typename TreeT::ValueType;
770 const Vec3i inIdx = local_util::floorVec3(inCoord);
771 const Vec3R uvw = inCoord - inIdx;
775 ValueT data[2][2][2];
777 BoxSampler::getValues(data, inTree,
Coord(inIdx));
779 return BoxSampler::trilinearInterpolation(data, uvw);
785template<
class ValueT,
size_t N>
787QuadraticSampler::triquadraticInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw)
789 auto _interpolate = [](
const ValueT* value,
double weight)
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);
803 for (
int dx = 0; dx < 3; ++dx) {
805 for (
int dy = 0; dy < 3; ++dy) {
816 const ValueT* vz = &data[dx][dy][0];
817 vy[dy] = _interpolate(vz, uvw.
z());
822 vx[dx] = _interpolate(vy, uvw.
y());
826 return _interpolate(vx, uvw.
x());
831QuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
832 typename TreeT::ValueType& result)
834 using ValueT =
typename TreeT::ValueType;
836 const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx -
Vec3i(1, 1, 1);
837 const Vec3R uvw = inCoord - inIdx;
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;
851 result = QuadraticSampler::triquadraticInterpolation(data, uvw);
857inline typename TreeT::ValueType
858QuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
860 using ValueT =
typename TreeT::ValueType;
862 const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx -
Vec3i(1, 1, 1);
863 const Vec3R uvw = inCoord - inIdx;
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));
876 return QuadraticSampler::triquadraticInterpolation(data, uvw);
885StaggeredPointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
886 typename TreeT::ValueType& result)
888 using ValueType =
typename TreeT::ValueType;
890 ValueType tempX, tempY, tempZ;
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;
897 result.x() = tempX.x();
898 result.y() = tempY.y();
899 result.z() = tempZ.z();
905inline typename TreeT::ValueType
906StaggeredPointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
908 using ValueT =
typename TreeT::ValueType;
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));
914 return ValueT(tempX.x(), tempY.y(), tempZ.z());
923StaggeredBoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
924 typename TreeT::ValueType& result)
926 using ValueType =
typename TreeT::ValueType;
928 ValueType tempX, tempY, tempZ;
929 tempX = tempY = tempZ = zeroVal<ValueType>();
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;
936 result.x() = tempX.x();
937 result.y() = tempY.y();
938 result.z() = tempZ.z();
944inline typename TreeT::ValueType
945StaggeredBoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
947 using ValueT =
typename TreeT::ValueType;
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));
953 return ValueT(tempX.x(), tempY.y(), tempZ.z());
962StaggeredQuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
963 typename TreeT::ValueType& result)
965 using ValueType =
typename TreeT::ValueType;
967 ValueType tempX, tempY, tempZ;
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;
974 result.x() = tempX.x();
975 result.y() = tempY.y();
976 result.z() = tempZ.z();
982inline typename TreeT::ValueType
983StaggeredQuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
985 using ValueT =
typename TreeT::ValueType;
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));
991 return ValueT(tempX.x(), tempY.y(), tempZ.z());
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
ValueAccessors are designed to help accelerate accesses into the OpenVDB Tree structures by storing c...
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
Int32 ValueType
Definition Coord.h:33
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
The Value Accessor Implementation and API methods. The majoirty of the API matches the API of a compa...
Definition ValueAccessor.h:367
std::shared_ptr< T > SharedPtr
Definition Types.h:114
Definition Exceptions.h:13
_TreeType TreeType
Definition Grid.h:1061
typename tree::ValueAccessor< TreeType > AccessorType
Definition Grid.h:1072
#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