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