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