OpenVDB: PointMove.h Source File

OpenVDB 6.0.0

PointMove.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
58
59 #ifndef OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
60 #define OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
61
62 #include <openvdb/openvdb.h>
63
64 #include <openvdb/points/PointDataGrid.h>
65 #include <openvdb/points/PointMask.h>
66
67 #include <tbb/concurrent_vector.h>
68
69 #include <algorithm>
70 #include <iterator> // for std::begin(), std::end()
71 #include <map>
72 #include <numeric> // for std::iota()
73 #include <tuple>
74 #include <unordered_map>
75 #include <vector>
76
77 class TestPointMove;
78
79
80 namespace openvdb {
81 OPENVDB_USE_VERSION_NAMESPACE
82 namespace OPENVDB_VERSION_NAME {
83 namespace points {
84
85 // dummy object for future use
86 namespace future { struct Advect { }; }
87
88
95 template <typename PointDataGridT, typename DeformerT, typename FilterT = NullFilter>
96 inline void movePoints(PointDataGridT& points,
97 DeformerT& deformer,
98 const FilterT& filter = NullFilter(),
99 future::Advect* objectNotInUse = nullptr,
100 bool threaded = true);
101
102
110 template <typename PointDataGridT, typename DeformerT, typename FilterT = NullFilter>
111 inline void movePoints(PointDataGridT& points,
112 const math::Transform& transform,
113 DeformerT& deformer,
114 const FilterT& filter = NullFilter(),
115 future::Advect* objectNotInUse = nullptr,
116 bool threaded = true);
117
118
119 // define leaf index in use as 32-bit
120 namespace point_move_internal { using LeafIndex = Index32; }
121
122
124 template <typename T>
125 class CachedDeformer
126 {
127 public:
128 using LeafIndex = point_move_internal::LeafIndex;
129 using Vec3T = typename math::Vec3<T>;
130 using LeafVecT = std::vector<Vec3T>;
131 using LeafMapT = std::unordered_map<LeafIndex, Vec3T>;
132
133 // Internal data cache to allow the deformer to offer light-weight copying
134 struct Cache
135 {
136 struct Leaf
137 {
139 void clear() {
140 vecData.clear();
141 mapData.clear();
142 totalSize = 0;
143 }
144
145 LeafVecT vecData;
146 LeafMapT mapData;
147 Index totalSize = 0;
148 }; // struct Leaf
149
150 std::vector<Leaf> leafs;
151 }; // struct Cache
152
154 explicit CachedDeformer(Cache& cache);
155
161 template <typename PointDataGridT, typename DeformerT, typename FilterT>
162 void evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
163 bool threaded = true);
164
167 template <typename LeafT>
168 void reset(const LeafT& leaf, size_t idx);
169
171 template <typename IndexIterT>
172 void apply(Vec3d& position, const IndexIterT& iter) const;
173
174 private:
175 friend class ::TestPointMove;
176
177 Cache& mCache;
178 LeafVecT mLocalLeafVec;
179 const LeafVecT* mLeafVec = nullptr;
180 const LeafMapT* mLeafMap = nullptr;
181 }; // class CachedDeformer
182
183
185
186
187 namespace point_move_internal {
188
189
190 using IndexTriple = std::tuple<LeafIndex, Index, Index>;
191 using IndexTripleArray = tbb::concurrent_vector<IndexTriple>;
192 using GlobalPointIndexMap = std::vector<IndexTripleArray>;
193
194 using IndexPair = std::pair<Index, Index>;
195 using IndexPairArray = std::vector<IndexPair>;
196 using LocalPointIndexMap = std::vector<IndexPairArray>;
197
198 using IndexArray = std::vector<Index>;
199
200 using LeafIndexArray = std::vector<LeafIndex>;
201 using LeafOffsetArray = std::vector<LeafIndexArray>;
202 using LeafMap = std::map<Coord, LeafIndex>;
203
204 // TODO: The following infrastructure - ArrayProcessor, PerformTypedMoveOp, processTypedArray()
205 // is required to improve AttributeArray copying performance beyond using the virtual function
206 // AttributeArray::set(Index, AttributeArray&, Index), however an ABI=6+ addition to AttributeArray
207 // could eliminate this cost for the typical case where ValueType and CodecType are the same in
208 // source and target arrays, as they are here.
209
210
212 template<typename ValueType, typename OpType>
213 struct ArrayProcessor {
214 static inline void call(OpType& op, const AttributeArray& array) {
215 #ifdef _MSC_VER
216 op.operator()<ValueType>(array);
217 #else
218 op.template operator()<ValueType>(array);
219 #endif
220 }
221 };
222
225 template<typename ArrayType, typename OpType>
226 bool
227 processTypedArray(const ArrayType& array, OpType& op)
228 {
229 using namespace openvdb;
230 using namespace openvdb::math;
231 if (array.template hasValueType<bool>()) ArrayProcessor<bool, OpType>::call(op, array);
232 else if (array.template hasValueType<int16_t>()) ArrayProcessor<int16_t, OpType>::call(op, array);
233 else if (array.template hasValueType<int32_t>()) ArrayProcessor<int32_t, OpType>::call(op, array);
234 else if (array.template hasValueType<int64_t>()) ArrayProcessor<int64_t, OpType>::call(op, array);
235 else if (array.template hasValueType<float>()) ArrayProcessor<float, OpType>::call(op, array);
236 else if (array.template hasValueType<double>()) ArrayProcessor<double, OpType>::call(op, array);
237 else if (array.template hasValueType<Vec3<int32_t>>()) ArrayProcessor<Vec3<int32_t>, OpType>::call(op, array);
238 else if (array.template hasValueType<Vec3<float>>()) ArrayProcessor<Vec3<float>, OpType>::call(op, array);
239 else if (array.template hasValueType<Vec3<double>>()) ArrayProcessor<Vec3<double>, OpType>::call(op, array);
240 else if (array.template hasValueType<GroupType>()) ArrayProcessor<GroupType, OpType>::call(op, array);
241 else if (array.template hasValueType<StringIndexType>()) ArrayProcessor<StringIndexType, OpType>::call(op, array);
242 else if (array.template hasValueType<Mat3<float>>()) ArrayProcessor<Mat3<float>, OpType>::call(op, array);
243 else if (array.template hasValueType<Mat3<double>>()) ArrayProcessor<Mat3<double>, OpType>::call(op, array);
244 else if (array.template hasValueType<Mat4<float>>()) ArrayProcessor<Mat4<float>, OpType>::call(op, array);
245 else if (array.template hasValueType<Mat4<double>>()) ArrayProcessor<Mat4<double>, OpType>::call(op, array);
246 else if (array.template hasValueType<Quat<float>>()) ArrayProcessor<Quat<float>, OpType>::call(op, array);
247 else if (array.template hasValueType<Quat<double>>()) ArrayProcessor<Quat<double>, OpType>::call(op, array);
248 else return false;
249 return true;
250 }
251
252
254 struct AttributeHandles
255 {
256 using HandleArray = std::vector<AttributeHandle<int>::Ptr>;
257
258 AttributeHandles(const size_t size)
259 : mHandles() { mHandles.reserve(size); }
260
261 AttributeArray& getArray(const Index leafOffset)
262 {
263 auto* handle = reinterpret_cast<AttributeWriteHandle<int>*>(mHandles[leafOffset].get());
264 assert(handle);
265 return handle->array();
266 }
267
268 const AttributeArray& getConstArray(const Index leafOffset) const
269 {
270 const auto* handle = mHandles[leafOffset].get();
271 assert(handle);
272 return handle->array();
273 }
274
275 template <typename ValueT>
276 AttributeHandle<ValueT>& getHandle(const Index leafOffset)
277 {
278 auto* handle = reinterpret_cast<AttributeHandle<ValueT>*>(mHandles[leafOffset].get());
279 assert(handle);
280 return *handle;
281 }
282
283 template <typename ValueT>
284 AttributeWriteHandle<ValueT>& getWriteHandle(const Index leafOffset)
285 {
286 auto* handle = reinterpret_cast<AttributeWriteHandle<ValueT>*>(mHandles[leafOffset].get());
287 assert(handle);
288 return *handle;
289 }
290
292 struct CacheHandleOp
293 {
294 CacheHandleOp(HandleArray& handles)
295 : mHandles(handles) { }
296
297 template<typename ValueT>
298 void operator()(const AttributeArray& array) const
299 {
300 auto* handleAsInt = reinterpret_cast<AttributeHandle<int>*>(
301 new AttributeHandle<ValueT>(array));
302 mHandles.emplace_back(handleAsInt);
303 }
304
305 private:
306 HandleArray& mHandles;
307 }; // struct CacheHandleOp
308
309 template <typename LeafRangeT>
310 void cache(const LeafRangeT& range, const Index attributeIndex)
311 {
312 using namespace openvdb::math;
313
314 mHandles.clear();
315 CacheHandleOp op(mHandles);
316
317 for (auto leaf = range.begin(); leaf; ++leaf) {
318 auto& array = leaf->attributeArray(attributeIndex);
319 processTypedArray(array, op);
320 }
321 }
322
323 private:
324 HandleArray mHandles;
325 }; // struct AttributeHandles
326
327
328 template <typename DeformerT, typename TreeT, typename FilterT>
329 struct BuildMoveMapsOp
330 {
331 using LeafT = typename TreeT::LeafNodeType;
332 using LeafArrayT = std::vector<LeafT*>;
333 using LeafManagerT = typename tree::LeafManager<TreeT>;
334
335 BuildMoveMapsOp(const DeformerT& deformer,
336 GlobalPointIndexMap& globalMoveLeafMap,
337 LocalPointIndexMap& localMoveLeafMap,
338 const LeafMap& targetLeafMap,
339 const math::Transform& targetTransform,
340 const math::Transform& sourceTransform,
341 const FilterT& filter)
342 : mDeformer(deformer)
343 , mGlobalMoveLeafMap(globalMoveLeafMap)
344 , mLocalMoveLeafMap(localMoveLeafMap)
345 , mTargetLeafMap(targetLeafMap)
346 , mTargetTransform(targetTransform)
347 , mSourceTransform(sourceTransform)
348 , mFilter(filter) { }
349
350 void operator()(LeafT& leaf, size_t idx) const
351 {
352 DeformerT deformer(mDeformer);
353 deformer.reset(leaf, idx);
354
355 // determine source leaf node origin and offset in the source leaf vector
356
357 Coord sourceLeafOrigin = leaf.origin();
358
359 auto sourceHandle = AttributeWriteHandle<Vec3f>::create(leaf.attributeArray("P"));
360
361 for (auto iter = leaf.beginIndexOn(mFilter); iter; iter++) {
362
363 const bool useIndexSpace = DeformerTraits<DeformerT>::IndexSpace;
364
365 // extract index-space position and apply index-space deformation (if applicable)
366
367 Vec3d positionIS = sourceHandle->get(*iter) + iter.getCoord().asVec3d();
368 if (useIndexSpace) {
369 deformer.apply(positionIS, iter);
370 }
371
372 // transform to world-space position and apply world-space deformation (if applicable)
373
374 Vec3d positionWS = mSourceTransform.indexToWorld(positionIS);
375 if (!useIndexSpace) {
376 deformer.apply(positionWS, iter);
377 }
378
379 // transform to index-space position of target grid
380
381 positionIS = mTargetTransform.worldToIndex(positionWS);
382
383 // determine target voxel and offset
384
385 Coord targetVoxel = Coord::round(positionIS);
386 Index targetOffset = LeafT::coordToOffset(targetVoxel);
387
388 // set new local position in source transform space (if point has been deformed)
389
390 Vec3d voxelPosition(positionIS - targetVoxel.asVec3d());
391 sourceHandle->set(*iter, voxelPosition);
392
393 // determine target leaf node origin and offset in the target leaf vector
394
395 Coord targetLeafOrigin = targetVoxel & ~(LeafT::DIM - 1);
396 assert(mTargetLeafMap.find(targetLeafOrigin) != mTargetLeafMap.end());
397 const LeafIndex targetLeafOffset(mTargetLeafMap.at(targetLeafOrigin));
398
399 // insert into move map based on whether point ends up in a new leaf node or not
400
401 if (targetLeafOrigin == sourceLeafOrigin) {
402 mLocalMoveLeafMap[targetLeafOffset].emplace_back(targetOffset, *iter);
403 }
404 else {
405 mGlobalMoveLeafMap[targetLeafOffset].push_back(IndexTriple(
406 LeafIndex(static_cast<LeafIndex>(idx)), targetOffset, *iter));
407 }
408 }
409 }
410
411 private:
412 const DeformerT& mDeformer;
413 GlobalPointIndexMap& mGlobalMoveLeafMap;
414 LocalPointIndexMap& mLocalMoveLeafMap;
415 const LeafMap& mTargetLeafMap;
416 const math::Transform& mTargetTransform;
417 const math::Transform& mSourceTransform;
418 const FilterT& mFilter;
419 }; // struct BuildMoveMapsOp
420
421 template <typename LeafT>
422 inline Index
423 indexOffsetFromVoxel(const Index voxelOffset, const LeafT& leaf, IndexArray& offsets)
424 {
425 // compute the target point index by summing the point index of the previous
426 // voxel with the current number of points added to this voxel, tracked by the
427 // offsets array
428
429 Index targetOffset = offsets[voxelOffset]++;
430 if (voxelOffset > 0) {
431 targetOffset += static_cast<Index>(leaf.getValue(voxelOffset - 1));
432 }
433 return targetOffset;
434 }
435
436 template <typename TreeT>
437 struct GlobalMovePointsOp
438 {
439 using LeafT = typename TreeT::LeafNodeType;
440 using LeafArrayT = std::vector<LeafT*>;
441 using LeafManagerT = typename tree::LeafManager<TreeT>;
442
443 GlobalMovePointsOp(LeafOffsetArray& offsetMap,
444 AttributeHandles& targetHandles,
445 AttributeHandles& sourceHandles,
446 const Index attributeIndex,
447 const GlobalPointIndexMap& moveLeafMap)
448 : mOffsetMap(offsetMap)
449 , mTargetHandles(targetHandles)
450 , mSourceHandles(sourceHandles)
451 , mAttributeIndex(attributeIndex)
452 , mMoveLeafMap(moveLeafMap) { }
453
454 struct PerformTypedMoveOp
455 {
456 PerformTypedMoveOp(AttributeHandles& targetHandles, AttributeHandles& sourceHandles,
457 Index targetOffset, const LeafT& targetLeaf,
458 IndexArray& offsets, const IndexTripleArray& indices)
459 : mTargetHandles(targetHandles)
460 , mSourceHandles(sourceHandles)
461 , mTargetOffset(targetOffset)
462 , mTargetLeaf(targetLeaf)
463 , mOffsets(offsets)
464 , mIndices(indices) { }
465
466 template<typename ValueT>
467 void operator()(const AttributeArray&) const
468 {
469 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(mTargetOffset);
470 targetHandle.expand();
471
472 // build a sorted index vector that references the indices in order of their source
473 // leafs and voxels to ensure determinism in the resulting point orders
474
475 std::vector<int> sortedIndices(mIndices.size());
476 std::iota(std::begin(sortedIndices), std::end(sortedIndices), 0);
477 std::sort(std::begin(sortedIndices), std::end(sortedIndices),
478 [&](int i, int j)
479 {
480 const Index& indexI0(std::get<0>(mIndices[i]));
481 const Index& indexJ0(std::get<0>(mIndices[j]));
482 if (indexI0 < indexJ0) return true;
483 if (indexI0 > indexJ0) return false;
484 return std::get<2>(mIndices[i]) < std::get<2>(mIndices[j]);
485 }
486 );
487
488 for (const auto& index : sortedIndices) {
489 const auto& it = mIndices[index];
490 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(std::get<0>(it));
491 const Index targetIndex = indexOffsetFromVoxel(std::get<1>(it), mTargetLeaf, mOffsets);
492 for (Index i = 0; i < sourceHandle.stride(); i++) {
493 ValueT sourceValue = sourceHandle.get(std::get<2>(it), i);
494 targetHandle.set(targetIndex, i, sourceValue);
495 }
496 }
497 }
498
499 private:
500 AttributeHandles& mTargetHandles;
501 AttributeHandles& mSourceHandles;
502 Index mTargetOffset;
503 const LeafT& mTargetLeaf;
504 IndexArray& mOffsets;
505 const IndexTripleArray& mIndices;
506 }; // struct PerformTypedMoveOp
507
508 void performMove(Index targetOffset, const LeafT& targetLeaf,
509 IndexArray& offsets, const IndexTripleArray& indices) const
510 {
511 auto& targetArray = mTargetHandles.getArray(targetOffset);
512
513 for (const auto& it : indices) {
514 const auto& sourceArray = mSourceHandles.getConstArray(std::get<0>(it));
515 const Index tgtOffset = indexOffsetFromVoxel(std::get<1>(it), targetLeaf, offsets);
516 targetArray.set(tgtOffset, sourceArray, std::get<2>(it));
517 }
518 }
519
520 void operator()(LeafT& leaf, size_t aIdx) const
521 {
522 const Index idx(static_cast<Index>(aIdx));
523 const auto& moveIndices = mMoveLeafMap.at(aIdx);
524 if (moveIndices.empty()) return;
525
526 // extract per-voxel offsets for this leaf
527
528 auto& offsets = mOffsetMap[aIdx];
529
530 const auto& array = leaf.constAttributeArray(mAttributeIndex);
531
532 PerformTypedMoveOp op(mTargetHandles, mSourceHandles, idx, leaf, offsets, moveIndices);
533 if (!processTypedArray(array, op)) {
534 this->performMove(idx, leaf, offsets, moveIndices);
535 }
536 }
537
538 private:
539 LeafOffsetArray& mOffsetMap;
540 AttributeHandles& mTargetHandles;
541 AttributeHandles& mSourceHandles;
542 const Index mAttributeIndex;
543 const GlobalPointIndexMap& mMoveLeafMap;
544 }; // struct GlobalMovePointsOp
545
546 template <typename TreeT>
547 struct LocalMovePointsOp
548 {
549 using LeafT = typename TreeT::LeafNodeType;
550 using LeafArrayT = std::vector<LeafT*>;
551 using LeafManagerT = typename tree::LeafManager<TreeT>;
552
553 LocalMovePointsOp( LeafOffsetArray& offsetMap,
554 AttributeHandles& targetHandles,
555 const LeafIndexArray& sourceIndices,
556 AttributeHandles& sourceHandles,
557 const Index attributeIndex,
558 const LocalPointIndexMap& moveLeafMap)
559 : mOffsetMap(offsetMap)
560 , mTargetHandles(targetHandles)
561 , mSourceIndices(sourceIndices)
562 , mSourceHandles(sourceHandles)
563 , mAttributeIndex(attributeIndex)
564 , mMoveLeafMap(moveLeafMap) { }
565
566 struct PerformTypedMoveOp
567 {
568 PerformTypedMoveOp(AttributeHandles& targetHandles, AttributeHandles& sourceHandles,
569 Index targetOffset, Index sourceOffset, const LeafT& targetLeaf,
570 IndexArray& offsets, const IndexPairArray& indices)
571 : mTargetHandles(targetHandles)
572 , mSourceHandles(sourceHandles)
573 , mTargetOffset(targetOffset)
574 , mSourceOffset(sourceOffset)
575 , mTargetLeaf(targetLeaf)
576 , mOffsets(offsets)
577 , mIndices(indices) { }
578
579 template<typename ValueT>
580 void operator()(const AttributeArray&) const
581 {
582 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(mTargetOffset);
583 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(mSourceOffset);
584
585 targetHandle.expand();
586
587 for (const auto& it : mIndices) {
588 const Index targetIndex = indexOffsetFromVoxel(it.first, mTargetLeaf, mOffsets);
589 for (Index i = 0; i < sourceHandle.stride(); i++) {
590 ValueT sourceValue = sourceHandle.get(it.second, i);
591 targetHandle.set(targetIndex, i, sourceValue);
592 }
593 }
594 }
595
596 private:
597 AttributeHandles& mTargetHandles;
598 AttributeHandles& mSourceHandles;
599 Index mTargetOffset;
600 Index mSourceOffset;
601 const LeafT& mTargetLeaf;
602 IndexArray& mOffsets;
603 const IndexPairArray& mIndices;
604 }; // struct PerformTypedMoveOp
605
606 template <typename ValueT>
607 void performTypedMove(Index sourceOffset, Index targetOffset, const LeafT& targetLeaf,
608 IndexArray& offsets, const IndexPairArray& indices) const
609 {
610 auto& targetHandle = mTargetHandles.getWriteHandle<ValueT>(targetOffset);
611 const auto& sourceHandle = mSourceHandles.getHandle<ValueT>(sourceOffset);
612
613 targetHandle.expand();
614
615 for (const auto& it : indices) {
616 const Index tgtOffset = indexOffsetFromVoxel(it.first, targetLeaf, offsets);
617 for (Index i = 0; i < sourceHandle.stride(); i++) {
618 ValueT sourceValue = sourceHandle.get(it.second, i);
619 targetHandle.set(tgtOffset, i, sourceValue);
620 }
621 }
622 }
623
624 void performMove(Index targetOffset, Index sourceOffset, const LeafT& targetLeaf,
625 IndexArray& offsets, const IndexPairArray& indices) const
626 {
627 auto& targetArray = mTargetHandles.getArray(targetOffset);
628 const auto& sourceArray = mSourceHandles.getConstArray(sourceOffset);
629
630 for (const auto& it : indices) {
631 const Index tgtOffset = indexOffsetFromVoxel(it.first, targetLeaf, offsets);
632 targetArray.set(tgtOffset, sourceArray, it.second);
633 }
634 }
635
636 void operator()(const LeafT& leaf, size_t aIdx) const
637 {
638 const Index idx(static_cast<Index>(aIdx));
639 const auto& moveIndices = mMoveLeafMap.at(aIdx);
640 if (moveIndices.empty()) return;
641
642 // extract target leaf and per-voxel offsets for this leaf
643
644 auto& offsets = mOffsetMap[aIdx];
645
646 // extract source leaf that has the same origin as the target leaf (if any)
647
648 assert(aIdx < mSourceIndices.size());
649 const Index sourceOffset(mSourceIndices[aIdx]);
650
651 const auto& array = leaf.constAttributeArray(mAttributeIndex);
652
653 PerformTypedMoveOp op(mTargetHandles, mSourceHandles,
654 idx, sourceOffset, leaf, offsets, moveIndices);
655 if (!processTypedArray(array, op)) {
656 this->performMove(idx, sourceOffset, leaf, offsets, moveIndices);
657 }
658 }
659
660 private:
661 LeafOffsetArray& mOffsetMap;
662 AttributeHandles& mTargetHandles;
663 const LeafIndexArray& mSourceIndices;
664 AttributeHandles& mSourceHandles;
665 const Index mAttributeIndex;
666 const LocalPointIndexMap& mMoveLeafMap;
667 }; // struct LocalMovePointsOp
668
669 } // namespace point_move_internal
670
671
673
674
675 template <typename PointDataGridT, typename DeformerT, typename FilterT>
676 inline void movePoints( PointDataGridT& points,
677 const math::Transform& transform,
678 DeformerT& deformer,
679 const FilterT& filter,
680 future::Advect* objectNotInUse,
681 bool threaded)
682 {
683 using LeafIndex = point_move_internal::LeafIndex;
684 using PointDataTreeT = typename PointDataGridT::TreeType;
685 using LeafT = typename PointDataTreeT::LeafNodeType;
686 using LeafManagerT = typename tree::LeafManager<PointDataTreeT>;
687
688 using namespace point_move_internal;
689
690 // this object is for future use only
691 assert(!objectNotInUse);
692 (void)objectNotInUse;
693
694 PointDataTreeT& tree = points.tree();
695
696 // early exit if no LeafNodes
697
698 PointDataTree::LeafCIter iter = tree.cbeginLeaf();
699
700 if (!iter) return;
701
702 // build voxel topology taking into account any point group deletion
703
704 auto newPoints = point_mask_internal::convertPointsToScalar<PointDataGrid>(
705 points, transform, filter, deformer, threaded);
706 auto& newTree = newPoints->tree();
707
708 // create leaf managers for both trees
709
710 LeafManagerT sourceLeafManager(tree);
711 LeafManagerT targetLeafManager(newTree);
712
713 // initialize attribute handles
714 AttributeHandles sourceHandles(sourceLeafManager.leafCount());
715 AttributeHandles targetHandles(targetLeafManager.leafCount());
716
717 // extract the existing attribute set
718 const auto& existingAttributeSet = points.tree().cbeginLeaf()->attributeSet();
719
720 // build a coord -> index map for looking up target leafs by origin and a faster
721 // unordered map for finding the source index from a target index
722
723 LeafMap targetLeafMap;
724 LeafIndexArray sourceIndices(targetLeafManager.leafCount(),
725 std::numeric_limits<LeafIndex>::max());
726
727 LeafOffsetArray offsetMap(targetLeafManager.leafCount());
728
729 {
730 LeafMap sourceLeafMap;
731 auto sourceRange = sourceLeafManager.leafRange();
732 for (auto leaf = sourceRange.begin(); leaf; ++leaf) {
733 sourceLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
734 }
735 auto targetRange = targetLeafManager.leafRange();
736 for (auto leaf = targetRange.begin(); leaf; ++leaf) {
737 targetLeafMap.insert({leaf->origin(), LeafIndex(static_cast<LeafIndex>(leaf.pos()))});
738 }
739
740 // perform four independent per-leaf operations in parallel
741 targetLeafManager.foreach(
742 [&](LeafT& leaf, size_t idx) {
743 // map frequency => cumulative histogram
744 auto* buffer = leaf.buffer().data();
745 for (Index i = 1; i < leaf.buffer().size(); i++) {
746 buffer[i] = buffer[i-1] + buffer[i];
747 }
748 // replace attribute set with a copy of the existing one
749 leaf.replaceAttributeSet(new AttributeSet(existingAttributeSet, leaf.getLastValue()),
750 /*allowMismatchingDescriptors=*/true);
751 // store the index of the source leaf in a corresponding target leaf array
752 const auto it = sourceLeafMap.find(leaf.origin());
753 if (it != sourceLeafMap.end()) {
754 sourceIndices[idx] = it->second;
755 }
756 // allocate offset maps
757 offsetMap[idx].resize(LeafT::SIZE);
758 },
759 threaded);
760 }
761
762 // moving leaf
763
764 GlobalPointIndexMap globalMoveLeafMap(targetLeafManager.leafCount());
765 LocalPointIndexMap localMoveLeafMap(targetLeafManager.leafCount());
766
767 // build global and local move leaf maps and update local positions
768
769 if (filter.state() == index::ALL) {
770 NullFilter nullFilter;
771 BuildMoveMapsOp<DeformerT, PointDataTreeT, NullFilter> op(deformer,
772 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
773 transform, points.transform(), nullFilter);
774 sourceLeafManager.foreach(op, threaded);
775 } else {
776 BuildMoveMapsOp<DeformerT, PointDataTreeT, FilterT> op(deformer,
777 globalMoveLeafMap, localMoveLeafMap, targetLeafMap,
778 transform, points.transform(), filter);
779 sourceLeafManager.foreach(op, threaded);
780 }
781
782 for (const auto& it : existingAttributeSet.descriptor().map()) {
783
784 const Index attributeIndex = static_cast<Index>(it.second);
785
786 // zero offsets
787 targetLeafManager.foreach(
788 [&offsetMap](const LeafT& /*leaf*/, size_t idx) {
789 std::fill(offsetMap[idx].begin(), offsetMap[idx].end(), 0);
790 },
791 threaded);
792
793 // cache attribute handles
794
795 sourceHandles.cache(sourceLeafManager.leafRange(), attributeIndex);
796 targetHandles.cache(targetLeafManager.leafRange(), attributeIndex);
797
798 // move points between leaf nodes
799
800 GlobalMovePointsOp<PointDataTreeT> globalMoveOp(offsetMap, targetHandles,
801 sourceHandles, attributeIndex, globalMoveLeafMap);
802 targetLeafManager.foreach(globalMoveOp, threaded);
803
804 // move points within leaf nodes
805
806 LocalMovePointsOp<PointDataTreeT> localMoveOp(offsetMap, targetHandles,
807 sourceIndices, sourceHandles,
808 attributeIndex, localMoveLeafMap);
809 targetLeafManager.foreach(localMoveOp, threaded);
810 }
811
812 points.setTree(newPoints->treePtr());
813 }
814
815
816 template <typename PointDataGridT, typename DeformerT, typename FilterT>
817 inline void movePoints( PointDataGridT& points,
818 DeformerT& deformer,
819 const FilterT& filter,
820 future::Advect* objectNotInUse,
821 bool threaded)
822 {
823 movePoints(points, points.transform(), deformer, filter, objectNotInUse, threaded);
824 }
825
826
828
829
830 template <typename T>
831 CachedDeformer<T>::CachedDeformer(Cache& cache)
832 : mCache(cache) { }
833
834
835 template <typename T>
836 template <typename PointDataGridT, typename DeformerT, typename FilterT>
837 void CachedDeformer<T>::evaluate(PointDataGridT& grid, DeformerT& deformer, const FilterT& filter,
838 bool threaded)
839 {
840 using TreeT = typename PointDataGridT::TreeType;
841 using LeafT = typename TreeT::LeafNodeType;
842 using LeafManagerT = typename tree::LeafManager<TreeT>;
843 LeafManagerT leafManager(grid.tree());
844
845 // initialize cache
846 auto& leafs = mCache.leafs;
847 leafs.resize(leafManager.leafCount());
848
849 const auto& transform = grid.transform();
850
851 // insert deformed positions into the cache
852
853 auto cachePositionsOp = [&](const LeafT& leaf, size_t idx) {
854
855 const Index64 totalPointCount = leaf.pointCount();
856 if (totalPointCount == 0) return;
857
858 // deformer is copied to ensure that it is unique per-thread
859
860 DeformerT newDeformer(deformer);
861
862 // if more than half the number of total points are evaluated by the filter, prefer
863 // accessing the data from a vector instead of a hash map for faster performance
864 const Index64 vectorThreshold = totalPointCount / 2;
865
866 newDeformer.reset(leaf, idx);
867
868 auto handle = AttributeHandle<Vec3f>::create(leaf.constAttributeArray("P"));
869
870 auto& cache = leafs[idx];
871 cache.clear();
872
873 // only insert into a vector directly if the filter evaluates all points and the
874 // number of active points is greater than the vector threshold
875 const bool useVector = filter.state() == index::ALL &&
876 (leaf.isDense() || (leaf.onPointCount() > vectorThreshold));
877 if (useVector) {
878 cache.vecData.resize(totalPointCount);
879 }
880
881 for (auto iter = leaf.beginIndexOn(filter); iter; iter++) {
882
883 // extract index-space position and apply index-space deformation (if defined)
884
885 Vec3d position = handle->get(*iter) + iter.getCoord().asVec3d();
886
887 // if deformer is designed to be used in index-space, perform deformation prior
888 // to transforming position to world-space, otherwise perform deformation afterwards
889
890 if (DeformerTraits<DeformerT>::IndexSpace) {
891 newDeformer.apply(position, iter);
892 position = transform.indexToWorld(position);
893 }
894 else {
895 position = transform.indexToWorld(position);
896 newDeformer.apply(position, iter);
897 }
898
899 // insert new position into the cache
900
901 if (useVector) {
902 cache.vecData[*iter] = static_cast<Vec3T>(position);
903 }
904 else {
905 cache.mapData.insert({*iter, static_cast<Vec3T>(position)});
906 }
907 }
908
909 // after insertion, move the data into a vector if the threshold is reached
910
911 if (!useVector && cache.mapData.size() > vectorThreshold) {
912 cache.vecData.resize(totalPointCount);
913 for (const auto& it : cache.mapData) {
914 cache.vecData[it.first] = it.second;
915 }
916 cache.mapData.clear();
917 }
918
919 // store the total number of points to allow use of an expanded vector on access
920
921 if (!cache.mapData.empty()) {
922 cache.totalSize = static_cast<Index>(totalPointCount);
923 }
924 };
925
926 leafManager.foreach(cachePositionsOp, threaded);
927 }
928
929
930 template <typename T>
931 template <typename LeafT>
932 void CachedDeformer<T>::reset(const LeafT& /*leaf*/, size_t idx)
933 {
934 if (idx >= mCache.leafs.size()) {
935 if (mCache.leafs.empty()) {
936 throw IndexError("No leafs in cache, perhaps CachedDeformer has not been evaluated?");
937 } else {
938 throw IndexError("Leaf index is out-of-range of cache leafs.");
939 }
940 }
941 auto& cache = mCache.leafs[idx];
942 if (!cache.mapData.empty()) {
943 // expand into a local vector if there are greater than 16 values in the hash map
944 // and the expanded vector would contain fewer values than 256 times those in the
945 // hash map, this trades a little extra storage for faster random access performance
946 if (cache.mapData.size() > 16 &&
947 cache.totalSize < (cache.mapData.size() * 256)) {
948 if (cache.totalSize < cache.mapData.size()) {
949 throw ValueError("Cache total size is not valid.");
950 }
951 mLocalLeafVec.resize(cache.totalSize);
952 for (const auto& it : cache.mapData) {
953 assert(it.first < cache.totalSize);
954 mLocalLeafVec[it.first] = it.second;
955 }
956 mLeafVec = &mLocalLeafVec;
957 mLeafMap = nullptr;
958 }
959 else {
960 mLeafMap = &cache.mapData;
961 mLeafVec = nullptr;
962 }
963 }
964 else {
965 mLeafVec = &cache.vecData;
966 mLeafMap = nullptr;
967 }
968 }
969
970
971 template <typename T>
972 template <typename IndexIterT>
973 void CachedDeformer<T>::apply(Vec3d& position, const IndexIterT& iter) const
974 {
975 assert(*iter >= 0);
976
977 if (mLeafMap) {
978 auto it = mLeafMap->find(*iter);
979 if (it == mLeafMap->end()) return;
980 position = static_cast<openvdb::Vec3d>(it->second);
981 }
982 else {
983 assert(mLeafVec);
984
985 if (mLeafVec->empty()) return;
986 assert(*iter < mLeafVec->size());
987 position = static_cast<openvdb::Vec3d>((*mLeafVec)[*iter]);
988 }
989 }
990
991
992 } // namespace points
993 } // namespace OPENVDB_VERSION_NAME
994 } // namespace openvdb
995
996 #endif // OPENVDB_POINTS_POINT_MOVE_HAS_BEEN_INCLUDED
997
998 // Copyright (c) 2012-2018 DreamWorks Animation LLC
999 // All rights reserved. This software is distributed under the
1000 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
openvdb::v6_0::points::point_move_internal::indexOffsetFromVoxel
Index indexOffsetFromVoxel(const Index voxelOffset, const LeafT &leaf, IndexArray &offsets)
Definition: PointMove.h:423
openvdb::v6_0::points::CachedDeformer::LeafMapT
std::unordered_map< LeafIndex, Vec3T > LeafMapT
Definition: PointMove.h:131
openvdb::v6_0::points::point_move_internal::LeafIndexArray
std::vector< LeafIndex > LeafIndexArray
Definition: PointMove.h:200
openvdb::v6_0::points::DeformerTraits
Deformer Traits for optionally configuring deformers to be applied in index-space....
Definition: PointMask.h:103
openvdb::v6_0::points::NullFilter
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:77
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::PerformTypedMoveOp
Definition: PointMove.h:566
openvdb::v6_0::math::Mat4
4x4 -matrix class.
Definition: Mat3.h:49
openvdb::v6_0::points::point_move_internal::AttributeHandles::getArray
AttributeArray & getArray(const Index leafOffset)
Definition: PointMove.h:261
openvdb::v6_0::Index
Index32 Index
Definition: Types.h:61
openvdb::v6_0::Index64
uint64_t Index64
Definition: Types.h:60
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:441
openvdb::v6_0::tree::LeafIteratorBase
Base class for tree-traversal iterators over all leaf nodes (but not leaf voxels)
Definition: TreeIterator.h:1235
openvdb::v6_0::points::point_move_internal::LeafMap
std::map< Coord, LeafIndex > LeafMap
Definition: PointMove.h:202
openvdb::v6_0::points::AttributeWriteHandle
Write-able version of AttributeHandle.
Definition: AttributeArray.h:903
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::performMove
void performMove(Index targetOffset, Index sourceOffset, const LeafT &targetLeaf, IndexArray &offsets, const IndexPairArray &indices) const
Definition: PointMove.h:624
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::PerformTypedMoveOp
Definition: PointMove.h:454
openvdb.h
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::operator()
void operator()(const LeafT &leaf, size_t aIdx) const
Definition: PointMove.h:636
openvdb::v6_0::points::point_move_internal::LocalPointIndexMap
std::vector< IndexPairArray > LocalPointIndexMap
Definition: PointMove.h:196
openvdb::v6_0::points::CachedDeformer::Cache::leafs
std::vector< Leaf > leafs
Definition: PointMove.h:150
openvdb::v6_0::points::point_move_internal::AttributeHandles
Cache read and write attribute handles to amortize construction cost.
Definition: PointMove.h:254
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:550
openvdb::v6_0::points::CachedDeformer::Cache::Leaf::clear
void clear()
clear data buffers and reset counter
Definition: PointMove.h:139
openvdb::v6_0::math::Vec3d
Vec3< double > Vec3d
Definition: Vec3.h:679
openvdb::v6_0::points::point_move_internal::IndexArray
std::vector< Index > IndexArray
Definition: PointMove.h:198
openvdb::v6_0::math::Vec3
Definition: Mat.h:197
openvdb::v6_0::points::CachedDeformer::evaluate
void evaluate(PointDataGridT &grid, DeformerT &deformer, const FilterT &filter, bool threaded=true)
Definition: PointMove.h:837
openvdb::v6_0::points::CachedDeformer::Cache
Definition: PointMove.h:134
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::performTypedMove
void performTypedMove(Index sourceOffset, Index targetOffset, const LeafT &targetLeaf, IndexArray &offsets, const IndexPairArray &indices) const
Definition: PointMove.h:607
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::GlobalMovePointsOp
GlobalMovePointsOp(LeafOffsetArray &offsetMap, AttributeHandles &targetHandles, AttributeHandles &sourceHandles, const Index attributeIndex, const GlobalPointIndexMap &moveLeafMap)
Definition: PointMove.h:443
openvdb::v6_0::points::CachedDeformer::Cache::Leaf::vecData
LeafVecT vecData
Definition: PointMove.h:145
openvdb::v6_0::points::CachedDeformer::apply
void apply(Vec3d &position, const IndexIterT &iter) const
Retrieve the new position from the cache.
Definition: PointMove.h:973
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:439
openvdb::v6_0::points::CachedDeformer::reset
void reset(const LeafT &leaf, size_t idx)
Definition: PointMove.h:932
openvdb::v6_0::math::Mat3
3x3 matrix class.
Definition: Mat3.h:55
openvdb::v6_0::points::point_move_internal::BuildMoveMapsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:332
openvdb::v6_0::points::point_move_internal::BuildMoveMapsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:331
openvdb::v6_0::points::point_move_internal::AttributeHandles::getHandle
AttributeHandle< ValueT > & getHandle(const Index leafOffset)
Definition: PointMove.h:276
openvdb::v6_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:51
openvdb::v6_0::points::point_move_internal::GlobalPointIndexMap
std::vector< IndexTripleArray > GlobalPointIndexMap
Definition: PointMove.h:192
openvdb::v6_0::points::point_move_internal::LeafOffsetArray
std::vector< LeafIndexArray > LeafOffsetArray
Definition: PointMove.h:201
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::operator()
void operator()(LeafT &leaf, size_t aIdx) const
Definition: PointMove.h:520
openvdb::v6_0::points::AttributeHandle::create
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2095
openvdb::v6_0::points::point_move_internal::AttributeHandles::cache
void cache(const LeafRangeT &range, const Index attributeIndex)
Definition: PointMove.h:310
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::PerformTypedMoveOp::operator()
void operator()(const AttributeArray &) const
Definition: PointMove.h:580
openvdb::v6_0::points::point_move_internal::AttributeHandles::CacheHandleOp
Create a handle and reinterpret cast as an int handle to store.
Definition: PointMove.h:292
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::PerformTypedMoveOp::PerformTypedMoveOp
PerformTypedMoveOp(AttributeHandles &targetHandles, AttributeHandles &sourceHandles, Index targetOffset, Index sourceOffset, const LeafT &targetLeaf, IndexArray &offsets, const IndexPairArray &indices)
Definition: PointMove.h:568
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::LocalMovePointsOp
LocalMovePointsOp(LeafOffsetArray &offsetMap, AttributeHandles &targetHandles, const LeafIndexArray &sourceIndices, AttributeHandles &sourceHandles, const Index attributeIndex, const LocalPointIndexMap &moveLeafMap)
Definition: PointMove.h:553
openvdb::v6_0::points::point_move_internal::AttributeHandles::AttributeHandles
AttributeHandles(const size_t size)
Definition: PointMove.h:258
openvdb::v6_0::Index32
uint32_t Index32
Definition: Types.h:59
openvdb::v6_0::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:62
openvdb::v6_0::points::CachedDeformer
A Deformer that caches the resulting positions from evaluating another Deformer.
Definition: PointMove.h:125
openvdb::v6_0::points::point_move_internal::AttributeHandles::getWriteHandle
AttributeWriteHandle< ValueT > & getWriteHandle(const Index leafOffset)
Definition: PointMove.h:284
openvdb::v6_0::math::Transform::indexToWorld
Vec3d indexToWorld(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:135
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:136
openvdb::v6_0::math::Coord::asVec3d
Vec3d asVec3d() const
Definition: Coord.h:170
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp
Definition: PointMove.h:547
openvdb::v6_0::points::point_move_internal::processTypedArray
bool processTypedArray(const ArrayType &array, OpType &op)
Utility function that, given a generic attribute array, calls a functor with the fully-resolved value...
Definition: PointMove.h:227
openvdb
Definition: Exceptions.h:40
openvdb::v6_0::math::Quat
Definition: Mat.h:196
openvdb::v6_0::points::point_move_internal::BuildMoveMapsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:333
openvdb::v6_0::points::point_move_internal::AttributeHandles::getConstArray
const AttributeArray & getConstArray(const Index leafOffset) const
Definition: PointMove.h:268
openvdb::v6_0::IndexError
Definition: Exceptions.h:84
openvdb::v6_0::math::Transform
Definition: Transform.h:66
openvdb::v6_0::points::point_move_internal::BuildMoveMapsOp::BuildMoveMapsOp
BuildMoveMapsOp(const DeformerT &deformer, GlobalPointIndexMap &globalMoveLeafMap, LocalPointIndexMap &localMoveLeafMap, const LeafMap &targetLeafMap, const math::Transform &targetTransform, const math::Transform &sourceTransform, const FilterT &filter)
Definition: PointMove.h:335
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::PerformTypedMoveOp::operator()
void operator()(const AttributeArray &) const
Definition: PointMove.h:467
openvdb::v6_0::tree::LeafManager
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::performMove
void performMove(Index targetOffset, const LeafT &targetLeaf, IndexArray &offsets, const IndexTripleArray &indices) const
Definition: PointMove.h:508
openvdb::v6_0::points::CachedDeformer::LeafVecT
std::vector< Vec3T > LeafVecT
Definition: PointMove.h:130
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::LeafT
typename TreeT::LeafNodeType LeafT
Definition: PointMove.h:549
openvdb::v6_0::points::point_move_internal::AttributeHandles::CacheHandleOp::operator()
void operator()(const AttributeArray &array) const
Definition: PointMove.h:298
PointMask.h
Methods for extracting masks from VDB Point grids.
openvdb::v6_0::points::movePoints
void movePoints(PointDataGridT &points, const math::Transform &transform, DeformerT &deformer, const FilterT &filter=NullFilter(), future::Advect *objectNotInUse=nullptr, bool threaded=true)
Move points in a PointDataGrid using a custom deformer and a new transform.
Definition: PointMove.h:676
openvdb::v6_0::points::point_move_internal::AttributeHandles::CacheHandleOp::CacheHandleOp
CacheHandleOp(HandleArray &handles)
Definition: PointMove.h:294
openvdb::v6_0::math::Coord::round
static Coord round(const Vec3< T > &xyz)
Return xyz rounded to the closest integer coordinates (cell centered conversion).
Definition: Coord.h:77
openvdb::v6_0::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
openvdb::v6_0::points::CachedDeformer::Cache::Leaf::mapData
LeafMapT mapData
Definition: PointMove.h:146
openvdb::v6_0::points::AttributeArray
Base class for storing attribute data.
Definition: AttributeArray.h:118
openvdb::v6_0::points::point_move_internal::BuildMoveMapsOp
Definition: PointMove.h:329
openvdb::v6_0::points::AttributeHandle
Definition: AttributeArray.h:832
openvdb::v6_0::points::index::ALL
Definition: IndexIterator.h:70
openvdb::v6_0::points::point_move_internal::BuildMoveMapsOp::operator()
void operator()(LeafT &leaf, size_t idx) const
Definition: PointMove.h:350
PointDataGrid.h
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
openvdb::v6_0::points::point_move_internal::IndexTriple
std::tuple< LeafIndex, Index, Index > IndexTriple
Definition: PointMove.h:190
openvdb::v6_0::points::point_move_internal::IndexTripleArray
tbb::concurrent_vector< IndexTriple > IndexTripleArray
Definition: PointMove.h:191
openvdb::v6_0::points::point_move_internal::IndexPair
std::pair< Index, Index > IndexPair
Definition: PointMove.h:194
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::PerformTypedMoveOp::PerformTypedMoveOp
PerformTypedMoveOp(AttributeHandles &targetHandles, AttributeHandles &sourceHandles, Index targetOffset, const LeafT &targetLeaf, IndexArray &offsets, const IndexTripleArray &indices)
Definition: PointMove.h:456
openvdb::v6_0::points::point_move_internal::LeafIndex
Index32 LeafIndex
Definition: PointMove.h:120
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp
Definition: PointMove.h:437
openvdb::v6_0::points::CachedDeformer::Vec3T
typename math::Vec3< T > Vec3T
Definition: PointMove.h:129
openvdb::v6_0::ValueError
Definition: Exceptions.h:92
openvdb::v6_0::points::CachedDeformer::LeafIndex
point_move_internal::LeafIndex LeafIndex
Definition: PointMove.h:128
openvdb::v6_0::points::CachedDeformer::Cache::Leaf
Definition: PointMove.h:136
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:188
openvdb::v6_0::points::point_move_internal::ArrayProcessor
Helper class used internally by processTypedArray()
Definition: PointMove.h:213
openvdb::v6_0::points::point_move_internal::ArrayProcessor::call
static void call(OpType &op, const AttributeArray &array)
Definition: PointMove.h:214
openvdb::v6_0::points::point_move_internal::LocalMovePointsOp::LeafManagerT
typename tree::LeafManager< TreeT > LeafManagerT
Definition: PointMove.h:551
openvdb::v6_0::points::future::Advect
Definition: PointMove.h:86
openvdb::v6_0::points::AttributeHandle::size
Index size() const
Definition: AttributeArray.h:855
openvdb::v6_0::points::point_move_internal::AttributeHandles::HandleArray
std::vector< AttributeHandle< int >::Ptr > HandleArray
Definition: PointMove.h:256
openvdb::v6_0::points::point_move_internal::IndexPairArray
std::vector< IndexPair > IndexPairArray
Definition: PointMove.h:195
openvdb::v6_0::points::point_move_internal::GlobalMovePointsOp::LeafArrayT
std::vector< LeafT * > LeafArrayT
Definition: PointMove.h:440