OpenVDB 3.2.0

GridTransformer.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2016 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 //
33
34 #ifndef OPENVDB_TOOLS_GRIDTRANSFORMER_HAS_BEEN_INCLUDED
35 #define OPENVDB_TOOLS_GRIDTRANSFORMER_HAS_BEEN_INCLUDED
36
37 #include <cmath>
38 #include <boost/bind.hpp>
39 #include <boost/function.hpp>
40 #include <boost/shared_ptr.hpp>
41 #include <tbb/blocked_range.h>
42 #include <tbb/parallel_reduce.h>
43 #include <openvdb/Grid.h>
44 #include <openvdb/Types.h>
45 #include <openvdb/math/Math.h> // for isApproxEqual()
46 #include <openvdb/util/NullInterrupter.h>
47 #include "ChangeBackground.h"
48 #include "Interpolation.h"
49 #include "LevelSetRebuild.h" // for doLevelSetRebuild()
50 #include "SignedFloodFill.h" // for signedFloodFill
51 #include "Prune.h" // for pruneLevelSet
52
53 namespace openvdb {
54 OPENVDB_USE_VERSION_NAMESPACE
55 namespace OPENVDB_VERSION_NAME {
56 namespace tools {
57
81 template<typename Sampler, typename Interrupter, typename GridType>
82 inline void
83 resampleToMatch(const GridType& inGrid, GridType& outGrid, Interrupter& interrupter);
84
106 template<typename Sampler, typename GridType>
107 inline void
108 resampleToMatch(const GridType& inGrid, GridType& outGrid);
109
110
112
113
114 namespace internal {
115
119 template<typename Sampler, typename TreeT>
120 class TileSampler: public Sampler
121 {
122 public:
123 typedef typename TreeT::ValueType ValueT;
124
128 TileSampler(const CoordBBox& b, const ValueT& tileVal, bool on):
129 mBBox(b.min().asVec3d(), b.max().asVec3d()), mVal(tileVal), mActive(on), mEmpty(false)
130 {
131 mBBox.expand(-this->radius()); // shrink the bounding box by the sample radius
132 mEmpty = mBBox.empty();
133 }
134
135 bool sample(const TreeT& inTree, const Vec3R& inCoord, ValueT& result) const
136 {
137 if (!mEmpty && mBBox.isInside(inCoord)) { result = mVal; return mActive; }
138 return Sampler::sample(inTree, inCoord, result);
139 }
140
141 protected:
142 BBoxd mBBox;
143 ValueT mVal;
144 bool mActive, mEmpty;
145 };
146
147
150 template<typename TreeT>
151 class TileSampler<PointSampler, TreeT>: public PointSampler {
152 public:
153 TileSampler(const CoordBBox&, const typename TreeT::ValueType&, bool) {}
154 };
155
158 template<typename TreeT>
159 class TileSampler<StaggeredPointSampler, TreeT>: public StaggeredPointSampler {
160 public:
161 TileSampler(const CoordBBox&, const typename TreeT::ValueType&, bool) {}
162 };
163
164 } // namespace internal
165
166
168
169
187 class GridResampler
188 {
189 public:
190 typedef boost::shared_ptr<GridResampler> Ptr;
191 typedef boost::function<bool (void)> InterruptFunc;
192
193 GridResampler(): mThreaded(true), mTransformTiles(true) {}
194 virtual ~GridResampler() {}
195
197 void setThreaded(bool b) { mThreaded = b; }
199 bool threaded() const { return mThreaded; }
201 void setTransformTiles(bool b) { mTransformTiles = b; }
203 bool transformTiles() const { return mTransformTiles; }
204
208 template<typename InterrupterType> void setInterrupter(InterrupterType&);
209
210 template<typename Sampler, typename GridT, typename Transformer>
211 void transformGrid(const Transformer&,
212 const GridT& inGrid, GridT& outGrid) const;
213
214 protected:
215 template<typename Sampler, typename GridT, typename Transformer>
216 void applyTransform(const Transformer&, const GridT& inGrid, GridT& outGrid) const;
217
218 bool interrupt() const { return mInterrupt && mInterrupt(); }
219
220 private:
221 template<typename Sampler, typename InTreeT, typename OutTreeT, typename Transformer>
222 static void transformBBox(const Transformer&, const CoordBBox& inBBox,
223 const InTreeT& inTree, OutTreeT& outTree, const InterruptFunc&,
224 const Sampler& = Sampler());
225
226 template<typename Sampler, typename TreeT, typename Transformer>
227 class RangeProcessor;
228
229 bool mThreaded, mTransformTiles;
230 InterruptFunc mInterrupt;
231 };
232
233
235
236
255 class GridTransformer: public GridResampler
256 {
257 public:
258 typedef boost::shared_ptr<GridTransformer> Ptr;
259
260 GridTransformer(const Mat4R& xform);
261 GridTransformer(
262 const Vec3R& pivot,
263 const Vec3R& scale,
264 const Vec3R& rotate,
265 const Vec3R& translate,
266 const std::string& xformOrder = "tsr",
267 const std::string& rotationOrder = "zyx");
268 virtual ~GridTransformer() {}
269
270 const Mat4R& getTransform() const { return mTransform; }
271
272 template<class Sampler, class GridT>
273 void transformGrid(const GridT& inGrid, GridT& outGrid) const;
274
275 private:
276 struct MatrixTransform;
277
278 inline void init(const Vec3R& pivot, const Vec3R& scale,
279 const Vec3R& rotate, const Vec3R& translate,
280 const std::string& xformOrder, const std::string& rotOrder);
281
282 Vec3R mPivot;
283 Vec3i mMipLevels;
284 Mat4R mTransform, mPreScaleTransform, mPostScaleTransform;
285 };
286
287
289
290
291 namespace local_util {
292
295 template<typename T>
296 inline bool
297 decompose(const math::Mat4<T>& m, math::Vec3<T>& scale,
298 math::Vec3<T>& rotate, math::Vec3<T>& translate)
299 {
300 if (!math::isAffine(m)) return false;
301
302 // This is the translation in world space
303 translate = m.getTranslation();
304 // Extract translation.
305 const math::Mat3<T> xform = m.getMat3();
306
307 const math::Vec3<T> unsignedScale(
308 (math::Vec3<T>(1, 0, 0) * xform).length(),
309 (math::Vec3<T>(0, 1, 0) * xform).length(),
310 (math::Vec3<T>(0, 0, 1) * xform).length());
311
312 const bool hasUniformScale = unsignedScale.eq(math::Vec3<T>(unsignedScale[0]));
313
314 bool hasRotation = false;
315 bool validDecomposition = false;
316
317 T minAngle = std::numeric_limits<T>::max();
318
319 // If the transformation matrix contains a reflection,
320 // test different negative scales to find a decomposition
321 // that favors the optimal resampling algorithm.
322 for (size_t n = 0; n < 8; ++n) {
323
324 const math::Vec3<T> signedScale(
325 n & 0x1 ? -unsignedScale.x() : unsignedScale.x(),
326 n & 0x2 ? -unsignedScale.y() : unsignedScale.y(),
327 n & 0x4 ? -unsignedScale.z() : unsignedScale.z());
328
329 // Extract scale and potentially reflection.
330 const math::Mat3<T> mat = xform * math::scale<math::Mat3<T> >(signedScale).inverse();
331 if (mat.det() < T(0.0)) continue; // Skip if mat contains a reflection.
332
333 const math::Vec3<T> tmpAngle = math::eulerAngles(mat, math::XYZ_ROTATION);
334
335 const math::Mat3<T> rebuild =
336 math::rotation<math::Mat3<T> >(math::Vec3<T>(1, 0, 0), tmpAngle.x()) *
337 math::rotation<math::Mat3<T> >(math::Vec3<T>(0, 1, 0), tmpAngle.y()) *
338 math::rotation<math::Mat3<T> >(math::Vec3<T>(0, 0, 1), tmpAngle.z()) *
339 math::scale<math::Mat3<T> >(signedScale);
340
341 if (xform.eq(rebuild)) {
342
343 const T maxAngle = std::max(std::abs(tmpAngle[0]),
344 std::max(std::abs(tmpAngle[1]), std::abs(tmpAngle[2])));
345
346 if (!(minAngle < maxAngle)) { // Update if less or equal.
347
348 minAngle = maxAngle;
349 rotate = tmpAngle;
350 scale = signedScale;
351
352 hasRotation = !rotate.eq(math::Vec3<T>::zero());
353 validDecomposition = true;
354
355 if (hasUniformScale || !hasRotation) {
356 // Current decomposition is optimal.
357 break;
358 }
359 }
360 }
361 }
362
363 if (!validDecomposition || (hasRotation && !hasUniformScale)) {
364 // The decomposition is invalid if the transformation matrix contains shear.
365 // No unique decomposition if scale is nonuniform and rotation is nonzero.
366 return false;
367 }
368
369 return true;
370 }
371
372 } // namespace local_util
373
374
376
377
381 struct GridTransformer::MatrixTransform
382 {
383 MatrixTransform(): mat(Mat4R::identity()), invMat(Mat4R::identity()) {}
384 MatrixTransform(const Mat4R& xform): mat(xform), invMat(xform.inverse()) {}
385
386 bool isAffine() const { return math::isAffine(mat); }
387
388 Vec3R transform(const Vec3R& pos) const { return mat.transformH(pos); }
389
390 Vec3R invTransform(const Vec3R& pos) const { return invMat.transformH(pos); }
391
392 Mat4R mat, invMat;
393 };
394
395
397
398
403 class ABTransform
404 {
405 public:
408 ABTransform(const math::Transform& aXform, const math::Transform& bXform):
409 mAXform(aXform),
410 mBXform(bXform),
411 mIsAffine(mAXform.isLinear() && mBXform.isLinear()),
412 mIsIdentity(mIsAffine && mAXform == mBXform)
413 {}
414
415 bool isAffine() const { return mIsAffine; }
416
417 bool isIdentity() const { return mIsIdentity; }
418
419 openvdb::Vec3R transform(const openvdb::Vec3R& pos) const
420 {
421 return mBXform.worldToIndex(mAXform.indexToWorld(pos));
422 }
423
424 openvdb::Vec3R invTransform(const openvdb::Vec3R& pos) const
425 {
426 return mAXform.worldToIndex(mBXform.indexToWorld(pos));
427 }
428
429 const math::Transform& getA() const { return mAXform; }
430 const math::Transform& getB() const { return mBXform; }
431
432 private:
433 const math::Transform &mAXform, &mBXform;
434 const bool mIsAffine;
435 const bool mIsIdentity;
436 };
437
438
445 template<typename Sampler, typename Interrupter, typename GridType>
446 inline void
447 doResampleToMatch(const GridType& inGrid, GridType& outGrid, Interrupter& interrupter)
448 {
449 ABTransform xform(inGrid.transform(), outGrid.transform());
450
451 if (Sampler::consistent() && xform.isIdentity()) {
452 // If the transforms of the input and output are identical, the
453 // output tree is simply a deep copy of the input tree.
454 outGrid.setTree(inGrid.tree().copy());
455 } else if (xform.isAffine()) {
456 // If the input and output transforms are both affine, create an
457 // input to output transform (in:index-to-world * out:world-to-index)
458 // and use the fast GridTransformer API.
459 Mat4R mat = xform.getA().baseMap()->getAffineMap()->getMat4() *
460 ( xform.getB().baseMap()->getAffineMap()->getMat4().inverse() );
461
462 GridTransformer transformer(mat);
463 transformer.setInterrupter(interrupter);
464
465 // Transform the input grid and store the result in the output grid.
466 transformer.transformGrid<Sampler>(inGrid, outGrid);
467 } else {
468 // If either the input or the output transform is non-affine,
469 // use the slower GridResampler API.
470 GridResampler resampler;
471 resampler.setInterrupter(interrupter);
472
473 resampler.transformGrid<Sampler>(xform, inGrid, outGrid);
474 }
475 }
476
477
478 template<typename Sampler, typename Interrupter, typename GridType>
479 inline void
480 resampleToMatch(const GridType& inGrid, GridType& outGrid, Interrupter& interrupter)
481 {
482 if (inGrid.getGridClass() == GRID_LEVEL_SET) {
483 // If the input grid is a level set, resample it using the level set rebuild tool.
484
485 if (inGrid.constTransform() == outGrid.constTransform()) {
486 // If the transforms of the input and output grids are identical,
487 // the output tree is simply a deep copy of the input tree.
488 outGrid.setTree(inGrid.tree().copy());
489 return;
490 }
491
492 // If the output grid is a level set, resample the input grid to have the output grid's
493 // background value. Otherwise, preserve the input grid's background value.
494 typedef typename GridType::ValueType ValueT;
495 const ValueT halfWidth = ((outGrid.getGridClass() == openvdb::GRID_LEVEL_SET)
496 ? ValueT(outGrid.background() * (1.0 / outGrid.voxelSize()[0]))
497 : ValueT(inGrid.background() * (1.0 / inGrid.voxelSize()[0])));
498
499 typename GridType::Ptr tempGrid;
500 try {
501 tempGrid = doLevelSetRebuild(inGrid, /*iso=*/zeroVal<ValueT>(),
502 /*exWidth=*/halfWidth, /*inWidth=*/halfWidth,
503 &outGrid.constTransform(), &interrupter);
504 } catch (TypeError&) {
505 // The input grid is classified as a level set, but it has a value type
506 // that is not supported by the level set rebuild tool. Fall back to
507 // using the generic resampler.
508 tempGrid.reset();
509 }
510 if (tempGrid) {
511 outGrid.setTree(tempGrid->treePtr());
512 return;
513 }
514 }
515
516 // If the input grid is not a level set, use the generic resampler.
517 doResampleToMatch<Sampler>(inGrid, outGrid, interrupter);
518 }
519
520
521 template<typename Sampler, typename GridType>
522 inline void
523 resampleToMatch(const GridType& inGrid, GridType& outGrid)
524 {
525 util::NullInterrupter interrupter;
526 resampleToMatch<Sampler>(inGrid, outGrid, interrupter);
527 }
528
529
531
532
533 inline
534 GridTransformer::GridTransformer(const Mat4R& xform):
535 mPivot(0, 0, 0),
536 mMipLevels(0, 0, 0),
537 mTransform(xform),
538 mPreScaleTransform(Mat4R::identity()),
539 mPostScaleTransform(Mat4R::identity())
540 {
541 Vec3R scale, rotate, translate;
542 if (local_util::decompose(mTransform, scale, rotate, translate)) {
543 // If the transform can be decomposed into affine components,
544 // use them to set up a mipmapping-like scheme for downsampling.
545 init(mPivot, scale, rotate, translate, "srt", "zyx");
546 }
547 }
548
549
550 inline
551 GridTransformer::GridTransformer(
552 const Vec3R& pivot, const Vec3R& scale,
553 const Vec3R& rotate, const Vec3R& translate,
554 const std::string& xformOrder, const std::string& rotOrder):
555 mPivot(0, 0, 0),
556 mMipLevels(0, 0, 0),
557 mPreScaleTransform(Mat4R::identity()),
558 mPostScaleTransform(Mat4R::identity())
559 {
560 init(pivot, scale, rotate, translate, xformOrder, rotOrder);
561 }
562
563
565
566
567 inline void
568 GridTransformer::init(
569 const Vec3R& pivot, const Vec3R& scale,
570 const Vec3R& rotate, const Vec3R& translate,
571 const std::string& xformOrder, const std::string& rotOrder)
572 {
573 if (xformOrder.size() != 3) {
574 OPENVDB_THROW(ValueError, "invalid transform order (" + xformOrder + ")");
575 }
576 if (rotOrder.size() != 3) {
577 OPENVDB_THROW(ValueError, "invalid rotation order (" + rotOrder + ")");
578 }
579
580 mPivot = pivot;
581
582 // Scaling is handled via a mipmapping-like scheme of successive
583 // halvings of the tree resolution, until the remaining scale
584 // factor is greater than or equal to 1/2.
585 Vec3R scaleRemainder = scale;
586 for (int i = 0; i < 3; ++i) {
587 double s = std::fabs(scale(i));
588 if (s < 0.5) {
589 mMipLevels(i) = int(std::floor(-std::log(s)/std::log(2.0)));
590 scaleRemainder(i) = scale(i) * (1 << mMipLevels(i));
591 }
592 }
593
594 // Build pre-scale and post-scale transform matrices based on
595 // the user-specified order of operations.
596 // Note that we iterate over the transform order string in reverse order
597 // (e.g., "t", "r", "s", given "srt"). This is because math::Mat matrices
598 // postmultiply row vectors rather than premultiplying column vectors.
599 mTransform = mPreScaleTransform = mPostScaleTransform = Mat4R::identity();
600 Mat4R* remainder = &mPostScaleTransform;
601 int rpos, spos, tpos;
602 rpos = spos = tpos = 3;
603 for (int ix = 2; ix >= 0; --ix) { // reverse iteration
604 switch (xformOrder[ix]) {
605
606 case 'r':
607 rpos = ix;
608 mTransform.preTranslate(pivot);
609 remainder->preTranslate(pivot);
610
611 int xpos, ypos, zpos;
612 xpos = ypos = zpos = 3;
613 for (int ir = 2; ir >= 0; --ir) {
614 switch (rotOrder[ir]) {
615 case 'x':
616 xpos = ir;
617 mTransform.preRotate(math::X_AXIS, rotate.x());
618 remainder->preRotate(math::X_AXIS, rotate.x());
619 break;
620 case 'y':
621 ypos = ir;
622 mTransform.preRotate(math::Y_AXIS, rotate.y());
623 remainder->preRotate(math::Y_AXIS, rotate.y());
624 break;
625 case 'z':
626 zpos = ir;
627 mTransform.preRotate(math::Z_AXIS, rotate.z());
628 remainder->preRotate(math::Z_AXIS, rotate.z());
629 break;
630 }
631 }
632 // Reject rotation order strings that don't contain exactly one
633 // instance of "x", "y" and "z".
634 if (xpos > 2 || ypos > 2 || zpos > 2) {
635 OPENVDB_THROW(ValueError, "invalid rotation order (" + rotOrder + ")");
636 }
637
638 mTransform.preTranslate(-pivot);
639 remainder->preTranslate(-pivot);
640 break;
641
642 case 's':
643 spos = ix;
644 mTransform.preTranslate(pivot);
645 mTransform.preScale(scale);
646 mTransform.preTranslate(-pivot);
647
648 remainder->preTranslate(pivot);
649 remainder->preScale(scaleRemainder);
650 remainder->preTranslate(-pivot);
651 remainder = &mPreScaleTransform;
652 break;
653
654 case 't':
655 tpos = ix;
656 mTransform.preTranslate(translate);
657 remainder->preTranslate(translate);
658 break;
659 }
660 }
661 // Reject transform order strings that don't contain exactly one
662 // instance of "t", "r" and "s".
663 if (tpos > 2 || rpos > 2 || spos > 2) {
664 OPENVDB_THROW(ValueError, "invalid transform order (" + xformOrder + ")");
665 }
666 }
667
668
670
671
672 template<typename InterrupterType>
673 void
674 GridResampler::setInterrupter(InterrupterType& interrupter)
675 {
676 mInterrupt = boost::bind(&InterrupterType::wasInterrupted,
677 /*this=*/&interrupter, /*percent=*/-1);
678 }
679
680
681 template<typename Sampler, typename GridT, typename Transformer>
682 void
683 GridResampler::transformGrid(const Transformer& xform,
684 const GridT& inGrid, GridT& outGrid) const
685 {
686 tools::changeBackground(outGrid.tree(), inGrid.background());
687 applyTransform<Sampler>(xform, inGrid, outGrid);
688 }
689
690
691 template<class Sampler, class GridT>
692 void
693 GridTransformer::transformGrid(const GridT& inGrid, GridT& outGrid) const
694 {
695 tools::changeBackground(outGrid.tree(), inGrid.background());
696
697 if (!Sampler::mipmap() || mMipLevels == Vec3i::zero()) {
698 // Skip the mipmapping step.
699 const MatrixTransform xform(mTransform);
700 applyTransform<Sampler>(xform, inGrid, outGrid);
701
702 } else {
703 bool firstPass = true;
704 const typename GridT::ValueType background = inGrid.background();
705 typename GridT::Ptr tempGrid = GridT::create(background);
706
707 if (!mPreScaleTransform.eq(Mat4R::identity())) {
708 firstPass = false;
709 // Apply the pre-scale transform to the input grid
710 // and store the result in a temporary grid.
711 const MatrixTransform xform(mPreScaleTransform);
712 applyTransform<Sampler>(xform, inGrid, *tempGrid);
713 }
714
715 // While the scale factor along one or more axes is less than 1/2,
716 // scale the grid by half along those axes.
717 Vec3i count = mMipLevels; // # of halvings remaining per axis
718 while (count != Vec3i::zero()) {
719 MatrixTransform xform;
720 xform.mat.setTranslation(mPivot);
721 xform.mat.preScale(Vec3R(
722 count.x() ? .5 : 1, count.y() ? .5 : 1, count.z() ? .5 : 1));
723 xform.mat.preTranslate(-mPivot);
724 xform.invMat = xform.mat.inverse();
725
726 if (firstPass) {
727 firstPass = false;
728 // Scale the input grid and store the result in a temporary grid.
729 applyTransform<Sampler>(xform, inGrid, *tempGrid);
730 } else {
731 // Scale the temporary grid and store the result in a transient grid,
732 // then swap the two and discard the transient grid.
733 typename GridT::Ptr destGrid = GridT::create(background);
734 applyTransform<Sampler>(xform, *tempGrid, *destGrid);
735 tempGrid.swap(destGrid);
736 }
737 // (3, 2, 1) -> (2, 1, 0) -> (1, 0, 0) -> (0, 0, 0), etc.
738 count = math::maxComponent(count - 1, Vec3i::zero());
739 }
740
741 // Apply the post-scale transform and store the result in the output grid.
742 if (!mPostScaleTransform.eq(Mat4R::identity())) {
743 const MatrixTransform xform(mPostScaleTransform);
744 applyTransform<Sampler>(xform, *tempGrid, outGrid);
745 } else {
746 outGrid.setTree(tempGrid->treePtr());
747 }
748 }
749 }
750
751
753
754
755 template<class Sampler, class TreeT, typename Transformer>
756 class GridResampler::RangeProcessor
757 {
758 public:
759 typedef typename TreeT::LeafCIter LeafIterT;
760 typedef typename TreeT::ValueAllCIter TileIterT;
761 typedef typename tree::IteratorRange<LeafIterT> LeafRange;
762 typedef typename tree::IteratorRange<TileIterT> TileRange;
763 typedef typename tree::ValueAccessor<const TreeT> InTreeAccessor;
764 typedef typename tree::ValueAccessor<TreeT> OutTreeAccessor;
765
766 RangeProcessor(const Transformer& xform, const CoordBBox& b, const TreeT& inT, TreeT& outT):
767 mIsRoot(true), mXform(xform), mBBox(b),
768 mInTree(inT), mOutTree(&outT), mInAcc(mInTree), mOutAcc(*mOutTree)
769 {}
770
771 RangeProcessor(const Transformer& xform, const CoordBBox& b, const TreeT& inTree):
772 mIsRoot(false), mXform(xform), mBBox(b),
773 mInTree(inTree), mOutTree(new TreeT(inTree.background())),
774 mInAcc(mInTree), mOutAcc(*mOutTree)
775 {}
776
777 ~RangeProcessor() { if (!mIsRoot) delete mOutTree; }
778
780 RangeProcessor(RangeProcessor& other, tbb::split):
781 mIsRoot(false),
782 mXform(other.mXform),
783 mBBox(other.mBBox),
784 mInTree(other.mInTree),
785 mOutTree(new TreeT(mInTree.background())),
786 mInAcc(mInTree),
787 mOutAcc(*mOutTree),
788 mInterrupt(other.mInterrupt)
789 {}
790
791 void setInterrupt(const InterruptFunc& f) { mInterrupt = f; }
792
794 void operator()(LeafRange& r)
795 {
796 for ( ; r; ++r) {
797 if (interrupt()) break;
798 LeafIterT i = r.iterator();
799 CoordBBox bbox(i->origin(), i->origin() + Coord(i->dim()));
800 if (!mBBox.empty()) {
801 // Intersect the leaf node's bounding box with mBBox.
802 bbox = CoordBBox(
803 Coord::maxComponent(bbox.min(), mBBox.min()),
804 Coord::minComponent(bbox.max(), mBBox.max()));
805 }
806 if (!bbox.empty()) {
807 transformBBox<Sampler>(mXform, bbox, mInAcc, mOutAcc, mInterrupt);
808 }
809 }
810 }
811
813 void operator()(TileRange& r)
814 {
815 for ( ; r; ++r) {
816 if (interrupt()) break;
817
818 TileIterT i = r.iterator();
819 // Skip voxels and background tiles.
820 if (!i.isTileValue()) continue;
821 if (!i.isValueOn() && math::isApproxEqual(*i, mOutTree->background())) continue;
822
823 CoordBBox bbox;
824 i.getBoundingBox(bbox);
825 if (!mBBox.empty()) {
826 // Intersect the tile's bounding box with mBBox.
827 bbox = CoordBBox(
828 Coord::maxComponent(bbox.min(), mBBox.min()),
829 Coord::minComponent(bbox.max(), mBBox.max()));
830 }
831 if (!bbox.empty()) {
836 internal::TileSampler<Sampler, InTreeAccessor>
837 sampler(bbox, i.getValue(), i.isValueOn());
838 transformBBox(mXform, bbox, mInAcc, mOutAcc, mInterrupt, sampler);
839 }
840 }
841 }
842
844 void join(RangeProcessor& other)
845 {
846 if (!interrupt()) mOutTree->merge(*other.mOutTree);
847 }
848
849 private:
850 bool interrupt() const { return mInterrupt && mInterrupt(); }
851
852 const bool mIsRoot; // true if mOutTree is the top-level tree
853 Transformer mXform;
854 CoordBBox mBBox;
855 const TreeT& mInTree;
856 TreeT* mOutTree;
857 InTreeAccessor mInAcc;
858 OutTreeAccessor mOutAcc;
859 InterruptFunc mInterrupt;
860 };
861
862
864
865
866 template<class Sampler, class GridT, typename Transformer>
867 void
868 GridResampler::applyTransform(const Transformer& xform,
869 const GridT& inGrid, GridT& outGrid) const
870 {
871 typedef typename GridT::TreeType TreeT;
872 const TreeT& inTree = inGrid.tree();
873 TreeT& outTree = outGrid.tree();
874
875 typedef RangeProcessor<Sampler, TreeT, Transformer> RangeProc;
876
877 const GridClass gridClass = inGrid.getGridClass();
878
879 if (gridClass != GRID_LEVEL_SET && mTransformTiles) {
880 // Independently transform the tiles of the input grid.
881 // Note: Tiles in level sets can only be background tiles, and they
882 // are handled more efficiently with a signed flood fill (see below).
883
884 RangeProc proc(xform, CoordBBox(), inTree, outTree);
885 proc.setInterrupt(mInterrupt);
886
887 typename RangeProc::TileIterT tileIter = inTree.cbeginValueAll();
888 tileIter.setMaxDepth(tileIter.getLeafDepth() - 1); // skip leaf nodes
889 typename RangeProc::TileRange tileRange(tileIter);
890
891 if (mThreaded) {
892 tbb::parallel_reduce(tileRange, proc);
893 } else {
894 proc(tileRange);
895 }
896 }
897
898 CoordBBox clipBBox;
899 if (gridClass == GRID_LEVEL_SET) {
900 // Inactive voxels in level sets can only be background voxels, and they
901 // are handled more efficiently with a signed flood fill (see below).
902 clipBBox = inGrid.evalActiveVoxelBoundingBox();
903 }
904
905 // Independently transform the leaf nodes of the input grid.
906
907 RangeProc proc(xform, clipBBox, inTree, outTree);
908 proc.setInterrupt(mInterrupt);
909
910 typename RangeProc::LeafRange leafRange(inTree.cbeginLeaf());
911
912 if (mThreaded) {
913 tbb::parallel_reduce(leafRange, proc);
914 } else {
915 proc(leafRange);
916 }
917
918 // If the grid is a level set, mark inactive voxels as inside or outside.
919 if (gridClass == GRID_LEVEL_SET) {
920 tools::pruneLevelSet(outTree);
921 tools::signedFloodFill(outTree);
922 }
923 }
924
925
927
928
929 //static
930 template<class Sampler, class InTreeT, class OutTreeT, class Transformer>
931 void
932 GridResampler::transformBBox(
933 const Transformer& xform,
934 const CoordBBox& bbox,
935 const InTreeT& inTree,
936 OutTreeT& outTree,
937 const InterruptFunc& interrupt,
938 const Sampler& sampler)
939 {
940 typedef typename OutTreeT::ValueType ValueT;
941
942 // Transform the corners of the input tree's bounding box
943 // and compute the enclosing bounding box in the output tree.
944 Vec3R
945 inRMin(bbox.min().x(), bbox.min().y(), bbox.min().z()),
946 inRMax(bbox.max().x(), bbox.max().y(), bbox.max().z()),
947 outRMin = math::minComponent(xform.transform(inRMin), xform.transform(inRMax)),
948 outRMax = math::maxComponent(xform.transform(inRMin), xform.transform(inRMax));
949 for (int i = 0; i < 8; ++i) {
950 Vec3R corner(
951 i & 1 ? inRMax.x() : inRMin.x(),
952 i & 2 ? inRMax.y() : inRMin.y(),
953 i & 4 ? inRMax.z() : inRMin.z());
954 outRMin = math::minComponent(outRMin, xform.transform(corner));
955 outRMax = math::maxComponent(outRMax, xform.transform(corner));
956 }
957 Vec3i
958 outMin = local_util::floorVec3(outRMin) - Sampler::radius(),
959 outMax = local_util::ceilVec3(outRMax) + Sampler::radius();
960
961 if (!xform.isAffine()) {
962 // If the transform is not affine, back-project each output voxel
963 // into the input tree.
964 Vec3R xyz, inXYZ;
965 Coord outXYZ;
966 int &x = outXYZ.x(), &y = outXYZ.y(), &z = outXYZ.z();
967 for (x = outMin.x(); x <= outMax.x(); ++x) {
968 if (interrupt && interrupt()) break;
969 xyz.x() = x;
970 for (y = outMin.y(); y <= outMax.y(); ++y) {
971 if (interrupt && interrupt()) break;
972 xyz.y() = y;
973 for (z = outMin.z(); z <= outMax.z(); ++z) {
974 xyz.z() = z;
975 inXYZ = xform.invTransform(xyz);
976 ValueT result;
977 if (sampler.sample(inTree, inXYZ, result)) {
978 outTree.setValueOn(outXYZ, result);
979 } else {
980 // Note: Don't overwrite existing active values with inactive values.
981 if (!outTree.isValueOn(outXYZ)) {
982 outTree.setValueOff(outXYZ, result);
983 }
984 }
985 }
986 }
987 }
988 } else { // affine
989 // Compute step sizes in the input tree that correspond to
990 // unit steps in x, y and z in the output tree.
991 const Vec3R
992 translation = xform.invTransform(Vec3R(0, 0, 0)),
993 deltaX = xform.invTransform(Vec3R(1, 0, 0)) - translation,
994 deltaY = xform.invTransform(Vec3R(0, 1, 0)) - translation,
995 deltaZ = xform.invTransform(Vec3R(0, 0, 1)) - translation;
996
997 #if defined(__ICC)
998 const Vec3R dummy = deltaX;
1002 #endif
1003
1004 // Step by whole voxels through the output tree, sampling the
1005 // corresponding fractional voxels of the input tree.
1006 Vec3R inStartX = xform.invTransform(Vec3R(outMin));
1007 Coord outXYZ;
1008 int &x = outXYZ.x(), &y = outXYZ.y(), &z = outXYZ.z();
1009 for (x = outMin.x(); x <= outMax.x(); ++x, inStartX += deltaX) {
1010 if (interrupt && interrupt()) break;
1011 Vec3R inStartY = inStartX;
1012 for (y = outMin.y(); y <= outMax.y(); ++y, inStartY += deltaY) {
1013 if (interrupt && interrupt()) break;
1014 Vec3R inXYZ = inStartY;
1015 for (z = outMin.z(); z <= outMax.z(); ++z, inXYZ += deltaZ) {
1016 ValueT result;
1017 if (sampler.sample(inTree, inXYZ, result)) {
1018 outTree.setValueOn(outXYZ, result);
1019 } else {
1020 // Note: Don't overwrite existing active values with inactive values.
1021 if (!outTree.isValueOn(outXYZ)) {
1022 outTree.setValueOff(outXYZ, result);
1023 }
1024 }
1025 }
1026 }
1027 }
1028 }
1029 } // GridResampler::transformBBox()
1030
1031 } // namespace tools
1032 } // namespace OPENVDB_VERSION_NAME
1033 } // namespace openvdb
1034
1035 #endif // OPENVDB_TOOLS_GRIDTRANSFORMER_HAS_BEEN_INCLUDED
1036
1037 // Copyright (c) 2012-2016 DreamWorks Animation LLC
1038 // All rights reserved. This software is distributed under the
1039 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v3_2_0::tools::GridTransformer::GridTransformer
GridTransformer(const Mat4R &xform)
Definition: GridTransformer.h:534
openvdb::v3_2_0::tools::GridResampler::transformTiles
bool transformTiles() const
Return true if tile processing is enabled.
Definition: GridTransformer.h:203
openvdb::v3_2_0::tools::GridResampler::Ptr
boost::shared_ptr< GridResampler > Ptr
Definition: GridTransformer.h:190
openvdb::v3_2_0::tools::signedFloodFill
void signedFloodFill(TreeOrLeafManagerT &tree, bool threaded=true, size_t grainSize=1, Index minLevel=0)
Set the values of all inactive voxels and tiles of a narrow-band level set from the signs of the acti...
Definition: SignedFloodFill.h:294
openvdb::v3_2_0::GridClass
GridClass
Definition: Types.h:211
openvdb::v3_2_0::math::Coord::max
static Coord max()
Return the largest possible coordinate.
Definition: Coord.h:72
openvdb::v3_2_0::tools::local_util::ceilVec3
Vec3i ceilVec3(const Vec3R &v)
Definition: Interpolation.h:617
openvdb::v3_2_0::math::Coord::minComponent
void minComponent(const Coord &other)
Perform a component-wise minimum with the other Coord.
Definition: Coord.h:191
Types.h
openvdb::v3_2_0::math::Vec3::z
T & z()
Definition: Vec3.h:99
openvdb::v3_2_0::tools::GridTransformer::MatrixTransform::transform
Vec3R transform(const Vec3R &pos) const
Definition: GridTransformer.h:388
NullInterrupter.h
openvdb::v3_2_0::tools::GridResampler::~GridResampler
virtual ~GridResampler()
Definition: GridTransformer.h:194
Math.h
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
openvdb::v3_2_0::tools::internal::TileSampler::mVal
ValueT mVal
Definition: GridTransformer.h:143
openvdb::v3_2_0::math::minComponent
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:519
openvdb::v3_2_0::tools::internal::TileSampler::mBBox
BBoxd mBBox
Definition: GridTransformer.h:142
openvdb::v3_2_0::util::NullInterrupter
Dummy NOOP interrupter class defining interface.
Definition: NullInterrupter.h:52
openvdb::v3_2_0::tools::GridResampler::threaded
bool threaded() const
Return true if threading is enabled.
Definition: GridTransformer.h:199
openvdb::v3_2_0::math::X_AXIS
Definition: Math.h:857
openvdb::v3_2_0::tools::Sampler::radius
static int radius()
openvdb::v3_2_0::tools::GridTransformer::MatrixTransform::MatrixTransform
MatrixTransform()
Definition: GridTransformer.h:383
openvdb::v3_2_0::math::Mat4< Real >::identity
static const Mat4< Real > & identity()
Predefined constant for identity matrix.
Definition: Mat4.h:152
openvdb::v3_2_0::tools::GridResampler::setThreaded
void setThreaded(bool b)
Enable or disable threading. (Threading is enabled by default.)
Definition: GridTransformer.h:197
openvdb::v3_2_0::tools::GridResampler::InterruptFunc
boost::function< bool(void)> InterruptFunc
Definition: GridTransformer.h:191
openvdb::v3_2_0::math::Vec3< Real >
LevelSetRebuild.h
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
openvdb::v3_2_0::math::rotation
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:153
ChangeBackground.h
Efficient multi-threaded replacement of the background values in tree.
openvdb::v3_2_0::math::Mat4::eq
bool eq(const Mat4 &m, T eps=1.0e-8) const
Test if "this" is equivalent to m with tolerance of eps value.
Definition: Mat4.h:375
openvdb::v3_2_0::tools::ABTransform::getB
const math::Transform & getB() const
Definition: GridTransformer.h:430
openvdb::v3_2_0::tools::GridTransformer
A GridTransformer applies a geometric transformation to an input grid using one of several sampling s...
Definition: GridTransformer.h:255
openvdb::v3_2_0::tools::GridResampler::interrupt
bool interrupt() const
Definition: GridTransformer.h:218
openvdb::v3_2_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:47
openvdb::v3_2_0::tools::GridResampler::setTransformTiles
void setTransformTiles(bool b)
Enable or disable processing of tiles. (Enabled by default, except for level set grids.)
Definition: GridTransformer.h:201
openvdb::v3_2_0::tools::doLevelSetRebuild
boost::enable_if< boost::is_floating_point< typename GridType::ValueType >, typename GridType::Ptr >::type doLevelSetRebuild(const GridType &grid, typename GridType::ValueType iso, typename GridType::ValueType exWidth, typename GridType::ValueType inWidth, const math::Transform *xform, InterruptT *interrupter)
Definition: LevelSetRebuild.h:229
openvdb::v3_2_0::math::Y_AXIS
Definition: Math.h:858
openvdb::v3_2_0::tools::GridResampler::setInterrupter
void setInterrupter(InterrupterType &)
Allow processing to be aborted by providing an interrupter object. The interrupter will be queried pe...
Definition: GridTransformer.h:674
openvdb::v3_2_0::tools::GridResampler
Definition: GridTransformer.h:187
openvdb::v3_2_0::math::Coord::maxComponent
void maxComponent(const Coord &other)
Perform a component-wise maximum with the other Coord.
Definition: Coord.h:199
openvdb::v3_2_0::tools::composite::max
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:132
openvdb::v3_2_0::tools::GridTransformer::~GridTransformer
virtual ~GridTransformer()
Definition: GridTransformer.h:268
openvdb::v3_2_0::math::BBox< Vec3d >
openvdb::v3_2_0::tools::pruneLevelSet
void pruneLevelSet(TreeT &tree, bool threaded=true, size_t grainSize=1)
Reduce the memory footprint of a tree by replacing nodes whose values are all inactive with inactive ...
Definition: Prune.h:429
openvdb::v3_2_0::math::Coord::x
Int32 x() const
Definition: Coord.h:146
openvdb::v3_2_0::tools::resampleToMatch
void resampleToMatch(const GridType &inGrid, GridType &outGrid)
Resample an input grid into an output grid of the same type such that, after resampling, the input and output grids coincide (apart from sampling artifacts), but the output grid&#39;s transform is unchanged.
Definition: GridTransformer.h:523
openvdb::v3_2_0::tools::changeBackground
void changeBackground(TreeOrLeafManagerT &tree, const typename TreeOrLeafManagerT::ValueType &background, bool threaded=true, size_t grainSize=32)
Replace the background value in all the nodes of a tree.
Definition: ChangeBackground.h:230
openvdb::v3_2_0::tree::ValueAccessor< const TreeT >
openvdb::v3_2_0::math::Mat4::preRotate
void preRotate(Axis axis, T angle)
Left multiplies by a rotation clock-wiseabout the given axis into this matrix.
Definition: Mat4.h:840
openvdb::v3_2_0::math::Vec3i
Vec3< int32_t > Vec3i
Definition: Vec3.h:648
Prune.h
Defined various multi-threaded utility functions for trees.
openvdb::v3_2_0::math::Mat4< Real >
openvdb::v3_2_0::tools::internal::TileSampler< StaggeredPointSampler, TreeT >::TileSampler
TileSampler(const CoordBBox &, const typename TreeT::ValueType &, bool)
Definition: GridTransformer.h:161
openvdb::v3_2_0::tools::GridTransformer::MatrixTransform::invTransform
Vec3R invTransform(const Vec3R &pos) const
Definition: GridTransformer.h:390
openvdb::v3_2_0::tools::GridResampler::GridResampler
GridResampler()
Definition: GridTransformer.h:193
openvdb::v3_2_0::tools::internal::TileSampler::TileSampler
TileSampler(const CoordBBox &b, const ValueT &tileVal, bool on)
Definition: GridTransformer.h:128
openvdb::v3_2_0::tools::GridTransformer::MatrixTransform::invMat
Mat4R invMat
Definition: GridTransformer.h:392
openvdb::v3_2_0::math::Mat4::preTranslate
void preTranslate(const Vec3< T0 > &tr)
Left multiples by the specified translation, i.e. Trans * (*this)
Definition: Mat4.h:745
openvdb::v3_2_0::math::isApproxEqual
bool isApproxEqual(const Type &a, const Type &b)
Return true if a is equal to b to within the default floating-point comparison tolerance.
Definition: Math.h:370
openvdb::v3_2_0::math::XYZ_ROTATION
Definition: Math.h:864
openvdb::v3_2_0::tools::Sampler::mipmap
static bool mipmap()
openvdb::v3_2_0::tools::Sampler
Provises a unified interface for sampling, i.e. interpolation.
Definition: Interpolation.h:90
openvdb::v3_2_0::tools::ABTransform::transform
openvdb::Vec3R transform(const openvdb::Vec3R &pos) const
Definition: GridTransformer.h:419
openvdb::v3_2_0::math::Mat4::inverse
Mat4 inverse(T tolerance=0) const
Definition: Mat4.h:527
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
Definition: version.h:43
openvdb::v3_2_0::tools::GridTransformer::transformGrid
void transformGrid(const GridT &inGrid, GridT &outGrid) const
Definition: GridTransformer.h:693
openvdb::v3_2_0::tools::StaggeredPointSampler
Definition: Interpolation.h:223
openvdb::v3_2_0::tools::internal::TileSampler::sample
bool sample(const TreeT &inTree, const Vec3R &inCoord, ValueT &result) const
Definition: GridTransformer.h:135
openvdb::v3_2_0::tools::ABTransform::isIdentity
bool isIdentity() const
Definition: GridTransformer.h:417
openvdb::v3_2_0::tools::GridTransformer::MatrixTransform::isAffine
bool isAffine() const
Definition: GridTransformer.h:386
openvdb::v3_2_0::tools::GridTransformer::MatrixTransform
Definition: GridTransformer.h:381
SignedFloodFill.h
Propagates the sign of distance values from the active voxels in the narrow band to the inactive valu...
openvdb::v3_2_0::tree::IteratorRange
Definition: TreeIterator.h:1339
openvdb::v3_2_0::math::Vec3::x
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:97
openvdb::v3_2_0::math::Transform
Calculate an axis-aligned bounding box in index space from a bounding sphere in world space...
Definition: Transform.h:66
openvdb::v3_2_0::tools::GridResampler::transformGrid
void transformGrid(const Transformer &, const GridT &inGrid, GridT &outGrid) const
Definition: GridTransformer.h:683
openvdb::v3_2_0::tools::ABTransform::ABTransform
ABTransform(const math::Transform &aXform, const math::Transform &bXform)
Definition: GridTransformer.h:408
openvdb::v3_2_0::math::isAffine
bool isAffine(const Mat4< T > &m)
Definition: Mat4.h:1366
openvdb::v3_2_0::tools::ABTransform::invTransform
openvdb::Vec3R invTransform(const openvdb::Vec3R &pos) const
Definition: GridTransformer.h:424
openvdb::v3_2_0::math::Vec3::eq
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:145
openvdb
Definition: Exceptions.h:39
openvdb::v3_2_0::math::scale
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
Definition: Mat.h:594
openvdb::v3_2_0::math::Mat3
3x3 matrix class.
Definition: Mat3.h:54
openvdb::v3_2_0::math::Mat3::eq
bool eq(const Mat3 &m, T eps=1.0e-8) const
Test if "this" is equivalent to m with tolerance of eps value.
Definition: Mat3.h:345
openvdb::v3_2_0::tools::internal::TileSampler::mEmpty
bool mEmpty
Definition: GridTransformer.h:144
openvdb::v3_2_0::tools::GridResampler::applyTransform
void applyTransform(const Transformer &, const GridT &inGrid, GridT &outGrid) const
Definition: GridTransformer.h:868
openvdb::v3_2_0::math::Mat4::getMat3
Mat3< T > getMat3() const
Definition: Mat4.h:339
openvdb::v3_2_0::tools::internal::TileSampler
A TileSampler wraps a grid sampler of another type (BoxSampler, QuadraticSampler, etc...
Definition: GridTransformer.h:120
openvdb::v3_2_0::math::Coord::z
Int32 z() const
Definition: Coord.h:148
openvdb::v3_2_0::math::Z_AXIS
Definition: Math.h:859
openvdb::v3_2_0::math::Mat4::setTranslation
void setTranslation(const Vec3< T > &t)
Definition: Mat4.h:356
openvdb::v3_2_0::TypeError
Definition: Exceptions.h:87
openvdb::v3_2_0::math::CoordBBox::min
const Coord & min() const
Definition: Coord.h:332
openvdb::v3_2_0::tools::local_util::floorVec3
Vec3i floorVec3(const Vec3R &v)
Definition: Interpolation.h:610
openvdb::v3_2_0::tools::ABTransform::getA
const math::Transform & getA() const
Definition: GridTransformer.h:429
openvdb::v3_2_0::tools::doResampleToMatch
void doResampleToMatch(const GridType &inGrid, GridType &outGrid, Interrupter &interrupter)
Definition: GridTransformer.h:447
openvdb::v3_2_0::math::Vec3::y
T & y()
Definition: Vec3.h:98
openvdb::v3_2_0::tools::local_util::decompose
bool decompose(const math::Mat4< T > &m, math::Vec3< T > &scale, math::Vec3< T > &rotate, math::Vec3< T > &translate)
Decompose an affine transform into scale, rotation and translation components.
Definition: GridTransformer.h:297
openvdb::v3_2_0::math::Coord::min
static Coord min()
Return the smallest possible coordinate.
Definition: Coord.h:69
openvdb::v3_2_0::math::CoordBBox::max
const Coord & max() const
Definition: Coord.h:333
openvdb::v3_2_0::tools::GridTransformer::Ptr
boost::shared_ptr< GridTransformer > Ptr
Definition: GridTransformer.h:258
openvdb::v3_2_0::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:259
Interpolation.h
openvdb::v3_2_0::tools::internal::TileSampler::ValueT
TreeT::ValueType ValueT
Definition: GridTransformer.h:123
openvdb::v3_2_0::math::eulerAngles
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:314
openvdb::v3_2_0::math::Coord::y
Int32 y() const
Definition: Coord.h:147
Grid.h
openvdb::v3_2_0::ValueError
Definition: Exceptions.h:88
openvdb::v3_2_0::Vec3R
math::Vec3< Real > Vec3R
Definition: Types.h:76
openvdb::v3_2_0::tools::Sampler::sample
static bool sample(const TreeT &inTree, const Vec3R &inCoord, typename TreeT::ValueType &result)
Sample inTree at the floating-point index coordinate inCoord and store the result in result...
openvdb::v3_2_0::tools::GridTransformer::MatrixTransform::MatrixTransform
MatrixTransform(const Mat4R &xform)
Definition: GridTransformer.h:384
openvdb::v3_2_0::GRID_LEVEL_SET
Definition: Types.h:213
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
openvdb::v3_2_0::tools::ABTransform::isAffine
bool isAffine() const
Definition: GridTransformer.h:415
openvdb::v3_2_0::tools::internal::TileSampler< PointSampler, TreeT >::TileSampler
TileSampler(const CoordBBox &, const typename TreeT::ValueType &, bool)
Definition: GridTransformer.h:153
openvdb::v3_2_0::math::CoordBBox::empty
bool empty() const
Definition: Coord.h:350
openvdb::v3_2_0::math::maxComponent
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition: Vec2.h:528
openvdb::v3_2_0::math::Mat4::getTranslation
Vec3< T > getTranslation() const
Return the translation component.
Definition: Mat4.h:351
openvdb::v3_2_0::tools::PointSampler
Definition: Interpolation.h:123
openvdb::v3_2_0::tools::GridTransformer::MatrixTransform::mat
Mat4R mat
Definition: GridTransformer.h:392
openvdb::v3_2_0::tools::GridTransformer::getTransform
const Mat4R & getTransform() const
Definition: GridTransformer.h:270
openvdb::v3_2_0::tools::ABTransform
This class implements the Transformer functor interface (specifically, the isAffine(), transform() and invTransform() methods) for a transform that maps an A grid into a B grid&#39;s index space such that, after resampling, A&#39;s index space and transform match B&#39;s index space and transform.
Definition: GridTransformer.h:403
openvdb::v3_2_0::math::Mat4::preScale
void preScale(const Vec3< T0 > &v)
Definition: Mat4.h:778
openvdb::v3_2_0::util::wasInterrupted
bool wasInterrupted(T *i, int percent=-1)
Definition: NullInterrupter.h:76
openvdb::v3_2_0::tools::composite::min
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:128