40#ifndef OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
41#define OPENVDB_TOOLS_INTERPOLATION_HAS_BEEN_INCLUDED
43#include <openvdb/version.h>
62template <
size_t Order,
bool Staggered = false>
65 static_assert(Order < 3,
"Samplers of order higher than 2 are not supported");
79 typename TreeT::ValueType& result);
85 static typename TreeT::ValueType
sample(
const TreeT& inTree,
const Vec3R& inCoord);
98 static const char*
name() {
return "point"; }
108 template<
class TreeT>
109 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
110 typename TreeT::ValueType& result);
114 template<
class TreeT>
115 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
121 static const char*
name() {
return "box"; }
131 template<
class TreeT>
132 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
133 typename TreeT::ValueType& result);
137 template<
class TreeT>
138 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
142 template<
class ValueT,
class TreeT,
size_t N>
143 static inline void getValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk);
148 template<
class ValueT,
class TreeT,
size_t N>
149 static inline bool probeValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk);
153 template<
class ValueT,
size_t N>
154 static inline void extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT& vMax);
157 template<
class ValueT,
size_t N>
158 static inline ValueT trilinearInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw);
164 static const char*
name() {
return "quadratic"; }
174 template<
class TreeT>
175 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
176 typename TreeT::ValueType& result);
180 template<
class TreeT>
181 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
183 template<
class ValueT,
size_t N>
184 static inline ValueT triquadraticInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw);
198 static const char*
name() {
return "point"; }
208 template<
class TreeT>
209 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
210 typename TreeT::ValueType& result);
214 template<
class TreeT>
215 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
221 static const char*
name() {
return "box"; }
231 template<
class TreeT>
232 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
233 typename TreeT::ValueType& result);
237 template<
class TreeT>
238 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
244 static const char*
name() {
return "quadratic"; }
254 template<
class TreeT>
255 static bool sample(
const TreeT& inTree,
const Vec3R& inCoord,
256 typename TreeT::ValueType& result);
260 template<
class TreeT>
261 static typename TreeT::ValueType sample(
const TreeT& inTree,
const Vec3R& inCoord);
282template<
typename Gr
idOrTreeType,
typename SamplerType>
294 : mTree(&(grid.tree())), mTransform(&(grid.transform())) {}
299 : mTree(&tree), mTransform(&transform) {}
307 template<
typename RealType>
310 return this->isSample(Vec3d(x,y,z));
321 return this->isSample(
Coord(i,j,k));
333 SamplerType::sample(*mTree, ispoint, result);
342 SamplerType::sample(*mTree, mTransform->worldToIndex(wspoint), result);
347 const TreeType* mTree;
364template<
typename TreeT,
typename SamplerType>
378 : mAccessor(&acc), mTransform(&transform) {}
386 template<
typename RealType>
389 return this->isSample(Vec3d(x,y,z));
400 return this->isSample(
Coord(i,j,k));
412 SamplerType::sample(*mAccessor, ispoint, result);
421 SamplerType::sample(*mAccessor, mTransform->worldToIndex(wspoint), result);
426 const AccessorType* mAccessor;
443template<
typename GridOrTreeT,
458 : mSourceTree(&(sourceGrid.tree()))
459 , mSourceXform(&(sourceGrid.transform()))
460 , mTargetXform(&targetXform)
461 , mAligned(targetXform == *mSourceXform)
471 : mSourceTree(&sourceTree)
472 , mSourceXform(&sourceXform)
473 , mTargetXform(&targetXform)
474 , mAligned(targetXform == sourceXform)
481 if (mAligned)
return mSourceTree->getValue(ijk);
482 const Vec3R world = mTargetXform->indexToWorld(ijk);
483 return SamplerT::sample(*mSourceTree, mSourceXform->worldToIndex(world));
488 const TreeType* mSourceTree;
495template<
typename TreeT,
512 : mSourceAcc(&sourceAccessor)
513 , mSourceXform(&sourceXform)
514 , mTargetXform(&targetXform)
515 , mAligned(targetXform == sourceXform)
522 if (mAligned)
return mSourceAcc->getValue(ijk);
523 const Vec3R world = mTargetXform->indexToWorld(ijk);
524 return SamplerT::sample(*mSourceAcc, mSourceXform->worldToIndex(world));
529 const AccessorType* mSourceAcc;
539template <
typename GridT,
542 typename FloatT =
float>
546 static_assert(std::is_floating_point<FloatT>::value,
547 "AlphaMask requires a floating-point value type");
553 AlphaMask(
const GridT& grid,
const MaskT& mask, FloatT min, FloatT max,
bool invert)
555 , mSampler(mAcc, mask.transform() , grid.transform())
557 , mInvNorm(1/(max-min))
565 a = math::SmoothUnitStep( (mSampler(xyz) - mMin) * mInvNorm );
567 if (mInvert) std::swap(a,b);
572 using AccT =
typename MaskType::ConstAccessor;
581namespace local_util {
586 return Vec3i(
int(std::floor(v(0))),
int(std::floor(v(1))),
int(std::floor(v(2))));
593 return Vec3i(
int(std::ceil(v(0))),
int(std::ceil(v(1))),
int(std::ceil(v(2))));
600 return Vec3i(
int(::round(v(0))),
int(::round(v(1))),
int(::round(v(2))));
611PointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
612 typename TreeT::ValueType& result)
614 return inTree.probeValue(
Coord(local_util::roundVec3(inCoord)), result);
618inline typename TreeT::ValueType
619PointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
621 return inTree.getValue(
Coord(local_util::roundVec3(inCoord)));
627template<
class ValueT,
class TreeT,
size_t N>
629BoxSampler::getValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk)
631 data[0][0][0] = inTree.getValue(ijk);
634 data[0][0][1] = inTree.getValue(ijk);
637 data[0][1][1] = inTree.getValue(ijk);
640 data[0][1][0] = inTree.getValue(ijk);
644 data[1][0][0] = inTree.getValue(ijk);
647 data[1][0][1] = inTree.getValue(ijk);
650 data[1][1][1] = inTree.getValue(ijk);
653 data[1][1][0] = inTree.getValue(ijk);
656template<
class ValueT,
class TreeT,
size_t N>
658BoxSampler::probeValues(ValueT (&data)[N][N][N],
const TreeT& inTree,
Coord ijk)
660 bool hasActiveValues =
false;
661 hasActiveValues |= inTree.probeValue(ijk, data[0][0][0]);
664 hasActiveValues |= inTree.probeValue(ijk, data[0][0][1]);
667 hasActiveValues |= inTree.probeValue(ijk, data[0][1][1]);
670 hasActiveValues |= inTree.probeValue(ijk, data[0][1][0]);
674 hasActiveValues |= inTree.probeValue(ijk, data[1][0][0]);
677 hasActiveValues |= inTree.probeValue(ijk, data[1][0][1]);
680 hasActiveValues |= inTree.probeValue(ijk, data[1][1][1]);
683 hasActiveValues |= inTree.probeValue(ijk, data[1][1][0]);
685 return hasActiveValues;
688template<
class ValueT,
size_t N>
690BoxSampler::extrema(ValueT (&data)[N][N][N], ValueT& vMin, ValueT &vMax)
692 vMin = vMax = data[0][0][0];
693 vMin = math::Min(vMin, data[0][0][1]);
694 vMax = math::Max(vMax, data[0][0][1]);
695 vMin = math::Min(vMin, data[0][1][0]);
696 vMax = math::Max(vMax, data[0][1][0]);
697 vMin = math::Min(vMin, data[0][1][1]);
698 vMax = math::Max(vMax, data[0][1][1]);
699 vMin = math::Min(vMin, data[1][0][0]);
700 vMax = math::Max(vMax, data[1][0][0]);
701 vMin = math::Min(vMin, data[1][0][1]);
702 vMax = math::Max(vMax, data[1][0][1]);
703 vMin = math::Min(vMin, data[1][1][0]);
704 vMax = math::Max(vMax, data[1][1][0]);
705 vMin = math::Min(vMin, data[1][1][1]);
706 vMax = math::Max(vMax, data[1][1][1]);
710template<
class ValueT,
size_t N>
712BoxSampler::trilinearInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw)
714 auto _interpolate = [](
const ValueT& a,
const ValueT& b,
double weight)
717 const auto temp = (b - a) * weight;
719 return static_cast<ValueT
>(a + ValueT(temp));
730 _interpolate(data[0][0][0], data[0][0][1], uvw[2]),
731 _interpolate(data[0][1][0], data[0][1][1], uvw[2]),
734 _interpolate(data[1][0][0], data[1][0][1], uvw[2]),
735 _interpolate(data[1][1][0], data[1][1][1], uvw[2]),
743BoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
744 typename TreeT::ValueType& result)
746 using ValueT =
typename TreeT::ValueType;
748 const Vec3i inIdx = local_util::floorVec3(inCoord);
749 const Vec3R uvw = inCoord - inIdx;
753 ValueT data[2][2][2];
755 const bool hasActiveValues = BoxSampler::probeValues(data, inTree,
Coord(inIdx));
757 result = BoxSampler::trilinearInterpolation(data, uvw);
759 return hasActiveValues;
764inline typename TreeT::ValueType
765BoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
767 using ValueT =
typename TreeT::ValueType;
769 const Vec3i inIdx = local_util::floorVec3(inCoord);
770 const Vec3R uvw = inCoord - inIdx;
774 ValueT data[2][2][2];
776 BoxSampler::getValues(data, inTree,
Coord(inIdx));
778 return BoxSampler::trilinearInterpolation(data, uvw);
784template<
class ValueT,
size_t N>
786QuadraticSampler::triquadraticInterpolation(ValueT (&data)[N][N][N],
const Vec3R& uvw)
788 auto _interpolate = [](
const ValueT* value,
double weight)
792 a =
static_cast<ValueT
>(0.5 * (value[0] + value[2]) - value[1]),
793 b =
static_cast<ValueT
>(0.5 * (value[2] - value[0])),
794 c =
static_cast<ValueT
>(value[1]);
795 const auto temp = weight * (weight * a + b) + c;
797 return static_cast<ValueT
>(temp);
802 for (
int dx = 0; dx < 3; ++dx) {
804 for (
int dy = 0; dy < 3; ++dy) {
815 const ValueT* vz = &data[dx][dy][0];
816 vy[dy] = _interpolate(vz, uvw.
z());
821 vx[dx] = _interpolate(vy, uvw.
y());
825 return _interpolate(vx, uvw.
x());
830QuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
831 typename TreeT::ValueType& result)
833 using ValueT =
typename TreeT::ValueType;
835 const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx - Vec3i(1, 1, 1);
836 const Vec3R uvw = inCoord - inIdx;
841 ValueT data[3][3][3];
842 for (
int dx = 0, ix = inLoIdx.x(); dx < 3; ++dx, ++ix) {
843 for (
int dy = 0, iy = inLoIdx.y(); dy < 3; ++dy, ++iy) {
844 for (
int dz = 0, iz = inLoIdx.z(); dz < 3; ++dz, ++iz) {
845 if (inTree.probeValue(
Coord(ix, iy, iz), data[dx][dy][dz])) active =
true;
850 result = QuadraticSampler::triquadraticInterpolation(data, uvw);
856inline typename TreeT::ValueType
857QuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
859 using ValueT =
typename TreeT::ValueType;
861 const Vec3i inIdx = local_util::floorVec3(inCoord), inLoIdx = inIdx - Vec3i(1, 1, 1);
862 const Vec3R uvw = inCoord - inIdx;
866 ValueT data[3][3][3];
867 for (
int dx = 0, ix = inLoIdx.x(); dx < 3; ++dx, ++ix) {
868 for (
int dy = 0, iy = inLoIdx.y(); dy < 3; ++dy, ++iy) {
869 for (
int dz = 0, iz = inLoIdx.z(); dz < 3; ++dz, ++iz) {
870 data[dx][dy][dz] = inTree.getValue(
Coord(ix, iy, iz));
875 return QuadraticSampler::triquadraticInterpolation(data, uvw);
884StaggeredPointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
885 typename TreeT::ValueType& result)
887 using ValueType =
typename TreeT::ValueType;
889 ValueType tempX, tempY, tempZ;
892 active = PointSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.5, 0, 0), tempX) || active;
893 active = PointSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0, 0.5, 0), tempY) || active;
894 active = PointSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0, 0, 0.5), tempZ) || active;
896 result.x() = tempX.x();
897 result.y() = tempY.y();
898 result.z() = tempZ.z();
904inline typename TreeT::ValueType
905StaggeredPointSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
907 using ValueT =
typename TreeT::ValueType;
909 const ValueT tempX = PointSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.5, 0.0, 0.0));
910 const ValueT tempY = PointSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.0, 0.5, 0.0));
911 const ValueT tempZ = PointSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.0, 0.0, 0.5));
913 return ValueT(tempX.x(), tempY.y(), tempZ.z());
922StaggeredBoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
923 typename TreeT::ValueType& result)
925 using ValueType =
typename TreeT::ValueType;
927 ValueType tempX, tempY, tempZ;
928 tempX = tempY = tempZ = zeroVal<ValueType>();
931 active = BoxSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.5, 0, 0), tempX) || active;
932 active = BoxSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0, 0.5, 0), tempY) || active;
933 active = BoxSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0, 0, 0.5), tempZ) || active;
935 result.x() = tempX.x();
936 result.y() = tempY.y();
937 result.z() = tempZ.z();
943inline typename TreeT::ValueType
944StaggeredBoxSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
946 using ValueT =
typename TreeT::ValueType;
948 const ValueT tempX = BoxSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.5, 0.0, 0.0));
949 const ValueT tempY = BoxSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.0, 0.5, 0.0));
950 const ValueT tempZ = BoxSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.0, 0.0, 0.5));
952 return ValueT(tempX.x(), tempY.y(), tempZ.z());
961StaggeredQuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord,
962 typename TreeT::ValueType& result)
964 using ValueType =
typename TreeT::ValueType;
966 ValueType tempX, tempY, tempZ;
969 active = QuadraticSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.5, 0, 0), tempX) || active;
970 active = QuadraticSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0, 0.5, 0), tempY) || active;
971 active = QuadraticSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0, 0, 0.5), tempZ) || active;
973 result.x() = tempX.x();
974 result.y() = tempY.y();
975 result.z() = tempZ.z();
981inline typename TreeT::ValueType
982StaggeredQuadraticSampler::sample(
const TreeT& inTree,
const Vec3R& inCoord)
984 using ValueT =
typename TreeT::ValueType;
986 const ValueT tempX = QuadraticSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.5, 0.0, 0.0));
987 const ValueT tempY = QuadraticSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.0, 0.5, 0.0));
988 const ValueT tempZ = QuadraticSampler::sample<TreeT>(inTree, inCoord +
Vec3R(0.0, 0.0, 0.5));
990 return ValueT(tempX.x(), tempY.y(), tempZ.z());
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:25
Int32 ValueType
Definition Coord.h:32
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition Vec3.h:85
T & y()
Definition Vec3.h:86
T & z()
Definition Vec3.h:87
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:212