OpenVDB 5.1.0

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