7#ifndef OPENVDB_TOOLS_GRIDTRANSFORMER_HAS_BEEN_INCLUDED 
    8#define OPENVDB_TOOLS_GRIDTRANSFORMER_HAS_BEEN_INCLUDED 
   20#include <tbb/blocked_range.h> 
   21#include <tbb/parallel_reduce.h> 
   53template<
typename Sampler, 
typename Interrupter, 
typename Gr
idType>
 
   55resampleToMatch(
const GridType& inGrid, GridType& outGrid, Interrupter& interrupter);
 
   78template<
typename Sampler, 
typename Gr
idType>
 
   92template<
typename Sampler, 
typename TreeT>
 
   93class TileSampler: 
public Sampler
 
   96    using ValueT = 
typename TreeT::ValueType;
 
  101    TileSampler(
const CoordBBox& b, 
const ValueT& tileVal, 
bool on):
 
  102        mBBox(b.
min().asVec3d(), b.
max().asVec3d()), mVal(tileVal), mActive(on), mEmpty(false)
 
  104        mBBox.expand(-this->radius()); 
 
  105        mEmpty = mBBox.empty();
 
  108    bool sample(
const TreeT& inTree, 
const Vec3R& inCoord, ValueT& result)
 const 
  110        if (!mEmpty && mBBox.isInside(inCoord)) { result = mVal; 
return mActive; }
 
  111        return Sampler::sample(inTree, inCoord, result);
 
  117    bool mActive, mEmpty;
 
  123template<
typename TreeT>
 
  124class TileSampler<PointSampler, TreeT>: 
