HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointConversion.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
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 //
29 ///////////////////////////////////////////////////////////////////////////
30 
31 /// @author Dan Bailey, Nick Avramoussis
32 ///
33 /// @file points/PointConversion.h
34 ///
35 /// @brief Convert points and attributes to and from VDB Point Data grids.
36 
37 #ifndef OPENVDB_POINTS_POINT_CONVERSION_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_POINT_CONVERSION_HAS_BEEN_INCLUDED
39 
40 #include <openvdb/math/Transform.h>
41 
45 
46 #include "AttributeArrayString.h"
47 #include "AttributeSet.h"
48 #include "IndexFilter.h"
49 #include "PointAttribute.h"
50 #include "PointDataGrid.h"
51 #include "PointGroup.h"
52 
53 #include <tbb/parallel_reduce.h>
54 
55 #include <type_traits>
56 
57 namespace openvdb {
59 namespace OPENVDB_VERSION_NAME {
60 namespace points {
61 
62 
63 /// @brief Localises points with position into a @c PointDataGrid into two stages:
64 /// allocation of the leaf attribute data and population of the positions.
65 ///
66 /// @param pointIndexGrid a PointIndexGrid into the points.
67 /// @param positions list of world space point positions.
68 /// @param xform world to index space transform.
69 /// @param positionDefaultValue metadata default position value
70 ///
71 /// @note The position data must be supplied in a Point-Partitioner compatible
72 /// data structure. A convenience PointAttributeVector class is offered.
73 ///
74 /// @note The position data is populated separately to perform world space to
75 /// voxel space conversion and apply quantisation.
76 ///
77 /// @note A @c PointIndexGrid to the points must be supplied to perform this
78 /// operation. Typically this is built implicitly by the PointDataGrid constructor.
79 
80 template<
81  typename CompressionT,
82  typename PointDataGridT,
83  typename PositionArrayT,
84  typename PointIndexGridT>
85 inline typename PointDataGridT::Ptr
86 createPointDataGrid(const PointIndexGridT& pointIndexGrid,
87  const PositionArrayT& positions,
88  const math::Transform& xform,
89  Metadata::Ptr positionDefaultValue = Metadata::Ptr());
90 
91 
92 /// @brief Convenience method to create a @c PointDataGrid from a std::vector of
93 /// point positions.
94 ///
95 /// @param positions list of world space point positions.
96 /// @param xform world to index space transform.
97 /// @param positionDefaultValue metadata default position value
98 ///
99 /// @note This method implicitly wraps the std::vector for a Point-Partitioner compatible
100 /// data structure and creates the required @c PointIndexGrid to the points.
101 
102 template <typename CompressionT, typename PointDataGridT, typename ValueT>
103 inline typename PointDataGridT::Ptr
104 createPointDataGrid(const std::vector<ValueT>& positions,
105  const math::Transform& xform,
106  Metadata::Ptr positionDefaultValue = Metadata::Ptr());
107 
108 
109 /// @brief Stores point attribute data in an existing @c PointDataGrid attribute.
110 ///
111 /// @param tree the PointDataGrid to be populated.
112 /// @param pointIndexTree a PointIndexTree into the points.
113 /// @param attributeName the name of the VDB Points attribute to be populated.
114 /// @param data a wrapper to the attribute data.
115 /// @param stride the stride of the attribute
116 /// @param insertMetadata true if strings are to be automatically inserted as metadata.
117 ///
118 /// @note A @c PointIndexGrid to the points must be supplied to perform this
119 /// operation. This is required to ensure the same point index ordering.
120 template <typename PointDataTreeT, typename PointIndexTreeT, typename PointArrayT>
121 inline void
122 populateAttribute( PointDataTreeT& tree,
123  const PointIndexTreeT& pointIndexTree,
124  const openvdb::Name& attributeName,
125  const PointArrayT& data,
126  const Index stride = 1,
127  const bool insertMetadata = true);
128 
129 /// @brief Convert the position attribute from a Point Data Grid
130 ///
131 /// @param positionAttribute the position attribute to be populated.
132 /// @param grid the PointDataGrid to be converted.
133 /// @param pointOffsets a vector of cumulative point offsets for each leaf
134 /// @param startOffset a value to shift all the point offsets by
135 /// @param filter an index filter
136 /// @param inCoreOnly true if out-of-core leaf nodes are to be ignored
137 ///
138 
139 template <typename PositionAttribute, typename PointDataGridT, typename FilterT = NullFilter>
140 inline void
141 convertPointDataGridPosition( PositionAttribute& positionAttribute,
142  const PointDataGridT& grid,
143  const std::vector<Index64>& pointOffsets,
144  const Index64 startOffset,
145  const FilterT& filter = NullFilter(),
146  const bool inCoreOnly = false);
147 
148 
149 /// @brief Convert the attribute from a PointDataGrid
150 ///
151 /// @param attribute the attribute to be populated.
152 /// @param tree the PointDataTree to be converted.
153 /// @param pointOffsets a vector of cumulative point offsets for each leaf.
154 /// @param startOffset a value to shift all the point offsets by
155 /// @param arrayIndex the index in the Descriptor of the array to be converted.
156 /// @param stride the stride of the attribute
157 /// @param filter an index filter
158 /// @param inCoreOnly true if out-of-core leaf nodes are to be ignored
159 template <typename TypedAttribute, typename PointDataTreeT, typename FilterT = NullFilter>
160 inline void
162  const PointDataTreeT& tree,
163  const std::vector<Index64>& pointOffsets,
164  const Index64 startOffset,
165  const unsigned arrayIndex,
166  const Index stride = 1,
167  const FilterT& filter = NullFilter(),
168  const bool inCoreOnly = false);
169 
170 
171 /// @brief Convert the group from a PointDataGrid
172 ///
173 /// @param group the group to be populated.
174 /// @param tree the PointDataTree to be converted.
175 /// @param pointOffsets a vector of cumulative point offsets for each leaf
176 /// @param startOffset a value to shift all the point offsets by
177 /// @param index the group index to be converted.
178 /// @param filter an index filter
179 /// @param inCoreOnly true if out-of-core leaf nodes are to be ignored
180 ///
181 
182 template <typename Group, typename PointDataTreeT, typename FilterT = NullFilter>
183 inline void
184 convertPointDataGridGroup( Group& group,
185  const PointDataTreeT& tree,
186  const std::vector<Index64>& pointOffsets,
187  const Index64 startOffset,
188  const AttributeSet::Descriptor::GroupIndex index,
189  const FilterT& filter = NullFilter(),
190  const bool inCoreOnly = false);
191 
192 /// @ brief Given a container of world space positions and a target points per voxel,
193 /// compute a uniform voxel size that would best represent the storage of the points in a grid.
194 /// This voxel size is typically used for conversion of the points into a PointDataGrid.
195 ///
196 /// @param positions array of world space positions
197 /// @param pointsPerVoxel the target number of points per voxel, must be positive and non-zero
198 /// @param transform voxel size will be computed using this optional transform if provided
199 /// @param decimalPlaces for readability, truncate voxel size to this number of decimals
200 /// @param interrupter an optional interrupter
201 ///
202 /// @note if none or one point provided in positions, the default voxel size of 0.1 will be returned
203 ///
204 template<typename PositionWrapper, typename InterrupterT = openvdb::util::NullInterrupter>
205 inline float
206 computeVoxelSize( const PositionWrapper& positions,
207  const uint32_t pointsPerVoxel,
209  const Index decimalPlaces = 5,
210  InterrupterT* const interrupter = nullptr);
211 
212 
213 ////////////////////////////////////////
214 
215 
216 /// @brief Point-partitioner compatible STL vector attribute wrapper for convenience
217 template<typename ValueType>
219 public:
220  using PosType = ValueType;
221  using value_type= ValueType;
222 
223  PointAttributeVector(const std::vector<value_type>& data,
224  const Index stride = 1)
225  : mData(data)
226  , mStride(stride) { }
227 
228  size_t size() const { return mData.size(); }
229  void getPos(size_t n, ValueType& xyz) const { xyz = mData[n]; }
230  void get(ValueType& value, size_t n) const { value = mData[n]; }
231  void get(ValueType& value, size_t n, openvdb::Index m) const { value = mData[n * mStride + m]; }
232 
233 private:
234  const std::vector<value_type>& mData;
235  const Index mStride;
236 }; // PointAttributeVector
237 
238 
239 ////////////////////////////////////////
240 
241 
242 namespace point_conversion_internal {
243 
244 
245 // ConversionTraits to create the relevant Attribute Handles from a LeafNode
246 template <typename T> struct ConversionTraits
247 {
250  static T zero() { return zeroVal<T>(); }
251  template <typename LeafT>
252  static typename Handle::Ptr handleFromLeaf(LeafT& leaf, Index index) {
253  const AttributeArray& array = leaf.constAttributeArray(index);
254  return Handle::create(array);
255  }
256  template <typename LeafT>
257  static typename WriteHandle::Ptr writeHandleFromLeaf(LeafT& leaf, Index index) {
258  AttributeArray& array = leaf.attributeArray(index);
259  return WriteHandle::create(array);
260  }
261 }; // ConversionTraits
262 template <> struct ConversionTraits<openvdb::Name>
263 {
266  static openvdb::Name zero() { return ""; }
267  template <typename LeafT>
268  static typename Handle::Ptr handleFromLeaf(LeafT& leaf, Index index) {
269  const AttributeArray& array = leaf.constAttributeArray(index);
270  const AttributeSet::Descriptor& descriptor = leaf.attributeSet().descriptor();
271  return Handle::create(array, descriptor.getMetadata());
272  }
273  template <typename LeafT>
274  static typename WriteHandle::Ptr writeHandleFromLeaf(LeafT& leaf, Index index) {
275  AttributeArray& array = leaf.attributeArray(index);
276  const AttributeSet::Descriptor& descriptor = leaf.attributeSet().descriptor();
277  return WriteHandle::create(array, descriptor.getMetadata());
278  }
279 }; // ConversionTraits<openvdb::Name>
280 
281 
282 template<typename PointDataTreeType, typename PointIndexTreeType>
284 
286  using LeafRangeT = typename LeafManagerT::LeafRange;
287 
288  using PointIndexLeafNode = typename PointIndexTreeType::LeafNodeType;
290 
291  InitialiseAttributesOp( const PointIndexTreeType& pointIndexTree,
292  const AttributeSet::Descriptor::Ptr& attributeDescriptor)
293  : mPointIndexTree(pointIndexTree)
294  , mAttributeDescriptor(attributeDescriptor) { }
295 
296  void operator()(const typename LeafManagerT::LeafRange& range) const {
297  for (auto leaf = range.begin(); leaf; ++leaf) {
298 
299  // obtain the PointIndexLeafNode (using the origin of the current leaf)
300 
301  const PointIndexLeafNode* pointIndexLeaf = mPointIndexTree.probeConstLeaf(leaf->origin());
302 
303  if (!pointIndexLeaf) continue;
304 
305  // initialise the attribute storage
306 
307  const IndexArray& indices = pointIndexLeaf->indices();
308 
309  auto pointCount = static_cast<Index>(indices.size());
310 
311  leaf->initializeAttributes(mAttributeDescriptor, pointCount);
312  }
313  }
314 
315  //////////
316 
317  const PointIndexTreeType& mPointIndexTree;
318  const AttributeSet::Descriptor::Ptr& mAttributeDescriptor;
319 };
320 
321 template< typename PointDataTreeType,
322  typename PointIndexTreeType,
323  typename PositionListType>
325 
327  using LeafRangeT = typename LeafManagerT::LeafRange;
328 
329  using PointIndexLeafNode = typename PointIndexTreeType::LeafNodeType;
331 
333 
334  PopulatePositionAttributeOp(const PointIndexTreeType& pointIndexTree,
335  const math::Transform& transform,
336  const PositionListType& positions)
337  : mPointIndexTree(pointIndexTree)
338  , mTransform(transform)
339  , mPositions(positions) { }
340 
341  void operator()(const typename LeafManagerT::LeafRange& range) const {
342 
343  for (auto leaf = range.begin(); leaf; ++leaf) {
344 
345  // obtain the PointIndexLeafNode (using the origin of the current leaf)
346 
347  const PointIndexLeafNode* pointIndexLeaf = mPointIndexTree.probeConstLeaf(leaf->origin());
348 
349  if (!pointIndexLeaf) continue;
350 
351  auto attributeWriteHandle = AttributeWriteHandle<Vec3f>::create(leaf->attributeArray("P"));
352 
353  Index64 index = 0;
354 
355  const IndexArray& indices = pointIndexLeaf->indices();
356 
357  for (const Index64 i: indices) {
358  ValueType positionWorldSpace;
359  mPositions.getPos(i, positionWorldSpace);
360 
361  const ValueType positionIndexSpace = mTransform.worldToIndex(positionWorldSpace);
362 
363  const ValueType positionVoxelSpace = ValueType(
364  positionIndexSpace.x() - math::Round(positionIndexSpace.x()),
365  positionIndexSpace.y() - math::Round(positionIndexSpace.y()),
366  positionIndexSpace.z() - math::Round(positionIndexSpace.z()));
367 
368  attributeWriteHandle->set(static_cast<Index>(index), Vec3f(positionVoxelSpace));
369 
370  index++;
371  }
372  }
373  }
374 
375  //////////
376 
377  const PointIndexTreeType& mPointIndexTree;
379  const PositionListType& mPositions;
380 };
381 
382 template< typename PointDataTreeType,
383  typename PointIndexTreeType,
384  typename AttributeListType>
386 
388  using LeafRangeT = typename LeafManagerT::LeafRange;
389  using PointIndexLeafNode = typename PointIndexTreeType::LeafNodeType;
393 
394  PopulateAttributeOp(const PointIndexTreeType& pointIndexTree,
395  const AttributeListType& data,
396  const size_t index,
397  const Index stride = 1)
398  : mPointIndexTree(pointIndexTree)
399  , mData(data)
400  , mIndex(index)
401  , mStride(stride) { }
402 
403  void operator()(const typename LeafManagerT::LeafRange& range) const {
404 
405  for (auto leaf = range.begin(); leaf; ++leaf) {
406 
407  // obtain the PointIndexLeafNode (using the origin of the current leaf)
408 
409  const PointIndexLeafNode* pointIndexLeaf =
410  mPointIndexTree.probeConstLeaf(leaf->origin());
411 
412  if (!pointIndexLeaf) continue;
413 
414  typename HandleT::Ptr attributeWriteHandle =
415  ConversionTraits<ValueType>::writeHandleFromLeaf(*leaf, static_cast<Index>(mIndex));
416 
417  Index64 index = 0;
418 
419  const IndexArray& indices = pointIndexLeaf->indices();
420 
421  for (const Index64 leafIndex: indices)
422  {
424  for (Index i = 0; i < mStride; i++) {
425  mData.get(value, leafIndex, i);
426  attributeWriteHandle->set(static_cast<Index>(index), i, value);
427  }
428  index++;
429  }
430 
431  // attempt to compact the array
432 
433  attributeWriteHandle->compact();
434  }
435  }
436 
437  //////////
438 
439  const PointIndexTreeType& mPointIndexTree;
440  const AttributeListType& mData;
441  const size_t mIndex;
442  const Index mStride;
443 };
444 
445 template<typename PointDataTreeType, typename Attribute, typename FilterT>
447 
448  using LeafNode = typename PointDataTreeType::LeafNodeType;
449  using ValueType = typename Attribute::ValueType;
450  using HandleT = typename Attribute::Handle;
453  using LeafRangeT = typename LeafManagerT::LeafRange;
454 
456  const std::vector<Index64>& pointOffsets,
457  const Index64 startOffset,
458  const math::Transform& transform,
459  const size_t index,
460  const FilterT& filter,
461  const bool inCoreOnly)
462  : mAttribute(attribute)
463  , mPointOffsets(pointOffsets)
464  , mStartOffset(startOffset)
465  , mTransform(transform)
466  , mIndex(index)
467  , mFilter(filter)
468  , mInCoreOnly(inCoreOnly)
469  {
470  // only accept Vec3f as ValueType
471  static_assert(VecTraits<ValueType>::Size == 3 &&
473  "ValueType is not Vec3f");
474  }
475 
476  template <typename IterT>
477  void convert(IterT& iter, HandleT& targetHandle,
478  SourceHandleT& sourceHandle, Index64& offset) const
479  {
480  for (; iter; ++iter) {
481  const Vec3d xyz = iter.getCoord().asVec3d();
482  const Vec3d pos = sourceHandle.get(*iter);
483  targetHandle.set(static_cast<Index>(offset++), /*stride=*/0,
484  mTransform.indexToWorld(pos + xyz));
485  }
486  }
487 
488  void operator()(const LeafRangeT& range) const
489  {
490  HandleT pHandle(mAttribute);
491 
492  for (auto leaf = range.begin(); leaf; ++leaf) {
493 
494  assert(leaf.pos() < mPointOffsets.size());
495 
496  if (mInCoreOnly && leaf->buffer().isOutOfCore()) continue;
497 
499 
500  if (leaf.pos() > 0) offset += mPointOffsets[leaf.pos() - 1];
501 
502  auto handle = SourceHandleT::create(leaf->constAttributeArray(mIndex));
503 
504  if (mFilter.state() == index::ALL) {
505  auto iter = leaf->beginIndexOn();
506  convert(iter, pHandle, *handle, offset);
507  }
508  else {
509  auto iter = leaf->beginIndexOn(mFilter);
510  convert(iter, pHandle, *handle, offset);
511  }
512  }
513  }
514 
515  //////////
516 
518  const std::vector<Index64>& mPointOffsets;
521  const size_t mIndex;
522  const FilterT& mFilter;
523  const bool mInCoreOnly;
524 }; // ConvertPointDataGridPositionOp
525 
526 
527 template<typename PointDataTreeType, typename Attribute, typename FilterT>
529 
530  using LeafNode = typename PointDataTreeType::LeafNodeType;
531  using ValueType = typename Attribute::ValueType;
532  using HandleT = typename Attribute::Handle;
535  using LeafRangeT = typename LeafManagerT::LeafRange;
536 
538  const std::vector<Index64>& pointOffsets,
539  const Index64 startOffset,
540  const size_t index,
541  const Index stride,
542  const FilterT& filter,
543  const bool inCoreOnly)
544  : mAttribute(attribute)
545  , mPointOffsets(pointOffsets)
546  , mStartOffset(startOffset)
547  , mIndex(index)
548  , mStride(stride)
549  , mFilter(filter)
550  , mInCoreOnly(inCoreOnly) { }
551 
552  template <typename IterT>
553  void convert(IterT& iter, HandleT& targetHandle,
554  SourceHandleT& sourceHandle, Index64& offset) const
555  {
556  if (sourceHandle.isUniform()) {
557  const ValueType uniformValue(sourceHandle.get(0));
558  for (; iter; ++iter) {
559  for (Index i = 0; i < mStride; i++) {
560  targetHandle.set(static_cast<Index>(offset), i, uniformValue);
561  }
562  offset++;
563  }
564  }
565  else {
566  for (; iter; ++iter) {
567  for (Index i = 0; i < mStride; i++) {
568  targetHandle.set(static_cast<Index>(offset), i,
569  sourceHandle.get(*iter, /*stride=*/i));
570  }
571  offset++;
572  }
573  }
574  }
575 
576  void operator()(const LeafRangeT& range) const
577  {
578  HandleT pHandle(mAttribute);
579 
580  for (auto leaf = range.begin(); leaf; ++leaf) {
581 
582  assert(leaf.pos() < mPointOffsets.size());
583 
584  if (mInCoreOnly && leaf->buffer().isOutOfCore()) continue;
585 
587 
588  if (leaf.pos() > 0) offset += mPointOffsets[leaf.pos() - 1];
589 
590  typename SourceHandleT::Ptr handle = ConversionTraits<ValueType>::handleFromLeaf(
591  *leaf, static_cast<Index>(mIndex));
592 
593  if (mFilter.state() == index::ALL) {
594  auto iter = leaf->beginIndexOn();
595  convert(iter, pHandle, *handle, offset);
596  } else {
597  auto iter = leaf->beginIndexOn(mFilter);
598  convert(iter, pHandle, *handle, offset);
599  }
600  }
601  }
602 
603  //////////
604 
606  const std::vector<Index64>& mPointOffsets;
608  const size_t mIndex;
609  const Index mStride;
610  const FilterT& mFilter;
611  const bool mInCoreOnly;
612 }; // ConvertPointDataGridAttributeOp
613 
614 template<typename PointDataTreeType, typename Group, typename FilterT>
616 
617  using LeafNode = typename PointDataTreeType::LeafNodeType;
618  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
620  using LeafRangeT = typename LeafManagerT::LeafRange;
621 
623  const std::vector<Index64>& pointOffsets,
624  const Index64 startOffset,
625  const AttributeSet::Descriptor::GroupIndex index,
626  const FilterT& filter,
627  const bool inCoreOnly)
628  : mGroup(group)
629  , mPointOffsets(pointOffsets)
630  , mStartOffset(startOffset)
631  , mIndex(index)
632  , mFilter(filter)
633  , mInCoreOnly(inCoreOnly) { }
634 
635  template <typename IterT>
636  void convert(IterT& iter, const GroupAttributeArray& groupArray, Index64& offset) const
637  {
638  const auto bitmask = static_cast<GroupType>(1 << mIndex.second);
639 
640  if (groupArray.isUniform()) {
641  if (groupArray.get(0) & bitmask) {
642  for (; iter; ++iter) {
643  mGroup.setOffsetOn(static_cast<Index>(offset));
644  offset++;
645  }
646  }
647  }
648  else {
649  for (; iter; ++iter) {
650  if (groupArray.get(*iter) & bitmask) {
651  mGroup.setOffsetOn(static_cast<Index>(offset));
652  }
653  offset++;
654  }
655  }
656  }
657 
658  void operator()(const LeafRangeT& range) const
659  {
660  for (auto leaf = range.begin(); leaf; ++leaf) {
661 
662  assert(leaf.pos() < mPointOffsets.size());
663 
664  if (mInCoreOnly && leaf->buffer().isOutOfCore()) continue;
665 
667 
668  if (leaf.pos() > 0) offset += mPointOffsets[leaf.pos() - 1];
669 
670  const AttributeArray& array = leaf->constAttributeArray(mIndex.first);
671  assert(isGroup(array));
672  const GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
673 
674  if (mFilter.state() == index::ALL) {
675  auto iter = leaf->beginIndexOn();
676  convert(iter, groupArray, offset);
677  }
678  else {
679  auto iter = leaf->beginIndexOn(mFilter);
680  convert(iter, groupArray, offset);
681  }
682  }
683  }
684 
685  //////////
686 
687  Group& mGroup;
688  const std::vector<Index64>& mPointOffsets;
691  const FilterT& mFilter;
692  const bool mInCoreOnly;
693 }; // ConvertPointDataGridGroupOp
694 
695 template<typename PositionArrayT>
697 {
698  CalculatePositionBounds(const PositionArrayT& positions,
699  const math::Mat4d& inverse)
700  : mPositions(positions)
701  , mInverseMat(inverse)
702  , mMin(std::numeric_limits<Real>::max())
703  , mMax(-std::numeric_limits<Real>::max()) {}
704 
706  : mPositions(other.mPositions)
707  , mInverseMat(other.mInverseMat)
708  , mMin(std::numeric_limits<Real>::max())
709  , mMax(-std::numeric_limits<Real>::max()) {}
710 
711  void operator()(const tbb::blocked_range<size_t>& range) {
712  Vec3R pos;
713  for (size_t n = range.begin(), N = range.end(); n != N; ++n) {
714  mPositions.getPos(n, pos);
715  pos = mInverseMat.transform(pos);
716  mMin = math::minComponent(mMin, pos);
717  mMax = math::maxComponent(mMax, pos);
718  }
719  }
720 
721  void join(const CalculatePositionBounds& other) {
722  mMin = math::minComponent(mMin, other.mMin);
723  mMax = math::maxComponent(mMax, other.mMax);
724  }
725 
727  return BBoxd(mMin, mMax);
728  }
729 
730 private:
731  const PositionArrayT& mPositions;
732  const math::Mat4d& mInverseMat;
733  Vec3R mMin, mMax;
734 };
735 
736 } // namespace point_conversion_internal
737 
738 
739 ////////////////////////////////////////
740 
741 
742 template<typename CompressionT, typename PointDataGridT, typename PositionArrayT, typename PointIndexGridT>
743 inline typename PointDataGridT::Ptr
744 createPointDataGrid(const PointIndexGridT& pointIndexGrid, const PositionArrayT& positions,
745  const math::Transform& xform, Metadata::Ptr positionDefaultValue)
746 {
747  using PointDataTreeT = typename PointDataGridT::TreeType;
748  using PointIndexTreeT = typename PointIndexGridT::TreeType;
749  using LeafManagerT = typename tree::LeafManager<PointDataTreeT>;
750  using LeafRangeT = typename LeafManagerT::LeafRange;
751  using PositionAttributeT = TypedAttributeArray<Vec3f, CompressionT>;
752 
755 
756  const NamePair positionType = PositionAttributeT::attributeType();
757 
758  // construct the Tree using a topology copy of the PointIndexGrid
759 
760  const PointIndexTreeT& pointIndexTree(pointIndexGrid.tree());
761  typename PointDataTreeT::Ptr treePtr(new PointDataTreeT(pointIndexTree));
762 
763  LeafManagerT leafManager = LeafManagerT(*treePtr);
764  LeafRangeT leafRange = leafManager.leafRange();
765 
766  // create attribute descriptor from position type
767 
768  auto descriptor = AttributeSet::Descriptor::create(positionType);
769 
770  // add default value for position if provided
771 
772  if (positionDefaultValue) descriptor->setDefaultValue("P", *positionDefaultValue);
773 
774  // create point attribute storage on each leaf
775 
776  InitialiseAttributesOp<PointDataTreeT, PointIndexTreeT> initialise(
777  pointIndexGrid.tree(), descriptor);
778  tbb::parallel_for(leafRange, initialise);
779 
780  // populate position attribute
781 
782  PopulatePositionAttributeOp<PointDataTreeT,
783  PointIndexTreeT,
784  PositionArrayT> populate(pointIndexTree,
785  xform,
786  positions);
787 
788  tbb::parallel_for(leafRange, populate);
789 
790  auto grid = PointDataGridT::create(treePtr);
791  grid->setTransform(xform.copy());
792  return grid;
793 }
794 
795 
796 ////////////////////////////////////////
797 
798 
799 template <typename CompressionT, typename PointDataGridT, typename ValueT>
800 inline typename PointDataGridT::Ptr
801 createPointDataGrid(const std::vector<ValueT>& positions,
802  const math::Transform& xform,
803  Metadata::Ptr positionDefaultValue)
804 {
805  const PointAttributeVector<ValueT> pointList(positions);
806 
807  tools::PointIndexGrid::Ptr pointIndexGrid = tools::createPointIndexGrid<tools::PointIndexGrid>(pointList, xform);
808  return createPointDataGrid<CompressionT, PointDataGridT>(*pointIndexGrid, pointList, xform, positionDefaultValue);
809 }
810 
811 
812 ////////////////////////////////////////
813 
814 
815 template <typename PointDataTreeT, typename PointIndexTreeT, typename PointArrayT>
816 inline void
817 populateAttribute(PointDataTreeT& tree, const PointIndexTreeT& pointIndexTree,
818  const openvdb::Name& attributeName, const PointArrayT& data, const Index stride,
819  const bool insertMetadata)
820 {
822  using ValueType = typename PointArrayT::value_type;
823 
824  auto iter = tree.cbeginLeaf();
825 
826  if (!iter) return;
827 
828  const size_t index = iter->attributeSet().find(attributeName);
829 
830  if (index == AttributeSet::INVALID_POS) {
831  OPENVDB_THROW(KeyError, "Attribute not found to populate - " << attributeName << ".");
832  }
833 
834  if (insertMetadata) {
836  }
837 
838  // populate attribute
839 
840  typename tree::LeafManager<PointDataTreeT> leafManager(tree);
841 
842  PopulateAttributeOp<PointDataTreeT,
843  PointIndexTreeT,
844  PointArrayT> populate(pointIndexTree, data, index, stride);
845  tbb::parallel_for(leafManager.leafRange(), populate);
846 }
847 
848 
849 ////////////////////////////////////////
850 
851 
852 template <typename PositionAttribute, typename PointDataGridT, typename FilterT>
853 inline void
854 convertPointDataGridPosition( PositionAttribute& positionAttribute,
855  const PointDataGridT& grid,
856  const std::vector<Index64>& pointOffsets,
857  const Index64 startOffset,
858  const FilterT& filter,
859  const bool inCoreOnly)
860 {
861  using TreeType = typename PointDataGridT::TreeType;
862  using LeafManagerT = typename tree::LeafManager<const TreeType>;
863 
865 
866  const TreeType& tree = grid.tree();
867  auto iter = tree.cbeginLeaf();
868 
869  if (!iter) return;
870 
871  const size_t positionIndex = iter->attributeSet().find("P");
872 
873  positionAttribute.expand();
874  LeafManagerT leafManager(tree);
875  ConvertPointDataGridPositionOp<TreeType, PositionAttribute, FilterT> convert(
876  positionAttribute, pointOffsets, startOffset, grid.transform(), positionIndex,
877  filter, inCoreOnly);
878  tbb::parallel_for(leafManager.leafRange(), convert);
879  positionAttribute.compact();
880 }
881 
882 
883 ////////////////////////////////////////
884 
885 
886 template <typename TypedAttribute, typename PointDataTreeT, typename FilterT>
887 inline void
889  const PointDataTreeT& tree,
890  const std::vector<Index64>& pointOffsets,
891  const Index64 startOffset,
892  const unsigned arrayIndex,
893  const Index stride,
894  const FilterT& filter,
895  const bool inCoreOnly)
896 {
897  using LeafManagerT = typename tree::LeafManager<const PointDataTreeT>;
898 
900 
901  auto iter = tree.cbeginLeaf();
902 
903  if (!iter) return;
904 
905  attribute.expand();
906  LeafManagerT leafManager(tree);
907  ConvertPointDataGridAttributeOp<PointDataTreeT, TypedAttribute, FilterT> convert(
908  attribute, pointOffsets, startOffset, arrayIndex, stride,
909  filter, inCoreOnly);
910  tbb::parallel_for(leafManager.leafRange(), convert);
911  attribute.compact();
912 }
913 
914 
915 ////////////////////////////////////////
916 
917 
918 template <typename Group, typename PointDataTreeT, typename FilterT>
919 inline void
921  const PointDataTreeT& tree,
922  const std::vector<Index64>& pointOffsets,
923  const Index64 startOffset,
924  const AttributeSet::Descriptor::GroupIndex index,
925  const FilterT& filter,
926  const bool inCoreOnly)
927 {
928  using LeafManagerT= typename tree::LeafManager<const PointDataTreeT>;
929 
931 
932  auto iter = tree.cbeginLeaf();
933  if (!iter) return;
934 
935  LeafManagerT leafManager(tree);
936  ConvertPointDataGridGroupOp<PointDataTree, Group, FilterT> convert(
937  group, pointOffsets, startOffset, index,
938  filter, inCoreOnly);
939  tbb::parallel_for(leafManager.leafRange(), convert);
940 
941  // must call this after modifying point groups in parallel
942 
943  group.finalize();
944 }
945 
946 template<typename PositionWrapper, typename InterrupterT>
947 inline float
948 computeVoxelSize( const PositionWrapper& positions,
949  const uint32_t pointsPerVoxel,
950  const math::Mat4d transform,
951  const Index decimalPlaces,
952  InterrupterT* const interrupter)
953 {
954  using namespace point_conversion_internal;
955 
956  struct Local {
957 
958  static bool voxelSizeFromVolume(const double volume,
959  const size_t estimatedVoxelCount,
960  float& voxelSize)
961  {
962  // dictated by the math::ScaleMap limit
963  static const double minimumVoxelVolume(3e-15);
964  static const double maximumVoxelVolume(std::numeric_limits<float>::max());
965 
966  double voxelVolume = volume / static_cast<double>(estimatedVoxelCount);
967  bool valid = true;
968 
969  if (voxelVolume < minimumVoxelVolume) {
970  voxelVolume = minimumVoxelVolume;
971  valid = false;
972  }
973  else if (voxelVolume > maximumVoxelVolume) {
974  voxelVolume = maximumVoxelVolume;
975  valid = false;
976  }
977 
978  voxelSize = static_cast<float>(math::Pow(voxelVolume, 1.0/3.0));
979  return valid;
980  }
981 
982  static float truncate(const float voxelSize, Index decPlaces)
983  {
984  float truncatedVoxelSize = voxelSize;
985 
986  // attempt to truncate from decPlaces -> 11
987  for (int i = decPlaces; i < 11; i++) {
988  truncatedVoxelSize = static_cast<float>(math::Truncate(double(voxelSize), i));
989  if (truncatedVoxelSize != 0.0f) break;
990  }
991 
992  return truncatedVoxelSize;
993  }
994  };
995 
996  if (pointsPerVoxel == 0) OPENVDB_THROW(ValueError, "Points per voxel cannot be zero.");
997 
998  // constructed with the default voxel size as specified by openvdb interface values
999 
1000  float voxelSize(0.1f);
1001 
1002  const size_t numPoints = positions.size();
1003 
1004  // return the default voxel size if we have zero or only 1 point
1005 
1006  if (numPoints <= 1) return voxelSize;
1007 
1008  size_t targetVoxelCount(numPoints / size_t(pointsPerVoxel));
1009  if (targetVoxelCount == 0) targetVoxelCount++;
1010 
1011  // calculate the world space, transform-oriented bounding box
1012 
1013  math::Mat4d inverseTransform = transform.inverse();
1014  inverseTransform = math::unit(inverseTransform);
1015 
1016  tbb::blocked_range<size_t> range(0, numPoints);
1017  CalculatePositionBounds<PositionWrapper> calculateBounds(positions, inverseTransform);
1018  tbb::parallel_reduce(range, calculateBounds);
1019 
1020  BBoxd bbox = calculateBounds.getBoundingBox();
1021 
1022  // return default size if points are coincident
1023 
1024  if (bbox.min() == bbox.max()) return voxelSize;
1025 
1026  double volume = bbox.volume();
1027 
1028  // handle points that are collinear or coplanar by expanding the volume
1029 
1030  if (math::isApproxZero(volume)) {
1031  Vec3d extents = bbox.extents().sorted().reversed();
1032  if (math::isApproxZero(extents[1])) {
1033  // colinear (maxExtent^3)
1034  volume = extents[0]*extents[0]*extents[0];
1035  }
1036  else {
1037  // coplanar (maxExtent*nextMaxExtent^2)
1038  volume = extents[0]*extents[1]*extents[1];
1039  }
1040  }
1041 
1042  double previousVolume = volume;
1043 
1044  if (!Local::voxelSizeFromVolume(volume, targetVoxelCount, voxelSize)) {
1045  OPENVDB_LOG_DEBUG("Out of range, clamping voxel size.");
1046  return voxelSize;
1047  }
1048 
1049  size_t previousVoxelCount(0);
1050  size_t voxelCount(1);
1051 
1052  if (interrupter) interrupter->start("Computing voxel size");
1053 
1054  while (voxelCount > previousVoxelCount)
1055  {
1056  math::Transform::Ptr newTransform;
1057 
1058  if (!math::isIdentity(transform))
1059  {
1060  // if using a custom transform, pre-scale by coefficients
1061  // which define the new voxel size
1062 
1063  math::Mat4d matrix(transform);
1064  matrix.preScale(Vec3d(voxelSize) / math::getScale(matrix));
1065  newTransform = math::Transform::createLinearTransform(matrix);
1066  }
1067  else
1068  {
1069  newTransform = math::Transform::createLinearTransform(voxelSize);
1070  }
1071 
1072  // create a mask grid of the points from the calculated voxel size
1073  // this is the same function call as tools::createPointMask() which has
1074  // been duplicated to provide an interrupter
1075 
1076  MaskGrid::Ptr mask = createGrid<MaskGrid>(false);
1077  mask->setTransform(newTransform);
1078  tools::PointsToMask<MaskGrid, InterrupterT> pointMaskOp(*mask, interrupter);
1079  pointMaskOp.addPoints(positions);
1080 
1081  if (interrupter && util::wasInterrupted(interrupter)) break;
1082 
1083  previousVoxelCount = voxelCount;
1084  voxelCount = mask->activeVoxelCount();
1085  volume = math::Pow3(voxelSize) * voxelCount;
1086 
1087  // stop if no change in the volume or the volume has increased
1088 
1089  if (volume >= previousVolume) break;
1090  previousVolume = volume;
1091 
1092  const float previousVoxelSize = voxelSize;
1093 
1094  // compute the new voxel size and if invalid return the previous value
1095 
1096  if (!Local::voxelSizeFromVolume(volume, targetVoxelCount, voxelSize)) {
1097  voxelSize = previousVoxelSize;
1098  break;
1099  }
1100 
1101  // halt convergence if the voxel size has decreased by less
1102  // than 10% in this iteration
1103 
1104  if (voxelSize / previousVoxelSize > 0.9f) break;
1105  }
1106 
1107  if (interrupter) interrupter->end();
1108 
1109  // truncate the voxel size for readability and return the value
1110 
1111  return Local::truncate(voxelSize, decimalPlaces);
1112 }
1113 
1114 
1115 ////////////////////////////////////////
1116 
1117 
1118 // deprecated functions
1119 
1120 
1121 template <typename PositionAttribute, typename PointDataGridT>
1123 inline void
1124 convertPointDataGridPosition( PositionAttribute& positionAttribute,
1125  const PointDataGridT& grid,
1126  const std::vector<Index64>& pointOffsets,
1127  const Index64 startOffset,
1128  const std::vector<Name>& includeGroups,
1129  const std::vector<Name>& excludeGroups,
1130  const bool inCoreOnly = false)
1131 {
1132  auto leaf = grid.tree().cbeginLeaf();
1133  if (!leaf) return;
1134  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
1135  convertPointDataGridPosition(positionAttribute, grid, pointOffsets, startOffset,
1136  filter, inCoreOnly);
1137 }
1138 
1139 
1140 template <typename TypedAttribute, typename PointDataTreeT>
1142 inline void
1144  const PointDataTreeT& tree,
1145  const std::vector<Index64>& pointOffsets,
1146  const Index64 startOffset,
1147  const unsigned arrayIndex,
1148  const Index stride,
1149  const std::vector<Name>& includeGroups,
1150  const std::vector<Name>& excludeGroups,
1151  const bool inCoreOnly = false)
1152 {
1153  auto leaf = tree.cbeginLeaf();
1154  if (!leaf) return;
1155  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
1156  convertPointDataGridAttribute(attribute, tree, pointOffsets, startOffset,
1157  arrayIndex, stride, filter, inCoreOnly);
1158 }
1159 
1160 
1161 template <typename Group, typename PointDataTreeT>
1163 inline void
1165  const PointDataTreeT& tree,
1166  const std::vector<Index64>& pointOffsets,
1167  const Index64 startOffset,
1168  const AttributeSet::Descriptor::GroupIndex index,
1169  const std::vector<Name>& includeGroups,
1170  const std::vector<Name>& excludeGroups,
1171  const bool inCoreOnly = false)
1172 {
1173  auto leaf = tree.cbeginLeaf();
1174  if (!leaf) return;
1175  MultiGroupFilter filter(includeGroups, excludeGroups, leaf->attributeSet());
1176  convertPointDataGridGroup(group, tree, pointOffsets, startOffset,
1177  index, filter, inCoreOnly);
1178 }
1179 
1180 
1181 } // namespace points
1182 } // namespace OPENVDB_VERSION_NAME
1183 } // namespace openvdb
1184 
1185 #endif // OPENVDB_POINTS_POINT_CONVERSION_HAS_BEEN_INCLUDED
1186 
1187 // Copyright (c) 2012-2018 DreamWorks Animation LLC
1188 // All rights reserved. This software is distributed under the
1189 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
bool isUniform() const override
Return true if this array is stored as a single uniform value.
Vec2< T > minComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise minimum of the two vectors.
Definition: Vec2.h:530
Definition: ImfName.h:53
This tool produces a grid where every voxel that contains a point is active. It employes thread-local...
Type Truncate(Type x, unsigned int digits)
Return x truncated to the given number of decimal digits.
Definition: Math.h:824
GLsizei GLenum const void * indices
Definition: glcorearb.h:405
void operator()(const typename LeafManagerT::LeafRange &range) const
void operator()(const typename LeafManagerT::LeafRange &range) const
GLenum GLint * range
Definition: glcorearb.h:1924
PointDataGridT::Ptr createPointDataGrid(const PointIndexGridT &pointIndexGrid, const PositionArrayT &positions, const math::Transform &xform, Metadata::Ptr positionDefaultValue=Metadata::Ptr())
Localises points with position into a PointDataGrid into two stages: allocation of the leaf attribute...
Vec3d indexToWorld(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:135
Type Pow(Type x, int n)
Return xn.
Definition: Math.h:515
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:386
static TypedAttributeArray & cast(AttributeArray &attributeArray)
Cast an AttributeArray to TypedAttributeArray<T>
ValueType get(Index n) const
Return the value at index n.
bool isIdentity(const MatType &m)
Determine if a matrix is an identity matrix.
Definition: Mat.h:892
GLint GLuint mask
Definition: glcorearb.h:123
Point group manipulation in a VDB Point Grid.
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
void convert(IterT &iter, HandleT &targetHandle, SourceHandleT &sourceHandle, Index64 &offset) const
Index filters primarily designed to be used with a FilterIndexIter.
#define OPENVDB_LOG_DEBUG(mesg)
Definition: logging.h:304
Makes every voxel of a grid active if it contains a point.
Definition: PointsToMask.h:94
MatType unit(const MatType &mat, typename MatType::value_type eps=1.0e-8)
Return a copy of the given matrix with its upper 3×3 rows normalized.
Definition: Mat.h:680
png_uint_32 i
Definition: png.h:2877
uint64 value_type
Definition: GA_PrimCompat.h:29
static Ptr create(AttributeArray &array, const bool expand=true)
bool isGroup(const AttributeArray &array)
CalculatePositionBounds(const PositionArrayT &positions, const math::Mat4d &inverse)
float computeVoxelSize(const PositionWrapper &positions, const uint32_t pointsPerVoxel, const math::Mat4d transform=math::Mat4d::identity(), const Index decimalPlaces=5, InterrupterT *const interrupter=nullptr)
SYS_FORCE_INLINE const_iterator end() const
static Ptr create(const AttributeArray &array, const bool preserveCompression=true)
void populateAttribute(PointDataTreeT &tree, const PointIndexTreeT &pointIndexTree, const openvdb::Name &attributeName, const PointArrayT &data, const Index stride=1, const bool insertMetadata=true)
Stores point attribute data in an existing PointDataGrid attribute.
ConvertPointDataGridPositionOp(Attribute &attribute, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const math::Transform &transform, const size_t index, const FilterT &filter, const bool inCoreOnly)
GLdouble n
Definition: glcorearb.h:2007
GLfloat f
Definition: glcorearb.h:1925
Base class for storing attribute data.
Vec3< T > reversed() const
Return the vector (z, y, x)
Definition: Vec3.h:475
ConvertPointDataGridAttributeOp(Attribute &attribute, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const size_t index, const Index stride, const FilterT &filter, const bool inCoreOnly)
#define OPENVDB_DEPRECATED
Definition: Platform.h:49
void preScale(const Vec3< T0 > &v)
Definition: Mat4.h:782
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:773
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:871
Attribute array storage for string data using Descriptor Metadata.
PopulatePositionAttributeOp(const PointIndexTreeType &pointIndexTree, const math::Transform &transform, const PositionListType &positions)
GLintptr offset
Definition: glcorearb.h:664
OPENVDB_API void calculateBounds(const Transform &t, const Vec3d &minWS, const Vec3d &maxWS, Vec3d &minIS, Vec3d &maxIS)
Calculate an axis-aligned bounding box in index space from an axis-aligned bounding box in world spac...
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:110
Type Pow3(Type x)
Return x3.
Definition: Math.h:506
ConvertPointDataGridGroupOp(Group &group, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const AttributeSet::Descriptor::GroupIndex index, const FilterT &filter, const bool inCoreOnly)
Vec3< T > sorted() const
Return a vector with the components of this in ascending order.
Definition: Vec3.h:465
void convert(IterT &iter, const GroupAttributeArray &groupArray, Index64 &offset) const
GLboolean * data
Definition: glcorearb.h:130
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:115
std::pair< Name, Name > NamePair
bool isApproxZero(const Type &x)
Return true if x is equal to zero to within the default floating-point comparison tolerance...
Definition: Math.h:320
GA_API const UT_StringHolder transform
Point attribute manipulation in a VDB Point Grid.
GLsizei const GLfloat * value
Definition: glcorearb.h:823
Typed class for storing attribute data.
Set of Attribute Arrays which tracks metadata about each array.
ElementType volume() const
Return the volume enclosed by this bounding box.
Definition: BBox.h:127
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
GLuint index
Definition: glcorearb.h:785
void convertPointDataGridAttribute(TypedAttribute &attribute, const PointDataTreeT &tree, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const unsigned arrayIndex, const Index stride=1, const FilterT &filter=NullFilter(), const bool inCoreOnly=false)
Convert the attribute from a PointDataGrid.
Vec4< T0 > transform(const Vec4< T0 > &v) const
Transform a Vec4 by post-multiplication.
Definition: Mat4.h:1044
math::BBox< Vec3d > BBoxd
Definition: Types.h:91
Vec2< T > maxComponent(const Vec2< T > &v1, const Vec2< T > &v2)
Return component-wise maximum of the two vectors.
Definition: Vec2.h:539
Vec3< typename MatType::value_type > getScale(const MatType &mat)
Return a Vec3 representing the lengths of the passed matrix's upper 3×3's rows.
Definition: Mat.h:665
static const Mat4< double > & identity()
Predefined constant for identity matrix.
Definition: Mat4.h:152
Index64 pointOffsets(std::vector< Index64 > &pointOffsets, const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Populate an array of cumulative point offsets per leaf node.
Definition: PointCount.h:149
GA_API const UT_StringHolder N
Point-partitioner compatible STL vector attribute wrapper for convenience.
void convert(IterT &iter, HandleT &targetHandle, SourceHandleT &sourceHandle, Index64 &offset) const
void convertPointDataGridGroup(Group &group, const PointDataTreeT &tree, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const AttributeSet::Descriptor::GroupIndex index, const FilterT &filter=NullFilter(), const bool inCoreOnly=false)
Convert the group from a PointDataGrid.
static Transform::Ptr createLinearTransform(double voxelSize=1.0)
Create and return a shared pointer to a new transform.
InitialiseAttributesOp(const PointIndexTreeType &pointIndexTree, const AttributeSet::Descriptor::Ptr &attributeDescriptor)
Vec3d worldToIndex(const Vec3d &xyz) const
Apply this transformation to the given coordinates.
Definition: Transform.h:137
bool wasInterrupted(T *i, int percent=-1)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Mat4 inverse(T tolerance=0) const
Definition: Mat4.h:531
void convertPointDataGridPosition(PositionAttribute &positionAttribute, const PointDataGridT &grid, const std::vector< Index64 > &pointOffsets, const Index64 startOffset, const FilterT &filter=NullFilter(), const bool inCoreOnly=false)
Convert the position attribute from a Point Data Grid.
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
PopulateAttributeOp(const PointIndexTreeType &pointIndexTree, const AttributeListType &data, const size_t index, const Index stride=1)
void addPoints(const PointListT &points, size_t grainSize=1024)
Activates the state of any voxel in the input grid that contains a point.
Definition: PointsToMask.h:150
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1296
PointAttributeVector(const std::vector< value_type > &data, const Index stride=1)
math::Vec3< float > Vec3f
Definition: Types.h:81