OpenVDB 12.0.0
 
Loading...
Searching...
No Matches
AttributeArray.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/// @file points/AttributeArray.h
5///
6/// @authors Dan Bailey, Mihai Alden, Nick Avramoussis, James Bird, Khang Ngo
7///
8/// @brief Attribute Array storage templated on type and compression codec.
9
10#ifndef OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
11#define OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
12
13#include <openvdb/Types.h>
15#include <openvdb/util/Name.h>
17#include <openvdb/util/Assert.h>
18#include <openvdb/io/io.h> // 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 // local copy of AttributeArray (to preserve compression)
821 AttributeArray::Ptr mLocalArray;
822
823 Index mStrideOrTotalSize;
824 Index mSize;
825 bool mCollapseOnDestruction;
826}; // class AttributeHandle
827
828
829////////////////////////////////////////
830
831
832/// Write-able version of AttributeHandle
833template <typename ValueType, typename CodecType = UnknownCodec>
834class AttributeWriteHandle : public AttributeHandle<ValueType, CodecType>
835{
836public:
838 using Ptr = std::shared_ptr<Handle>;
839 using ScopedPtr = std::unique_ptr<Handle>;
840
841 static Ptr create(AttributeArray& array, const bool expand = true);
842
844
845 virtual ~AttributeWriteHandle() = default;
846
847 /// @brief If this array is uniform, replace it with an array of length size().
848 /// @param fill if true, assign the uniform value to each element of the array.
849 void expand(bool fill = true);
850
851 /// Replace the existing array with a uniform value (zero if none provided).
852 void collapse();
853 void collapse(const ValueType& uniformValue);
854
855 /// Compact the existing array to become uniform if all values are identical
856 bool compact();
857
858 /// @brief Fill the existing array with the given value.
859 /// @note Identical to collapse() except a non-uniform array will not become uniform.
860 void fill(const ValueType& value);
861
862 void set(Index n, const ValueType& value);
863 void set(Index n, Index m, const ValueType& value);
864
866
867private:
868 friend class ::TestAttributeArray;
869
870 template <bool IsUnknownCodec>
871 typename std::enable_if<IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
872
873 template <bool IsUnknownCodec>
874 typename std::enable_if<!IsUnknownCodec, void>::type set(Index index, const ValueType& value) const;
875}; // class AttributeWriteHandle
876
877
878////////////////////////////////////////
879
880
881// Attribute codec implementation
882
883
884template<typename ValueType>
885inline void
886NullCodec::decode(const ValueType& data, ValueType& val)
887{
888 val = data;
889}
890
891
892template<typename ValueType>
893inline void
894NullCodec::encode(const ValueType& val, ValueType& data)
895{
896 data = val;
897}
898
899
900template<typename StorageType, typename ValueType>
901inline void
902TruncateCodec::decode(const StorageType& data, ValueType& val)
903{
904 val = static_cast<ValueType>(data);
905}
906
907
908template<typename StorageType, typename ValueType>
909inline void
910TruncateCodec::encode(const ValueType& val, StorageType& data)
911{
912 data = static_cast<StorageType>(val);
913}
914
915
916template <bool OneByte, typename Range>
917template<typename StorageType, typename ValueType>
918inline void
919FixedPointCodec<OneByte, Range>::decode(const StorageType& data, ValueType& val)
920{
922
923 // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
924
925 val = Range::template decode<ValueType>(val);
926}
927
928
929template <bool OneByte, typename Range>
930template<typename StorageType, typename ValueType>
931inline void
932FixedPointCodec<OneByte, Range>::encode(const ValueType& val, StorageType& data)
933{
934 // shift value range to be -0.5 => 0.5 (as this is most commonly used for position)
935
936 const ValueType newVal = Range::template encode<ValueType>(val);
937
939}
940
941
942template<typename T>
943inline void
948
949
950template<typename T>
951inline void
956
957
958////////////////////////////////////////
959
960// AttributeArray implementation
961
962template <typename IterT>
963void AttributeArray::doCopyValues(const AttributeArray& sourceArray, const IterT& iter,
964 bool rangeChecking/*=true*/)
965{
966 // ensure both arrays have float-float or integer-integer value types
967 OPENVDB_ASSERT(sourceArray.valueTypeIsFloatingPoint() == this->valueTypeIsFloatingPoint());
968 // ensure both arrays have been loaded from disk (if delay-loaded)
969 OPENVDB_ASSERT(sourceArray.isDataLoaded() && this->isDataLoaded());
970 // ensure storage size * stride matches on both arrays
971 OPENVDB_ASSERT(this->storageTypeSize()*this->stride() ==
972 sourceArray.storageTypeSize()*sourceArray.stride());
973
974 const size_t bytes(sourceArray.storageTypeSize()*sourceArray.stride());
975 const char* const sourceBuffer = sourceArray.dataAsByteArray();
976 char* const targetBuffer = this->dataAsByteArray();
977 OPENVDB_ASSERT(sourceBuffer && targetBuffer);
978
979 if (rangeChecking && this->isUniform()) {
980 OPENVDB_THROW(IndexError, "Cannot copy array data as target array is uniform.");
981 }
982
983 const bool sourceIsUniform = sourceArray.isUniform();
984
985 const Index sourceDataSize = rangeChecking ? sourceArray.dataSize() : 0;
986 const Index targetDataSize = rangeChecking ? this->dataSize() : 0;
987
988 for (IterT it(iter); it; ++it) {
989 const Index sourceIndex = sourceIsUniform ? 0 : it.sourceIndex();
990 const Index targetIndex = it.targetIndex();
991
992 if (rangeChecking) {
993 if (sourceIndex >= sourceDataSize) {
995 "Cannot copy array data as source index exceeds size of source array.");
996 }
997 if (targetIndex >= targetDataSize) {
999 "Cannot copy array data as target index exceeds size of target array.");
1000 }
1001 } else {
1002 // range-checking asserts
1003 OPENVDB_ASSERT(sourceIndex < sourceArray.dataSize());
1004 OPENVDB_ASSERT(targetIndex < this->dataSize());
1005 if (this->isUniform()) OPENVDB_ASSERT(targetIndex == Index(0));
1006 }
1007
1008 const size_t targetOffset(targetIndex * bytes);
1009 const size_t sourceOffset(sourceIndex * bytes);
1010
1011 std::memcpy(targetBuffer + targetOffset, sourceBuffer + sourceOffset, bytes);
1012 }
1013}
1014
1015template <typename IterT>
1016void AttributeArray::copyValuesUnsafe(const AttributeArray& sourceArray, const IterT& iter)
1017{
1018 this->doCopyValues(sourceArray, iter, /*range-checking=*/false);
1019}
1020
1021template <typename IterT>
1022void AttributeArray::copyValues(const AttributeArray& sourceArray, const IterT& iter,
1023 bool compact/* = true*/)
1024{
1025 const Index bytes = sourceArray.storageTypeSize();
1026 if (bytes != this->storageTypeSize()) {
1027 OPENVDB_THROW(TypeError, "Cannot copy array data due to mis-match in storage type sizes.");
1028 }
1029
1030 // ensure both arrays have been loaded from disk
1031 sourceArray.loadData();
1032 this->loadData();
1033
1034 // if the target array is uniform, expand it first
1035 this->expand();
1036
1037 // TODO: Acquire mutex locks for source and target arrays to ensure that
1038 // value copying is always thread-safe. Note that the unsafe method will be
1039 // faster, but can only be used if neither the source or target arrays are
1040 // modified during copying. Note that this will require a new private
1041 // virtual method with ABI=7 to access the mutex from the derived class.
1042
1043 this->doCopyValues(sourceArray, iter, true);
1044
1045 // attempt to compact target array
1046 if (compact) {
1047 this->compact();
1048 }
1049}
1050
1051
1052////////////////////////////////////////
1053
1054// TypedAttributeArray implementation
1055
1056
1057template<typename ValueType_, typename Codec_>
1059 Index n, Index strideOrTotalSize, bool constantStride, const ValueType& uniformValue)
1060 : AttributeArray()
1061 , mData(new StorageType[1])
1062 , mSize(n)
1063 , mStrideOrTotalSize(strideOrTotalSize)
1064{
1065 if (constantStride) {
1066 this->setConstantStride(true);
1067 if (strideOrTotalSize == 0) {
1068 OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a constant stride requires that " \
1069 "stride to be at least one.")
1070 }
1071 }
1072 else {
1073 this->setConstantStride(false);
1074 if (mStrideOrTotalSize < n) {
1075 OPENVDB_THROW(ValueError, "Creating a TypedAttributeArray with a non-constant stride must have " \
1076 "a total size of at least the number of elements in the array.")
1077 }
1078 }
1079 mSize = std::max(Index(1), mSize);
1080 mStrideOrTotalSize = std::max(Index(1), mStrideOrTotalSize);
1081 Codec::encode(uniformValue, this->data()[0]);
1082}
1083
1084
1085template<typename ValueType_, typename Codec_>
1087 : TypedAttributeArray(rhs, tbb::spin_mutex::scoped_lock(rhs.mMutex))
1088{
1089}
1090
1091
1092template<typename ValueType_, typename Codec_>
1094 const tbb::spin_mutex::scoped_lock& lock)
1095 : AttributeArray(rhs, lock)
1096 , mSize(rhs.mSize)
1097 , mStrideOrTotalSize(rhs.mStrideOrTotalSize)
1098{
1099 if (this->validData()) {
1100 this->allocate();
1101 std::memcpy(static_cast<void*>(this->data()), rhs.data(), this->arrayMemUsage());
1102 }
1103}
1104
1105
1106template<typename ValueType_, typename Codec_>
1107TypedAttributeArray<ValueType_, Codec_>&
1109{
1110 if (&rhs != this) {
1111 // lock both the source and target arrays to ensure thread-safety
1112 tbb::spin_mutex::scoped_lock lock(mMutex);
1113 tbb::spin_mutex::scoped_lock rhsLock(rhs.mMutex);
1114
1115 this->deallocate();
1116
1117 mFlags = rhs.mFlags;
1119 mSize = rhs.mSize;
1120 mStrideOrTotalSize = rhs.mStrideOrTotalSize;
1121 mIsUniform = rhs.mIsUniform;
1122
1123 if (this->validData()) {
1124 this->allocate();
1125 std::memcpy(static_cast<void*>(this->data()), rhs.data(), this->arrayMemUsage());
1126 }
1127 }
1128
1129 return *this;
1130}
1131
1132
1133template<typename ValueType_, typename Codec_>
1134inline const NamePair&
1136{
1137 static NamePair sTypeName = []() {
1138 return NamePair(typeNameAsString<ValueType>(), Codec::name());
1139 }();
1140 return sTypeName;
1141}
1142
1143
1144template<typename ValueType_, typename Codec_>
1145inline bool
1150
1151
1152template<typename ValueType_, typename Codec_>
1153inline void
1158
1159
1160template<typename ValueType_, typename Codec_>
1161inline void
1166
1167
1168template<typename ValueType_, typename Codec_>
1171 const Metadata* metadata)
1172{
1173 const TypedMetadata<ValueType>* typedMetadata = metadata ?
1174 dynamic_cast<const TypedMetadata<ValueType>*>(metadata) : nullptr;
1175
1176 return Ptr(new TypedAttributeArray(n, stride, constantStride,
1177 typedMetadata ? typedMetadata->value() : zeroVal<ValueType>()));
1178}
1179
1180template<typename ValueType_, typename Codec_>
1183{
1184 if (!attributeArray.isType<TypedAttributeArray>()) {
1185 OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1186 }
1187 return static_cast<TypedAttributeArray&>(attributeArray);
1188}
1189
1190template<typename ValueType_, typename Codec_>
1193{
1194 if (!attributeArray.isType<TypedAttributeArray>()) {
1195 OPENVDB_THROW(TypeError, "Invalid Attribute Type");
1196 }
1197 return static_cast<const TypedAttributeArray&>(attributeArray);
1198}
1199
1200template<typename ValueType_, typename Codec_>
1206
1207
1208template<typename ValueType_, typename Codec_>
1209size_t
1210TypedAttributeArray<ValueType_, Codec_>::arrayMemUsage() const
1211{
1212 if (this->isOutOfCore()) return 0;
1213
1214 return (mIsUniform ? 1 : this->dataSize()) * sizeof(StorageType);
1215}
1216
1217
1218template<typename ValueType_, typename Codec_>
1219void
1220TypedAttributeArray<ValueType_, Codec_>::allocate()
1221{
1222 OPENVDB_ASSERT(!mData);
1223 if (mIsUniform) {
1224 mData.reset(new StorageType[1]);
1225 }
1226 else {
1227 const size_t size(this->dataSize());
1228 OPENVDB_ASSERT(size > 0);
1229 mData.reset(new StorageType[size]);
1230 }
1231}
1232
1233
1234template<typename ValueType_, typename Codec_>
1235void
1236TypedAttributeArray<ValueType_, Codec_>::deallocate()
1237{
1238 // detach from file if delay-loaded
1239 if (this->isOutOfCore()) {
1240 this->setOutOfCore(false);
1241 this->mPageHandle.reset();
1242 }
1243 if (mData) mData.reset();
1244}
1245
1246
1247template<typename ValueType_, typename Codec_>
1248bool
1250{
1251 // TODO: Update to use Traits that correctly handle matrices and quaternions.
1252
1253 if (std::is_same<ValueType, Quats>::value ||
1254 std::is_same<ValueType, Quatd>::value ||
1255 std::is_same<ValueType, Mat3s>::value ||
1256 std::is_same<ValueType, Mat3d>::value ||
1257 std::is_same<ValueType, Mat4s>::value ||
1258 std::is_same<ValueType, Mat4d>::value) return true;
1259
1260 using ElementT = typename VecTraits<ValueType>::ElementType;
1261
1262 // half is not defined as float point as expected, so explicitly handle it
1263 return std::is_floating_point<ElementT>::value || std::is_same<math::half, ElementT>::value;
1264}
1265
1266
1267template<typename ValueType_, typename Codec_>
1268bool
1270{
1271 // half is not defined as a non-class type as expected, so explicitly exclude it
1272 return std::is_class<ValueType>::value && !std::is_same<math::half, ValueType>::value;
1273}
1274
1275
1276template<typename ValueType_, typename Codec_>
1277bool
1282
1283
1284template<typename ValueType_, typename Codec_>
1285bool
1287{
1288 // TODO: improve performance by making this a compile-time check using type traits
1289 return !this->valueType().compare(0, 4, "quat");
1290}
1291
1292
1293template<typename ValueType_, typename Codec_>
1294bool
1296{
1297 // TODO: improve performance by making this a compile-time check using type traits
1298 return !this->valueType().compare(0, 3, "mat");
1299}
1300
1301
1302template<typename ValueType_, typename Codec_>
1303size_t
1305{
1306 return sizeof(*this) + (bool(mData) ? this->arrayMemUsage() : 0);
1307}
1308
1309
1310template<typename ValueType_, typename Codec_>
1311size_t
1313{
1314 return sizeof(*this) + (mIsUniform ? 1 : this->dataSize()) * sizeof(StorageType);
1315}
1316
1317
1318template<typename ValueType_, typename Codec_>
1321{
1322 OPENVDB_ASSERT(n < this->dataSize());
1323
1324 ValueType val;
1325 Codec::decode(/*in=*/this->data()[mIsUniform ? 0 : n], /*out=*/val);
1326 return val;
1327}
1328
1329
1330template<typename ValueType_, typename Codec_>
1333{
1334 if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1335 if (this->isOutOfCore()) this->doLoad();
1336
1337 return this->getUnsafe(n);
1338}
1339
1340
1341template<typename ValueType_, typename Codec_>
1342template<typename T>
1343void
1345{
1346 val = static_cast<T>(this->getUnsafe(n));
1347}
1348
1349
1350template<typename ValueType_, typename Codec_>
1351template<typename T>
1352void
1354{
1355 val = static_cast<T>(this->get(n));
1356}
1357
1358
1359template<typename ValueType_, typename Codec_>
1362{
1363 return static_cast<const TypedAttributeArray<ValueType, Codec>*>(array)->getUnsafe(n);
1364}
1365
1366
1367template<typename ValueType_, typename Codec_>
1368void
1370{
1371 OPENVDB_ASSERT(n < this->dataSize());
1372 OPENVDB_ASSERT(!this->isOutOfCore());
1373 OPENVDB_ASSERT(!this->isUniform());
1374
1375 // this unsafe method assumes the data is not uniform, however if it is, this redirects the index
1376 // to zero, which is marginally less efficient but ensures not writing to an illegal address
1377
1378 Codec::encode(/*in=*/val, /*out=*/this->data()[mIsUniform ? 0 : n]);
1379}
1380
1381
1382template<typename ValueType_, typename Codec_>
1383void
1385{
1386 if (n >= this->dataSize()) OPENVDB_THROW(IndexError, "Out-of-range access.");
1387 if (this->isOutOfCore()) this->doLoad();
1388 if (this->isUniform()) this->expand();
1389
1390 this->setUnsafe(n, val);
1391}
1392
1393
1394template<typename ValueType_, typename Codec_>
1395template<typename T>
1396void
1398{
1399 this->setUnsafe(n, static_cast<ValueType>(val));
1400}
1401
1402
1403template<typename ValueType_, typename Codec_>
1404template<typename T>
1405void
1407{
1408 this->set(n, static_cast<ValueType>(val));
1409}
1410
1411
1412template<typename ValueType_, typename Codec_>
1413void
1415{
1416 static_cast<TypedAttributeArray<ValueType, Codec>*>(array)->setUnsafe(n, value);
1417}
1418
1419
1420template<typename ValueType_, typename Codec_>
1421void
1423{
1424 if (!mIsUniform) return;
1425
1426 const StorageType val = this->data()[0];
1427
1428 {
1429 tbb::spin_mutex::scoped_lock lock(mMutex);
1430 this->deallocate();
1431 mIsUniform = false;
1432 this->allocate();
1433 }
1434
1435 if (fill) {
1436 for (Index i = 0; i < this->dataSize(); ++i) this->data()[i] = val;
1437 }
1438}
1439
1440
1441template<typename ValueType_, typename Codec_>
1442bool
1444{
1445 if (mIsUniform) return true;
1446
1447 // compaction is not possible if any values are different
1448 const ValueType_ val = this->get(0);
1449 for (Index i = 1; i < this->dataSize(); i++) {
1450 if (!math::isExactlyEqual(this->get(i), val)) return false;
1451 }
1452
1453 this->collapse(this->get(0));
1454 return true;
1455}
1456
1457
1458template<typename ValueType_, typename Codec_>
1459void
1464
1465
1466template<typename ValueType_, typename Codec_>
1467void
1469{
1470 if (!mIsUniform) {
1471 tbb::spin_mutex::scoped_lock lock(mMutex);
1472 this->deallocate();
1473 mIsUniform = true;
1474 this->allocate();
1475 }
1476 Codec::encode(uniformValue, this->data()[0]);
1477}
1478
1479
1480template<typename ValueType_, typename Codec_>
1481void
1486
1487
1488template<typename ValueType_, typename Codec_>
1489void
1491{
1492 if (this->isOutOfCore()) {
1493 tbb::spin_mutex::scoped_lock lock(mMutex);
1494 this->deallocate();
1495 this->allocate();
1496 }
1497
1498 const Index size = mIsUniform ? 1 : this->dataSize();
1499 for (Index i = 0; i < size; ++i) {
1500 Codec::encode(value, this->data()[i]);
1501 }
1502}
1503
1504
1505template<typename ValueType_, typename Codec_>
1506void
1511
1512
1513template<typename ValueType_, typename Codec_>
1514bool
1519
1520
1521template<typename ValueType_, typename Codec_>
1522void
1523TypedAttributeArray<ValueType_, Codec_>::setOutOfCore(const bool b)
1524{
1525 mOutOfCore = b;
1526}
1527
1528
1529template<typename ValueType_, typename Codec_>
1530void
1531TypedAttributeArray<ValueType_, Codec_>::doLoad() const
1532{
1533 if (!(this->isOutOfCore())) return;
1534
1535 TypedAttributeArray<ValueType_, Codec_>* self =
1536 const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
1537
1538 // This lock will be contended at most once, after which this buffer
1539 // will no longer be out-of-core.
1540 tbb::spin_mutex::scoped_lock lock(self->mMutex);
1541 this->doLoadUnsafe();
1542}
1543
1544
1545template<typename ValueType_, typename Codec_>
1546void
1548{
1549 this->doLoad();
1550}
1551
1552
1553template<typename ValueType_, typename Codec_>
1554bool
1559
1560
1561template<typename ValueType_, typename Codec_>
1562void
1564{
1565 this->readMetadata(is);
1566 this->readBuffers(is);
1567}
1568
1569
1570template<typename ValueType_, typename Codec_>
1571void
1573{
1574 // read data
1575
1576 Index64 bytes = Index64(0);
1577 is.read(reinterpret_cast<char*>(&bytes), sizeof(Index64));
1578 bytes = bytes - /*flags*/sizeof(Int16) - /*size*/sizeof(Index);
1579
1580 uint8_t flags = uint8_t(0);
1581 is.read(reinterpret_cast<char*>(&flags), sizeof(uint8_t));
1582 mFlags = flags;
1583
1584 uint8_t serializationFlags = uint8_t(0);
1585 is.read(reinterpret_cast<char*>(&serializationFlags), sizeof(uint8_t));
1586
1587 Index size = Index(0);
1588 is.read(reinterpret_cast<char*>(&size), sizeof(Index));
1589 mSize = size;
1590
1591 // warn if an unknown flag has been set
1592 if (mFlags >= 0x20) {
1593 OPENVDB_LOG_WARN("Unknown attribute flags for VDB file format.");
1594 }
1595 // error if an unknown serialization flag has been set,
1596 // as this will adjust the layout of the data and corrupt the ability to read
1597 if (serializationFlags >= 0x10) {
1598 OPENVDB_THROW(IoError, "Unknown attribute serialization flags for VDB file format.");
1599 }
1600
1601 // set uniform, compressed and page read state
1602
1603 mIsUniform = serializationFlags & WRITEUNIFORM;
1604 mUsePagedRead = serializationFlags & WRITEPAGED;
1605 mCompressedBytes = bytes;
1606 mFlags |= PARTIALREAD; // mark data as having been partially read
1607
1608 // read strided value (set to 1 if array is not strided)
1609
1610 if (serializationFlags & WRITESTRIDED) {
1611 Index stride = Index(0);
1612 is.read(reinterpret_cast<char*>(&stride), sizeof(Index));
1613 mStrideOrTotalSize = stride;
1614 }
1615 else {
1616 mStrideOrTotalSize = 1;
1617 }
1618}
1619
1620
1621template<typename ValueType_, typename Codec_>
1622void
1624{
1625 if (mUsePagedRead) {
1626 // use readBuffers(PagedInputStream&) for paged buffers
1627 OPENVDB_THROW(IoError, "Cannot read paged AttributeArray buffers.");
1628 }
1629
1630 tbb::spin_mutex::scoped_lock lock(mMutex);
1631
1632 this->deallocate();
1633
1634 uint8_t bloscCompressed(0);
1635 if (!mIsUniform) is.read(reinterpret_cast<char*>(&bloscCompressed), sizeof(uint8_t));
1636
1638 std::unique_ptr<char[]> buffer(new char[mCompressedBytes]);
1639 is.read(buffer.get(), mCompressedBytes);
1640 mCompressedBytes = 0;
1641 mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1642
1643 // compressed on-disk
1644
1645 if (bloscCompressed == uint8_t(1)) {
1646
1647 // decompress buffer
1648
1649 const size_t inBytes = this->dataSize() * sizeof(StorageType);
1650 std::unique_ptr<char[]> newBuffer = compression::bloscDecompress(buffer.get(), inBytes);
1651 if (newBuffer) buffer.reset(newBuffer.release());
1652 }
1653
1654 // set data to buffer
1655
1656 mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1657}
1658
1659
1660template<typename ValueType_, typename Codec_>
1661void
1663{
1664 if (!mUsePagedRead) {
1665 if (!is.sizeOnly()) this->readBuffers(is.getInputStream());
1666 return;
1667 }
1668
1669#ifdef OPENVDB_USE_DELAYED_LOADING
1670 // If this array is being read from a memory-mapped file, delay loading of its data
1671 // until the data is actually accessed.
1672 io::MappedFile::Ptr mappedFile = io::getMappedFilePtr(is.getInputStream());
1673 const bool delayLoad = (mappedFile.get() != nullptr);
1674#endif
1675
1676 if (is.sizeOnly())
1677 {
1678 size_t compressedBytes(mCompressedBytes);
1679 mCompressedBytes = 0; // if not set to zero, mPageHandle will attempt to destroy invalid memory
1680 mFlags = static_cast<uint8_t>(mFlags & ~PARTIALREAD); // mark data read as having completed
1682 mPageHandle = is.createHandle(compressedBytes);
1683 return;
1684 }
1685
1687
1688 tbb::spin_mutex::scoped_lock lock(mMutex);
1689
1690 this->deallocate();
1691
1692#ifdef OPENVDB_USE_DELAYED_LOADING
1693 this->setOutOfCore(delayLoad);
1694 is.read(mPageHandle, std::streamsize(mPageHandle->size()), delayLoad);
1695#else
1696 is.read(mPageHandle, std::streamsize(mPageHandle->size()), false);
1697#endif // OPENVDB_USE_DELAYED_LOADING
1698
1699#ifdef OPENVDB_USE_DELAYED_LOADING
1700 if (!delayLoad) {
1701#endif
1702 std::unique_ptr<char[]> buffer = mPageHandle->read();
1703 mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1704 mPageHandle.reset();
1705#ifdef OPENVDB_USE_DELAYED_LOADING
1706 }
1707#endif
1708
1709 // clear page state
1710
1711 mUsePagedRead = 0;
1712}
1713
1714
1715template<typename ValueType_, typename Codec_>
1716void
1718{
1719 this->write(os, /*outputTransient=*/false);
1720}
1721
1722
1723template<typename ValueType_, typename Codec_>
1724void
1725TypedAttributeArray<ValueType_, Codec_>::write(std::ostream& os, bool outputTransient) const
1726{
1727 this->writeMetadata(os, outputTransient, /*paged=*/false);
1728 this->writeBuffers(os, outputTransient);
1729}
1730
1731
1732template<typename ValueType_, typename Codec_>
1733void
1734TypedAttributeArray<ValueType_, Codec_>::writeMetadata(std::ostream& os, bool outputTransient, bool paged) const
1735{
1736 if (!outputTransient && this->isTransient()) return;
1737
1738 if (mFlags & PARTIALREAD) {
1739 OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1740 }
1741
1742 uint8_t flags(mFlags);
1743 uint8_t serializationFlags(0);
1744 Index size(mSize);
1745 Index strideOrTotalSize(mStrideOrTotalSize);
1746 bool strideOfOne(this->stride() == 1);
1747
1748 bool bloscCompression = io::getDataCompression(os) & io::COMPRESS_BLOSC;
1749
1750 // any compressed data needs to be loaded if out-of-core
1751 if (bloscCompression) this->doLoad();
1752
1753 size_t compressedBytes = 0;
1754
1755 if (!strideOfOne)
1756 {
1757 serializationFlags |= WRITESTRIDED;
1758 }
1759
1760 if (mIsUniform)
1761 {
1762 serializationFlags |= WRITEUNIFORM;
1763 if (bloscCompression && paged) serializationFlags |= WRITEPAGED;
1764 }
1765 else if (bloscCompression)
1766 {
1767 if (paged) serializationFlags |= WRITEPAGED;
1768 else {
1769 const char* charBuffer = reinterpret_cast<const char*>(this->data());
1770 const size_t inBytes = this->arrayMemUsage();
1771 compressedBytes = compression::bloscCompressedSize(charBuffer, inBytes);
1772 }
1773 }
1774
1775 Index64 bytes = /*flags*/ sizeof(Int16) + /*size*/ sizeof(Index);
1776
1777 bytes += (compressedBytes > 0) ? compressedBytes : this->arrayMemUsage();
1778
1779 // write data
1780
1781 os.write(reinterpret_cast<const char*>(&bytes), sizeof(Index64));
1782 os.write(reinterpret_cast<const char*>(&flags), sizeof(uint8_t));
1783 os.write(reinterpret_cast<const char*>(&serializationFlags), sizeof(uint8_t));
1784 os.write(reinterpret_cast<const char*>(&size), sizeof(Index));
1785
1786 // write strided
1787 if (!strideOfOne) os.write(reinterpret_cast<const char*>(&strideOrTotalSize), sizeof(Index));
1788}
1789
1790
1791template<typename ValueType_, typename Codec_>
1792void
1793TypedAttributeArray<ValueType_, Codec_>::writeBuffers(std::ostream& os, bool outputTransient) const
1794{
1795 if (!outputTransient && this->isTransient()) return;
1796
1797 if (mFlags & PARTIALREAD) {
1798 OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1799 }
1800
1801 this->doLoad();
1802
1803 if (this->isUniform()) {
1804 os.write(reinterpret_cast<const char*>(this->data()), sizeof(StorageType));
1805 }
1807 {
1808 std::unique_ptr<char[]> compressedBuffer;
1809 size_t compressedBytes = 0;
1810 const char* charBuffer = reinterpret_cast<const char*>(this->data());
1811 const size_t inBytes = this->arrayMemUsage();
1812 compressedBuffer = compression::bloscCompress(charBuffer, inBytes, compressedBytes);
1813 if (compressedBuffer) {
1814 uint8_t bloscCompressed(1);
1815 os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1816 os.write(reinterpret_cast<const char*>(compressedBuffer.get()), compressedBytes);
1817 }
1818 else {
1819 uint8_t bloscCompressed(0);
1820 os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1821 os.write(reinterpret_cast<const char*>(this->data()), inBytes);
1822 }
1823 }
1824 else
1825 {
1826 uint8_t bloscCompressed(0);
1827 os.write(reinterpret_cast<const char*>(&bloscCompressed), sizeof(uint8_t));
1828 os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1829 }
1830}
1831
1832
1833template<typename ValueType_, typename Codec_>
1834void
1836{
1837 if (!outputTransient && this->isTransient()) return;
1838
1839 // paged compression only available when Blosc is enabled
1840 bool bloscCompression = io::getDataCompression(os.getOutputStream()) & io::COMPRESS_BLOSC;
1841 if (!bloscCompression) {
1842 if (!os.sizeOnly()) this->writeBuffers(os.getOutputStream(), outputTransient);
1843 return;
1844 }
1845
1846 if (mFlags & PARTIALREAD) {
1847 OPENVDB_THROW(IoError, "Cannot write out a partially-read AttributeArray.");
1848 }
1849
1850 this->doLoad();
1851
1852 os.write(reinterpret_cast<const char*>(this->data()), this->arrayMemUsage());
1853}
1854
1855
1856template<typename ValueType_, typename Codec_>
1857void
1858TypedAttributeArray<ValueType_, Codec_>::doLoadUnsafe() const
1859{
1860 if (!(this->isOutOfCore())) return;
1861
1862 // this function expects the mutex to already be locked
1863
1864 auto* self = const_cast<TypedAttributeArray<ValueType_, Codec_>*>(this);
1865
1866 OPENVDB_ASSERT(self->mPageHandle);
1867 OPENVDB_ASSERT(!(self->mFlags & PARTIALREAD));
1868
1869 std::unique_ptr<char[]> buffer = self->mPageHandle->read();
1870
1871 self->mData.reset(reinterpret_cast<StorageType*>(buffer.release()));
1872
1873 self->mPageHandle.reset();
1874
1875 // clear all write and out-of-core flags
1876
1877 self->mOutOfCore = false;
1878}
1879
1880
1881template<typename ValueType_, typename Codec_>
1894
1895
1896template<typename ValueType_, typename Codec_>
1897bool
1898TypedAttributeArray<ValueType_, Codec_>::isEqual(const AttributeArray& other) const
1899{
1900 const TypedAttributeArray<ValueType_, Codec_>* const otherT = dynamic_cast<const TypedAttributeArray<ValueType_, Codec_>* >(&other);
1901 if(!otherT) return false;
1902 if(this->mSize != otherT->mSize ||
1903 this->mStrideOrTotalSize != otherT->mStrideOrTotalSize ||
1904 this->mIsUniform != otherT->mIsUniform ||
1905 this->attributeType() != this->attributeType()) return false;
1906
1907 this->doLoad();
1908 otherT->doLoad();
1909
1910 const StorageType *target = this->data(), *source = otherT->data();
1911 if (!target && !source) return true;
1912 if (!target || !source) return false;
1913 Index n = this->mIsUniform ? 1 : mSize;
1914 while (n && math::isExactlyEqual(*target++, *source++)) --n;
1915 return n == 0;
1916}
1917
1918
1919template<typename ValueType_, typename Codec_>
1920char*
1921TypedAttributeArray<ValueType_, Codec_>::dataAsByteArray()
1922{
1923 return reinterpret_cast<char*>(this->data());
1924}
1925
1926
1927template<typename ValueType_, typename Codec_>
1928const char*
1929TypedAttributeArray<ValueType_, Codec_>::dataAsByteArray() const
1930{
1931 return reinterpret_cast<const char*>(this->data());
1932}
1933
1934
1935////////////////////////////////////////
1936
1937
1938/// Accessor to call unsafe get and set methods based on templated Codec and Value
1939template <typename CodecType, typename ValueType>
1941{
1942 using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
1943 using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
1944
1945 /// Getter that calls to TypedAttributeArray::getUnsafe()
1946 /// @note Functor argument is provided but not required for the generic case
1947 static ValueType get(GetterPtr /*functor*/, const AttributeArray* array, const Index n) {
1949 }
1950
1951 /// Getter that calls to TypedAttributeArray::setUnsafe()
1952 /// @note Functor argument is provided but not required for the generic case
1953 static void set(SetterPtr /*functor*/, AttributeArray* array, const Index n, const ValueType& value) {
1955 }
1956};
1957
1958
1959/// Partial specialization when Codec is not known at compile-time to use the supplied functor instead
1960template <typename ValueType>
1961struct AccessorEval<UnknownCodec, ValueType>
1962{
1963 using GetterPtr = ValueType (*)(const AttributeArray* array, const Index n);
1964 using SetterPtr = void (*)(AttributeArray* array, const Index n, const ValueType& value);
1965
1966 /// Getter that calls the supplied functor
1967 static ValueType get(GetterPtr functor, const AttributeArray* array, const Index n) {
1968 return (*functor)(array, n);
1969 }
1970
1971 /// Setter that calls the supplied functor
1972 static void set(SetterPtr functor, AttributeArray* array, const Index n, const ValueType& value) {
1973 (*functor)(array, n, value);
1974 }
1975};
1976
1977
1978////////////////////////////////////////
1979
1980// AttributeHandle implementation
1981
1982template <typename ValueType, typename CodecType>
1983typename AttributeHandle<ValueType, CodecType>::Ptr
1985{
1987 new AttributeHandle<ValueType, CodecType>(array, collapseOnDestruction));
1988}
1989
1990template <typename ValueType, typename CodecType>
1992 : mArray(&array)
1993 , mStrideOrTotalSize(array.hasConstantStride() ? array.stride() : 1)
1994 , mSize(array.hasConstantStride() ? array.size() : array.dataSize())
1995 , mCollapseOnDestruction(collapseOnDestruction && array.isStreaming())
1996{
1997 if (!this->compatibleType<std::is_same<CodecType, UnknownCodec>::value>()) {
1998 OPENVDB_THROW(TypeError, "Cannot bind handle due to incompatible type of AttributeArray.");
1999 }
2000
2001 // load data if delay-loaded
2002
2003 mArray->loadData();
2004
2005 // bind getter and setter methods
2006
2007 AttributeArray::AccessorBasePtr accessor = mArray->getAccessor();
2008 OPENVDB_ASSERT(accessor);
2009
2010 AttributeArray::Accessor<ValueType>* typedAccessor = static_cast<AttributeArray::Accessor<ValueType>*>(accessor.get());
2011
2012 mGetter = typedAccessor->mGetter;
2013 mSetter = typedAccessor->mSetter;
2014 mCollapser = typedAccessor->mCollapser;
2015 mFiller = typedAccessor->mFiller;
2016}
2017
2018template <typename ValueType, typename CodecType>
2020{
2021 // if enabled, attribute is collapsed on destruction of the handle to save memory
2022 if (mCollapseOnDestruction) const_cast<AttributeArray*>(this->mArray)->collapse();
2023}
2024
2025template <typename ValueType, typename CodecType>
2026template <bool IsUnknownCodec>
2027typename std::enable_if<IsUnknownCodec, bool>::type
2028AttributeHandle<ValueType, CodecType>::compatibleType() const
2029{
2030 // if codec is unknown, just check the value type
2031
2032 return mArray->hasValueType<ValueType>();
2033}
2034
2035template <typename ValueType, typename CodecType>
2036template <bool IsUnknownCodec>
2037typename std::enable_if<!IsUnknownCodec, bool>::type
2038AttributeHandle<ValueType, CodecType>::compatibleType() const
2039{
2040 // if the codec is known, check the value type and codec
2041
2042 return mArray->isType<TypedAttributeArray<ValueType, CodecType>>();
2043}
2044
2045template <typename ValueType, typename CodecType>
2051
2052template <typename ValueType, typename CodecType>
2054{
2055 Index index = n * mStrideOrTotalSize + m;
2056 OPENVDB_ASSERT(index < (mSize * mStrideOrTotalSize));
2057 return index;
2058}
2059
2060template <typename ValueType, typename CodecType>
2065
2066template <typename ValueType, typename CodecType>
2067template <bool IsUnknownCodec>
2068typename std::enable_if<IsUnknownCodec, ValueType>::type
2070{
2071 // if the codec is unknown, use the getter functor
2072
2073 return (*mGetter)(mArray, index);
2074}
2075
2076template <typename ValueType, typename CodecType>
2077template <bool IsUnknownCodec>
2078typename std::enable_if<!IsUnknownCodec, ValueType>::type
2080{
2081 // if the codec is known, call the method on the attribute array directly
2082
2084}
2085
2086template <typename ValueType, typename CodecType>
2088{
2089 return mArray->isUniform();
2090}
2091
2092template <typename ValueType, typename CodecType>
2094{
2095 return mArray->hasConstantStride();
2096}
2097
2098////////////////////////////////////////
2099
2100// AttributeWriteHandle implementation
2101
2102template <typename ValueType, typename CodecType>
2109
2110template <typename ValueType, typename CodecType>
2112 : AttributeHandle<ValueType, CodecType>(array, /*collapseOnDestruction=*/false)
2113{
2114 if (expand) array.expand();
2115}
2116
2117template <typename ValueType, typename CodecType>
2119{
2120 this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, 0), value);
2121}
2122
2123template <typename ValueType, typename CodecType>
2125{
2126 this->set<std::is_same<CodecType, UnknownCodec>::value>(this->index(n, m), value);
2127}
2128
2129template <typename ValueType, typename CodecType>
2131{
2132 const_cast<AttributeArray*>(this->mArray)->expand(fill);
2133}
2134
2135template <typename ValueType, typename CodecType>
2140
2141template <typename ValueType, typename CodecType>
2143{
2144 return const_cast<AttributeArray*>(this->mArray)->compact();
2145}
2146
2147template <typename ValueType, typename CodecType>
2149{
2150 this->mCollapser(const_cast<AttributeArray*>(this->mArray), uniformValue);
2151}
2152
2153template <typename ValueType, typename CodecType>
2155{
2156 this->mFiller(const_cast<AttributeArray*>(this->mArray), value);
2157}
2158
2159template <typename ValueType, typename CodecType>
2160template <bool IsUnknownCodec>
2161typename std::enable_if<IsUnknownCodec, void>::type
2162AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2163{
2164 // if the codec is unknown, use the setter functor
2165
2166 (*this->mSetter)(const_cast<AttributeArray*>(this->mArray), index, value);
2167}
2168
2169template <typename ValueType, typename CodecType>
2170template <bool IsUnknownCodec>
2171typename std::enable_if<!IsUnknownCodec, void>::type
2172AttributeWriteHandle<ValueType, CodecType>::set(Index index, const ValueType& value) const
2173{
2174 // if the codec is known, call the method on the attribute array directly
2175
2176 TypedAttributeArray<ValueType, CodecType>::setUnsafe(const_cast<AttributeArray*>(this->mArray), index, value);
2177}
2178
2179template <typename ValueType, typename CodecType>
2185
2186
2187} // namespace points
2188} // namespace OPENVDB_VERSION_NAME
2189} // namespace openvdb
2190
2191#endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Index Iterators.
#define OPENVDB_API
Definition Platform.h:268
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:1016
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:1022
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:2019
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:1984
AttributeHandle(const AttributeArray &array, const bool collapseOnDestruction=true)
Definition AttributeArray.h:1991
ValueType get(Index n, Index m=0) const
Definition AttributeArray.h:2061
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:2087
std::unique_ptr< Handle > UniquePtr
Definition AttributeArray.h:768
bool hasConstantStride() const
Definition AttributeArray.h:2093
AttributeHandle & operator=(const AttributeHandle &)=default
Index index(Index n, Index m) const
Definition AttributeArray.h:2053
AttributeWriteHandle(AttributeArray &array, const bool expand=true)
Definition AttributeArray.h:2111
std::shared_ptr< Handle > Ptr
Definition AttributeArray.h:838
bool compact()
Compact the existing array to become uniform if all values are identical.
Definition AttributeArray.h:2142
void collapse()
Replace the existing array with a uniform value (zero if none provided).
Definition AttributeArray.h:2136
void set(Index n, const ValueType &value)
Definition AttributeArray.h:2118
std::unique_ptr< Handle > ScopedPtr
Definition AttributeArray.h:839
AttributeWriteHandle< ValueType, CodecType > Handle
Definition AttributeArray.h:837
static Ptr create(AttributeArray &array, const bool expand=true)
Definition AttributeArray.h:2104
void set(Index n, Index m, const ValueType &value)
Definition AttributeArray.h:2124
void collapse(const ValueType &uniformValue)
Definition AttributeArray.h:2148
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:1717
size_t memUsageIfLoaded() const override
Definition AttributeArray.h:1312
void getUnsafe(Index n, T &value) const
Return the value at index n (assumes in-core)
Definition AttributeArray.h:1344
ValueType getUnsafe(Index n) const
Return the value at index n (assumes in-core)
Definition AttributeArray.h:1320
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:1623
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:1883
void write(std::ostream &os, bool outputTransient) const override
Definition AttributeArray.h:1725
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:1304
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:1058
bool isDataLoaded() const override
Return true if all data has been loaded.
Definition AttributeArray.h:1555
bool isOutOfCore() const
Return true if this buffer's values have not yet been read from disk.
Definition AttributeArray.h:1515
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:1278
static TypedAttributeArray & cast(AttributeArray &attributeArray)
Cast an AttributeArray to TypedAttributeArray<T>
Definition AttributeArray.h:1182
TypedAttributeArray & operator=(TypedAttributeArray &&)=delete
Move assignment operator disabled.
void writeBuffers(std::ostream &os, bool outputTransient) const override
Definition AttributeArray.h:1793
AttributeArray::Ptr copy() const override
Definition AttributeArray.h:1202
Index storageTypeSize() const override
Definition AttributeArray.h:594
bool valueTypeIsQuaternion() const override
Return true if the value type is a quaternion.
Definition AttributeArray.h:1286
void readPagedBuffers(compression::PagedInputStream &) override
Read attribute buffers from a paged stream.
Definition AttributeArray.h:1662
void set(Index n, const ValueType &value)
Set value at the given index n.
Definition AttributeArray.h:1384
TypedAttributeArray & operator=(const TypedAttributeArray &)
Definition AttributeArray.h:1108
static void registerType()
Register this attribute type along with a factory function.
Definition AttributeArray.h:1154
bool valueTypeIsFloatingPoint() const override
Return true if the value type is floating point.
Definition AttributeArray.h:1249
void writeMetadata(std::ostream &os, bool outputTransient, bool paged) const override
Definition AttributeArray.h:1734
static void unregisterType()
Remove this attribute type from the registry.
Definition AttributeArray.h:1162
const StorageType * data() const
Definition AttributeArray.h:716
void loadData() const override
Ensures all data is in-core.
Definition AttributeArray.h:1547
void read(std::istream &) override
Read attribute data from a stream.
Definition AttributeArray.h:1563
ValueType get(Index n) const
Return the value at index n.
Definition AttributeArray.h:1332
TypedAttributeArray(TypedAttributeArray &&)=delete
Move constructor disabled.
static const NamePair & attributeType()
Return the name of this attribute's type (includes codec)
Definition AttributeArray.h:1135
TypedAttributeArray(const TypedAttributeArray &)
Definition AttributeArray.h:1086
static void fill(AttributeArray *array, const ValueType &value)
Non-member equivalent to fill() that static_casts array to this TypedAttributeArray.
Definition AttributeArray.h:1507
static void collapse(AttributeArray *array, const ValueType &value)
Non-member equivalent to collapse() that static_casts array to this TypedAttributeArray.
Definition AttributeArray.h:1482
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:1192
bool valueTypeIsClass() const override
Return true if the value type is a class (ie vector, matrix or quaternion return true)
Definition AttributeArray.h:1269
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:1460
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:1422
static bool isRegistered()
Return true if this attribute type is registered.
Definition AttributeArray.h:1146
bool valueTypeIsMatrix() const override
Return true if the value type is a matrix.
Definition AttributeArray.h:1295
static ValueType getUnsafe(const AttributeArray *array, const Index n)
Definition AttributeArray.h:1361
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:1468
void set(Index n, const T &value)
Set value at the given index n.
Definition AttributeArray.h:1406
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:1170
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:1835
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:1397
void setUnsafe(Index n, const ValueType &value)
Set value at the given index n (assumes in-core)
Definition AttributeArray.h:1369
static void setUnsafe(AttributeArray *array, const Index n, const ValueType &value)
Definition AttributeArray.h:1414
void readMetadata(std::istream &) override
Read attribute metadata from a stream.
Definition AttributeArray.h:1572
void get(Index n, T &value) const
Return the value at index n.
Definition AttributeArray.h:1353
#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:28
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Definition Math.h:443
internal::half half
Definition Types.h:29
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:54
int16_t Int16
Definition Types.h:55
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:70
uint64_t Index64
Definition Types.h:53
const char * typeNameAsString()
Definition Types.h:516
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
static pnanovdb_uint32_t allocate(pnanovdb_uint32_t *poffset, pnanovdb_uint32_t size, pnanovdb_uint32_t alignment)
Definition pnanovdb_validate_strides.h:20
static const bool IsVec
Definition Types.h:245
typename T::ValueType ElementType
Definition Types.h:247
static ValueType get(GetterPtr functor, const AttributeArray *array, const Index n)
Getter that calls the supplied functor.
Definition AttributeArray.h:1967
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition AttributeArray.h:1964
static void set(SetterPtr functor, AttributeArray *array, const Index n, const ValueType &value)
Setter that calls the supplied functor.
Definition AttributeArray.h:1972
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition AttributeArray.h:1963
Accessor to call unsafe get and set methods based on templated Codec and Value.
Definition AttributeArray.h:1941
void(*)(AttributeArray *array, const Index n, const ValueType &value) SetterPtr
Definition AttributeArray.h:1943
static ValueType get(GetterPtr, const AttributeArray *array, const Index n)
Definition AttributeArray.h:1947
ValueType(*)(const AttributeArray *array, const Index n) GetterPtr
Definition AttributeArray.h:1942
static void set(SetterPtr, AttributeArray *array, const Index n, const ValueType &value)
Definition AttributeArray.h:1953
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:932
static void decode(const StorageType &, ValueType &)
Definition AttributeArray.h:919
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:894
static const char * name()
Definition AttributeArray.h:443
static void decode(const ValueType &, ValueType &)
Definition AttributeArray.h:886
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:910
static void decode(const StorageType &, ValueType &)
Definition AttributeArray.h:902
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:944
static void encode(const math::Vec3< T > &, StorageType &)
Definition AttributeArray.h:952
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