OpenVDB  9.0.0
AttributeArray.h
Go to the documentation of this file.
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3 
4 /// @file points/AttributeArray.h
5 ///
6 /// @authors Dan Bailey, Mihai Alden, Nick Avramoussis, James Bird, Khang Ngo
7 ///
8 /// @brief Attribute Array storage templated on type and compression codec.
9 
10 #ifndef OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
11 #define OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
12 
13 #include <openvdb/Types.h>
15 #include <openvdb/util/Name.h>
16 #include <openvdb/util/logging.h>
17 #include <openvdb/io/io.h> // MappedFile
18 #include <openvdb/io/Compression.h> // COMPRESS_BLOSC
19 
20 #include "IndexIterator.h"
21 #include "StreamCompression.h"
22 
23 #include <tbb/spin_mutex.h>
24 #include <atomic>
25 
26 #include <memory>
27 #include <mutex>
28 #include <string>
29 #include <type_traits>
30 
31 
32 class TestAttributeArray;
33 
34 namespace openvdb {
36 namespace OPENVDB_VERSION_NAME {
37 
38 
39 using NamePair = std::pair<Name, Name>;
40 
41 namespace points {
42 
43 
44 ////////////////////////////////////////
45 
46 // Utility methods
47 
48 template <typename IntegerT, typename FloatT>
49 inline IntegerT
51 {
52  static_assert(std::is_unsigned<IntegerT>::value, "IntegerT must be unsigned");
53  if (FloatT(0.0) > s) return std::numeric_limits<IntegerT>::min();
54  else if (FloatT(1.0) <= s) return std::numeric_limits<IntegerT>::max();
55  return IntegerT(s * FloatT(std::numeric_limits<IntegerT>::max()));
56 }
57 
58 
59 template <typename FloatT, typename IntegerT>
60 inline FloatT
61 fixedPointToFloatingPoint(const IntegerT s)
62 {
63  static_assert(std::is_unsigned<IntegerT>::value, "IntegerT must be unsigned");
64  return FloatT(s) / FloatT((std::numeric_limits<IntegerT>::max()));
65 }
66 
67 template <typename IntegerVectorT, typename FloatT>
68 inline IntegerVectorT
70 {
71  return IntegerVectorT(
72  floatingPointToFixedPoint<typename IntegerVectorT::ValueType>(v.x()),
73  floatingPointToFixedPoint<typename IntegerVectorT::ValueType>(v.y()),
74  floatingPointToFixedPoint<typename IntegerVectorT::ValueType>(v.z()));
75 }
76 
77 template <typename FloatVectorT, typename IntegerT>
78 inline FloatVectorT
80 {
81  return FloatVectorT(
82  fixedPointToFloatingPoint<typename FloatVectorT::ValueType>(v.x()),
83  fixedPointToFloatingPoint<typename FloatVectorT::ValueType>(v.y()),
84  fixedPointToFloatingPoint<typename FloatVectorT::ValueType>(v.z()));
85 }
86 
87 
88 ////////////////////////////////////////
89 
90 
91 /// Base class for storing attribute data
93 {
94 protected:
95  struct AccessorBase;
96  template <typename T> struct Accessor;
97 
98  using AccessorBasePtr = std::shared_ptr<AccessorBase>;
99 
100 public:
101  enum Flag {
102  TRANSIENT = 0x1, /// by default not written to disk
103  HIDDEN = 0x2, /// hidden from UIs or iterators
104  CONSTANTSTRIDE = 0x8, /// stride size does not vary in the array
105  STREAMING = 0x10, /// streaming mode collapses attributes when first accessed
106  PARTIALREAD = 0x20 /// data has been partially read (compressed bytes is used)
107  };
108 
110  WRITESTRIDED = 0x1, /// data is marked as strided when written
111  WRITEUNIFORM = 0x2, /// data is marked as uniform when written
112  WRITEMEMCOMPRESS = 0x4, /// data is marked as compressed in-memory when written
113  /// (deprecated flag as of ABI=6)
114  WRITEPAGED = 0x8 /// data is written out in pages
115  };
116 
117  // Scoped Lock wrapper class that locks the AttributeArray registry mutex
119  {
120  tbb::spin_mutex::scoped_lock lock;
121  public:
123  }; // class ScopedRegistryLock
124 
125  using Ptr = std::shared_ptr<AttributeArray>;
126  using ConstPtr = std::shared_ptr<const AttributeArray>;
127 
128  using FactoryMethod = Ptr (*)(Index, Index, bool, const Metadata*);
129 
130  template <typename ValueType, typename CodecType> friend class AttributeHandle;
131 
132  AttributeArray(): mPageHandle() { mOutOfCore = 0; }
133  virtual ~AttributeArray()
134  {
135  // if this AttributeArray has been partially read, zero the compressed bytes,
136  // so the page handle won't attempt to clean up invalid memory
137  if (mFlags & PARTIALREAD) mCompressedBytes = 0;
138  }
143 
144  /// Return a copy of this attribute.
145  virtual AttributeArray::Ptr copy() const = 0;
146 
147  /// Return a copy of this attribute.
148 #ifndef _MSC_VER
149  OPENVDB_DEPRECATED_MESSAGE("In-memory compression no longer supported, use AttributeArray::copy() instead")
150 #endif
152 
153  /// Return the number of elements in this array.
154  /// @note This does not count each data element in a strided array
155  virtual Index size() const = 0;
156 
157  /// Return the stride of this array.
158  /// @note a return value of zero means a non-constant stride
159  virtual Index stride() const = 0;
160 
161  /// Return the total number of data elements in this array.
162  /// @note This counts each data element in a strided array
163  virtual Index dataSize() const = 0;
164 
165  /// Return the name of the value type of a single element in this array (e.g., "float" or "vec3d").
166  virtual Name valueType() const = 0;
167 
168  /// Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
169  virtual Name codecType() const = 0;
170 
171  /// Return the size in bytes of the value type of a single element in this array.
172  /// (e.g. "float" -> 4 bytes, "vec3d" -> 24 bytes").
173  virtual Index valueTypeSize() const = 0;
174 
175  /// Return the size in bytes of the storage type of a single element of this array.
176  /// @note If the Codec is a NullCodec, valueSize() == storageSize()
177  virtual Index storageTypeSize() const = 0;
178 
179  /// Return @c true if the value type is floating point
180  virtual bool valueTypeIsFloatingPoint() const = 0;
181 
182  /// Return @c true if the value type is a class (ie vector, matrix or quaternion return true)
183  virtual bool valueTypeIsClass() const = 0;
184 
185  /// Return @c true if the value type is a vector
186  virtual bool valueTypeIsVector() const = 0;
187 
188  /// Return @c true if the value type is a quaternion
189  virtual bool valueTypeIsQuaternion() const = 0;
190 
191  /// Return @c true if the value type is a matrix
192  virtual bool valueTypeIsMatrix() const = 0;
193 
194  /// Return the number of bytes of memory used by this attribute.
195  virtual size_t memUsage() const = 0;
196 
197  /// Create a new attribute array of the given (registered) type, length and stride.
198  /// @details If @a lock is non-null, the AttributeArray registry mutex
199  /// has already been locked
200  static Ptr create(const NamePair& type, Index length, Index stride = 1,
201  bool constantStride = true,
202  const Metadata* metadata = nullptr,
203  const ScopedRegistryLock* lock = nullptr);
204 
205  /// Return @c true if the given attribute type name is registered.
206  static bool isRegistered(const NamePair& type, const ScopedRegistryLock* lock = nullptr);
207  /// Clear the attribute type registry.
208  static void clearRegistry(const ScopedRegistryLock* lock = nullptr);
209 
210  /// Return the name of this attribute's type.
211  virtual const NamePair& type() const = 0;
212  /// Return @c true if this attribute is of the same type as the template parameter.
213  template<typename AttributeArrayType>
214  bool isType() const { return this->type() == AttributeArrayType::attributeType(); }
215 
216  /// Return @c true if this attribute has a value type the same as the template parameter
217  template<typename ValueType>
218  bool hasValueType() const { return this->type().first == typeNameAsString<ValueType>(); }
219 
220  /// @brief Set value at given index @a n from @a sourceIndex of another @a sourceArray.
221  // Windows does not allow base classes to be easily deprecated.
222 #ifndef _MSC_VER
223  OPENVDB_DEPRECATED_MESSAGE("Use copyValues() with source-target index pairs")
224 #endif
225  virtual void set(const Index n, const AttributeArray& sourceArray, const Index sourceIndex) = 0;
226 
227  /// @brief Copy values into this array from a source array to a target array
228  /// as referenced by an iterator.
229  /// @details Iterators must adhere to the ForwardIterator interface described
230  /// in the example below:
231  /// @code
232  /// struct MyIterator
233  /// {
234  /// // returns true if the iterator is referencing valid copying indices
235  /// operator bool() const;
236  /// // increments the iterator
237  /// MyIterator& operator++();
238  /// // returns the source index that the iterator is referencing for copying
239  /// Index sourceIndex() const;
240  /// // returns the target index that the iterator is referencing for copying
241  /// Index targetIndex() const;
242  /// };
243  /// @endcode
244  /// @note It is assumed that the strided storage sizes match, the arrays are both in-core,
245  /// and both value types are floating-point or both integer.
246  /// @note It is possible to use this method to write to a uniform target array
247  /// if the iterator does not have non-zero target indices.
248  /// @note This method is not thread-safe, it must be guaranteed that this array is not
249  /// concurrently modified by another thread and that the source array is also not modified.
250  template<typename IterT>
251  void copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter);
252  /// @brief Like copyValuesUnsafe(), but if @a compact is true, attempt to collapse this array.
253  /// @note This method is not thread-safe, it must be guaranteed that this array is not
254  /// concurrently modified by another thread and that the source array is also not modified.
255  template<typename IterT>
256  void copyValues(const AttributeArray& sourceArray, const IterT& iter, bool compact = true);
257 
258  /// Return @c true if this array is stored as a single uniform value.
259  virtual bool isUniform() const = 0;
260  /// @brief If this array is uniform, replace it with an array of length size().
261  /// @param fill if true, assign the uniform value to each element of the array.
262  virtual void expand(bool fill = true) = 0;
263  /// Replace the existing array with a uniform zero value.
264  virtual void collapse() = 0;
265  /// Compact the existing array to become uniform if all values are identical
266  virtual bool compact() = 0;
267 
268  // Windows does not allow base classes to be deprecated
269 #ifndef _MSC_VER
270  OPENVDB_DEPRECATED_MESSAGE("Previously this compressed the attribute array, now it does nothing")
271 #endif
272  virtual bool compress() = 0;
273  // Windows does not allow base classes to be deprecated
274 #ifndef _MSC_VER
275  OPENVDB_DEPRECATED_MESSAGE("Previously this uncompressed the attribute array, now it does nothing")
276 #endif
277  virtual bool decompress() = 0;
278 
279  /// @brief Specify whether this attribute should be hidden (e.g., from UI or iterators).
280  /// @details This is useful if the attribute is used for blind data or as scratch space
281  /// for a calculation.
282  /// @note Attributes are not hidden by default.
283  void setHidden(bool state);
284  /// Return @c true if this attribute is hidden (e.g., from UI or iterators).
285  bool isHidden() const { return bool(mFlags & HIDDEN); }
286 
287  /// @brief Specify whether this attribute should only exist in memory
288  /// and not be serialized during stream output.
289  /// @note Attributes are not transient by default.
290  void setTransient(bool state);
291  /// Return @c true if this attribute is not serialized during stream output.
292  bool isTransient() const { return bool(mFlags & TRANSIENT); }
293 
294  /// @brief Specify whether this attribute is to be streamed off disk, in which
295  /// case, the attributes are collapsed after being first loaded leaving them
296  /// in a destroyed state.
297  /// @note This operation is not thread-safe.
298  void setStreaming(bool state);
299  /// Return @c true if this attribute is in streaming mode.
300  bool isStreaming() const { return bool(mFlags & STREAMING); }
301 
302  /// Return @c true if this attribute has a constant stride
303  bool hasConstantStride() const { return bool(mFlags & CONSTANTSTRIDE); }
304 
305  /// @brief Retrieve the attribute array flags
306  uint8_t flags() const { return mFlags; }
307 
308  /// Read attribute metadata and buffers from a stream.
309  virtual void read(std::istream&) = 0;
310  /// Write attribute metadata and buffers to a stream.
311  /// @param outputTransient if true, write out transient attributes
312  virtual void write(std::ostream&, bool outputTransient) const = 0;
313  /// Write attribute metadata and buffers to a stream, don't write transient attributes.
314  virtual void write(std::ostream&) const = 0;
315 
316  /// Read attribute metadata from a stream.
317  virtual void readMetadata(std::istream&) = 0;
318  /// Write attribute metadata to a stream.
319  /// @param outputTransient if true, write out transient attributes
320  /// @param paged if true, data is written out in pages
321  virtual void writeMetadata(std::ostream&, bool outputTransient, bool paged) const = 0;
322 
323  /// Read attribute buffers from a stream.
324  virtual void readBuffers(std::istream&) = 0;
325  /// Write attribute buffers to a stream.
326  /// @param outputTransient if true, write out transient attributes
327  virtual void writeBuffers(std::ostream&, bool outputTransient) const = 0;
328 
329  /// Read attribute buffers from a paged stream.
331  /// Write attribute buffers to a paged stream.
332  /// @param outputTransient if true, write out transient attributes
333  virtual void writePagedBuffers(compression::PagedOutputStream&, bool outputTransient) const = 0;
334 
335  /// Ensures all data is in-core
336  virtual void loadData() const = 0;
337 
338  /// Return @c true if all data has been loaded
339  virtual bool isDataLoaded() const = 0;
340 
341  /// Check the compressed bytes and flags. If they are equal, perform a deeper
342  /// comparison check necessary on the inherited types (TypedAttributeArray)
343  /// Requires non operator implementation due to inheritance
344  bool operator==(const AttributeArray& other) const;
345  bool operator!=(const AttributeArray& other) const { return !this->operator==(other); }
346 
347 #if OPENVDB_ABI_VERSION_NUMBER >= 9
348  /// Indirect virtual function to retrieve the data buffer cast to a char byte array
349  const char* constDataAsByteArray() const { return this->dataAsByteArray(); }
350 #endif
351 
352 private:
353  friend class ::TestAttributeArray;
354 
355  /// Virtual function used by the comparison operator to perform
356  /// comparisons on inherited types
357  virtual bool isEqual(const AttributeArray& other) const = 0;
358 
359  /// Virtual function to retrieve the data buffer cast to a char byte array
360  virtual char* dataAsByteArray() = 0;
361  virtual const char* dataAsByteArray() const = 0;
362 
363  /// Private implementation for copyValues/copyValuesUnsafe
364  template <typename IterT>
365  void doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
366  bool rangeChecking = true);
367 
368 protected:
369 #if OPENVDB_ABI_VERSION_NUMBER >= 7
370  AttributeArray(const AttributeArray& rhs, const tbb::spin_mutex::scoped_lock&);
371 #endif
372 
373  /// @brief Specify whether this attribute has a constant stride or not.
374  void setConstantStride(bool state);
375 
376  /// Obtain an Accessor that stores getter and setter functors.
377  virtual AccessorBasePtr getAccessor() const = 0;
378 
379  /// Register a attribute type along with a factory function.
380  static void registerType(const NamePair& type, FactoryMethod,
381  const ScopedRegistryLock* lock = nullptr);
382  /// Remove a attribute type from the registry.
383  static void unregisterType(const NamePair& type,
384  const ScopedRegistryLock* lock = nullptr);
385 
386  bool mIsUniform = true;
387  mutable tbb::spin_mutex mMutex;
388  uint8_t mFlags = 0;
389  uint8_t mUsePagedRead = 0;
390  std::atomic<Index32> mOutOfCore; // interpreted as bool
391  /// used for out-of-core, paged reading
392  union {
395  };
396 }; // class AttributeArray
397 
398 
399 ////////////////////////////////////////
400 
401 
402 /// Accessor base class for AttributeArray storage where type is not available
403 struct AttributeArray::AccessorBase { virtual ~AccessorBase() = default; };
404 
405 /// Templated Accessor stores typed function pointers used in binding
406 /// AttributeHandles
407 template <typename T>
409 {
410  using GetterPtr = T (*)(const AttributeArray* array, const Index n);
411  using SetterPtr = void (*)(AttributeArray* array, const Index n, const T& value);
412  using ValuePtr = void (*)(AttributeArray* array, const T& value);
413 
414  Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler) :
415  mGetter(getter), mSetter(setter), mCollapser(collapser), mFiller(filler) { }
416 
421 }; // struct AttributeArray::Accessor
422 
423 
424 ////////////////////////////////////////
425 
426 
427 namespace attribute_traits
428 {
429  template <typename T> struct TruncateTrait { };
430  template <> struct TruncateTrait<float> { using Type = math::half; };
431  template <> struct TruncateTrait<int> { using Type = short; };
432 
433  template <typename T> struct TruncateTrait<math::Vec3<T>> {
435  };
436 
437  template <bool OneByte, typename T> struct UIntTypeTrait { };
438  template<typename T> struct UIntTypeTrait</*OneByte=*/true, T> { using Type = uint8_t; };
439  template<typename T> struct UIntTypeTrait</*OneByte=*/false, T> { using Type = uint16_t; };
440  template<typename T> struct UIntTypeTrait</*OneByte=*/true, math::Vec3<T>> {
442  };
443  template<typename T> struct UIntTypeTrait</*OneByte=*/false, math::Vec3<T>> {
445  };
446 }
447 
448 
449 ////////////////////////////////////////
450 
451 
452 // Attribute codec schemes
453 
454 struct UnknownCodec { };
455 
456 
457 struct NullCodec
458 {
459  template <typename T>
460  struct Storage { using Type = T; };
461 
462  template<typename ValueType> static void decode(const ValueType&, ValueType&);
463  template<typename ValueType> static void encode(const ValueType&, ValueType&);
464  static const char* name() { return "null"; }
465 };
466 
467 
469 {
470  template <typename T>
472 
473  template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
474  template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
475  static const char* name() { return "trnc"; }
476 };
477 
478 
479 // Fixed-point codec range for voxel-space positions [-0.5,0.5]
481 {
482  static const char* name() { return "fxpt"; }
483  template <typename ValueType> static ValueType encode(const ValueType& value) { return value + ValueType(0.5); }
484  template <typename ValueType> static ValueType decode(const ValueType& value) { return value - ValueType(0.5); }
485 };
486 
487 
488 // Fixed-point codec range for unsigned values in the unit range [0.0,1.0]
489 struct UnitRange
490 {
491  static const char* name() { return "ufxpt"; }
492  template <typename ValueType> static ValueType encode(const ValueType& value) { return value; }
493  template <typename ValueType> static ValueType decode(const ValueType& value) { return value; }
494 };
495 
496 
497 template <bool OneByte, typename Range=PositionRange>
499 {
500  template <typename T>
502 
503  template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
504  template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
505 
506  static const char* name() {
507  static const std::string Name = std::string(Range::name()) + (OneByte ? "8" : "16");
508  return Name.c_str();
509  }
510 };
511 
512 
514 {
515  using StorageType = uint16_t;
516 
517  template <typename T>
518  struct Storage { using Type = StorageType; };
519 
520  template<typename T> static void decode(const StorageType&, math::Vec3<T>&);
521  template<typename T> static void encode(const math::Vec3<T>&, StorageType&);
522  static const char* name() { return "uvec"; }
523 };
524 
525 
526 ////////////////////////////////////////
527 
528 
529 /// Typed class for storing attribute data
530 
531 template<typename ValueType_, typename Codec_ = NullCodec>
533 {
534 public:
535  using Ptr = std::shared_ptr<TypedAttributeArray>;
536  using ConstPtr = std::shared_ptr<const TypedAttributeArray>;
537 
538  using ValueType = ValueType_;
539  using Codec = Codec_;
540  using StorageType = typename Codec::template Storage<ValueType>::Type;
541 
542  //////////
543 
544  /// Default constructor, always constructs a uniform attribute.
545  explicit TypedAttributeArray(Index n = 1, Index strideOrTotalSize = 1, bool constantStride = true,
546  const ValueType& uniformValue = zeroVal<ValueType>());
547 #if OPENVDB_ABI_VERSION_NUMBER >= 7
548  /// Deep copy constructor.
549  /// @note This method is thread-safe (as of ABI=7) for concurrently reading from the
550  /// source attribute array while being deep-copied. Specifically, this means that the
551  /// attribute array being deep-copied can be out-of-core and safely loaded in one thread
552  /// while being copied using this copy-constructor in another thread.
553  /// It is not thread-safe for write.
555  /// Deep copy constructor.
556  OPENVDB_DEPRECATED_MESSAGE("Use copy-constructor without unused bool parameter")
557  TypedAttributeArray(const TypedAttributeArray&, bool /*unused*/);
558 #else
559  /// Deep copy constructor.
560  /// @note This method is not thread-safe for reading or writing, use
561  /// TypedAttributeArray::copy() to ensure thread-safety when reading concurrently.
562  TypedAttributeArray(const TypedAttributeArray&, bool uncompress = false);
563 #endif
564  /// Deep copy assignment operator.
565  /// @note this operator is thread-safe.
566  TypedAttributeArray& operator=(const TypedAttributeArray&);
567  /// Move constructor disabled.
569  /// Move assignment operator disabled.
571 
572  ~TypedAttributeArray() override { this->deallocate(); }
573 
574  /// Return a copy of this attribute.
575  /// @note This method is thread-safe.
576  AttributeArray::Ptr copy() const override;
577 
578  /// Return a copy of this attribute.
579  /// @note This method is thread-safe.
580  OPENVDB_DEPRECATED_MESSAGE("In-memory compression no longer supported, use AttributeArray::copy() instead")
581  AttributeArray::Ptr copyUncompressed() const override;
582 
583  /// Return a new attribute array of the given length @a n and @a stride with uniform value zero.
584  static Ptr create(Index n, Index strideOrTotalSize = 1, bool constantStride = true,
585  const Metadata* metadata = nullptr);
586 
587  /// Cast an AttributeArray to TypedAttributeArray<T>
588  static TypedAttributeArray& cast(AttributeArray& attributeArray);
589 
590  /// Cast an AttributeArray to TypedAttributeArray<T>
591  static const TypedAttributeArray& cast(const AttributeArray& attributeArray);
592 
593  /// Return the name of this attribute's type (includes codec)
594  static const NamePair& attributeType();
595  /// Return the name of this attribute's type.
596  const NamePair& type() const override { return attributeType(); }
597 
598  /// Return @c true if this attribute type is registered.
599  static bool isRegistered();
600  /// Register this attribute type along with a factory function.
601  static void registerType();
602  /// Remove this attribute type from the registry.
603  static void unregisterType();
604 
605  /// Return the number of elements in this array.
606  Index size() const override { return mSize; }
607 
608  /// Return the stride of this array.
609  /// @note A return value of zero means a variable stride
610  Index stride() const override { return hasConstantStride() ? mStrideOrTotalSize : 0; }
611 
612  /// Return the size of the data in this array.
613  Index dataSize() const override {
614  return hasConstantStride() ? mSize * mStrideOrTotalSize : mStrideOrTotalSize;
615  }
616 
617  /// Return the name of the value type of a single element in this array (e.g., "float" or "vec3d").
618  Name valueType() const override { return typeNameAsString<ValueType>(); }
619 
620  /// Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
621  Name codecType() const override { return Codec::name(); }
622 
623  /// Return the size in bytes of the value type of a single element in this array.
624  Index valueTypeSize() const override { return sizeof(ValueType); }
625 
626  /// Return the size in bytes of the storage type of a single element of this array.
627  /// @note If the Codec is a NullCodec, valueSize() == storageSize()
628  Index storageTypeSize() const override { return sizeof(StorageType); }
629 
630  /// Return @c true if the value type is floating point
631  bool valueTypeIsFloatingPoint() const override;
632 
633  /// Return @c true if the value type is a class (ie vector, matrix or quaternion return true)
634  bool valueTypeIsClass() const override;
635 
636  /// Return @c true if the value type is a vector
637  bool valueTypeIsVector() const override;
638 
639  /// Return @c true if the value type is a quaternion
640  bool valueTypeIsQuaternion() const override;
641 
642  /// Return @c true if the value type is a matrix
643  bool valueTypeIsMatrix() const override;
644 
645  /// Return the number of bytes of memory used by this attribute.
646  size_t memUsage() const override;
647 
648  /// Return the value at index @a n (assumes in-core)
649  ValueType getUnsafe(Index n) const;
650  /// Return the value at index @a n
651  ValueType get(Index n) const;
652  /// Return the @a value at index @a n (assumes in-core)
653  template<typename T> void getUnsafe(Index n, T& value) const;
654  /// Return the @a value at index @a n
655  template<typename T> void get(Index n, T& value) const;
656 
657  /// Non-member equivalent to getUnsafe() that static_casts array to this TypedAttributeArray
658  /// (assumes in-core)
659  static ValueType getUnsafe(const AttributeArray* array, const Index n);
660 
661  /// Set @a value at the given index @a n (assumes in-core)
662  void setUnsafe(Index n, const ValueType& value);
663  /// Set @a value at the given index @a n
664  void set(Index n, const ValueType& value);
665  /// Set @a value at the given index @a n (assumes in-core)
666  template<typename T> void setUnsafe(Index n, const T& value);
667  /// Set @a value at the given index @a n
668  template<typename T> void set(Index n, const T& value);
669 
670  /// Non-member equivalent to setUnsafe() that static_casts array to this TypedAttributeArray
671  /// (assumes in-core)
672  static void setUnsafe(AttributeArray* array, const Index n, const ValueType& value);
673 
674  /// Set value at given index @a n from @a sourceIndex of another @a sourceArray
675  OPENVDB_DEPRECATED_MESSAGE("Use copyValues() with source-target index pairs")
676  void set(const Index n, const AttributeArray& sourceArray, const Index sourceIndex) override;
677 
678  /// Return @c true if this array is stored as a single uniform value.
679  bool isUniform() const override { return mIsUniform; }
680  /// @brief Replace the single value storage with an array of length size().
681  /// @note Non-uniform attributes are unchanged.
682  /// @param fill toggle to initialize the array elements with the pre-expanded value.
683  void expand(bool fill = true) override;
684  /// Replace the existing array with a uniform zero value.
685  void collapse() override;
686  /// Compact the existing array to become uniform if all values are identical
687  bool compact() override;
688 
689  /// Replace the existing array with the given uniform value.
690  void collapse(const ValueType& uniformValue);
691  /// @brief Fill the existing array with the given value.
692  /// @note Identical to collapse() except a non-uniform array will not become uniform.
693  void fill(const ValueType& value);
694 
695  /// Non-member equivalent to collapse() that static_casts array to this TypedAttributeArray
696  static void collapse(AttributeArray* array, const ValueType& value);
697  /// Non-member equivalent to fill() that static_casts array to this TypedAttributeArray
698  static void fill(AttributeArray* array, const ValueType& value);
699 
700  /// Compress the attribute array.
701  OPENVDB_DEPRECATED_MESSAGE("Previously this compressed the attribute array, now it does nothing")
702  bool compress() override;
703  /// Uncompress the attribute array.
704  OPENVDB_DEPRECATED_MESSAGE("Previously this uncompressed the attribute array, now it does nothing")
705  bool decompress() override;
706 
707  /// Read attribute data from a stream.
708  void read(std::istream&) override;
709  /// Write attribute data to a stream.
710  /// @param os the output stream
711  /// @param outputTransient if true, write out transient attributes
712  void write(std::ostream& os, bool outputTransient) const override;
713  /// Write attribute data to a stream, don't write transient attributes.
714  void write(std::ostream&) const override;
715 
716  /// Read attribute metadata from a stream.
717  void readMetadata(std::istream&) override;
718  /// Write attribute metadata to a stream.
719  /// @param os the output stream
720  /// @param outputTransient if true, write out transient attributes
721  /// @param paged if true, data is written out in pages
722  void writeMetadata(std::ostream& os, bool outputTransient, bool paged) const override;
723 
724  /// Read attribute buffers from a stream.
725  void readBuffers(std::istream&) override;
726  /// Write attribute buffers to a stream.
727  /// @param os the output stream
728  /// @param outputTransient if true, write out transient attributes
729  void writeBuffers(std::ostream& os, bool outputTransient) const override;
730 
731  /// Read attribute buffers from a paged stream.
732  void readPagedBuffers(compression::PagedInputStream&) override;
733  /// Write attribute buffers to a paged stream.
734  /// @param os the output stream
735  /// @param outputTransient if true, write out transient attributes
736  void writePagedBuffers(compression::PagedOutputStream& os, bool outputTransient) const override;
737 
738  /// Return @c true if this buffer's values have not yet been read from disk.
739  inline bool isOutOfCore() const;
740 
741  /// Ensures all data is in-core
742  void loadData() const override;
743 
744  /// Return @c true if all data has been loaded
745  bool isDataLoaded() const override;
746 
747 #if OPENVDB_ABI_VERSION_NUMBER >= 9
748  /// Return the raw data buffer
749  inline const StorageType* constData() const { return this->data(); }
750 #endif
751 
752 protected:
753  AccessorBasePtr getAccessor() const override;
754 
755  /// Return the raw data buffer
756  inline StorageType* data() { assert(validData()); return mData.get(); }
757  inline const StorageType* data() const { assert(validData()); return mData.get(); }
758 
759  /// Verify that data is not out-of-core or in a partially-read state
760  inline bool validData() const { return !(isOutOfCore() || (flags() & PARTIALREAD)); }
761 
762 private:
763  friend class ::TestAttributeArray;
764 
765 #if OPENVDB_ABI_VERSION_NUMBER >= 7
766  TypedAttributeArray(const TypedAttributeArray&, const tbb::spin_mutex::scoped_lock&);
767 #endif
768 
769  /// Load data from memory-mapped file.
770  inline void doLoad() const;
771  /// Load data from memory-mapped file (unsafe as this function is not protected by a mutex).
772  /// @param compression parameter no longer used
773  inline void doLoadUnsafe(const bool compression = true) const;
774  /// Compress in-core data assuming mutex is locked
775  inline bool compressUnsafe();
776 
777  /// Toggle out-of-core state
778  inline void setOutOfCore(const bool);
779 
780  /// Compare the this data to another attribute array. Used by the base class comparison operator
781  bool isEqual(const AttributeArray& other) const override;
782 
783  /// Virtual function to retrieve the data buffer from the derived class cast to a char byte array
784  char* dataAsByteArray() override;
785  const char* dataAsByteArray() const override;
786 
787  size_t arrayMemUsage() const;
788  void allocate();
789  void deallocate();
790 
791  /// Helper function for use with registerType()
792  static AttributeArray::Ptr factory(Index n, Index strideOrTotalSize, bool constantStride,
793  const Metadata* metadata) {
794  return TypedAttributeArray::create(n, strideOrTotalSize, constantStride, metadata);
795  }
796 
797  static std::unique_ptr<const NamePair> sTypeName;
798  std::unique_ptr<StorageType[]> mData;
799  Index mSize;
800  Index mStrideOrTotalSize;
801 }; // class TypedAttributeArray
802 
803 
804 ////////////////////////////////////////
805 
806 
807 /// AttributeHandles provide access to specific TypedAttributeArray methods without needing
808 /// to know the compression codec, however these methods also incur the cost of a function pointer
809 template <typename ValueType, typename CodecType = UnknownCodec>
811 {
812 public:
814  using Ptr = std::shared_ptr<Handle>;
815  using UniquePtr = std::unique_ptr<Handle>;
816 
817 protected:
818  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
819  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
820  using ValuePtr = void (*)(AttributeArray* array, const ValueType& value);
821 
822 public:
823  static Ptr create(const AttributeArray& array, const bool collapseOnDestruction = true);
824 
825  AttributeHandle(const AttributeArray& array, const bool collapseOnDestruction = true);
826 
827  AttributeHandle(const AttributeHandle&) = default;
829 
830  virtual ~AttributeHandle();
831 
832  Index stride() const { return mStrideOrTotalSize; }
833  Index size() const { return mSize; }
834 
835  bool isUniform() const;
836  bool hasConstantStride() const;
837 
838  ValueType get(Index n, Index m = 0) const;
839 
840  const AttributeArray& array() const;
841 
842 protected:
843  Index index(Index n, Index m) const;
844 
846 
851 
852 private:
853  friend class ::TestAttributeArray;
854 
855  template <bool IsUnknownCodec>
856  typename std::enable_if<IsUnknownCodec, bool>::type compatibleType() const;
857 
858  template <bool IsUnknownCodec>
859  typename std::enable_if<!IsUnknownCodec, bool>::type compatibleType() const;
860 
861  template <bool IsUnknownCodec>
862  typename std::enable_if<IsUnknownCodec, ValueType>::type get(Index index) const;
863 
864  template <bool IsUnknownCodec>
865  typename std::enable_if<!IsUnknownCodec, ValueType>::type get(Index index) const;
866 
867  // local copy of AttributeArray (to preserve compression)
868  AttributeArray::Ptr mLocalArray;
869 
870  Index mStrideOrTotalSize;
871  Index mSize;
872  bool mCollapseOnDestruction;
873 }; // class AttributeHandle
874 
875 
876 ////////////////////////////////////////
877 
878 
879 /// Write-able version of AttributeHandle
880 template <typename ValueType, typename CodecType = UnknownCodec>
881 class AttributeWriteHandle : public AttributeHandle<ValueType, CodecType>
882 {
883 public:
885  using Ptr = std::shared_ptr<Handle>;
886  using ScopedPtr = std::unique_ptr<Handle>;
887 
888  static Ptr create(AttributeArray& array, const bool expand = true);
889 
890  AttributeWriteHandle(AttributeArray& array, const bool expand = true);
891 
892  virtual ~AttributeWriteHandle() = default;
893 
894  /// @brief If this array is uniform, replace it with an array of length size().
895  /// @param fill if true, assign the uniform value to each element of the array.
896  void expand(bool fill = true);
897 
898  /// Replace the existing array with a uniform value (zero if none provided).
899  void collapse();
900  void collapse(const ValueType& uniformValue);
901 
902  /// Compact the existing array to become uniform if all values are identical
903  bool compact();
904 
905  /// @brief Fill the existing array with the given value.
906  /// @note Identical to collapse() except a non-uniform array will not become uniform.
907  void fill(const ValueType& value);
908 
909  void set(Index n, const ValueType& value);
910  void set(Index n, Index m, const ValueType& value);
911 
913 
914 private:
915  friend class ::TestAttributeArray;
916 
917  template <bool IsUnknownCodec>
918  typename std::enable_if<IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
919 
920  template <bool IsUnknownCodec>
921  typename std::enable_if<!IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
922 }; // class AttributeWriteHandle
923 
924 
925 ////////////////////////////////////////
926 
927 
928 // Attribute codec implementation
929 
930 
931 template<typename ValueType>
932 inline void
933 NullCodec::decode(const ValueType& data, ValueType& val)
934 {
935  val = data;
936 }
937 
938 
939 template<typename ValueType>
940 inline void
941 NullCodec::encode(const ValueType& val, ValueType& data)
942 {
943  data = val;
944 }
945 
946 
947 template<typename StorageType, typename ValueType>
948 inline void
949 TruncateCodec::decode(const StorageType& data, ValueType& val)
950 {
951  val = static_cast<ValueType>(data);
952 }
953 
954 
955 template<typename StorageType, typename ValueType>
956 inline void
957 TruncateCodec::encode(const ValueType& val, StorageType& data)
958 {
959  data = static_cast<StorageType>(val);
960 }
961 
962 
963 template <bool OneByte, typename Range>
964 template<typename StorageType, typename ValueType>
965 inline void
966 FixedPointCodec<OneByte, Range>::decode(const StorageType& data, ValueType& val)
967 {
968  val = fixedPointToFloatingPoint<ValueType>(data);
969 
970  // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
971 
972  val = Range::template decode<ValueType>(val);
973 }
974 
975 
976 template <bool OneByte, typename Range>
977 template<typename StorageType, typename ValueType>
978 inline void
979 FixedPointCodec<OneByte, Range>::encode(const ValueType& val, StorageType& data)
980 {
981  // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
982 
983  const ValueType newVal = Range::template encode<ValueType>(val);
984 
985  data = floatingPointToFixedPoint<StorageType>(newVal);
986 }
987 
988 
989 template<typename T>
990 inline void
991 UnitVecCodec::decode(const StorageType& data, math::Vec3<T>& val)
992 {
993  val = math::QuantizedUnitVec::unpack(data);
994 }
995 
996 
997 template<typename T>
998 inline void
999 UnitVecCodec::encode(const math::Vec3<T>& val, StorageType& data)
1000 {
1001  data = math::QuantizedUnitVec::pack(val);
1002 }
1003 
1004 
1005 ////////////////////////////////////////
1006 
1007 // AttributeArray implementation
1008 
1009 template <typename IterT>
1010 void AttributeArray::doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
1011  bool rangeChecking/*=true*/)
1012 {
1013  // ensure both arrays have float-float or integer-integer value types
1014  assert(sourceArray.valueTypeIsFloatingPoint() == this->valueTypeIsFloatingPoint());
1015  // ensure both arrays have been loaded from disk (if delay-loaded)
1016  assert(sourceArray.isDataLoaded() && this->isDataLoaded());
1017  // ensure storage size * stride matches on both arrays
1018  assert(this->storageTypeSize()*this->stride() ==
1019  sourceArray.storageTypeSize()*sourceArray.stride());
1020 
1021  const size_t bytes(sourceArray.storageTypeSize()*sourceArray.stride());
1022  const char* const sourceBuffer = sourceArray.dataAsByteArray();
1023  char* const targetBuffer = this->dataAsByteArray();
1024  assert(sourceBuffer && targetBuffer);
1025 
1026  if (rangeChecking && this->isUniform()) {
1027  OPENVDB_THROW(IndexError, "Cannot copy array data as target array is uniform.");
1028  }
1029 
1030  const bool sourceIsUniform = sourceArray.isUniform();
1031 
1032  const Index sourceDataSize = rangeChecking ? sourceArray.dataSize() : 0;
1033  const Index targetDataSize = rangeChecking ? this->dataSize() : 0;
1034 
1035  for (IterT it(iter); it; ++it) {
1036  const Index sourceIndex = sourceIsUniform ? 0 : it.sourceIndex();
1037  const Index targetIndex = it.targetIndex();
1038 
1039  if (rangeChecking) {
1040  if (sourceIndex >= sourceDataSize) {
1042  "Cannot copy array data as source index exceeds size of source array.");
1043  }
1044  if (targetIndex >= targetDataSize) {
1046  "Cannot copy array data as target index exceeds size of target array.");
1047  }
1048  } else {
1049  // range-checking asserts
1050  assert(sourceIndex < sourceArray.dataSize());
1051  assert(targetIndex < this->dataSize());
1052  if (this->isUniform()) assert(targetIndex == Index(0));
1053  }
1054 
1055  const size_t targetOffset(targetIndex * bytes);
1056  const size_t sourceOffset(sourceIndex * bytes);
1057 
1058  std::memcpy(targetBuffer + targetOffset, sourceBuffer + sourceOffset, bytes);
1059  }
1060 }
1061 
1062 template <typename IterT>
1063 void AttributeArray::copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter)
1064 {
1065  this->doCopyValues(sourceArray, iter, /*range-checking=*/false);
1066 }
1067 
1068 template <typename IterT>
1069 void AttributeArray::copyValues(const AttributeArray& sourceArray, const IterT& iter,
1070  bool compact/* = true*/)
1071 {
1072  const Index bytes = sourceArray.storageTypeSize();
1073  if (bytes != this->storageTypeSize()) {
1074  OPENVDB_THROW(TypeError, "Cannot copy array data due to mis-match in storage type sizes.");
1075  }
1076 
1077  // ensure both arrays have been loaded from disk
1078  sourceArray.loadData();
1079  this->loadData();
1080 
1081  // if the target array is uniform, expand it first
1082  this->expand();
1083 
1084  // TODO: Acquire mutex locks for source and target arrays to ensure that
1085  // value copying is always thread-safe. Note that the unsafe method will be
1086  // faster, but can only be used if neither the source or target arrays are
1087  // modified during copying. Note that this will require a new private
1088  // virtual method with ABI=7 to access the mutex from the derived class.
1089 
1090  this->doCopyValues(sourceArray, iter, true);
1091 
1092  // attempt to compact target array
1093  if (compact) {
1094  this->compact();
1095  }
1096 }
1097 
1098 
1099 ////////////////////////////////////////
1100 
1101 // TypedAttributeArray implementation
1102 
1103 template<typename ValueType_, typename Codec_>
1104 std::unique_ptr<const NamePair> TypedAttributeArray<ValueType_, Codec_>::sTypeName;
1105 
1106 
1107 template<typename ValueType_, typename Codec_>
1109  Index n, Index strideOrTotalSize, bool constantStride, const ValueType& uniformValue)
1110  : AttributeArray()
1111  , mData(new StorageType[1])
1112  , mSize(n)
1113  , mStrideOrTotalSize(strideOrTotalSize)
1114 {
1115  if (constantStride) {
1116  this->setConstantStride(true);
1117  if (strideOrTotalSize == 0) {
1118  OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a constant stride requires that " \
1119  "stride to be at least one.")
1120  }
1121  }
1122  else {
1123  this->setConstantStride(false);
1124  if (mStrideOrTotalSize < n) {
1125  OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a non-constant stride must have " \
1126  "a total size of at least the number of elements in the array.")
1127  }
1128  }
1129  mSize = std::max(Index(1), mSize);
1130  mStrideOrTotalSize = std::max(Index(1), mStrideOrTotalSize);
1131  Codec::encode(uniformValue, this->data()[0]);
1132 }
1133 
1134 
1135 #if OPENVDB_ABI_VERSION_NUMBER >= 7
1136 template<typename ValueType_, typename Codec_>
1138  : TypedAttributeArray(rhs, tbb::spin_mutex::scoped_lock(rhs.mMutex))
1139 {
1140 }
1141 
1142 
1143 template<typename ValueType_, typename Codec_>
1145  const tbb::spin_mutex::scoped_lock& lock)
1146  : AttributeArray(rhs, lock)
1147 #else
1148 template<typename ValueType_, typename Codec_>
1149 TypedAttributeArray<ValueType_, Codec_>::TypedAttributeArray(const TypedAttributeArray& rhs, bool)
1150  : AttributeArray(rhs)
1151 #endif
1152  , mSize(rhs.mSize)
1153  , mStrideOrTotalSize(rhs.mStrideOrTotalSize)
1154 {
1155  if (this->validData()) {
1156  this->allocate();
1157  std::memcpy(static_cast<void*>(this->data()), rhs.data(), this->arrayMemUsage());
1158  }
1159 }
1160 
1161 
1162 template<typename ValueType_, typename Codec_>
1163 TypedAttributeArray<ValueType_, Codec_>&
1165 {
1166  if (&rhs != this) {
1167  // lock both the source and target arrays to ensure thread-safety
1168  tbb::spin_mutex::scoped_lock lock(mMutex);
1169  tbb::spin_mutex::scoped_lock rhsLock(rhs.mMutex);
1170 
1171  this->deallocate();
1172 
1173  mFlags = rhs.mFlags;
1174  mUsePagedRead = rhs.mUsePagedRead;
1175  mSize = rhs.mSize;
1176  mStrideOrTotalSize = rhs.mStrideOrTotalSize;
1177  mIsUniform = rhs.mIsUniform;
1178 
1179  if (this->validData()) {
1180  this->allocate();
1181  std::memcpy(static_cast<void*>(this->data()), rhs.data(), this->arrayMemUsage());
1182  }
1183  }
1184 
1185  return *this;
1186 }
1187 
1188 
1189 template<typename ValueType_, typename Codec_>
1190 inline const NamePair&
1192 {
1193  static std::once_flag once;
1194  std::call_once(once, []()
1195  {
1196  sTypeName.reset(new NamePair(typeNameAsString<ValueType>(), Codec::name()));
1197  });
1198  return *sTypeName;
1199 }
1200 
1201 
1202 template<typename ValueType_, typename Codec_>
1203 inline bool
1205 {
1207 }
1208 
1209 
1210 template<typename ValueType_, typename Codec_>
1211 inline void
1213 {
1214  AttributeArray::registerType(TypedAttributeArray::attributeType(), TypedAttributeArray::factory);
1215 }
1216 
1217 
1218 template<typename ValueType_, typename Codec_>
1219 inline void
1221 {
1223 }
1224 
1225 
1226 template<typename ValueType_, typename Codec_>
1229  const Metadata* metadata)
1230 {
1231  const TypedMetadata<ValueType>* typedMetadata = metadata ?
1232  dynamic_cast<const TypedMetadata<ValueType>*>(metadata) : nullptr;
1233 
1234  return Ptr(new TypedAttributeArray(n, stride, constantStride,
1235  typedMetadata ? typedMetadata->value() : zeroVal<ValueType>()));
1236 }
1237 
1238 template<typename ValueType_, typename Codec_>
1241 {
1242  if (!attributeArray.isType<TypedAttributeArray>()) {
1243  OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1244  }
1245  return static_cast<TypedAttributeArray&>(attributeArray);
1246 }
1247 
1248 template<typename ValueType_, typename Codec_>
1251 {
1252  if (!attributeArray.isType<TypedAttributeArray>()) {
1253  OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1254  }
1255  return static_cast<const TypedAttributeArray&>(attributeArray);
1256 }
1257 
1258 template<typename ValueType_, typename Codec_>
1261 {
1262 #if OPENVDB_ABI_VERSION_NUMBER < 7
1263  tbb::spin_mutex::scoped_lock lock(mMutex);
1264 #endif
1266 }
1267 
1268 
1269 template<typename ValueType_, typename Codec_>
1272 {
1273  return this->copy();
1274 }
1275 
1276 
1277 template<typename ValueType_, typename Codec_>
1278 size_t
1280 {
1281  if (this->isOutOfCore()) return 0;
1282 
1283  return (mIsUniform ? 1 : this->dataSize()) * sizeof(StorageType);
1284 }
1285 
1286 
1287 template<typename ValueType_, typename Codec_>
1288 void
1289 TypedAttributeArray<ValueType_, Codec_>::allocate()
1290 {
1291  assert(!mData);
1292  if (mIsUniform) {
1293  mData.reset(new StorageType[1]);
1294  }
1295  else {
1296  const size_t size(this->dataSize());
1297  assert(size > 0);
1298  mData.reset(new StorageType[size]);
1299  }
1300 }
1301 
1302 
1303 template<typename ValueType_, typename Codec_>
1304 void
1305 TypedAttributeArray<ValueType_, Codec_>::deallocate()
1306 {
1307  // detach from file if delay-loaded
1308  if (this->isOutOfCore()) {
1309  this->setOutOfCore(false);
1310  this->mPageHandle.reset();
1311  }
1312  if (mData) mData.reset();
1313 }
1314 
1315 
1316 template<typename ValueType_, typename Codec_>
1317 bool
1319 {
1320  // TODO: Update to use Traits that correctly handle matrices and quaternions.
1321 
1328 
1329  using ElementT = typename VecTraits<ValueType>::ElementType;
1330 
1331  // half is not defined as float point as expected, so explicitly handle it
1333 }
1334 
1335 
1336 template<typename ValueType_, typename Codec_>
1337 bool
1339 {
1340  // half is not defined as a non-class type as expected, so explicitly exclude it
1342 }
1343 
1344 
1345 template<typename ValueType_, typename Codec_>
1346 bool
1348 {
1350 }
1351 
1352 
1353 template<typename ValueType_, typename Codec_>
1354 bool
1356 {
1357  // TODO: improve performance by making this a compile-time check using type traits
1358  return !this->valueType().compare(0, 4, "quat");
1359 }
1360 
1361 
1362 template<typename ValueType_, typename Codec_>
1363 bool
1365 {
1366  // TODO: improve performance by making this a compile-time check using type traits
1367  return !this->valueType().compare(0, 3, "mat");
1368 }
1369 
1370 
1371 template<typename ValueType_, typename Codec_>
1372 size_t
1374 {
1375  return sizeof(*this) + (bool(mData) ? this->arrayMemUsage() : 0);
1376 }
1377 
1378 
1379 template<typename ValueType_, typename Codec_>
1382 {
1383  assert(n < this->dataSize());
1384 
1385  ValueType val;
1386  Codec::decode(/*in=*/this->data()[mIsUniform ? 0 : n], /*out=*/val);
1387  return val;
1388 }
1389 
1390 
1391 template<typename ValueType_, typename Codec_>
1394 {
1395  if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1396  if (this->isOutOfCore()) this->doLoad();
1397 
1398  return this->getUnsafe(n);
1399 }
1400 
1401 
1402 template<typename ValueType_, typename Codec_>
1403 template<typename T>
1404 void
1406 {
1407  val = static_cast<T>(this->getUnsafe(n));
1408 }
1409 
1410 
1411 template<typename ValueType_, typename Codec_>
1412 template<typename T>
1413 void
1415 {
1416  val = static_cast<T>(this->get(n));
1417 }
1418 
1419 
1420 template<typename ValueType_, typename Codec_>
1423 {
1424  return static_cast<const TypedAttributeArray<ValueType, Codec>*>(array)->getUnsafe(n);
1425 }
1426 
1427 
1428 template<typename ValueType_, typename Codec_>
1429 void
1431 {
1432  assert(n < this->dataSize());
1433  assert(!this->isOutOfCore());
1434  assert(!this->isUniform());
1435 
1436  // this unsafe method assumes the data is not uniform, however if it is, this redirects the index
1437  // to zero, which is marginally less efficient but ensures not writing to an illegal address
1438 
1439  Codec::encode(/*in=*/val, /*out=*/this->data()[mIsUniform ? 0 : n]);
1440 }
1441 
1442 
1443 template<typename ValueType_, typename Codec_>
1444 void
1446 {
1447  if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1448  if (this->isOutOfCore()) this->doLoad();
1449  if (this->isUniform()) this->expand();
1450 
1451  this->setUnsafe(n, val);
1452 }
1453 
1454 
1455 template<typename ValueType_, typename Codec_>
1456 template<typename T>
1457 void
1459 {
1460  this->setUnsafe(n, static_cast<ValueType>(val));
1461 }
1462 
1463 
1464 template<typename ValueType_, typename Codec_>
1465 template<typename T>
1466 void
1468 {
1469  this->set(n, static_cast<ValueType>(val));
1470 }
1471 
1472 
1473 template<typename ValueType_, typename Codec_>
1474 void
1476 {
1477  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->setUnsafe(n, value);
1478 }
1479 
1480 
1481 template<typename ValueType_, typename Codec_>
1482 void
1484 {
1485  const TypedAttributeArray& sourceTypedArray = static_cast<const TypedAttributeArray&>(sourceArray);
1486 
1487  ValueType sourceValue;
1488  sourceTypedArray.get(sourceIndex, sourceValue);
1489 
1490  this->set(n, sourceValue);
1491 }
1492 
1493 
1494 template<typename ValueType_, typename Codec_>
1495 void
1497 {
1498  if (!mIsUniform) return;
1499 
1500  const StorageType val = this->data()[0];
1501 
1502  {
1503  tbb::spin_mutex::scoped_lock lock(mMutex);
1504  this->deallocate();
1505  mIsUniform = false;
1506  this->allocate();
1507  }
1508 
1509  if (fill) {
1510  for (Index i = 0; i < this->dataSize(); ++i) this->data()[i] = val;
1511  }
1512 }
1513 
1514 
1515 template<typename ValueType_, typename Codec_>
1516 bool
1518 {
1519  if (mIsUniform) return true;
1520 
1521  // compaction is not possible if any values are different
1522  const ValueType_ val = this->get(0);
1523  for (Index i = 1; i < this->dataSize(); i++) {
1524  if (!math::isExactlyEqual(this->get(i), val)) return false;
1525  }
1526 
1527  this->collapse(this->get(0));
1528  return true;
1529 }
1530 
1531 
1532 template<typename ValueType_, typename Codec_>
1533 void
1535 {
1536  this->collapse(zeroVal<ValueType>());
1537 }
1538 
1539 
1540 template<typename ValueType_, typename Codec_>
1541 void
1543 {
1544  if (!mIsUniform) {
1545  tbb::spin_mutex::scoped_lock lock(mMutex);
1546  this->deallocate();
1547  mIsUniform = true;
1548  this->allocate();
1549  }
1550  Codec::encode(uniformValue, this->data()[0]);
1551 }
1552 
1553 
1554 template<typename ValueType_, typename Codec_>
1555 void
1557 {
1558  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->collapse(value);
1559 }
1560 
1561 
1562 template<typename ValueType_, typename Codec_>
1563 void
1565 {
1566  if (this->isOutOfCore()) {
1567  tbb::spin_mutex::scoped_lock lock(mMutex);
1568  this->deallocate();
1569  this->allocate();
1570  }
1571 
1572  const Index size = mIsUniform ? 1 : this->dataSize();
1573  for (Index i = 0; i < size; ++i) {
1574  Codec::encode(value, this->data()[i]);
1575  }
1576 }
1577 
1578 
1579 template<typename ValueType_, typename Codec_>
1580 void
1582 {
1583  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->fill(value);
1584 }
1585 
1586 
1587 template<typename ValueType_, typename Codec_>
1588 inline bool
1590 {
1591  return false;
1592 }
1593 
1594 
1595 template<typename ValueType_, typename Codec_>
1596 inline bool
1598 {
1599  return false;
1600 }
1601 
1602 
1603 template<typename ValueType_, typename Codec_>
1604 inline bool
1606 {
1607  return false;
1608 }
1609 
1610 
1611 template<typename ValueType_, typename Codec_>
1612 bool
1614 {
1615  return mOutOfCore;
1616 }
1617 
1618 
1619 template<typename ValueType_, typename Codec_>
1620 void
1622 {
1623  mOutOfCore = b;
1624 }
1625 
1626 
1627 template<typename ValueType_, typename Codec_>
1628 void
1629 TypedAttributeArray<ValueType_, Codec_>::doLoad() const
1630 {
1631  if (!(this->isOutOfCore())) return;
1632 
1633  TypedAttributeArray<ValueType_, Codec_>* self =
1634  const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
1635 
1636  // This lock will be contended at most once, after which this buffer
1637  // will no longer be out-of-core.
1638  tbb::spin_mutex::scoped_lock lock(self->mMutex);
1639  this->doLoadUnsafe();
1640 }
1641 
1642 
1643 template<typename ValueType_, typename Codec_>
1644 void
1646 {
1647  this->doLoad();
1648 }
1649 
1650 
1651 template<typename ValueType_, typename Codec_>
1652 bool
1654 {
1655  return !this->isOutOfCore();
1656 }
1657 
1658 
1659 template<typename ValueType_, typename Codec_>
1660 void
1662 {
1663  this->readMetadata(is);
1664  this->readBuffers(is);
1665 }
1666 
1667 
1668 template<typename ValueType_, typename Codec_>
1669 void
1671 {
1672  // read data
1673 
1674  Index64 bytes = Index64(0);
1675  is.read(reinterpret_cast<char*>(&bytes), sizeof(Index64));
1676  bytes = bytes - /*flags*/sizeof(Int16) - /*size*/sizeof(Index);
1677 
1678  uint8_t flags = uint8_t(0);
1679  is.read(reinterpret_cast<char*>(&flags), sizeof(uint8_t));
1680  mFlags = flags;
1681 
1682  uint8_t serializationFlags = uint8_t(0);
1683  is.read(reinterpret_cast<char*>(&serializationFlags), sizeof(uint8_t));
1684 
1685  Index size = Index(0);
1686  is.read(reinterpret_cast<char*>(&size), sizeof(Index));
1687  mSize = size;
1688 
1689  // warn if an unknown flag has been set
1690  if (mFlags >= 0x20) {
1691  OPENVDB_LOG_WARN("Unknown attribute flags for VDB file format.");
1692  }
1693  // error if an unknown serialization flag has been set,
1694  // as this will adjust the layout of the data and corrupt the ability to read
1695  if (serializationFlags >= 0x10) {
1696  OPENVDB_THROW(IoError, "Unknown attribute serialization flags for VDB file format.");
1697  }
1698 
1699  // set uniform, compressed and page read state
1700 
1701  mIsUniform = serializationFlags & WRITEUNIFORM;
1702  mUsePagedRead = serializationFlags & WRITEPAGED;
1703  mCompressedBytes = bytes;
1704  mFlags |= PARTIALREAD; // mark data as having been partially read
1705 
1706  // read strided value (set to 1 if array is not strided)
1707 
1708  if (serializationFlags & WRITESTRIDED) {
1709  Index stride = Index(0);
1710  is.read(reinterpret_cast<char*>(&stride), sizeof(Index));
1711  mStrideOrTotalSize = stride;
1712  }
1713  else {
1714  mStrideOrTotalSize = 1;
1715  }
1716 }
1717 
1718 
1719 template<typename ValueType_, typename Codec_>
1720 void
1722 {
1723  if (mUsePagedRead) {
1724  // use readBuffers(PagedInputStream&) for paged buffers
1725  OPENVDB_THROW(IoError, "Cannot read paged AttributeArray buffers.");
1726  }
1727 
1728  tbb::spin_mutex::scoped_lock lock(mMutex);
1729 
1730  this->deallocate();
1731 
1732  uint8_t bloscCompressed(0);
1733  if (!mIsUniform) is.read(reinterpret_cast<char*>(&bloscCompressed), sizeof(uint8_t));
1734 
1735  assert(mFlags & PARTIALREAD);
1736  std::unique_ptr<char[]> buffer(new char[mCompressedBytes]);
1737  is.read(buffer.get(), mCompressedBytes);
1738  mCompressedBytes = 0;
1739  mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1740 
1741  // compressed on-disk
1742 
1743  if (bloscCompressed == uint8_t(1)) {
1744 
1745  // decompress buffer
1746 
1747  const size_t inBytes = this->dataSize() * sizeof(StorageType);
1748  std::unique_ptr<char[]> newBuffer = compression::bloscDecompress(buffer.get(), inBytes);
1749  if (newBuffer) buffer.reset(newBuffer.release());
1750  }
1751 
1752  // set data to buffer
1753 
1754  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1755 }
1756 
1757 
1758 template<typename ValueType_, typename Codec_>
1759 void
1761 {
1762  if (!mUsePagedRead) {
1763  if (!is.sizeOnly()) this->readBuffers(is.getInputStream());
1764  return;
1765  }
1766 
1767  // If this array is being read from a memory-mapped file, delay loading of its data
1768  // until the data is actually accessed.
1770  const bool delayLoad = (mappedFile.get() != nullptr);
1771 
1772  if (is.sizeOnly())
1773  {
1774  size_t compressedBytes(mCompressedBytes);
1775  mCompressedBytes = 0; // if not set to zero, mPageHandle will attempt to destroy invalid memory
1776  mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1777  assert(!mPageHandle);
1778  mPageHandle = is.createHandle(compressedBytes);
1779  return;
1780  }
1781 
1782  assert(mPageHandle);
1783 
1784  tbb::spin_mutex::scoped_lock lock(mMutex);
1785 
1786  this->deallocate();
1787 
1788  this->setOutOfCore(delayLoad);
1789  is.read(mPageHandle, std::streamsize(mPageHandle->size()), delayLoad);
1790 
1791  if (!delayLoad) {
1792  std::unique_ptr<char[]> buffer = mPageHandle->read();
1793  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1794  mPageHandle.reset();
1795  }
1796 
1797  // clear page state
1798 
1799  mUsePagedRead = 0;
1800 }
1801 
1802 
1803 template<typename ValueType_, typename Codec_>
1804 void
1806 {
1807  this->write(os, /*outputTransient=*/false);
1808 }
1809 
1810 
1811 template<typename ValueType_, typename Codec_>
1812 void
1813 TypedAttributeArray<ValueType_, Codec_>::write(std::ostream& os, bool outputTransient) const
1814 {
1815  this->writeMetadata(os, outputTransient, /*paged=*/false);
1816  this->writeBuffers(os, outputTransient);
1817 }
1818 
1819 
1820 template<typename ValueType_, typename Codec_>
1821 void
1822 TypedAttributeArray<ValueType_, Codec_>::writeMetadata(std::ostream& os, bool outputTransient, bool paged) const
1823 {
1824  if (!outputTransient && this->isTransient()) return;
1825 
1826  if (mFlags & PARTIALREAD) {
1827  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1828  }
1829 
1830  uint8_t flags(mFlags);
1831  uint8_t serializationFlags(0);
1832  Index size(mSize);
1833  Index stride(mStrideOrTotalSize);
1834  bool strideOfOne(this->stride() == 1);
1835 
1836  bool bloscCompression = io::getDataCompression(os) & io::COMPRESS_BLOSC;
1837 
1838  // any compressed data needs to be loaded if out-of-core
1839  if (bloscCompression) this->doLoad();
1840 
1841  size_t compressedBytes = 0;
1842 
1843  if (!strideOfOne)
1844  {
1845  serializationFlags |= WRITESTRIDED;
1846  }
1847 
1848  if (mIsUniform)
1849  {
1850  serializationFlags |= WRITEUNIFORM;
1851  if (bloscCompression && paged) serializationFlags |= WRITEPAGED;
1852  }
1853  else if (bloscCompression)
1854  {
1855  if (paged) serializationFlags |= WRITEPAGED;
1856  else {
1857  const char* charBuffer = reinterpret_cast<const char*>(this->data());
1858  const size_t inBytes = this->arrayMemUsage();
1859  compressedBytes = compression::bloscCompressedSize(charBuffer, inBytes);
1860  }
1861  }
1862 
1863  Index64 bytes = /*flags*/ sizeof(Int16) + /*size*/ sizeof(Index);
1864 
1865  bytes += (compressedBytes > 0) ? compressedBytes : this->arrayMemUsage();
1866 
1867  // write data
1868 
1869  os.write(reinterpret_cast<const char*>(&bytes), sizeof(Index64));
1870  os.write(reinterpret_cast<const char*>(&flags), sizeof(uint8_t));
1871  os.write(reinterpret_cast<const char*>(&serializationFlags), sizeof(uint8_t));
1872  os.write(reinterpret_cast<const char*>(&size), sizeof(Index));
1873 
1874  // write strided
1875  if (!strideOfOne) os.write(reinterpret_cast<const char*>(&stride), sizeof(Index));
1876 }
1877 
1878 
1879 template<typename ValueType_, typename Codec_>
1880 void
1881 TypedAttributeArray<ValueType_, Codec_>::writeBuffers(std::ostream& os, bool outputTransient) const
1882 {
1883  if (!outputTransient && this->isTransient()) return;
1884 
1885  if (mFlags & PARTIALREAD) {
1886  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1887  }
1888 
1889  this->doLoad();
1890 
1891  if (this->isUniform()) {
1892  os.write(reinterpret_cast<const char*>(this->data()), sizeof(StorageType));
1893  }
1895  {
1896  std::unique_ptr<char[]> compressedBuffer;
1897  size_t compressedBytes = 0;
1898  const char* charBuffer = reinterpret_cast<const char*>(this->data());
1899  const size_t inBytes = this->arrayMemUsage();
1900  compressedBuffer = compression::bloscCompress(charBuffer, inBytes, compressedBytes);
1901  if (compressedBuffer) {
1902  uint8_t bloscCompressed(1);
1903  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1904  os.write(reinterpret_cast<const char*>(compressedBuffer.get()), compressedBytes);
1905  }
1906  else {
1907  uint8_t bloscCompressed(0);
1908  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1909  os.write(reinterpret_cast<const char*>(this->data()), inBytes);
1910  }
1911  }
1912  else
1913  {
1914  uint8_t bloscCompressed(0);
1915  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1916  os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1917  }
1918 }
1919 
1920 
1921 template<typename ValueType_, typename Codec_>
1922 void
1924 {
1925  if (!outputTransient && this->isTransient()) return;
1926 
1927  // paged compression only available when Blosc is enabled
1928  bool bloscCompression = io::getDataCompression(os.getOutputStream()) & io::COMPRESS_BLOSC;
1929  if (!bloscCompression) {
1930  if (!os.sizeOnly()) this->writeBuffers(os.getOutputStream(), outputTransient);
1931  return;
1932  }
1933 
1934  if (mFlags & PARTIALREAD) {
1935  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1936  }
1937 
1938  this->doLoad();
1939 
1940  os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1941 }
1942 
1943 
1944 template<typename ValueType_, typename Codec_>
1945 void
1946 TypedAttributeArray<ValueType_, Codec_>::doLoadUnsafe(const bool /*compression*/) const
1947 {
1948  if (!(this->isOutOfCore())) return;
1949 
1950  // this function expects the mutex to already be locked
1951 
1952  auto* self = const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
1953 
1954  assert(self->mPageHandle);
1955  assert(!(self->mFlags & PARTIALREAD));
1956 
1957  std::unique_ptr<char[]> buffer = self->mPageHandle->read();
1958 
1959  self->mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1960 
1961  self->mPageHandle.reset();
1962 
1963  // clear all write and out-of-core flags
1964 
1965  self->mOutOfCore = false;
1966 }
1967 
1968 
1969 template<typename ValueType_, typename Codec_>
1972 {
1973  // use the faster 'unsafe' get and set methods as attribute handles
1974  // ensure data is in-core when constructed
1975 
1981 }
1982 
1983 
1984 template<typename ValueType_, typename Codec_>
1985 bool
1987 {
1988  const TypedAttributeArray<ValueType_, Codec_>* const otherT = dynamic_cast<const TypedAttributeArray<ValueType_, Codec_>* >(&other);
1989  if(!otherT) return false;
1990  if(this->mSize != otherT->mSize ||
1991  this->mStrideOrTotalSize != otherT->mStrideOrTotalSize ||
1992  this->mIsUniform != otherT->mIsUniform ||
1993  this->attributeType() != this->attributeType()) return false;
1994 
1995  this->doLoad();
1996  otherT->doLoad();
1997 
1998  const StorageType *target = this->data(), *source = otherT->data();
1999  if (!target && !source) return true;
2000  if (!target || !source) return false;
2001  Index n = this->mIsUniform ? 1 : mSize;
2002  while (n && math::isExactlyEqual(*target++, *source++)) --n;
2003  return n == 0;
2004 }
2005 
2006 
2007 template<typename ValueType_, typename Codec_>
2008 char*
2009 TypedAttributeArray<ValueType_, Codec_>::dataAsByteArray()
2010 {
2011  return reinterpret_cast<char*>(this->data());
2012 }
2013 
2014 
2015 template<typename ValueType_, typename Codec_>
2016 const char*
2017 TypedAttributeArray<ValueType_, Codec_>::dataAsByteArray() const
2018 {
2019  return reinterpret_cast<const char*>(this->data());
2020 }
2021 
2022 
2023 ////////////////////////////////////////
2024 
2025 
2026 /// Accessor to call unsafe get and set methods based on templated Codec and Value
2027 template <typename CodecType, typename ValueType>
2029 {
2030  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
2031  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
2032 
2033  /// Getter that calls to TypedAttributeArray::getUnsafe()
2034  /// @note Functor argument is provided but not required for the generic case
2035  static ValueType get(GetterPtr /*functor*/, const AttributeArray* array, const Index n) {
2037  }
2038 
2039  /// Getter that calls to TypedAttributeArray::setUnsafe()
2040  /// @note Functor argument is provided but not required for the generic case
2041  static void set(SetterPtr /*functor*/, AttributeArray* array, const Index n, const ValueType& value) {
2043  }
2044 };
2045 
2046 
2047 /// Partial specialization when Codec is not known at compile-time to use the supplied functor instead
2048 template <typename ValueType>
2049 struct AccessorEval<UnknownCodec, ValueType>
2050 {
2051  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
2052  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
2053 
2054  /// Getter that calls the supplied functor
2055  static ValueType get(GetterPtr functor, const AttributeArray* array, const Index n) {
2056  return (*functor)(array, n);
2057  }
2058 
2059  /// Setter that calls the supplied functor
2060  static void set(SetterPtr functor, AttributeArray* array, const Index n, const ValueType& value) {
2061  (*functor)(array, n, value);
2062  }
2063 };
2064 
2065 
2066 ////////////////////////////////////////
2067 
2068 // AttributeHandle implementation
2069 
2070 template <typename ValueType, typename CodecType>
2072 AttributeHandle<ValueType, CodecType>::create(const AttributeArray& array, const bool collapseOnDestruction)
2073 {
2075  new AttributeHandle<ValueType, CodecType>(array, collapseOnDestruction));
2076 }
2077 
2078 template <typename ValueType, typename CodecType>
2079 AttributeHandle<ValueType, CodecType>::AttributeHandle(const AttributeArray& array, const bool collapseOnDestruction)
2080  : mArray(&array)
2081  , mStrideOrTotalSize(array.hasConstantStride() ? array.stride() : 1)
2082  , mSize(array.hasConstantStride() ? array.size() : array.dataSize())
2083  , mCollapseOnDestruction(collapseOnDestruction && array.isStreaming())
2084 {
2085  if (!this->compatibleType<std::is_same<CodecType, UnknownCodec>::value>()) {
2086  OPENVDB_THROW(TypeError, "Cannot bind handle due to incompatible type of AttributeArray.");
2087  }
2088 
2089  // load data if delay-loaded
2090 
2091  mArray->loadData();
2092 
2093  // bind getter and setter methods
2094 
2096  assert(accessor);
2097 
2098  AttributeArray::Accessor<ValueType>* typedAccessor = static_cast<AttributeArray::Accessor<ValueType>*>(accessor.get());
2099 
2100  mGetter = typedAccessor->mGetter;
2101  mSetter = typedAccessor->mSetter;
2102  mCollapser = typedAccessor->mCollapser;
2103  mFiller = typedAccessor->mFiller;
2104 }
2105 
2106 template <typename ValueType, typename CodecType>
2108 {
2109  // if enabled, attribute is collapsed on destruction of the handle to save memory
2110  if (mCollapseOnDestruction) const_cast<AttributeArray*>(this->mArray)->collapse();
2111 }
2112 
2113 template <typename ValueType, typename CodecType>
2114 template <bool IsUnknownCodec>
2115 typename std::enable_if<IsUnknownCodec, bool>::type
2117 {
2118  // if codec is unknown, just check the value type
2119 
2120  return mArray->hasValueType<ValueType>();
2121 }
2122 
2123 template <typename ValueType, typename CodecType>
2124 template <bool IsUnknownCodec>
2125 typename std::enable_if<!IsUnknownCodec, bool>::type
2126 AttributeHandle<ValueType, CodecType>::compatibleType() const
2127 {
2128  // if the codec is known, check the value type and codec
2129 
2130  return mArray->isType<TypedAttributeArray<ValueType, CodecType>>();
2131 }
2132 
2133 template <typename ValueType, typename CodecType>
2135 {
2136  assert(mArray);
2137  return *mArray;
2138 }
2139 
2140 template <typename ValueType, typename CodecType>
2142 {
2143  Index index = n * mStrideOrTotalSize + m;
2144  assert(index < (mSize * mStrideOrTotalSize));
2145  return index;
2146 }
2147 
2148 template <typename ValueType, typename CodecType>
2150 {
2151  return this->get<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m));
2152 }
2153 
2154 template <typename ValueType, typename CodecType>
2155 template <bool IsUnknownCodec>
2156 typename std::enable_if<IsUnknownCodec, ValueType>::type
2158 {
2159  // if the codec is unknown, use the getter functor
2160 
2161  return (*mGetter)(mArray, index);
2162 }
2163 
2164 template <typename ValueType, typename CodecType>
2165 template <bool IsUnknownCodec>
2166 typename std::enable_if<!IsUnknownCodec, ValueType>::type
2168 {
2169  // if the codec is known, call the method on the attribute array directly
2170 
2172 }
2173 
2174 template <typename ValueType, typename CodecType>
2176 {
2177  return mArray->isUniform();
2178 }
2179 
2180 template <typename ValueType, typename CodecType>
2182 {
2183  return mArray->hasConstantStride();
2184 }
2185 
2186 ////////////////////////////////////////
2187 
2188 // AttributeWriteHandle implementation
2189 
2190 template <typename ValueType, typename CodecType>
2193 {
2195  new AttributeWriteHandle<ValueType, CodecType>(array, expand));
2196 }
2197 
2198 template <typename ValueType, typename CodecType>
2200  : AttributeHandle<ValueType, CodecType>(array, /*collapseOnDestruction=*/false)
2201 {
2202  if (expand) array.expand();
2203 }
2204 
2205 template <typename ValueType, typename CodecType>
2207 {
2208  this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, 0), value);
2209 }
2210 
2211 template <typename ValueType, typename CodecType>
2213 {
2214  this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m), value);
2215 }
2216 
2217 template <typename ValueType, typename CodecType>
2219 {
2220  const_cast<AttributeArray*>(this->mArray)->expand(fill);
2221 }
2222 
2223 template <typename ValueType, typename CodecType>
2225 {
2226  const_cast<AttributeArray*>(this->mArray)->collapse();
2227 }
2228 
2229 template <typename ValueType, typename CodecType>
2231 {
2232  return const_cast<AttributeArray*>(this->mArray)->compact();
2233 }
2234 
2235 template <typename ValueType, typename CodecType>
2236 void AttributeWriteHandle<ValueType, CodecType>::collapse(const ValueType& uniformValue)
2237 {
2238  this->mCollapser(const_cast<AttributeArray*>(this->mArray), uniformValue);
2239 }
2240 
2241 template <typename ValueType, typename CodecType>
2243 {
2244  this->mFiller(const_cast<AttributeArray*>(this->mArray), value);
2245 }
2246 
2247 template <typename ValueType, typename CodecType>
2248 template <bool IsUnknownCodec>
2249 typename std::enable_if<IsUnknownCodec, void>::type
2250 AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2251 {
2252  // if the codec is unknown, use the setter functor
2253 
2254  (*this->mSetter)(const_cast<AttributeArray*>(this->mArray), index, value);
2255 }
2256 
2257 template <typename ValueType, typename CodecType>
2258 template <bool IsUnknownCodec>
2259 typename std::enable_if<!IsUnknownCodec, void>::type
2260 AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2261 {
2262  // if the codec is known, call the method on the attribute array directly
2263 
2264  TypedAttributeArray<ValueType, CodecType>::setUnsafe(const_cast<AttributeArray*>(this->mArray), index, value);
2265 }
2266 
2267 template <typename ValueType, typename CodecType>
2269 {
2270  assert(this->mArray);
2271  return *const_cast<AttributeArray*>(this->mArray);
2272 }
2273 
2274 
2275 } // namespace points
2276 } // namespace OPENVDB_VERSION_NAME
2277 } // namespace openvdb
2278 
2279 #endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
ValueT value
Definition: GridBuilder.h:1287
Index Iterators.
#define OPENVDB_API
Definition: Platform.h:254
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition: Platform.h:123
Convenience wrappers to using Blosc and reading and writing of Paged data.
Definition: Exceptions.h:57
Definition: Exceptions.h:58
Base class for storing metadata information in a grid.
Definition: Metadata.h:24
Definition: Exceptions.h:64
Templated metadata class to hold specific types.
Definition: Metadata.h:122
T & value()
Return this metadata's value.
Definition: Metadata.h:249
Definition: Exceptions.h:65
std::unique_ptr< PageHandle > Ptr
Definition: StreamCompression.h:170
A Paging wrapper to std::istream that is responsible for reading from a given input stream and creati...
Definition: StreamCompression.h:205
PageHandle::Ptr createHandle(std::streamsize n)
Creates a PageHandle to access the next.
bool sizeOnly() const
Definition: StreamCompression.h:215
void read(PageHandle::Ptr &pageHandle, std::streamsize n, bool delayed=true)
Takes a pageHandle and updates the referenced page with the current stream pointer position and if de...
std::istream & getInputStream()
Definition: StreamCompression.h:218
A Paging wrapper to std::ostream that is responsible for writing from a given output stream at interv...
Definition: StreamCompression.h:242
PagedOutputStream & write(const char *str, std::streamsize n)
Writes the given.
std::ostream & getOutputStream()
Set and get the output stream.
Definition: StreamCompression.h:255
bool sizeOnly() const
Definition: StreamCompression.h:252
SharedPtr< MappedFile > Ptr
Definition: io.h:136
Definition: Vec3.h:24
T & y()
Definition: Vec3.h:90
T & z()
Definition: Vec3.h:91
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:89
Base class for storing attribute data.
Definition: AttributeArray.h:93
virtual Name valueType() const =0
Return the name of the value type of a single element in this array (e.g., "float" or "vec3d").
AttributeArray(const AttributeArray &rhs, const tbb::spin_mutex::scoped_lock &)
void setConstantStride(bool state)
Specify whether this attribute has a constant stride or not.
static Ptr create(const NamePair &type, Index length, Index stride=1, bool constantStride=true, const Metadata *metadata=nullptr, const ScopedRegistryLock *lock=nullptr)
bool isTransient() const
Return true if this attribute is not serialized during stream output.
Definition: AttributeArray.h:292
SerializationFlag
Definition: AttributeArray.h:109
virtual Index dataSize() const =0
virtual bool isUniform() const =0
Return true if this array is stored as a single uniform value.
virtual void readBuffers(std::istream &)=0
Read attribute buffers from a stream.
std::shared_ptr< AttributeArray > Ptr
Definition: AttributeArray.h:125
virtual void set(const Index n, const AttributeArray &sourceArray, const Index sourceIndex)=0
Set value at given index n from sourceIndex of another sourceArray.
const char * constDataAsByteArray() const
Indirect virtual function to retrieve the data buffer cast to a char byte array.
Definition: AttributeArray.h:349
virtual ~AttributeArray()
Definition: AttributeArray.h:133
compression::PageHandle::Ptr mPageHandle
Definition: AttributeArray.h:393
AttributeArray & operator=(const AttributeArray &rhs)
Flag
Definition: AttributeArray.h:101
AttributeArray()
Definition: AttributeArray.h:132
virtual Index stride() const =0
bool isHidden() const
Return true if this attribute is hidden (e.g., from UI or iterators).
Definition: AttributeArray.h:285
bool isType() const
Return true if this attribute is of the same type as the template parameter.
Definition: AttributeArray.h:214
virtual const NamePair & type() const =0
Return the name of this attribute's type.
virtual bool valueTypeIsQuaternion() const =0
Return true if the value type is a quaternion.
virtual bool valueTypeIsVector() const =0
Return true if the value type is a vector.
uint8_t mFlags
Definition: AttributeArray.h:388
virtual AccessorBasePtr getAccessor() const =0
Obtain an Accessor that stores getter and setter functors.
void setStreaming(bool state)
Specify whether this attribute is to be streamed off disk, in which case, the attributes are collapse...
AttributeArray(const AttributeArray &rhs)
virtual bool isDataLoaded() const =0
Return true if all data has been loaded.
uint8_t flags() const
Retrieve the attribute array flags.
Definition: AttributeArray.h:306
AttributeArray & operator=(AttributeArray &&)=delete
bool hasValueType() const
Return true if this attribute has a value type the same as the template parameter.
Definition: AttributeArray.h:218
std::atomic< Index32 > mOutOfCore
Definition: AttributeArray.h:390
virtual void writeBuffers(std::ostream &, bool outputTransient) const =0
static void clearRegistry(const ScopedRegistryLock *lock=nullptr)
Clear the attribute type registry.
std::shared_ptr< AccessorBase > AccessorBasePtr
Definition: AttributeArray.h:98
virtual Index size() const =0
void setTransient(bool state)
Specify whether this attribute should only exist in memory and not be serialized during stream output...
virtual void read(std::istream &)=0
Read attribute metadata and buffers from a stream.
void setHidden(bool state)
Specify whether this attribute should be hidden (e.g., from UI or iterators).
virtual void write(std::ostream &, bool outputTransient) const =0
virtual bool compact()=0
Compact the existing array to become uniform if all values are identical.
virtual AttributeArray::Ptr copyUncompressed() const =0
Return a copy of this attribute.
virtual void readPagedBuffers(compression::PagedInputStream &)=0
Read attribute buffers from a paged stream.
virtual bool valueTypeIsClass() const =0
Return true if the value type is a class (ie vector, matrix or quaternion return true)
virtual void loadData() const =0
Ensures all data is in-core.
uint8_t mUsePagedRead
Definition: AttributeArray.h:389
virtual bool valueTypeIsMatrix() const =0
Return true if the value type is a matrix.
bool operator==(const AttributeArray &other) const
tbb::spin_mutex mMutex
Definition: AttributeArray.h:387
bool operator!=(const AttributeArray &other) const
Definition: AttributeArray.h:345
bool isStreaming() const
Return true if this attribute is in streaming mode.
Definition: AttributeArray.h:300
virtual void writeMetadata(std::ostream &, bool outputTransient, bool paged) const =0
static bool isRegistered(const NamePair &type, const ScopedRegistryLock *lock=nullptr)
Return true if the given attribute type name is registered.
Ptr(*)(Index, Index, bool, const Metadata *) FactoryMethod
Definition: AttributeArray.h:128
virtual Name codecType() const =0
Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
virtual void readMetadata(std::istream &)=0
Read attribute metadata from a stream.
std::shared_ptr< const AttributeArray > ConstPtr
Definition: AttributeArray.h:126
virtual void collapse()=0
Replace the existing array with a uniform zero value.
virtual void writePagedBuffers(compression::PagedOutputStream &, bool outputTransient) const =0
virtual Index storageTypeSize() const =0
virtual void write(std::ostream &) const =0
Write attribute metadata and buffers to a stream, don't write transient attributes.
static void registerType(const NamePair &type, FactoryMethod, const ScopedRegistryLock *lock=nullptr)
Register a attribute type along with a factory function.
virtual AttributeArray::Ptr copy() const =0
Return a copy of this attribute.
virtual Index valueTypeSize() const =0
virtual bool valueTypeIsFloatingPoint() const =0
Return true if the value type is floating point.
static void unregisterType(const NamePair &type, const ScopedRegistryLock *lock=nullptr)
Remove a attribute type from the registry.
bool hasConstantStride() const
Return true if this attribute has a constant stride.
Definition: AttributeArray.h:303
size_t mCompressedBytes
Definition: AttributeArray.h:394
bool mIsUniform
Definition: AttributeArray.h:386
virtual void expand(bool fill=true)=0
If this array is uniform, replace it with an array of length size().
virtual size_t memUsage() const =0
Return the number of bytes of memory used by this attribute.
AttributeArray(AttributeArray &&)=delete
Definition: AttributeArray.h:811
virtual ~AttributeHandle()
Definition: AttributeArray.h:2107
Index size() const
Definition: AttributeArray.h:833
void(*)(AttributeArray *array, const ValueType &value) ValuePtr
Definition: AttributeArray.h:820
SetterPtr mSetter
Definition: AttributeArray.h:848
Index stride() const
Definition: AttributeArray.h:832
std::shared_ptr< Handle > Ptr
Definition: AttributeArray.h:814
GetterPtr mGetter
Definition: AttributeArray.h:847
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:819
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2072
AttributeHandle(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2079
AttributeHandle & operator=(const AttributeHandle &)=default
ValuePtr mFiller
Definition: AttributeArray.h:850
ValueType get(Index n, Index m=0) const
Definition: AttributeArray.h:2149
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:818
AttributeHandle(const AttributeHandle &)=default
ValuePtr mCollapser
Definition: AttributeArray.h:849
const AttributeArray & array() const
Definition: AttributeArray.h:2134
const AttributeArray * mArray
Definition: AttributeArray.h:845
bool isUniform() const
Definition: AttributeArray.h:2175
std::unique_ptr< Handle > UniquePtr
Definition: AttributeArray.h:815
bool hasConstantStride() const
Definition: AttributeArray.h:2181
Index index(Index n, Index m) const
Definition: AttributeArray.h:2141
Write-able version of AttributeHandle.
Definition: AttributeArray.h:882
AttributeWriteHandle(AttributeArray &array, const bool expand=true)
Definition: AttributeArray.h:2199
std::shared_ptr< Handle > Ptr
Definition: AttributeArray.h:885
bool compact()
Compact the existing array to become uniform if all values are identical.
Definition: AttributeArray.h:2230
void collapse()
Replace the existing array with a uniform value (zero if none provided).
Definition: AttributeArray.h:2224
void set(Index n, const ValueType &value)
Definition: AttributeArray.h:2206
void expand(bool fill=true)
If this array is uniform, replace it with an array of length size().
Definition: AttributeArray.h:2218
AttributeArray & array()
Definition: AttributeArray.h:2268
std::unique_ptr< Handle > ScopedPtr
Definition: AttributeArray.h:886
static Ptr create(AttributeArray &array, const bool expand=true)
Definition: AttributeArray.h:2192
void set(Index n, Index m, const ValueType &value)
Definition: AttributeArray.h:2212
void fill(const ValueType &value)
Fill the existing array with the given value.
Definition: AttributeArray.h:2242
void collapse(const ValueType &uniformValue)
Definition: AttributeArray.h:2236
Typed class for storing attribute data.
Definition: AttributeArray.h:533
Index valueTypeSize() const override
Return the size in bytes of the value type of a single element in this array.
Definition: AttributeArray.h:624
ValueType getUnsafe(Index n) const
Return the value at index n (assumes in-core)
Definition: AttributeArray.h:1381
void readBuffers(std::istream &) override
Read attribute buffers from a stream.
Definition: AttributeArray.h:1721
std::shared_ptr< TypedAttributeArray > Ptr
Definition: AttributeArray.h:535
AccessorBasePtr getAccessor() const override
Obtain an Accessor that stores getter and setter functors.
Definition: AttributeArray.h:1971
void write(std::ostream &os, bool outputTransient) const override
Definition: AttributeArray.h:1813
typename Codec::template Storage< ValueType >::Type StorageType
Definition: AttributeArray.h:540
const StorageType * constData() const
Return the raw data buffer.
Definition: AttributeArray.h:749
size_t memUsage() const override
Return the number of bytes of memory used by this attribute.
Definition: AttributeArray.h:1373
const StorageType * data() const
Definition: AttributeArray.h:757
ValueType_ ValueType
Definition: AttributeArray.h:538
TypedAttributeArray(Index n=1, Index strideOrTotalSize=1, bool constantStride=true, const ValueType &uniformValue=zeroVal< ValueType >())
Default constructor, always constructs a uniform attribute.
Definition: AttributeArray.h:1108
bool isDataLoaded() const override
Return true if all data has been loaded.
Definition: AttributeArray.h:1653
bool isOutOfCore() const
Return true if this buffer's values have not yet been read from disk.
Definition: AttributeArray.h:1613
bool valueTypeIsVector() const override
Return true if the value type is a vector.
Definition: AttributeArray.h:1347
bool validData() const
Verify that data is not out-of-core or in a partially-read state.
Definition: AttributeArray.h:760
bool compact() override
Compact the existing array to become uniform if all values are identical.
Definition: AttributeArray.h:1517
static TypedAttributeArray & cast(AttributeArray &attributeArray)
Cast an AttributeArray to TypedAttributeArray<T>
Definition: AttributeArray.h:1240
void writeBuffers(std::ostream &os, bool outputTransient) const override
Definition: AttributeArray.h:1881
AttributeArray::Ptr copy() const override
Definition: AttributeArray.h:1260
Index storageTypeSize() const override
Definition: AttributeArray.h:628
bool valueTypeIsQuaternion() const override
Return true if the value type is a quaternion.
Definition: AttributeArray.h:1355
void readPagedBuffers(compression::PagedInputStream &) override
Read attribute buffers from a paged stream.
Definition: AttributeArray.h:1760
void set(Index n, const ValueType &value)
Set value at the given index n.
Definition: AttributeArray.h:1445
TypedAttributeArray & operator=(const TypedAttributeArray &)
Definition: AttributeArray.h:1164
static void registerType()
Register this attribute type along with a factory function.
Definition: AttributeArray.h:1212
bool valueTypeIsFloatingPoint() const override
Return true if the value type is floating point.
Definition: AttributeArray.h:1318
void writeMetadata(std::ostream &os, bool outputTransient, bool paged) const override
Definition: AttributeArray.h:1822
static void unregisterType()
Remove this attribute type from the registry.
Definition: AttributeArray.h:1220
void loadData() const override
Ensures all data is in-core.
Definition: AttributeArray.h:1645
void read(std::istream &) override
Read attribute data from a stream.
Definition: AttributeArray.h:1661
ValueType get(Index n) const
Return the value at index n.
Definition: AttributeArray.h:1393
TypedAttributeArray(TypedAttributeArray &&)=delete
Move constructor disabled.
static const NamePair & attributeType()
Return the name of this attribute's type (includes codec)
Definition: AttributeArray.h:1191
bool valueTypeIsClass() const override
Return true if the value type is a class (ie vector, matrix or quaternion return true)
Definition: AttributeArray.h:1338
Index size() const override
Return the number of elements in this array.
Definition: AttributeArray.h:606
void collapse() override
Replace the existing array with a uniform zero value.
Definition: AttributeArray.h:1534
Index dataSize() const override
Return the size of the data in this array.
Definition: AttributeArray.h:613
Codec_ Codec
Definition: AttributeArray.h:539
~TypedAttributeArray() override
Definition: AttributeArray.h:572
void expand(bool fill=true) override
Replace the single value storage with an array of length size().
Definition: AttributeArray.h:1496
AttributeArray::Ptr copyUncompressed() const override
Definition: AttributeArray.h:1271
static bool isRegistered()
Return true if this attribute type is registered.
Definition: AttributeArray.h:1204
TypedAttributeArray & operator=(TypedAttributeArray &&)=delete
Move assignment operator disabled.
bool valueTypeIsMatrix() const override
Return true if the value type is a matrix.
Definition: AttributeArray.h:1364
void fill(const ValueType &value)
Fill the existing array with the given value.
Definition: AttributeArray.h:1564
Index stride() const override
Definition: AttributeArray.h:610
StorageType * data()
Return the raw data buffer.
Definition: AttributeArray.h:756
static Ptr create(Index n, Index strideOrTotalSize=1, bool constantStride=true, const Metadata *metadata=nullptr)
Return a new attribute array of the given length n and stride with uniform value zero.
Definition: AttributeArray.h:1228
Name codecType() const override
Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
Definition: AttributeArray.h:621
bool decompress() override
Uncompress the attribute array.
Definition: AttributeArray.h:1605
bool compress() override
Compress the attribute array.
Definition: AttributeArray.h:1589
void writePagedBuffers(compression::PagedOutputStream &os, bool outputTransient) const override
Definition: AttributeArray.h:1923
Name valueType() const override
Return the name of the value type of a single element in this array (e.g., "float" or "vec3d").
Definition: AttributeArray.h:618
void setUnsafe(Index n, const ValueType &value)
Set value at the given index n (assumes in-core)
Definition: AttributeArray.h:1430
void readMetadata(std::istream &) override
Read attribute metadata from a stream.
Definition: AttributeArray.h:1670
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition: logging.h:256
static void read(std::istream &is, GridHandle< BufferT > &handle, Codec codec)
static fileSize_t write(std::ostream &os, const GridHandle< BufferT > &handle, Codec codec)
OPENVDB_API size_t bloscCompressedSize(const char *buffer, const size_t uncompressedBytes)
Convenience wrapper to retrieve the compressed size of buffer when compressed.
OPENVDB_API void bloscDecompress(char *uncompressedBuffer, const size_t expectedBytes, const size_t bufferBytes, const char *compressedBuffer)
Decompress into the supplied buffer. Will throw if decompression fails or uncompressed buffer has ins...
OPENVDB_API void bloscCompress(char *compressedBuffer, size_t &compressedBytes, const size_t bufferBytes, const char *uncompressedBuffer, const size_t uncompressedBytes)
Compress into the supplied buffer.
OPENVDB_API SharedPtr< MappedFile > getMappedFilePtr(std::ios_base &)
Return a shared pointer to the memory-mapped file with which the given stream is associated,...
@ COMPRESS_BLOSC
Definition: Compression.h:56
OPENVDB_API uint32_t getDataCompression(std::ios_base &)
Return a bitwise OR of compression option flags (COMPRESS_ZIP, COMPRESS_ACTIVE_MASK,...
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:444
internal::half half
Definition: Types.h:29
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:477
FloatVectorT fixedPointToFloatingPoint(const math::Vec3< IntegerT > &v)
Definition: AttributeArray.h:79
IntegerVectorT floatingPointToFixedPoint(const math::Vec3< FloatT > &v)
Definition: AttributeArray.h:69
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:103
Index64 memUsage(const TreeT &tree, bool threaded=true)
Return the total amount of memory in bytes occupied by this tree.
Definition: Count.h:408
std::string Name
Definition: Name.h:17
Index32 Index
Definition: Types.h:54
int16_t Int16
Definition: Types.h:55
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:39
uint64_t Index64
Definition: Types.h:53
Definition: Exceptions.h:13
Definition: Coord.h:586
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
static pnanovdb_uint32_t allocate(pnanovdb_uint32_t *poffset, pnanovdb_uint32_t size, pnanovdb_uint32_t alignment)
Definition: pnanovdb_validate_strides.h:20
Definition: Types.h:205
typename T::ValueType ElementType
Definition: Types.h:208
static ValueType get(GetterPtr functor, const AttributeArray *array, const Index n)
Getter that calls the supplied functor.
Definition: AttributeArray.h:2055
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:2052
static void set(SetterPtr functor, AttributeArray *array, const Index n, const ValueType &value)
Setter that calls the supplied functor.
Definition: AttributeArray.h:2060
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:2051
Accessor to call unsafe get and set methods based on templated Codec and Value.
Definition: AttributeArray.h:2029
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:2031
static ValueType get(GetterPtr, const AttributeArray *array, const Index n)
Definition: AttributeArray.h:2035
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:2030
static void set(SetterPtr, AttributeArray *array, const Index n, const ValueType &value)
Definition: AttributeArray.h:2041
Accessor base class for AttributeArray storage where type is not available.
Definition: AttributeArray.h:403
Definition: AttributeArray.h:409
SetterPtr mSetter
Definition: AttributeArray.h:418
GetterPtr mGetter
Definition: AttributeArray.h:417
void(*)(AttributeArray *array, const T &value) ValuePtr
Definition: AttributeArray.h:412
T(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:410
void(*)(AttributeArray *array, const Index n, const T &value) SetterPtr
Definition: AttributeArray.h:411
ValuePtr mFiller
Definition: AttributeArray.h:420
Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler)
Definition: AttributeArray.h:414
ValuePtr mCollapser
Definition: AttributeArray.h:419
Definition: AttributeArray.h:501
typename attribute_traits::UIntTypeTrait< OneByte, T >::Type Type
Definition: AttributeArray.h:501
Definition: AttributeArray.h:499
static const char * name()
Definition: AttributeArray.h:506
Definition: AttributeArray.h:460
T Type
Definition: AttributeArray.h:460
Definition: AttributeArray.h:458
static const char * name()
Definition: AttributeArray.h:464
Definition: AttributeArray.h:481
static ValueType decode(const ValueType &value)
Definition: AttributeArray.h:484
static ValueType encode(const ValueType &value)
Definition: AttributeArray.h:483
static const char * name()
Definition: AttributeArray.h:482
Definition: AttributeArray.h:471
typename attribute_traits::TruncateTrait< T >::Type Type
Definition: AttributeArray.h:471
Definition: AttributeArray.h:469
static const char * name()
Definition: AttributeArray.h:475
Definition: AttributeArray.h:490
static ValueType decode(const ValueType &value)
Definition: AttributeArray.h:493
static ValueType encode(const ValueType &value)
Definition: AttributeArray.h:492
static const char * name()
Definition: AttributeArray.h:491
Definition: AttributeArray.h:518
StorageType Type
Definition: AttributeArray.h:518
Definition: AttributeArray.h:514
uint16_t StorageType
Definition: AttributeArray.h:515
static const char * name()
Definition: AttributeArray.h:522
Definition: AttributeArray.h:454
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202