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