HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AttributeSet.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 /// @file points/AttributeSet.h
32 ///
33 /// @authors Dan Bailey, Mihai Alden
34 ///
35 /// @brief Set of Attribute Arrays which tracks metadata about each array.
36 
37 #ifndef OPENVDB_POINTS_ATTRIBUTE_SET_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_ATTRIBUTE_SET_HAS_BEEN_INCLUDED
39 
40 #include "AttributeArray.h"
41 #include <openvdb/version.h>
42 #include <openvdb/MetaMap.h>
43 
44 #include <limits>
45 #include <memory>
46 #include <vector>
47 
48 
49 class TestAttributeSet;
50 
51 
52 namespace openvdb {
54 namespace OPENVDB_VERSION_NAME {
55 namespace points {
56 
57 
58 ////////////////////////////////////////
59 
60 
61 /// Ordered collection of uniquely-named attribute arrays
63 {
64 public:
65  enum { INVALID_POS = std::numeric_limits<size_t>::max() };
66 
67  using Ptr = std::shared_ptr<AttributeSet>;
68  using ConstPtr = std::shared_ptr<const AttributeSet>;
69 
70  class Descriptor;
71 
72  using DescriptorPtr = std::shared_ptr<Descriptor>;
73  using DescriptorConstPtr = std::shared_ptr<const Descriptor>;
74 
75  //////////
76 
77  struct Util
78  {
79  /// Attribute and type name pair.
80  struct NameAndType {
81  NameAndType(const std::string& n, const NamePair& t, const Index s = 1)
82  : name(n), type(t), stride(s) {}
86  };
87 
88  using NameAndTypeVec = std::vector<NameAndType>;
89  using NameToPosMap = std::map<std::string, size_t>;
90  using GroupIndex = std::pair<size_t, uint8_t>;
91  };
92 
93  //////////
94 
95  AttributeSet();
96 
97  /// Construct a new AttributeSet from the given AttributeSet.
98  /// @param attributeSet the old attribute set
99  /// @param arrayLength the desired length of the arrays in the new AttributeSet
100  /// @note This constructor is typically used to resize an existing AttributeSet as
101  /// it transfers attribute metadata such as hidden and transient flags
102  AttributeSet(const AttributeSet& attributeSet, Index arrayLength);
103 
104  /// Construct a new AttributeSet from the given Descriptor.
105  /// @param descriptor stored in the new AttributeSet and used in construction
106  /// @param arrayLength the desired length of the arrays in the new AttributeSet
107  /// @note Descriptors do not store attribute metadata such as hidden and transient flags
108  /// which live on the AttributeArrays, so for constructing from an existing AttributeSet
109  /// use the AttributeSet(const AttributeSet&, Index) constructor instead
110  explicit AttributeSet(const DescriptorPtr& descriptor, Index arrayLength = 1);
111 
112  /// Shallow copy constructor, the descriptor and attribute arrays will be shared.
113  AttributeSet(const AttributeSet&);
114 
115  /// Disallow copy assignment, since it wouldn't be obvious whether the copy is deep or shallow.
116  AttributeSet& operator=(const AttributeSet&) = delete;
117 
118  //@{
119  /// @brief Return a reference to this attribute set's descriptor, which might
120  /// be shared with other sets.
121  Descriptor& descriptor() { return *mDescr; }
122  const Descriptor& descriptor() const { return *mDescr; }
123  //@}
124 
125  /// @brief Return a pointer to this attribute set's descriptor, which might be
126  /// shared with other sets
127  DescriptorPtr descriptorPtr() const { return mDescr; }
128 
129  /// Return the number of attributes in this set.
130  size_t size() const { return mAttrs.size(); }
131 
132  /// Return the number of bytes of memory used by this attribute set.
133  size_t memUsage() const;
134 
135  /// @brief Return the position of the attribute array whose name is @a name,
136  /// or @c INVALID_POS if no match is found.
137  size_t find(const std::string& name) const;
138 
139  /// @brief Replace the attribute array whose name is @a name.
140  /// @return The position of the updated attribute array or @c INVALID_POS
141  /// if the given name does not exist or if the replacement failed because
142  /// the new array type does not comply with the descriptor.
143  size_t replace(const std::string& name, const AttributeArray::Ptr&);
144 
145  /// @brief Replace the attribute array stored at position @a pos in this container.
146  /// @return The position of the updated attribute array or @c INVALID_POS
147  /// if replacement failed because the new array type does not comply with
148  /// the descriptor.
149  size_t replace(size_t pos, const AttributeArray::Ptr&);
150 
151  //@{
152  /// @brief Return a pointer to the attribute array whose name is @a name or
153  /// a null pointer if no match is found.
154  const AttributeArray* getConst(const std::string& name) const;
155  const AttributeArray* get(const std::string& name) const;
156  AttributeArray* get(const std::string& name);
157  //@}
158 
159  //@{
160  /// @brief Return a pointer to the attribute array stored at position @a pos
161  /// in this set.
162  const AttributeArray* getConst(size_t pos) const;
163  const AttributeArray* get(size_t pos) const;
164  AttributeArray* get(size_t pos);
165  //@}
166 
167  //@{
168  /// @brief Return the group offset from the name or index of the group
169  /// A group attribute array is a single byte (8-bit), each bit of which
170  /// can denote a group. The group offset is the position of the bit that
171  /// denotes the requested group if all group attribute arrays in the set
172  /// (and only attribute arrays marked as group) were to be laid out linearly
173  /// according to their order in the set.
174  size_t groupOffset(const Name& groupName) const;
175  size_t groupOffset(const Util::GroupIndex& index) const;
176  //@}
177 
178  /// Return the group index from the name of the group
179  Util::GroupIndex groupIndex(const Name& groupName) const;
180  /// Return the group index from the offset of the group
181  /// @note see offset description for groupOffset()
182  Util::GroupIndex groupIndex(const size_t offset) const;
183 
184  /// Return true if the attribute array stored at position @a pos is shared.
185  bool isShared(size_t pos) const;
186  /// @brief If the attribute array stored at position @a pos is shared,
187  /// replace the array with a deep copy of itself that is not
188  /// shared with anyone else.
189  void makeUnique(size_t pos);
190 
191  /// Append attribute @a attribute (simple method)
193  const NamePair& type,
194  const Index strideOrTotalSize = 1,
195  const bool constantStride = true,
196  Metadata::Ptr defaultValue = Metadata::Ptr());
197 
198  /// Append attribute @a attribute (descriptor-sharing)
199  /// Requires current descriptor to match @a expected
200  /// On append, current descriptor is replaced with @a replacement
201  AttributeArray::Ptr appendAttribute(const Descriptor& expected, DescriptorPtr& replacement,
202  const size_t pos, const Index strideOrTotalSize = 1,
203  const bool constantStride = true);
204 
205  /// Drop attributes with @a pos indices (simple method)
206  /// Creates a new descriptor for this attribute set
207  void dropAttributes(const std::vector<size_t>& pos);
208 
209  /// Drop attributes with @a pos indices (descriptor-sharing method)
210  /// Requires current descriptor to match @a expected
211  /// On drop, current descriptor is replaced with @a replacement
212  void dropAttributes(const std::vector<size_t>& pos,
213  const Descriptor& expected, DescriptorPtr& replacement);
214 
215  /// Re-name attributes in set to match a provided descriptor
216  /// Replaces own descriptor with @a replacement
217  void renameAttributes(const Descriptor& expected, const DescriptorPtr& replacement);
218 
219  /// Re order attribute set to match a provided descriptor
220  /// Replaces own descriptor with @a replacement
221  void reorderAttributes(const DescriptorPtr& replacement);
222 
223  /// Replace the current descriptor with a @a replacement
224  /// Note the provided Descriptor must be identical to the replacement
225  /// unless @a allowMismatchingDescriptors is true (default is false)
226  void resetDescriptor(const DescriptorPtr& replacement, const bool allowMismatchingDescriptors = false);
227 
228  /// Read the entire set from a stream.
229  void read(std::istream&);
230  /// Write the entire set to a stream.
231  /// @param outputTransient if true, write out transient attributes
232  void write(std::ostream&, bool outputTransient = false) const;
233 
234  /// This will read the attribute descriptor from a stream.
235  void readDescriptor(std::istream&);
236  /// This will write the attribute descriptor to a stream.
237  /// @param outputTransient if true, write out transient attributes
238  void writeDescriptor(std::ostream&, bool outputTransient = false) const;
239 
240  /// This will read the attribute metadata from a stream.
241  void readMetadata(std::istream&);
242  /// This will write the attribute metadata to a stream.
243  /// @param outputTransient if true, write out transient attributes
244  /// @param paged if true, data is written out in pages
245  void writeMetadata(std::ostream&, bool outputTransient = false, bool paged = false) const;
246 
247  /// This will read the attribute data from a stream.
248  void readAttributes(std::istream&);
249  /// This will write the attribute data to a stream.
250  /// @param outputTransient if true, write out transient attributes
251  void writeAttributes(std::ostream&, bool outputTransient = false) const;
252 
253  /// Compare the descriptors and attribute arrays on the attribute sets
254  /// Exit early if the descriptors do not match
255  bool operator==(const AttributeSet& other) const;
256  bool operator!=(const AttributeSet& other) const { return !this->operator==(other); }
257 
258 private:
259  using AttrArrayVec = std::vector<AttributeArray::Ptr>;
260 
261  DescriptorPtr mDescr;
262  AttrArrayVec mAttrs;
263 }; // class AttributeSet
264 
265 ////////////////////////////////////////
266 
267 
268 /// A container for ABI=5 to help ease introduction of upcoming features
269 #if OPENVDB_ABI_VERSION_NUMBER >= 5
270 namespace future {
271  class Container
272  {
273  class Element { };
274  std::vector<std::shared_ptr<Element>> mElements;
275  };
276 }
277 #endif
278 
279 
280 ////////////////////////////////////////
281 
282 
283 /// @brief An immutable object that stores name, type and AttributeSet position
284 /// for a constant collection of attribute arrays.
285 /// @note The attribute name is actually mutable, but the attribute type
286 /// and position can not be changed after creation.
287 class OPENVDB_API AttributeSet::Descriptor
288 {
289 public:
290  using Ptr = std::shared_ptr<Descriptor>;
291 
296  using ConstIterator = NameToPosMap::const_iterator;
297 
298  /// Utility method to construct a NameAndType sequence.
299  struct Inserter {
301  Inserter& add(const NameAndType& nameAndType) {
302  vec.push_back(nameAndType); return *this;
303  }
304  Inserter& add(const Name& name, const NamePair& type) {
305  vec.emplace_back(name, type); return *this;
306  }
307  Inserter& add(const NameAndTypeVec& other) {
308  for (NameAndTypeVec::const_iterator it = other.begin(), itEnd = other.end(); it != itEnd; ++it) {
309  vec.emplace_back(it->name, it->type);
310  }
311  return *this;
312  }
313  };
314 
315  //////////
316 
317  Descriptor();
318 
319  /// Copy constructor
320  Descriptor(const Descriptor&);
321 
322  /// Create a new descriptor from a position attribute type and assumes "P" (for convenience).
323  static Ptr create(const NamePair&);
324 
325  /// Create a new descriptor as a duplicate with a new attribute appended
326  Ptr duplicateAppend(const Name& name, const NamePair& type) const;
327 
328  /// Create a new descriptor as a duplicate with existing attributes dropped
329  Ptr duplicateDrop(const std::vector<size_t>& pos) const;
330 
331  /// Return the number of attributes in this descriptor.
332  size_t size() const { return mTypes.size(); }
333 
334  /// Return the number of attributes with this attribute type
335  size_t count(const NamePair& type) const;
336 
337  /// Return the number of bytes of memory used by this attribute set.
338  size_t memUsage() const;
339 
340  /// @brief Return the position of the attribute array whose name is @a name,
341  /// or @c INVALID_POS if no match is found.
342  size_t find(const std::string& name) const;
343 
344  /// Rename an attribute array
345  size_t rename(const std::string& fromName, const std::string& toName);
346 
347  /// Return the name of the attribute array's type.
348  const Name& valueType(size_t pos) const;
349  /// Return the name of the attribute array's type.
350  const NamePair& type(size_t pos) const;
351 
352  /// Retrieve metadata map
353  MetaMap& getMetadata();
354  const MetaMap& getMetadata() const;
355 
356  /// Return true if the attribute has a default value
357  bool hasDefaultValue(const Name& name) const;
358  /// Get a default value for an existing attribute
359  template<typename ValueType>
360  ValueType getDefaultValue(const Name& name) const
361  {
362  const size_t pos = find(name);
363  if (pos == INVALID_POS) {
364  OPENVDB_THROW(LookupError, "Cannot find attribute name to set default value.")
365  }
366 
367  std::stringstream ss;
368  ss << "default:" << name;
369 
370  auto metadata = mMetadata.getMetadata<TypedMetadata<ValueType>>(ss.str());
371 
372  if (metadata) return metadata->value();
373 
374  return zeroVal<ValueType>();
375  }
376  /// Set a default value for an existing attribute
377  void setDefaultValue(const Name& name, const Metadata& defaultValue);
378  // Remove the default value if it exists
379  void removeDefaultValue(const Name& name);
380  // Prune any default values for which the key is no longer present
381  void pruneUnusedDefaultValues();
382 
383  /// Return true if this descriptor is equal to the given one.
384  bool operator==(const Descriptor&) const;
385  /// Return true if this descriptor is not equal to the given one.
386  bool operator!=(const Descriptor& rhs) const { return !this->operator==(rhs); }
387  /// Return true if this descriptor contains the same attributes
388  /// as the given descriptor, ignoring attribute order
389  bool hasSameAttributes(const Descriptor& rhs) const;
390 
391  /// Return a reference to the name-to-position map.
392  const NameToPosMap& map() const { return mNameMap; }
393  /// Return a reference to the name-to-position group map.
394  const NameToPosMap& groupMap() const { return mGroupMap; }
395 
396  /// Return @c true if group exists
397  bool hasGroup(const Name& group) const;
398  /// Define a group name to offset mapping
399  void setGroup(const Name& group, const size_t offset);
400  /// Drop any mapping keyed by group name
401  void dropGroup(const Name& group);
402  /// Clear all groups
403  void clearGroups();
404  /// Rename a group
405  size_t renameGroup(const std::string& fromName, const std::string& toName);
406  /// Return a unique name for a group based on given name
407  const Name uniqueGroupName(const Name& name) const;
408 
409  //@{
410  /// @brief Return the group offset from the name or index of the group
411  /// A group attribute array is a single byte (8-bit), each bit of which
412  /// can denote a group. The group offset is the position of the bit that
413  /// denotes the requested group if all group attribute arrays in the set
414  /// (and only attribute arrays marked as group) were to be laid out linearly
415  /// according to their order in the set.
416  size_t groupOffset(const Name& groupName) const;
417  size_t groupOffset(const GroupIndex& index) const;
418  //@}
419 
420  /// Return the group index from the name of the group
421  GroupIndex groupIndex(const Name& groupName) const;
422  /// Return the group index from the offset of the group
423  /// @note see offset description for groupOffset()
424  GroupIndex groupIndex(const size_t offset) const;
425 
426  /// Return a unique name for an attribute array based on given name
427  const Name uniqueName(const Name& name) const;
428 
429  /// Return true if the name is valid
430  static bool validName(const Name& name);
431 
432  /// @brief Extract each name from @a nameStr into @a includeNames, or into @a excludeNames
433  /// if the name is prefixed with a caret.
434  /// @param nameStr the input string of names
435  /// @param includeNames on exit, the list of names that are not prefixed with a caret
436  /// @param excludeNames on exit, the list of names that are prefixed with a caret
437  /// @param includeAll on exit, @c true if a "*" wildcard is present in the @a includeNames
438  static void parseNames( std::vector<std::string>& includeNames,
439  std::vector<std::string>& excludeNames,
440  bool& includeAll,
441  const std::string& nameStr);
442 
443  /// @brief Extract each name from @a nameStr into @a includeNames, or into @a excludeNames
444  /// if the name is prefixed with a caret.
445  static void parseNames( std::vector<std::string>& includeNames,
446  std::vector<std::string>& excludeNames,
447  const std::string& nameStr);
448 
449  /// Serialize this descriptor to the given stream.
450  void write(std::ostream&) const;
451  /// Unserialize this transform from the given stream.
452  void read(std::istream&);
453 
454 protected:
455  /// Append to a vector of names and types from this Descriptor in position order
456  void appendTo(NameAndTypeVec& attrs) const;
457 
458  /// Create a new descriptor from the given attribute and type name pairs
459  /// and copy the group maps and metamap.
460  static Ptr create(const NameAndTypeVec&, const NameToPosMap&, const MetaMap&);
461 
462  size_t insert(const std::string& name, const NamePair& typeName);
463 
464 private:
465  friend class ::TestAttributeSet;
466 
467  NameToPosMap mNameMap;
468  std::vector<NamePair> mTypes;
469  NameToPosMap mGroupMap;
470  MetaMap mMetadata;
471 #if OPENVDB_ABI_VERSION_NUMBER >= 5
472  // as this change is part of an ABI change, there's no good reason to reduce the reserved
473  // space aside from keeping the memory size of an AttributeSet the same for convenience
474  // (note that this assumes a typical three-pointer implementation for std::vector)
475  future::Container mFutureContainer; // occupies 3 reserved slots
476  int64_t mReserved[5]; // for future use
477 #else
478  int64_t mReserved[8]; // for future use
479 #endif
480 }; // class Descriptor
481 
482 } // namespace points
483 } // namespace OPENVDB_VERSION_NAME
484 } // namespace openvdb
485 
486 #endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
487 
488 // Copyright (c) 2012-2018 DreamWorks Animation LLC
489 // All rights reserved. This software is distributed under the
490 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
Definition: ImfName.h:53
ValueType getDefaultValue(const Name &name) const
Get a default value for an existing attribute.
Definition: AttributeSet.h:360
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets...
Definition: AttributeSet.h:121
const Descriptor & descriptor() const
Return a reference to this attribute set's descriptor, which might be shared with other sets...
Definition: AttributeSet.h:122
void dropGroup(PointDataTree &tree, const Name &group, const bool compact=true)
Drops an existing group from the VDB tree.
Definition: PointGroup.h:545
bool operator!=(const Descriptor &rhs) const
Return true if this descriptor is not equal to the given one.
Definition: AttributeSet.h:386
T & value()
Return this metadata's value.
Definition: Metadata.h:299
GLsizei const GLchar *const * string
Definition: glcorearb.h:813
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:189
std::shared_ptr< const AttributeSet > ConstPtr
Definition: AttributeSet.h:68
bool operator!=(const AttributeSet &other) const
Definition: AttributeSet.h:256
void read(T &in, bool &v)
Definition: ImfXdr.h:611
Container that maps names (strings) to values of arbitrary types.
Definition: MetaMap.h:46
Utility method to construct a NameAndType sequence.
Definition: AttributeSet.h:299
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
bool operator==(const BaseDimensions< T > &a, const BaseDimensions< Y > &b)
Definition: Dimensions.h:137
GLdouble n
Definition: glcorearb.h:2007
Base class for storing attribute data.
#define OPENVDB_API
Helper macros for defining library symbol visibility.
Definition: Platform.h:194
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
Templated metadata class to hold specific types.
Definition: Metadata.h:171
GLint GLenum GLboolean GLsizei stride
Definition: glcorearb.h:871
GLintptr offset
Definition: glcorearb.h:664
std::shared_ptr< const Descriptor > DescriptorConstPtr
Definition: AttributeSet.h:73
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
const NameToPosMap & groupMap() const
Return a reference to the name-to-position group map.
Definition: AttributeSet.h:394
NameAndType(const std::string &n, const NamePair &t, const Index s=1)
Definition: AttributeSet.h:81
std::pair< Name, Name > NamePair
GLuint const GLchar * name
Definition: glcorearb.h:785
Inserter & add(const NameAndType &nameAndType)
Definition: AttributeSet.h:301
GLint GLsizei count
Definition: glcorearb.h:404
GLuint index
Definition: glcorearb.h:785
Base class for storing metadata information in a grid.
Definition: Metadata.h:50
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:691
size_t size() const
Return the number of attributes in this set.
Definition: AttributeSet.h:130
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:62
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:107
Inserter & add(const Name &name, const NamePair &type)
Definition: AttributeSet.h:304
Attribute Array storage templated on type and compression codec.
void write(T &out, bool v)
Definition: ImfXdr.h:332
void appendAttribute(PointDataTreeT &tree, const Name &name, const NamePair &type, const Index strideOrTotalSize=1, const bool constantStride=true, Metadata::Ptr metaDefaultValue=Metadata::Ptr(), const bool hidden=false, const bool transient=false)
Appends a new attribute to the VDB tree (this method does not require a templated AttributeType) ...
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:135
DescriptorPtr descriptorPtr() const
Return a pointer to this attribute set's descriptor, which might be shared with other sets...
Definition: AttributeSet.h:127
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
const NameToPosMap & map() const
Return a reference to the name-to-position map.
Definition: AttributeSet.h:392