HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointAttribute.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /// @author Dan Bailey, Khang Ngo
5 ///
6 /// @file points/PointAttribute.h
7 ///
8 /// @brief Point attribute manipulation in a VDB Point Grid.
9 
10 #ifndef OPENVDB_POINTS_POINT_ATTRIBUTE_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_POINT_ATTRIBUTE_HAS_BEEN_INCLUDED
12 
13 #include <openvdb/openvdb.h>
14 
15 #include "AttributeArrayString.h"
16 #include "AttributeSet.h"
17 #include "AttributeGroup.h"
18 #include "PointDataGrid.h"
19 
20 
21 namespace openvdb {
23 namespace OPENVDB_VERSION_NAME {
24 namespace points {
25 
26 namespace point_attribute_internal {
27 
28 template <typename ValueType>
29 struct Default
30 {
31  static inline ValueType value() { return zeroVal<ValueType>(); }
32 };
33 
34 } // namespace point_attribute_internal
35 
36 
37 /// @brief Appends a new attribute to the VDB tree
38 /// (this method does not require a templated AttributeType)
39 ///
40 /// @param tree the PointDataTree to be appended to.
41 /// @param name name for the new attribute.
42 /// @param type the type of the attibute.
43 /// @param strideOrTotalSize the stride of the attribute
44 /// @param constantStride if @c false, stride is interpreted as total size of the array
45 /// @param defaultValue metadata default attribute value
46 /// @param hidden mark attribute as hidden
47 /// @param transient mark attribute as transient
48 template <typename PointDataTreeT>
49 inline void appendAttribute(PointDataTreeT& tree,
50  const Name& name,
51  const NamePair& type,
52  const Index strideOrTotalSize = 1,
53  const bool constantStride = true,
54  const Metadata* defaultValue = nullptr,
55  const bool hidden = false,
56  const bool transient = false);
57 
58 /// @brief Appends a new attribute to the VDB tree.
59 ///
60 /// @param tree the PointDataTree to be appended to.
61 /// @param name name for the new attribute
62 /// @param uniformValue the initial value of the attribute
63 /// @param strideOrTotalSize the stride of the attribute
64 /// @param constantStride if @c false, stride is interpreted as total size of the array
65 /// @param defaultValue metadata default attribute value
66 /// @param hidden mark attribute as hidden
67 /// @param transient mark attribute as transient
68 template <typename ValueType,
69  typename CodecType = NullCodec,
70  typename PointDataTreeT = PointDataTree>
71 inline void appendAttribute(PointDataTreeT& tree,
72  const std::string& name,
73  const ValueType& uniformValue =
75  const Index strideOrTotalSize = 1,
76  const bool constantStride = true,
77  const TypedMetadata<ValueType>* defaultValue = nullptr,
78  const bool hidden = false,
79  const bool transient = false);
80 
81 /// @brief Collapse the attribute into a uniform value
82 ///
83 /// @param tree the PointDataTree in which to collapse the attribute.
84 /// @param name name for the attribute.
85 /// @param uniformValue value of the attribute
86 template <typename ValueType, typename PointDataTreeT>
87 inline void collapseAttribute( PointDataTreeT& tree,
88  const Name& name,
89  const ValueType& uniformValue =
91 
92 /// @brief Drops attributes from the VDB tree.
93 ///
94 /// @param tree the PointDataTree to be dropped from.
95 /// @param indices indices of the attributes to drop.
96 template <typename PointDataTreeT>
97 inline void dropAttributes( PointDataTreeT& tree,
98  const std::vector<size_t>& indices);
99 
100 /// @brief Drops attributes from the VDB tree.
101 ///
102 /// @param tree the PointDataTree to be dropped from.
103 /// @param names names of the attributes to drop.
104 template <typename PointDataTreeT>
105 inline void dropAttributes( PointDataTreeT& tree,
106  const std::vector<Name>& names);
107 
108 /// @brief Drop one attribute from the VDB tree (convenience method).
109 ///
110 /// @param tree the PointDataTree to be dropped from.
111 /// @param index index of the attribute to drop.
112 template <typename PointDataTreeT>
113 inline void dropAttribute( PointDataTreeT& tree,
114  const size_t& index);
115 
116 /// @brief Drop one attribute from the VDB tree (convenience method).
117 ///
118 /// @param tree the PointDataTree to be dropped from.
119 /// @param name name of the attribute to drop.
120 template <typename PointDataTreeT>
121 inline void dropAttribute( PointDataTreeT& tree,
122  const Name& name);
123 
124 /// @brief Rename attributes in a VDB tree.
125 ///
126 /// @param tree the PointDataTree.
127 /// @param oldNames a list of old attribute names to rename from.
128 /// @param newNames a list of new attribute names to rename to.
129 ///
130 /// @note Number of oldNames must match the number of newNames.
131 ///
132 /// @note Duplicate names and renaming group attributes are not allowed.
133 template <typename PointDataTreeT>
134 inline void renameAttributes(PointDataTreeT& tree,
135  const std::vector<Name>& oldNames,
136  const std::vector<Name>& newNames);
137 
138 /// @brief Rename an attribute in a VDB tree.
139 ///
140 /// @param tree the PointDataTree.
141 /// @param oldName the old attribute name to rename from.
142 /// @param newName the new attribute name to rename to.
143 ///
144 /// @note newName must not already exist and must not be a group attribute.
145 template <typename PointDataTreeT>
146 inline void renameAttribute(PointDataTreeT& tree,
147  const Name& oldName,
148  const Name& newName);
149 
150 /// @brief Compact attributes in a VDB tree (if possible).
151 ///
152 /// @param tree the PointDataTree.
153 template <typename PointDataTreeT>
154 inline void compactAttributes(PointDataTreeT& tree);
155 
156 
157 ////////////////////////////////////////
158 
159 
160 namespace point_attribute_internal {
161 
162 
163 template <typename ValueType>
165  const AttributeSet::Descriptor&, const ValueType& uniformValue)
166 {
167  AttributeWriteHandle<ValueType> handle(array);
168  handle.collapse(uniformValue);
169 }
170 
171 
173  const AttributeSet::Descriptor& descriptor, const Name& uniformValue)
174 {
175  StringAttributeWriteHandle handle(array, descriptor.getMetadata());
176  handle.collapse(uniformValue);
177 }
178 
179 
180 ////////////////////////////////////////
181 
182 
183 template <typename ValueType, typename CodecType>
185 {
186  static const NamePair& type() {
188  }
189 };
190 
191 
192 template <typename CodecType>
193 struct AttributeTypeConversion<Name, CodecType>
194 {
195  static const NamePair& type() { return StringAttributeArray::attributeType(); }
196 };
197 
198 
199 ////////////////////////////////////////
200 
201 
202 template <typename PointDataTreeT, typename ValueType>
204 {
205  static void add(PointDataTreeT&, const ValueType&) {}
206 
207  template<typename AttributeListType>
208  static void add(PointDataTreeT&, const AttributeListType&) {}
209 };
210 
211 
212 template <typename PointDataTreeT>
213 struct MetadataStorage<PointDataTreeT, Name>
214 {
215  static void add(PointDataTreeT& tree, const Name& uniformValue) {
216  MetaMap& metadata = makeDescriptorUnique(tree)->getMetadata();
217  StringMetaInserter inserter(metadata);
218  inserter.insert(uniformValue);
219  }
220 
221  template<typename AttributeListType>
222  static void add(PointDataTreeT& tree, const AttributeListType& data) {
223  MetaMap& metadata = makeDescriptorUnique(tree)->getMetadata();
224  StringMetaInserter inserter(metadata);
225  Name value;
226 
227  for (size_t i = 0; i < data.size(); i++) {
228  data.get(value, i);
229  inserter.insert(value);
230  }
231  }
232 };
233 
234 
235 } // namespace point_attribute_internal
236 
237 
238 ////////////////////////////////////////
239 
240 
241 template <typename PointDataTreeT>
242 inline void appendAttribute(PointDataTreeT& tree,
243  const Name& name,
244  const NamePair& type,
245  const Index strideOrTotalSize,
246  const bool constantStride,
247  const Metadata* defaultValue,
248  const bool hidden,
249  const bool transient)
250 {
251  auto iter = tree.cbeginLeaf();
252 
253  if (!iter) return;
254 
255  // do not append a non-unique attribute
256 
257  const auto& descriptor = iter->attributeSet().descriptor();
258  const size_t index = descriptor.find(name);
259 
260  if (index != AttributeSet::INVALID_POS) {
261  OPENVDB_THROW(KeyError,
262  "Cannot append an attribute with a non-unique name - " << name << ".");
263  }
264 
265  // create a new attribute descriptor
266 
267  auto newDescriptor = descriptor.duplicateAppend(name, type);
268 
269  // store the attribute default value in the descriptor metadata
270 
271  if (defaultValue) {
272  newDescriptor->setDefaultValue(name, *defaultValue);
273  }
274 
275  // extract new pos
276 
277  const size_t pos = newDescriptor->find(name);
278 
279  // acquire registry lock to avoid locking when appending attributes in parallel
280 
282 
283  // insert attributes using the new descriptor
284 
285  tree::LeafManager<PointDataTreeT> leafManager(tree);
286  leafManager.foreach(
287  [&](typename PointDataTree::LeafNodeType& leaf, size_t /*idx*/) {
288  auto expected = leaf.attributeSet().descriptorPtr();
289 
290  auto attribute = leaf.appendAttribute(*expected, newDescriptor,
291  pos, strideOrTotalSize, constantStride, defaultValue,
292  &lock);
293 
294  if (hidden) attribute->setHidden(true);
295  if (transient) attribute->setTransient(true);
296  }, /*threaded=*/ true
297  );
298 }
299 
300 
301 ////////////////////////////////////////
302 
303 
304 template <typename ValueType, typename CodecType, typename PointDataTreeT>
305 inline void appendAttribute(PointDataTreeT& tree,
306  const std::string& name,
307  const ValueType& uniformValue,
308  const Index strideOrTotalSize,
309  const bool constantStride,
310  const TypedMetadata<ValueType>* defaultValue,
311  const bool hidden,
312  const bool transient)
313 {
315  "ValueType must not be derived from AttributeArray");
316 
320 
322  strideOrTotalSize, constantStride, defaultValue, hidden, transient);
323 
324  // if the uniform value is equal to either the default value provided
325  // through the metadata argument or the default value for this value type,
326  // it is not necessary to perform the collapse
327 
328  const bool uniformIsDefault = math::isExactlyEqual(uniformValue,
329  bool(defaultValue) ? defaultValue->value() : Default<ValueType>::value());
330  if (!uniformIsDefault) {
332  collapseAttribute<ValueType>(tree, name, uniformValue);
333  }
334 }
335 
336 
337 ////////////////////////////////////////
338 
339 
340 template <typename ValueType, typename PointDataTreeT>
341 inline void collapseAttribute( PointDataTreeT& tree,
342  const Name& name,
343  const ValueType& uniformValue)
344 {
346  "ValueType must not be derived from AttributeArray");
347 
348  auto iter = tree.cbeginLeaf();
349 
350  if (!iter) return;
351 
352  const auto& descriptor = iter->attributeSet().descriptor();
353 
354  // throw if attribute name does not exist
355 
356  const size_t index = descriptor.find(name);
357  if (index == AttributeSet::INVALID_POS) {
358  OPENVDB_THROW(KeyError, "Cannot find attribute name in PointDataTree.");
359  }
360 
361  tree::LeafManager<PointDataTreeT> leafManager(tree);
362  leafManager.foreach(
363  [&](typename PointDataTree::LeafNodeType& leaf, size_t /*idx*/) {
364  assert(leaf.hasAttribute(index));
365  AttributeArray& array = leaf.attributeArray(index);
367  array, descriptor, uniformValue);
368  }, /*threaded=*/true
369  );
370 }
371 
372 
373 ////////////////////////////////////////
374 
375 
376 template <typename PointDataTreeT>
377 inline void dropAttributes( PointDataTreeT& tree,
378  const std::vector<size_t>& indices)
379 {
380  auto iter = tree.cbeginLeaf();
381 
382  if (!iter) return;
383 
384  const auto& descriptor = iter->attributeSet().descriptor();
385 
386  // throw if position index present in the indices as this attribute is mandatory
387 
388  const size_t positionIndex = descriptor.find("P");
389  if (positionIndex!= AttributeSet::INVALID_POS &&
390  std::find(indices.begin(), indices.end(), positionIndex) != indices.end()) {
391  OPENVDB_THROW(KeyError, "Cannot drop mandatory position attribute.");
392  }
393 
394  // insert attributes using the new descriptor
395 
396  auto newDescriptor = descriptor.duplicateDrop(indices);
397 
398  tree::LeafManager<PointDataTreeT> leafManager(tree);
399  leafManager.foreach(
400  [&](typename PointDataTree::LeafNodeType& leaf, size_t /*idx*/) {
401  auto expected = leaf.attributeSet().descriptorPtr();
402  leaf.dropAttributes(indices, *expected, newDescriptor);
403  }, /*threaded=*/true
404  );
405 }
406 
407 
408 ////////////////////////////////////////
409 
410 
411 template <typename PointDataTreeT>
412 inline void dropAttributes( PointDataTreeT& tree,
413  const std::vector<Name>& names)
414 {
415  auto iter = tree.cbeginLeaf();
416 
417  if (!iter) return;
418 
419  const AttributeSet& attributeSet = iter->attributeSet();
420  const AttributeSet::Descriptor& descriptor = attributeSet.descriptor();
421 
422  std::vector<size_t> indices;
423 
424  for (const Name& name : names) {
425  const size_t index = descriptor.find(name);
426 
427  // do not attempt to drop an attribute that does not exist
428  if (index == AttributeSet::INVALID_POS) {
429  OPENVDB_THROW(KeyError,
430  "Cannot drop an attribute that does not exist - " << name << ".");
431  }
432 
433  indices.push_back(index);
434  }
435 
436  dropAttributes(tree, indices);
437 }
438 
439 
440 ////////////////////////////////////////
441 
442 
443 template <typename PointDataTreeT>
444 inline void dropAttribute( PointDataTreeT& tree,
445  const size_t& index)
446 {
447  std::vector<size_t> indices{index};
448  dropAttributes(tree, indices);
449 }
450 
451 
452 template <typename PointDataTreeT>
453 inline void dropAttribute( PointDataTreeT& tree,
454  const Name& name)
455 {
456  std::vector<Name> names{name};
457  dropAttributes(tree, names);
458 }
459 
460 
461 ////////////////////////////////////////
462 
463 
464 template <typename PointDataTreeT>
465 inline void renameAttributes( PointDataTreeT& tree,
466  const std::vector<Name>& oldNames,
467  const std::vector<Name>& newNames)
468 {
469  if (oldNames.size() != newNames.size()) {
470  OPENVDB_THROW(ValueError, "Mis-matching sizes of name vectors, cannot rename attributes.");
471  }
472 
473  using Descriptor = AttributeSet::Descriptor;
474 
475  auto iter = tree.beginLeaf();
476 
477  if (!iter) return;
478 
479  const AttributeSet& attributeSet = iter->attributeSet();
480  const Descriptor::Ptr descriptor = attributeSet.descriptorPtr();
481  auto newDescriptor = std::make_shared<Descriptor>(*descriptor);
482 
483  for (size_t i = 0; i < oldNames.size(); i++) {
484  const Name& oldName = oldNames[i];
485  if (descriptor->find(oldName) == AttributeSet::INVALID_POS) {
486  OPENVDB_THROW(KeyError, "Cannot find requested attribute - " << oldName << ".");
487  }
488 
489  const Name& newName = newNames[i];
490  if (descriptor->find(newName) != AttributeSet::INVALID_POS) {
491  OPENVDB_THROW(KeyError,
492  "Cannot rename attribute as new name already exists - " << newName << ".");
493  }
494 
495  const AttributeArray* array = attributeSet.getConst(oldName);
496  assert(array);
497 
498  if (isGroup(*array)) {
499  OPENVDB_THROW(KeyError, "Cannot rename group attribute - " << oldName << ".");
500  }
501 
502  newDescriptor->rename(oldName, newName);
503  }
504 
505  for (; iter; ++iter) {
506  iter->renameAttributes(*descriptor, newDescriptor);
507  }
508 }
509 
510 
511 template <typename PointDataTreeT>
512 inline void renameAttribute(PointDataTreeT& tree,
513  const Name& oldName,
514  const Name& newName)
515 {
516  renameAttributes(tree, {oldName}, {newName});
517 }
518 
519 
520 ////////////////////////////////////////
521 
522 
523 template <typename PointDataTreeT>
524 inline void compactAttributes(PointDataTreeT& tree)
525 {
526  auto iter = tree.beginLeaf();
527  if (!iter) return;
528 
529  tree::LeafManager<PointDataTreeT> leafManager(tree);
530  leafManager.foreach(
531  [&](typename PointDataTree::LeafNodeType& leaf, size_t /*idx*/) {
532  leaf.compactAttributes();
533  }, /*threaded=*/ true
534  );
535 }
536 
537 
538 ////////////////////////////////////////
539 
540 
541 template <typename PointDataTreeT>
542 OPENVDB_DEPRECATED inline void
543 appendAttribute(PointDataTreeT& tree,
544  const Name& name,
545  const NamePair& type,
546  const Index strideOrTotalSize,
547  const bool constantStride,
548  Metadata::Ptr metaDefaultValue,
549  const bool hidden = false,
550  const bool transient = false)
551 {
552  // default metadata value must now be provided as a raw pointer
553  appendAttribute(tree, name, type, strideOrTotalSize, constantStride,
554  metaDefaultValue.get(), hidden, transient);
555 }
556 
557 
558 template <typename ValueType,
559  typename CodecType = NullCodec,
560  typename PointDataTreeT = PointDataTree>
561 OPENVDB_DEPRECATED inline void
562 appendAttribute(PointDataTreeT& tree,
563  const std::string& name,
564  const ValueType& uniformValue,
565  const Index strideOrTotalSize,
566  const bool constantStride,
567  Metadata::Ptr metaDefaultValue,
568  const bool hidden = false,
569  const bool transient = false)
570 {
571  // default metadata value must now be provided as a typed raw pointer
572  TypedMetadata<ValueType>* metadata = nullptr;
573  if (metaDefaultValue) {
574  metadata = dynamic_cast<TypedMetadata<ValueType>*>(metaDefaultValue.get());
575  }
576  appendAttribute<ValueType, CodecType>(tree, name, uniformValue, strideOrTotalSize, constantStride,
577  metadata, hidden, transient);
578 }
579 
580 
581 ////////////////////////////////////////
582 
583 
584 } // namespace points
585 } // namespace OPENVDB_VERSION_NAME
586 } // namespace openvdb
587 
588 #endif // OPENVDB_POINTS_POINT_ATTRIBUTE_HAS_BEEN_INCLUDED
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: ImfName.h:54
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets...
Definition: AttributeSet.h:102
Index insert(const Name &name, Index hint=Index(0))
Insert the string into the metadata using the hint if non-zero.
GLuint const GLchar * name
Definition: glew.h:1814
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:408
T & value()
Return this metadata's value.
Definition: Metadata.h:249
GLuint index
Definition: glew.h:1814
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:166
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Container that maps names (strings) to values of arbitrary types.
Definition: MetaMap.h:19
void collapse()
Replace the existing array with a uniform value (zero if none provided).
bool isGroup(const AttributeArray &array)
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
void appendAttribute(PointDataTreeT &tree, const Name &name, const NamePair &type, const Index strideOrTotalSize=1, const bool constantStride=true, const Metadata *defaultValue=nullptr, const bool hidden=false, const bool transient=false)
Appends a new attribute to the VDB tree (this method does not require a templated AttributeType) ...
Base class for storing attribute data.
GLint GLenum GLsizei GLint GLsizei const void * data
Definition: glew.h:1379
Templated metadata class to hold specific types.
Definition: Metadata.h:121
GLuint GLuint GLsizei GLenum const void * indices
Definition: glew.h:1253
static const NamePair & attributeType()
Return the name of this attribute's type (includes codec)
Class to help with insertion of keyed string values into metadata.
Attribute array storage for string data using Descriptor Metadata.
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...
void collapse()
Set membership for the whole array and attempt to collapse.
GLuint const GLuint * names
Definition: glew.h:2690
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:82
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
static void add(PointDataTreeT &, const AttributeListType &)
std::pair< Name, Name > NamePair
void foreach(const LeafOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to each leaf node in the LeafManager.
Definition: LeafManager.h:496
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1253
GLsizei const GLchar *const * string
Definition: glew.h:1844
typename RootNodeType::LeafNodeType LeafNodeType
Definition: Tree.h:183
Set of Attribute Arrays which tracks metadata about each array.
void collapseAttribute(PointDataTreeT &tree, const Name &name, const ValueType &uniformValue=point_attribute_internal::Default< ValueType >::value())
Collapse the attribute into a uniform value.
void collapseAttribute(AttributeArray &array, const AttributeSet::Descriptor &, const ValueType &uniformValue)
Attribute Group access and filtering for iteration.
void dropAttribute(PointDataTreeT &tree, const size_t &index)
Drop one attribute from the VDB tree (convenience method).
FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out)
Definition: format.h:2104
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glew.h:3446
Base class for storing metadata information in a grid.
Definition: Metadata.h:23
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:38
OIIO_API bool attribute(string_view name, TypeDesc type, const void *val)
GLenum array
Definition: glew.h:9066
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 >>> PointDataTree
Point index tree configured to match the default VDB configurations.
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
void renameAttribute(PointDataTreeT &tree, const Name &oldName, const Name &newName)
Rename an attribute in a VDB tree.
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:112
GLsizei const GLfloat * value
Definition: glew.h:1849
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set's descriptor, which might be shared with other sets...
Definition: AttributeSet.h:108
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82
type
Definition: core.h:528