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