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