OpenVDB  7.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 
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 <tbb/atomic.h>
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 
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(std::floor(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 
89 
90 
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,
103  HIDDEN = 0x2,
104  OUTOFCORE = 0x4,
105  CONSTANTSTRIDE = 0x8,
106  STREAMING = 0x10,
107  PARTIALREAD = 0x20
108  };
109 
111  WRITESTRIDED = 0x1,
112  WRITEUNIFORM = 0x2,
113  WRITEMEMCOMPRESS = 0x4,
114  WRITEPAGED = 0x8
116  };
117 
118  // Scoped Lock wrapper class that locks the AttributeArray registry mutex
120  {
121  tbb::spin_mutex::scoped_lock lock;
122  public:
124  }; // class ScopedRegistryLock
125 
126  using Ptr = std::shared_ptr<AttributeArray>;
127  using ConstPtr = std::shared_ptr<const AttributeArray>;
128 
129  using FactoryMethod = Ptr (*)(Index, Index, bool);
130 
131  template <typename ValueType, typename CodecType> friend class AttributeHandle;
132 
133 #if OPENVDB_ABI_VERSION_NUMBER >= 5
134  AttributeArray(): mPageHandle() { mOutOfCore = 0; }
135 #else
136  AttributeArray(): mPageHandle() {}
137 #endif
138  virtual ~AttributeArray()
139  {
140  // if this AttributeArray has been partially read, zero the compressed bytes,
141  // so the page handle won't attempt to clean up invalid memory
142  if (mFlags & PARTIALREAD) mCompressedBytes = 0;
143  }
144 #if OPENVDB_ABI_VERSION_NUMBER >= 6
145  AttributeArray(const AttributeArray& rhs);
146  AttributeArray& operator=(const AttributeArray& rhs);
147 #else
148  AttributeArray(const AttributeArray&) = default;
149  AttributeArray& operator=(const AttributeArray&) = default;
150 #endif
151  AttributeArray(AttributeArray&&) = default;
152  AttributeArray& operator=(AttributeArray&&) = default;
153 
155  virtual AttributeArray::Ptr copy() const = 0;
156 
159 #ifndef _MSC_VER
161 #endif
162  virtual AttributeArray::Ptr copyUncompressed() const = 0;
163 
166  virtual Index size() const = 0;
167 
170  virtual Index stride() const = 0;
171 
174  virtual Index dataSize() const = 0;
175 
176 #if OPENVDB_ABI_VERSION_NUMBER >= 6
177  virtual Name valueType() const = 0;
179 
181  virtual Name codecType() const = 0;
182 
185  virtual Index valueTypeSize() const = 0;
186 
189  virtual Index storageTypeSize() const = 0;
190 
192  virtual bool valueTypeIsFloatingPoint() const = 0;
193 
195  virtual bool valueTypeIsClass() const = 0;
196 
198  virtual bool valueTypeIsVector() const = 0;
199 
201  virtual bool valueTypeIsQuaternion() const = 0;
202 
204  virtual bool valueTypeIsMatrix() const = 0;
205 #endif
206 
208  virtual size_t memUsage() const = 0;
209 
213  static Ptr create(const NamePair& type, Index length, Index stride = 1,
214  bool constantStride = true, const ScopedRegistryLock* lock = nullptr);
216  static bool isRegistered(const NamePair& type, const ScopedRegistryLock* lock = nullptr);
218  static void clearRegistry(const ScopedRegistryLock* lock = nullptr);
219 
221  virtual const NamePair& type() const = 0;
223  template<typename AttributeArrayType>
224  bool isType() const { return this->type() == AttributeArrayType::attributeType(); }
225 
227  template<typename ValueType>
228  bool hasValueType() const { return this->type().first == typeNameAsString<ValueType>(); }
229 
232 #if OPENVDB_ABI_VERSION_NUMBER >= 6
233  // Windows does not allow base classes to be easily deprecated.
234 #ifndef _MSC_VER
236 #endif
237 #endif
238  virtual void set(const Index n, const AttributeArray& sourceArray, const Index sourceIndex) = 0;
239 
240 #if OPENVDB_ABI_VERSION_NUMBER >= 6
241  template<typename IterT>
265  void copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter);
269  template<typename IterT>
270  void copyValues(const AttributeArray& sourceArray, const IterT& iter, bool compact = true);
271 #endif
272 
274  virtual bool isUniform() const = 0;
277  virtual void expand(bool fill = true) = 0;
279  virtual void collapse() = 0;
281  virtual bool compact() = 0;
282 
285  OPENVDB_DEPRECATED bool isCompressed() const { return false; }
287  // Windows does not allow base classes to be deprecated
288 #ifndef _MSC_VER
290 #endif
291  virtual bool compress() = 0;
293  // Windows does not allow base classes to be deprecated
294 #ifndef _MSC_VER
296 #endif
297  virtual bool decompress() = 0;
298 
303  void setHidden(bool state);
305  bool isHidden() const { return bool(mFlags & HIDDEN); }
306 
310  void setTransient(bool state);
312  bool isTransient() const { return bool(mFlags & TRANSIENT); }
313 
318  void setStreaming(bool state);
320  bool isStreaming() const { return bool(mFlags & STREAMING); }
321 
323  bool hasConstantStride() const { return bool(mFlags & CONSTANTSTRIDE); }
324 
326  uint8_t flags() const { return mFlags; }
327 
329  virtual void read(std::istream&) = 0;
332  virtual void write(std::ostream&, bool outputTransient) const = 0;
334  virtual void write(std::ostream&) const = 0;
335 
337  virtual void readMetadata(std::istream&) = 0;
341  virtual void writeMetadata(std::ostream&, bool outputTransient, bool paged) const = 0;
342 
344  virtual void readBuffers(std::istream&) = 0;
347  virtual void writeBuffers(std::ostream&, bool outputTransient) const = 0;
348 
350  virtual void readPagedBuffers(compression::PagedInputStream&) = 0;
353  virtual void writePagedBuffers(compression::PagedOutputStream&, bool outputTransient) const = 0;
354 
356  virtual void loadData() const = 0;
357 
358 #if OPENVDB_ABI_VERSION_NUMBER >= 6
359  virtual bool isDataLoaded() const = 0;
361 #endif
362 
366  bool operator==(const AttributeArray& other) const;
367  bool operator!=(const AttributeArray& other) const { return !this->operator==(other); }
368 
369 private:
370  friend class ::TestAttributeArray;
371 
374  virtual bool isEqual(const AttributeArray& other) const = 0;
375 
376 #if OPENVDB_ABI_VERSION_NUMBER >= 6
377  virtual char* dataAsByteArray() = 0;
379  virtual const char* dataAsByteArray() const = 0;
380 
382  template <typename IterT>
383  void doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
384  bool rangeChecking = true);
385 #endif
386 
387 protected:
388 #if OPENVDB_ABI_VERSION_NUMBER >= 7
389  AttributeArray(const AttributeArray& rhs, const tbb::spin_mutex::scoped_lock&);
390 #endif
391 
393  void setConstantStride(bool state);
394 
396  virtual AccessorBasePtr getAccessor() const = 0;
397 
399  static void registerType(const NamePair& type, FactoryMethod,
400  const ScopedRegistryLock* lock = nullptr);
402  static void unregisterType(const NamePair& type,
403  const ScopedRegistryLock* lock = nullptr);
404 
405 #if OPENVDB_ABI_VERSION_NUMBER < 6
406 
407  size_t mCompressedBytes = 0;
408  uint8_t mFlags = 0;
409  uint8_t mUsePagedRead = 0;
410 #if OPENVDB_ABI_VERSION_NUMBER >= 5
411  tbb::atomic<Index32> mOutOfCore; // interpreted as bool
412 #endif
413  compression::PageHandle::Ptr mPageHandle;
414 
415 #else // #if OPENVDB_ABI_VERSION_NUMBER < 6
416 
417  bool mIsUniform = true;
418  mutable tbb::spin_mutex mMutex;
419  uint8_t mFlags = 0;
420  uint8_t mUsePagedRead = 0;
421  tbb::atomic<Index32> mOutOfCore; // interpreted as bool
423  union {
425  size_t mCompressedBytes; // as of ABI=6, this data is packed together to save memory
426  };
427 
428 #endif
429 }; // class AttributeArray
430 
431 
433 
434 
436 struct AttributeArray::AccessorBase { virtual ~AccessorBase() = default; };
437 
440 template <typename T>
442 {
443  using GetterPtr = T (*)(const AttributeArray* array, const Index n);
444  using SetterPtr = void (*)(AttributeArray* array, const Index n, const T& value);
445  using ValuePtr = void (*)(AttributeArray* array, const T& value);
446 
447  Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler) :
448  mGetter(getter), mSetter(setter), mCollapser(collapser), mFiller(filler) { }
449 
454 }; // struct AttributeArray::Accessor
455 
456 
458 
459 
460 namespace attribute_traits
461 {
462  template <typename T> struct TruncateTrait { };
463  template <> struct TruncateTrait<float> { using Type = half; };
464  template <> struct TruncateTrait<int> { using Type = short; };
465 
466  template <typename T> struct TruncateTrait<math::Vec3<T>> {
468  };
469 
470  template <bool OneByte, typename T> struct UIntTypeTrait { };
471  template<typename T> struct UIntTypeTrait</*OneByte=*/true, T> { using Type = uint8_t; };
472  template<typename T> struct UIntTypeTrait</*OneByte=*/false, T> { using Type = uint16_t; };
473  template<typename T> struct UIntTypeTrait</*OneByte=*/true, math::Vec3<T>> {
475  };
476  template<typename T> struct UIntTypeTrait</*OneByte=*/false, math::Vec3<T>> {
478  };
479 }
480 
481 
483 
484 
485 // Attribute codec schemes
486 
487 struct UnknownCodec { };
488 
489 
490 struct NullCodec
491 {
492  template <typename T>
493  struct Storage { using Type = T; };
494 
495  template<typename ValueType> static void decode(const ValueType&, ValueType&);
496  template<typename ValueType> static void encode(const ValueType&, ValueType&);
497  static const char* name() { return "null"; }
498 };
499 
500 
502 {
503  template <typename T>
505 
506  template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
507  template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
508  static const char* name() { return "trnc"; }
509 };
510 
511 
512 // Fixed-point codec range for voxel-space positions [-0.5,0.5]
514 {
515  static const char* name() { return "fxpt"; }
516  template <typename ValueType> static ValueType encode(const ValueType& value) { return value + ValueType(0.5); }
517  template <typename ValueType> static ValueType decode(const ValueType& value) { return value - ValueType(0.5); }
518 };
519 
520 
521 // Fixed-point codec range for unsigned values in the unit range [0.0,1.0]
522 struct UnitRange
523 {
524  static const char* name() { return "ufxpt"; }
525  template <typename ValueType> static ValueType encode(const ValueType& value) { return value; }
526  template <typename ValueType> static ValueType decode(const ValueType& value) { return value; }
527 };
528 
529 
530 template <bool OneByte, typename Range=PositionRange>
532 {
533  template <typename T>
535 
536  template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
537  template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
538 
539  static const char* name() {
540  static const std::string Name = std::string(Range::name()) + (OneByte ? "8" : "16");
541  return Name.c_str();
542  }
543 };
544 
545 
547 {
548  using StorageType = uint16_t;
549 
550  template <typename T>
551  struct Storage { using Type = StorageType; };
552 
553  template<typename T> static void decode(const StorageType&, math::Vec3<T>&);
554  template<typename T> static void encode(const math::Vec3<T>&, StorageType&);
555  static const char* name() { return "uvec"; }
556 };
557 
558 
560 
561 
563 
564 template<typename ValueType_, typename Codec_ = NullCodec>
565 #if OPENVDB_ABI_VERSION_NUMBER >= 6 // for ABI=6, class is final to allow for de-virtualization
567 #else
569 #endif
570 {
571 public:
572  using Ptr = std::shared_ptr<TypedAttributeArray>;
573  using ConstPtr = std::shared_ptr<const TypedAttributeArray>;
574 
575  using ValueType = ValueType_;
576  using Codec = Codec_;
577  using StorageType = typename Codec::template Storage<ValueType>::Type;
578 
580 
582  explicit TypedAttributeArray(Index n = 1, Index strideOrTotalSize = 1, bool constantStride = true,
583  const ValueType& uniformValue = zeroVal<ValueType>());
584 #if OPENVDB_ABI_VERSION_NUMBER >= 7
595 #else
596  TypedAttributeArray(const TypedAttributeArray&, bool uncompress = false);
600 #endif
601  TypedAttributeArray& operator=(const TypedAttributeArray&);
607  TypedAttributeArray& operator=(TypedAttributeArray&&) = delete;
608 
609  ~TypedAttributeArray() override { this->deallocate(); }
610 
613  AttributeArray::Ptr copy() const override;
614 
617  OPENVDB_DEPRECATED AttributeArray::Ptr copyUncompressed() const override;
618 
620  static Ptr create(Index n, Index strideOrTotalSize = 1, bool constantStride = true);
621 
623  static TypedAttributeArray& cast(AttributeArray& attributeArray);
624 
626  static const TypedAttributeArray& cast(const AttributeArray& attributeArray);
627 
629  static const NamePair& attributeType();
631  const NamePair& type() const override { return attributeType(); }
632 
634  static bool isRegistered();
636  static void registerType();
638  static void unregisterType();
639 
641  Index size() const override { return mSize; }
642 
645  Index stride() const override { return hasConstantStride() ? mStrideOrTotalSize : 0; }
646 
648  Index dataSize() const override {
649  return hasConstantStride() ? mSize * mStrideOrTotalSize : mStrideOrTotalSize;
650  }
651 
652 #if OPENVDB_ABI_VERSION_NUMBER >= 6
653  Name valueType() const override { return typeNameAsString<ValueType>(); }
655 
657  Name codecType() const override { return Codec::name(); }
658 
660  Index valueTypeSize() const override { return sizeof(ValueType); }
661 
664  Index storageTypeSize() const override { return sizeof(StorageType); }
665 
667  bool valueTypeIsFloatingPoint() const override;
668 
670  bool valueTypeIsClass() const override;
671 
673  bool valueTypeIsVector() const override;
674 
676  bool valueTypeIsQuaternion() const override;
677 
679  bool valueTypeIsMatrix() const override;
680 #endif
681 
683  size_t memUsage() const override;
684 
686  ValueType getUnsafe(Index n) const;
688  ValueType get(Index n) const;
690  template<typename T> void getUnsafe(Index n, T& value) const;
692  template<typename T> void get(Index n, T& value) const;
693 
696  static ValueType getUnsafe(const AttributeArray* array, const Index n);
697 
699  void setUnsafe(Index n, const ValueType& value);
701  void set(Index n, const ValueType& value);
703  template<typename T> void setUnsafe(Index n, const T& value);
705  template<typename T> void set(Index n, const T& value);
706 
709  static void setUnsafe(AttributeArray* array, const Index n, const ValueType& value);
710 
712 #if OPENVDB_ABI_VERSION_NUMBER >= 6
714 #endif
715  void set(const Index n, const AttributeArray& sourceArray, const Index sourceIndex) override;
716 
718  bool isUniform() const override { return mIsUniform; }
722  void expand(bool fill = true) override;
724  void collapse() override;
726  bool compact() override;
727 
729  void collapse(const ValueType& uniformValue);
732  void fill(const ValueType& value);
733 
735  static void collapse(AttributeArray* array, const ValueType& value);
737  static void fill(AttributeArray* array, const ValueType& value);
738 
740  OPENVDB_DEPRECATED bool compress() override;
742  OPENVDB_DEPRECATED bool decompress() override;
743 
745  void read(std::istream&) override;
749  void write(std::ostream& os, bool outputTransient) const override;
751  void write(std::ostream&) const override;
752 
754  void readMetadata(std::istream&) override;
759  void writeMetadata(std::ostream& os, bool outputTransient, bool paged) const override;
760 
762  void readBuffers(std::istream&) override;
766  void writeBuffers(std::ostream& os, bool outputTransient) const override;
767 
769  void readPagedBuffers(compression::PagedInputStream&) override;
773  void writePagedBuffers(compression::PagedOutputStream& os, bool outputTransient) const override;
774 
776  inline bool isOutOfCore() const;
777 
779  void loadData() const override;
780 
781 #if OPENVDB_ABI_VERSION_NUMBER >= 6
782  bool isDataLoaded() const override;
784 #endif
785 
786 protected:
787  AccessorBasePtr getAccessor() const override;
788 
790  inline StorageType* data() { assert(validData()); return mData.get(); }
791  inline const StorageType* data() const { assert(validData()); return mData.get(); }
792 
794  inline bool validData() const { return !(isOutOfCore() || (flags() & PARTIALREAD)); }
795 
796 private:
797  friend class ::TestAttributeArray;
798 
799 #if OPENVDB_ABI_VERSION_NUMBER >= 7
800  TypedAttributeArray(const TypedAttributeArray&, const tbb::spin_mutex::scoped_lock&);
801 #endif
802 
804  inline void doLoad() const;
807  inline void doLoadUnsafe(const bool compression = true) const;
809  inline bool compressUnsafe();
810 
812  inline void setOutOfCore(const bool);
813 
815  bool isEqual(const AttributeArray& other) const override;
816 
817 #if OPENVDB_ABI_VERSION_NUMBER >= 6
818  char* dataAsByteArray() override;
820  const char* dataAsByteArray() const override;
821 #endif
822 
823  size_t arrayMemUsage() const;
824  void allocate();
825  void deallocate();
826 
828  static AttributeArray::Ptr factory(Index n, Index strideOrTotalSize, bool constantStride) {
829  return TypedAttributeArray::create(n, strideOrTotalSize, constantStride);
830  }
831 
832  static std::unique_ptr<const NamePair> sTypeName;
833  std::unique_ptr<StorageType[]> mData;
834  Index mSize;
835  Index mStrideOrTotalSize;
836 #if OPENVDB_ABI_VERSION_NUMBER < 6 // as of ABI=6, this data lives in the base class to reduce memory
837  bool mIsUniform = true;
838  mutable tbb::spin_mutex mMutex;
839 #endif
840 }; // class TypedAttributeArray
841 
842 
844 
845 
848 template <typename ValueType, typename CodecType = UnknownCodec>
850 {
851 public:
853  using Ptr = std::shared_ptr<Handle>;
854  using UniquePtr = std::unique_ptr<Handle>;
855 
856 protected:
857  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
858  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
859  using ValuePtr = void (*)(AttributeArray* array, const ValueType& value);
860 
861 public:
862  static Ptr create(const AttributeArray& array, const bool collapseOnDestruction = true);
863 
864  AttributeHandle(const AttributeArray& array, const bool collapseOnDestruction = true);
865 
866  AttributeHandle(const AttributeHandle&) = default;
867  AttributeHandle& operator=(const AttributeHandle&) = default;
868 
869  virtual ~AttributeHandle();
870 
871  Index stride() const { return mStrideOrTotalSize; }
872  Index size() const { return mSize; }
873 
874  bool isUniform() const;
875  bool hasConstantStride() const;
876 
877  ValueType get(Index n, Index m = 0) const;
878 
879  const AttributeArray& array() const;
880 
881 protected:
882  Index index(Index n, Index m) const;
883 
885 
890 
891 private:
892  friend class ::TestAttributeArray;
893 
894  template <bool IsUnknownCodec>
895  typename std::enable_if<IsUnknownCodec, bool>::type compatibleType() const;
896 
897  template <bool IsUnknownCodec>
898  typename std::enable_if<!IsUnknownCodec, bool>::type compatibleType() const;
899 
900  template <bool IsUnknownCodec>
901  typename std::enable_if<IsUnknownCodec, ValueType>::type get(Index index) const;
902 
903  template <bool IsUnknownCodec>
904  typename std::enable_if<!IsUnknownCodec, ValueType>::type get(Index index) const;
905 
906  // local copy of AttributeArray (to preserve compression)
907  AttributeArray::Ptr mLocalArray;
908 
909  Index mStrideOrTotalSize;
910  Index mSize;
911  bool mCollapseOnDestruction;
912 }; // class AttributeHandle
913 
914 
916 
917 
919 template <typename ValueType, typename CodecType = UnknownCodec>
920 class AttributeWriteHandle : public AttributeHandle<ValueType, CodecType>
921 {
922 public:
924  using Ptr = std::shared_ptr<Handle>;
925  using ScopedPtr = std::unique_ptr<Handle>;
926 
927  static Ptr create(AttributeArray& array, const bool expand = true);
928 
929  AttributeWriteHandle(AttributeArray& array, const bool expand = true);
930 
931  virtual ~AttributeWriteHandle() = default;
932 
935  void expand(bool fill = true);
936 
938  void collapse();
939  void collapse(const ValueType& uniformValue);
940 
942  bool compact();
943 
946  void fill(const ValueType& value);
947 
948  void set(Index n, const ValueType& value);
949  void set(Index n, Index m, const ValueType& value);
950 
951  AttributeArray& array();
952 
953 private:
954  friend class ::TestAttributeArray;
955 
956  template <bool IsUnknownCodec>
957  typename std::enable_if<IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
958 
959  template <bool IsUnknownCodec>
960  typename std::enable_if<!IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
961 }; // class AttributeWriteHandle
962 
963 
965 
966 
967 // Attribute codec implementation
968 
969 
970 template<typename ValueType>
971 inline void
972 NullCodec::decode(const ValueType& data, ValueType& val)
973 {
974  val = data;
975 }
976 
977 
978 template<typename ValueType>
979 inline void
980 NullCodec::encode(const ValueType& val, ValueType& data)
981 {
982  data = val;
983 }
984 
985 
986 template<typename StorageType, typename ValueType>
987 inline void
988 TruncateCodec::decode(const StorageType& data, ValueType& val)
989 {
990  val = static_cast<ValueType>(data);
991 }
992 
993 
994 template<typename StorageType, typename ValueType>
995 inline void
996 TruncateCodec::encode(const ValueType& val, StorageType& data)
997 {
998  data = static_cast<StorageType>(val);
999 }
1000 
1001 
1002 template <bool OneByte, typename Range>
1003 template<typename StorageType, typename ValueType>
1004 inline void
1005 FixedPointCodec<OneByte, Range>::decode(const StorageType& data, ValueType& val)
1006 {
1007  val = fixedPointToFloatingPoint<ValueType>(data);
1008 
1009  // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
1010 
1011  val = Range::template decode<ValueType>(val);
1012 }
1013 
1014 
1015 template <bool OneByte, typename Range>
1016 template<typename StorageType, typename ValueType>
1017 inline void
1018 FixedPointCodec<OneByte, Range>::encode(const ValueType& val, StorageType& data)
1019 {
1020  // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
1021 
1022  const ValueType newVal = Range::template encode<ValueType>(val);
1023 
1024  data = floatingPointToFixedPoint<StorageType>(newVal);
1025 }
1026 
1027 
1028 template<typename T>
1029 inline void
1030 UnitVecCodec::decode(const StorageType& data, math::Vec3<T>& val)
1031 {
1032  val = math::QuantizedUnitVec::unpack(data);
1033 }
1034 
1035 
1036 template<typename T>
1037 inline void
1038 UnitVecCodec::encode(const math::Vec3<T>& val, StorageType& data)
1039 {
1040  data = math::QuantizedUnitVec::pack(val);
1041 }
1042 
1043 
1045 
1046 // AttributeArray implementation
1047 
1048 #if OPENVDB_ABI_VERSION_NUMBER >= 6
1049 
1050 template <typename IterT>
1051 void AttributeArray::doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
1052  bool rangeChecking/*=true*/)
1053 {
1054  // ensure both arrays have float-float or integer-integer value types
1055  assert(sourceArray.valueTypeIsFloatingPoint() == this->valueTypeIsFloatingPoint());
1056  // ensure both arrays have been loaded from disk (if delay-loaded)
1057  assert(sourceArray.isDataLoaded() && this->isDataLoaded());
1058  // ensure storage size * stride matches on both arrays
1059  assert(this->storageTypeSize()*this->stride() ==
1060  sourceArray.storageTypeSize()*sourceArray.stride());
1061 
1062  const size_t bytes(sourceArray.storageTypeSize()*sourceArray.stride());
1063  const char* const sourceBuffer = sourceArray.dataAsByteArray();
1064  char* const targetBuffer = this->dataAsByteArray();
1065  assert(sourceBuffer && targetBuffer);
1066 
1067  if (rangeChecking && this->isUniform()) {
1068  OPENVDB_THROW(IndexError, "Cannot copy array data as target array is uniform.");
1069  }
1070 
1071  const bool sourceIsUniform = sourceArray.isUniform();
1072 
1073  const Index sourceDataSize = rangeChecking ? sourceArray.dataSize() : 0;
1074  const Index targetDataSize = rangeChecking ? this->dataSize() : 0;
1075 
1076  for (IterT it(iter); it; ++it) {
1077  const Index sourceIndex = sourceIsUniform ? 0 : it.sourceIndex();
1078  const Index targetIndex = it.targetIndex();
1079 
1080  if (rangeChecking) {
1081  if (sourceIndex >= sourceDataSize) {
1083  "Cannot copy array data as source index exceeds size of source array.");
1084  }
1085  if (targetIndex >= targetDataSize) {
1087  "Cannot copy array data as target index exceeds size of target array.");
1088  }
1089  } else {
1090  // range-checking asserts
1091  assert(sourceIndex < sourceArray.dataSize());
1092  assert(targetIndex < this->dataSize());
1093  if (this->isUniform()) assert(targetIndex == Index(0));
1094  }
1095 
1096  const size_t targetOffset(targetIndex * bytes);
1097  const size_t sourceOffset(sourceIndex * bytes);
1098 
1099  std::memcpy(targetBuffer + targetOffset, sourceBuffer + sourceOffset, bytes);
1100  }
1101 }
1102 
1103 template <typename IterT>
1104 void AttributeArray::copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter)
1105 {
1106  this->doCopyValues(sourceArray, iter, /*range-checking=*/false);
1107 }
1108 
1109 template <typename IterT>
1110 void AttributeArray::copyValues(const AttributeArray& sourceArray, const IterT& iter,
1111  bool compact/* = true*/)
1112 {
1113  const Index bytes = sourceArray.storageTypeSize();
1114  if (bytes != this->storageTypeSize()) {
1115  OPENVDB_THROW(TypeError, "Cannot copy array data due to mis-match in storage type sizes.");
1116  }
1117 
1118  // ensure both arrays have been loaded from disk
1119  sourceArray.loadData();
1120  this->loadData();
1121 
1122  // if the target array is uniform, expand it first
1123  this->expand();
1124 
1125  // TODO: Acquire mutex locks for source and target arrays to ensure that
1126  // value copying is always thread-safe. Note that the unsafe method will be
1127  // faster, but can only be used if neither the source or target arrays are
1128  // modified during copying. Note that this will require a new private
1129  // virtual method with ABI=7 to access the mutex from the derived class.
1130 
1131  this->doCopyValues(sourceArray, iter, true);
1132 
1133  // attempt to compact target array
1134  if (compact) {
1135  this->compact();
1136  }
1137 }
1138 #endif
1139 
1140 
1142 
1143 // TypedAttributeArray implementation
1144 
1145 template<typename ValueType_, typename Codec_>
1146 std::unique_ptr<const NamePair> TypedAttributeArray<ValueType_, Codec_>::sTypeName;
1147 
1148 
1149 template<typename ValueType_, typename Codec_>
1151  Index n, Index strideOrTotalSize, bool constantStride, const ValueType& uniformValue)
1152  : AttributeArray()
1153  , mData(new StorageType[1])
1154  , mSize(n)
1155  , mStrideOrTotalSize(strideOrTotalSize)
1156 {
1157  if (constantStride) {
1158  this->setConstantStride(true);
1159  if (strideOrTotalSize == 0) {
1160  OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a constant stride requires that " \
1161  "stride to be at least one.")
1162  }
1163  }
1164  else {
1165  this->setConstantStride(false);
1166  if (mStrideOrTotalSize < n) {
1167  OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a non-constant stride must have " \
1168  "a total size of at least the number of elements in the array.")
1169  }
1170  }
1171  mSize = std::max(Index(1), mSize);
1172  mStrideOrTotalSize = std::max(Index(1), mStrideOrTotalSize);
1173  Codec::encode(uniformValue, this->data()[0]);
1174 }
1175 
1176 
1177 #if OPENVDB_ABI_VERSION_NUMBER >= 7
1178 template<typename ValueType_, typename Codec_>
1180  : TypedAttributeArray(rhs, tbb::spin_mutex::scoped_lock(rhs.mMutex))
1181 {
1182 }
1183 
1184 
1185 template<typename ValueType_, typename Codec_>
1187  const tbb::spin_mutex::scoped_lock& lock)
1188  : AttributeArray(rhs, lock)
1189 #else
1190 template<typename ValueType_, typename Codec_>
1192  : AttributeArray(rhs)
1193 #endif
1194  , mSize(rhs.mSize)
1195  , mStrideOrTotalSize(rhs.mStrideOrTotalSize)
1196 #if OPENVDB_ABI_VERSION_NUMBER < 6
1197  , mIsUniform(rhs.mIsUniform)
1198 #endif
1199 {
1200  if (this->validData()) {
1201  this->allocate();
1202  std::memcpy(this->data(), rhs.data(), this->arrayMemUsage());
1203  }
1204 }
1205 
1206 
1207 template<typename ValueType_, typename Codec_>
1210 {
1211  if (&rhs != this) {
1212  // lock both the source and target arrays to ensure thread-safety
1213  tbb::spin_mutex::scoped_lock lock(mMutex);
1214  tbb::spin_mutex::scoped_lock rhsLock(rhs.mMutex);
1215 
1216  this->deallocate();
1217 
1218  mFlags = rhs.mFlags;
1220  mSize = rhs.mSize;
1221  mStrideOrTotalSize = rhs.mStrideOrTotalSize;
1222  mIsUniform = rhs.mIsUniform;
1223 
1224  if (this->validData()) {
1225  this->allocate();
1226  std::memcpy(this->newDataAsByteArray(), rhs.newDataAsByteArray(), this->arrayMemUsage());
1227  }
1228  }
1229 }
1230 
1231 
1232 template<typename ValueType_, typename Codec_>
1233 inline const NamePair&
1235 {
1236  static std::once_flag once;
1237  std::call_once(once, []()
1238  {
1239  sTypeName.reset(new NamePair(typeNameAsString<ValueType>(), Codec::name()));
1240  });
1241  return *sTypeName;
1242 }
1243 
1244 
1245 template<typename ValueType_, typename Codec_>
1246 inline bool
1248 {
1250 }
1251 
1252 
1253 template<typename ValueType_, typename Codec_>
1254 inline void
1256 {
1257  AttributeArray::registerType(TypedAttributeArray::attributeType(), TypedAttributeArray::factory);
1258 }
1259 
1260 
1261 template<typename ValueType_, typename Codec_>
1262 inline void
1264 {
1266 }
1267 
1268 
1269 template<typename ValueType_, typename Codec_>
1272 {
1273  return Ptr(new TypedAttributeArray(n, stride, constantStride));
1274 }
1275 
1276 template<typename ValueType_, typename Codec_>
1279 {
1280  if (!attributeArray.isType<TypedAttributeArray>()) {
1281  OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1282  }
1283  return static_cast<TypedAttributeArray&>(attributeArray);
1284 }
1285 
1286 template<typename ValueType_, typename Codec_>
1289 {
1290  if (!attributeArray.isType<TypedAttributeArray>()) {
1291  OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1292  }
1293  return static_cast<const TypedAttributeArray&>(attributeArray);
1294 }
1295 
1296 template<typename ValueType_, typename Codec_>
1299 {
1300 #if OPENVDB_ABI_VERSION_NUMBER < 7
1301  tbb::spin_mutex::scoped_lock lock(mMutex);
1302 #endif
1304 }
1305 
1306 
1307 template<typename ValueType_, typename Codec_>
1310 {
1311  return this->copy();
1312 }
1313 
1314 
1315 template<typename ValueType_, typename Codec_>
1316 size_t
1318 {
1319  if (this->isOutOfCore()) return 0;
1320 
1321  return (mIsUniform ? 1 : this->dataSize()) * sizeof(StorageType);
1322 }
1323 
1324 
1325 template<typename ValueType_, typename Codec_>
1326 void
1328 {
1329  assert(!mData);
1330  if (mIsUniform) {
1331  mData.reset(new StorageType[1]);
1332  }
1333  else {
1334  const size_t size(this->dataSize());
1335  assert(size > 0);
1336  mData.reset(new StorageType[size]);
1337  }
1338 }
1339 
1340 
1341 template<typename ValueType_, typename Codec_>
1342 void
1344 {
1345  // detach from file if delay-loaded
1346  if (this->isOutOfCore()) {
1347  this->setOutOfCore(false);
1348  this->mPageHandle.reset();
1349  }
1350  if (mData) mData.reset();
1351 }
1352 
1353 
1354 #if OPENVDB_ABI_VERSION_NUMBER >= 6
1355 template<typename ValueType_, typename Codec_>
1356 bool
1358 {
1359  // TODO: Update to use Traits that correctly handle matrices and quaternions.
1360 
1361  if (std::is_same<ValueType, Quats>::value ||
1362  std::is_same<ValueType, Quatd>::value ||
1363  std::is_same<ValueType, Mat3s>::value ||
1364  std::is_same<ValueType, Mat3d>::value ||
1365  std::is_same<ValueType, Mat4s>::value ||
1366  std::is_same<ValueType, Mat4d>::value) return true;
1367 
1368  using ElementT = typename VecTraits<ValueType>::ElementType;
1369 
1370  // half is not defined as float point as expected, so explicitly handle it
1371  return std::is_floating_point<ElementT>::value || std::is_same<half, ElementT>::value;
1372 }
1373 
1374 
1375 template<typename ValueType_, typename Codec_>
1376 bool
1378 {
1379  // half is not defined as a non-class type as expected, so explicitly exclude it
1380  return std::is_class<ValueType>::value && !std::is_same<half, ValueType>::value;
1381 }
1382 
1383 
1384 template<typename ValueType_, typename Codec_>
1385 bool
1387 {
1389 }
1390 
1391 
1392 template<typename ValueType_, typename Codec_>
1393 bool
1395 {
1396  // TODO: improve performance by making this a compile-time check using type traits
1397  return !this->valueType().compare(0, 4, "quat");
1398 }
1399 
1400 
1401 template<typename ValueType_, typename Codec_>
1402 bool
1404 {
1405  // TODO: improve performance by making this a compile-time check using type traits
1406  return !this->valueType().compare(0, 3, "mat");
1407 }
1408 #endif
1409 
1410 
1411 template<typename ValueType_, typename Codec_>
1412 size_t
1414 {
1415  return sizeof(*this) + (bool(mData) ? this->arrayMemUsage() : 0);
1416 }
1417 
1418 
1419 template<typename ValueType_, typename Codec_>
1422 {
1423  assert(n < this->dataSize());
1424 
1425  ValueType val;
1426  Codec::decode(/*in=*/this->data()[mIsUniform ? 0 : n], /*out=*/val);
1427  return val;
1428 }
1429 
1430 
1431 template<typename ValueType_, typename Codec_>
1434 {
1435  if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1436  if (this->isOutOfCore()) this->doLoad();
1437 
1438  return this->getUnsafe(n);
1439 }
1440 
1441 
1442 template<typename ValueType_, typename Codec_>
1443 template<typename T>
1444 void
1446 {
1447  val = static_cast<T>(this->getUnsafe(n));
1448 }
1449 
1450 
1451 template<typename ValueType_, typename Codec_>
1452 template<typename T>
1453 void
1455 {
1456  val = static_cast<T>(this->get(n));
1457 }
1458 
1459 
1460 template<typename ValueType_, typename Codec_>
1463 {
1464  return static_cast<const TypedAttributeArray<ValueType, Codec>*>(array)->getUnsafe(n);
1465 }
1466 
1467 
1468 template<typename ValueType_, typename Codec_>
1469 void
1471 {
1472  assert(n < this->dataSize());
1473  assert(!this->isOutOfCore());
1474  assert(!this->isUniform());
1475 
1476  // this unsafe method assumes the data is not uniform, however if it is, this redirects the index
1477  // to zero, which is marginally less efficient but ensures not writing to an illegal address
1478 
1479  Codec::encode(/*in=*/val, /*out=*/this->data()[mIsUniform ? 0 : n]);
1480 }
1481 
1482 
1483 template<typename ValueType_, typename Codec_>
1484 void
1486 {
1487  if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1488  if (this->isOutOfCore()) this->doLoad();
1489  if (this->isUniform()) this->expand();
1490 
1491  this->setUnsafe(n, val);
1492 }
1493 
1494 
1495 template<typename ValueType_, typename Codec_>
1496 template<typename T>
1497 void
1499 {
1500  this->setUnsafe(n, static_cast<ValueType>(val));
1501 }
1502 
1503 
1504 template<typename ValueType_, typename Codec_>
1505 template<typename T>
1506 void
1508 {
1509  this->set(n, static_cast<ValueType>(val));
1510 }
1511 
1512 
1513 template<typename ValueType_, typename Codec_>
1514 void
1516 {
1517  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->setUnsafe(n, value);
1518 }
1519 
1520 
1521 template<typename ValueType_, typename Codec_>
1522 void
1524 {
1525  const TypedAttributeArray& sourceTypedArray = static_cast<const TypedAttributeArray&>(sourceArray);
1526 
1527  ValueType sourceValue;
1528  sourceTypedArray.get(sourceIndex, sourceValue);
1529 
1530  this->set(n, sourceValue);
1531 }
1532 
1533 
1534 template<typename ValueType_, typename Codec_>
1535 void
1537 {
1538  if (!mIsUniform) return;
1539 
1540  const StorageType val = this->data()[0];
1541 
1542  {
1543  tbb::spin_mutex::scoped_lock lock(mMutex);
1544  this->deallocate();
1545  mIsUniform = false;
1546  this->allocate();
1547  }
1548 
1549  if (fill) {
1550  for (Index i = 0; i < this->dataSize(); ++i) this->data()[i] = val;
1551  }
1552 }
1553 
1554 
1555 template<typename ValueType_, typename Codec_>
1556 bool
1558 {
1559  if (mIsUniform) return true;
1560 
1561  // compaction is not possible if any values are different
1562  const ValueType_ val = this->get(0);
1563  for (Index i = 1; i < this->dataSize(); i++) {
1564  if (!math::isExactlyEqual(this->get(i), val)) return false;
1565  }
1566 
1567  this->collapse(this->get(0));
1568  return true;
1569 }
1570 
1571 
1572 template<typename ValueType_, typename Codec_>
1573 void
1575 {
1576  this->collapse(zeroVal<ValueType>());
1577 }
1578 
1579 
1580 template<typename ValueType_, typename Codec_>
1581 void
1583 {
1584  if (!mIsUniform) {
1585  tbb::spin_mutex::scoped_lock lock(mMutex);
1586  this->deallocate();
1587  mIsUniform = true;
1588  this->allocate();
1589  }
1590  Codec::encode(uniformValue, this->data()[0]);
1591 }
1592 
1593 
1594 template<typename ValueType_, typename Codec_>
1595 void
1597 {
1598  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->collapse(value);
1599 }
1600 
1601 
1602 template<typename ValueType_, typename Codec_>
1603 void
1605 {
1606  if (this->isOutOfCore()) {
1607  tbb::spin_mutex::scoped_lock lock(mMutex);
1608  this->deallocate();
1609  this->allocate();
1610  }
1611 
1612  const Index size = mIsUniform ? 1 : this->dataSize();
1613  for (Index i = 0; i < size; ++i) {
1614  Codec::encode(value, this->data()[i]);
1615  }
1616 }
1617 
1618 
1619 template<typename ValueType_, typename Codec_>
1620 void
1622 {
1623  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->fill(value);
1624 }
1625 
1626 
1627 template<typename ValueType_, typename Codec_>
1628 inline bool
1630 {
1631  return false;
1632 }
1633 
1634 
1635 template<typename ValueType_, typename Codec_>
1636 inline bool
1638 {
1639  return false;
1640 }
1641 
1642 
1643 template<typename ValueType_, typename Codec_>
1644 inline bool
1646 {
1647  return false;
1648 }
1649 
1650 
1651 template<typename ValueType_, typename Codec_>
1652 bool
1654 {
1655 #if OPENVDB_ABI_VERSION_NUMBER >= 5
1656  return mOutOfCore;
1657 #else
1658  return (mFlags & OUTOFCORE);
1659 #endif
1660 }
1661 
1662 
1663 template<typename ValueType_, typename Codec_>
1664 void
1666 {
1667 #if OPENVDB_ABI_VERSION_NUMBER >= 5
1668  mOutOfCore = b;
1669 #else
1670  if (b) mFlags = static_cast<uint8_t>(mFlags | OUTOFCORE);
1671  else mFlags = static_cast<uint8_t>(mFlags & ~OUTOFCORE);
1672 #endif
1673 }
1674 
1675 
1676 template<typename ValueType_, typename Codec_>
1677 void
1679 {
1680  if (!(this->isOutOfCore())) return;
1681 
1683  const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
1684 
1685  // This lock will be contended at most once, after which this buffer
1686  // will no longer be out-of-core.
1687  tbb::spin_mutex::scoped_lock lock(self->mMutex);
1688  this->doLoadUnsafe();
1689 }
1690 
1691 
1692 template<typename ValueType_, typename Codec_>
1693 void
1695 {
1696  this->doLoad();
1697 }
1698 
1699 
1700 #if OPENVDB_ABI_VERSION_NUMBER >= 6
1701 template<typename ValueType_, typename Codec_>
1702 bool
1704 {
1705  return !this->isOutOfCore();
1706 }
1707 #endif
1708 
1709 
1710 template<typename ValueType_, typename Codec_>
1711 void
1713 {
1714  this->readMetadata(is);
1715  this->readBuffers(is);
1716 }
1717 
1718 
1719 template<typename ValueType_, typename Codec_>
1720 void
1722 {
1723  // read data
1724 
1725  Index64 bytes = Index64(0);
1726  is.read(reinterpret_cast<char*>(&bytes), sizeof(Index64));
1727  bytes = bytes - /*flags*/sizeof(Int16) - /*size*/sizeof(Index);
1728 
1729  uint8_t flags = uint8_t(0);
1730  is.read(reinterpret_cast<char*>(&flags), sizeof(uint8_t));
1731  mFlags = flags;
1732 
1733  uint8_t serializationFlags = uint8_t(0);
1734  is.read(reinterpret_cast<char*>(&serializationFlags), sizeof(uint8_t));
1735 
1736  Index size = Index(0);
1737  is.read(reinterpret_cast<char*>(&size), sizeof(Index));
1738  mSize = size;
1739 
1740  // warn if an unknown flag has been set
1741  if (mFlags >= 0x20) {
1742  OPENVDB_LOG_WARN("Unknown attribute flags for VDB file format.");
1743  }
1744  // error if an unknown serialization flag has been set,
1745  // as this will adjust the layout of the data and corrupt the ability to read
1746  if (serializationFlags >= 0x10) {
1747  OPENVDB_THROW(IoError, "Unknown attribute serialization flags for VDB file format.");
1748  }
1749 
1750  // set uniform, compressed and page read state
1751 
1752  mIsUniform = serializationFlags & WRITEUNIFORM;
1753  mUsePagedRead = serializationFlags & WRITEPAGED;
1754  mCompressedBytes = bytes;
1755  mFlags |= PARTIALREAD; // mark data as having been partially read
1756 
1757  // read strided value (set to 1 if array is not strided)
1758 
1759  if (serializationFlags & WRITESTRIDED) {
1760  Index stride = Index(0);
1761  is.read(reinterpret_cast<char*>(&stride), sizeof(Index));
1762  mStrideOrTotalSize = stride;
1763  }
1764  else {
1765  mStrideOrTotalSize = 1;
1766  }
1767 }
1768 
1769 
1770 template<typename ValueType_, typename Codec_>
1771 void
1773 {
1774  if (mUsePagedRead) {
1775  // use readBuffers(PagedInputStream&) for paged buffers
1776  OPENVDB_THROW(IoError, "Cannot read paged AttributeArray buffers.");
1777  }
1778 
1779  tbb::spin_mutex::scoped_lock lock(mMutex);
1780 
1781  this->deallocate();
1782 
1783  uint8_t bloscCompressed(0);
1784  if (!mIsUniform) is.read(reinterpret_cast<char*>(&bloscCompressed), sizeof(uint8_t));
1785 
1786  assert(mFlags & PARTIALREAD);
1787  std::unique_ptr<char[]> buffer(new char[mCompressedBytes]);
1788  is.read(buffer.get(), mCompressedBytes);
1789  mCompressedBytes = 0;
1790  mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1791 
1792  // compressed on-disk
1793 
1794  if (bloscCompressed == uint8_t(1)) {
1795 
1796  // decompress buffer
1797 
1798  const size_t inBytes = this->dataSize() * sizeof(StorageType);
1799  std::unique_ptr<char[]> newBuffer = compression::bloscDecompress(buffer.get(), inBytes);
1800  if (newBuffer) buffer.reset(newBuffer.release());
1801  }
1802 
1803  // set data to buffer
1804 
1805  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1806 }
1807 
1808 
1809 template<typename ValueType_, typename Codec_>
1810 void
1812 {
1813  if (!mUsePagedRead) {
1814  if (!is.sizeOnly()) this->readBuffers(is.getInputStream());
1815  return;
1816  }
1817 
1818  // If this array is being read from a memory-mapped file, delay loading of its data
1819  // until the data is actually accessed.
1821  const bool delayLoad = (mappedFile.get() != nullptr);
1822 
1823  if (is.sizeOnly())
1824  {
1825  size_t compressedBytes(mCompressedBytes);
1826  mCompressedBytes = 0; // if not set to zero, mPageHandle will attempt to destroy invalid memory
1827  mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1828  assert(!mPageHandle);
1829  mPageHandle = is.createHandle(compressedBytes);
1830  return;
1831  }
1832 
1833  assert(mPageHandle);
1834 
1835  tbb::spin_mutex::scoped_lock lock(mMutex);
1836 
1837  this->deallocate();
1838 
1839  this->setOutOfCore(delayLoad);
1840  is.read(mPageHandle, std::streamsize(mPageHandle->size()), delayLoad);
1841 
1842  if (!delayLoad) {
1843  std::unique_ptr<char[]> buffer = mPageHandle->read();
1844  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1845  }
1846 
1847  // clear page state
1848 
1849  mUsePagedRead = 0;
1850 }
1851 
1852 
1853 template<typename ValueType_, typename Codec_>
1854 void
1856 {
1857  this->write(os, /*outputTransient=*/false);
1858 }
1859 
1860 
1861 template<typename ValueType_, typename Codec_>
1862 void
1863 TypedAttributeArray<ValueType_, Codec_>::write(std::ostream& os, bool outputTransient) const
1864 {
1865  this->writeMetadata(os, outputTransient, /*paged=*/false);
1866  this->writeBuffers(os, outputTransient);
1867 }
1868 
1869 
1870 template<typename ValueType_, typename Codec_>
1871 void
1872 TypedAttributeArray<ValueType_, Codec_>::writeMetadata(std::ostream& os, bool outputTransient, bool paged) const
1873 {
1874  if (!outputTransient && this->isTransient()) return;
1875 
1876  if (mFlags & PARTIALREAD) {
1877  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1878  }
1879 
1880 #if OPENVDB_ABI_VERSION_NUMBER >= 5
1881  uint8_t flags(mFlags);
1882 #else
1883  uint8_t flags(mFlags & uint8_t(~OUTOFCORE));
1884 #endif
1885  uint8_t serializationFlags(0);
1886  Index size(mSize);
1887  Index stride(mStrideOrTotalSize);
1888  bool strideOfOne(this->stride() == 1);
1889 
1890  bool bloscCompression = io::getDataCompression(os) & io::COMPRESS_BLOSC;
1891 
1892  // any compressed data needs to be loaded if out-of-core
1893  if (bloscCompression) this->doLoad();
1894 
1895  size_t compressedBytes = 0;
1896 
1897  if (!strideOfOne)
1898  {
1899  serializationFlags |= WRITESTRIDED;
1900  }
1901 
1902  if (mIsUniform)
1903  {
1904  serializationFlags |= WRITEUNIFORM;
1905  if (bloscCompression && paged) serializationFlags |= WRITEPAGED;
1906  }
1907  else if (bloscCompression)
1908  {
1909  if (paged) serializationFlags |= WRITEPAGED;
1910  else {
1911  const char* charBuffer = reinterpret_cast<const char*>(this->data());
1912  const size_t inBytes = this->arrayMemUsage();
1913  compressedBytes = compression::bloscCompressedSize(charBuffer, inBytes);
1914  }
1915  }
1916 
1917  Index64 bytes = /*flags*/ sizeof(Int16) + /*size*/ sizeof(Index);
1918 
1919  bytes += (compressedBytes > 0) ? compressedBytes : this->arrayMemUsage();
1920 
1921  // write data
1922 
1923  os.write(reinterpret_cast<const char*>(&bytes), sizeof(Index64));
1924  os.write(reinterpret_cast<const char*>(&flags), sizeof(uint8_t));
1925  os.write(reinterpret_cast<const char*>(&serializationFlags), sizeof(uint8_t));
1926  os.write(reinterpret_cast<const char*>(&size), sizeof(Index));
1927 
1928  // write strided
1929  if (!strideOfOne) os.write(reinterpret_cast<const char*>(&stride), sizeof(Index));
1930 }
1931 
1932 
1933 template<typename ValueType_, typename Codec_>
1934 void
1935 TypedAttributeArray<ValueType_, Codec_>::writeBuffers(std::ostream& os, bool outputTransient) const
1936 {
1937  if (!outputTransient && this->isTransient()) return;
1938 
1939  if (mFlags & PARTIALREAD) {
1940  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1941  }
1942 
1943  this->doLoad();
1944 
1945  if (this->isUniform()) {
1946  os.write(reinterpret_cast<const char*>(this->data()), sizeof(StorageType));
1947  }
1949  {
1950  std::unique_ptr<char[]> compressedBuffer;
1951  size_t compressedBytes = 0;
1952  const char* charBuffer = reinterpret_cast<const char*>(this->data());
1953  const size_t inBytes = this->arrayMemUsage();
1954  compressedBuffer = compression::bloscCompress(charBuffer, inBytes, compressedBytes);
1955  if (compressedBuffer) {
1956  uint8_t bloscCompressed(1);
1957  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1958  os.write(reinterpret_cast<const char*>(compressedBuffer.get()), compressedBytes);
1959  }
1960  else {
1961  uint8_t bloscCompressed(0);
1962  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1963  os.write(reinterpret_cast<const char*>(this->data()), inBytes);
1964  }
1965  }
1966  else
1967  {
1968  uint8_t bloscCompressed(0);
1969  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1970  os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1971  }
1972 }
1973 
1974 
1975 template<typename ValueType_, typename Codec_>
1976 void
1978 {
1979  if (!outputTransient && this->isTransient()) return;
1980 
1981  // paged compression only available when Blosc is enabled
1982  bool bloscCompression = io::getDataCompression(os.getOutputStream()) & io::COMPRESS_BLOSC;
1983  if (!bloscCompression) {
1984  if (!os.sizeOnly()) this->writeBuffers(os.getOutputStream(), outputTransient);
1985  return;
1986  }
1987 
1988  if (mFlags & PARTIALREAD) {
1989  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1990  }
1991 
1992  this->doLoad();
1993 
1994  os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1995 }
1996 
1997 
1998 template<typename ValueType_, typename Codec_>
1999 void
2000 TypedAttributeArray<ValueType_, Codec_>::doLoadUnsafe(const bool /*compression*/) const
2001 {
2002  if (!(this->isOutOfCore())) return;
2003 
2004  // this function expects the mutex to already be locked
2005 
2006  auto* self = const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
2007 
2008  assert(self->mPageHandle);
2009  assert(!(self->mFlags & PARTIALREAD));
2010 
2011  std::unique_ptr<char[]> buffer = self->mPageHandle->read();
2012 
2013  self->mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
2014 
2015  self->mPageHandle.reset();
2016 
2017  // clear all write and out-of-core flags
2018 
2019 #if OPENVDB_ABI_VERSION_NUMBER >= 5
2020  self->mOutOfCore = false;
2021 #else
2022  self->mFlags &= uint8_t(~OUTOFCORE);
2023 #endif
2024 }
2025 
2026 
2027 template<typename ValueType_, typename Codec_>
2030 {
2031  // use the faster 'unsafe' get and set methods as attribute handles
2032  // ensure data is uncompressed and in-core when constructed
2033 
2039 }
2040 
2041 
2042 template<typename ValueType_, typename Codec_>
2043 bool
2045 {
2046  const TypedAttributeArray<ValueType_, Codec_>* const otherT = dynamic_cast<const TypedAttributeArray<ValueType_, Codec_>* >(&other);
2047  if(!otherT) return false;
2048  if(this->mSize != otherT->mSize ||
2049  this->mStrideOrTotalSize != otherT->mStrideOrTotalSize ||
2050  this->mIsUniform != otherT->mIsUniform ||
2051  this->attributeType() != this->attributeType()) return false;
2052 
2053  this->doLoad();
2054  otherT->doLoad();
2055 
2056  const StorageType *target = this->data(), *source = otherT->data();
2057  if (!target && !source) return true;
2058  if (!target || !source) return false;
2059  Index n = this->mIsUniform ? 1 : mSize;
2060  while (n && math::isExactlyEqual(*target++, *source++)) --n;
2061  return n == 0;
2062 }
2063 
2064 
2065 #if OPENVDB_ABI_VERSION_NUMBER >= 6
2066 template<typename ValueType_, typename Codec_>
2067 char*
2069 {
2070  return reinterpret_cast<char*>(this->data());
2071 }
2072 
2073 
2074 template<typename ValueType_, typename Codec_>
2075 const char*
2077 {
2078  return reinterpret_cast<const char*>(this->data());
2079 }
2080 #endif
2081 
2082 
2084 
2085 
2087 template <typename CodecType, typename ValueType>
2089 {
2090  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
2091  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
2092 
2095  static ValueType get(GetterPtr /*functor*/, const AttributeArray* array, const Index n) {
2097  }
2098 
2101  static void set(SetterPtr /*functor*/, AttributeArray* array, const Index n, const ValueType& value) {
2103  }
2104 };
2105 
2106 
2108 template <typename ValueType>
2110 {
2111  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
2112  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
2113 
2115  static ValueType get(GetterPtr functor, const AttributeArray* array, const Index n) {
2116  return (*functor)(array, n);
2117  }
2118 
2120  static void set(SetterPtr functor, AttributeArray* array, const Index n, const ValueType& value) {
2121  (*functor)(array, n, value);
2122  }
2123 };
2124 
2125 
2127 
2128 // AttributeHandle implementation
2129 
2130 template <typename ValueType, typename CodecType>
2132 AttributeHandle<ValueType, CodecType>::create(const AttributeArray& array, const bool collapseOnDestruction)
2133 {
2135  new AttributeHandle<ValueType, CodecType>(array, collapseOnDestruction));
2136 }
2137 
2138 template <typename ValueType, typename CodecType>
2139 AttributeHandle<ValueType, CodecType>::AttributeHandle(const AttributeArray& array, const bool collapseOnDestruction)
2140  : mArray(&array)
2141  , mStrideOrTotalSize(array.hasConstantStride() ? array.stride() : 1)
2142  , mSize(array.hasConstantStride() ? array.size() : array.dataSize())
2143  , mCollapseOnDestruction(collapseOnDestruction && array.isStreaming())
2144 {
2145  if (!this->compatibleType<std::is_same<CodecType, UnknownCodec>::value>()) {
2146  OPENVDB_THROW(TypeError, "Cannot bind handle due to incompatible type of AttributeArray.");
2147  }
2148 
2149  // load data if delay-loaded
2150 
2151  mArray->loadData();
2152 
2153  // bind getter and setter methods
2154 
2156  assert(accessor);
2157 
2158  AttributeArray::Accessor<ValueType>* typedAccessor = static_cast<AttributeArray::Accessor<ValueType>*>(accessor.get());
2159 
2160  mGetter = typedAccessor->mGetter;
2161  mSetter = typedAccessor->mSetter;
2162  mCollapser = typedAccessor->mCollapser;
2163  mFiller = typedAccessor->mFiller;
2164 }
2165 
2166 template <typename ValueType, typename CodecType>
2168 {
2169  // if enabled, attribute is collapsed on destruction of the handle to save memory
2170  if (mCollapseOnDestruction) const_cast<AttributeArray*>(this->mArray)->collapse();
2171 }
2172 
2173 template <typename ValueType, typename CodecType>
2174 template <bool IsUnknownCodec>
2175 typename std::enable_if<IsUnknownCodec, bool>::type
2177 {
2178  // if codec is unknown, just check the value type
2179 
2180  return mArray->hasValueType<ValueType>();
2181 }
2182 
2183 template <typename ValueType, typename CodecType>
2184 template <bool IsUnknownCodec>
2185 typename std::enable_if<!IsUnknownCodec, bool>::type
2187 {
2188  // if the codec is known, check the value type and codec
2189 
2191 }
2192 
2193 template <typename ValueType, typename CodecType>
2195 {
2196  assert(mArray);
2197  return *mArray;
2198 }
2199 
2200 template <typename ValueType, typename CodecType>
2202 {
2203  Index index = n * mStrideOrTotalSize + m;
2204  assert(index < (mSize * mStrideOrTotalSize));
2205  return index;
2206 }
2207 
2208 template <typename ValueType, typename CodecType>
2210 {
2211  return this->get<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m));
2212 }
2213 
2214 template <typename ValueType, typename CodecType>
2215 template <bool IsUnknownCodec>
2216 typename std::enable_if<IsUnknownCodec, ValueType>::type
2218 {
2219  // if the codec is unknown, use the getter functor
2220 
2221  return (*mGetter)(mArray, index);
2222 }
2223 
2224 template <typename ValueType, typename CodecType>
2225 template <bool IsUnknownCodec>
2226 typename std::enable_if<!IsUnknownCodec, ValueType>::type
2228 {
2229  // if the codec is known, call the method on the attribute array directly
2230 
2232 }
2233 
2234 template <typename ValueType, typename CodecType>
2236 {
2237  return mArray->isUniform();
2238 }
2239 
2240 template <typename ValueType, typename CodecType>
2242 {
2243  return mArray->hasConstantStride();
2244 }
2245 
2247 
2248 // AttributeWriteHandle implementation
2249 
2250 template <typename ValueType, typename CodecType>
2253 {
2255  new AttributeWriteHandle<ValueType, CodecType>(array, expand));
2256 }
2257 
2258 template <typename ValueType, typename CodecType>
2260  : AttributeHandle<ValueType, CodecType>(array, /*collapseOnDestruction=*/false)
2261 {
2262  if (expand) array.expand();
2263 }
2264 
2265 template <typename ValueType, typename CodecType>
2267 {
2268  this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, 0), value);
2269 }
2270 
2271 template <typename ValueType, typename CodecType>
2273 {
2274  this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m), value);
2275 }
2276 
2277 template <typename ValueType, typename CodecType>
2279 {
2280  const_cast<AttributeArray*>(this->mArray)->expand(fill);
2281 }
2282 
2283 template <typename ValueType, typename CodecType>
2285 {
2286  const_cast<AttributeArray*>(this->mArray)->collapse();
2287 }
2288 
2289 template <typename ValueType, typename CodecType>
2291 {
2292  return const_cast<AttributeArray*>(this->mArray)->compact();
2293 }
2294 
2295 template <typename ValueType, typename CodecType>
2296 void AttributeWriteHandle<ValueType, CodecType>::collapse(const ValueType& uniformValue)
2297 {
2298  this->mCollapser(const_cast<AttributeArray*>(this->mArray), uniformValue);
2299 }
2300 
2301 template <typename ValueType, typename CodecType>
2303 {
2304  this->mFiller(const_cast<AttributeArray*>(this->mArray), value);
2305 }
2306 
2307 template <typename ValueType, typename CodecType>
2308 template <bool IsUnknownCodec>
2309 typename std::enable_if<IsUnknownCodec, void>::type
2310 AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2311 {
2312  // if the codec is unknown, use the setter functor
2313 
2314  (*this->mSetter)(const_cast<AttributeArray*>(this->mArray), index, value);
2315 }
2316 
2317 template <typename ValueType, typename CodecType>
2318 template <bool IsUnknownCodec>
2319 typename std::enable_if<!IsUnknownCodec, void>::type
2320 AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2321 {
2322  // if the codec is known, call the method on the attribute array directly
2323 
2324  TypedAttributeArray<ValueType, CodecType>::setUnsafe(const_cast<AttributeArray*>(this->mArray), index, value);
2325 }
2326 
2327 template <typename ValueType, typename CodecType>
2329 {
2330  assert(this->mArray);
2331  return *const_cast<AttributeArray*>(this->mArray);
2332 }
2333 
2334 
2335 } // namespace points
2336 } // namespace OPENVDB_VERSION_NAME
2337 } // namespace openvdb
2338 
2339 #endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
#define OPENVDB_API
Helper macros for defining library symbol visibility.
Definition: Platform.h:230
const NamePair & type() const override
Return the name of this attribute&#39;s type.
Definition: AttributeArray.h:631
void setUnsafe(Index n, const ValueType &value)
Set value at the given index n (assumes uncompressed and in-core)
Definition: AttributeArray.h:1470
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:2112
void setConstantStride(bool state)
Specify whether this attribute has a constant stride or not.
bool compact() override
Compact the existing array to become uniform if all values are identical.
Definition: AttributeArray.h:1557
virtual Index stride() const =0
void collapse() override
Replace the existing array with a uniform zero value.
Definition: AttributeArray.h:1574
Definition: AttributeArray.h:522
AttributeWriteHandle(AttributeArray &array, const bool expand=true)
Definition: AttributeArray.h:2259
Definition: AttributeArray.h:504
Definition: Exceptions.h:57
StorageType Type
Definition: AttributeArray.h:551
#define OPENVDB_DEPRECATED
Definition: Platform.h:42
streaming mode collapses attributes when first accessed
Definition: AttributeArray.h:107
T & z()
Definition: Vec3.h:85
bool isOutOfCore() const
Return true if this buffer&#39;s values have not yet been read from disk.
Definition: AttributeArray.h:1653
Index valueTypeSize() const override
Return the size in bytes of the value type of a single element in this array.
Definition: AttributeArray.h:660
const AttributeArray & array() const
Definition: AttributeArray.h:2194
Definition: AttributeArray.h:493
static const NamePair & attributeType()
Return the name of this attribute&#39;s type (includes codec)
Definition: AttributeArray.h:1234
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.
IntegerVectorT floatingPointToFixedPoint(const math::Vec3< FloatT > &v)
Definition: AttributeArray.h:69
SetterPtr mSetter
Definition: AttributeArray.h:451
static void registerType(const NamePair &type, FactoryMethod, const ScopedRegistryLock *lock=nullptr)
Register a attribute type along with a factory function.
void set(Index n, const ValueType &value)
Set value at the given index n.
Definition: AttributeArray.h:1485
bool validData() const
Verify that data is not out-of-core or in a partially-read state.
Definition: AttributeArray.h:794
static Ptr create(Index n, Index strideOrTotalSize=1, bool constantStride=true)
Return a new attribute array of the given length n and stride with uniform value zero.
Definition: AttributeArray.h:1271
tbb::atomic< Index32 > mOutOfCore
Definition: AttributeArray.h:421
Definition: AttributeArray.h:551
Accessor base class for AttributeArray storage where type is not available.
Definition: AttributeArray.h:436
SharedPtr< MappedFile > Ptr
Definition: io.h:136
std::shared_ptr< AttributeArray > Ptr
Definition: AttributeArray.h:126
virtual void expand(bool fill=true)=0
If this array is uniform, replace it with an array of length size().
OPENVDB_DEPRECATED bool isCompressed() const
Definition: AttributeArray.h:285
bool operator!=(const AttributeArray &other) const
Definition: AttributeArray.h:367
~TypedAttributeArray() override
Definition: AttributeArray.h:609
Accessor to call unsafe get and set methods based on templated Codec and Value.
Definition: AttributeArray.h:2088
Definition: AttributeArray.h:513
void(*)(AttributeArray *array, const Index n, const StringIndexType &value) SetterPtr
Definition: AttributeArray.h:858
std::unique_ptr< PageHandle > Ptr
Definition: StreamCompression.h:171
A Paging wrapper to std::istream that is responsible for reading from a given input stream and creati...
Definition: StreamCompression.h:208
StorageType * data()
Return the raw data buffer.
Definition: AttributeArray.h:790
bool isTransient() const
Return true if this attribute is not serialized during stream output.
Definition: AttributeArray.h:312
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:82
std::string Name
Definition: Name.h:17
void write(std::ostream &os, bool outputTransient) const override
Definition: AttributeArray.h:1863
Base class for storing attribute data.
Definition: AttributeArray.h:92
OPENVDB_API size_t bloscCompressedSize(const char *buffer, const size_t uncompressedBytes)
Convenience wrapper to retrieve the compressed size of buffer when compressed.
void fill(const ValueType &value)
Fill the existing array with the given value.
Definition: AttributeArray.h:1604
void set(Index n, const ValueType &value)
Definition: AttributeArray.h:2266
virtual bool isDataLoaded() const =0
Return true if all data has been loaded.
Index size() const
Definition: AttributeArray.h:872
bool isHidden() const
Return true if this attribute is hidden (e.g., from UI or iterators).
Definition: AttributeArray.h:305
static ValueType decode(const ValueType &value)
Definition: AttributeArray.h:526
bool isType() const
Return true if this attribute is of the same type as the template parameter.
Definition: AttributeArray.h:224
void(*)(AttributeArray *array, const StringIndexType &value) ValuePtr
Definition: AttributeArray.h:859
ValuePtr mCollapser
Definition: AttributeArray.h:452
std::istream & getInputStream()
Definition: StreamCompression.h:222
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...
void(*)(AttributeArray *array, const Index n, const T &value) SetterPtr
Definition: AttributeArray.h:444
virtual AccessorBasePtr getAccessor() const =0
Obtain an Accessor that stores getter and setter functors.
T & y()
Definition: Vec3.h:84
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:2091
OPENVDB_API uint32_t getDataCompression(std::ios_base &)
Return a bitwise OR of compression option flags (COMPRESS_ZIP, COMPRESS_ACTIVE_MASK, etc.) specifying whether and how input data is compressed or output data should be compressed.
AttributeHandle(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2139
static const char * name()
Definition: AttributeArray.h:555
SerializationFlag
Definition: AttributeArray.h:110
virtual Index dataSize() const =0
static TypedAttributeArray & cast(AttributeArray &attributeArray)
Cast an AttributeArray to TypedAttributeArray<T>
Definition: AttributeArray.h:1278
void expand(bool fill=true)
If this array is uniform, replace it with an array of length size().
Definition: AttributeArray.h:2278
bool valueTypeIsQuaternion() const override
Return true if the value type is a quaternion.
Definition: AttributeArray.h:1394
ValueType_ ValueType
Definition: AttributeArray.h:575
Typed class for storing attribute data.
Definition: AttributeArray.h:566
static const char * name()
Definition: AttributeArray.h:515
data is marked as strided when written
Definition: AttributeArray.h:112
uint8_t mUsePagedRead
Definition: AttributeArray.h:420
Index stride() const override
Definition: AttributeArray.h:645
ValuePtr mCollapser
Definition: AttributeArray.h:888
T(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:443
AccessorBasePtr getAccessor() const override
Obtain an Accessor that stores getter and setter functors.
Definition: AttributeArray.h:2029
Definition: Exceptions.h:65
tbb::spin_mutex mMutex
Definition: AttributeArray.h:418
T Type
Definition: AttributeArray.h:493
static const char * name()
Definition: AttributeArray.h:497
bool hasConstantStride() const
Return true if this attribute has a constant stride.
Definition: AttributeArray.h:323
bool hasValueType() const
Return true if this attribute has a value type the same as the template parameter.
Definition: AttributeArray.h:228
Index storageTypeSize() const override
Definition: AttributeArray.h:664
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2132
typename T::ValueType ElementType
Definition: Types.h:185
OPENVDB_DEPRECATED AttributeArray::Ptr copyUncompressed() const override
Definition: AttributeArray.h:1309
Convenience wrappers to using Blosc and reading and writing of Paged data.
bool valueTypeIsFloatingPoint() const override
Return true if the value type is floating point.
Definition: AttributeArray.h:1357
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:654
bool hasConstantStride() const
Definition: AttributeArray.h:2241
void readBuffers(std::istream &) override
Read attribute buffers from a stream.
Definition: AttributeArray.h:1772
void(*)(AttributeArray *array, const T &value) ValuePtr
Definition: AttributeArray.h:445
int16_t Int16
Definition: Types.h:32
ValueType get(Index n, Index m=0) const
Definition: AttributeArray.h:2209
A Paging wrapper to std::ostream that is responsible for writing from a given output stream at interv...
Definition: StreamCompression.h:245
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:102
static ValueType encode(const ValueType &value)
Definition: AttributeArray.h:516
static void unregisterType(const NamePair &type, const ScopedRegistryLock *lock=nullptr)
Remove a attribute type from the registry.
Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler)
Definition: AttributeArray.h:447
uint16_t StorageType
Definition: AttributeArray.h:548
Definition: Compression.h:56
OPENVDB_DEPRECATED bool decompress() override
Uncompress the attribute array.
Definition: AttributeArray.h:1645
static void registerType()
Register this attribute type along with a factory function.
Definition: AttributeArray.h:1255
bool isUniform() const
Definition: AttributeArray.h:2235
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:39
GetterPtr mGetter
Definition: AttributeArray.h:450
void writeMetadata(std::ostream &os, bool outputTransient, bool paged) const override
Definition: AttributeArray.h:1872
static const char * name()
Definition: AttributeArray.h:524
Definition: AttributeArray.h:501
virtual bool valueTypeIsFloatingPoint() const =0
Return true if the value type is floating point.
PageHandle::Ptr createHandle(std::streamsize n)
Creates a PageHandle to access the next.
typename attribute_traits::UIntTypeTrait< OneByte, T >::Type Type
Definition: AttributeArray.h:534
static const char * name()
Definition: AttributeArray.h:539
Definition: Types.h:181
Definition: Exceptions.h:13
Index index(Index n, Index m) const
Definition: AttributeArray.h:2201
bool isDataLoaded() const override
Return true if all data has been loaded.
Definition: AttributeArray.h:1703
bool sizeOnly() const
Definition: StreamCompression.h:256
TypedAttributeArray & operator=(const TypedAttributeArray &)
Definition: AttributeArray.h:1209
Write-able version of AttributeHandle.
Definition: AttributeArray.h:920
virtual Index storageTypeSize() const =0
static bool isRegistered()
Return true if this attribute type is registered.
Definition: AttributeArray.h:1247
Flag
Definition: AttributeArray.h:101
Index Iterators.
PagedOutputStream & write(const char *str, std::streamsize n)
Writes the given.
bool compact()
Compact the existing array to become uniform if all values are identical.
Definition: AttributeArray.h:2290
virtual ~AttributeHandle()
Definition: AttributeArray.h:2167
std::shared_ptr< TypedAttributeArray > Ptr
Definition: AttributeArray.h:572
void fill(const ValueType &value)
Fill the existing array with the given value.
Definition: AttributeArray.h:2302
void expand(bool fill=true) override
Replace the single value storage with an array of length size().
Definition: AttributeArray.h:1536
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:83
AttributeArray::Ptr copy() const override
Definition: AttributeArray.h:1298
ValueType getUnsafe(Index n) const
Return the value at index n (assumes uncompressed and in-core)
Definition: AttributeArray.h:1421
AttributeArray & array()
Definition: AttributeArray.h:2328
void collapse()
Replace the existing array with a uniform value (zero if none provided).
Definition: AttributeArray.h:2284
bool sizeOnly() const
Definition: StreamCompression.h:219
FloatVectorT fixedPointToFloatingPoint(const math::Vec3< IntegerT > &v)
Definition: AttributeArray.h:79
Definition: AttributeArray.h:490
static void unregisterType()
Remove this attribute type from the registry.
Definition: AttributeArray.h:1263
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:471
static const char * name()
Definition: AttributeArray.h:508
Definition: AttributeArray.h:534
virtual void loadData() const =0
Ensures all data is in-core.
void loadData() const override
Ensures all data is in-core.
Definition: AttributeArray.h:1694
Index32 Index
Definition: Types.h:31
ValuePtr mFiller
Definition: AttributeArray.h:889
bool valueTypeIsMatrix() const override
Return true if the value type is a matrix.
Definition: AttributeArray.h:1403
bool mIsUniform
Definition: AttributeArray.h:417
GetterPtr mGetter
Definition: AttributeArray.h:886
Index size() const override
Return the number of elements in this array.
Definition: AttributeArray.h:641
Definition: AttributeArray.h:531
virtual ~AttributeArray()
Definition: AttributeArray.h:138
Definition: AttributeArray.h:849
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:1150
static ValueType decode(const ValueType &value)
Definition: AttributeArray.h:517
uint8_t flags() const
Retrieve the attribute array flags.
Definition: AttributeArray.h:326
hidden from UIs or iterators
Definition: AttributeArray.h:104
Definition: Mat.h:170
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...
static Ptr create(AttributeArray &array, const bool expand=true)
Definition: AttributeArray.h:2252
Definition: Coord.h:16
Definition: Exceptions.h:58
AttributeArray()
Definition: AttributeArray.h:134
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form &#39;someVar << "some text" << ...&#39;.
Definition: logging.h:253
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:102
const AttributeArray * mArray
Definition: AttributeArray.h:884
const StorageType * data() const
Definition: AttributeArray.h:791
static bool isRegistered(const NamePair &type, const ScopedRegistryLock *lock=nullptr)
Return true if the given attribute type name is registered.
typename attribute_traits::TruncateTrait< T >::Type Type
Definition: AttributeArray.h:504
uint64_t Index64
Definition: Types.h:30
void writePagedBuffers(compression::PagedOutputStream &os, bool outputTransient) const override
Definition: AttributeArray.h:1977
Name codecType() const override
Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
Definition: AttributeArray.h:657
bool isUniform() const override
Return true if this array is stored as a single uniform value.
Definition: AttributeArray.h:718
ValueType get(Index n) const
Return the value at index n.
Definition: AttributeArray.h:1433
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:388
std::shared_ptr< Handle > Ptr
Definition: AttributeArray.h:924
uint8_t mFlags
Definition: AttributeArray.h:419
Ptr(*)(Index, Index, bool) FactoryMethod
Definition: AttributeArray.h:129
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:2111
static ValueType encode(const ValueType &value)
Definition: AttributeArray.h:525
void readPagedBuffers(compression::PagedInputStream &) override
Read attribute buffers from a paged stream.
Definition: AttributeArray.h:1811
void writeBuffers(std::ostream &os, bool outputTransient) const override
Definition: AttributeArray.h:1935
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:154
bool isStreaming() const
Return true if this attribute is in streaming mode.
Definition: AttributeArray.h:320
SetterPtr mSetter
Definition: AttributeArray.h:887
Index stride() const
Definition: AttributeArray.h:871
compression::PageHandle::Ptr mPageHandle
Definition: AttributeArray.h:424
ValuePtr mFiller
Definition: AttributeArray.h:453
size_t mCompressedBytes
Definition: AttributeArray.h:425
OPENVDB_DEPRECATED bool compress() override
Compress the attribute array.
Definition: AttributeArray.h:1629
std::shared_ptr< AccessorBase > AccessorBasePtr
Definition: AttributeArray.h:98
bool valueTypeIsClass() const override
Return true if the value type is a class (ie vector, matrix or quaternion return true) ...
Definition: AttributeArray.h:1377
Codec_ Codec
Definition: AttributeArray.h:576
OPENVDB_API SharedPtr< MappedFile > getMappedFilePtr(std::ios_base &)
Return a shared pointer to the memory-mapped file with which the given stream is associated, or a null pointer if the stream is not associated with a memory-mapped file.
virtual bool isUniform() const =0
Return true if this array is stored as a single uniform value.
std::ostream & getOutputStream()
Set and get the output stream.
Definition: StreamCompression.h:259
size_t memUsage() const override
Return the number of bytes of memory used by this attribute.
Definition: AttributeArray.h:1413
void readMetadata(std::istream &) override
Read attribute metadata from a stream.
Definition: AttributeArray.h:1721
bool valueTypeIsVector() const override
Return true if the value type is a vector.
Definition: AttributeArray.h:1386
Index dataSize() const override
Return the size of the data in this array.
Definition: AttributeArray.h:648
Definition: AttributeArray.h:546
void read(std::istream &) override
Read attribute data from a stream.
Definition: AttributeArray.h:1712
Definition: Exceptions.h:64
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:2090
typename Codec::template Storage< ValueType >::Type StorageType
Definition: AttributeArray.h:577
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:106
std::shared_ptr< const AttributeArray > ConstPtr
Definition: AttributeArray.h:127
Definition: AttributeArray.h:487
StringIndexType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:857