public PointSampler {
 
  126    TileSampler(
const CoordBBox&, 
const typename TreeT::ValueType&, 
bool) {}
 
  131template<
typename TreeT>
 
  132class TileSampler<StaggeredPointSampler, TreeT>: 
public StaggeredPointSampler {
 
  134    TileSampler(
const CoordBBox&, 
const typename TreeT::ValueType&, 
bool) {}
 
  186    template<
typename InterrupterType> 
void setInterrupter(InterrupterType&);
 
  188    template<
typename Sampler, 
typename Gr
idT, 
typename Transformer>
 
  189    void transformGrid(
const Transformer&,
 
  190        const GridT& inGrid, GridT& 
outGrid) 
const;
 
  193    template<
typename Sampler, 
typename Gr
idT, 
typename Transformer>
 
  194    void applyTransform(
const Transformer&, 
const GridT& inGrid, GridT& 
outGrid) 
const;
 
  196    bool interrupt()
 const { 
return mInterrupt && mInterrupt(); }
 
  199    template<
typename Sampler, 
typename InTreeT, 
typename OutTreeT, 
typename Transformer>
 
  200    static void transformBBox(
const Transformer&, 
const CoordBBox& inBBox,
 
  201        const InTreeT& inTree, 
OutTreeT& outTree, 
const InterruptFunc&,
 
  204    template<
typename Sampler, 
typename TreeT, 
typename Transformer>
 
  205    class RangeProcessor;
 
  207    bool mThreaded, mTransformTiles;
 
  208    InterruptFunc mInterrupt;
 
 
  243        const Vec3R& translate,
 
  244        const std::string& xformOrder = 
"tsr",
 
  245        const std::string& rotationOrder = 
"zyx");
 
  253    template<
class Sampler, 
class Gr
idT>
 
  254    void transformGrid(
const GridT& inGrid, GridT& 
outGrid) 
const;
 
  257    struct MatrixTransform;
 
  259    inline void init(
const Vec3R& pivot, 
const Vec3R& scale,
 
  261        const std::string& xformOrder, 
const std::string& rotOrder);
 
  265    Mat4R mTransform, mPreScaleTransform, mPostScaleTransform;
 
 
  298    const bool hasUniformScale = unsignedScale.
eq(
math::Vec3<T>(unsignedScale[0]));
 
  300    bool hasRotation = 
false;
 
  301    bool validDecomposition = 
false;
 
  303    T minAngle = std::numeric_limits<T>::max();
 
  307    for (
size_t n = 0; n < 8; ++n) {
 
  309            n & 0x1 ? -unsignedScale.
x() : unsignedScale.
x(),
 
  310            n & 0x2 ? -unsignedScale.
y() : unsignedScale.
y(),
 
  311            n & 0x4 ? -unsignedScale.
z() : unsignedScale.
z());
 
  315        if (mat.
det() < T(0.0)) 
continue; 
 
  325        if (xform.
eq(rebuild)) {
 
  327            const T maxAngle = std::max(std::abs(tmpAngle[0]),
 
  328                std::max(std::abs(tmpAngle[1]), std::abs(tmpAngle[2])));
 
  330            if (!(minAngle < maxAngle)) { 
 
  337                validDecomposition = 
true;
 
  339                if (hasUniformScale || !hasRotation) {
 
  347    if (!validDecomposition) {
 
  351    if (hasRotation && !hasUniformScale) {
 
 
 
  397        mIsAffine(mAXform.isLinear() && mBXform.isLinear()),
 
  398        mIsIdentity(mIsAffine && mAXform == mBXform)
 
 
  407        return mBXform.worldToIndex(mAXform.indexToWorld(pos));
 
 
  412        return mAXform.worldToIndex(mBXform.indexToWorld(pos));
 
 
  420    const bool mIsAffine;
 
  421    const bool mIsIdentity;
 
 
  431template<
typename Sampler, 
typename Interrupter, 
typename Gr
idType>
 
  440        outGrid.setTree(inGrid.tree().copy());
 
  446            ( xform.
getB().baseMap()->getAffineMap()->getMat4().inverse() );
 
 
  464template<
typename ValueType>
 
  466    static ValueType 
eval(
const ValueType& background, 
const Vec3d& voxelSize)
 
  469        ValueType result(background * (1.0 / voxelSize[0]));
 
 
 
  484template<
typename Sampler, 
typename Interrupter, 
typename Gr
idType>
 
  491        if (inGrid.constTransform() == 
outGrid.constTransform()) {
 
  494            outGrid.setTree(inGrid.tree().copy());
 
  500        using ValueT = 
typename GridType::ValueType;
 
  503        const ValueT halfWidth = outIsLevelSet
 
  507        typename GridType::Ptr tempGrid;
 
  510                halfWidth, halfWidth,
 
  511                &
outGrid.constTransform(), &interrupter);
 
  519            outGrid.setTree(tempGrid->treePtr());
 
 
  529template<
typename Sampler, 
typename Gr
idType>
 
  546    mPreScaleTransform(
Mat4R::identity()),
 
  547    mPostScaleTransform(
Mat4R::identity())
 
  549    Vec3R scale, rotate, translate;
 
  553        init(mPivot, scale, rotate, translate, 
"rst", 
"zyx");
 
 
  562    const std::string& xformOrder, 
const std::string& rotOrder):
 
  565    mPreScaleTransform(
Mat4R::identity()),
 
  566    mPostScaleTransform(
Mat4R::identity())
 
  568    init(pivot, scale, rotate, translate, xformOrder, rotOrder);
 
 
  576GridTransformer::init(
 
  579    const std::string& xformOrder, 
const std::string& rotOrder)
 
  581    if (xformOrder.size() != 3) {
 
  584    if (rotOrder.size() != 3) {
 
  593    Vec3R scaleRemainder = scale;
 
  594    for (
int i = 0; i < 3; ++i) {
 
  595        double s = std::fabs(scale(i));
 
  597            mMipLevels(i) = int(std::floor(-std::log(s)/std::log(2.0)));
 
  598            scaleRemainder(i) = scale(i) * (1 << mMipLevels(i));
 
  607    mTransform = mPreScaleTransform = mPostScaleTransform = 
Mat4R::identity();
 
  608    Mat4R* remainder = &mPostScaleTransform;
 
  609    int rpos, spos, tpos;
 
  610    rpos = spos = tpos = 3;
 
  611    for (
int ix = 2; ix >= 0; --ix) { 
 
  612        switch (xformOrder[ix]) {
 
  616            mTransform.preTranslate(pivot);
 
  617            remainder->preTranslate(pivot);
 
  619            int xpos, ypos, zpos;
 
  620            xpos = ypos = zpos = 3;
 
  621            for (
int ir = 2; ir >= 0; --ir) {
 
  622                switch (rotOrder[ir]) {
 
  642            if (xpos > 2 || ypos > 2 || zpos > 2) {
 
  643                OPENVDB_THROW(ValueError, 
"invalid rotation order (" + rotOrder + 
")");
 
  646            mTransform.preTranslate(-pivot);
 
  647            remainder->preTranslate(-pivot);
 
  652            mTransform.preTranslate(pivot);
 
  653            mTransform.preScale(scale);
 
  654            mTransform.preTranslate(-pivot);
 
  656            remainder->preTranslate(pivot);
 
  657            remainder->preScale(scaleRemainder);
 
  658            remainder->preTranslate(-pivot);
 
  659            remainder = &mPreScaleTransform;
 
  664            mTransform.preTranslate(translate);
 
  665            remainder->preTranslate(translate);
 
  671    if (tpos > 2 || rpos > 2 || spos > 2) {
 
  672        OPENVDB_THROW(ValueError, 
"invalid transform order (" + xformOrder + 
")");
 
  680template<
typename InterrupterType>
 
  684    mInterrupt = std::bind(&InterrupterType::wasInterrupted,
 
 
  689template<
typename Sampler, 
typename Gr
idT, 
typename Transformer>
 
  692    const GridT& inGrid, GridT& 
outGrid)
 const 
 
  699template<
class Sampler, 
class Gr
idT>
 
  711        bool firstPass = 
true;
 
  712        const typename GridT::ValueType background = inGrid.background();
 
  713        typename GridT::Ptr tempGrid = GridT::create(background);
 
  725        Vec3i count = mMipLevels; 
 
  730                count.
x() ? .5 : 1, count.
y() ? .5 : 1, count.
z() ? .5 : 1));
 
  741                typename GridT::Ptr destGrid = GridT::create(background);
 
  743                tempGrid.swap(destGrid);
 
  754            outGrid.setTree(tempGrid->treePtr());
 
 
  763template<
class Sampler, 
class TreeT, 
typename Transformer>
 
  764class GridResampler::RangeProcessor
 
  767    using LeafIterT = 
typename TreeT::LeafCIter;
 
  768    using TileIterT = 
typename TreeT::ValueAllCIter;
 
  774    RangeProcessor(
const Transformer& xform, 
const CoordBBox& b, 
const TreeT& inT, TreeT& outT):
 
  775        mIsRoot(true), mXform(xform), mBBox(b),
 
  776        mInTree(inT), mOutTree(&outT), mInAcc(mInTree), mOutAcc(*mOutTree)
 
  779    RangeProcessor(
const Transformer& xform, 
const CoordBBox& b, 
const TreeT& inTree):
 
  780        mIsRoot(false), mXform(xform), mBBox(b),
 
  781        mInTree(inTree), mOutTree(new TreeT(inTree.background())),
 
  782        mInAcc(mInTree), mOutAcc(*mOutTree)
 
  785    ~RangeProcessor() { 
if (!mIsRoot) 
delete mOutTree; }
 
  788    RangeProcessor(RangeProcessor& other, tbb::split):
 
  790        mXform(other.mXform),
 
  792        mInTree(other.mInTree),
 
  793        mOutTree(new TreeT(mInTree.background())),
 
  796        mInterrupt(other.mInterrupt)
 
  799    void setInterrupt(
const InterruptFunc& f) { mInterrupt = f; }
 
  802    void operator()(
const LeafRange& r)
 
  804        for (LeafRange it(r); it.test(); ++it) {
 
  805            if (interrupt()) 
break;
 
  806            LeafIterT i = it.iterator();
 
  807            CoordBBox bbox(i->origin(), i->origin() + Coord(i->dim()));
 
  808            if (!mBBox.empty()) {
 
  815                transformBBox<Sampler>(mXform, bbox, mInAcc, mOutAcc, mInterrupt);
 
  821    void operator()(
const TileRange& r)
 
  823        for (TileRange it(r); it.test(); ++it) {
 
  824            if (interrupt()) 
break;
 
  826            TileIterT i = it.iterator();
 
  828            if (!i.isTileValue()) 
continue;
 
  832            i.getBoundingBox(bbox);
 
  833            if (!mBBox.empty()) {
 
  844                internal::TileSampler<Sampler, InTreeAccessor>
 
  845                    sampler(bbox, i.getValue(), i.isValueOn());
 
  846                transformBBox(mXform, bbox, mInAcc, mOutAcc, mInterrupt, sampler);
 
  852    void join(RangeProcessor& other)
 
  854        if (!interrupt()) mOutTree->merge(*other.mOutTree);
 
  858    bool interrupt()
 const { 
return mInterrupt && mInterrupt(); }
 
  863    const TreeT& mInTree;
 
  865    InTreeAccessor mInAcc;
 
  866    OutTreeAccessor mOutAcc;
 
  874template<
class Sampler, 
class Gr
idT, 
typename Transformer>
 
  877    const GridT& inGrid, GridT& 
outGrid)
 const 
  879    using TreeT = 
typename GridT::TreeType;
 
  880    const TreeT& inTree = inGrid.tree();
 
  881    TreeT& outTree = 
outGrid.tree();
 
  883    using RangeProc = RangeProcessor<Sampler, TreeT, Transformer>;
 
  885    const GridClass gridClass = inGrid.getGridClass();
 
  893        proc.setInterrupt(mInterrupt);
 
  895        typename RangeProc::TileIterT tileIter = inTree.cbeginValueAll();
 
  896        tileIter.setMaxDepth(tileIter.getLeafDepth() - 1); 
 
  897        typename RangeProc::TileRange tileRange(tileIter);
 
  900            tbb::parallel_reduce(tileRange, 
proc);
 
  910        clipBBox = inGrid.evalActiveVoxelBoundingBox();
 
  915    RangeProc 
proc(xform, clipBBox, inTree, outTree);
 
  916    proc.setInterrupt(mInterrupt);
 
  918    typename RangeProc::LeafRange leafRange(inTree.cbeginLeaf());
 
  921        tbb::parallel_reduce(leafRange, 
proc);
 
 
  938template<
class Sampler, 
class InTreeT, 
class OutTreeT, 
class Transformer>
 
  940GridResampler::transformBBox(
 
  941    const Transformer& xform,
 
  943    const InTreeT& inTree,
 
  945    const InterruptFunc& interrupt,
 
  948    using ValueT = 
typename OutTreeT::ValueType;
 
  954        inRMax(bbox.
max().
x()+1, bbox.
max().
y()+1, bbox.
max().
z()+1),
 
  957    for (
int i = 0; i < 8; ++i) {
 
  959            i & 1 ? inRMax.x() : inRMin.x(),
 
  960            i & 2 ? inRMax.y() : inRMin.y(),
 
  961            i & 4 ? inRMax.z() : inRMin.z());
 
  969    if (!xform.isAffine()) {
 
  974        int &x = outXYZ.
x(), &y = outXYZ.
y(), &z = outXYZ.
z();
 
  975        for (x = outMin.
x(); x <= outMax.x(); ++x) {
 
  978            for (y = outMin.
y(); y <= outMax.y(); ++y) {
 
  981                for (z = outMin.
z(); z <= outMax.z(); ++z) {
 
  983                    inXYZ = xform.invTransform(xyz);
 
  985                    if (sampler.
sample(inTree, inXYZ, result)) {
 
  986                        outTree.setValueOn(outXYZ, result);
 
  989                        if (!outTree.isValueOn(outXYZ)) {
 
  990                            outTree.setValueOff(outXYZ, result);
 
 1000            translation = xform.invTransform(
Vec3R(0, 0, 0)),
 
 1001            deltaX = xform.invTransform(
Vec3R(1, 0, 0)) - translation,
 
 1002            deltaY = xform.invTransform(
Vec3R(0, 1, 0)) - translation,
 
 1003            deltaZ = xform.invTransform(
Vec3R(0, 0, 1)) - translation;
 
 1009        const Vec3R dummy = deltaX;
 
 1014        Vec3R inStartX = xform.invTransform(
Vec3R(outMin));
 
 1016        int &x = outXYZ.
x(), &y = outXYZ.y(), &z = outXYZ.z();
 
 1017        for (x = outMin.
x(); x <= outMax.x(); ++x, inStartX += deltaX) {
 
 1019            Vec3R inStartY = inStartX;
 
 1020            for (y = outMin.
y(); y <= outMax.y(); ++y, inStartY += deltaY) {
 
 1022                Vec3R inXYZ = inStartY;
 
 1023                for (z = outMin.
z(); z <= outMax.z(); ++z, inXYZ += deltaZ) {
 
 1025                    if (sampler.
sample(inTree, inXYZ, result)) {
 
 1026                        outTree.setValueOn(outXYZ, result);
 
 1029                        if (!outTree.isValueOn(outXYZ)) {
 
 1030                            outTree.setValueOff(outXYZ, result);
 
 1045#ifdef OPENVDB_USE_EXPLICIT_INSTANTIATION 
 1047#ifdef OPENVDB_INSTANTIATE_GRIDTRANSFORMER 
 1051#define _FUNCTION(TreeT) \ 
 1052    void resampleToMatch<PointSampler>(const Grid<TreeT>&, Grid<TreeT>&, util::NullInterrupter&) 
 1056#define _FUNCTION(TreeT) \ 
 1057    void resampleToMatch<BoxSampler>(const Grid<TreeT>&, Grid<TreeT>&, util::NullInterrupter&) 
 1061#define _FUNCTION(TreeT) \ 
 1062    void resampleToMatch<QuadraticSampler>(const Grid<TreeT>&, Grid<TreeT>&, util::NullInterrupter&) 
 1066#define _FUNCTION(TreeT) \ 
 1067    void resampleToMatch<QuadraticSampler>(const Grid<TreeT>&, Grid<TreeT>&, util::NullInterrupter&) 
Efficient multi-threaded replacement of the background values in tree.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
Defined various multi-threaded utility functions for trees.
Propagate the signs of distance values from the active voxels in the narrow band to the inactive valu...
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition Coord.h:176
void maxComponent(const Coord &other)
Perform a component-wise maximum with the other Coord.
Definition Coord.h:184
Definition Exceptions.h:64
Definition Exceptions.h:65
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:252
const Coord & min() const
Definition Coord.h:324
const Coord & max() const
Definition Coord.h:325
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:26
Int32 y() const
Definition Coord.h:132
Int32 x() const
Definition Coord.h:131
Int32 z() const
Definition Coord.h:133
3x3 matrix class.
Definition Mat3.h:29
bool eq(const Mat3 &m, T eps=1.0e-8) const
Return true if this matrix is equivalent to m within a tolerance of eps.
Definition Mat3.h:301
T det() const
Determinant of matrix.
Definition Mat3.h:479
4x4 -matrix class.
Definition Mat4.h:31
void preScale(const Vec3< T0 > &v)
Definition Mat4.h:736
Vec3< T > getTranslation() const
Return the translation component.
Definition Mat4.h:309
void preTranslate(const Vec3< T0 > &tr)
Left multiples by the specified translation, i.e. Trans * (*this)
Definition Mat4.h:703
Mat4 inverse(T tolerance=0) const
Definition Mat4.h:485
Mat3< T > getMat3() const
Definition Mat4.h:297
static const Mat4< Real > & identity()
Definition Mat4.h:117
void setTranslation(const Vec3< T > &t)
Definition Mat4.h:314
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition Vec3.h:86
bool eq(const Vec3< T > &v, T eps=static_cast< T >(1.0e-7)) const
Test if "this" vector is equivalent to vector v with tolerance of eps.
Definition Vec3.h:134
T & y()
Definition Vec3.h:87
T & z()
Definition Vec3.h:88
static Vec3< T > zero()
Predefined constants, e.g. Vec3d v = Vec3d::xNegAxis();.
Definition Vec3.h:467
Definition TreeIterator.h:1304
Vec3< typename MatType::value_type > eulerAngles(const MatType &mat, RotationOrder rotationOrder, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the Euler angles composing the given rotation matrix.
Definition Mat.h:333
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
Definition Math.h:406
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition Mat.h:615
Vec3< double > Vec3d
Definition Vec3.h:665
bool isAffine(const Mat4< T > &m)
Definition Mat4.h:1305
MatType rotation(const Quat< typename MatType::value_type > &q, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the rotation matrix specified by the given quaternion.
Definition Mat.h:172
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition Vec2.h:504
Vec3< int32_t > Vec3i
Definition Vec3.h:662
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition Vec2.h:513
@ Z_AXIS
Definition Math.h:904
@ X_AXIS
Definition Math.h:902
@ Y_AXIS
Definition Math.h:903
@ XYZ_ROTATION
Definition Math.h:909
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
GridClass
Definition Types.h:453
@ GRID_LEVEL_SET
Definition Types.h:455
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:70
math::Mat4< Real > Mat4R
Definition Types.h:101
math::BBox< Vec3d > BBoxd
Definition Types.h:84
math::Vec3< Real > Vec3R
Definition Types.h:72
std::shared_ptr< T > SharedPtr
Definition Types.h:114
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Base class for interrupters.
Definition NullInterrupter.h:26
#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
#define OPENVDB_NUMERIC_TREE_INSTANTIATE(Function)
Definition version.h.in:163
#define OPENVDB_VEC3_TREE_INSTANTIATE(Function)
Definition version.h.in:164
#define OPENVDB_VOLUME_TREE_INSTANTIATE(Function)
Definition version.h.in:165