OpenVDB 14.0.0
Loading...
Searching...
No Matches
AttributeArray.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/// @file points/AttributeArray.h
5///
6/// @authors Dan Bailey, Mihai Alden, Nick Avramoussis, James Bird, Khang Ngo
7///
8/// @brief Attribute Array storage templated on type and compression codec.
9
10#ifndef OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
11#define OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
12
13#include <openvdb/Types.h>
15#include <openvdb/util/Name.h>
17#include <openvdb/util/Assert.h>
18#include <openvdb/io/io.h>
19#include <openvdb/io/Compression.h> // COMPRESS_BLOSC
20
21#include "IndexIterator.h"
22#include "StreamCompression.h"
23
24#include <tbb/spin_mutex.h>
25#include <atomic>
26
27#include <memory>
28#include <mutex>
29#include <string>
30#include <type_traits>
31
32
33class TestAttributeArray;
34
35namespace openvdb {
37namespace OPENVDB_VERSION_NAME {
38
39
40using NamePair = std::pair<Name, Name>;
41
42namespace points {
43
44
45////////////////////////////////////////
46
47// Utility methods
48
49template <typename IntegerT, typename FloatT>
50inline IntegerT
52{
53 static_assert(std::is_unsigned<IntegerT>::value, "IntegerT must be unsigned");
54 if (FloatT(0.0) > s) return std::numeric_limits<IntegerT>::min();
55 else if (FloatT(1.0) <= s) return std::numeric_limits<IntegerT>::max();
56 return IntegerT(s * FloatT(std::numeric_limits<IntegerT>::max()));
57}
58
59
60template <typename FloatT, typename IntegerT>
61inline FloatT
63{
64 static_assert(std::is_unsigned<IntegerT>::value, "IntegerT must be unsigned");
65 return FloatT(s) / FloatT((std::numeric_limits<IntegerT>::max()));
66}
67
68template <typename IntegerVectorT, typename FloatT>
69inline IntegerVectorT
77
78template <typename FloatVectorT, typename IntegerT>
79inline FloatVectorT
87
88
89////////////////////////////////////////
90
91
92/// Base class for storing attribute data
94{
95protected:
96 struct AccessorBase;
97 template <typename T> struct Accessor;
98
99 using AccessorBasePtr = std::shared_ptr<AccessorBase>;
100
101public:
102 enum Flag {
103 TRANSIENT = 0x1, /// by default not written to disk
104 HIDDEN = 0x2, /// hidden from UIs or iterators
105 CONSTANTSTRIDE = 0x8, /// stride size does not vary in the array
106 STREAMING = 0x10, /// streaming mode collapses attributes when first accessed
107 PARTIALREAD = 0x20 /// data has been partially read (compressed bytes is used)
108 };
109
111 WRITESTRIDED = 0x1, /// data is marked as strided when written
112 WRITEUNIFORM = 0x2, /// data is marked as uniform when written
113 WRITEMEMCOMPRESS = 0x4, /// data is marked as compressed in-memory when written
114 /// (deprecated flag as of ABI=6)
115 WRITEPAGED = 0x8 /// data is written out in pages
116 };
117
118 // Scoped Lock wrapper class that locks the AttributeArray registry mutex
120 {
121 tbb::spin_mutex::scoped_lock lock;
122 public:
124 }; // class ScopedRegistryLock
125
126 using Ptr = std::shared_ptr<AttributeArray>;
127 using ConstPtr = std::shared_ptr<const AttributeArray>;
128
129 using FactoryMethod = Ptr (*)(Index, Index, bool, const Metadata*);
130
131 template <typename ValueType, typename CodecType> friend class AttributeHandle;
132
135 {
136 // if this AttributeArray has been partially read, zero the compressed bytes,
137 // so the page handle won't attempt to clean up invalid memory
139 }
144
145 /// Return a copy of this attribute.
146 virtual AttributeArray::Ptr copy() const = 0;
147
148 /// Return the number of elements in this array.
149 /// @note This does not count each data element in a strided array
150 virtual Index size() const = 0;
151
152 /// Return the stride of this array.
153 /// @note a return value of zero means a non-constant stride
154 virtual Index stride() const = 0;
155
156 /// Return the total number of data elements in this array.
157 /// @note This counts each data element in a strided array
158 virtual Index dataSize() const = 0;
159
160 /// Return the name of the value type of a single element in this array (e.g., "float" or "vec3d").
161 virtual Name valueType() const = 0;
162
163 /// Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
164 virtual Name codecType() const = 0;
165
166 /// Return the size in bytes of the value type of a single element in this array.
167 /// (e.g. "float" -> 4 bytes, "vec3d" -> 24 bytes").
168 virtual Index valueTypeSize() const = 0;
169
170 /// Return the size in bytes of the storage type of a single element of this array.
171 /// @note If the Codec is a NullCodec, valueSize() == storageSize()
172 virtual Index storageTypeSize() const = 0;
173
174 /// Return @c true if the value type is floating point
175 virtual bool valueTypeIsFloatingPoint() const = 0;
176
177 /// Return @c true if the value type is a class (ie vector, matrix or quaternion return true)
178 virtual bool valueTypeIsClass() const = 0;
179
180 /// Return @c true if the value type is a vector
181 virtual bool valueTypeIsVector() const = 0;
182
183 /// Return @c true if the value type is a quaternion
184 virtual bool valueTypeIsQuaternion() const = 0;
185
186 /// Return @c true if the value type is a matrix
187 virtual bool valueTypeIsMatrix() const = 0;
188
189 /// Return the number of bytes of memory used by this attribute.
190 virtual size_t memUsage() const = 0;
191
192#if OPENVDB_ABI_VERSION_NUMBER < 14
193 OPENVDB_DEPRECATED_MESSAGE("Use memUsage() instead. This method is deprecated and will be removed. Delayed loading is no longer supported.")
194 virtual size_t memUsageIfLoaded() const = 0;
195#endif // OPENVDB_ABI_VERSION_NUMBER < 14
196
197 /// Create a new attribute array of the given (registered) type, length and stride.
198 /// @details If @a lock is non-null, the AttributeArray registry mutex
199 /// has already been locked
200 static Ptr create(const NamePair& type, Index length, Index stride = 1,
201 bool constantStride = true,
202 const Metadata* metadata = nullptr,
203 const ScopedRegistryLock* lock = nullptr);
204
205 /// Return @c true if the given attribute type name is registered.
206 static bool isRegistered(const NamePair& type, const ScopedRegistryLock* lock = nullptr);
207 /// Clear the attribute type registry.
208 static void clearRegistry(const ScopedRegistryLock* lock = nullptr);
209
210 /// Return the name of this attribute's type.
211 virtual const NamePair& type() const = 0;
212 /// Return @c true if this attribute is of the same type as the template parameter.
213 template<typename AttributeArrayType>
214 bool isType() const { return this->type() == AttributeArrayType::attributeType(); }
215
216 /// Return @c true if this attribute has a value type the same as the template parameter
217 template<typename ValueType>
218 bool hasValueType() const { return this->type().first == typeNameAsString<ValueType>(); }
219
220 /// @brief Copy values into this array from a source array to a target array
221 /// as referenced by an iterator.
222 /// @details Iterators must adhere to the ForwardIterator interface described
223 /// in the example below:
224 /// @code
225 /// struct MyIterator
226 /// {
227 /// // returns true if the iterator is referencing valid copying indices
228 /// operator bool() const;
229 /// // increments the iterator
230 /// MyIterator& operator++();
231 /// // returns the source index that the iterator is referencing for copying
232 /// Index sourceIndex() const;
233 /// // returns the target index that the iterator is referencing for copying
234 /// Index targetIndex() const;
235 /// };
236 /// @endcode
237 /// @note It is assumed that the strided storage sizes match, the arrays are both in-core,
238 /// and both value types are floating-point or both integer.
239 /// @note It is possible to use this method to write to a uniform target array
240 /// if the iterator does not have non-zero target indices.
241 /// @note This method is not thread-safe, it must be guaranteed that this array is not
242 /// concurrently modified by another thread and that the source array is also not modified.
243 template<typename IterT>
244 void copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter);
245 /// @brief Like copyValuesUnsafe(), but if @a compact is true, attempt to collapse this array.
246 /// @note This method is not thread-safe, it must be guaranteed that this array is not
247 /// concurrently modified by another thread and that the source array is also not modified.
248 template<typename IterT>
249 void copyValues(const AttributeArray& sourceArray, const IterT& iter, bool compact = true);
250
251 /// Return @c true if this array is stored as a single uniform value.
252 virtual bool isUniform() const = 0;
253 /// @brief If this array is uniform, replace it with an array of length size().
254 /// @param fill if true, assign the uniform value to each element of the array.
255 virtual void expand(bool fill = true) = 0;
256 /// Replace the existing array with a uniform zero value.
257 virtual void collapse() = 0;
258 /// Compact the existing array to become uniform if all values are identical
259 virtual bool compact() = 0;
260
261 /// @brief Specify whether this attribute should be hidden (e.g., from UI or iterators).
262 /// @details This is useful if the attribute is used for blind data or as scratch space
263 /// for a calculation.
264 /// @note Attributes are not hidden by default.
265 void setHidden(bool state);
266 /// Return @c true if this attribute is hidden (e.g., from UI or iterators).
267 bool isHidden() const { return bool(mFlags & HIDDEN); }
268
269 /// @brief Specify whether this attribute should only exist in memory
270 /// and not be serialized during stream output.
271 /// @note Attributes are not transient by default.
272 void setTransient(bool state);
273 /// Return @c true if this attribute is not serialized during stream output.
274 bool isTransient() const { return bool(mFlags & TRANSIENT); }
275
276 /// @brief Specify whether this attribute is to be streamed off disk, in which
277 /// case, the attributes are collapsed after being first loaded leaving them
278 /// in a destroyed state.
279 /// @note This operation is not thread-safe.
280 void setStreaming(bool state);
281 /// Return @c true if this attribute is in streaming mode.
282 bool isStreaming() const { return bool(mFlags & STREAMING); }
283
284 /// Return @c true if this attribute has a constant stride
285 bool hasConstantStride() const { return bool(mFlags & CONSTANTSTRIDE); }
286
287 /// @brief Retrieve the attribute array flags
288 uint8_t flags() const { return mFlags; }
289
290 /// Read attribute metadata and buffers from a stream.
291 virtual void read(std::istream&) = 0;
292 /// Write attribute metadata and buffers to a stream.
293 /// @param outputTransient if true, write out transient attributes
294 virtual void write(std::ostream&, bool outputTransient) const = 0;
295 /// Write attribute metadata and buffers to a stream, don't write transient attributes.
296 virtual void write(std::ostream&) const = 0;
297
298 /// Read attribute metadata from a stream.
299 virtual void readMetadata(std::istream&) = 0;
300 /// Write attribute metadata to a stream.
301 /// @param outputTransient if true, write out transient attributes
302 /// @param paged if true, data is written out in pages
303 virtual void writeMetadata(std::ostream&, bool outputTransient, bool paged) const = 0;
304
305 /// Read attribute buffers from a stream.
306 virtual void readBuffers(std::istream&) = 0;
307 /// Write attribute buffers to a stream.
308 /// @param outputTransient if true, write out transient attributes
309 virtual void writeBuffers(std::ostream&, bool outputTransient) const = 0;
310
311 /// Read attribute buffers from a paged stream.
313 /// Skip attribute buffers in a paged stream without reading or
314 /// allocating any data.
316 /// Write attribute buffers to a paged stream.
317 /// @param outputTransient if true, write out transient attributes
318 virtual void writePagedBuffers(compression::PagedOutputStream&, bool outputTransient) const = 0;
319
320#if OPENVDB_ABI_VERSION_NUMBER < 14
321 OPENVDB_DEPRECATED_MESSAGE("This method is deprecated and will be removed. Delayed loading is no longer supported.")
322 virtual void loadData() const = 0;
323
324 OPENVDB_DEPRECATED_MESSAGE("This method is deprecated and will be removed. Delayed loading is no longer supported.")
325 virtual bool isDataLoaded() const = 0;
326#endif // OPENVDB_ABI_VERSION_NUMBER < 14
327
328 /// Check the compressed bytes and flags. If they are equal, perform a deeper
329 /// comparison check necessary on the inherited types (TypedAttributeArray)
330 /// Requires non operator implementation due to inheritance
331 bool operator==(const AttributeArray& other) const;
332 bool operator!=(const AttributeArray& other) const { return !this->operator==(other); }
333
334 /// Indirect virtual function to retrieve the data buffer cast to a char byte array
335 const char* constDataAsByteArray() const { return this->dataAsByteArray(); }
336
337private:
338 friend class ::TestAttributeArray;
339
340 /// Virtual function used by the comparison operator to perform
341 /// comparisons on inherited types
342 virtual bool isEqual(const AttributeArray& other) const = 0;
343
344 /// Virtual function to retrieve the data buffer cast to a char byte array
345 virtual char* dataAsByteArray() = 0;
346 virtual const char* dataAsByteArray() const = 0;
347
348 /// Private implementation for copyValues/copyValuesUnsafe
349 template <typename IterT>
350 void doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
351 bool rangeChecking = true);
352
353protected:
354 AttributeArray(const AttributeArray& rhs, const tbb::spin_mutex::scoped_lock&);
355
356 /// @brief Specify whether this attribute has a constant stride or not.
357 void setConstantStride(bool state);
358
359 /// Obtain an Accessor that stores getter and setter functors.
360 virtual AccessorBasePtr getAccessor() const = 0;
361
362 /// Register a attribute type along with a factory function.
364 const ScopedRegistryLock* lock = nullptr);
365 /// Remove a attribute type from the registry.
366 static void unregisterType(const NamePair& type,
367 const ScopedRegistryLock* lock = nullptr);
368
369 bool mIsUniform = true;
370 mutable tbb::spin_mutex mMutex;
371 uint8_t mFlags = 0;
372 uint8_t mUsePagedRead = 0;
373#if OPENVDB_ABI_VERSION_NUMBER < 14
374 std::atomic<Index32> mOutOfCore{0}; // interpreted as bool
375#endif
376 /// used for out-of-core, paged reading
377 union {
378 std::unique_ptr<compression::PageHandle> mPageHandle;
380 };
381}; // class AttributeArray
382
383
384////////////////////////////////////////
385
386
387/// Accessor base class for AttributeArray storage where type is not available
388struct AttributeArray::AccessorBase { virtual ~AccessorBase() = default; };
389
390/// Templated Accessor stores typed function pointers used in binding
391/// AttributeHandles
392template <typename T>
394{
395 using GetterPtr = T (*)(const AttributeArray* array, const Index n);
396 using SetterPtr = void (*)(AttributeArray* array, const Index n, const T& value);
397 using ValuePtr = void (*)(AttributeArray* array, const T& value);
398
399 Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler) :
400 mGetter(getter), mSetter(setter), mCollapser(collapser), mFiller(filler) { }
401
406}; // struct AttributeArray::Accessor
407
408
409////////////////////////////////////////
410
411
413{
414 template <typename T> struct TruncateTrait { };
415 template <> struct TruncateTrait<float> { using Type = math::half; };
416 template <> struct TruncateTrait<int> { using Type = short; };
417
418 template <typename T> struct TruncateTrait<math::Vec3<T>> {
420 };
421
422 template <bool OneByte, typename T> struct UIntTypeTrait { };
423 template<typename T> struct UIntTypeTrait</*OneByte=*/true, T> { using Type = uint8_t; };
424 template<typename T> struct UIntTypeTrait</*OneByte=*/false, T> { using Type = uint16_t; };
425 template<typename T> struct UIntTypeTrait</*OneByte=*/true, math::Vec3<T>> {
427 };
428 template<typename T> struct UIntTypeTrait</*OneByte=*/false, math::Vec3<T>> {
430 };
431}
432
433
434////////////////////////////////////////
435
436
437// Attribute codec schemes
438
439struct UnknownCodec { };
440
441
443{
444 template <typename T>
445 struct Storage { using Type = T; };
446
447 template<typename ValueType> static void decode(const ValueType&, ValueType&);
448 template<typename ValueType> static void encode(const ValueType&, ValueType&);
449 static const char* name() { return "null"; }
450};
451
452
454{
455 template <typename T>
457
458 template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
459 template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
460 static const char* name() { return "trnc"; }
461};
462
463
464// Fixed-point codec range for voxel-space positions [-0.5,0.5]
466{
467 static const char* name() { return "fxpt"; }
468 template <typename ValueType> static ValueType encode(const ValueType& value) { return value + ValueType(0.5); }
469 template <typename ValueType> static ValueType decode(const ValueType& value) { return value - ValueType(0.5); }
470};
471
472
473// Fixed-point codec range for unsigned values in the unit range [0.0,1.0]
475{
476 static const char* name() { return "ufxpt"; }
477 template <typename ValueType> static ValueType encode(const ValueType& value) { return value; }
478 template <typename ValueType> static ValueType decode(const ValueType& value) { return value; }
479};
480
481
482template <bool OneByte, typename Range=PositionRange>
484{
485 template <typename T>
487
488 template<typename StorageType, typename ValueType> static void decode(const StorageType&, ValueType&);
489 template<typename StorageType, typename ValueType> static void encode(const ValueType&, StorageType&);
490
491 static const char* name() {
492 static const std::string Name = std::string(Range::name()) + (OneByte ? "8" : "16");
493 return Name.c_str();
494 }
495};
496
497
499{
500 using StorageType = uint16_t;
501
502 template <typename T>
503 struct Storage { using Type = StorageType; };
504
505 template<typename T> static void decode(const StorageType&, math::Vec3<T>&);
506 template<typename T> static void encode(const math::Vec3<T>&, StorageType&);
507 static const char* name() { return "uvec"; }
508};
509
510
511////////////////////////////////////////
512
513
514/// Typed class for storing attribute data
515
516template<typename ValueType_, typename Codec_ = NullCodec>
518{
519public:
520 using Ptr = std::shared_ptr<TypedAttributeArray>;
521 using ConstPtr = std::shared_ptr<const TypedAttributeArray>;
522
523 using ValueType = ValueType_;
524 using Codec = Codec_;
525 using StorageType = typename Codec::template Storage<ValueType>::Type;
526
527 //////////
528
529 /// Default constructor, always constructs a uniform attribute.
530 explicit TypedAttributeArray(Index n = 1, Index strideOrTotalSize = 1, bool constantStride = true,
531 const ValueType& uniformValue = zeroVal<ValueType>());
532
533 /// Deep copy constructor.
534 /// @note This method is thread-safe (as of ABI=7) for concurrently reading from the
535 /// source attribute array while being deep-copied. Specifically, this means that the
536 /// attribute array being deep-copied can be out-of-core and safely loaded in one thread
537 /// while being copied using this copy-constructor in another thread.
538 /// It is not thread-safe for write.
540
541 /// Deep copy assignment operator.
542 /// @note this operator is thread-safe.
544 /// Move constructor disabled.
546 /// Move assignment operator disabled.
548
549 ~TypedAttributeArray() override { this->deallocate(); }
550
551 /// Return a copy of this attribute.
552 /// @note This method is thread-safe.
553 AttributeArray::Ptr copy() const override;
554
555 /// Return a new attribute array of the given length @a n and @a stride with uniform value zero.
556 static Ptr create(Index n, Index strideOrTotalSize = 1, bool constantStride = true,
557 const Metadata* metadata = nullptr);
558
559 /// Cast an AttributeArray to TypedAttributeArray<T>
560 static TypedAttributeArray& cast(AttributeArray& attributeArray);
561
562 /// Cast an AttributeArray to TypedAttributeArray<T>
563 static const TypedAttributeArray& cast(const AttributeArray& attributeArray);
564
565 /// Return the name of this attribute's type (includes codec)
566 static const NamePair& attributeType();
567 /// Return the name of this attribute's type.
568 const NamePair& type() const override { return attributeType(); }
569
570 /// Return @c true if this attribute type is registered.
571 static bool isRegistered();
572 /// Register this attribute type along with a factory function.
573 static void registerType();
574 /// Remove this attribute type from the registry.
575 static void unregisterType();
576
577 /// Return the number of elements in this array.
578 Index size() const override { return mSize; }
579
580 /// Return the stride of this array.
581 /// @note A return value of zero means a variable stride
582 Index stride() const override { return hasConstantStride() ? mStrideOrTotalSize : 0; }
583
584 /// Return the size of the data in this array.
585 Index dataSize() const override {
586 return hasConstantStride() ? mSize * mStrideOrTotalSize : mStrideOrTotalSize;
587 }
588
589 /// Return the name of the value type of a single element in this array (e.g., "float" or "vec3d").
590 Name valueType() const override { return typeNameAsString<ValueType>(); }
591
592 /// Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
593 Name codecType() const override { return Codec::name(); }
594
595 /// Return the size in bytes of the value type of a single element in this array.
596 Index valueTypeSize() const override { return sizeof(ValueType); }
597
598 /// Return the size in bytes of the storage type of a single element of this array.
599 /// @note If the Codec is a NullCodec, valueSize() == storageSize()
600 Index storageTypeSize() const override { return sizeof(StorageType); }
601
602 /// Return @c true if the value type is floating point
603 bool valueTypeIsFloatingPoint() const override;
604
605 /// Return @c true if the value type is a class (ie vector, matrix or quaternion return true)
606 bool valueTypeIsClass() const override;
607
608 /// Return @c true if the value type is a vector
609 bool valueTypeIsVector() const override;
610
611 /// Return @c true if the value type is a quaternion
612 bool valueTypeIsQuaternion() const override;
613
614 /// Return @c true if the value type is a matrix
615 bool valueTypeIsMatrix() const override;
616
617 /// Return the number of bytes of memory used by this attribute.
618 size_t memUsage() const override;
619
620#if OPENVDB_ABI_VERSION_NUMBER < 14
621 OPENVDB_DEPRECATED_MESSAGE("Use memUsage() instead. This method is deprecated and will be removed. Delayed loading is no longer supported.")
622 size_t memUsageIfLoaded() const override { return memUsage(); }
623#endif // OPENVDB_ABI_VERSION_NUMBER < 14
624
625 /// Return the value at index @a n (assumes in-core)
627 /// Return the value at index @a n
629 /// Return the @a value at index @a n (assumes in-core)
630 template<typename T> void getUnsafe(Index n, T& value) const;
631 /// Return the @a value at index @a n
632 template<typename T> void get(Index n, T& value) const;
633
634 /// Non-member equivalent to getUnsafe() that static_casts array to this TypedAttributeArray
635 /// (assumes in-core)
636 static ValueType getUnsafe(const AttributeArray* array, const Index n);
637
638 /// Set @a value at the given index @a n (assumes in-core)
639 void setUnsafe(Index n, const ValueType& value);
640 /// Set @a value at the given index @a n
641 void set(Index n, const ValueType& value);
642 /// Set @a value at the given index @a n (assumes in-core)
643 template<typename T> void setUnsafe(Index n, const T& value);
644 /// Set @a value at the given index @a n
645 template<typename T> void set(Index n, const T& value);
646
647 /// Non-member equivalent to setUnsafe() that static_casts array to this TypedAttributeArray
648 /// (assumes in-core)
649 static void setUnsafe(AttributeArray* array, const Index n, const ValueType& value);
650
651 /// Return @c true if this array is stored as a single uniform value.
652 bool isUniform() const override { return mIsUniform; }
653 /// @brief Replace the single value storage with an array of length size().
654 /// @note Non-uniform attributes are unchanged.
655 /// @param fill toggle to initialize the array elements with the pre-expanded value.
656 void expand(bool fill = true) override;
657 /// Replace the existing array with a uniform zero value.
658 void collapse() override;
659 /// Compact the existing array to become uniform if all values are identical
660 bool compact() override;
661
662 /// Replace the existing array with the given uniform value.
663 void collapse(const ValueType& uniformValue);
664 /// @brief Fill the existing array with the given value.
665 /// @note Identical to collapse() except a non-uniform array will not become uniform.
666 void fill(const ValueType& value);
667
668 /// Non-member equivalent to collapse() that static_casts array to this TypedAttributeArray
669 static void collapse(AttributeArray* array, const ValueType& value);
670 /// Non-member equivalent to fill() that static_casts array to this TypedAttributeArray
671 static void fill(AttributeArray* array, const ValueType& value);
672
673 /// Read attribute data from a stream.
674 void read(std::istream&) override;
675 /// Write attribute data to a stream.
676 /// @param os the output stream
677 /// @param outputTransient if true, write out transient attributes
678 void write(std::ostream& os, bool outputTransient) const override;
679 /// Write attribute data to a stream, don't write transient attributes.
680 void write(std::ostream&) const override;
681
682 /// Read attribute metadata from a stream.
683 void readMetadata(std::istream&) override;
684 /// Write attribute metadata to a stream.
685 /// @param os the output stream
686 /// @param outputTransient if true, write out transient attributes
687 /// @param paged if true, data is written out in pages
688 void writeMetadata(std::ostream& os, bool outputTransient, bool paged) const override;
689
690 /// Read attribute buffers from a stream.
691 void readBuffers(std::istream&) override;
692 /// Write attribute buffers to a stream.
693 /// @param os the output stream
694 /// @param outputTransient if true, write out transient attributes
695 void writeBuffers(std::ostream& os, bool outputTransient) const override;
696
697 /// Read attribute buffers from a paged stream.
699 /// Write attribute buffers to a paged stream.
700 /// @param os the output stream
701 /// @param outputTransient if true, write out transient attributes
702 void writePagedBuffers(compression::PagedOutputStream& os, bool outputTransient) const override;
703
704#if OPENVDB_ABI_VERSION_NUMBER < 14
705 OPENVDB_DEPRECATED_MESSAGE("This method is deprecated and will be removed. Delayed loading is no longer supported.")
706 void loadData() const override { }
707
708 OPENVDB_DEPRECATED_MESSAGE("Always returns true. This method is deprecated and will be removed. Delayed loading is no longer supported.")
709 bool isDataLoaded() const override { return true; }
710#endif // OPENVDB_ABI_VERSION_NUMBER < 14
711
712 /// Return the raw data buffer
713 inline const StorageType* constData() const { return this->data(); }
714
715protected:
716 AccessorBasePtr getAccessor() const override;
717
718 /// Return the raw data buffer
719 inline StorageType* data() { OPENVDB_ASSERT(validData()); return mData.get(); }
720 inline const StorageType* data() const { OPENVDB_ASSERT(validData()); return mData.get(); }
721
722 /// Verify that data is not out-of-core or in a partially-read state
723 inline bool validData() const { return !((flags() & PARTIALREAD)); }
724
725private:
726 friend class ::TestAttributeArray;
727
728 TypedAttributeArray(const TypedAttributeArray&, const tbb::spin_mutex::scoped_lock&);
729
730 /// Toggle out-of-core state
731 inline void setOutOfCore(const bool);
732
733 /// Compare the this data to another attribute array. Used by the base class comparison operator
734 bool isEqual(const AttributeArray& other) const override;
735
736 /// Virtual function to retrieve the data buffer from the derived class cast to a char byte array
737 char* dataAsByteArray() override;
738 const char* dataAsByteArray() const override;
739
740 size_t arrayMemUsage() const;
741 void allocate();
742 void deallocate();
743
744 /// Helper function for use with registerType()
745 static AttributeArray::Ptr factory(Index n, Index strideOrTotalSize, bool constantStride,
746 const Metadata* metadata) {
747 return TypedAttributeArray::create(n, strideOrTotalSize, constantStride, metadata);
748 }
749
750 std::unique_ptr<StorageType[]> mData;
751 Index mSize;
752 Index mStrideOrTotalSize;
753}; // class TypedAttributeArray
754
755
756////////////////////////////////////////
757
758
759/// AttributeHandles provide access to specific TypedAttributeArray methods without needing
760/// to know the compression codec, however these methods also incur the cost of a function pointer
761template <typename ValueType, typename CodecType = UnknownCodec>
763{
764public:
766 using Ptr = std::shared_ptr<Handle>;
767 using UniquePtr = std::unique_ptr<Handle>;
768
769protected:
770 using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
771 using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
772 using ValuePtr = void (*)(AttributeArray* array, const ValueType& value);
773
774public:
775 static Ptr create(const AttributeArray& array, const bool collapseOnDestruction = true);
776
777 AttributeHandle(const AttributeArray& array, const bool collapseOnDestruction = true);
778
781
783
784 Index stride() const { return mStrideOrTotalSize; }
785 Index size() const { return mSize; }
786
787 bool isUniform() const;
788 bool hasConstantStride() const;
789
790 ValueType get(Index n, Index m = 0) const;
791
792 const AttributeArray& array() const;
793
794protected:
795 Index index(Index n, Index m) const;
796
798
803
804private:
805 friend class ::TestAttributeArray;
806
807 template <bool IsUnknownCodec>
808 typename std::enable_if<IsUnknownCodec, bool>::type compatibleType() const;
809
810 template <bool IsUnknownCodec>
811 typename std::enable_if<!IsUnknownCodec, bool>::type compatibleType() const;
812
813 template <bool IsUnknownCodec>
814 typename std::enable_if<IsUnknownCodec, ValueType>::type get(Index index) const;
815
816 template <bool IsUnknownCodec>
817 typename std::enable_if<!IsUnknownCodec, ValueType>::type get(Index index) const;
818
819 Index mStrideOrTotalSize;
820 Index mSize;
821 bool mCollapseOnDestruction;
822}; // class AttributeHandle
823
824
825////////////////////////////////////////
826
827
828/// Write-able version of AttributeHandle
829template <typename ValueType, typename CodecType = UnknownCodec>
830class AttributeWriteHandle : public AttributeHandle<ValueType, CodecType>
831{
832public:
834 using Ptr = std::shared_ptr<Handle>;
835 using ScopedPtr = std::unique_ptr<Handle>;
836
837 static Ptr create(AttributeArray& array, const bool expand = true);
838
840
841 virtual ~AttributeWriteHandle() = default;
842
843 /// @brief If this array is uniform, replace it with an array of length size().
844 /// @param fill if true, assign the uniform value to each element of the array.
845 void expand(bool fill = true);
846
847 /// Replace the existing array with a uniform value (zero if none provided).
848 void collapse();
849 void collapse(const ValueType& uniformValue);
850
851 /// Compact the existing array to become uniform if all values are identical
852 bool compact();
853
854 /// @brief Fill the existing array with the given value.
855 /// @note Identical to collapse() except a non-uniform array will not become uniform.
856 void fill(const ValueType& value);
857
858 void set(Index n, const ValueType& value);
859 void set(Index n, Index m, const ValueType& value);
860
862
863private:
864 friend class ::TestAttributeArray;
865
866 template <bool IsUnknownCodec>
867 typename std::enable_if<IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
868
869 template <bool IsUnknownCodec>
870 typename std::enable_if<!IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
871}; // class AttributeWriteHandle
872
873
874////////////////////////////////////////
875
876
877// Attribute codec implementation
878
879
880template<typename ValueType>
881inline void
882NullCodec::decode(const ValueType& data, ValueType& val)
883{
884 val = data;
885}
886
887
888template<typename ValueType>
889inline void
890NullCodec::encode(const ValueType& val, ValueType& data)
891{
892 data = val;
893}
894
895
896template<typename StorageType, typename ValueType>
897inline void
898TruncateCodec::decode(const StorageType& data, ValueType& val)
899{
900 val = static_cast<ValueType>(data);
901}
902
903
904template<typename StorageType, typename ValueType>
905inline void
906TruncateCodec::encode(const ValueType& val, StorageType& data)
907{
908 data = static_cast<StorageType>(val);
909}
910
911
912template <bool OneByte, typename Range>
913template<typename StorageType, typename ValueType>
914inline void
915FixedPointCodec<OneByte, Range>::decode(const StorageType& data, ValueType& val)
916{
918
919 // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
920
921 val = Range::template decode<ValueType>(val);
922}
923
924
925template <bool OneByte, typename Range>
926template<typename StorageType, typename ValueType>
927inline void
928FixedPointCodec<OneByte, Range>::encode(const ValueType& val, StorageType& data)
929{
930 // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
931
932 const ValueType newVal = Range::template encode<ValueType>(val);
933
935}
936
937
938template<typename T>
939inline void
944
945
946template<typename T>
947inline void
952
953
954////////////////////////////////////////
955
956// AttributeArray implementation
957
958template <typename IterT>
959void AttributeArray::doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
960 bool rangeChecking/*=true*/)
961{
962 // ensure both arrays have float-float or integer-integer value types
963 OPENVDB_ASSERT(sourceArray.valueTypeIsFloatingPoint() == this->valueTypeIsFloatingPoint());
964 // ensure storage size * stride matches on both arrays
965 OPENVDB_ASSERT(this->storageTypeSize()*this->stride() ==
966 sourceArray.storageTypeSize()*sourceArray.stride());
967
968 const size_t bytes(sourceArray.storageTypeSize()*sourceArray.stride());
969 const char* const sourceBuffer = sourceArray.dataAsByteArray();
970 char* const targetBuffer = this->dataAsByteArray();
971 OPENVDB_ASSERT(sourceBuffer && targetBuffer);
972
973 if (rangeChecking && this->isUniform()) {
974 OPENVDB_THROW(IndexError, "Cannot copy array data as target array is uniform.");
975 }
976
977 const bool sourceIsUniform = sourceArray.isUniform();
978
979 const Index sourceDataSize = rangeChecking ? sourceArray.dataSize() : 0;
980 const Index targetDataSize = rangeChecking ? this->dataSize() : 0;
981
982 for (IterT it(iter); it; ++it) {
983 const Index sourceIndex = sourceIsUniform ? 0 : it.sourceIndex();
984 const Index targetIndex = it.targetIndex();
985
986 if (rangeChecking) {
987 if (sourceIndex >= sourceDataSize) {
989 "Cannot copy array data as source index exceeds size of source array.");
990 }
991 if (targetIndex >= targetDataSize) {
993 "Cannot copy array data as target index exceeds size of target array.");
994 }
995 } else {
996 // range-checking asserts
997 OPENVDB_ASSERT(sourceIndex < sourceArray.dataSize());
998 OPENVDB_ASSERT(targetIndex < this->dataSize());
999 if (this->isUniform()) OPENVDB_ASSERT(targetIndex == Index(0));
1000 }
1001
1002 const size_t targetOffset(targetIndex * bytes);
1003 const size_t sourceOffset(sourceIndex * bytes);
1004
1005 std::memcpy(targetBuffer + targetOffset, sourceBuffer + sourceOffset, bytes);
1006 }
1007}
1008
1009template <typename IterT>
1010void AttributeArray::copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter)
1011{
1012 this->doCopyValues(sourceArray, iter, /*range-checking=*/false);
1013}
1014
1015template <typename IterT>
1016void AttributeArray::copyValues(const AttributeArray& sourceArray, const IterT& iter,
1017 bool compact/* = true*/)
1018{
1019 const Index bytes = sourceArray.storageTypeSize();
1020 if (bytes != this->storageTypeSize()) {
1021 OPENVDB_THROW(TypeError, "Cannot copy array data due to mis-match in storage type sizes.");
1022 }
1023
1024 // if the target array is uniform, expand it first
1025 this->expand();
1026
1027 // TODO: Acquire mutex locks for source and target arrays to ensure that
1028 // value copying is always thread-safe. Note that the unsafe method will be
1029 // faster, but can only be used if neither the source or target arrays are
1030 // modified during copying. Note that this will require a new private
1031 // virtual method with ABI=7 to access the mutex from the derived class.
1032
1033 this->doCopyValues(sourceArray, iter, true);
1034
1035 // attempt to compact target array
1036 if (compact) {
1037 this->compact();
1038 }
1039}
1040
1041
1042////////////////////////////////////////
1043
1044// TypedAttributeArray implementation
1045
1046
1047template<typename ValueType_, typename Codec_>
1049 Index n, Index strideOrTotalSize, bool constantStride, const ValueType& uniformValue)
1050 : AttributeArray()
1051 , mData(new StorageType[1])
1052 , mSize(n)
1053 , mStrideOrTotalSize(strideOrTotalSize)
1054{
1055 if (constantStride) {
1056 this->setConstantStride(true);
1057 if (strideOrTotalSize == 0) {
1058 OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a constant stride requires that " \
1059 "stride to be at least one.")
1060 }
1061 }
1062 else {
1063 this->setConstantStride(false);
1064 if (mStrideOrTotalSize < n) {
1065 OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a non-constant stride must have " \
1066 "a total size of at least the number of elements in the array.")
1067 }
1068 }
1069 mSize = std::max(Index(1), mSize);
1070 mStrideOrTotalSize = std::max(Index(1), mStrideOrTotalSize);
1071 Codec::encode(uniformValue, this->data()[0]);
1072}
1073
1074
1075template<typename ValueType_, typename Codec_>
1077 : TypedAttributeArray(rhs, tbb::spin_mutex::scoped_lock(rhs.mMutex))
1078{
1079}
1080
1081
1082template<typename ValueType_, typename Codec_>
1084 const tbb::spin_mutex::scoped_lock& lock)
1085 : AttributeArray(rhs, lock)
1086 , mSize(rhs.mSize)
1087 , mStrideOrTotalSize(rhs.mStrideOrTotalSize)
1088{
1089 if (this->validData()) {
1090 this->allocate();
1091 std::memcpy(static_cast<void*>(this->data()), rhs.data(), this->arrayMemUsage());
1092 }
1093}
1094
1095
1096template<typename ValueType_, typename Codec_>
1097TypedAttributeArray<ValueType_, Codec_>&
1099{
1100 if (&rhs != this) {
1101 // lock both the source and target arrays to ensure thread-safety
1102 tbb::spin_mutex::scoped_lock lock(mMutex);
1103 tbb::spin_mutex::scoped_lock rhsLock(rhs.mMutex);
1104
1105 this->deallocate();
1106
1107 mFlags = rhs.mFlags;
1109 mSize = rhs.mSize;
1110 mStrideOrTotalSize = rhs.mStrideOrTotalSize;
1111 mIsUniform = rhs.mIsUniform;
1112
1113 if (this->validData()) {
1114 this->allocate();
1115 std::memcpy(static_cast<void*>(this->data()), rhs.data(), this->arrayMemUsage());
1116 }
1117 }
1118
1119 return *this;
1120}
1121
1122
1123template<typename ValueType_, typename Codec_>
1124inline const NamePair&
1126{
1127 static NamePair sTypeName = []() {
1128 return NamePair(typeNameAsString<ValueType>(), Codec::name());
1129 }();
1130 return sTypeName;
1131}
1132
1133
1134template<typename ValueType_, typename Codec_>
1135inline bool
1140
1141
1142template<typename ValueType_, typename Codec_>
1143inline void
1148
1149
1150template<typename ValueType_, typename Codec_>
1151inline void
1156
1157
1158template<typename ValueType_, typename Codec_>
1161 const Metadata* metadata)
1162{
1163 const TypedMetadata<ValueType>* typedMetadata = metadata ?
1164 dynamic_cast<const TypedMetadata<ValueType>*>(metadata) : nullptr;
1165
1166 return Ptr(new TypedAttributeArray(n, stride, constantStride,
1167 typedMetadata ? typedMetadata->value() : zeroVal<ValueType>()));
1168}
1169
1170template<typename ValueType_, typename Codec_>
1173{
1174 if (!attributeArray.isType<TypedAttributeArray>()) {
1175 OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1176 }
1177 return static_cast<TypedAttributeArray&>(attributeArray);
1178}
1179
1180template<typename ValueType_, typename Codec_>
1183{
1184 if (!attributeArray.isType<TypedAttributeArray>()) {
1185 OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1186 }
1187 return static_cast<const TypedAttributeArray&>(attributeArray);
1188}
1189
1190template<typename ValueType_, typename Codec_>
1196
1197
1198template<typename ValueType_, typename Codec_>
1199size_t
1200TypedAttributeArray<ValueType_, Codec_>::arrayMemUsage() const
1201{
1202 return (mIsUniform ? 1 : this->dataSize()) * sizeof(StorageType);
1203}
1204
1205
1206template<typename ValueType_, typename Codec_>
1207void
1208TypedAttributeArray<ValueType_, Codec_>::allocate()
1209{
1210 OPENVDB_ASSERT(!mData);
1211 if (mIsUniform) {
1212 mData.reset(new StorageType[1]);
1213 }
1214 else {
1215 const size_t size(this->dataSize());
1216 OPENVDB_ASSERT(size > 0);
1217 mData.reset(new StorageType[size]);
1218 }
1219}
1220
1221
1222template<typename ValueType_, typename Codec_>
1223void
1224TypedAttributeArray<ValueType_, Codec_>::deallocate()
1225{
1226 if (mData) mData.reset();
1227}
1228
1229
1230template<typename ValueType_, typename Codec_>
1231bool
1233{
1234 // TODO: Update to use Traits that correctly handle matrices and quaternions.
1235
1236 if (std::is_same<ValueType, Quats>::value ||
1237 std::is_same<ValueType, Quatd>::value ||
1238 std::is_same<ValueType, Mat3s>::value ||
1239 std::is_same<ValueType, Mat3d>::value ||
1240 std::is_same<ValueType, Mat4s>::value ||
1241 std::is_same<ValueType, Mat4d>::value) return true;
1242
1243 using ElementT = typename VecTraits<ValueType>::ElementType;
1244
1245 // half is not defined as float point as expected, so explicitly handle it
1246 return std::is_floating_point<ElementT>::value || std::is_same<math::half, ElementT>::value;
1247}
1248
1249
1250template<typename ValueType_, typename Codec_>
1251bool
1253{
1254 // half is not defined as a non-class type as expected, so explicitly exclude it
1255 return std::is_class<ValueType>::value && !std::is_same<math::half, ValueType>::value;
1256}
1257
1258
1259template<typename ValueType_, typename Codec_>
1260bool
1265
1266
1267template<typename ValueType_, typename Codec_>
1268bool
1270{
1271 // TODO: improve performance by making this a compile-time check using type traits
1272 return !this->valueType().compare(0, 4, "quat");
1273}
1274
1275
1276template<typename ValueType_, typename Codec_>
1277bool
1279{
1280 // TODO: improve performance by making this a compile-time check using type traits
1281 return !this->valueType().compare(0, 3, "mat");
1282}
1283
1284
1285template<typename ValueType_, typename Codec_>
1286size_t
1288{
1289 return sizeof(*this) + (bool(mData) ? this->arrayMemUsage() : 0);
1290}
1291
1292
1293template<typename ValueType_, typename Codec_>
1296{
1297 OPENVDB_ASSERT(n < this->dataSize());
1298
1299 ValueType val;
1300 Codec::decode(/*in=*/this->data()[mIsUniform ? 0 : n], /*out=*/val);
1301 return val;
1302}
1303
1304
1305template<typename ValueType_, typename Codec_>
1308{
1309 if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1310
1311 return this->getUnsafe(n);
1312}
1313
1314
1315template<typename ValueType_, typename Codec_>
1316template<typename T>
1317void
1319{
1320 val = static_cast<T>(this->getUnsafe(n));
1321}
1322
1323
1324template<typename ValueType_, typename Codec_>
1325template<typename T>
1326void
1328{
1329 val = static_cast<T>(this->get(n));
1330}
1331
1332
1333template<typename ValueType_, typename Codec_>
1336{
1337 return static_cast<const TypedAttributeArray<ValueType, Codec>*>(array)->getUnsafe(n);
1338}
1339
1340
1341template<typename ValueType_, typename Codec_>
1342void
1344{
1345 OPENVDB_ASSERT(n < this->dataSize());
1346 OPENVDB_ASSERT(!this->isUniform());
1347
1348 // this unsafe method assumes the data is not uniform, however if it is, this redirects the index
1349 // to zero, which is marginally less efficient but ensures not writing to an illegal address
1350
1351 Codec::encode(/*in=*/val, /*out=*/this->data()[mIsUniform ? 0 : n]);
1352}
1353
1354
1355template<typename ValueType_, typename Codec_>
1356void
1358{
1359 if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1360 if (this->isUniform()) this->expand();
1361
1362 this->setUnsafe(n, val);
1363}
1364
1365
1366template<typename ValueType_, typename Codec_>
1367template<typename T>
1368void
1370{
1371 this->setUnsafe(n, static_cast<ValueType>(val));
1372}
1373
1374
1375template<typename ValueType_, typename Codec_>
1376template<typename T>
1377void
1379{
1380 this->set(n, static_cast<ValueType>(val));
1381}
1382
1383
1384template<typename ValueType_, typename Codec_>
1385void
1387{
1388 static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->setUnsafe(n, value);
1389}
1390
1391
1392template<typename ValueType_, typename Codec_>
1393void
1395{
1396 if (!mIsUniform) return;
1397
1398 const StorageType val = this->data()[0];
1399
1400 {
1401 tbb::spin_mutex::scoped_lock lock(mMutex);
1402 this->deallocate();
1403 mIsUniform = false;
1404 this->allocate();
1405 }
1406
1407 if (fill) {
1408 for (Index i = 0; i < this->dataSize(); ++i) this->data()[i] = val;
1409 }
1410}
1411
1412
1413template<typename ValueType_, typename Codec_>
1414bool
1416{
1417 if (mIsUniform) return true;
1418
1419 // compaction is not possible if any values are different
1420 const ValueType_ val = this->get(0);
1421 for (Index i = 1; i < this->dataSize(); i++) {
1422 if (!math::isExactlyEqual(this->get(i), val)) return false;
1423 }
1424
1425 this->collapse(this->get(0));
1426 return true;
1427}
1428
1429
1430template<typename ValueType_, typename Codec_>
1431void
1436
1437
1438template<typename ValueType_, typename Codec_>
1439void
1441{
1442 if (!mIsUniform) {
1443 tbb::spin_mutex::scoped_lock lock(mMutex);
1444 this->deallocate();
1445 mIsUniform = true;
1446 this->allocate();
1447 }
1448 Codec::encode(uniformValue, this->data()[0]);
1449}
1450
1451
1452template<typename ValueType_, typename Codec_>
1453void
1458
1459
1460template<typename ValueType_, typename Codec_>
1461void
1463{
1464 const Index size = mIsUniform ? 1 : this->dataSize();
1465 for (Index i = 0; i < size; ++i) {
1466 Codec::encode(value, this->data()[i]);
1467 }
1468}
1469
1470
1471template<typename ValueType_, typename Codec_>
1472void
1477
1478
1479template<typename ValueType_, typename Codec_>
1480void
1482{
1483 this->readMetadata(is);
1484 this->readBuffers(is);
1485}
1486
1487
1488template<typename ValueType_, typename Codec_>
1489void
1491{
1492 // read data
1493
1494 Index64 bytes = Index64(0);
1495 is.read(reinterpret_cast<char*>(&bytes), sizeof(Index64));
1496 if (bytes < /*flags*/sizeof(Int16) + /*size*/sizeof(Index)) {
1497 OPENVDB_THROW(IoError, "Invalid attribute array byte count for VDB file format.");
1498 }
1499 bytes = bytes - /*flags*/sizeof(Int16) - /*size*/sizeof(Index);
1500
1501 uint8_t flags = uint8_t(0);
1502 is.read(reinterpret_cast<char*>(&flags), sizeof(uint8_t));
1503 mFlags = flags;
1504
1505 uint8_t serializationFlags = uint8_t(0);
1506 is.read(reinterpret_cast<char*>(&serializationFlags), sizeof(uint8_t));
1507
1508 Index size = Index(0);
1509 is.read(reinterpret_cast<char*>(&size), sizeof(Index));
1510 mSize = size;
1511
1512 // warn if an unknown flag has been set
1513 if (mFlags >= 0x20) {
1514 OPENVDB_LOG_WARN("Unknown attribute flags for VDB file format.");
1515 }
1516 // error if an unknown serialization flag has been set,
1517 // as this will adjust the layout of the data and corrupt the ability to read
1518 if (serializationFlags >= 0x10) {
1519 OPENVDB_THROW(IoError, "Unknown attribute serialization flags for VDB file format.");
1520 }
1521
1522 // set uniform, compressed and page read state
1523
1524 mIsUniform = serializationFlags & WRITEUNIFORM;
1525 mUsePagedRead = serializationFlags & WRITEPAGED;
1526 mCompressedBytes = bytes;
1527 mFlags |= PARTIALREAD; // mark data as having been partially read
1528
1529 // read strided value (set to 1 if array is not strided)
1530
1531 if (serializationFlags & WRITESTRIDED) {
1532 Index stride = Index(0);
1533 is.read(reinterpret_cast<char*>(&stride), sizeof(Index));
1534 mStrideOrTotalSize = stride;
1535 }
1536 else {
1537 mStrideOrTotalSize = 1;
1538 }
1539
1540 // size and stride come from the file, so reject values that make dataSize()
1541 // overflow or be smaller than size(), as point indices are checked against size()
1542 if (mSize == 0) {
1543 OPENVDB_THROW(IoError, "Invalid attribute array size for VDB file format.");
1544 }
1545 if (this->hasConstantStride()) {
1546 if (mStrideOrTotalSize == 0 ||
1547 Index64(mSize) * Index64(mStrideOrTotalSize) > Index64(std::numeric_limits<Index>::max())) {
1548 OPENVDB_THROW(IoError, "Invalid attribute array stride for VDB file format.");
1549 }
1550 }
1551 else if (mStrideOrTotalSize < mSize) {
1552 OPENVDB_THROW(IoError, "Invalid attribute array total size for VDB file format.");
1553 }
1554}
1555
1556
1557template<typename ValueType_, typename Codec_>
1558void
1560{
1561 if (mUsePagedRead) {
1562 // use readBuffers(PagedInputStream&) for paged buffers
1563 OPENVDB_THROW(IoError, "Cannot read paged AttributeArray buffers.");
1564 }
1565
1566 this->deallocate();
1567
1568 uint8_t bloscCompressed(0);
1569 if (!mIsUniform) is.read(reinterpret_cast<char*>(&bloscCompressed), sizeof(uint8_t));
1570
1572
1573 // the byte count and the element count are independent fields in the file,
1574 // so check that uncompressed data holds every element
1575 // (the blosc path checks the decompressed size instead)
1576 if (bloscCompressed != uint8_t(1) && mCompressedBytes < this->arrayMemUsage()) {
1577 OPENVDB_THROW(IoError, "Attribute array data is smaller than the array size.");
1578 }
1579
1580 const size_t bytesRead = mCompressedBytes;
1581 std::unique_ptr<char[]> buffer(new char[mCompressedBytes]);
1582 is.read(buffer.get(), mCompressedBytes);
1583 mCompressedBytes = 0;
1584 mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1585
1586 // compressed on-disk
1587
1588 if (bloscCompressed == uint8_t(1)) {
1589
1590 // decompress buffer
1591
1592 compression::bloscValidateCompressedBytes(buffer.get(), bytesRead);
1593 const size_t inBytes = this->dataSize() * sizeof(StorageType);
1594 std::unique_ptr<char[]> newBuffer = compression::bloscDecompress(buffer.get(), inBytes);
1595 if (newBuffer) buffer.reset(newBuffer.release());
1596 }
1597
1598 // set data to buffer
1599
1600 mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1601}
1602
1603
1604template<typename ValueType_, typename Codec_>
1605void
1607{
1608 if (!mUsePagedRead) {
1609 if (!is.sizeOnly()) this->readBuffers(is.getInputStream());
1610 return;
1611 }
1612
1613 if (is.sizeOnly())
1614 {
1615 // the paged buffer becomes the array data, so it must hold every element
1616 if (mCompressedBytes < this->arrayMemUsage()) {
1617 OPENVDB_THROW(IoError, "Attribute array data is smaller than the array size.");
1618 }
1619 size_t compressedBytes(mCompressedBytes);
1620 mCompressedBytes = 0; // if not set to zero, mPageHandle will attempt to destroy invalid memory
1621 mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1623 mPageHandle = is.createHandle(compressedBytes);
1624 return;
1625 }
1626
1628
1629 this->deallocate();
1630
1631 is.read(mPageHandle, std::streamsize(mPageHandle->size()), false);
1632 std::unique_ptr<char[]> buffer = mPageHandle->read();
1633 mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1634 mPageHandle.reset();
1635
1636 // clear page state
1637
1638 mUsePagedRead = 0;
1639}
1640
1641
1642inline void
1644{
1645 if (!mUsePagedRead) {
1646 if (!is.sizeOnly()) {
1647 // for non-paged data, seek past the raw data in the stream
1648 std::istream& inputStream = is.getInputStream();
1649 uint8_t bloscCompressed(0);
1650 if (!mIsUniform) inputStream.read(reinterpret_cast<char*>(&bloscCompressed), sizeof(uint8_t));
1651 auto meta = io::getStreamMetadataPtr(inputStream);
1652 if (meta && meta->seekable()) {
1653 inputStream.seekg(mCompressedBytes, std::ios_base::cur);
1654 } else {
1655 std::vector<char> tempData(mCompressedBytes);
1656 inputStream.read(tempData.data(), mCompressedBytes);
1657 }
1658 mCompressedBytes = 0;
1659 mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD);
1660 }
1661 return;
1662 }
1663
1664 if (is.sizeOnly())
1665 {
1666 size_t compressedBytes(mCompressedBytes);
1667 mCompressedBytes = 0;
1668 mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD);
1670 mPageHandle = is.createHandle(compressedBytes);
1671 return;
1672 }
1673
1675
1676 is.skip(mPageHandle, std::streamsize(mPageHandle->size()));
1677 mPageHandle.reset();
1678
1679 // clear page state
1680
1681 mUsePagedRead = 0;
1682}
1683
1684
1685template<typename ValueType_, typename Codec_>
1686void
1688{
1689 this->write(os, /*outputTransient=*/false);
1690}
1691
1692
1693template<typename ValueType_, typename Codec_>
1694void
1695TypedAttributeArray<ValueType_, Codec_>::write(std::ostream& os, bool outputTransient) const
1696{
1697 this->writeMetadata(os, outputTransient, /*paged=*/false);
1698 this->writeBuffers(os, outputTransient);
1699}
1700
1701
1702template<typename ValueType_, typename Codec_>
1703void
1704TypedAttributeArray<ValueType_, Codec_>::writeMetadata(std::ostream& os, bool outputTransient, bool paged) const
1705{
1706 if (!outputTransient && this->isTransient()) return;
1707
1708 if (mFlags & PARTIALREAD) {
1709 OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1710 }
1711
1712 uint8_t flags(mFlags);
1713 uint8_t serializationFlags(0);
1714 Index size(mSize);
1715 Index strideOrTotalSize(mStrideOrTotalSize);
1716 bool strideOfOne(this->stride() == 1);
1717
1718 bool bloscCompression = io::getDataCompression(os) & io::COMPRESS_BLOSC;
1719
1720 size_t compressedBytes = 0;
1721
1722 if (!strideOfOne)
1723 {
1724 serializationFlags |= WRITESTRIDED;
1725 }
1726
1727 if (mIsUniform)
1728 {
1729 serializationFlags |= WRITEUNIFORM;
1730 if (bloscCompression && paged) serializationFlags |= WRITEPAGED;
1731 }
1732 else if (bloscCompression)
1733 {
1734 if (paged) serializationFlags |= WRITEPAGED;
1735 else {
1736 const char* charBuffer = reinterpret_cast<const char*>(this->data());
1737 const size_t inBytes = this->arrayMemUsage();
1738 compressedBytes = compression::bloscCompressedSize(charBuffer, inBytes);
1739 }
1740 }
1741
1742 Index64 bytes = /*flags*/ sizeof(Int16) + /*size*/ sizeof(Index);
1743
1744 bytes += (compressedBytes > 0) ? compressedBytes : this->arrayMemUsage();
1745
1746 // write data
1747
1748 os.write(reinterpret_cast<const char*>(&bytes), sizeof(Index64));
1749 os.write(reinterpret_cast<const char*>(&flags), sizeof(uint8_t));
1750 os.write(reinterpret_cast<const char*>(&serializationFlags), sizeof(uint8_t));
1751 os.write(reinterpret_cast<const char*>(&size), sizeof(Index));
1752
1753 // write strided
1754 if (!strideOfOne) os.write(reinterpret_cast<const char*>(&strideOrTotalSize), sizeof(Index));
1755}
1756
1757
1758template<typename ValueType_, typename Codec_>
1759void
1760TypedAttributeArray<ValueType_, Codec_>::writeBuffers(std::ostream& os, bool outputTransient) const
1761{
1762 if (!outputTransient && this->isTransient()) return;
1763
1764 if (mFlags & PARTIALREAD) {
1765 OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1766 }
1767
1768 if (this->isUniform()) {
1769 os.write(reinterpret_cast<const char*>(this->data()), sizeof(StorageType));
1770 }
1772 {
1773 std::unique_ptr<char[]> compressedBuffer;
1774 size_t compressedBytes = 0;
1775 const char* charBuffer = reinterpret_cast<const char*>(this->data());
1776 const size_t inBytes = this->arrayMemUsage();
1777 compressedBuffer = compression::bloscCompress(charBuffer, inBytes, compressedBytes);
1778 if (compressedBuffer) {
1779 uint8_t bloscCompressed(1);
1780 os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1781 os.write(reinterpret_cast<const char*>(compressedBuffer.get()), compressedBytes);
1782 }
1783 else {
1784 uint8_t bloscCompressed(0);
1785 os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1786 os.write(reinterpret_cast<const char*>(this->data()), inBytes);
1787 }
1788 }
1789 else
1790 {
1791 uint8_t bloscCompressed(0);
1792 os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1793 os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1794 }
1795}
1796
1797
1798template<typename ValueType_, typename Codec_>
1799void
1801{
1802 if (!outputTransient && this->isTransient()) return;
1803
1804 // paged compression only applies when Blosc compression is requested
1805 bool bloscCompression = io::getDataCompression(os.getOutputStream()) & io::COMPRESS_BLOSC;
1806 if (!bloscCompression) {
1807 if (!os.sizeOnly()) this->writeBuffers(os.getOutputStream(), outputTransient);
1808 return;
1809 }
1810
1811 if (mFlags & PARTIALREAD) {
1812 OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1813 }
1814
1815 os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1816}
1817
1818
1819template<typename ValueType_, typename Codec_>
1832
1833
1834template<typename ValueType_, typename Codec_>
1835bool
1836TypedAttributeArray<ValueType_, Codec_>::isEqual(const AttributeArray& other) const
1837{
1838 const TypedAttributeArray<ValueType_, Codec_>* const otherT = dynamic_cast<const TypedAttributeArray<ValueType_, Codec_>* >(&other);
1839 if(!otherT) return false;
1840 if(this->mSize != otherT->mSize ||
1841 this->mStrideOrTotalSize != otherT->mStrideOrTotalSize ||
1842 this->mIsUniform != otherT->mIsUniform ||
1843 this->attributeType() != this->attributeType()) return false;
1844
1845 const StorageType *target = this->data(), *source = otherT->data();
1846 if (!target && !source) return true;
1847 if (!target || !source) return false;
1848 Index n = this->mIsUniform ? 1 : mSize;
1849 while (n && math::isExactlyEqual(*target++, *source++)) --n;
1850 return n == 0;
1851}
1852
1853
1854template<typename ValueType_, typename Codec_>
1855char*
1856TypedAttributeArray<ValueType_, Codec_>::dataAsByteArray()
1857{
1858 return reinterpret_cast<char*>(this->data());
1859}
1860
1861
1862template<typename ValueType_, typename Codec_>
1863const char*
1864TypedAttributeArray<ValueType_, Codec_>::dataAsByteArray() const
1865{
1866 return reinterpret_cast<const char*>(this->data());
1867}
1868
1869
1870////////////////////////////////////////
1871
1872
1873/// Accessor to call unsafe get and set methods based on templated Codec and Value
1874template <typename CodecType, typename ValueType>
1876{
1877 using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
1878 using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
1879
1880 /// Getter that calls to TypedAttributeArray::getUnsafe()
1881 /// @note Functor argument is provided but not required for the generic case
1882 static ValueType get(GetterPtr /*functor*/, const AttributeArray* array, const Index n) {
1884 }
1885
1886 /// Getter that calls to TypedAttributeArray::setUnsafe()
1887 /// @note Functor argument is provided but not required for the generic case
1888 static void set(SetterPtr /*functor*/, AttributeArray* array, const Index n, const ValueType& value) {
1890 }
1891};
1892
1893
1894/// Partial specialization when Codec is not known at compile-time to use the supplied functor instead
1895template <typename ValueType>
1896struct AccessorEval<UnknownCodec, ValueType>
1897{
1898 using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
1899 using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
1900
1901 /// Getter that calls the supplied functor
1902 static ValueType get(GetterPtr functor, const AttributeArray* array, const Index n) {
1903 return (*functor)(array, n);
1904 }
1905
1906 /// Setter that calls the supplied functor
1907 static void set(SetterPtr functor, AttributeArray* array, const Index n, const ValueType& value) {
1908 (*functor)(array, n, value);
1909 }
1910};
1911
1912
1913////////////////////////////////////////
1914
1915// AttributeHandle implementation
1916
1917template <typename ValueType, typename CodecType>
1918typename AttributeHandle<ValueType, CodecType>::Ptr
1920{
1922 new AttributeHandle<ValueType, CodecType>(array, collapseOnDestruction));
1923}
1924
1925template <typename ValueType, typename CodecType>
1927 : mArray(&array)
1928 , mStrideOrTotalSize(array.hasConstantStride() ? array.stride() : 1)
1929 , mSize(array.hasConstantStride() ? array.size() : array.dataSize())
1930 , mCollapseOnDestruction(collapseOnDestruction && array.isStreaming())
1931{
1932 if (!this->compatibleType<std::is_same<CodecType, UnknownCodec>::value>()) {
1933 OPENVDB_THROW(TypeError, "Cannot bind handle due to incompatible type of AttributeArray.");
1934 }
1935
1936 // bind getter and setter methods
1937
1938 AttributeArray::AccessorBasePtr accessor = mArray->getAccessor();
1939 OPENVDB_ASSERT(accessor);
1940
1941 AttributeArray::Accessor<ValueType>* typedAccessor = static_cast<AttributeArray::Accessor<ValueType>*>(accessor.get());
1942
1943 mGetter = typedAccessor->mGetter;
1944 mSetter = typedAccessor->mSetter;
1945 mCollapser = typedAccessor->mCollapser;
1946 mFiller = typedAccessor->mFiller;
1947}
1948
1949template <typename ValueType, typename CodecType>
1951{
1952 // if enabled, attribute is collapsed on destruction of the handle to save memory
1953 if (mCollapseOnDestruction) const_cast<AttributeArray*>(this->mArray)->collapse();
1954}
1955
1956template <typename ValueType, typename CodecType>
1957template <bool IsUnknownCodec>
1958typename std::enable_if<IsUnknownCodec, bool>::type
1959AttributeHandle<ValueType, CodecType>::compatibleType() const
1960{
1961 // if codec is unknown, just check the value type
1962
1963 return mArray->hasValueType<ValueType>();
1964}
1965
1966template <typename ValueType, typename CodecType>
1967template <bool IsUnknownCodec>
1968typename std::enable_if<!IsUnknownCodec, bool>::type
1969AttributeHandle<ValueType, CodecType>::compatibleType() const
1970{
1971 // if the codec is known, check the value type and codec
1972
1973 return mArray->isType<TypedAttributeArray<ValueType, CodecType>>();
1974}
1975
1976template <typename ValueType, typename CodecType>
1982
1983template <typename ValueType, typename CodecType>
1985{
1986 Index index = n * mStrideOrTotalSize + m;
1987 OPENVDB_ASSERT(index < (mSize * mStrideOrTotalSize));
1988 return index;
1989}
1990
1991template <typename ValueType, typename CodecType>
1996
1997template <typename ValueType, typename CodecType>
1998template <bool IsUnknownCodec>
1999typename std::enable_if<IsUnknownCodec, ValueType>::type
2001{
2002 // if the codec is unknown, use the getter functor
2003
2004 return (*mGetter)(mArray, index);
2005}
2006
2007template <typename ValueType, typename CodecType>
2008template <bool IsUnknownCodec>
2009typename std::enable_if<!IsUnknownCodec, ValueType>::type
2011{
2012 // if the codec is known, call the method on the attribute array directly
2013
2015}
2016
2017template <typename ValueType, typename CodecType>
2019{
2020 return mArray->isUniform();
2021}
2022
2023template <typename ValueType, typename CodecType>
2025{
2026 return mArray->hasConstantStride();
2027}
2028
2029////////////////////////////////////////
2030
2031// AttributeWriteHandle implementation
2032
2033template <typename ValueType, typename CodecType>
2040
2041template <typename ValueType, typename CodecType>
2043 : AttributeHandle<ValueType, CodecType>(array, /*collapseOnDestruction=*/false)
2044{
2045 if (expand) array.expand();
2046}
2047
2048template <typename ValueType, typename CodecType>
2050{
2051 this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, 0), value);
2052}
2053
2054template <typename ValueType, typename CodecType>
2056{
2057 this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m), value);
2058}
2059
2060template <typename ValueType, typename CodecType>
2062{
2063 const_cast<AttributeArray*>(this->mArray)->expand(fill);
2064}
2065
2066template <typename ValueType, typename CodecType>
2071
2072template <typename ValueType, typename CodecType>
2074{
2075 return const_cast<AttributeArray*>(this->mArray)->compact();
2076}
2077
2078template <typename ValueType, typename CodecType>
2080{
2081 this->mCollapser(const_cast<AttributeArray*>(this->mArray), uniformValue);
2082}
2083
2084template <typename ValueType, typename CodecType>
2086{
2087 this->mFiller(const_cast<AttributeArray*>(this->mArray), value);
2088}
2089
2090template <typename ValueType, typename CodecType>
2091template <bool IsUnknownCodec>
2092typename std::enable_if<IsUnknownCodec, void>::type
2093AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2094{
2095 // if the codec is unknown, use the setter functor
2096
2097 (*this->mSetter)(const_cast<AttributeArray*>(this->mArray), index, value);
2098}
2099
2100template <typename ValueType, typename CodecType>
2101template <bool IsUnknownCodec>
2102typename std::enable_if<!IsUnknownCodec, void>::type
2103AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2104{
2105 // if the codec is known, call the method on the attribute array directly
2106
2107 TypedAttributeArray<ValueType, CodecType>::setUnsafe(const_cast<AttributeArray*>(this->mArray), index, value);
2108}
2109
2110template <typename ValueType, typename CodecType>
2116
2117
2118} // namespace points
2119} // namespace OPENVDB_VERSION_NAME
2120} // namespace openvdb
2121
2122#endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Index Iterators.
#define OPENVDB_API
Definition Platform.h:286
#define OPENVDB_DEPRECATED_MESSAGE(msg)
Definition Platform.h:158
Convenience wrappers to using Blosc and reading and writing of Paged data.
Definition Exceptions.h:57
Definition Exceptions.h:58
Base class for storing metadata information in a grid.
Definition Metadata.h:25
Definition Exceptions.h:64
Templated metadata class to hold specific types.
Definition Metadata.h:123
T & value()
Return this metadata's value.
Definition Metadata.h:250
Definition Exceptions.h:65
A Paging wrapper to std::istream that is responsible for reading from a given input stream and creati...
Definition StreamCompression.h:208
PageHandle::Ptr createHandle(std::streamsize n)
Creates a PageHandle to access the next.
void skip(PageHandle::Ptr &pageHandle, std::streamsize n)
Skip past the page data referenced by pageHandle without reading or decompressing it.
bool sizeOnly() const
Definition StreamCompression.h:218
void read(PageHandle::Ptr &pageHandle, std::streamsize n, bool delayed=true)
Takes a pageHandle and updates the referenced page with the current stream pointer position and if de...
std::istream & getInputStream()
Definition StreamCompression.h:221
A Paging wrapper to std::ostream that is responsible for writing from a given output stream at interv...
Definition StreamCompression.h:249
std::ostream & getOutputStream()
Set and get the output stream.
Definition StreamCompression.h:262
bool sizeOnly() const
Definition StreamCompression.h:259
PagedOutputStream & write(const char *str, std::streamsize n)
Writes the given.
static Vec3s unpack(const uint16_t data)
Definition QuantizedUnitVec.h:86
static uint16_t pack(const Vec3< T > &vec)
Definition QuantizedUnitVec.h:48
Definition Vec3.h:25
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
Definition Vec3.h:86
T & y()
Definition Vec3.h:87
T & z()
Definition Vec3.h:88
Base class for storing attribute data.
Definition AttributeArray.h:94
virtual Name valueType() const =0
Return the name of the value type of a single element in this array (e.g., "float" or "vec3d").
const char * constDataAsByteArray() const
Indirect virtual function to retrieve the data buffer cast to a char byte array.
Definition AttributeArray.h:335
AttributeArray(const AttributeArray &rhs, const tbb::spin_mutex::scoped_lock &)
void setConstantStride(bool state)
Specify whether this attribute has a constant stride or not.
static Ptr create(const NamePair &type, Index length, Index stride=1, bool constantStride=true, const Metadata *metadata=nullptr, const ScopedRegistryLock *lock=nullptr)
bool isTransient() const
Return true if this attribute is not serialized during stream output.
Definition AttributeArray.h:274
SerializationFlag
Definition AttributeArray.h:110
@ WRITESTRIDED
Definition AttributeArray.h:111
@ WRITEUNIFORM
data is marked as strided when written
Definition AttributeArray.h:112
@ WRITEPAGED
Definition AttributeArray.h:115
@ WRITEMEMCOMPRESS
data is marked as uniform when written
Definition AttributeArray.h:113
AttributeArray & operator=(const AttributeArray &rhs)
virtual Index dataSize() const =0
virtual bool isUniform() const =0
Return true if this array is stored as a single uniform value.
virtual void readBuffers(std::istream &)=0
Read attribute buffers from a stream.
std::shared_ptr< AttributeArray > Ptr
Definition AttributeArray.h:126
virtual ~AttributeArray()
Definition AttributeArray.h:134
Flag
Definition AttributeArray.h:102
@ TRANSIENT
Definition AttributeArray.h:103
@ PARTIALREAD
streaming mode collapses attributes when first accessed
Definition AttributeArray.h:107
@ HIDDEN
by default not written to disk
Definition AttributeArray.h:104
@ CONSTANTSTRIDE
hidden from UIs or iterators
Definition AttributeArray.h:105
@ STREAMING
stride size does not vary in the array
Definition AttributeArray.h:106
AttributeArray()
Definition AttributeArray.h:133
virtual Index stride() const =0
bool isHidden() const
Return true if this attribute is hidden (e.g., from UI or iterators).
Definition AttributeArray.h:267
bool isType() const
Return true if this attribute is of the same type as the template parameter.
Definition AttributeArray.h:214
virtual bool valueTypeIsQuaternion() const =0
Return true if the value type is a quaternion.
virtual bool valueTypeIsVector() const =0
Return true if the value type is a vector.
void copyValuesUnsafe(const AttributeArray &sourceArray, const IterT &iter)
Copy values into this array from a source array to a target array as referenced by an iterator.
Definition AttributeArray.h:1010
uint8_t mFlags
Definition AttributeArray.h:371
virtual AccessorBasePtr getAccessor() const =0
Obtain an Accessor that stores getter and setter functors.
void setStreaming(bool state)
Specify whether this attribute is to be streamed off disk, in which case, the attributes are collapse...
AttributeArray(const AttributeArray &rhs)
uint8_t flags() const
Retrieve the attribute array flags.
Definition AttributeArray.h:288
bool hasValueType() const
Return true if this attribute has a value type the same as the template parameter.
Definition AttributeArray.h:218
virtual void writeBuffers(std::ostream &, bool outputTransient) const =0
static void clearRegistry(const ScopedRegistryLock *lock=nullptr)
Clear the attribute type registry.
std::shared_ptr< AccessorBase > AccessorBasePtr
Definition AttributeArray.h:99
void setTransient(bool state)
Specify whether this attribute should only exist in memory and not be serialized during stream output...
virtual void read(std::istream &)=0
Read attribute metadata and buffers from a stream.
void copyValues(const AttributeArray &sourceArray, const IterT &iter, bool compact=true)
Like copyValuesUnsafe(), but if compact is true, attempt to collapse this array.
Definition AttributeArray.h:1016
void setHidden(bool state)
Specify whether this attribute should be hidden (e.g., from UI or iterators).
virtual void write(std::ostream &, bool outputTransient) const =0
virtual bool compact()=0
Compact the existing array to become uniform if all values are identical.
virtual void readPagedBuffers(compression::PagedInputStream &)=0
Read attribute buffers from a paged stream.
void skipPagedBuffers(compression::PagedInputStream &)
Definition AttributeArray.h:1643
virtual bool valueTypeIsClass() const =0
Return true if the value type is a class (ie vector, matrix or quaternion return true)
uint8_t mUsePagedRead
Definition AttributeArray.h:372
virtual bool valueTypeIsMatrix() const =0
Return true if the value type is a matrix.
bool operator==(const AttributeArray &other) const
tbb::spin_mutex mMutex
Definition AttributeArray.h:370
bool operator!=(const AttributeArray &other) const
Definition AttributeArray.h:332
bool isStreaming() const
Return true if this attribute is in streaming mode.
Definition AttributeArray.h:282
std::unique_ptr< compression::PageHandle > mPageHandle
Definition AttributeArray.h:378
virtual void writeMetadata(std::ostream &, bool outputTransient, bool paged) const =0
AttributeArray & operator=(AttributeArray &&)=delete
static bool isRegistered(const NamePair &type, const ScopedRegistryLock *lock=nullptr)
Return true if the given attribute type name is registered.
Ptr(*)(Index, Index, bool, const Metadata *) FactoryMethod
Definition AttributeArray.h:129
virtual Name codecType() const =0
Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
friend class AttributeHandle
Definition AttributeArray.h:131
virtual void readMetadata(std::istream &)=0
Read attribute metadata from a stream.
std::shared_ptr< const AttributeArray > ConstPtr
Definition AttributeArray.h:127
virtual void collapse()=0
Replace the existing array with a uniform zero value.
virtual void writePagedBuffers(compression::PagedOutputStream &, bool outputTransient) const =0
virtual Index storageTypeSize() const =0
virtual void write(std::ostream &) const =0
Write attribute metadata and buffers to a stream, don't write transient attributes.
static void registerType(const NamePair &type, FactoryMethod, const ScopedRegistryLock *lock=nullptr)
Register a attribute type along with a factory function.
virtual AttributeArray::Ptr copy() const =0
Return a copy of this attribute.
virtual Index valueTypeSize() const =0
virtual bool valueTypeIsFloatingPoint() const =0
Return true if the value type is floating point.
static void unregisterType(const NamePair &type, const ScopedRegistryLock *lock=nullptr)
Remove a attribute type from the registry.
bool hasConstantStride() const
Return true if this attribute has a constant stride.
Definition AttributeArray.h:285
virtual const NamePair & type() const =0
Return the name of this attribute's type.
size_t mCompressedBytes
Definition AttributeArray.h:379
bool mIsUniform
Definition AttributeArray.h:369
virtual void expand(bool fill=true)=0
If this array is uniform, replace it with an array of length size().
virtual size_t memUsage() const =0
Return the number of bytes of memory used by this attribute.
AttributeArray(AttributeArray &&)=delete
virtual ~AttributeHandle()
Definition AttributeArray.h:1950
Index size() const
Definition AttributeArray.h:785
void(*)(AttributeArray *array, const ValueType &value) ValuePtr
Definition AttributeArray.h:772
SetterPtr mSetter
Definition AttributeArray.h:800
Index stride() const
Definition AttributeArray.h:784
std::shared_ptr< Handle > Ptr
Definition AttributeArray.h:766
GetterPtr mGetter
Definition AttributeArray.h:799
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition AttributeArray.h:771
static Ptr create(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition AttributeArray.h:1919
AttributeHandle(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition AttributeArray.h:1926
ValueType get(Index n, Index m=0) const
Definition AttributeArray.h:1992
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition AttributeArray.h:770
AttributeHandle(const AttributeHandle &)=default
AttributeHandle< ValueType, CodecType > Handle
Definition AttributeArray.h:765
ValuePtr mCollapser
Definition AttributeArray.h:801
const AttributeArray * mArray
Definition AttributeArray.h:797
bool isUniform() const
Definition AttributeArray.h:2018
std::unique_ptr< Handle > UniquePtr
Definition AttributeArray.h:767
bool hasConstantStride() const
Definition AttributeArray.h:2024
AttributeHandle & operator=(const AttributeHandle &)=default
Index index(Index n, Index m) const
Definition AttributeArray.h:1984
AttributeWriteHandle(AttributeArray &array, const bool expand=true)
Definition AttributeArray.h:2042
std::shared_ptr< Handle > Ptr
Definition AttributeArray.h:834
bool compact()
Compact the existing array to become uniform if all values are identical.
Definition AttributeArray.h:2073
void collapse()
Replace the existing array with a uniform value (zero if none provided).
Definition AttributeArray.h:2067
void set(Index n, const ValueType &value)
Definition AttributeArray.h:2049
std::unique_ptr< Handle > ScopedPtr
Definition AttributeArray.h:835
AttributeWriteHandle< ValueType, CodecType > Handle
Definition AttributeArray.h:833
static Ptr create(AttributeArray &array, const bool expand=true)
Definition AttributeArray.h:2035
void set(Index n, Index m, const ValueType &value)
Definition AttributeArray.h:2055
void collapse(const ValueType &uniformValue)
Definition AttributeArray.h:2079
Typed class for storing attribute data.
Definition AttributeArray.h:518
Index valueTypeSize() const override
Return the size in bytes of the value type of a single element in this array.
Definition AttributeArray.h:596
void write(std::ostream &) const override
Write attribute data to a stream, don't write transient attributes.
Definition AttributeArray.h:1687
void getUnsafe(Index n, T &value) const
Return the value at index n (assumes in-core)
Definition AttributeArray.h:1318
ValueType getUnsafe(Index n) const
Return the value at index n (assumes in-core)
Definition AttributeArray.h:1295
bool isUniform() const override
Return true if this array is stored as a single uniform value.
Definition AttributeArray.h:652
void readBuffers(std::istream &) override
Read attribute buffers from a stream.
Definition AttributeArray.h:1559
std::shared_ptr< TypedAttributeArray > Ptr
Definition AttributeArray.h:520
AccessorBasePtr getAccessor() const override
Obtain an Accessor that stores getter and setter functors.
Definition AttributeArray.h:1821
void write(std::ostream &os, bool outputTransient) const override
Definition AttributeArray.h:1695
typename Codec::template Storage< ValueType >::Type StorageType
Definition AttributeArray.h:525
size_t memUsage() const override
Return the number of bytes of memory used by this attribute.
Definition AttributeArray.h:1287
ValueType_ ValueType
Definition AttributeArray.h:523
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:1048
std::shared_ptr< const TypedAttributeArray > ConstPtr
Definition AttributeArray.h:521
bool valueTypeIsVector() const override
Return true if the value type is a vector.
Definition AttributeArray.h:1261
static TypedAttributeArray & cast(AttributeArray &attributeArray)
Cast an AttributeArray to TypedAttributeArray<T>
Definition AttributeArray.h:1172
TypedAttributeArray & operator=(TypedAttributeArray &&)=delete
Move assignment operator disabled.
void writeBuffers(std::ostream &os, bool outputTransient) const override
Definition AttributeArray.h:1760
AttributeArray::Ptr copy() const override
Definition AttributeArray.h:1192
Index storageTypeSize() const override
Definition AttributeArray.h:600
bool valueTypeIsQuaternion() const override
Return true if the value type is a quaternion.
Definition AttributeArray.h:1269
void readPagedBuffers(compression::PagedInputStream &) override
Read attribute buffers from a paged stream.
Definition AttributeArray.h:1606
void set(Index n, const ValueType &value)
Set value at the given index n.
Definition AttributeArray.h:1357
TypedAttributeArray & operator=(const TypedAttributeArray &)
Definition AttributeArray.h:1098
static void registerType()
Register this attribute type along with a factory function.
Definition AttributeArray.h:1144
bool valueTypeIsFloatingPoint() const override
Return true if the value type is floating point.
Definition AttributeArray.h:1232
void writeMetadata(std::ostream &os, bool outputTransient, bool paged) const override
Definition AttributeArray.h:1704
static void unregisterType()
Remove this attribute type from the registry.
Definition AttributeArray.h:1152
const StorageType * data() const
Definition AttributeArray.h:720
void read(std::istream &) override
Read attribute data from a stream.
Definition AttributeArray.h:1481
ValueType get(Index n) const
Return the value at index n.
Definition AttributeArray.h:1307
TypedAttributeArray(TypedAttributeArray &&)=delete
Move constructor disabled.
static const NamePair & attributeType()
Return the name of this attribute's type (includes codec)
Definition AttributeArray.h:1125
TypedAttributeArray(const TypedAttributeArray &)
Definition AttributeArray.h:1076
static void fill(AttributeArray *array, const ValueType &value)
Non-member equivalent to fill() that static_casts array to this TypedAttributeArray.
Definition AttributeArray.h:1473
static void collapse(AttributeArray *array, const ValueType &value)
Non-member equivalent to collapse() that static_casts array to this TypedAttributeArray.
Definition AttributeArray.h:1454
const NamePair & type() const override
Return the name of this attribute's type.
Definition AttributeArray.h:568
static const TypedAttributeArray & cast(const AttributeArray &attributeArray)
Cast an AttributeArray to TypedAttributeArray<T>
Definition AttributeArray.h:1182
bool valueTypeIsClass() const override
Return true if the value type is a class (ie vector, matrix or quaternion return true)
Definition AttributeArray.h:1252
Index size() const override
Return the number of elements in this array.
Definition AttributeArray.h:578
void collapse() override
Replace the existing array with a uniform zero value.
Definition AttributeArray.h:1432
Index dataSize() const override
Return the size of the data in this array.
Definition AttributeArray.h:585
Codec_ Codec
Definition AttributeArray.h:524
~TypedAttributeArray() override
Definition AttributeArray.h:549
void expand(bool fill=true) override
Replace the single value storage with an array of length size().
Definition AttributeArray.h:1394
static bool isRegistered()
Return true if this attribute type is registered.
Definition AttributeArray.h:1136
bool valueTypeIsMatrix() const override
Return true if the value type is a matrix.
Definition AttributeArray.h:1278
static ValueType getUnsafe(const AttributeArray *array, const Index n)
Definition AttributeArray.h:1335
const StorageType * constData() const
Return the raw data buffer.
Definition AttributeArray.h:713
void collapse(const ValueType &uniformValue)
Replace the existing array with the given uniform value.
Definition AttributeArray.h:1440
void set(Index n, const T &value)
Set value at the given index n.
Definition AttributeArray.h:1378
Index stride() const override
Definition AttributeArray.h:582
static Ptr create(Index n, Index strideOrTotalSize=1, bool constantStride=true, const Metadata *metadata=nullptr)
Return a new attribute array of the given length n and stride with uniform value zero.
Definition AttributeArray.h:1160
Name codecType() const override
Return the name of the codec used by this array (e.g., "trnc" or "fxpt").
Definition AttributeArray.h:593
void writePagedBuffers(compression::PagedOutputStream &os, bool outputTransient) const override
Definition AttributeArray.h:1800
Name valueType() const override
Return the name of the value type of a single element in this array (e.g., "float" or "vec3d").
Definition AttributeArray.h:590
void setUnsafe(Index n, const T &value)
Set value at the given index n (assumes in-core)
Definition AttributeArray.h:1369
void setUnsafe(Index n, const ValueType &value)
Set value at the given index n (assumes in-core)
Definition AttributeArray.h:1343
static void setUnsafe(AttributeArray *array, const Index n, const ValueType &value)
Definition AttributeArray.h:1386
void readMetadata(std::istream &) override
Read attribute metadata from a stream.
Definition AttributeArray.h:1490
void get(Index n, T &value) const
Return the value at index n.
Definition AttributeArray.h:1327
#define OPENVDB_LOG_WARN(message)
Log a warning message of the form 'someVar << "some text" << ...'.
Definition logging.h:163
size_t bloscCompressedSize(const char *buffer, const size_t uncompressedBytes)
Convenience wrapper to retrieve the compressed size of buffer when compressed.
void bloscCompress(char *compressedBuffer, size_t &compressedBytes, const size_t bufferBytes, const char *uncompressedBuffer, const size_t uncompressedBytes)
Compress into the supplied buffer.
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...
void bloscValidateCompressedBytes(const char *buffer, const size_t bufferBytes)
Throws an IoError if the Blosc header of buffer does not fit in bufferBytes or reports more compresse...
@ COMPRESS_BLOSC
Definition Compression.h:56
uint32_t getDataCompression(std::ios_base &)
Return a bitwise OR of compression option flags (COMPRESS_ZIP, COMPRESS_ACTIVE_MASK,...
SharedPtr< StreamMetadata > getStreamMetadataPtr(std::ios_base &)
Return a shared pointer to an object that stores metadata (file format, compression scheme,...
Definition Types.h:763
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition Math.h:465
internal::half half
Definition HalfDecl.h:25
Definition AttributeArray.h:413
Definition IndexIterator.h:35
Definition Grid.h:1187
FloatT fixedPointToFloatingPoint(const IntegerT s)
Definition AttributeArray.h:62
IntegerT floatingPointToFixedPoint(const FloatT s)
Definition AttributeArray.h:51
std::string Name
Definition Name.h:19
Index32 Index
Definition Types.h:34
int16_t Int16
Definition Types.h:35
std::pair< Name, Name > NamePair
Definition AttributeArray.h:40
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
Definition Math.h:71
uint64_t Index64
Definition Types.h:33
const char * typeNameAsString()
Definition Types.h:587
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
static const bool IsVec
Definition Types.h:297
typename T::ValueType ElementType
Definition Types.h:299
static ValueType get(GetterPtr functor, const AttributeArray *array, const Index n)
Getter that calls the supplied functor.
Definition AttributeArray.h:1902
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition AttributeArray.h:1899
static void set(SetterPtr functor, AttributeArray *array, const Index n, const ValueType &value)
Setter that calls the supplied functor.
Definition AttributeArray.h:1907
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition AttributeArray.h:1898
Accessor to call unsafe get and set methods based on templated Codec and Value.
Definition AttributeArray.h:1876
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition AttributeArray.h:1878
static ValueType get(GetterPtr, const AttributeArray *array, const Index n)
Definition AttributeArray.h:1882
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition AttributeArray.h:1877
static void set(SetterPtr, AttributeArray *array, const Index n, const ValueType &value)
Definition AttributeArray.h:1888
Accessor base class for AttributeArray storage where type is not available.
Definition AttributeArray.h:388
SetterPtr mSetter
Definition AttributeArray.h:403
GetterPtr mGetter
Definition AttributeArray.h:402
void(*)(AttributeArray *array, const T &value) ValuePtr
Definition AttributeArray.h:397
T(*)(const AttributeArray *array, const Index n) GetterPtr
Definition AttributeArray.h:395
void(*)(AttributeArray *array, const Index n, const T &value) SetterPtr
Definition AttributeArray.h:396
ValuePtr mFiller
Definition AttributeArray.h:405
Accessor(GetterPtr getter, SetterPtr setter, ValuePtr collapser, ValuePtr filler)
Definition AttributeArray.h:399
ValuePtr mCollapser
Definition AttributeArray.h:404
typename attribute_traits::UIntTypeTrait< OneByte, T >::Type Type
Definition AttributeArray.h:486
Definition AttributeArray.h:484
static void encode(const ValueType &, StorageType &)
Definition AttributeArray.h:928
static void decode(const StorageType &, ValueType &)
Definition AttributeArray.h:915
static const char * name()
Definition AttributeArray.h:491
Definition AttributeArray.h:445
T Type
Definition AttributeArray.h:445
Definition AttributeArray.h:443
static void encode(const ValueType &, ValueType &)
Definition AttributeArray.h:890
static const char * name()
Definition AttributeArray.h:449
static void decode(const ValueType &, ValueType &)
Definition AttributeArray.h:882
Definition AttributeArray.h:466
static ValueType decode(const ValueType &value)
Definition AttributeArray.h:469
static ValueType encode(const ValueType &value)
Definition AttributeArray.h:468
static const char * name()
Definition AttributeArray.h:467
static const char * name()
Definition AttributeArrayString.h:45
Definition AttributeArray.h:456
typename attribute_traits::TruncateTrait< T >::Type Type
Definition AttributeArray.h:456
Definition AttributeArray.h:454
static void encode(const ValueType &, StorageType &)
Definition AttributeArray.h:906
static void decode(const StorageType &, ValueType &)
Definition AttributeArray.h:898
static const char * name()
Definition AttributeArray.h:460
Definition AttributeArray.h:475
static ValueType decode(const ValueType &value)
Definition AttributeArray.h:478
static ValueType encode(const ValueType &value)
Definition AttributeArray.h:477
static const char * name()
Definition AttributeArray.h:476
Definition AttributeArray.h:503
StorageType Type
Definition AttributeArray.h:503
Definition AttributeArray.h:499
uint16_t StorageType
Definition AttributeArray.h:500
static void decode(const StorageType &, math::Vec3< T > &)
Definition AttributeArray.h:940
static void encode(const math::Vec3< T > &, StorageType &)
Definition AttributeArray.h:948
static const char * name()
Definition AttributeArray.h:507
Definition AttributeArray.h:439
math::Vec3< typename TruncateTrait< T >::Type > Type
Definition AttributeArray.h:419
math::Vec3< uint16_t > Type
Definition AttributeArray.h:429
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:291