OpenVDB  6.2.0
AttributeArray.h
Go to the documentation of this file.
1 //
3 // Copyright (c) DreamWorks Animation LLC
4 //
5 // All rights reserved. This software is distributed under the
6 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
7 //
8 // Redistributions of source code must retain the above copyright
9 // and license notice and the following restrictions and disclaimer.
10 //
11 // * Neither the name of DreamWorks Animation nor the names of
12 // its contributors may be used to endorse or promote products derived
13 // from this software without specific prior written permission.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE
27 // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00.
28 //
30 
36 
37 #ifndef OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
38 #define OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
39 
40 #include <openvdb/Types.h>
42 #include <openvdb/util/Name.h>
43 #include <openvdb/util/logging.h>
44 #include <openvdb/io/io.h> // MappedFile
45 #include <openvdb/io/Compression.h> // COMPRESS_BLOSC
46 
47 #include "IndexIterator.h"
48 #include "StreamCompression.h"
49 
50 #include <tbb/spin_mutex.h>
51 #include <tbb/atomic.h>
52 
53 #include <memory>
54 #include <string>
55 #include <type_traits>
56 
57 
58 class TestAttributeArray;
59 
60 namespace openvdb {
62 namespace OPENVDB_VERSION_NAME {
63 
64 
65 using NamePair = std::pair<Name, Name>;
66 
67 namespace points {
68 
69 
71 
72 // Utility methods
73 
74 template <typename IntegerT, typename FloatT>
75 inline IntegerT
77 {
78  static_assert(std::is_unsigned<IntegerT>::value, "IntegerT must be unsigned");
79  if (FloatT(0.0) > s) return std::numeric_limits<IntegerT>::min();
80  else if (FloatT(1.0) <= s) return std::numeric_limits<IntegerT>::max();
81  return IntegerT(std::floor(s * FloatT(std::numeric_limits<IntegerT>::max())));
82 }
83 
84 
85 template <typename FloatT, typename IntegerT>
86 inline FloatT
87 fixedPointToFloatingPoint(const IntegerT s)
88 {
89  static_assert(std::is_unsigned<IntegerT>::value, "IntegerT must be unsigned");
90  return FloatT(s) / FloatT((std::numeric_limits<IntegerT>::max()));
91 }
92 
93 template <typename IntegerVectorT, typename FloatT>
94 inline IntegerVectorT
96 {
97  return IntegerVectorT(
98  floatingPointToFixedPoint<typename IntegerVectorT::ValueType>(v.x()),
99  floatingPointToFixedPoint<typename IntegerVectorT::ValueType>(v.y()),
100  floatingPointToFixedPoint<typename IntegerVectorT::ValueType>(v.z()));
101 }
102 
103 template <typename FloatVectorT, typename IntegerT>
104 inline FloatVectorT
106 {
107  return FloatVectorT(
108  fixedPointToFloatingPoint<typename FloatVectorT::ValueType>(v.x()),
109  fixedPointToFloatingPoint<typename FloatVectorT::ValueType>(v.y()),
110  fixedPointToFloatingPoint<typename FloatVectorT::ValueType>(v.z()));
111 }
112 
113 
115 
116 
119 {
120 protected:
121  struct AccessorBase;
122  template <typename T> struct Accessor;
123 
124  using AccessorBasePtr = std::shared_ptr<AccessorBase>;
125 
126 public:
127  enum Flag {
128  TRANSIENT = 0x1,
129  HIDDEN = 0x2,
130  OUTOFCORE = 0x4,
131  CONSTANTSTRIDE = 0x8,
132  STREAMING = 0x10,
133  PARTIALREAD = 0x20
134  };
135 
137  WRITESTRIDED = 0x1,
138  WRITEUNIFORM = 0x2,
139  WRITEMEMCOMPRESS = 0x4,
140  WRITEPAGED = 0x8
142  };
143 
144  // Scoped Lock wrapper class that locks the AttributeArray registry mutex
146  {
147  tbb::spin_mutex::scoped_lock lock;
148  public:
150  }; // class ScopedRegistryLock
151 
152  using Ptr = std::shared_ptr<AttributeArray>;
153  using ConstPtr = std::shared_ptr<const AttributeArray>;
154 
155  using FactoryMethod = Ptr (*)(Index, Index, bool);
156 
157  template <typename ValueType, typename CodecType> friend class AttributeHandle;
158 
159 #if OPENVDB_ABI_VERSION_NUMBER >= 5
160  AttributeArray(): mPageHandle() { mOutOfCore = 0; }
161 #else
162  AttributeArray(): mPageHandle() {}
163 #endif
164  virtual ~AttributeArray()
165  {
166  // if this AttributeArray has been partially read, zero the compressed bytes,
167  // so the page handle won't attempt to clean up invalid memory
168  if (mFlags & PARTIALREAD) mCompressedBytes = 0;
169  }
170 #if OPENVDB_ABI_VERSION_NUMBER >= 6
172  : mIsUniform(rhs.mIsUniform)
173  , mFlags(rhs.mFlags)
174  , mUsePagedRead(rhs.mUsePagedRead)
175  , mOutOfCore(rhs.mOutOfCore)
176  , mPageHandle()
177  {
178  if (mFlags & PARTIALREAD) mCompressedBytes = rhs.mCompressedBytes;
179  else if (rhs.mPageHandle) mPageHandle = rhs.mPageHandle->copy();
180  }
182  {
183  // if this AttributeArray has been partially read, zero the compressed bytes,
184  // so the page handle won't attempt to clean up invalid memory
185  if (mFlags & PARTIALREAD) mCompressedBytes = 0;
186  mIsUniform = rhs.mIsUniform;
187  mFlags = rhs.mFlags;
188  mUsePagedRead = rhs.mUsePagedRead;
189  mOutOfCore = rhs.mOutOfCore;
190  if (mFlags & PARTIALREAD) mCompressedBytes = rhs.mCompressedBytes;
191  else if (rhs.mPageHandle) mPageHandle = rhs.mPageHandle->copy();
192  else mPageHandle.reset();
193  return *this;
194  }
195 #else
196  AttributeArray(const AttributeArray&) = default;
197  AttributeArray& operator=(const AttributeArray&) = default;
198 #endif
199  AttributeArray(AttributeArray&&) = default;
200  AttributeArray& operator=(AttributeArray&&) = default;
201 
204  virtual AttributeArray::Ptr copy() const = 0;
205 
208  virtual AttributeArray::Ptr copyUncompressed() const = 0;
209 
212  virtual Index size() const = 0;
213 
216  virtual Index stride() const = 0;
217 
220  virtual Index dataSize() const = 0;
221 
222 #if OPENVDB_ABI_VERSION_NUMBER >= 6
223  virtual Name valueType() const = 0;
225 
227  virtual Name codecType() const = 0;
228 
231  virtual Index valueTypeSize() const = 0;
232 
235  virtual Index storageTypeSize() const = 0;
236 
238  virtual bool valueTypeIsFloatingPoint() const = 0;
239 
241  virtual bool valueTypeIsClass() const = 0;
242 
244  virtual bool valueTypeIsVector() const = 0;
245 
247  virtual bool valueTypeIsQuaternion() const = 0;
248 
250  virtual bool valueTypeIsMatrix() const = 0;
251 #endif
252 
254  virtual size_t memUsage() const = 0;
255 
259  static Ptr create(const NamePair& type, Index length, Index stride = 1,
260  bool constantStride = true, const ScopedRegistryLock* lock = nullptr);
262  static bool isRegistered(const NamePair& type, const ScopedRegistryLock* lock = nullptr);
264  static void clearRegistry(const ScopedRegistryLock* lock = nullptr);
265 
267  virtual const NamePair& type() const = 0;
269  template<typename AttributeArrayType>
270  bool isType() const { return this->type() == AttributeArrayType::attributeType(); }
271 
273  template<typename ValueType>
274  bool hasValueType() const { return this->type().first == typeNameAsString<ValueType>(); }
275 
278 #if OPENVDB_ABI_VERSION_NUMBER >= 6
279  // Windows does not allow base classes to be easily deprecated.
280 #ifndef _MSC_VER
282 #endif
283 #endif
284  virtual void set(const Index n, const AttributeArray& sourceArray, const Index sourceIndex) = 0;
285 
286 #if OPENVDB_ABI_VERSION_NUMBER >= 6
287  template<typename IterT>
311  void copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter);
315  template<typename IterT>
316  void copyValues(const AttributeArray& sourceArray, const IterT& iter, bool compact = true);
317 #endif
318 
320  virtual bool isUniform() const = 0;
323  virtual void expand(bool fill = true) = 0;
325  virtual void collapse() = 0;
327  virtual bool compact() = 0;
328 
331  OPENVDB_DEPRECATED bool isCompressed() const { return false; }
333  // Windows does not allow base classes to be deprecated
334 #ifndef _MSC_VER
336 #endif
337  virtual bool compress() = 0;
339  // Windows does not allow base classes to be deprecated
340 #ifndef _MSC_VER
342 #endif
343  virtual bool decompress() = 0;
344 
349  void setHidden(bool state);
351  bool isHidden() const { return bool(mFlags & HIDDEN); }
352 
356  void setTransient(bool state);
358  bool isTransient() const { return bool(mFlags & TRANSIENT); }
359 
364  void setStreaming(bool state);
366  bool isStreaming() const { return bool(mFlags & STREAMING); }
367 
369  bool hasConstantStride() const { return bool(mFlags & CONSTANTSTRIDE); }
370 
372  uint8_t flags() const { return mFlags; }
373 
375  virtual void read(std::istream&) = 0;
378  virtual void write(std::ostream&, bool outputTransient) const = 0;
380  virtual void write(std::ostream&) const = 0;
381 
383  virtual void readMetadata(std::istream&) = 0;
387  virtual void writeMetadata(std::ostream&, bool outputTransient, bool paged) const = 0;
388 
390  virtual void readBuffers(std::istream&) = 0;
393  virtual void writeBuffers(std::ostream&, bool outputTransient) const = 0;
394 
396  virtual void readPagedBuffers(compression::PagedInputStream&) = 0;
399  virtual void writePagedBuffers(compression::PagedOutputStream&, bool outputTransient) const = 0;
400 
402  virtual void loadData() const = 0;
403 
404 #if OPENVDB_ABI_VERSION_NUMBER >= 6
405  virtual bool isDataLoaded() const = 0;
407 #endif
408 
412  bool operator==(const AttributeArray& other) const;
413  bool operator!=(const AttributeArray& other) const { return !this->operator==(other); }
414 
415 private:
416  friend class ::TestAttributeArray;
417 
420  virtual bool isEqual(const AttributeArray& other) const = 0;
421 
422 #if OPENVDB_ABI_VERSION_NUMBER >= 6
423  virtual char* dataAsByteArray() = 0;
425  virtual const char* dataAsByteArray() const = 0;
426 
428  template <typename IterT>
429  void doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
430  bool rangeChecking = true);
431 #endif
432 
433 protected:
435  void setConstantStride(bool state);
436 
438  virtual AccessorBasePtr getAccessor() const = 0;
439 
441  static void registerType(const NamePair& type, FactoryMethod,
442  const ScopedRegistryLock* lock = nullptr);
444  static void unregisterType(const NamePair& type,
445  const ScopedRegistryLock* lock = nullptr);
446 
447 #if OPENVDB_ABI_VERSION_NUMBER < 6
448 
449  size_t mCompressedBytes = 0;
450  uint8_t mFlags = 0;
451  uint8_t mUsePagedRead = 0;
452 #if OPENVDB_ABI_VERSION_NUMBER >= 5
453  tbb::atomic<Index32> mOutOfCore; // interpreted as bool
454 #endif
455  compression::PageHandle::Ptr mPageHandle;
456 
457 #else // #if OPENVDB_ABI_VERSION_NUMBER < 6
458 
459  bool mIsUniform = true;
460  mutable tbb::spin_mutex mMutex;
461  uint8_t mFlags = 0;
462  uint8_t mUsePagedRead = 0;
463  tbb::atomic<Index32> mOutOfCore; // interpreted as bool
465  union {
467  size_t mCompressedBytes; // as of ABI=6, this data is packed together to save memory
468  };
469 
470 #endif
471 }; // class AttributeArray
472 
473 
475 
476 
478 struct AttributeArray::AccessorBase { virtual ~AccessorBase() = default; };
479 
482 template <typename T>
484 {
485  using GetterPtr = T (*)(const AttributeArray* array, const Index n);
486  using SetterPtr = void (*)(AttributeArray* array, const Index n, const T& value);
487  using ValuePtr = void (*)(AttributeArray* array, const T& value);
488 
489  Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler) :
490  mGetter(getter), mSetter(setter), mCollapser(collapser), mFiller(filler) { }
491 
496 }; // struct AttributeArray::Accessor
497 
498 
500 
501 
502 namespace attribute_traits
503 {
504  template <typename T> struct TruncateTrait { };
505  template <> struct TruncateTrait<float> { using Type = half; };
506  template <> struct TruncateTrait<int> { using Type = short; };
507 
508  template <typename T> struct TruncateTrait<math::Vec3<T>> {
510  };
511 
512  template <bool OneByte, typename T> struct UIntTypeTrait { };
513  template<typename T> struct UIntTypeTrait</*OneByte=*/true, T> { using Type = uint8_t; };
514  template<typename T> struct UIntTypeTrait</*OneByte=*/false, T> { using Type = uint16_t; };
515  template<typename T> struct UIntTypeTrait</*OneByte=*/true, math::Vec3<T>> {
517  };
518  template<typename T> struct UIntTypeTrait</*OneByte=*/false, math::Vec3<T>> {
520  };
521 }
522 
523 
525 
526 
527 // Attribute codec schemes
528 
529 struct UnknownCodec { };
530 
531 
532 struct NullCodec
533 {
534  template <typename T>
535  struct Storage { using Type = T; };
536 
537  template<typename ValueType> static void decode(const ValueType&, ValueType&);
538  template<typename ValueType> static void encode(const ValueType&, ValueType&);
539  static const char* name() { return "null"; }
540 };
541 
542 
544 {
545  template <typename T>
547 
548  template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
549  template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
550  static const char* name() { return "trnc"; }
551 };
552 
553 
554 // Fixed-point codec range for voxel-space positions [-0.5,0.5]
556 {
557  static const char* name() { return "fxpt"; }
558  template <typename ValueType> static ValueType encode(const ValueType& value) { return value + ValueType(0.5); }
559  template <typename ValueType> static ValueType decode(const ValueType& value) { return value - ValueType(0.5); }
560 };
561 
562 
563 // Fixed-point codec range for unsigned values in the unit range [0.0,1.0]
564 struct UnitRange
565 {
566  static const char* name() { return "ufxpt"; }
567  template <typename ValueType> static ValueType encode(const ValueType& value) { return value; }
568  template <typename ValueType> static ValueType decode(const ValueType& value) { return value; }
569 };
570 
571 
572 template <bool OneByte, typename Range=PositionRange>
574 {
575  template <typename T>
577 
578  template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
579  template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
580 
581  static const char* name() {
582  static const std::string Name = std::string(Range::name()) + (OneByte ? "8" : "16");
583  return Name.c_str();
584  }
585 };
586 
587 
589 {
590  using StorageType = uint16_t;
591 
592  template <typename T>
593  struct Storage { using Type = StorageType; };
594 
595  template<typename T> static void decode(const StorageType&, math::Vec3<T>&);
596  template<typename T> static void encode(const math::Vec3<T>&, StorageType&);
597  static const char* name() { return "uvec"; }
598 };
599 
600 
602 
603 
605 
606 template<typename ValueType_, typename Codec_ = NullCodec>
607 #if OPENVDB_ABI_VERSION_NUMBER >= 6 // for ABI=6, class is final to allow for de-virtualization
609 #else
611 #endif
612 {
613 public:
614  using Ptr = std::shared_ptr<TypedAttributeArray>;
615  using ConstPtr = std::shared_ptr<const TypedAttributeArray>;
616 
617  using ValueType = ValueType_;
618  using Codec = Codec_;
619  using StorageType = typename Codec::template Storage<ValueType>::Type;
620 
622 
624  explicit TypedAttributeArray(Index n = 1, Index strideOrTotalSize = 1, bool constantStride = true,
625  const ValueType& uniformValue = zeroVal<ValueType>());
628  TypedAttributeArray(const TypedAttributeArray&, bool uncompress = false);
631  TypedAttributeArray& operator=(const TypedAttributeArray&);
635  TypedAttributeArray& operator=(TypedAttributeArray&&) = delete;
636 
637  ~TypedAttributeArray() override { this->deallocate(); }
638 
641  AttributeArray::Ptr copy() const override;
642 
645  AttributeArray::Ptr copyUncompressed() const override;
646 
648  static Ptr create(Index n, Index strideOrTotalSize = 1, bool constantStride = true);
649 
651  static TypedAttributeArray& cast(AttributeArray& attributeArray);
652 
654  static const TypedAttributeArray& cast(const AttributeArray& attributeArray);
655 
657  static const NamePair& attributeType();
659  const NamePair& type() const override { return attributeType(); }
660 
662  static bool isRegistered();
664  static void registerType();
666  static void unregisterType();
667 
669  Index size() const override { return mSize; }
670 
673  Index stride() const override { return hasConstantStride() ? mStrideOrTotalSize : 0; }
674 
676  Index dataSize() const override {
677  return hasConstantStride() ? mSize * mStrideOrTotalSize : mStrideOrTotalSize;
678  }
679 
680 #if OPENVDB_ABI_VERSION_NUMBER >= 6
681  Name valueType() const override { return typeNameAsString<ValueType>(); }
683 
685  Name codecType() const override { return Codec::name(); }
686 
688  Index valueTypeSize() const override { return sizeof(ValueType); }
689 
692  Index storageTypeSize() const override { return sizeof(StorageType); }
693 
695  bool valueTypeIsFloatingPoint() const override;
696 
698  bool valueTypeIsClass() const override;
699 
701  bool valueTypeIsVector() const override;
702 
704  bool valueTypeIsQuaternion() const override;
705 
707  bool valueTypeIsMatrix() const override;
708 #endif
709 
711  size_t memUsage() const override;
712 
714  ValueType getUnsafe(Index n) const;
716  ValueType get(Index n) const;
718  template<typename T> void getUnsafe(Index n, T& value) const;
720  template<typename T> void get(Index n, T& value) const;
721 
724  static ValueType getUnsafe(const AttributeArray* array, const Index n);
725 
727  void setUnsafe(Index n, const ValueType& value);
729  void set(Index n, const ValueType& value);
731  template<typename T> void setUnsafe(Index n, const T& value);
733  template<typename T> void set(Index n, const T& value);
734 
737  static void setUnsafe(AttributeArray* array, const Index n, const ValueType& value);
738 
740 #if OPENVDB_ABI_VERSION_NUMBER >= 6
742 #endif
743  void set(const Index n, const AttributeArray& sourceArray, const Index sourceIndex) override;
744 
746  bool isUniform() const override { return mIsUniform; }
750  void expand(bool fill = true) override;
752  void collapse() override;
754  bool compact() override;
755 
757  void collapse(const ValueType& uniformValue);
760  void fill(const ValueType& value);
761 
763  static void collapse(AttributeArray* array, const ValueType& value);
765  static void fill(AttributeArray* array, const ValueType& value);
766 
768  OPENVDB_DEPRECATED bool compress() override;
770  OPENVDB_DEPRECATED bool decompress() override;
771 
773  void read(std::istream&) override;
777  void write(std::ostream& os, bool outputTransient) const override;
779  void write(std::ostream&) const override;
780 
782  void readMetadata(std::istream&) override;
787  void writeMetadata(std::ostream& os, bool outputTransient, bool paged) const override;
788 
790  void readBuffers(std::istream&) override;
794  void writeBuffers(std::ostream& os, bool outputTransient) const override;
795 
797  void readPagedBuffers(compression::PagedInputStream&) override;
801  void writePagedBuffers(compression::PagedOutputStream& os, bool outputTransient) const override;
802 
804  inline bool isOutOfCore() const;
805 
807  void loadData() const override;
808 
809 #if OPENVDB_ABI_VERSION_NUMBER >= 6
810  bool isDataLoaded() const override;
812 #endif
813 
814 protected:
815  AccessorBasePtr getAccessor() const override;
816 
818  inline StorageType* data() { assert(validData()); return mData.get(); }
819  inline const StorageType* data() const { assert(validData()); return mData.get(); }
820 
822  inline bool validData() const { return !(isOutOfCore() || (flags() & PARTIALREAD)); }
823 
824 private:
825  friend class ::TestAttributeArray;
826 
828  inline void doLoad() const;
831  inline void doLoadUnsafe(const bool compression = true) const;
833  inline bool compressUnsafe();
834 
836  inline void setOutOfCore(const bool);
837 
839  bool isEqual(const AttributeArray& other) const override;
840 
841 #if OPENVDB_ABI_VERSION_NUMBER >= 6
842  char* dataAsByteArray() override;
844  const char* dataAsByteArray() const override;
845 #endif
846 
847  size_t arrayMemUsage() const;
848  void allocate();
849  void deallocate();
850 
852  static AttributeArray::Ptr factory(Index n, Index strideOrTotalSize, bool constantStride) {
853  return TypedAttributeArray::create(n, strideOrTotalSize, constantStride);
854  }
855 
856  static tbb::atomic<const NamePair*> sTypeName;
857  std::unique_ptr<StorageType[]> mData;
858  Index mSize;
859  Index mStrideOrTotalSize;
860 #if OPENVDB_ABI_VERSION_NUMBER < 6 // as of ABI=6, this data lives in the base class to reduce memory
861  bool mIsUniform = true;
862  mutable tbb::spin_mutex mMutex;
863 #endif
864 }; // class TypedAttributeArray
865 
866 
868 
869 
872 template <typename ValueType, typename CodecType = UnknownCodec>
874 {
875 public:
877  using Ptr = std::shared_ptr<Handle>;
878  using UniquePtr = std::unique_ptr<Handle>;
879 
880 protected:
881  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
882  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
883  using ValuePtr = void (*)(AttributeArray* array, const ValueType& value);
884 
885 public:
886  static Ptr create(const AttributeArray& array, const bool collapseOnDestruction = true);
887 
888  AttributeHandle(const AttributeArray& array, const bool collapseOnDestruction = true);
889 
890  AttributeHandle(const AttributeHandle&) = default;
891  AttributeHandle& operator=(const AttributeHandle&) = default;
892 
893  virtual ~AttributeHandle();
894 
895  Index stride() const { return mStrideOrTotalSize; }
896  Index size() const { return mSize; }
897 
898  bool isUniform() const;
899  bool hasConstantStride() const;
900 
901  ValueType get(Index n, Index m = 0) const;
902 
903  const AttributeArray& array() const;
904 
905 protected:
906  Index index(Index n, Index m) const;
907 
909 
914 
915 private:
916  friend class ::TestAttributeArray;
917 
918  template <bool IsUnknownCodec>
919  typename std::enable_if<IsUnknownCodec, bool>::type compatibleType() const;
920 
921  template <bool IsUnknownCodec>
922  typename std::enable_if<!IsUnknownCodec, bool>::type compatibleType() const;
923 
924  template <bool IsUnknownCodec>
925  typename std::enable_if<IsUnknownCodec, ValueType>::type get(Index index) const;
926 
927  template <bool IsUnknownCodec>
928  typename std::enable_if<!IsUnknownCodec, ValueType>::type get(Index index) const;
929 
930  // local copy of AttributeArray (to preserve compression)
931  AttributeArray::Ptr mLocalArray;
932 
933  Index mStrideOrTotalSize;
934  Index mSize;
935  bool mCollapseOnDestruction;
936 }; // class AttributeHandle
937 
938 
940 
941 
943 template <typename ValueType, typename CodecType = UnknownCodec>
944 class AttributeWriteHandle : public AttributeHandle<ValueType, CodecType>
945 {
946 public:
948  using Ptr = std::shared_ptr<Handle>;
949  using ScopedPtr = std::unique_ptr<Handle>;
950 
951  static Ptr create(AttributeArray& array, const bool expand = true);
952 
953  AttributeWriteHandle(AttributeArray& array, const bool expand = true);
954 
955  virtual ~AttributeWriteHandle() = default;
956 
959  void expand(bool fill = true);
960 
962  void collapse();
963  void collapse(const ValueType& uniformValue);
964 
966  bool compact();
967 
970  void fill(const ValueType& value);
971 
972  void set(Index n, const ValueType& value);
973  void set(Index n, Index m, const ValueType& value);
974 
975  AttributeArray& array();
976 
977 private:
978  friend class ::TestAttributeArray;
979 
980  template <bool IsUnknownCodec>
981  typename std::enable_if<IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
982 
983  template <bool IsUnknownCodec>
984  typename std::enable_if<!IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
985 }; // class AttributeWriteHandle
986 
987 
989 
990 
991 // Attribute codec implementation
992 
993 
994 template<typename ValueType>
995 inline void
996 NullCodec::decode(const ValueType& data, ValueType& val)
997 {
998  val = data;
999 }
1000 
1001 
1002 template<typename ValueType>
1003 inline void
1004 NullCodec::encode(const ValueType& val, ValueType& data)
1005 {
1006  data = val;
1007 }
1008 
1009 
1010 template<typename StorageType, typename ValueType>
1011 inline void
1012 TruncateCodec::decode(const StorageType& data, ValueType& val)
1013 {
1014  val = static_cast<ValueType>(data);
1015 }
1016 
1017 
1018 template<typename StorageType, typename ValueType>
1019 inline void
1020 TruncateCodec::encode(const ValueType& val, StorageType& data)
1021 {
1022  data = static_cast<StorageType>(val);
1023 }
1024 
1025 
1026 template <bool OneByte, typename Range>
1027 template<typename StorageType, typename ValueType>
1028 inline void
1029 FixedPointCodec<OneByte, Range>::decode(const StorageType& data, ValueType& val)
1030 {
1031  val = fixedPointToFloatingPoint<ValueType>(data);
1032 
1033  // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
1034 
1035  val = Range::template decode<ValueType>(val);
1036 }
1037 
1038 
1039 template <bool OneByte, typename Range>
1040 template<typename StorageType, typename ValueType>
1041 inline void
1042 FixedPointCodec<OneByte, Range>::encode(const ValueType& val, StorageType& data)
1043 {
1044  // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
1045 
1046  const ValueType newVal = Range::template encode<ValueType>(val);
1047 
1048  data = floatingPointToFixedPoint<StorageType>(newVal);
1049 }
1050 
1051 
1052 template<typename T>
1053 inline void
1054 UnitVecCodec::decode(const StorageType& data, math::Vec3<T>& val)
1055 {
1056  val = math::QuantizedUnitVec::unpack(data);
1057 }
1058 
1059 
1060 template<typename T>
1061 inline void
1062 UnitVecCodec::encode(const math::Vec3<T>& val, StorageType& data)
1063 {
1064  data = math::QuantizedUnitVec::pack(val);
1065 }
1066 
1067 
1069 
1070 // AttributeArray implementation
1071 
1072 #if OPENVDB_ABI_VERSION_NUMBER >= 6
1073 
1074 template <typename IterT>
1075 void AttributeArray::doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
1076  bool rangeChecking/*=true*/)
1077 {
1078  // ensure both arrays have float-float or integer-integer value types
1079  assert(sourceArray.valueTypeIsFloatingPoint() == this->valueTypeIsFloatingPoint());
1080  // ensure both arrays have been loaded from disk (if delay-loaded)
1081  assert(sourceArray.isDataLoaded() && this->isDataLoaded());
1082  // ensure storage size * stride matches on both arrays
1083  assert(this->storageTypeSize()*this->stride() ==
1084  sourceArray.storageTypeSize()*sourceArray.stride());
1085 
1086  const size_t bytes(sourceArray.storageTypeSize()*sourceArray.stride());
1087  const char* const sourceBuffer = sourceArray.dataAsByteArray();
1088  char* const targetBuffer = this->dataAsByteArray();
1089  assert(sourceBuffer && targetBuffer);
1090 
1091  if (rangeChecking && this->isUniform()) {
1092  OPENVDB_THROW(IndexError, "Cannot copy array data as target array is uniform.");
1093  }
1094 
1095  const bool sourceIsUniform = sourceArray.isUniform();
1096 
1097  const Index sourceDataSize = rangeChecking ? sourceArray.dataSize() : 0;
1098  const Index targetDataSize = rangeChecking ? this->dataSize() : 0;
1099 
1100  for (IterT it(iter); it; ++it) {
1101  const Index sourceIndex = sourceIsUniform ? 0 : it.sourceIndex();
1102  const Index targetIndex = it.targetIndex();
1103 
1104  if (rangeChecking) {
1105  if (sourceIndex >= sourceDataSize) {
1107  "Cannot copy array data as source index exceeds size of source array.");
1108  }
1109  if (targetIndex >= targetDataSize) {
1111  "Cannot copy array data as target index exceeds size of target array.");
1112  }
1113  } else {
1114  // range-checking asserts
1115  assert(sourceIndex < sourceArray.dataSize());
1116  assert(targetIndex < this->dataSize());
1117  if (this->isUniform()) assert(targetIndex == Index(0));
1118  }
1119 
1120  const size_t targetOffset(targetIndex * bytes);
1121  const size_t sourceOffset(sourceIndex * bytes);
1122 
1123  std::memcpy(targetBuffer + targetOffset, sourceBuffer + sourceOffset, bytes);
1124  }
1125 }
1126 
1127 template <typename IterT>
1128 void AttributeArray::copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter)
1129 {
1130  this->doCopyValues(sourceArray, iter, /*range-checking=*/false);
1131 }
1132 
1133 template <typename IterT>
1134 void AttributeArray::copyValues(const AttributeArray& sourceArray, const IterT& iter,
1135  bool compact/* = true*/)
1136 {
1137  const Index bytes = sourceArray.storageTypeSize();
1138  if (bytes != this->storageTypeSize()) {
1139  OPENVDB_THROW(TypeError, "Cannot copy array data due to mis-match in storage type sizes.");
1140  }
1141 
1142  // ensure both arrays have been loaded from disk
1143  sourceArray.loadData();
1144  this->loadData();
1145 
1146  // if the target array is uniform, expand it first
1147  this->expand();
1148 
1149  // TODO: Acquire mutex locks for source and target arrays to ensure that
1150  // value copying is always thread-safe. Note that the unsafe method will be
1151  // faster, but can only be used if neither the source or target arrays are
1152  // modified during copying. Note that this will require a new private
1153  // virtual method with ABI=7 to access the mutex from the derived class.
1154 
1155  this->doCopyValues(sourceArray, iter, true);
1156 
1157  // attempt to compact target array
1158  if (compact) {
1159  this->compact();
1160  }
1161 }
1162 #endif
1163 
1164 
1166 
1167 // TypedAttributeArray implementation
1168 
1169 template<typename ValueType_, typename Codec_>
1170 tbb::atomic<const NamePair*> TypedAttributeArray<ValueType_, Codec_>::sTypeName;
1171 
1172 
1173 template<typename ValueType_, typename Codec_>
1175  Index n, Index strideOrTotalSize, bool constantStride, const ValueType& uniformValue)
1176  : AttributeArray()
1177  , mData(new StorageType[1])
1178  , mSize(n)
1179  , mStrideOrTotalSize(strideOrTotalSize)
1180 {
1181  if (constantStride) {
1182  this->setConstantStride(true);
1183  if (strideOrTotalSize == 0) {
1184  OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a constant stride requires that " \
1185  "stride to be at least one.")
1186  }
1187  }
1188  else {
1189  this->setConstantStride(false);
1190  if (mStrideOrTotalSize < n) {
1191  OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a non-constant stride must have " \
1192  "a total size of at least the number of elements in the array.")
1193  }
1194  }
1195  mSize = std::max(Index(1), mSize);
1196  mStrideOrTotalSize = std::max(Index(1), mStrideOrTotalSize);
1197  Codec::encode(uniformValue, this->data()[0]);
1198 }
1199 
1200 
1201 template<typename ValueType_, typename Codec_>
1203  : AttributeArray(rhs)
1204  , mSize(rhs.mSize)
1205  , mStrideOrTotalSize(rhs.mStrideOrTotalSize)
1206 #if OPENVDB_ABI_VERSION_NUMBER < 6
1207  , mIsUniform(rhs.mIsUniform)
1208 #endif
1209 {
1210  if (this->validData()) {
1211  this->allocate();
1212  std::memcpy(this->data(), rhs.data(), this->arrayMemUsage());
1213  }
1214 }
1215 
1216 
1217 template<typename ValueType_, typename Codec_>
1220 {
1221  if (&rhs != this) {
1222  // lock both the source and target arrays to ensure thread-safety
1223  tbb::spin_mutex::scoped_lock lock(mMutex);
1224  tbb::spin_mutex::scoped_lock rhsLock(rhs.mMutex);
1225 
1226  this->deallocate();
1227 
1228  mFlags = rhs.mFlags;
1230  mSize = rhs.mSize;
1231  mStrideOrTotalSize = rhs.mStrideOrTotalSize;
1232  mIsUniform = rhs.mIsUniform;
1233 
1234  if (this->validData()) {
1235  this->allocate();
1236  std::memcpy(this->newDataAsByteArray(), rhs.newDataAsByteArray(), this->arrayMemUsage());
1237  }
1238  }
1239 }
1240 
1241 
1242 template<typename ValueType_, typename Codec_>
1243 inline const NamePair&
1245 {
1246  if (sTypeName == nullptr) {
1247  NamePair* s = new NamePair(typeNameAsString<ValueType>(), Codec::name());
1248  if (sTypeName.compare_and_swap(s, nullptr) != nullptr) delete s;
1249  }
1250  return *sTypeName;
1251 }
1252 
1253 
1254 template<typename ValueType_, typename Codec_>
1255 inline bool
1257 {
1259 }
1260 
1261 
1262 template<typename ValueType_, typename Codec_>
1263 inline void
1265 {
1266  AttributeArray::registerType(TypedAttributeArray::attributeType(), TypedAttributeArray::factory);
1267 }
1268 
1269 
1270 template<typename ValueType_, typename Codec_>
1271 inline void
1273 {
1275 }
1276 
1277 
1278 template<typename ValueType_, typename Codec_>
1281 {
1282  return Ptr(new TypedAttributeArray(n, stride, constantStride));
1283 }
1284 
1285 template<typename ValueType_, typename Codec_>
1288 {
1289  if (!attributeArray.isType<TypedAttributeArray>()) {
1290  OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1291  }
1292  return static_cast<TypedAttributeArray&>(attributeArray);
1293 }
1294 
1295 template<typename ValueType_, typename Codec_>
1298 {
1299  if (!attributeArray.isType<TypedAttributeArray>()) {
1300  OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1301  }
1302  return static_cast<const TypedAttributeArray&>(attributeArray);
1303 }
1304 
1305 template<typename ValueType_, typename Codec_>
1308 {
1309  tbb::spin_mutex::scoped_lock lock(mMutex);
1311 }
1312 
1313 
1314 template<typename ValueType_, typename Codec_>
1317 {
1318  tbb::spin_mutex::scoped_lock lock(mMutex);
1319  return AttributeArray::Ptr(new TypedAttributeArray<ValueType, Codec>(*this, /*decompress = */true));
1320 }
1321 
1322 
1323 template<typename ValueType_, typename Codec_>
1324 size_t
1326 {
1327  if (this->isOutOfCore()) return 0;
1328 
1329  return (mIsUniform ? 1 : this->dataSize()) * sizeof(StorageType);
1330 }
1331 
1332 
1333 template<typename ValueType_, typename Codec_>
1334 void
1336 {
1337  assert(!mData);
1338  if (mIsUniform) {
1339  mData.reset(new StorageType[1]);
1340  }
1341  else {
1342  const size_t size(this->dataSize());
1343  assert(size > 0);
1344  mData.reset(new StorageType[size]);
1345  }
1346 }
1347 
1348 
1349 template<typename ValueType_, typename Codec_>
1350 void
1352 {
1353  // detach from file if delay-loaded
1354  if (this->isOutOfCore()) {
1355  this->setOutOfCore(false);
1356  this->mPageHandle.reset();
1357  }
1358  if (mData) mData.reset();
1359 }
1360 
1361 
1362 #if OPENVDB_ABI_VERSION_NUMBER >= 6
1363 template<typename ValueType_, typename Codec_>
1364 bool
1366 {
1367  // TODO: Update to use Traits that correctly handle matrices and quaternions.
1368 
1369  if (std::is_same<ValueType, Quats>::value ||
1370  std::is_same<ValueType, Quatd>::value ||
1371  std::is_same<ValueType, Mat3s>::value ||
1372  std::is_same<ValueType, Mat3d>::value ||
1373  std::is_same<ValueType, Mat4s>::value ||
1374  std::is_same<ValueType, Mat4d>::value) return true;
1375 
1376  using ElementT = typename VecTraits<ValueType>::ElementType;
1377 
1378  // half is not defined as float point as expected, so explicitly handle it
1379  return std::is_floating_point<ElementT>::value || std::is_same<half, ElementT>::value;
1380 }
1381 
1382 
1383 template<typename ValueType_, typename Codec_>
1384 bool
1386 {
1387  // half is not defined as a non-class type as expected, so explicitly exclude it
1388  return std::is_class<ValueType>::value && !std::is_same<half, ValueType>::value;
1389 }
1390 
1391 
1392 template<typename ValueType_, typename Codec_>
1393 bool
1395 {
1397 }
1398 
1399 
1400 template<typename ValueType_, typename Codec_>
1401 bool
1403 {
1404  // TODO: improve performance by making this a compile-time check using type traits
1405  return !this->valueType().compare(0, 4, "quat");
1406 }
1407 
1408 
1409 template<typename ValueType_, typename Codec_>
1410 bool
1412 {
1413  // TODO: improve performance by making this a compile-time check using type traits
1414  return !this->valueType().compare(0, 3, "mat");
1415 }
1416 #endif
1417 
1418 
1419 template<typename ValueType_, typename Codec_>
1420 size_t
1422 {
1423  return sizeof(*this) + (bool(mData) ? this->arrayMemUsage() : 0);
1424 }
1425 
1426 
1427 template<typename ValueType_, typename Codec_>
1430 {
1431  assert(n < this->dataSize());
1432 
1433  ValueType val;
1434  Codec::decode(/*in=*/this->data()[mIsUniform ? 0 : n], /*out=*/val);
1435  return val;
1436 }
1437 
1438 
1439 template<typename ValueType_, typename Codec_>
1442 {
1443  if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1444  if (this->isOutOfCore()) this->doLoad();
1445 
1446  return this->getUnsafe(n);
1447 }
1448 
1449 
1450 template<typename ValueType_, typename Codec_>
1451 template<typename T>
1452 void
1454 {
1455  val = static_cast<T>(this->getUnsafe(n));
1456 }
1457 
1458 
1459 template<typename ValueType_, typename Codec_>
1460 template<typename T>
1461 void
1463 {
1464  val = static_cast<T>(this->get(n));
1465 }
1466 
1467 
1468 template<typename ValueType_, typename Codec_>
1471 {
1472  return static_cast<const TypedAttributeArray<ValueType, Codec>*>(array)->getUnsafe(n);
1473 }
1474 
1475 
1476 template<typename ValueType_, typename Codec_>
1477 void
1479 {
1480  assert(n < this->dataSize());
1481  assert(!this->isOutOfCore());
1482  assert(!this->isUniform());
1483 
1484  // this unsafe method assumes the data is not uniform, however if it is, this redirects the index
1485  // to zero, which is marginally less efficient but ensures not writing to an illegal address
1486 
1487  Codec::encode(/*in=*/val, /*out=*/this->data()[mIsUniform ? 0 : n]);
1488 }
1489 
1490 
1491 template<typename ValueType_, typename Codec_>
1492 void
1494 {
1495  if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1496  if (this->isOutOfCore()) this->doLoad();
1497  if (this->isUniform()) this->expand();
1498 
1499  this->setUnsafe(n, val);
1500 }
1501 
1502 
1503 template<typename ValueType_, typename Codec_>
1504 template<typename T>
1505 void
1507 {
1508  this->setUnsafe(n, static_cast<ValueType>(val));
1509 }
1510 
1511 
1512 template<typename ValueType_, typename Codec_>
1513 template<typename T>
1514 void
1516 {
1517  this->set(n, static_cast<ValueType>(val));
1518 }
1519 
1520 
1521 template<typename ValueType_, typename Codec_>
1522 void
1524 {
1525  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->setUnsafe(n, value);
1526 }
1527 
1528 
1529 template<typename ValueType_, typename Codec_>
1530 void
1532 {
1533  const TypedAttributeArray& sourceTypedArray = static_cast<const TypedAttributeArray&>(sourceArray);
1534 
1535  ValueType sourceValue;
1536  sourceTypedArray.get(sourceIndex, sourceValue);
1537 
1538  this->set(n, sourceValue);
1539 }
1540 
1541 
1542 template<typename ValueType_, typename Codec_>
1543 void
1545 {
1546  if (!mIsUniform) return;
1547 
1548  const StorageType val = this->data()[0];
1549 
1550  {
1551  tbb::spin_mutex::scoped_lock lock(mMutex);
1552  this->deallocate();
1553  mIsUniform = false;
1554  this->allocate();
1555  }
1556 
1557  if (fill) {
1558  for (Index i = 0; i < this->dataSize(); ++i) this->data()[i] = val;
1559  }
1560 }
1561 
1562 
1563 template<typename ValueType_, typename Codec_>
1564 bool
1566 {
1567  if (mIsUniform) return true;
1568 
1569  // compaction is not possible if any values are different
1570  const ValueType_ val = this->get(0);
1571  for (Index i = 1; i < this->dataSize(); i++) {
1572  if (!math::isExactlyEqual(this->get(i), val)) return false;
1573  }
1574 
1575  this->collapse(this->get(0));
1576  return true;
1577 }
1578 
1579 
1580 template<typename ValueType_, typename Codec_>
1581 void
1583 {
1584  this->collapse(zeroVal<ValueType>());
1585 }
1586 
1587 
1588 template<typename ValueType_, typename Codec_>
1589 void
1591 {
1592  if (!mIsUniform) {
1593  tbb::spin_mutex::scoped_lock lock(mMutex);
1594  this->deallocate();
1595  mIsUniform = true;
1596  this->allocate();
1597  }
1598  Codec::encode(uniformValue, this->data()[0]);
1599 }
1600 
1601 
1602 template<typename ValueType_, typename Codec_>
1603 void
1605 {
1606  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->collapse(value);
1607 }
1608 
1609 
1610 template<typename ValueType_, typename Codec_>
1611 void
1613 {
1614  if (this->isOutOfCore()) {
1615  tbb::spin_mutex::scoped_lock lock(mMutex);
1616  this->deallocate();
1617  this->allocate();
1618  }
1619 
1620  const Index size = mIsUniform ? 1 : this->dataSize();
1621  for (Index i = 0; i < size; ++i) {
1622  Codec::encode(value, this->data()[i]);
1623  }
1624 }
1625 
1626 
1627 template<typename ValueType_, typename Codec_>
1628 void
1630 {
1631  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->fill(value);
1632 }
1633 
1634 
1635 template<typename ValueType_, typename Codec_>
1636 inline bool
1638 {
1639  return false;
1640 }
1641 
1642 
1643 template<typename ValueType_, typename Codec_>
1644 inline bool
1646 {
1647  return false;
1648 }
1649 
1650 
1651 template<typename ValueType_, typename Codec_>
1652 inline bool
1654 {
1655  return false;
1656 }
1657 
1658 
1659 template<typename ValueType_, typename Codec_>
1660 bool
1662 {
1663 #if OPENVDB_ABI_VERSION_NUMBER >= 5
1664  return mOutOfCore;
1665 #else
1666  return (mFlags & OUTOFCORE);
1667 #endif
1668 }
1669 
1670 
1671 template<typename ValueType_, typename Codec_>
1672 void
1674 {
1675 #if OPENVDB_ABI_VERSION_NUMBER >= 5
1676  mOutOfCore = b;
1677 #else
1678  if (b) mFlags = static_cast<uint8_t>(mFlags | OUTOFCORE);
1679  else mFlags = static_cast<uint8_t>(mFlags & ~OUTOFCORE);
1680 #endif
1681 }
1682 
1683 
1684 template<typename ValueType_, typename Codec_>
1685 void
1687 {
1688  if (!(this->isOutOfCore())) return;
1689 
1691  const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
1692 
1693  // This lock will be contended at most once, after which this buffer
1694  // will no longer be out-of-core.
1695  tbb::spin_mutex::scoped_lock lock(self->mMutex);
1696  this->doLoadUnsafe();
1697 }
1698 
1699 
1700 template<typename ValueType_, typename Codec_>
1701 void
1703 {
1704  this->doLoad();
1705 }
1706 
1707 
1708 #if OPENVDB_ABI_VERSION_NUMBER >= 6
1709 template<typename ValueType_, typename Codec_>
1710 bool
1712 {
1713  return !this->isOutOfCore();
1714 }
1715 #endif
1716 
1717 
1718 template<typename ValueType_, typename Codec_>
1719 void
1721 {
1722  this->readMetadata(is);
1723  this->readBuffers(is);
1724 }
1725 
1726 
1727 template<typename ValueType_, typename Codec_>
1728 void
1730 {
1731  // read data
1732 
1733  Index64 bytes = Index64(0);
1734  is.read(reinterpret_cast<char*>(&bytes), sizeof(Index64));
1735  bytes = bytes - /*flags*/sizeof(Int16) - /*size*/sizeof(Index);
1736 
1737  uint8_t flags = uint8_t(0);
1738  is.read(reinterpret_cast<char*>(&flags), sizeof(uint8_t));
1739  mFlags = flags;
1740 
1741  uint8_t serializationFlags = uint8_t(0);
1742  is.read(reinterpret_cast<char*>(&serializationFlags), sizeof(uint8_t));
1743 
1744  Index size = Index(0);
1745  is.read(reinterpret_cast<char*>(&size), sizeof(Index));
1746  mSize = size;
1747 
1748  // warn if an unknown flag has been set
1749  if (mFlags >= 0x20) {
1750  OPENVDB_LOG_WARN("Unknown attribute flags for VDB file format.");
1751  }
1752  // error if an unknown serialization flag has been set,
1753  // as this will adjust the layout of the data and corrupt the ability to read
1754  if (serializationFlags >= 0x10) {
1755  OPENVDB_THROW(IoError, "Unknown attribute serialization flags for VDB file format.");
1756  }
1757 
1758  // set uniform, compressed and page read state
1759 
1760  mIsUniform = serializationFlags & WRITEUNIFORM;
1761  mUsePagedRead = serializationFlags & WRITEPAGED;
1762  mCompressedBytes = bytes;
1763  mFlags |= PARTIALREAD; // mark data as having been partially read
1764 
1765  // read strided value (set to 1 if array is not strided)
1766 
1767  if (serializationFlags & WRITESTRIDED) {
1768  Index stride = Index(0);
1769  is.read(reinterpret_cast<char*>(&stride), sizeof(Index));
1770  mStrideOrTotalSize = stride;
1771  }
1772  else {
1773  mStrideOrTotalSize = 1;
1774  }
1775 }
1776 
1777 
1778 template<typename ValueType_, typename Codec_>
1779 void
1781 {
1782  if (mUsePagedRead) {
1783  // use readBuffers(PagedInputStream&) for paged buffers
1784  OPENVDB_THROW(IoError, "Cannot read paged AttributeArray buffers.");
1785  }
1786 
1787  tbb::spin_mutex::scoped_lock lock(mMutex);
1788 
1789  this->deallocate();
1790 
1791  uint8_t bloscCompressed(0);
1792  if (!mIsUniform) is.read(reinterpret_cast<char*>(&bloscCompressed), sizeof(uint8_t));
1793 
1794  assert(mFlags & PARTIALREAD);
1795  std::unique_ptr<char[]> buffer(new char[mCompressedBytes]);
1796  is.read(buffer.get(), mCompressedBytes);
1797  mCompressedBytes = 0;
1798  mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1799 
1800  // compressed on-disk
1801 
1802  if (bloscCompressed == uint8_t(1)) {
1803 
1804  // decompress buffer
1805 
1806  const size_t inBytes = this->dataSize() * sizeof(StorageType);
1807  std::unique_ptr<char[]> newBuffer = compression::bloscDecompress(buffer.get(), inBytes);
1808  if (newBuffer) buffer.reset(newBuffer.release());
1809  }
1810 
1811  // set data to buffer
1812 
1813  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1814 }
1815 
1816 
1817 template<typename ValueType_, typename Codec_>
1818 void
1820 {
1821  if (!mUsePagedRead) {
1822  if (!is.sizeOnly()) this->readBuffers(is.getInputStream());
1823  return;
1824  }
1825 
1826  // If this array is being read from a memory-mapped file, delay loading of its data
1827  // until the data is actually accessed.
1829  const bool delayLoad = (mappedFile.get() != nullptr);
1830 
1831  if (is.sizeOnly())
1832  {
1833  size_t compressedBytes(mCompressedBytes);
1834  mCompressedBytes = 0; // if not set to zero, mPageHandle will attempt to destroy invalid memory
1835  mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1836  assert(!mPageHandle);
1837  mPageHandle = is.createHandle(compressedBytes);
1838  return;
1839  }
1840 
1841  assert(mPageHandle);
1842 
1843  tbb::spin_mutex::scoped_lock lock(mMutex);
1844 
1845  this->deallocate();
1846 
1847  this->setOutOfCore(delayLoad);
1848  is.read(mPageHandle, std::streamsize(mPageHandle->size()), delayLoad);
1849 
1850  if (!delayLoad) {
1851  std::unique_ptr<char[]> buffer = mPageHandle->read();
1852  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1853  }
1854 
1855  // clear page state
1856 
1857  mUsePagedRead = 0;
1858 }
1859 
1860 
1861 template<typename ValueType_, typename Codec_>
1862 void
1864 {
1865  this->write(os, /*outputTransient=*/false);
1866 }
1867 
1868 
1869 template<typename ValueType_, typename Codec_>
1870 void
1871 TypedAttributeArray<ValueType_, Codec_>::write(std::ostream& os, bool outputTransient) const
1872 {
1873  this->writeMetadata(os, outputTransient, /*paged=*/false);
1874  this->writeBuffers(os, outputTransient);
1875 }
1876 
1877 
1878 template<typename ValueType_, typename Codec_>
1879 void
1880 TypedAttributeArray<ValueType_, Codec_>::writeMetadata(std::ostream& os, bool outputTransient, bool paged) const
1881 {
1882  if (!outputTransient && this->isTransient()) return;
1883 
1884  if (mFlags & PARTIALREAD) {
1885  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1886  }
1887 
1888 #if OPENVDB_ABI_VERSION_NUMBER >= 5
1889  uint8_t flags(mFlags);
1890 #else
1891  uint8_t flags(mFlags & uint8_t(~OUTOFCORE));
1892 #endif
1893  uint8_t serializationFlags(0);
1894  Index size(mSize);
1895  Index stride(mStrideOrTotalSize);
1896  bool strideOfOne(this->stride() == 1);
1897 
1898  bool bloscCompression = io::getDataCompression(os) & io::COMPRESS_BLOSC;
1899 
1900  // any compressed data needs to be loaded if out-of-core
1901  if (bloscCompression) this->doLoad();
1902 
1903  size_t compressedBytes = 0;
1904 
1905  if (!strideOfOne)
1906  {
1907  serializationFlags |= WRITESTRIDED;
1908  }
1909 
1910  if (mIsUniform)
1911  {
1912  serializationFlags |= WRITEUNIFORM;
1913  if (bloscCompression && paged) serializationFlags |= WRITEPAGED;
1914  }
1915  else if (bloscCompression)
1916  {
1917  if (paged) serializationFlags |= WRITEPAGED;
1918  else {
1919  const char* charBuffer = reinterpret_cast<const char*>(this->data());
1920  const size_t inBytes = this->arrayMemUsage();
1921  compressedBytes = compression::bloscCompressedSize(charBuffer, inBytes);
1922  }
1923  }
1924 
1925  Index64 bytes = /*flags*/ sizeof(Int16) + /*size*/ sizeof(Index);
1926 
1927  bytes += (compressedBytes > 0) ? compressedBytes : this->arrayMemUsage();
1928 
1929  // write data
1930 
1931  os.write(reinterpret_cast<const char*>(&bytes), sizeof(Index64));
1932  os.write(reinterpret_cast<const char*>(&flags), sizeof(uint8_t));
1933  os.write(reinterpret_cast<const char*>(&serializationFlags), sizeof(uint8_t));
1934  os.write(reinterpret_cast<const char*>(&size), sizeof(Index));
1935 
1936  // write strided
1937  if (!strideOfOne) os.write(reinterpret_cast<const char*>(&stride), sizeof(Index));
1938 }
1939 
1940 
1941 template<typename ValueType_, typename Codec_>
1942 void
1943 TypedAttributeArray<ValueType_, Codec_>::writeBuffers(std::ostream& os, bool outputTransient) const
1944 {
1945  if (!outputTransient && this->isTransient()) return;
1946 
1947  if (mFlags & PARTIALREAD) {
1948  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1949  }
1950 
1951  this->doLoad();
1952 
1953  if (this->isUniform()) {
1954  os.write(reinterpret_cast<const char*>(this->data()), sizeof(StorageType));
1955  }
1957  {
1958  std::unique_ptr<char[]> compressedBuffer;
1959  size_t compressedBytes = 0;
1960  const char* charBuffer = reinterpret_cast<const char*>(this->data());
1961  const size_t inBytes = this->arrayMemUsage();
1962  compressedBuffer = compression::bloscCompress(charBuffer, inBytes, compressedBytes);
1963  if (compressedBuffer) {
1964  uint8_t bloscCompressed(1);
1965  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1966  os.write(reinterpret_cast<const char*>(compressedBuffer.get()), compressedBytes);
1967  }
1968  else {
1969  uint8_t bloscCompressed(0);
1970  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1971  os.write(reinterpret_cast<const char*>(this->data()), inBytes);
1972  }
1973  }
1974  else
1975  {
1976  uint8_t bloscCompressed(0);
1977  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1978  os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1979  }
1980 }
1981 
1982 
1983 template<typename ValueType_, typename Codec_>
1984 void
1986 {
1987  if (!outputTransient && this->isTransient()) return;
1988 
1989  // paged compression only available when Blosc is enabled
1990  bool bloscCompression = io::getDataCompression(os.getOutputStream()) & io::COMPRESS_BLOSC;
1991  if (!bloscCompression) {
1992  if (!os.sizeOnly()) this->writeBuffers(os.getOutputStream(), outputTransient);
1993  return;
1994  }
1995 
1996  if (mFlags & PARTIALREAD) {
1997  OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1998  }
1999 
2000  this->doLoad();
2001 
2002  os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
2003 }
2004 
2005 
2006 template<typename ValueType_, typename Codec_>
2007 void
2008 TypedAttributeArray<ValueType_, Codec_>::doLoadUnsafe(const bool /*compression*/) const
2009 {
2010  if (!(this->isOutOfCore())) return;
2011 
2012  // this function expects the mutex to already be locked
2013 
2014  auto* self = const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
2015 
2016  assert(self->mPageHandle);
2017  assert(!(self->mFlags & PARTIALREAD));
2018 
2019  std::unique_ptr<char[]> buffer = self->mPageHandle->read();
2020 
2021  self->mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
2022 
2023  self->mPageHandle.reset();
2024 
2025  // clear all write and out-of-core flags
2026 
2027 #if OPENVDB_ABI_VERSION_NUMBER >= 5
2028  self->mOutOfCore = false;
2029 #else
2030  self->mFlags &= uint8_t(~OUTOFCORE);
2031 #endif
2032 }
2033 
2034 
2035 template<typename ValueType_, typename Codec_>
2038 {
2039  // use the faster 'unsafe' get and set methods as attribute handles
2040  // ensure data is uncompressed and in-core when constructed
2041 
2047 }
2048 
2049 
2050 template<typename ValueType_, typename Codec_>
2051 bool
2053 {
2054  const TypedAttributeArray<ValueType_, Codec_>* const otherT = dynamic_cast<const TypedAttributeArray<ValueType_, Codec_>* >(&other);
2055  if(!otherT) return false;
2056  if(this->mSize != otherT->mSize ||
2057  this->mStrideOrTotalSize != otherT->mStrideOrTotalSize ||
2058  this->mIsUniform != otherT->mIsUniform ||
2059  this->attributeType() != this->attributeType()) return false;
2060 
2061  this->doLoad();
2062  otherT->doLoad();
2063 
2064  const StorageType *target = this->data(), *source = otherT->data();
2065  if (!target && !source) return true;
2066  if (!target || !source) return false;
2067  Index n = this->mIsUniform ? 1 : mSize;
2068  while (n && math::isExactlyEqual(*target++, *source++)) --n;
2069  return n == 0;
2070 }
2071 
2072 
2073 #if OPENVDB_ABI_VERSION_NUMBER >= 6
2074 template<typename ValueType_, typename Codec_>
2075 char*
2077 {
2078  return reinterpret_cast<char*>(this->data());
2079 }
2080 
2081 
2082 template<typename ValueType_, typename Codec_>
2083 const char*
2085 {
2086  return reinterpret_cast<const char*>(this->data());
2087 }
2088 #endif
2089 
2090 
2092 
2093 
2095 template <typename CodecType, typename ValueType>
2097 {
2098  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
2099  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
2100 
2103  static ValueType get(GetterPtr /*functor*/, const AttributeArray* array, const Index n) {
2105  }
2106 
2109  static void set(SetterPtr /*functor*/, AttributeArray* array, const Index n, const ValueType& value) {
2111  }
2112 };
2113 
2114 
2116 template <typename ValueType>
2118 {
2119  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
2120  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
2121 
2123  static ValueType get(GetterPtr functor, const AttributeArray* array, const Index n) {
2124  return (*functor)(array, n);
2125  }
2126 
2128  static void set(SetterPtr functor, AttributeArray* array, const Index n, const ValueType& value) {
2129  (*functor)(array, n, value);
2130  }
2131 };
2132 
2133 
2135 
2136 // AttributeHandle implementation
2137 
2138 template <typename ValueType, typename CodecType>
2140 AttributeHandle<ValueType, CodecType>::create(const AttributeArray& array, const bool collapseOnDestruction)
2141 {
2143  new AttributeHandle<ValueType, CodecType>(array, collapseOnDestruction));
2144 }
2145 
2146 template <typename ValueType, typename CodecType>
2147 AttributeHandle<ValueType, CodecType>::AttributeHandle(const AttributeArray& array, const bool collapseOnDestruction)
2148  : mArray(&array)
2149  , mStrideOrTotalSize(array.hasConstantStride() ? array.stride() : 1)
2150  , mSize(array.hasConstantStride() ? array.size() : array.dataSize())
2151  , mCollapseOnDestruction(collapseOnDestruction && array.isStreaming())
2152 {
2153  if (!this->compatibleType<std::is_same<CodecType, UnknownCodec>::value>()) {
2154  OPENVDB_THROW(TypeError, "Cannot bind handle due to incompatible type of AttributeArray.");
2155  }
2156 
2157  // load data if delay-loaded
2158 
2159  mArray->loadData();
2160 
2161  // bind getter and setter methods
2162 
2164  assert(accessor);
2165 
2166  AttributeArray::Accessor<ValueType>* typedAccessor = static_cast<AttributeArray::Accessor<ValueType>*>(accessor.get());
2167 
2168  mGetter = typedAccessor->mGetter;
2169  mSetter = typedAccessor->mSetter;
2170  mCollapser = typedAccessor->mCollapser;
2171  mFiller = typedAccessor->mFiller;
2172 }
2173 
2174 template <typename ValueType, typename CodecType>
2176 {
2177  // if enabled, attribute is collapsed on destruction of the handle to save memory
2178  if (mCollapseOnDestruction) const_cast<AttributeArray*>(this->mArray)->collapse();
2179 }
2180 
2181 template <typename ValueType, typename CodecType>
2182 template <bool IsUnknownCodec>
2183 typename std::enable_if<IsUnknownCodec, bool>::type
2185 {
2186  // if codec is unknown, just check the value type
2187 
2188  return mArray->hasValueType<ValueType>();
2189 }
2190 
2191 template <typename ValueType, typename CodecType>
2192 template <bool IsUnknownCodec>
2193 typename std::enable_if<!IsUnknownCodec, bool>::type
2195 {
2196  // if the codec is known, check the value type and codec
2197 
2199 }
2200 
2201 template <typename ValueType, typename CodecType>
2203 {
2204  assert(mArray);
2205  return *mArray;
2206 }
2207 
2208 template <typename ValueType, typename CodecType>
2210 {
2211  Index index = n * mStrideOrTotalSize + m;
2212  assert(index < (mSize * mStrideOrTotalSize));
2213  return index;
2214 }
2215 
2216 template <typename ValueType, typename CodecType>
2218 {
2219  return this->get<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m));
2220 }
2221 
2222 template <typename ValueType, typename CodecType>
2223 template <bool IsUnknownCodec>
2224 typename std::enable_if<IsUnknownCodec, ValueType>::type
2226 {
2227  // if the codec is unknown, use the getter functor
2228 
2229  return (*mGetter)(mArray, index);
2230 }
2231 
2232 template <typename ValueType, typename CodecType>
2233 template <bool IsUnknownCodec>
2234 typename std::enable_if<!IsUnknownCodec, ValueType>::type
2236 {
2237  // if the codec is known, call the method on the attribute array directly
2238 
2240 }
2241 
2242 template <typename ValueType, typename CodecType>
2244 {
2245  return mArray->isUniform();
2246 }
2247 
2248 template <typename ValueType, typename CodecType>
2250 {
2251  return mArray->hasConstantStride();
2252 }
2253 
2255 
2256 // AttributeWriteHandle implementation
2257 
2258 template <typename ValueType, typename CodecType>
2261 {
2263  new AttributeWriteHandle<ValueType, CodecType>(array, expand));
2264 }
2265 
2266 template <typename ValueType, typename CodecType>
2268  : AttributeHandle<ValueType, CodecType>(array, /*collapseOnDestruction=*/false)
2269 {
2270  if (expand) array.expand();
2271 }
2272 
2273 template <typename ValueType, typename CodecType>
2275 {
2276  this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, 0), value);
2277 }
2278 
2279 template <typename ValueType, typename CodecType>
2281 {
2282  this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m), value);
2283 }
2284 
2285 template <typename ValueType, typename CodecType>
2287 {
2288  const_cast<AttributeArray*>(this->mArray)->expand(fill);
2289 }
2290 
2291 template <typename ValueType, typename CodecType>
2293 {
2294  const_cast<AttributeArray*>(this->mArray)->collapse();
2295 }
2296 
2297 template <typename ValueType, typename CodecType>
2299 {
2300  return const_cast<AttributeArray*>(this->mArray)->compact();
2301 }
2302 
2303 template <typename ValueType, typename CodecType>
2304 void AttributeWriteHandle<ValueType, CodecType>::collapse(const ValueType& uniformValue)
2305 {
2306  this->mCollapser(const_cast<AttributeArray*>(this->mArray), uniformValue);
2307 }
2308 
2309 template <typename ValueType, typename CodecType>
2311 {
2312  this->mFiller(const_cast<AttributeArray*>(this->mArray), value);
2313 }
2314 
2315 template <typename ValueType, typename CodecType>
2316 template <bool IsUnknownCodec>
2317 typename std::enable_if<IsUnknownCodec, void>::type
2318 AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2319 {
2320  // if the codec is unknown, use the setter functor
2321 
2322  (*this->mSetter)(const_cast<AttributeArray*>(this->mArray), index, value);
2323 }
2324 
2325 template <typename ValueType, typename CodecType>
2326 template <bool IsUnknownCodec>
2327 typename std::enable_if<!IsUnknownCodec, void>::type
2328 AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2329 {
2330  // if the codec is known, call the method on the attribute array directly
2331 
2332  TypedAttributeArray<ValueType, CodecType>::setUnsafe(const_cast<AttributeArray*>(this->mArray), index, value);
2333 }
2334 
2335 template <typename ValueType, typename CodecType>
2337 {
2338  assert(this->mArray);
2339  return *const_cast<AttributeArray*>(this->mArray);
2340 }
2341 
2342 
2343 } // namespace points
2344 } // namespace OPENVDB_VERSION_NAME
2345 } // namespace openvdb
2346 
2347 #endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
2348 
2349 // Copyright (c) DreamWorks Animation LLC
2350 // All rights reserved. This software is distributed under the
2351 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
static void unregisterType(const NamePair &type, const ScopedRegistryLock *lock=nullptr)
Remove a attribute type from the registry.
Definition: AttributeArray.h:593
Definition: AttributeArray.h:564
#define OPENVDB_API
Helper macros for defining library symbol visibility.
Definition: Platform.h:288
Accessor base class for AttributeArray storage where type is not available.
Definition: AttributeArray.h:478
ValuePtr mCollapser
Definition: AttributeArray.h:494
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:415
OPENVDB_API uint32_t getDataCompression(std::ios_base &)
Return a bitwise OR of compression option flags (COMPRESS_ZIP, COMPRESS_ACTIVE_MASK, etc.) specifying whether and how input data is compressed or output data should be compressed.
SetterPtr mSetter
Definition: AttributeArray.h:493
virtual ~AttributeHandle()
Definition: AttributeArray.h:2175
#define OPENVDB_DEPRECATED
Definition: Platform.h:69
bool compact()
Compact the existing array to become uniform if all values are identical.
Definition: AttributeArray.h:2298
virtual bool valueTypeIsFloatingPoint() const =0
Return true if the value type is floating point.
A Paging wrapper to std::istream that is responsible for reading from a given input stream and creati...
Definition: StreamCompression.h:235
TypedAttributeArray & operator=(const TypedAttributeArray &)
Definition: AttributeArray.h:1219
Typed class for storing attribute data.
Definition: AttributeArray.h:608
Index storageTypeSize() const override
Definition: AttributeArray.h:692
AttributeArray::Ptr copyUncompressed() const override
Definition: AttributeArray.h:1316
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.
static bool isRegistered()
Return true if this attribute type is registered.
Definition: AttributeArray.h:1256
virtual ~AttributeArray()
Definition: AttributeArray.h:164
AttributeArray & array()
Definition: AttributeArray.h:2336
void readBuffers(std::istream &) override
Read attribute buffers from a stream.
Definition: AttributeArray.h:1780
Index index(Index n, Index m) const
Definition: AttributeArray.h:2209
uint8_t flags() const
Retrieve the attribute array flags.
Definition: AttributeArray.h:372
void expand(bool fill=true) override
Replace the single value storage with an array of length size().
Definition: AttributeArray.h:1544
AttributeArray::Ptr copy() const override
Definition: AttributeArray.h:1307
static ValueType encode(const ValueType &value)
Definition: AttributeArray.h:558
OPENVDB_DEPRECATED bool decompress() override
Uncompress the attribute array.
Definition: AttributeArray.h:1653
static bool isRegistered(const NamePair &type, const ScopedRegistryLock *lock=nullptr)
Return true if the given attribute type name is registered.
static ValueType encode(const ValueType &value)
Definition: AttributeArray.h:567
static void registerType()
Register this attribute type along with a factory function.
Definition: AttributeArray.h:1264
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:133
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:109
void writeMetadata(std::ostream &os, bool outputTransient, bool paged) const override
Definition: AttributeArray.h:1880
static void unregisterType()
Remove this attribute type from the registry.
Definition: AttributeArray.h:1272
GetterPtr mGetter
Definition: AttributeArray.h:910
std::shared_ptr< Handle > Ptr
Definition: AttributeArray.h:948
Ptr(*)(Index, Index, bool) FactoryMethod
Definition: AttributeArray.h:155
AttributeArray & operator=(const AttributeArray &rhs)
Definition: AttributeArray.h:181
AttributeArray()
Definition: AttributeArray.h:160
Definition: AttributeArray.h:555
void readMetadata(std::istream &) override
Read attribute metadata from a stream.
Definition: AttributeArray.h:1729
Index size() const override
Return the number of elements in this array.
Definition: AttributeArray.h:669
Index size() const
Definition: AttributeArray.h:896
bool valueTypeIsVector() const override
Return true if the value type is a vector.
Definition: AttributeArray.h:1394
Flag
Definition: AttributeArray.h:127
std::shared_ptr< AccessorBase > AccessorBasePtr
Definition: AttributeArray.h:124
Index32 Index
Definition: Types.h:61
OPENVDB_API SharedPtr< MappedFile > getMappedFilePtr(std::ios_base &)
Return a shared pointer to the memory-mapped file with which the given stream is associated, or a null pointer if the stream is not associated with a memory-mapped file.
void(*)(AttributeArray *array, const StringIndexType &value) ValuePtr
Definition: AttributeArray.h:883
static const char * name()
Definition: AttributeArray.h:581
virtual bool isUniform() const =0
Return true if this array is stored as a single uniform value.
void(*)(AttributeArray *array, const Index n, const StringIndexType &value) SetterPtr
Definition: AttributeArray.h:882
Accessor to call unsafe get and set methods based on templated Codec and Value.
Definition: AttributeArray.h:2096
typename T::ValueType ElementType
Definition: Types.h:235
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2140
void collapse()
Replace the existing array with a uniform value (zero if none provided).
Definition: AttributeArray.h:2292
GetterPtr mGetter
Definition: AttributeArray.h:492
static Ptr create(AttributeArray &array, const bool expand=true)
Definition: AttributeArray.h:2260
Write-able version of AttributeHandle.
Definition: AttributeArray.h:944
std::shared_ptr< TypedAttributeArray > Ptr
Definition: AttributeArray.h:614
const StorageType * data() const
Definition: AttributeArray.h:819
void(*)(AttributeArray *array, const Index n, const T &value) SetterPtr
Definition: AttributeArray.h:486
StorageType Type
Definition: AttributeArray.h:593
void writePagedBuffers(compression::PagedOutputStream &os, bool outputTransient) const override
Definition: AttributeArray.h:1985
compression::PageHandle::Ptr mPageHandle
Definition: AttributeArray.h:466
Definition: Types.h:231
std::shared_ptr< const AttributeArray > ConstPtr
Definition: AttributeArray.h:153
bool isUniform() const override
Return true if this array is stored as a single uniform value.
Definition: AttributeArray.h:746
void writeBuffers(std::ostream &os, bool outputTransient) const override
Definition: AttributeArray.h:1943
virtual void loadData() const =0
Ensures all data is in-core.
bool mIsUniform
Definition: AttributeArray.h:459
std::ostream & getOutputStream()
Set and get the output stream.
Definition: StreamCompression.h:286
OPENVDB_DEPRECATED bool compress() override
Compress the attribute array.
Definition: AttributeArray.h:1637
Definition: Mat.h:197
Index valueTypeSize() const override
Return the size in bytes of the value type of a single element in this array.
Definition: AttributeArray.h:688
void(*)(AttributeArray *array, const T &value) ValuePtr
Definition: AttributeArray.h:487
FloatVectorT fixedPointToFloatingPoint(const math::Vec3< IntegerT > &v)
Definition: AttributeArray.h:105
Definition: AttributeArray.h:535
bool valueTypeIsClass() const override
Return true if the value type is a class (ie vector, matrix or quaternion return true) ...
Definition: AttributeArray.h:1385
Convenience wrappers to using Blosc and reading and writing of Paged data.
std::unique_ptr< PageHandle > Ptr
Definition: StreamCompression.h:198
Codec_ Codec
Definition: AttributeArray.h:618
T(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:485
void loadData() const override
Ensures all data is in-core.
Definition: AttributeArray.h:1702
SetterPtr mSetter
Definition: AttributeArray.h:911
size_t memUsage() const override
Return the number of bytes of memory used by this attribute.
Definition: AttributeArray.h:1421
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:65
bool valueTypeIsMatrix() const override
Return true if the value type is a matrix.
Definition: AttributeArray.h:1411
StringIndexType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:881
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:1174
Definition: AttributeArray.h:576
static const char * name()
Definition: AttributeArray.h:597
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:128
data is marked as strided when written
Definition: AttributeArray.h:138
Definition: Exceptions.h:91
std::string Name
Definition: Name.h:44
T Type
Definition: AttributeArray.h:535
typename attribute_traits::TruncateTrait< T >::Type Type
Definition: AttributeArray.h:546
typename Codec::template Storage< ValueType >::Type StorageType
Definition: AttributeArray.h:619
tbb::atomic< Index32 > mOutOfCore
Definition: AttributeArray.h:463
StorageType * data()
Return the raw data buffer.
Definition: AttributeArray.h:818
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...
uint8_t mFlags
Definition: AttributeArray.h:461
AttributeWriteHandle(AttributeArray &array, const bool expand=true)
Definition: AttributeArray.h:2267
virtual Index stride() const =0
bool sizeOnly() const
Definition: StreamCompression.h:246
bool isStreaming() const
Return true if this attribute is in streaming mode.
Definition: AttributeArray.h:366
Name codecType() const override
Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
Definition: AttributeArray.h:685
bool hasConstantStride() const
Definition: AttributeArray.h:2249
ValueType get(Index n) const
Return the value at index n.
Definition: AttributeArray.h:1441
const NamePair & type() const override
Return the name of this attribute&#39;s type.
Definition: AttributeArray.h:659
T & z()
Definition: Vec3.h:112
ValueType get(Index n, Index m=0) const
Definition: AttributeArray.h:2217
size_t mCompressedBytes
Definition: AttributeArray.h:467
const AttributeArray & array() const
Definition: AttributeArray.h:2202
bool compact() override
Compact the existing array to become uniform if all values are identical.
Definition: AttributeArray.h:1565
Definition: AttributeArray.h:588
void readPagedBuffers(compression::PagedInputStream &) override
Read attribute buffers from a paged stream.
Definition: AttributeArray.h:1819
void setUnsafe(Index n, const ValueType &value)
Set value at the given index n (assumes uncompressed and in-core)
Definition: AttributeArray.h:1478
T & y()
Definition: Vec3.h:111
Definition: Exceptions.h:40
void collapse() override
Replace the existing array with a uniform zero value.
Definition: AttributeArray.h:1582
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:2098
bool isOutOfCore() const
Return true if this buffer&#39;s values have not yet been read from disk.
Definition: AttributeArray.h:1661
static ValueType decode(const ValueType &value)
Definition: AttributeArray.h:568
AttributeArray(const AttributeArray &rhs)
Definition: AttributeArray.h:171
static const NamePair & attributeType()
Return the name of this attribute&#39;s type (includes codec)
Definition: AttributeArray.h:1244
static const char * name()
Definition: AttributeArray.h:557
std::shared_ptr< AttributeArray > Ptr
Definition: AttributeArray.h:152
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:2099
void setConstantStride(bool state)
Specify whether this attribute has a constant stride or not.
Definition: Exceptions.h:84
Index Iterators.
static ValueType decode(const ValueType &value)
Definition: AttributeArray.h:559
Index dataSize() const override
Return the size of the data in this array.
Definition: AttributeArray.h:676
bool validData() const
Verify that data is not out-of-core or in a partially-read state.
Definition: AttributeArray.h:822
Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler)
Definition: AttributeArray.h:489
static Ptr create(Index n, Index strideOrTotalSize=1, bool constantStride=true)
Return a new attribute array of the given length n and stride with uniform value zero.
Definition: AttributeArray.h:1280
void read(std::istream &) override
Read attribute data from a stream.
Definition: AttributeArray.h:1720
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:2120
uint64_t Index64
Definition: Types.h:60
virtual AccessorBasePtr getAccessor() const =0
Obtain an Accessor that stores getter and setter functors.
bool valueTypeIsQuaternion() const override
Return true if the value type is a quaternion.
Definition: AttributeArray.h:1402
~TypedAttributeArray() override
Definition: AttributeArray.h:637
static void registerType(const NamePair &type, FactoryMethod, const ScopedRegistryLock *lock=nullptr)
Register a attribute type along with a factory function.
Definition: AttributeArray.h:573
Definition: AttributeArray.h:873
hidden from UIs or iterators
Definition: AttributeArray.h:130
virtual Index dataSize() const =0
void write(std::ostream &os, bool outputTransient) const override
Definition: AttributeArray.h:1871
Index stride() const override
Definition: AttributeArray.h:673
const AttributeArray * mArray
Definition: AttributeArray.h:908
PagedOutputStream & write(const char *str, std::streamsize n)
Writes the given.
bool operator!=(const AttributeArray &other) const
Definition: AttributeArray.h:413
const std::enable_if<!VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:129
static const char * name()
Definition: AttributeArray.h:550
bool isTransient() const
Return true if this attribute is not serialized during stream output.
Definition: AttributeArray.h:358
tbb::spin_mutex mMutex
Definition: AttributeArray.h:460
ValuePtr mFiller
Definition: AttributeArray.h:913
bool sizeOnly() const
Definition: StreamCompression.h:283
AttributeHandle(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition: AttributeArray.h:2147
uint16_t StorageType
Definition: AttributeArray.h:590
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:498
void set(Index n, const ValueType &value)
Definition: AttributeArray.h:2274
virtual bool isDataLoaded() const =0
Return true if all data has been loaded.
SerializationFlag
Definition: AttributeArray.h:136
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form &#39;someVar << "some text" << ...&#39;.
Definition: logging.h:280
A Paging wrapper to std::ostream that is responsible for writing from a given output stream at interv...
Definition: StreamCompression.h:272
OPENVDB_DEPRECATED bool isCompressed() const
Definition: AttributeArray.h:331
bool isHidden() const
Return true if this attribute is hidden (e.g., from UI or iterators).
Definition: AttributeArray.h:351
virtual void expand(bool fill=true)=0
If this array is uniform, replace it with an array of length size().
void set(Index n, const ValueType &value)
Set value at the given index n.
Definition: AttributeArray.h:1493
typename attribute_traits::UIntTypeTrait< OneByte, T >::Type Type
Definition: AttributeArray.h:576
bool isType() const
Return true if this attribute is of the same type as the template parameter.
Definition: AttributeArray.h:270
PageHandle::Ptr createHandle(std::streamsize n)
Creates a PageHandle to access the next.
Definition: Compression.h:83
static TypedAttributeArray & cast(AttributeArray &attributeArray)
Cast an AttributeArray to TypedAttributeArray<T>
Definition: AttributeArray.h:1287
ValueType_ ValueType
Definition: AttributeArray.h:617
Definition: Exceptions.h:92
Definition: AttributeArray.h:543
Definition: AttributeArray.h:532
Definition: AttributeArray.h:529
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:180
AccessorBasePtr getAccessor() const override
Obtain an Accessor that stores getter and setter functors.
Definition: AttributeArray.h:2037
bool isDataLoaded() const override
Return true if all data has been loaded.
Definition: AttributeArray.h:1711
int16_t Int16
Definition: Types.h:62
void fill(const ValueType &value)
Fill the existing array with the given value.
Definition: AttributeArray.h:1612
SharedPtr< MappedFile > Ptr
Definition: io.h:163
bool valueTypeIsFloatingPoint() const override
Return true if the value type is floating point.
Definition: AttributeArray.h:1365
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...
ValuePtr mCollapser
Definition: AttributeArray.h:912
static const char * name()
Definition: AttributeArray.h:539
uint8_t mUsePagedRead
Definition: AttributeArray.h:462
Base class for storing attribute data.
Definition: AttributeArray.h:118
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:682
bool isUniform() const
Definition: AttributeArray.h:2243
Definition: AttributeArray.h:546
ValuePtr mFiller
Definition: AttributeArray.h:495
bool hasConstantStride() const
Return true if this attribute has a constant stride.
Definition: AttributeArray.h:369
bool hasValueType() const
Return true if this attribute has a value type the same as the template parameter.
Definition: AttributeArray.h:274
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:2119
ValueType getUnsafe(Index n) const
Return the value at index n (assumes uncompressed and in-core)
Definition: AttributeArray.h:1429
virtual Index storageTypeSize() const =0
Definition: AttributeArray.h:122
Definition: Exceptions.h:85
streaming mode collapses attributes when first accessed
Definition: AttributeArray.h:133
IntegerVectorT floatingPointToFixedPoint(const math::Vec3< FloatT > &v)
Definition: AttributeArray.h:95
OPENVDB_API size_t bloscCompressedSize(const char *buffer, const size_t uncompressedBytes)
Convenience wrapper to retrieve the compressed size of buffer when compressed.
void expand(bool fill=true)
If this array is uniform, replace it with an array of length size().
Definition: AttributeArray.h:2286
Index stride() const
Definition: AttributeArray.h:895
void fill(const ValueType &value)
Fill the existing array with the given value.
Definition: AttributeArray.h:2310
static const char * name()
Definition: AttributeArray.h:566
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:110
std::istream & getInputStream()
Definition: StreamCompression.h:249