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