HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PointGroup.h
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2012-2017 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
32 ///
33 /// @file points/PointGroup.h
34 ///
35 /// @brief Point group manipulation in a VDB Point Grid.
36 
37 #ifndef OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
39 
40 #include <openvdb/openvdb.h>
41 
42 #include "IndexIterator.h" // FilterTraits
43 #include "IndexFilter.h" // FilterTraits
44 #include "AttributeSet.h"
45 #include "PointDataGrid.h"
46 #include "PointAttribute.h"
47 
48 namespace openvdb {
50 namespace OPENVDB_VERSION_NAME {
51 namespace points {
52 
53 /// @brief Delete any group that is not present in the Descriptor.
54 ///
55 /// @param groups the vector of group names.
56 /// @param descriptor the descriptor that holds the group map.
57 inline void deleteMissingPointGroups( std::vector<std::string>& groups,
58  const AttributeSet::Descriptor& descriptor);
59 
60 /// @brief Appends a new empty group to the VDB tree.
61 ///
62 /// @param tree the PointDataTree to be appended to.
63 /// @param group name of the new group.
64 template <typename PointDataTree>
65 inline void appendGroup(PointDataTree& tree,
66  const Name& group);
67 
68 /// @brief Appends new empty groups to the VDB tree.
69 ///
70 /// @param tree the PointDataTree to be appended to.
71 /// @param groups names of the new groups.
72 template <typename PointDataTree>
73 inline void appendGroups(PointDataTree& tree,
74  const std::vector<Name>& groups);
75 
76 /// @brief Drops an existing group from the VDB tree.
77 ///
78 /// @param tree the PointDataTree to be dropped from.
79 /// @param group name of the group.
80 /// @param compact compact attributes if possible to reduce memory - if dropping
81 /// more than one group, compacting once at the end will be faster
82 template <typename PointDataTree>
83 inline void dropGroup( PointDataTree& tree,
84  const Name& group,
85  const bool compact = true);
86 
87 /// @brief Drops existing groups from the VDB tree, the tree is compacted after dropping.
88 ///
89 /// @param tree the PointDataTree to be dropped from.
90 /// @param groups names of the groups.
91 template <typename PointDataTree>
92 inline void dropGroups( PointDataTree& tree,
93  const std::vector<Name>& groups);
94 
95 /// @brief Drops all existing groups from the VDB tree, the tree is compacted after dropping.
96 ///
97 /// @param tree the PointDataTree to be dropped from.
98 template <typename PointDataTree>
99 inline void dropGroups( PointDataTree& tree);
100 
101 /// @brief Compacts existing groups of a VDB Tree to use less memory if possible.
102 ///
103 /// @param tree the PointDataTree to be compacted.
104 template <typename PointDataTree>
105 inline void compactGroups(PointDataTree& tree);
106 
107 /// @brief Sets group membership from a PointIndexTree-ordered vector.
108 ///
109 /// @param tree the PointDataTree.
110 /// @param indexTree the PointIndexTree.
111 /// @param membership @c 1 if the point is in the group, 0 otherwise.
112 /// @param group the name of the group.
113 /// @param remove if @c true also perform removal of points from the group.
114 ///
115 /// @note vector<bool> is not thread-safe on concurrent write, so use vector<short> instead
116 template <typename PointDataTree, typename PointIndexTree>
117 inline void setGroup( PointDataTree& tree,
118  const PointIndexTree& indexTree,
119  const std::vector<short>& membership,
120  const Name& group,
121  const bool remove = false);
122 
123 /// @brief Sets membership for the specified group for all points (on/off).
124 ///
125 /// @param tree the PointDataTree.
126 /// @param group the name of the group.
127 /// @param member true / false for membership of the group.
128 template <typename PointDataTree>
129 inline void setGroup( PointDataTree& tree,
130  const Name& group,
131  const bool member = true);
132 
133 /// @brief Sets group membership based on a provided filter.
134 ///
135 /// @param tree the PointDataTree.
136 /// @param group the name of the group.
137 /// @param filter filter data that is used to create a per-leaf filter
138 template <typename PointDataTree, typename FilterT>
139 inline void setGroupByFilter( PointDataTree& tree,
140  const Name& group,
141  const FilterT& filter);
142 
143 
144 ////////////////////////////////////////
145 
146 
147 namespace point_group_internal {
148 
149 
150 /// Copy a group attribute value from one group offset to another
151 template<typename PointDataTreeType>
152 struct CopyGroupOp {
153 
155  using LeafRangeT = typename LeafManagerT::LeafRange;
156  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
157 
158  CopyGroupOp(const GroupIndex& targetIndex,
159  const GroupIndex& sourceIndex)
160  : mTargetIndex(targetIndex)
161  , mSourceIndex(sourceIndex) { }
162 
163  void operator()(const typename LeafManagerT::LeafRange& range) const {
164 
165  for (auto leaf = range.begin(); leaf; ++leaf) {
166 
167  GroupHandle sourceGroup = leaf->groupHandle(mSourceIndex);
168  GroupWriteHandle targetGroup = leaf->groupWriteHandle(mTargetIndex);
169 
170  for (auto iter = leaf->beginIndexAll(); iter; ++iter) {
171  const bool groupOn = sourceGroup.get(*iter);
172  targetGroup.set(*iter, groupOn);
173  }
174  }
175  }
176 
177  //////////
178 
181 };
182 
183 
184 /// Set membership on or off for the specified group
185 template <typename PointDataTree, bool Member>
187 {
189  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
190 
191  SetGroupOp(const AttributeSet::Descriptor::GroupIndex& index)
192  : mIndex(index) { }
193 
194  void operator()(const typename LeafManagerT::LeafRange& range) const
195  {
196  for (auto leaf = range.begin(); leaf; ++leaf) {
197 
198  // obtain the group attribute array
199 
200  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
201 
202  // set the group value
203 
204  group.collapse(Member);
205  }
206  }
207 
208  //////////
209 
211 }; // struct SetGroupOp
212 
213 
214 template <typename PointDataTree, typename PointIndexTree, bool Remove>
216 {
218  using LeafRangeT = typename LeafManagerT::LeafRange;
219  using PointIndexLeafNode = typename PointIndexTree::LeafNodeType;
220  using IndexArray = typename PointIndexLeafNode::IndexArray;
221  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
222  using MembershipArray = std::vector<short>;
223 
225  const MembershipArray& membership,
226  const GroupIndex& index)
227  : mIndexTree(indexTree)
228  , mMembership(membership)
229  , mIndex(index) { }
230 
231  void operator()(const typename LeafManagerT::LeafRange& range) const
232  {
233  for (auto leaf = range.begin(); leaf; ++leaf) {
234 
235  // obtain the PointIndexLeafNode (using the origin of the current leaf)
236 
237  const PointIndexLeafNode* pointIndexLeaf = mIndexTree.probeConstLeaf(leaf->origin());
238 
239  if (!pointIndexLeaf) continue;
240 
241  // obtain the group attribute array
242 
243  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
244 
245  // initialise the attribute storage
246 
247  Index64 index = 0;
248 
249  const IndexArray& indices = pointIndexLeaf->indices();
250 
251  for (const Index64 i: indices) {
252  if (Remove) {
253  group.set(static_cast<Index>(index), mMembership[i]);
254  } else if (mMembership[i] == short(1)) {
255  group.set(static_cast<Index>(index), short(1));
256  }
257  index++;
258  }
259 
260  // attempt to compact the array
261 
262  group.compact();
263  }
264  }
265 
266  //////////
267 
271 }; // struct SetGroupFromIndexOp
272 
273 
274 template <typename PointDataTree, typename FilterT, typename IterT = typename PointDataTree::LeafNodeType::ValueAllCIter>
276 {
278  using LeafRangeT = typename LeafManagerT::LeafRange;
280  using GroupIndex = AttributeSet::Descriptor::GroupIndex;
281 
282  SetGroupByFilterOp( const GroupIndex& index, const FilterT& filter)
283  : mIndex(index)
284  , mFilter(filter) { }
285 
286  void operator()(const typename LeafManagerT::LeafRange& range) const
287  {
288  for (auto leaf = range.begin(); leaf; ++leaf) {
289 
290  // obtain the group attribute array
291 
292  GroupWriteHandle group(leaf->groupWriteHandle(mIndex));
293 
294  auto iter = leaf->template beginIndex<IterT, FilterT>(mFilter);
295 
296  for (; iter; ++iter) {
297  group.set(*iter, true);
298  }
299 
300  // attempt to compact the array
301 
302  group.compact();
303  }
304  }
305 
306  //////////
307 
309  const FilterT mFilter;
310 }; // struct SetGroupByFilterOp
311 
312 
313 ////////////////////////////////////////
314 
315 
316 /// Convenience class with methods for analyzing group data
318 {
319 public:
321 
322  GroupInfo(const AttributeSet& attributeSet)
323  : mAttributeSet(attributeSet) { }
324 
325  /// Return the number of bits in a group (typically 8)
326  static size_t groupBits() { return sizeof(GroupType) * CHAR_BIT; }
327 
328  /// Return the number of empty group slots which correlates to the number of groups
329  /// that can be stored without increasing the number of group attribute arrays
330  size_t unusedGroups() const
331  {
332  const Descriptor& descriptor = mAttributeSet.descriptor();
333 
334  // compute total slots (one slot per bit of the group attributes)
335 
336  const size_t groupAttributes = descriptor.count(GroupAttributeArray::attributeType());
337 
338  if (groupAttributes == 0) return 0;
339 
340  const size_t totalSlots = groupAttributes * this->groupBits();
341 
342  // compute slots in use
343 
344  const AttributeSet::Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
345  const size_t usedSlots = groupMap.size();
346 
347  return totalSlots - usedSlots;
348  }
349 
350  /// Return @c true if there are sufficient empty slots to allow compacting
351  bool canCompactGroups() const
352  {
353  // can compact if more unused groups than in one group attribute array
354 
355  return this->unusedGroups() >= this->groupBits();
356  }
357 
358  /// Return the next empty group slot
359  size_t nextUnusedOffset() const
360  {
361  const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
362 
363  // build a list of group indices
364 
365  std::vector<size_t> indices;
366  indices.reserve(groupMap.size());
367  for (const auto& namePos : groupMap) {
368  indices.push_back(namePos.second);
369  }
370 
371  std::sort(indices.begin(), indices.end());
372 
373  // return first index not present
374 
375  size_t offset = 0;
376  for (const size_t& index : indices) {
377  if (index != offset) break;
378  offset++;
379  }
380 
381  return offset;
382  }
383 
384  /// Return vector of indices correlating to the group attribute arrays
385  std::vector<size_t> populateGroupIndices() const
386  {
387  std::vector<size_t> indices;
388 
389  const Descriptor::NameToPosMap& map = mAttributeSet.descriptor().map();
390 
391  for (const auto& namePos : map) {
392  const AttributeArray* array = mAttributeSet.getConst(namePos.first);
393  if (isGroup(*array)) {
394  indices.push_back(namePos.second);
395  }
396  }
397 
398  return indices;
399  }
400 
401  /// Determine if a move is required to efficiently compact the data and store the
402  /// source name, offset and the target offset in the input parameters
403  bool requiresMove(Name& sourceName, size_t& sourceOffset, size_t& targetOffset) const {
404 
405  targetOffset = this->nextUnusedOffset();
406 
407  const Descriptor::NameToPosMap& groupMap = mAttributeSet.descriptor().groupMap();
408 
409  for (const auto& namePos : groupMap) {
410 
411  // move only required if source comes after the target
412 
413  if (namePos.second >= targetOffset) {
414  sourceName = namePos.first;
415  sourceOffset = namePos.second;
416  return true;
417  }
418  }
419 
420  return false;
421  }
422 
423 private:
424  const AttributeSet& mAttributeSet;
425 }; // class GroupInfo
426 
427 
428 } // namespace point_group_internal
429 
430 
431 ////////////////////////////////////////
432 
433 
434 inline void deleteMissingPointGroups( std::vector<std::string>& groups,
435  const AttributeSet::Descriptor& descriptor)
436 {
437  for (auto it = groups.begin(); it != groups.end();) {
438  if (!descriptor.hasGroup(*it)) it = groups.erase(it);
439  else ++it;
440  }
441 }
442 
443 
444 ////////////////////////////////////////
445 
446 
447 template <typename PointDataTree>
448 inline void appendGroup(PointDataTree& tree, const Name& group)
449 {
450  using Descriptor = AttributeSet::Descriptor;
451 
454 
455  if (group.empty()) {
456  OPENVDB_THROW(KeyError, "Cannot use an empty group name as a key.");
457  }
458 
459  auto iter = tree.cbeginLeaf();
460 
461  if (!iter) return;
462 
463  const AttributeSet& attributeSet = iter->attributeSet();
464  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
465  GroupInfo groupInfo(attributeSet);
466 
467  // don't add if group already exists
468 
469  if (descriptor->hasGroup(group)) return;
470 
471  // add a new group attribute if there are no unused groups
472 
473  if (groupInfo.unusedGroups() == 0) {
474 
475  // find a new internal group name
476 
477  const Name groupName = descriptor->uniqueName("__group");
478 
479  descriptor = descriptor->duplicateAppend(groupName, GroupAttributeArray::attributeType());
480 
481  const size_t pos = descriptor->find(groupName);
482 
483  // insert new group attribute
484 
485  AppendAttributeOp<PointDataTree> append(descriptor, pos);
486  tbb::parallel_for(typename tree::template LeafManager<PointDataTree>(tree).leafRange(), append);
487  }
488  else {
489  // make the descriptor unique before we modify the group map
490 
491  makeDescriptorUnique(tree);
492  descriptor = attributeSet.descriptorPtr();
493  }
494 
495  // ensure that there are now available groups
496 
497  assert(groupInfo.unusedGroups() > 0);
498 
499  // find next unused offset
500 
501  const size_t offset = groupInfo.nextUnusedOffset();
502 
503  // add the group mapping to the descriptor
504 
505  descriptor->setGroup(group, offset);
506 }
507 
508 
509 ////////////////////////////////////////
510 
511 
512 template <typename PointDataTree>
513 inline void appendGroups(PointDataTree& tree,
514  const std::vector<Name>& groups)
515 {
516  // TODO: could be more efficient by appending multiple groups at once
517  // instead of one-by-one, however this is likely not that common a use case
518 
519  for (const Name& name : groups) {
520  appendGroup(tree, name);
521  }
522 }
523 
524 
525 ////////////////////////////////////////
526 
527 
528 template <typename PointDataTree>
529 inline void dropGroup(PointDataTree& tree, const Name& group, const bool compact)
530 {
531  using Descriptor = AttributeSet::Descriptor;
532 
533  if (group.empty()) {
534  OPENVDB_THROW(KeyError, "Cannot use an empty group name as a key.");
535  }
536 
537  auto iter = tree.cbeginLeaf();
538 
539  if (!iter) return;
540 
541  const AttributeSet& attributeSet = iter->attributeSet();
542 
543  // make the descriptor unique before we modify the group map
544 
545  makeDescriptorUnique(tree);
546  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
547 
548  // now drop the group
549 
550  descriptor->dropGroup(group);
551 
552  if (compact) {
553  compactGroups(tree);
554  }
555 }
556 
557 
558 ////////////////////////////////////////
559 
560 
561 template <typename PointDataTree>
562 inline void dropGroups( PointDataTree& tree,
563  const std::vector<Name>& groups)
564 {
565  for (const Name& name : groups) {
566  dropGroup(tree, name, /*compact=*/false);
567  }
568 
569  // compaction done once for efficiency
570 
571  compactGroups(tree);
572 }
573 
574 
575 ////////////////////////////////////////
576 
577 
578 template <typename PointDataTree>
579 inline void dropGroups( PointDataTree& tree)
580 {
581  using Descriptor = AttributeSet::Descriptor;
582 
584 
585  auto iter = tree.cbeginLeaf();
586 
587  if (!iter) return;
588 
589  const AttributeSet& attributeSet = iter->attributeSet();
590  GroupInfo groupInfo(attributeSet);
591 
592  // make the descriptor unique before we modify the group map
593 
594  makeDescriptorUnique(tree);
595  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
596 
597  descriptor->clearGroups();
598 
599  // find all indices for group attribute arrays
600 
601  std::vector<size_t> indices = groupInfo.populateGroupIndices();
602 
603  // drop these attributes arrays
604 
605  dropAttributes(tree, indices);
606 }
607 
608 
609 ////////////////////////////////////////
610 
611 
612 template <typename PointDataTree>
613 inline void compactGroups(PointDataTree& tree)
614 {
615  using Descriptor = AttributeSet::Descriptor;
616  using GroupIndex = Descriptor::GroupIndex;
617 
620 
621  auto iter = tree.cbeginLeaf();
622 
623  if (!iter) return;
624 
625  const AttributeSet& attributeSet = iter->attributeSet();
626  GroupInfo groupInfo(attributeSet);
627 
628  // early exit if not possible to compact
629 
630  if (!groupInfo.canCompactGroups()) return;
631 
632  // make the descriptor unique before we modify the group map
633 
634  makeDescriptorUnique(tree);
635  Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
636 
637  // generate a list of group offsets and move them (one-by-one)
638  // TODO: improve this algorithm to move multiple groups per array at once
639  // though this is likely not that common a use case
640 
641  Name sourceName;
642  size_t sourceOffset, targetOffset;
643 
644  while (groupInfo.requiresMove(sourceName, sourceOffset, targetOffset)) {
645 
646  const GroupIndex sourceIndex = attributeSet.groupIndex(sourceOffset);
647  const GroupIndex targetIndex = attributeSet.groupIndex(targetOffset);
648 
649  CopyGroupOp<PointDataTree> copy(targetIndex, sourceIndex);
650  tbb::parallel_for(typename tree::template LeafManager<PointDataTree>(tree).leafRange(), copy);
651 
652  descriptor->setGroup(sourceName, targetOffset);
653  }
654 
655  // drop unused attribute arrays
656 
657  std::vector<size_t> indices = groupInfo.populateGroupIndices();
658 
659  const size_t totalAttributesToDrop = groupInfo.unusedGroups() / groupInfo.groupBits();
660 
661  assert(totalAttributesToDrop <= indices.size());
662 
663  std::vector<size_t> indicesToDrop(indices.end() - totalAttributesToDrop, indices.end());
664 
665  dropAttributes(tree, indicesToDrop);
666 }
667 
668 
669 ////////////////////////////////////////
670 
671 
672 template <typename PointDataTree, typename PointIndexTree>
673 inline void setGroup( PointDataTree& tree,
674  const PointIndexTree& indexTree,
675  const std::vector<short>& membership,
676  const Name& group,
677  const bool remove)
678 {
679  using Descriptor = AttributeSet::Descriptor;
680  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
681 
682  if (membership.size() != pointCount(tree)) {
683  OPENVDB_THROW(LookupError, "Membership vector size must match number of points.");
684  }
685 
687 
688  auto iter = tree.cbeginLeaf();
689 
690  if (!iter) return;
691 
692  const AttributeSet& attributeSet = iter->attributeSet();
693  const Descriptor& descriptor = attributeSet.descriptor();
694 
695  if (!descriptor.hasGroup(group)) {
696  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
697  }
698 
699  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
700 
701  // set membership
702 
703  if (remove) {
704  SetGroupFromIndexOp<PointDataTree,
705  PointIndexTree, false> set(indexTree, membership, index);
706  tbb::parallel_for(LeafManagerT(tree).leafRange(), set);
707  }
708  else {
709  SetGroupFromIndexOp<PointDataTree,
710  PointIndexTree, true> set(indexTree, membership, index);
711  tbb::parallel_for(LeafManagerT(tree).leafRange(), set);
712  }
713 }
714 
715 
716 ////////////////////////////////////////
717 
718 
719 template <typename PointDataTree>
720 inline void setGroup( PointDataTree& tree,
721  const Name& group,
722  const bool member)
723 {
724  using Descriptor = AttributeSet::Descriptor;
725  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
726 
728 
729  auto iter = tree.cbeginLeaf();
730 
731  if (!iter) return;
732 
733  const AttributeSet& attributeSet = iter->attributeSet();
734  const Descriptor& descriptor = attributeSet.descriptor();
735 
736  if (!descriptor.hasGroup(group)) {
737  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
738  }
739 
740  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
741 
742  // set membership based on member variable
743 
744  if (member) tbb::parallel_for(LeafManagerT(tree).leafRange(), SetGroupOp<PointDataTree, true>(index));
745  else tbb::parallel_for(LeafManagerT(tree).leafRange(), SetGroupOp<PointDataTree, false>(index));
746 }
747 
748 
749 ////////////////////////////////////////
750 
751 
752 template <typename PointDataTree, typename FilterT>
753 inline void setGroupByFilter( PointDataTree& tree,
754  const Name& group,
755  const FilterT& filter)
756 {
757  using Descriptor = AttributeSet::Descriptor;
758  using LeafManagerT = typename tree::template LeafManager<PointDataTree>;
759 
761 
762  auto iter = tree.cbeginLeaf();
763 
764  if (!iter) return;
765 
766  const AttributeSet& attributeSet = iter->attributeSet();
767  const Descriptor& descriptor = attributeSet.descriptor();
768 
769  if (!descriptor.hasGroup(group)) {
770  OPENVDB_THROW(LookupError, "Group must exist on Tree before defining membership.");
771  }
772 
773  const Descriptor::GroupIndex index = attributeSet.groupIndex(group);
774 
775  // set membership using filter
776 
777  SetGroupByFilterOp<PointDataTree, FilterT> set(index, filter);
778  tbb::parallel_for(LeafManagerT(tree).leafRange(), set);
779 }
780 
781 
782 ////////////////////////////////////////
783 
784 
785 template <typename PointDataTree>
787  const Name& group,
788  const Index64 targetPoints,
789  const unsigned int seed = 0)
790 {
792 
793  RandomFilter filter(tree, targetPoints, seed);
794 
795  setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
796 }
797 
798 
799 ////////////////////////////////////////
800 
801 
802 template <typename PointDataTree>
804  const Name& group,
805  const float percentage = 10.0f,
806  const unsigned int seed = 0)
807 {
809 
810  const int currentPoints = static_cast<int>(pointCount(tree));
811  const int targetPoints = int(math::Round((percentage * currentPoints)/100.0f));
812 
813  RandomFilter filter(tree, targetPoints, seed);
814 
815  setGroupByFilter<PointDataTree, RandomFilter>(tree, group, filter);
816 }
817 
818 
819 ////////////////////////////////////////
820 
821 
822 } // namespace points
823 } // namespace OPENVDB_VERSION_NAME
824 } // namespace openvdb
825 
826 
827 #endif // OPENVDB_POINTS_POINT_GROUP_HAS_BEEN_INCLUDED
828 
829 // Copyright (c) 2012-2017 DreamWorks Animation LLC
830 // All rights reserved. This software is distributed under the
831 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
CopyGroupOp(const GroupIndex &targetIndex, const GroupIndex &sourceIndex)
Definition: PointGroup.h:158
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
SetGroupFromIndexOp(const PointIndexTree &indexTree, const MembershipArray &membership, const GroupIndex &index)
Definition: PointGroup.h:224
Definition: ImfName.h:53
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets...
Definition: AttributeSet.h:121
Util::GroupIndex groupIndex(const Name &groupName) const
Return the group index from the name of the group.
GLsizei GLenum const void * indices
Definition: glcorearb.h:405
GLenum GLint * range
Definition: glcorearb.h:1924
void dropGroup(PointDataTree &tree, const Name &group, const bool compact=true)
Drops an existing group from the VDB tree.
Definition: PointGroup.h:529
LeafCIter cbeginLeaf() const
Return an iterator over all leaf nodes in this tree.
Definition: Tree.h:1182
SetGroupByFilterOp(const GroupIndex &index, const FilterT &filter)
Definition: PointGroup.h:282
static size_t groupBits()
Return the number of bits in a group (typically 8)
Definition: PointGroup.h:326
Copy a group attribute value from one group offset to another.
Definition: PointGroup.h:152
Index filters primarily designed to be used with a FilterIndexIter.
void setGroupByRandomTarget(PointDataTree &tree, const Name &group, const Index64 targetPoints, const unsigned int seed=0)
Definition: PointGroup.h:786
Set membership on or off for the specified group.
Definition: PointGroup.h:186
png_uint_32 i
Definition: png.h:2877
Index64 pointCount(const PointDataTreeT &tree, const bool inCoreOnly=false)
Total points in the PointDataTree.
Definition: PointCount.h:198
void setGroupByRandomPercentage(PointDataTree &tree, const Name &group, const float percentage=10.0f, const unsigned int seed=0)
Definition: PointGroup.h:803
bool isGroup(const AttributeArray &array)
Convenience class with methods for analyzing group data.
Definition: PointGroup.h:317
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:163
void deleteMissingPointGroups(std::vector< std::string > &groups, const AttributeSet::Descriptor &descriptor)
Delete any group that is not present in the Descriptor.
Definition: PointGroup.h:434
GLfloat f
Definition: glcorearb.h:1925
Base class for storing attribute data.
bool requiresMove(Name &sourceName, size_t &sourceOffset, size_t &targetOffset) const
Definition: PointGroup.h:403
#define OPENVDB_VERSION_NAME
Definition: version.h:43
float Round(float x)
Return x rounded to the nearest integer.
Definition: Math.h:785
void appendGroups(PointDataTree &tree, const std::vector< Name > &groups)
Appends new empty groups to the VDB tree.
Definition: PointGroup.h:513
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:194
static const NamePair & attributeType()
Return the name of this attribute's type (includes codec)
const AttributeArray * getConst(const std::string &name) const
Return a pointer to the attribute array whose name is name or a null pointer if no match is found...
bool collapse(bool on)
Set membership for the whole array and attempt to collapse.
GLintptr offset
Definition: glcorearb.h:664
void dropAttributes(PointDataTree &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:115
typename tree::LeafManager< PointDataTree > LeafManagerT
Definition: PointGroup.h:188
Index Iterators.
std::vector< size_t > populateGroupIndices() const
Return vector of indices correlating to the group attribute arrays.
Definition: PointGroup.h:385
GLuint const GLchar * name
Definition: glcorearb.h:785
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:286
Point attribute manipulation in a VDB Point Grid.
typename tree::LeafManager< PointDataTreeType > LeafManagerT
Definition: PointGroup.h:154
size_t nextUnusedOffset() const
Return the next empty group slot.
Definition: PointGroup.h:359
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:214
typedef int
Definition: png.h:1175
Set of Attribute Arrays which tracks metadata about each array.
SetGroupOp(const AttributeSet::Descriptor::GroupIndex &index)
Definition: PointGroup.h:191
GLuint index
Definition: glcorearb.h:785
void operator()(const typename LeafManagerT::LeafRange &range) const
Definition: PointGroup.h:231
void dropGroups(PointDataTree &tree, const std::vector< Name > &groups)
Drops existing groups from the VDB tree, the tree is compacted after dropping.
Definition: PointGroup.h:562
void setGroup(PointDataTree &tree, const PointIndexTree &indexTree, const std::vector< short > &membership, const Name &group, const bool remove=false)
Sets group membership from a PointIndexTree-ordered vector.
Definition: PointGroup.h:673
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:62
void appendGroup(PointDataTree &tree, const Name &group)
Appends a new empty group to the VDB tree.
Definition: PointGroup.h:448
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 >>> PointDataTree
Point index tree configured to match the default VDB configurations.
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
bool canCompactGroups() const
Return true if there are sufficient empty slots to allow compacting.
Definition: PointGroup.h:351
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set's descriptor, which might be shared with other sets...
Definition: AttributeSet.h:127
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointIndexLeafNode< PointIndex32, 3 >, 4 >, 5 >>> PointIndexTree
Point index tree configured to match the default OpenVDB tree configuration.
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
void compactGroups(PointDataTree &tree)
Compacts existing groups of a VDB Tree to use less memory if possible.
Definition: PointGroup.h:613
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glcorearb.h:1296
void setGroupByFilter(PointDataTree &tree, const Name &group, const FilterT &filter)
Sets group membership based on a provided filter.
Definition: PointGroup.h:753