OpenVDB  4.0.1
AttributeArray.h
Go to the documentation of this file.
1 //
3 // Copyright (c) 2012-2017 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  };
134 
136  WRITESTRIDED = 0x1,
137  WRITEUNIFORM = 0x2,
138  WRITEMEMCOMPRESS = 0x4,
139  WRITEPAGED = 0x8
140  };
141 
142  using Ptr = std::shared_ptr<AttributeArray>;
143  using ConstPtr = std::shared_ptr<const AttributeArray>;
144 
145  using FactoryMethod = Ptr (*)(Index, Index, bool);
146 
147  template <typename ValueType, typename CodecType> friend class AttributeHandle;
148 
149  AttributeArray() = default;
150  AttributeArray(const AttributeArray&) = default;
151  AttributeArray& operator=(const AttributeArray&) = default;
152  virtual ~AttributeArray() = default;
153 
155  virtual AttributeArray::Ptr copy() const = 0;
156 
158  virtual AttributeArray::Ptr copyUncompressed() const = 0;
159 
162  virtual Index size() const = 0;
163 
166  virtual Index stride() const = 0;
167 
170  virtual Index dataSize() const = 0;
171 
173  virtual size_t memUsage() const = 0;
174 
176  static Ptr create(const NamePair& type, Index length, Index stride = 1, bool constantStride = true);
178  static bool isRegistered(const NamePair& type);
180  static void clearRegistry();
181 
183  virtual const NamePair& type() const = 0;
185  template<typename AttributeArrayType>
186  bool isType() const { return this->type() == AttributeArrayType::attributeType(); }
187 
189  template<typename ValueType>
190  bool hasValueType() const { return this->type().first == typeNameAsString<ValueType>(); }
191 
193  virtual void set(const Index n, const AttributeArray& sourceArray, const Index sourceIndex) = 0;
194 
196  virtual bool isUniform() const = 0;
199  virtual void expand(bool fill = true) = 0;
201  virtual void collapse() = 0;
203  virtual bool compact() = 0;
204 
206  bool isCompressed() const { return mCompressedBytes != 0; }
208  virtual bool compress() = 0;
210  virtual bool decompress() = 0;
211 
216  void setHidden(bool state);
218  bool isHidden() const { return bool(mFlags & HIDDEN); }
219 
223  void setTransient(bool state);
225  bool isTransient() const { return bool(mFlags & TRANSIENT); }
226 
231  void setStreaming(bool state);
233  bool isStreaming() const { return bool(mFlags & STREAMING); }
234 
236  bool hasConstantStride() const { return bool(mFlags & CONSTANTSTRIDE); }
237 
239  uint8_t flags() const { return mFlags; }
240 
242  virtual void read(std::istream&) = 0;
245  virtual void write(std::ostream&, bool outputTransient) const = 0;
247  virtual void write(std::ostream&) const = 0;
248 
250  virtual void readMetadata(std::istream&) = 0;
254  virtual void writeMetadata(std::ostream&, bool outputTransient, bool paged) const = 0;
255 
257  virtual void readBuffers(std::istream&) = 0;
260  virtual void writeBuffers(std::ostream&, bool outputTransient) const = 0;
261 
263  virtual void readPagedBuffers(compression::PagedInputStream&) = 0;
266  virtual void writePagedBuffers(compression::PagedOutputStream&, bool outputTransient) const = 0;
267 
269  virtual void loadData() const = 0;
270 
274  bool operator==(const AttributeArray& other) const;
275  bool operator!=(const AttributeArray& other) const { return !this->operator==(other); }
276 
277 private:
278  friend class ::TestAttributeArray;
279 
282  virtual bool isEqual(const AttributeArray& other) const = 0;
283 
284 protected:
286  void setConstantStride(bool state);
287 
289  virtual AccessorBasePtr getAccessor() const = 0;
290 
292  static void registerType(const NamePair& type, FactoryMethod);
294  static void unregisterType(const NamePair& type);
295 
296  size_t mCompressedBytes = 0;
297  uint8_t mFlags = 0;
298  uint8_t mSerializationFlags = 0;
299 
302 }; // class AttributeArray
303 
304 
306 
307 
309 struct AttributeArray::AccessorBase { virtual ~AccessorBase() = default; };
310 
313 template <typename T>
315 {
316  using GetterPtr = T (*)(const AttributeArray* array, const Index n);
317  using SetterPtr = void (*)(AttributeArray* array, const Index n, const T& value);
318  using ValuePtr = void (*)(AttributeArray* array, const T& value);
319 
320  Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler) :
321  mGetter(getter), mSetter(setter), mCollapser(collapser), mFiller(filler) { }
322 
327 }; // struct AttributeArray::Accessor
328 
329 
331 
332 
333 namespace attribute_traits
334 {
335  template <typename T> struct TruncateTrait { };
336  template <> struct TruncateTrait<float> { using Type = half; };
337  template <> struct TruncateTrait<int> { using Type = short; };
338 
339  template <typename T> struct TruncateTrait<math::Vec3<T>> {
341  };
342 
343  template <bool OneByte, typename T> struct UIntTypeTrait { };
344  template<typename T> struct UIntTypeTrait</*OneByte=*/true, T> { using Type = uint8_t; };
345  template<typename T> struct UIntTypeTrait</*OneByte=*/false, T> { using Type = uint16_t; };
346  template<typename T> struct UIntTypeTrait</*OneByte=*/true, math::Vec3<T>> {
348  };
349  template<typename T> struct UIntTypeTrait</*OneByte=*/false, math::Vec3<T>> {
351  };
352 }
353 
354 
356 
357 
358 // Attribute codec schemes
359 
360 struct UnknownCodec { };
361 
362 
363 struct NullCodec
364 {
365  template <typename T>
366  struct Storage { using Type = T; };
367 
368  template<typename ValueType> static void decode(const ValueType&, ValueType&);
369  template<typename ValueType> static void encode(const ValueType&, ValueType&);
370  static const char* name() { return "null"; }
371 };
372 
373 
375 {
376  template <typename T>
378 
379  template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
380  template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
381  static const char* name() { return "trnc"; }
382 };
383 
384 
385 // Fixed-point codec range for voxel-space positions [-0.5,0.5]
387 {
388  static const char* name() { return "fxpt"; }
389  template <typename ValueType> static ValueType encode(const ValueType& value) { return value + ValueType(0.5); }
390  template <typename ValueType> static ValueType decode(const ValueType& value) { return value - ValueType(0.5); }
391 };
392 
393 
394 // Fixed-point codec range for unsigned values in the unit range [0.0,1.0]
395 struct UnitRange
396 {
397  static const char* name() { return "ufxpt"; }
398  template <typename ValueType> static ValueType encode(const ValueType& value) { return value; }
399  template <typename ValueType> static ValueType decode(const ValueType& value) { return value; }
400 };
401 
402 
403 template <bool OneByte, typename Range=PositionRange>
405 {
406  template <typename T>
408 
409  template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
410  template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
411 
412  static const char* name() {
413  static const std::string Name = std::string(Range::name()) + (OneByte ? "8" : "16");
414  return Name.c_str();
415  }
416 };
417 
418 
420 {
421  using StorageType = uint16_t;
422 
423  template <typename T>
424  struct Storage { using Type = StorageType; };
425 
426  template<typename T> static void decode(const StorageType&, math::Vec3<T>&);
427  template<typename T> static void encode(const math::Vec3<T>&, StorageType&);
428  static const char* name() { return "uvec"; }
429 };
430 
431 
433 
434 
436 template<typename ValueType_, typename Codec_ = NullCodec>
438 {
439 public:
440  using Ptr = std::shared_ptr<TypedAttributeArray>;
441  using ConstPtr = std::shared_ptr<const TypedAttributeArray>;
442 
443  using ValueType = ValueType_;
444  using Codec = Codec_;
445  using StorageType = typename Codec::template Storage<ValueType>::Type;
446 
448 
450  explicit TypedAttributeArray(Index n = 1, Index strideOrTotalSize = 1, bool constantStride = true,
451  const ValueType& uniformValue = zeroVal<ValueType>());
453  TypedAttributeArray(const TypedAttributeArray&, bool uncompress = false);
455  TypedAttributeArray& operator=(const TypedAttributeArray&);
459  TypedAttributeArray& operator=(TypedAttributeArray&&) = delete;
460 
461  virtual ~TypedAttributeArray() { this->deallocate(); }
462 
464  AttributeArray::Ptr copy() const override;
465 
467  AttributeArray::Ptr copyUncompressed() const override;
468 
470  static Ptr create(Index n, Index strideOrTotalSize = 1, bool constantStride = true);
471 
473  static TypedAttributeArray& cast(AttributeArray& attributeArray);
474 
476  static const TypedAttributeArray& cast(const AttributeArray& attributeArray);
477 
479  static const NamePair& attributeType();
481  const NamePair& type() const override { return attributeType(); }
482 
484  static bool isRegistered();
486  static void registerType();
488  static void unregisterType();
489 
491  Index size() const override { return mSize; }
492 
495  Index stride() const override { return hasConstantStride() ? mStrideOrTotalSize : 0; }
496 
498  Index dataSize() const override {
499  return hasConstantStride() ? mSize * mStrideOrTotalSize : mStrideOrTotalSize;
500  }
501 
503  size_t memUsage() const override;
504 
506  ValueType getUnsafe(Index n) const;
508  ValueType get(Index n) const;
510  template<typename T> void getUnsafe(Index n, T& value) const;
512  template<typename T> void get(Index n, T& value) const;
513 
516  static ValueType getUnsafe(const AttributeArray* array, const Index n);
517 
519  void setUnsafe(Index n, const ValueType& value);
521  void set(Index n, const ValueType& value);
523  template<typename T> void setUnsafe(Index n, const T& value);
525  template<typename T> void set(Index n, const T& value);
526 
529  static void setUnsafe(AttributeArray* array, const Index n, const ValueType& value);
530 
532  void set(const Index n, const AttributeArray& sourceArray, const Index sourceIndex) override;
533 
535  bool isUniform() const override { return mIsUniform; }
539  void expand(bool fill = true) override;
541  void collapse() override;
543  bool compact() override;
544 
546  void collapse(const ValueType& uniformValue);
549  void fill(const ValueType& value);
550 
552  static void collapse(AttributeArray* array, const ValueType& value);
554  static void fill(AttributeArray* array, const ValueType& value);
555 
557  bool compress() override;
559  bool decompress() override;
560 
562  void read(std::istream&) override;
566  void write(std::ostream& os, bool outputTransient) const override;
568  void write(std::ostream&) const override;
569 
571  void readMetadata(std::istream&) override;
576  void writeMetadata(std::ostream& os, bool outputTransient, bool paged) const override;
577 
579  void readBuffers(std::istream&) override;
583  void writeBuffers(std::ostream& os, bool outputTransient) const override;
584 
586  void readPagedBuffers(compression::PagedInputStream&) override;
590  void writePagedBuffers(compression::PagedOutputStream& os, bool outputTransient) const override;
591 
593  inline bool isOutOfCore() const;
594 
596  void loadData() const override;
597 
598 protected:
599  AccessorBasePtr getAccessor() const override;
600 
601 private:
603  inline void doLoad() const;
606  inline void doLoadUnsafe(const bool compression = true) const;
608  inline bool compressUnsafe();
609 
611  inline void setOutOfCore(const bool);
612 
614  bool isEqual(const AttributeArray& other) const override;
615 
616  size_t arrayMemUsage() const;
617  void allocate();
618  void deallocate();
619 
621  static AttributeArray::Ptr factory(Index n, Index strideOrTotalSize, bool constantStride) {
622  return TypedAttributeArray::create(n, strideOrTotalSize, constantStride);
623  }
624 
625  static tbb::atomic<const NamePair*> sTypeName;
626  std::unique_ptr<StorageType[]> mData;
627  Index mSize;
628  Index mStrideOrTotalSize;
629  bool mIsUniform = false;
630  tbb::spin_mutex mMutex;
631 }; // class TypedAttributeArray
632 
633 
635 
636 
639 template <typename ValueType, typename CodecType = UnknownCodec>
641 {
642 public:
644  using Ptr = std::shared_ptr<Handle>;
645  using UniquePtr = std::unique_ptr<Handle>;
646 
647 protected:
648  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
649  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
650  using ValuePtr = void (*)(AttributeArray* array, const ValueType& value);
651 
652 public:
653  static Ptr create(const AttributeArray& array, const bool preserveCompression = true);
654 
655  AttributeHandle(const AttributeArray& array, const bool preserveCompression = true);
656 
657  AttributeHandle(const AttributeHandle&) = default;
658  AttributeHandle& operator=(const AttributeHandle&) = default;
659 
660  virtual ~AttributeHandle();
661 
662  Index stride() const { return mStrideOrTotalSize; }
663  Index size() const { return mSize; }
664 
665  bool isUniform() const;
666  bool hasConstantStride() const;
667 
668  ValueType get(Index n, Index m = 0) const;
669 
670 protected:
671  Index index(Index n, Index m) const;
672 
674 
679 
680 private:
681  friend class ::TestAttributeArray;
682 
683  template <bool IsUnknownCodec>
684  typename std::enable_if<IsUnknownCodec, bool>::type compatibleType() const;
685 
686  template <bool IsUnknownCodec>
687  typename std::enable_if<!IsUnknownCodec, bool>::type compatibleType() const;
688 
689  template <bool IsUnknownCodec>
690  typename std::enable_if<IsUnknownCodec, ValueType>::type get(Index index) const;
691 
692  template <bool IsUnknownCodec>
693  typename std::enable_if<!IsUnknownCodec, ValueType>::type get(Index index) const;
694 
695  // local copy of AttributeArray (to preserve compression)
696  AttributeArray::Ptr mLocalArray;
697 
698  Index mStrideOrTotalSize;
699  Index mSize;
700  bool mCollapseOnDestruction;
701 }; // class AttributeHandle
702 
703 
705 
706 
708 template <typename ValueType, typename CodecType = UnknownCodec>
709 class AttributeWriteHandle : public AttributeHandle<ValueType, CodecType>
710 {
711 public:
713  using Ptr = std::shared_ptr<Handle>;
714  using ScopedPtr = std::unique_ptr<Handle>;
715 
716  static Ptr create(AttributeArray& array, const bool expand = true);
717 
718  AttributeWriteHandle(AttributeArray& array, const bool expand = true);
719 
720  virtual ~AttributeWriteHandle() = default;
721 
724  void expand(bool fill = true);
725 
727  void collapse();
728  void collapse(const ValueType& uniformValue);
729 
731  bool compact();
732 
735  void fill(const ValueType& value);
736 
737  void set(Index n, const ValueType& value);
738  void set(Index n, Index m, const ValueType& value);
739 
740 private:
741  friend class ::TestAttributeArray;
742 
743  template <bool IsUnknownCodec>
744  typename std::enable_if<IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
745 
746  template <bool IsUnknownCodec>
747  typename std::enable_if<!IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
748 }; // class AttributeWriteHandle
749 
750 
752 
753 
754 // Attribute codec implementation
755 
756 
757 template<typename ValueType>
758 inline void
759 NullCodec::decode(const ValueType& data, ValueType& val)
760 {
761  val = data;
762 }
763 
764 
765 template<typename ValueType>
766 inline void
767 NullCodec::encode(const ValueType& val, ValueType& data)
768 {
769  data = val;
770 }
771 
772 
773 template<typename StorageType, typename ValueType>
774 inline void
775 TruncateCodec::decode(const StorageType& data, ValueType& val)
776 {
777  val = static_cast<ValueType>(data);
778 }
779 
780 
781 template<typename StorageType, typename ValueType>
782 inline void
783 TruncateCodec::encode(const ValueType& val, StorageType& data)
784 {
785  data = static_cast<StorageType>(val);
786 }
787 
788 
789 template <bool OneByte, typename Range>
790 template<typename StorageType, typename ValueType>
791 inline void
792 FixedPointCodec<OneByte, Range>::decode(const StorageType& data, ValueType& val)
793 {
794  val = fixedPointToFloatingPoint<ValueType>(data);
795 
796  // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
797 
798  val = Range::template decode<ValueType>(val);
799 }
800 
801 
802 template <bool OneByte, typename Range>
803 template<typename StorageType, typename ValueType>
804 inline void
805 FixedPointCodec<OneByte, Range>::encode(const ValueType& val, StorageType& data)
806 {
807  // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
808 
809  const ValueType newVal = Range::template encode<ValueType>(val);
810 
811  data = floatingPointToFixedPoint<StorageType>(newVal);
812 }
813 
814 
815 template<typename T>
816 inline void
817 UnitVecCodec::decode(const StorageType& data, math::Vec3<T>& val)
818 {
819  val = math::QuantizedUnitVec::unpack(data);
820 }
821 
822 
823 template<typename T>
824 inline void
825 UnitVecCodec::encode(const math::Vec3<T>& val, StorageType& data)
826 {
827  data = math::QuantizedUnitVec::pack(val);
828 }
829 
830 
832 
833 // TypedAttributeArray implementation
834 
835 template<typename ValueType_, typename Codec_>
836 tbb::atomic<const NamePair*> TypedAttributeArray<ValueType_, Codec_>::sTypeName;
837 
838 
839 template<typename ValueType_, typename Codec_>
841  Index n, Index strideOrTotalSize, bool constantStride, const ValueType& uniformValue)
842  : mData(new StorageType[1])
843  , mSize(n)
844  , mStrideOrTotalSize(strideOrTotalSize)
845  , mIsUniform(true)
846 {
847  if (constantStride) {
848  this->setConstantStride(true);
849  if (strideOrTotalSize == 0) {
850  OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a constant stride requires that " \
851  "stride to be at least one.")
852  }
853  }
854  else {
855  this->setConstantStride(false);
856  if (mStrideOrTotalSize < n) {
857  OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a non-constant stride must have " \
858  "a total size of at least the number of elements in the array.")
859  }
860  }
861  mSize = std::max(Index(1), mSize);
862  mStrideOrTotalSize = std::max(Index(1), mStrideOrTotalSize);
863  Codec::encode(uniformValue, mData.get()[0]);
864 }
865 
866 
867 template<typename ValueType_, typename Codec_>
869  : AttributeArray(rhs)
870  , mSize(rhs.mSize)
871  , mStrideOrTotalSize(rhs.mStrideOrTotalSize)
872  , mIsUniform(rhs.mIsUniform)
873 {
874  // disable uncompress if data is not compressed
875 
876  if (!this->isCompressed()) uncompress = false;
877 
878  if (this->isOutOfCore()) {
879  // do nothing
880  } else if (mIsUniform) {
881  this->allocate();
882  mData.get()[0] = rhs.mData.get()[0];
883  } else if (this->isCompressed()) {
884  std::unique_ptr<char[]> buffer;
885  if (uncompress) {
886  const char* charBuffer = reinterpret_cast<const char*>(rhs.mData.get());
887  size_t uncompressedBytes = compression::bloscUncompressedSize(charBuffer);
888  buffer = compression::bloscDecompress(charBuffer, uncompressedBytes);
889  }
890  if (buffer) {
891  mCompressedBytes = 0;
892  } else {
893  // decompression wasn't requested or failed so deep copy instead
894  buffer.reset(new char[mCompressedBytes]);
895  std::memcpy(buffer.get(), rhs.mData.get(), mCompressedBytes);
896  }
897  assert(buffer);
898  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
899  } else {
900  this->allocate();
901  std::memcpy(mData.get(), rhs.mData.get(), this->arrayMemUsage());
902  }
903 }
904 
905 
906 template<typename ValueType_, typename Codec_>
909 {
910  if (&rhs != this) {
911  tbb::spin_mutex::scoped_lock lock(mMutex);
912 
913  this->deallocate();
914 
915  mFlags = rhs.mFlags;
918  mSize = rhs.mSize;
919  mStrideOrTotalSize = rhs.mStrideOrTotalSize;
920  mIsUniform = rhs.mIsUniform;
921 
922  if (rhs.isOutOfCore()) {
923  mPageHandle = rhs.mPageHandle;
924  } else if (mIsUniform) {
925  this->allocate();
926  mData.get()[0] = rhs.mData.get()[0];
927  } else if (this->isCompressed()) {
928  std::unique_ptr<char[]> buffer(new char[mCompressedBytes]);
929  std::memcpy(buffer.get(), rhs.mData.get(), mCompressedBytes);
930  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
931  } else {
932  this->allocate();
933  std::memcpy(mData.get(), rhs.mData.get(), arrayMemUsage());
934  }
935  }
936 }
937 
938 
939 template<typename ValueType_, typename Codec_>
940 inline const NamePair&
942 {
943  if (sTypeName == nullptr) {
944  NamePair* s = new NamePair(typeNameAsString<ValueType>(), Codec::name());
945  if (sTypeName.compare_and_swap(s, nullptr) != nullptr) delete s;
946  }
947  return *sTypeName;
948 }
949 
950 
951 template<typename ValueType_, typename Codec_>
952 inline bool
954 {
956 }
957 
958 
959 template<typename ValueType_, typename Codec_>
960 inline void
962 {
963  AttributeArray::registerType(TypedAttributeArray::attributeType(), TypedAttributeArray::factory);
964 }
965 
966 
967 template<typename ValueType_, typename Codec_>
968 inline void
970 {
972 }
973 
974 
975 template<typename ValueType_, typename Codec_>
978 {
979  return Ptr(new TypedAttributeArray(n, stride, constantStride));
980 }
981 
982 template<typename ValueType_, typename Codec_>
985 {
986  if (!attributeArray.isType<TypedAttributeArray>()) {
987  OPENVDB_THROW(TypeError, "Invalid Attribute Type");
988  }
989  return static_cast<TypedAttributeArray&>(attributeArray);
990 }
991 
992 template<typename ValueType_, typename Codec_>
995 {
996  if (!attributeArray.isType<TypedAttributeArray>()) {
997  OPENVDB_THROW(TypeError, "Invalid Attribute Type");
998  }
999  return static_cast<const TypedAttributeArray&>(attributeArray);
1000 }
1001 
1002 template<typename ValueType_, typename Codec_>
1005 {
1007 }
1008 
1009 
1010 template<typename ValueType_, typename Codec_>
1013 {
1014  return AttributeArray::Ptr(new TypedAttributeArray<ValueType, Codec>(*this, /*decompress = */true));
1015 }
1016 
1017 
1018 template<typename ValueType_, typename Codec_>
1019 size_t
1021 {
1022  if (this->isOutOfCore()) return 0;
1023  if (this->isCompressed()) return mCompressedBytes;
1024 
1025  return (mIsUniform ? 1 : this->dataSize()) * sizeof(StorageType);
1026 }
1027 
1028 
1029 template<typename ValueType_, typename Codec_>
1030 void
1032 {
1033  assert(!mData);
1034  if (mIsUniform) {
1035  mData.reset(new StorageType[1]);
1036  }
1037  else {
1038  const size_t size(this->dataSize());
1039  assert(size > 0);
1040  mData.reset(new StorageType[size]);
1041  }
1042 }
1043 
1044 
1045 template<typename ValueType_, typename Codec_>
1046 void
1048 {
1049  // detach from file if delay-loaded
1050  if (this->isOutOfCore()) {
1051  this->setOutOfCore(false);
1052  this->mPageHandle.reset();
1053  }
1054  if (mData) mData.reset();
1055 }
1056 
1057 
1058 template<typename ValueType_, typename Codec_>
1059 size_t
1061 {
1062  return sizeof(*this) + (bool(mData) ? this->arrayMemUsage() : 0);
1063 }
1064 
1065 
1066 template<typename ValueType_, typename Codec_>
1069 {
1070  assert(n < this->dataSize());
1071  assert(!this->isOutOfCore());
1072  assert(!this->isCompressed());
1073 
1074  ValueType val;
1075  Codec::decode(/*in=*/mData.get()[mIsUniform ? 0 : n], /*out=*/val);
1076  return val;
1077 }
1078 
1079 
1080 template<typename ValueType_, typename Codec_>
1083 {
1084  if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1085  if (this->isOutOfCore()) this->doLoad();
1086  if (this->isCompressed()) const_cast<TypedAttributeArray*>(this)->decompress();
1087 
1088  return this->getUnsafe(n);
1089 }
1090 
1091 
1092 template<typename ValueType_, typename Codec_>
1093 template<typename T>
1094 void
1096 {
1097  val = static_cast<T>(this->getUnsafe(n));
1098 }
1099 
1100 
1101 template<typename ValueType_, typename Codec_>
1102 template<typename T>
1103 void
1105 {
1106  val = static_cast<T>(this->get(n));
1107 }
1108 
1109 
1110 template<typename ValueType_, typename Codec_>
1113 {
1114  return static_cast<const TypedAttributeArray<ValueType, Codec>*>(array)->getUnsafe(n);
1115 }
1116 
1117 
1118 template<typename ValueType_, typename Codec_>
1119 void
1121 {
1122  assert(n < this->dataSize());
1123  assert(!this->isOutOfCore());
1124  assert(!this->isCompressed());
1125  assert(!this->isUniform());
1126 
1127  // this unsafe method assumes the data is not uniform, however if it is, this redirects the index
1128  // to zero, which is marginally less efficient but ensures not writing to an illegal address
1129 
1130  Codec::encode(/*in=*/val, /*out=*/mData.get()[mIsUniform ? 0 : n]);
1131 }
1132 
1133 
1134 template<typename ValueType_, typename Codec_>
1135 void
1137 {
1138  if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1139  if (this->isOutOfCore()) this->doLoad();
1140  if (this->isCompressed()) this->decompress();
1141  if (this->isUniform()) this->expand();
1142 
1143  this->setUnsafe(n, val);
1144 }
1145 
1146 
1147 template<typename ValueType_, typename Codec_>
1148 template<typename T>
1149 void
1151 {
1152  this->setUnsafe(n, static_cast<ValueType>(val));
1153 }
1154 
1155 
1156 template<typename ValueType_, typename Codec_>
1157 template<typename T>
1158 void
1160 {
1161  this->set(n, static_cast<ValueType>(val));
1162 }
1163 
1164 
1165 template<typename ValueType_, typename Codec_>
1166 void
1168 {
1169  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->setUnsafe(n, value);
1170 }
1171 
1172 
1173 template<typename ValueType_, typename Codec_>
1174 void
1176 {
1177  const TypedAttributeArray& sourceTypedArray = static_cast<const TypedAttributeArray&>(sourceArray);
1178 
1179  ValueType sourceValue;
1180  sourceTypedArray.get(sourceIndex, sourceValue);
1181 
1182  this->set(n, sourceValue);
1183 }
1184 
1185 
1186 template<typename ValueType_, typename Codec_>
1187 void
1189 {
1190  if (!mIsUniform) return;
1191 
1192  const StorageType val = mData.get()[0];
1193 
1194  {
1195  tbb::spin_mutex::scoped_lock lock(mMutex);
1196  this->deallocate();
1197  mIsUniform = false;
1198  this->allocate();
1199  }
1200 
1201  mCompressedBytes = 0;
1202 
1203  if (fill) {
1204  for (Index i = 0; i < this->dataSize(); ++i) mData.get()[i] = val;
1205  }
1206 }
1207 
1208 
1209 template<typename ValueType_, typename Codec_>
1210 bool
1212 {
1213  if (mIsUniform) return true;
1214 
1215  // compaction is not possible if any values are different
1216  const ValueType_ val = this->get(0);
1217  for (Index i = 1; i < this->dataSize(); i++) {
1218  if (!math::isExactlyEqual(this->get(i), val)) return false;
1219  }
1220 
1221  this->collapse(this->get(0));
1222  return true;
1223 }
1224 
1225 
1226 template<typename ValueType_, typename Codec_>
1227 void
1229 {
1230  this->collapse(zeroVal<ValueType>());
1231 }
1232 
1233 
1234 template<typename ValueType_, typename Codec_>
1235 void
1237 {
1238  if (!mIsUniform) {
1239  tbb::spin_mutex::scoped_lock lock(mMutex);
1240  this->deallocate();
1241  mIsUniform = true;
1242  this->allocate();
1243  }
1244  Codec::encode(uniformValue, mData.get()[0]);
1245 }
1246 
1247 
1248 template<typename ValueType_, typename Codec_>
1249 void
1251 {
1252  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->collapse(value);
1253 }
1254 
1255 
1256 template<typename ValueType_, typename Codec_>
1257 void
1259 {
1260  if (this->isOutOfCore()) {
1261  tbb::spin_mutex::scoped_lock lock(mMutex);
1262  this->deallocate();
1263  this->allocate();
1264  }
1265 
1266  const Index size = mIsUniform ? 1 : this->dataSize();
1267  for (Index i = 0; i < size; ++i) {
1268  Codec::encode(value, mData.get()[i]);
1269  }
1270 }
1271 
1272 
1273 template<typename ValueType_, typename Codec_>
1274 void
1276 {
1277  static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->fill(value);
1278 }
1279 
1280 
1281 template<typename ValueType_, typename Codec_>
1282 inline bool
1284 {
1285  if (!compression::bloscCanCompress()) return false;
1286 
1287  if (!mIsUniform && !this->isCompressed()) {
1288 
1289  tbb::spin_mutex::scoped_lock lock(mMutex);
1290 
1291  this->doLoadUnsafe(/*compression=*/false);
1292 
1293  if (this->isCompressed()) return true;
1294 
1295  return this->compressUnsafe();
1296  }
1297 
1298  return false;
1299 }
1300 
1301 
1302 template<typename ValueType_, typename Codec_>
1303 inline bool
1305 {
1306  if (!compression::bloscCanCompress()) return false;
1307  if (mIsUniform) return false;
1308 
1309  // assumes mutex is locked and data is not out-of-core
1310 
1311  const bool writeCompress = (mSerializationFlags & WRITEMEMCOMPRESS);
1312  const size_t inBytes = writeCompress ? mCompressedBytes : this->arrayMemUsage();
1313 
1314  if (inBytes > 0) {
1315  size_t outBytes;
1316  const char* charBuffer = reinterpret_cast<const char*>(mData.get());
1317  std::unique_ptr<char[]> buffer = compression::bloscCompress(charBuffer, inBytes, outBytes);
1318  if (buffer) {
1319  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1320  mCompressedBytes = outBytes;
1321  return true;
1322  }
1323  }
1324 
1325  return false;
1326 }
1327 
1328 
1329 template<typename ValueType_, typename Codec_>
1330 inline bool
1332 {
1333  tbb::spin_mutex::scoped_lock lock(mMutex);
1334 
1335  const bool writeCompress = (mSerializationFlags & WRITEMEMCOMPRESS);
1336 
1337  if (writeCompress) {
1338  this->doLoadUnsafe(/*compression=*/false);
1339  return true;
1340  }
1341 
1342  if (this->isCompressed()) {
1343  this->doLoadUnsafe();
1344  const char* charBuffer = reinterpret_cast<const char*>(this->mData.get());
1345  size_t uncompressedBytes = compression::bloscUncompressedSize(charBuffer);
1346  std::unique_ptr<char[]> buffer = compression::bloscDecompress(charBuffer, uncompressedBytes);
1347  if (buffer) {
1348  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1349  mCompressedBytes = 0;
1350  return true;
1351  }
1352  }
1353 
1354  return false;
1355 }
1356 
1357 
1358 template<typename ValueType_, typename Codec_>
1359 bool
1361 {
1362  return (mFlags & OUTOFCORE);
1363 }
1364 
1365 
1366 template<typename ValueType_, typename Codec_>
1367 void
1369 {
1370  if (b) mFlags = static_cast<uint8_t>(mFlags | OUTOFCORE);
1371  else mFlags = static_cast<uint8_t>(mFlags & ~OUTOFCORE);
1372 }
1373 
1374 
1375 template<typename ValueType_, typename Codec_>
1376 void
1378 {
1379  if (!(this->isOutOfCore())) return;
1380 
1382  const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
1383 
1384  // This lock will be contended at most once, after which this buffer
1385  // will no longer be out-of-core.
1386  tbb::spin_mutex::scoped_lock lock(self->mMutex);
1387  this->doLoadUnsafe();
1388 }
1389 
1390 
1391 template<typename ValueType_, typename Codec_>
1392 void
1394 {
1395  this->doLoad();
1396 }
1397 
1398 
1399 template<typename ValueType_, typename Codec_>
1400 void
1402 {
1403  this->readMetadata(is);
1404  this->readBuffers(is);
1405 }
1406 
1407 
1408 template<typename ValueType_, typename Codec_>
1409 void
1411 {
1412  // read data
1413 
1414  Index64 bytes = Index64(0);
1415  is.read(reinterpret_cast<char*>(&bytes), sizeof(Index64));
1416  bytes = bytes - /*flags*/sizeof(Int16) - /*size*/sizeof(Index);
1417 
1418  uint8_t flags = uint8_t(0);
1419  is.read(reinterpret_cast<char*>(&flags), sizeof(uint8_t));
1420  mFlags = flags;
1421 
1422  uint8_t serializationFlags = uint8_t(0);
1423  is.read(reinterpret_cast<char*>(&serializationFlags), sizeof(uint8_t));
1424  mSerializationFlags = serializationFlags;
1425 
1426  Index size = Index(0);
1427  is.read(reinterpret_cast<char*>(&size), sizeof(Index));
1428  mSize = size;
1429 
1430  // warn if an unknown flag has been set
1431  if (mFlags >= 0x20) {
1432  OPENVDB_LOG_WARN("Unknown attribute flags for VDB file format.");
1433  }
1434  // error if an unknown serialization flag has been set,
1435  // as this will adjust the layout of the data and corrupt the ability to read
1436  if (mSerializationFlags >= 0x10) {
1437  OPENVDB_THROW(IoError, "Unknown attribute serialization flags for VDB file format.");
1438  }
1439 
1440  // read uniform and compressed state
1441 
1442  mIsUniform = mSerializationFlags & WRITEUNIFORM;
1443  mCompressedBytes = bytes;
1444 
1445  // read strided value (set to 1 if array is not strided)
1446 
1448  Index stride = Index(0);
1449  is.read(reinterpret_cast<char*>(&stride), sizeof(Index));
1450  mStrideOrTotalSize = stride;
1451  }
1452  else {
1453  mStrideOrTotalSize = 1;
1454  }
1455 }
1456 
1457 
1458 template<typename ValueType_, typename Codec_>
1459 void
1461 {
1462  if ((mSerializationFlags & WRITEPAGED)) {
1463  // use readBuffers(PagedInputStream&) for paged buffers
1464  OPENVDB_THROW(IoError, "Cannot read paged AttributeArray buffers.");
1465  }
1466 
1467  tbb::spin_mutex::scoped_lock lock(mMutex);
1468 
1469  this->deallocate();
1470 
1471  uint8_t bloscCompressed(0);
1472  if (!mIsUniform) is.read(reinterpret_cast<char*>(&bloscCompressed), sizeof(uint8_t));
1473 
1474  std::unique_ptr<char[]> buffer(new char[mCompressedBytes]);
1475  is.read(buffer.get(), mCompressedBytes);
1476 
1477  if (mIsUniform) {
1478  // zero compressed bytes as uniform values are not compressed in memory
1479  mCompressedBytes = Index64(0);
1480  }
1481  else if (!(mSerializationFlags & WRITEMEMCOMPRESS)) {
1482  // zero compressed bytes if not compressed in memory
1483  mCompressedBytes = Index64(0);
1484  }
1485 
1486  // compressed on-disk
1487 
1488  if (bloscCompressed == uint8_t(1)) {
1489 
1490  // decompress buffer
1491 
1492  const size_t inBytes = this->dataSize() * sizeof(StorageType);
1493  std::unique_ptr<char[]> newBuffer = compression::bloscDecompress(buffer.get(), inBytes);
1494  if (newBuffer) buffer.reset(newBuffer.release());
1495  }
1496 
1497  // set data to buffer
1498 
1499  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1500 
1501  // clear all write flags
1502 
1503  if (mIsUniform) mSerializationFlags &= uint8_t(~WRITEUNIFORM & ~WRITEMEMCOMPRESS & ~WRITEPAGED);
1504  else mSerializationFlags &= uint8_t(~WRITEUNIFORM & ~WRITEPAGED);
1505 }
1506 
1507 
1508 template<typename ValueType_, typename Codec_>
1509 void
1511 {
1512  if (!(mSerializationFlags & WRITEPAGED)) {
1513  if (!is.sizeOnly()) this->readBuffers(is.getInputStream());
1514  return;
1515  }
1516 
1517  // If this array is being read from a memory-mapped file, delay loading of its data
1518  // until the data is actually accessed.
1520  const bool delayLoad = (mappedFile.get() != nullptr);
1521 
1522  if (is.sizeOnly())
1523  {
1525  return;
1526  }
1527 
1528  assert(mPageHandle);
1529 
1530  tbb::spin_mutex::scoped_lock lock(mMutex);
1531 
1532  this->deallocate();
1533 
1534  this->setOutOfCore(delayLoad);
1535  is.read(mPageHandle, mCompressedBytes, delayLoad);
1536 
1537  if (!delayLoad) {
1538  std::unique_ptr<char[]> buffer = mPageHandle->read();
1539  mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1540  }
1541 
1542  // zero compressed bytes as not compressed in memory
1543 
1544  if (mIsUniform) {
1545  // zero compressed bytes as uniform values are not compressed in memory
1547  }
1548  else if (!(mSerializationFlags & WRITEMEMCOMPRESS)) {
1550  }
1551 
1552  // clear all write flags
1553 
1554  if (mIsUniform) mSerializationFlags &= uint8_t(~WRITEUNIFORM & ~WRITEMEMCOMPRESS & ~WRITEPAGED);
1555  else mSerializationFlags &= uint8_t(~WRITEUNIFORM & ~WRITEPAGED);
1556 }
1557 
1558 
1559 template<typename ValueType_, typename Codec_>
1560 void
1562 {
1563  this->write(os, /*outputTransient=*/false);
1564 }
1565 
1566 
1567 template<typename ValueType_, typename Codec_>
1568 void
1569 TypedAttributeArray<ValueType_, Codec_>::write(std::ostream& os, bool outputTransient) const
1570 {
1571  this->writeMetadata(os, outputTransient, /*paged=*/false);
1572  this->writeBuffers(os, outputTransient);
1573 }
1574 
1575 
1576 template<typename ValueType_, typename Codec_>
1577 void
1578 TypedAttributeArray<ValueType_, Codec_>::writeMetadata(std::ostream& os, bool outputTransient, bool paged) const
1579 {
1580  if (!outputTransient && this->isTransient()) return;
1581 
1582  uint8_t flags(mFlags & uint8_t(~OUTOFCORE));
1583  uint8_t serializationFlags(0);
1584  Index size(mSize);
1585  Index stride(mStrideOrTotalSize);
1586  bool strideOfOne(this->stride() == 1);
1587 
1588  bool bloscCompression = io::getDataCompression(os) & io::COMPRESS_BLOSC;
1589 
1590  // any compressed data needs to be loaded if out-of-core
1591  if (bloscCompression || this->isCompressed()) this->doLoad();
1592 
1593  size_t compressedBytes = 0;
1594 
1595  if (!strideOfOne)
1596  {
1597  serializationFlags |= WRITESTRIDED;
1598  }
1599 
1600  if (mIsUniform)
1601  {
1602  serializationFlags |= WRITEUNIFORM;
1603  if (bloscCompression && paged) serializationFlags |= WRITEPAGED;
1604  }
1605  else if (bloscCompression && paged)
1606  {
1607  serializationFlags |= WRITEPAGED;
1608  if (this->isCompressed()) {
1609  serializationFlags |= WRITEMEMCOMPRESS;
1610  const char* charBuffer = reinterpret_cast<const char*>(mData.get());
1611  compressedBytes = compression::bloscUncompressedSize(charBuffer);
1612  }
1613  }
1614  else if (this->isCompressed())
1615  {
1616  serializationFlags |= WRITEMEMCOMPRESS;
1617  compressedBytes = mCompressedBytes;
1618  }
1619  else if (bloscCompression)
1620  {
1621  const char* charBuffer = reinterpret_cast<const char*>(mData.get());
1622  const size_t inBytes = this->arrayMemUsage();
1623  compressedBytes = compression::bloscCompressedSize(charBuffer, inBytes);
1624  }
1625 
1626  Index64 bytes = /*flags*/ sizeof(Int16) + /*size*/ sizeof(Index);
1627 
1628  bytes += (compressedBytes > 0) ? compressedBytes : this->arrayMemUsage();
1629 
1630  // write data
1631 
1632  os.write(reinterpret_cast<const char*>(&bytes), sizeof(Index64));
1633  os.write(reinterpret_cast<const char*>(&flags), sizeof(uint8_t));
1634  os.write(reinterpret_cast<const char*>(&serializationFlags), sizeof(uint8_t));
1635  os.write(reinterpret_cast<const char*>(&size), sizeof(Index));
1636 
1637  // write strided
1638  if (!strideOfOne) os.write(reinterpret_cast<const char*>(&stride), sizeof(Index));
1639 }
1640 
1641 
1642 template<typename ValueType_, typename Codec_>
1643 void
1644 TypedAttributeArray<ValueType_, Codec_>::writeBuffers(std::ostream& os, bool outputTransient) const
1645 {
1646  if (!outputTransient && this->isTransient()) return;
1647 
1648  this->doLoad();
1649 
1650  if (this->isUniform()) {
1651  os.write(reinterpret_cast<const char*>(mData.get()), sizeof(StorageType));
1652  }
1653  else if (this->isCompressed())
1654  {
1655  uint8_t bloscCompressed(0);
1656  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1657  os.write(reinterpret_cast<const char*>(mData.get()), mCompressedBytes);
1658  }
1660  {
1661  std::unique_ptr<char[]> compressedBuffer;
1662  size_t compressedBytes = 0;
1663  const char* charBuffer = reinterpret_cast<const char*>(mData.get());
1664  const size_t inBytes = this->arrayMemUsage();
1665  compressedBuffer = compression::bloscCompress(charBuffer, inBytes, compressedBytes);
1666  if (compressedBuffer) {
1667  uint8_t bloscCompressed(1);
1668  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1669  os.write(reinterpret_cast<const char*>(compressedBuffer.get()), compressedBytes);
1670  }
1671  else {
1672  uint8_t bloscCompressed(0);
1673  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1674  os.write(reinterpret_cast<const char*>(mData.get()), inBytes);
1675  }
1676  }
1677  else
1678  {
1679  uint8_t bloscCompressed(0);
1680  os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1681  os.write(reinterpret_cast<const char*>(mData.get()), this->arrayMemUsage());
1682  }
1683 }
1684 
1685 
1686 template<typename ValueType_, typename Codec_>
1687 void
1689 {
1690  if (!outputTransient && this->isTransient()) return;
1691 
1692  // paged compression only available when Blosc is enabled
1693  bool bloscCompression = io::getDataCompression(os.getOutputStream()) & io::COMPRESS_BLOSC;
1694  if (!bloscCompression) {
1695  if (!os.sizeOnly()) this->writeBuffers(os.getOutputStream(), outputTransient);
1696  return;
1697  }
1698 
1699  this->doLoad();
1700 
1701  const char* buffer;
1702  size_t bytes;
1703 
1704  std::unique_ptr<char[]> uncompressedBuffer;
1705  if (this->isCompressed()) {
1706  // paged streams require uncompressed buffers, so locally decompress
1707 
1708  const char* charBuffer = reinterpret_cast<const char*>(this->mData.get());
1709  bytes = compression::bloscUncompressedSize(charBuffer);
1710  uncompressedBuffer = compression::bloscDecompress(charBuffer, bytes);
1711  buffer = reinterpret_cast<const char*>(uncompressedBuffer.get());
1712  }
1713  else {
1714  buffer = reinterpret_cast<const char*>(mData.get());
1715  bytes = this->arrayMemUsage();
1716  }
1717 
1718  os.write(buffer, bytes);
1719 }
1720 
1721 
1722 template<typename ValueType_, typename Codec_>
1723 void
1724 TypedAttributeArray<ValueType_, Codec_>::doLoadUnsafe(const bool compression) const
1725 {
1726  if (!(this->isOutOfCore())) return;
1727 
1728  // this function expects the mutex to already be locked
1729 
1731 
1732  assert(self->mPageHandle);
1733 
1734  std::unique_ptr<char[]> buffer = self->mPageHandle->read();
1735 
1736  self->mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1737 
1738  self->mPageHandle.reset();
1739 
1740  // if data was compressed prior to being written to disk, re-compress
1741 
1742  if (self->mSerializationFlags & WRITEMEMCOMPRESS) {
1743  if (compression) self->compressUnsafe();
1744  else self->mCompressedBytes = 0;
1745  }
1746 
1747  // clear all write and out-of-core flags
1748 
1749  self->mFlags &= uint8_t(~OUTOFCORE);
1750  self->mSerializationFlags &= uint8_t(~WRITEUNIFORM & ~WRITEMEMCOMPRESS & ~WRITEPAGED);
1751 }
1752 
1753 
1754 template<typename ValueType_, typename Codec_>
1757 {
1758  // use the faster 'unsafe' get and set methods as attribute handles
1759  // ensure data is uncompressed and in-core when constructed
1760 
1766 }
1767 
1768 
1769 template<typename ValueType_, typename Codec_>
1770 bool
1772 {
1773  const TypedAttributeArray<ValueType_, Codec_>* const otherT = dynamic_cast<const TypedAttributeArray<ValueType_, Codec_>* >(&other);
1774  if(!otherT) return false;
1775  if(this->mSize != otherT->mSize ||
1776  this->mStrideOrTotalSize != otherT->mStrideOrTotalSize ||
1777  this->mIsUniform != otherT->mIsUniform ||
1778  *this->sTypeName != *otherT->sTypeName) return false;
1779 
1780  this->doLoad();
1781  otherT->doLoad();
1782 
1783  const StorageType *target = this->mData.get(), *source = otherT->mData.get();
1784  if (!target && !source) return true;
1785  if (!target || !source) return false;
1786  Index n = this->mIsUniform ? 1 : mSize;
1787  while (n && math::isExactlyEqual(*target++, *source++)) --n;
1788  return n == 0;
1789 }
1790 
1792 
1793 
1795 template <typename CodecType, typename ValueType>
1797 {
1798  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
1799  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
1800 
1803  static ValueType get(GetterPtr /*functor*/, const AttributeArray* array, const Index n) {
1805  }
1806 
1809  static void set(SetterPtr /*functor*/, AttributeArray* array, const Index n, const ValueType& value) {
1811  }
1812 };
1813 
1814 
1816 template <typename ValueType>
1818 {
1819  using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
1820  using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
1821 
1823  static ValueType get(GetterPtr functor, const AttributeArray* array, const Index n) {
1824  return (*functor)(array, n);
1825  }
1826 
1828  static void set(SetterPtr functor, AttributeArray* array, const Index n, const ValueType& value) {
1829  (*functor)(array, n, value);
1830  }
1831 };
1832 
1833 
1835 
1836 // AttributeHandle implementation
1837 
1838 template <typename ValueType, typename CodecType>
1840 AttributeHandle<ValueType, CodecType>::create(const AttributeArray& array, const bool preserveCompression)
1841 {
1843  new AttributeHandle<ValueType, CodecType>(array, preserveCompression));
1844 }
1845 
1846 template <typename ValueType, typename CodecType>
1847 AttributeHandle<ValueType, CodecType>::AttributeHandle(const AttributeArray& array, const bool preserveCompression)
1848  : mArray(&array)
1849  , mStrideOrTotalSize(array.hasConstantStride() ? array.stride() : 1)
1850  , mSize(array.hasConstantStride() ? array.size() : array.dataSize())
1851  , mCollapseOnDestruction(preserveCompression && array.isStreaming())
1852 {
1853  if (!this->compatibleType<std::is_same<CodecType, UnknownCodec>::value>()) {
1854  OPENVDB_THROW(TypeError, "Cannot bind handle due to incompatible type of AttributeArray.");
1855  }
1856 
1857  // load data if delay-loaded
1858 
1859  mArray->loadData();
1860 
1861  // if array is compressed and preserve compression is true, copy and decompress
1862  // into a local copy that is destroyed with handle to maintain thread-safety
1863 
1864  if (array.isCompressed())
1865  {
1866  if (preserveCompression && !array.isStreaming()) {
1867  mLocalArray = array.copyUncompressed();
1868  mLocalArray->decompress();
1869  mArray = mLocalArray.get();
1870  }
1871  else {
1872  const_cast<AttributeArray*>(mArray)->decompress();
1873  }
1874  }
1875 
1876  // bind getter and setter methods
1877 
1878  AttributeArray::AccessorBasePtr accessor = mArray->getAccessor();
1879  assert(accessor);
1880 
1881  AttributeArray::Accessor<ValueType>* typedAccessor = static_cast<AttributeArray::Accessor<ValueType>*>(accessor.get());
1882 
1883  mGetter = typedAccessor->mGetter;
1884  mSetter = typedAccessor->mSetter;
1885  mCollapser = typedAccessor->mCollapser;
1886  mFiller = typedAccessor->mFiller;
1887 }
1888 
1889 template <typename ValueType, typename CodecType>
1891 {
1892  // if enabled, attribute is collapsed on destruction of the handle to save memory
1893  if (mCollapseOnDestruction) const_cast<AttributeArray*>(this->mArray)->collapse();
1894 }
1895 
1896 template <typename ValueType, typename CodecType>
1897 template <bool IsUnknownCodec>
1898 typename std::enable_if<IsUnknownCodec, bool>::type
1900 {
1901  // if codec is unknown, just check the value type
1902 
1903  return mArray->hasValueType<ValueType>();
1904 }
1905 
1906 template <typename ValueType, typename CodecType>
1907 template <bool IsUnknownCodec>
1908 typename std::enable_if<!IsUnknownCodec, bool>::type
1910 {
1911  // if the codec is known, check the value type and codec
1912 
1913  return mArray->isType<TypedAttributeArray<ValueType, CodecType>>();
1914 }
1915 
1916 template <typename ValueType, typename CodecType>
1918 {
1919  Index index = n * mStrideOrTotalSize + m;
1920  assert(index < (mSize * mStrideOrTotalSize));
1921  return index;
1922 }
1923 
1924 template <typename ValueType, typename CodecType>
1926 {
1927  return this->get<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m));
1928 }
1929 
1930 template <typename ValueType, typename CodecType>
1931 template <bool IsUnknownCodec>
1932 typename std::enable_if<IsUnknownCodec, ValueType>::type
1934 {
1935  // if the codec is unknown, use the getter functor
1936 
1937  return (*mGetter)(mArray, index);
1938 }
1939 
1940 template <typename ValueType, typename CodecType>
1941 template <bool IsUnknownCodec>
1942 typename std::enable_if<!IsUnknownCodec, ValueType>::type
1944 {
1945  // if the codec is known, call the method on the attribute array directly
1946 
1948 }
1949 
1950 template <typename ValueType, typename CodecType>
1952 {
1953  return mArray->isUniform();
1954 }
1955 
1956 template <typename ValueType, typename CodecType>
1958 {
1959  return mArray->hasConstantStride();
1960 }
1961 
1963 
1964 // AttributeWriteHandle implementation
1965 
1966 template <typename ValueType, typename CodecType>
1969 {
1971  new AttributeWriteHandle<ValueType, CodecType>(array, expand));
1972 }
1973 
1974 template <typename ValueType, typename CodecType>
1976  : AttributeHandle<ValueType, CodecType>(array, /*preserveCompression = */ false)
1977 {
1978  if (expand) array.expand();
1979 }
1980 
1981 template <typename ValueType, typename CodecType>
1983 {
1984  this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, 0), value);
1985 }
1986 
1987 template <typename ValueType, typename CodecType>
1989 {
1990  this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m), value);
1991 }
1992 
1993 template <typename ValueType, typename CodecType>
1995 {
1996  const_cast<AttributeArray*>(this->mArray)->expand(fill);
1997 }
1998 
1999 template <typename ValueType, typename CodecType>
2001 {
2002  const_cast<AttributeArray*>(this->mArray)->collapse();
2003 }
2004 
2005 template <typename ValueType, typename CodecType>
2007 {
2008  return const_cast<AttributeArray*>(this->mArray)->compact();
2009 }
2010 
2011 template <typename ValueType, typename CodecType>
2012 void AttributeWriteHandle<ValueType, CodecType>::collapse(const ValueType& uniformValue)
2013 {
2014  this->mCollapser(const_cast<AttributeArray*>(this->mArray), uniformValue);
2015 }
2016 
2017 template <typename ValueType, typename CodecType>
2019 {
2020  this->mFiller(const_cast<AttributeArray*>(this->mArray), value);
2021 }
2022 
2023 template <typename ValueType, typename CodecType>
2024 template <bool IsUnknownCodec>
2025 typename std::enable_if<IsUnknownCodec, void>::type
2026 AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2027 {
2028  // if the codec is unknown, use the setter functor
2029 
2030  (*this->mSetter)(const_cast<AttributeArray*>(this->mArray), index, value);
2031 }
2032 
2033 template <typename ValueType, typename CodecType>
2034 template <bool IsUnknownCodec>
2035 typename std::enable_if<!IsUnknownCodec, void>::type
2036 AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2037 {
2038  // if the codec is known, call the method on the attribute array directly
2039 
2040  TypedAttributeArray<ValueType, CodecType>::setUnsafe(const_cast<AttributeArray*>(this->mArray), index, value);
2041 }
2042 
2043 
2044 } // namespace points
2045 } // namespace OPENVDB_VERSION_NAME
2046 } // namespace openvdb
2047 
2048 #endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
2049 
2050 // Copyright (c) 2012-2017 DreamWorks Animation LLC
2051 // All rights reserved. This software is distributed under the
2052 // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )
T(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:316
std::shared_ptr< Handle > Ptr
Definition: AttributeArray.h:713
Definition: Compression.h:81
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:1820
#define OPENVDB_API
Helper macros for defining library symbol visibility.
Definition: Platform.h:194
bool isStreaming() const
Return true if this attribute is in streaming mode.
Definition: AttributeArray.h:233
static const char * name()
Definition: AttributeArray.h:388
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:1798
IntegerVectorT floatingPointToFixedPoint(const math::Vec3< FloatT > &v)
Definition: AttributeArray.h:95
Definition: Mat.h:162
ValuePtr mFiller
Definition: AttributeArray.h:678
bool isTransient() const
Return true if this attribute is not serialized during stream output.
Definition: AttributeArray.h:225
bool hasValueType() const
Return true if this attribute has a value type the same as the template parameter.
Definition: AttributeArray.h:190
data is marked as uniform when written
Definition: AttributeArray.h:138
void writePagedBuffers(compression::PagedOutputStream &os, bool outputTransient) const override
Definition: AttributeArray.h:1688
void readBuffers(std::istream &) override
Read attribute buffers from a stream.
Definition: AttributeArray.h:1460
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...
bool operator!=(const AttributeArray &other) const
Definition: AttributeArray.h:275
Definition: AttributeArray.h:640
bool sizeOnly() const
Definition: StreamCompression.h:236
Definition: AttributeArray.h:424
Flag
Definition: AttributeArray.h:127
SetterPtr mSetter
Definition: AttributeArray.h:676
void(*)(AttributeArray *array, const StringIndexType &value) ValuePtr
Definition: AttributeArray.h:650
Definition: AttributeArray.h:366
ValueType get(Index n) const
Return the value at index n.
Definition: AttributeArray.h:1082
Index stride() const
Definition: AttributeArray.h:662
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.
T & z()
Definition: Vec3.h:111
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:101
const AttributeArray * mArray
Definition: AttributeArray.h:673
Definition: AttributeArray.h:360
void(*)(AttributeArray *array, const T &value) ValuePtr
Definition: AttributeArray.h:318
data is marked as compressed in-memory when written
Definition: AttributeArray.h:139
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
Definition: Vec3.h:502
size_t mCompressedBytes
Definition: AttributeArray.h:296
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:977
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:840
void set(Index n, const ValueType &value)
Set value at the given index n.
Definition: AttributeArray.h:1136
virtual void expand(bool fill=true)=0
If this array is uniform, replace it with an array of length size().
compression::PageHandle::Ptr mPageHandle
used for out-of-core, paged reading
Definition: AttributeArray.h:301
uint16_t StorageType
Definition: AttributeArray.h:421
uint8_t flags() const
Retrieve the attribute array flags.
Definition: AttributeArray.h:239
SerializationFlag
Definition: AttributeArray.h:135
Accessor to call unsafe get and set methods based on templated Codec and Value.
Definition: AttributeArray.h:1796
void readPagedBuffers(compression::PagedInputStream &) override
Read attribute buffers from a paged stream.
Definition: AttributeArray.h:1510
static void unregisterType(const NamePair &type)
Remove a attribute type from the registry.
std::shared_ptr< PageHandle > Ptr
Definition: StreamCompression.h:197
typename attribute_traits::UIntTypeTrait< OneByte, T >::Type Type
Definition: AttributeArray.h:407
void expand(bool fill=true) override
Replace the single value storage with an array of length size().
Definition: AttributeArray.h:1188
bool isCompressed() const
Return true if this array is compressed.
Definition: AttributeArray.h:206
static bool isRegistered(const NamePair &type)
Return true if the given attribute type name is registered.
data is marked as strided when written
Definition: AttributeArray.h:137
bool sizeOnly() const
Definition: StreamCompression.h:273
Accessor base class for AttributeArray storage where type is not available.
Definition: AttributeArray.h:309
static ValueType encode(const ValueType &value)
Definition: AttributeArray.h:389
ValuePtr mCollapser
Definition: AttributeArray.h:325
SharedPtr< MappedFile > Ptr
Definition: io.h:152
static Ptr create(const AttributeArray &array, const bool preserveCompression=true)
Definition: AttributeArray.h:1840
bool hasConstantStride() const
Definition: AttributeArray.h:1957
bool decompress() override
Uncompress the attribute array.
Definition: AttributeArray.h:1331
bool isOutOfCore() const
Return true if this buffer&#39;s values have not yet been read from disk.
Definition: AttributeArray.h:1360
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.
const NamePair & type() const override
Return the name of this attribute&#39;s type.
Definition: AttributeArray.h:481
Write-able version of AttributeHandle.
Definition: AttributeArray.h:709
Base class for storing attribute data.
Definition: AttributeArray.h:118
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:1819
hidden from UIs or iterators
Definition: AttributeArray.h:130
Convenience wrappers to using Blosc and reading and writing of Paged data.
static bool isRegistered()
Return true if this attribute type is registered.
Definition: AttributeArray.h:953
A Paging wrapper to std::ostream that is responsible for writing from a given output stream at interv...
Definition: StreamCompression.h:262
std::istream & getInputStream()
Definition: StreamCompression.h:239
void readMetadata(std::istream &) override
Read attribute metadata from a stream.
Definition: AttributeArray.h:1410
void(*)(AttributeArray *array, const Index n, const T &value) SetterPtr
Definition: AttributeArray.h:317
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & min(const T &a, const T &b)
Definition: Composite.h:128
#define OPENVDB_VERSION_NAME
Definition: version.h:43
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.
Definition: AttributeArray.h:363
ValueType_ ValueType
Definition: AttributeArray.h:443
Definition: AttributeArray.h:404
AttributeHandle(const AttributeArray &array, const bool preserveCompression=true)
Definition: AttributeArray.h:1847
FloatVectorT fixedPointToFloatingPoint(const math::Vec3< IntegerT > &v)
Definition: AttributeArray.h:105
Definition: Exceptions.h:91
virtual AttributeArray::Ptr copyUncompressed() const =0
Return an uncompressed copy of this attribute (will return a copy if not compressed).
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form &#39;someVar << "some text" << ...&#39;.
Definition: logging.h:278
size_t memUsage() const override
Return the number of bytes of memory used by this attribute.
Definition: AttributeArray.h:1060
Codec_ Codec
Definition: AttributeArray.h:444
typename Codec::template Storage< ValueType >::Type StorageType
Definition: AttributeArray.h:445
std::shared_ptr< TypedAttributeArray > Ptr
Definition: AttributeArray.h:440
static const char * name()
Definition: AttributeArray.h:428
PagedOutputStream & write(const char *str, std::streamsize n)
Writes the given.
static const char * name()
Definition: AttributeArray.h:381
std::shared_ptr< const AttributeArray > ConstPtr
Definition: AttributeArray.h:143
OPENVDB_API size_t bloscCompressedSize(const char *buffer, const size_t uncompressedBytes)
Convenience wrapper to retrieve the compressed size of buffer when compressed.
bool hasConstantStride() const
Return true if this attribute has a constant stride.
Definition: AttributeArray.h:236
StringIndexType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition: AttributeArray.h:648
Index size() const
Definition: AttributeArray.h:663
void writeBuffers(std::ostream &os, bool outputTransient) const override
Definition: AttributeArray.h:1644
Definition: AttributeArray.h:377
std::pair< Name, Name > NamePair
Definition: AttributeArray.h:65
void collapse() override
Replace the existing array with a uniform zero value.
Definition: AttributeArray.h:1228
AttributeArray::Ptr copy() const override
Return a copy of this attribute.
Definition: AttributeArray.h:1004
Definition: Exceptions.h:39
static TypedAttributeArray & cast(AttributeArray &attributeArray)
Cast an AttributeArray to TypedAttributeArray<T>
Definition: AttributeArray.h:984
Typed class for storing attribute data.
Definition: AttributeArray.h:437
OPENVDB_API size_t bloscUncompressedSize(const char *buffer)
Retrieves the uncompressed size of buffer when uncompressed.
A Paging wrapper to std::istream that is responsible for reading from a given input stream and creati...
Definition: StreamCompression.h:225
const boost::disable_if_c< VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:132
bool compact() override
Compact the existing array to become uniform if all values are identical.
Definition: AttributeArray.h:1211
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition: Vec3.h:109
std::shared_ptr< AccessorBase > AccessorBasePtr
Definition: AttributeArray.h:124
static ValueType decode(const ValueType &value)
Definition: AttributeArray.h:390
Index stride() const override
Definition: AttributeArray.h:495
Index Iterators.
TypedAttributeArray & operator=(const TypedAttributeArray &)
Deep copy assignment operator.
Definition: AttributeArray.h:908
T & y()
Definition: Vec3.h:110
static void registerType()
Register this attribute type along with a factory function.
Definition: AttributeArray.h:961
bool isHidden() const
Return true if this attribute is hidden (e.g., from UI or iterators).
Definition: AttributeArray.h:218
virtual AccessorBasePtr getAccessor() const =0
Obtain an Accessor that stores getter and setter functors.
typename attribute_traits::TruncateTrait< T >::Type Type
Definition: AttributeArray.h:377
static const char * name()
Definition: AttributeArray.h:412
uint8_t mSerializationFlags
Definition: AttributeArray.h:298
void(*)(AttributeArray *array, const Index n, const StringIndexType &value) SetterPtr
Definition: AttributeArray.h:649
void writeMetadata(std::ostream &os, bool outputTransient, bool paged) const override
Definition: AttributeArray.h:1578
Definition: Exceptions.h:92
GetterPtr mGetter
Definition: AttributeArray.h:675
std::shared_ptr< AttributeArray > Ptr
Definition: AttributeArray.h:142
Index size() const override
Return the number of elements in this array.
Definition: AttributeArray.h:491
static void registerType(const NamePair &type, FactoryMethod)
Register a attribute type along with a factory function.
uint64_t Index64
Definition: Types.h:56
int16_t Int16
Definition: Types.h:58
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition: Math.h:407
Definition: Exceptions.h:85
std::string Name
Definition: Name.h:44
ValuePtr mCollapser
Definition: AttributeArray.h:677
Definition: AttributeArray.h:395
bool compress() override
Compress the attribute array.
Definition: AttributeArray.h:1283
Ptr(*)(Index, Index, bool) FactoryMethod
Definition: AttributeArray.h:145
virtual ~TypedAttributeArray()
Definition: AttributeArray.h:461
AttributeArray::Ptr copyUncompressed() const override
Return an uncompressed copy of this attribute (will just return a copy if not compressed).
Definition: AttributeArray.h:1012
SetterPtr mSetter
Definition: AttributeArray.h:324
uint8_t mFlags
Definition: AttributeArray.h:297
void setUnsafe(Index n, const ValueType &value)
Set value at the given index n (assumes uncompressed and in-core)
Definition: AttributeArray.h:1120
AccessorBasePtr getAccessor() const override
Obtain an Accessor that stores getter and setter functors.
Definition: AttributeArray.h:1756
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition: AttributeArray.h:1799
void loadData() const override
Ensures all data is in-core.
Definition: AttributeArray.h:1393
static const char * name()
Definition: AttributeArray.h:397
Definition: Exceptions.h:84
Index dataSize() const override
Return the size of the data in this array.
Definition: AttributeArray.h:498
StorageType Type
Definition: AttributeArray.h:424
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...
Definition: AttributeArray.h:374
static void unregisterType()
Remove this attribute type from the registry.
Definition: AttributeArray.h:969
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
std::ostream & getOutputStream()
Set and get the output stream.
Definition: StreamCompression.h:276
bool isUniform() const
Definition: AttributeArray.h:1951
static ValueType decode(const ValueType &value)
Definition: AttributeArray.h:399
void read(std::istream &) override
Read attribute data from a stream.
Definition: AttributeArray.h:1401
Index32 Index
Definition: Types.h:57
ValueType getUnsafe(Index n) const
Return the value at index n (assumes uncompressed and in-core)
Definition: AttributeArray.h:1068
T Type
Definition: AttributeArray.h:366
OPENVDB_API bool bloscCanCompress()
Returns true if compression is available.
static const char * name()
Definition: AttributeArray.h:370
PageHandle::Ptr createHandle(std::streamsize n)
Creates a PageHandle to access the next.
static ValueType encode(const ValueType &value)
Definition: AttributeArray.h:398
void setConstantStride(bool state)
Specify whether this attribute has a constant stride or not.
bool isType() const
Return true if this attribute is of the same type as the template parameter.
Definition: AttributeArray.h:186
bool isUniform() const override
Return true if this array is stored as a single uniform value.
Definition: AttributeArray.h:535
ValuePtr mFiller
Definition: AttributeArray.h:326
Definition: AttributeArray.h:386
Definition: AttributeArray.h:419
static const NamePair & attributeType()
Return the name of this attribute&#39;s type (includes codec)
Definition: AttributeArray.h:941
Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler)
Definition: AttributeArray.h:320
GetterPtr mGetter
Definition: AttributeArray.h:323
void fill(const ValueType &value)
Fill the existing array with the given value.
Definition: AttributeArray.h:1258
void write(std::ostream &os, bool outputTransient) const override
Definition: AttributeArray.h:1569