OpenVDB: openvdb/points/PointDataGrid.h Source File

OpenVDB 9.1.0

PointDataGrid.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/// @author Dan Bailey
5///
6/// @file points/PointDataGrid.h
7///
8/// @brief Attribute-owned data structure for points. Point attributes are
9/// stored in leaf nodes and ordered by voxel for fast random and
10/// sequential access.
11
12#ifndef OPENVDB_POINTS_POINT_DATA_GRID_HAS_BEEN_INCLUDED
13#define OPENVDB_POINTS_POINT_DATA_GRID_HAS_BEEN_INCLUDED
14
15#include <openvdb/version.h>
16#include <openvdb/Grid.h>
17#include <openvdb/tree/Tree.h>
18#include <openvdb/tree/LeafNode.h>
19#include <openvdb/tools/PointIndexGrid.h>
20#include "AttributeArray.h"
21#include "AttributeArrayString.h"
22#include "AttributeGroup.h"
23#include "AttributeSet.h"
24#include "StreamCompression.h"
25#include <cstring> // std::memcpy
26#include <iostream>
27#include <limits>
28#include <memory>
29#include <type_traits> // std::is_same
30#include <utility> // std::pair, std::make_pair
31#include <vector>
32
33class TestPointDataLeaf;
34
35namespace openvdb {
36 OPENVDB_USE_VERSION_NAMESPACE
37namespace OPENVDB_VERSION_NAME {
38
39namespace io
40{
41
42/// @brief openvdb::io::readCompressedValues specialized on PointDataIndex32 arrays to
43/// ignore the value mask, use a larger block size and use 16-bit size instead of 64-bit
44template<>
45inline void
46readCompressedValues( std::istream& is, PointDataIndex32* destBuf, Index destCount,
47 const util::NodeMask<3>& /*valueMask*/, bool /*fromHalf*/)
48{
49 using compression::bloscDecompress;
50
51 const bool seek = destBuf == nullptr;
52
53 const size_t destBytes = destCount*sizeof(PointDataIndex32);
54 const size_t maximumBytes = std::numeric_limits<uint16_t>::max();
55 if (destBytes >= maximumBytes) {
56 OPENVDB_THROW(openvdb::IoError, "Cannot read more than " <<
57 maximumBytes << " bytes in voxel values.")
58 }
59
60 uint16_t bytes16;
61
62 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(is);
63
64 if (seek && meta) {
65 // buffer size temporarily stored in the StreamMetadata pass
66 // to avoid having to perform an expensive disk read for 2-bytes
67 bytes16 = static_cast<uint16_t>(meta->pass());
68 // seek over size of the compressed buffer
69 is.seekg(sizeof(uint16_t), std::ios_base::cur);
70 }
71 else {
72 // otherwise read from disk
73 is.read(reinterpret_cast<char*>(&bytes16), sizeof(uint16_t));
74 }
75
76 if (bytes16 == std::numeric_limits<uint16_t>::max()) {
77 // read or seek uncompressed data
78 if (seek) {
79 is.seekg(destBytes, std::ios_base::cur);
80 }
81 else {
82 is.read(reinterpret_cast<char*>(destBuf), destBytes);
83 }
84 }
85 else {
86 // read or seek uncompressed data
87 if (seek) {
88 is.seekg(int(bytes16), std::ios_base::cur);
89 }
90 else {
91 // decompress into the destination buffer
92 std::unique_ptr<char[]> bloscBuffer(new char[int(bytes16)]);
93 is.read(bloscBuffer.get(), bytes16);
94 std::unique_ptr<char[]> buffer = bloscDecompress( bloscBuffer.get(),
95 destBytes,
96 /*resize=*/false);
97 std::memcpy(destBuf, buffer.get(), destBytes);
98 }
99 }
100}
101
102/// @brief openvdb::io::writeCompressedValues specialized on PointDataIndex32 arrays to
103/// ignore the value mask, use a larger block size and use 16-bit size instead of 64-bit
104template<>
105inline void
106writeCompressedValues( std::ostream& os, PointDataIndex32* srcBuf, Index srcCount,
107 const util::NodeMask<3>& /*valueMask*/,
108 const util::NodeMask<3>& /*childMask*/, bool /*toHalf*/)
109{
110 using compression::bloscCompress;
111
112 const size_t srcBytes = srcCount*sizeof(PointDataIndex32);
113 const size_t maximumBytes = std::numeric_limits<uint16_t>::max();
114 if (srcBytes >= maximumBytes) {
115 OPENVDB_THROW(openvdb::IoError, "Cannot write more than " <<
116 maximumBytes << " bytes in voxel values.")
117 }
118
119 const char* charBuffer = reinterpret_cast<const char*>(srcBuf);
120
121 size_t compressedBytes;
122 std::unique_ptr<char[]> buffer = bloscCompress( charBuffer, srcBytes,
123 compressedBytes, /*resize=*/false);
124
125 if (compressedBytes > 0) {
126 auto bytes16 = static_cast<uint16_t>(compressedBytes); // clamp to 16-bit unsigned integer
127 os.write(reinterpret_cast<const char*>(&bytes16), sizeof(uint16_t));
128 os.write(reinterpret_cast<const char*>(buffer.get()), compressedBytes);
129 }
130 else {
131 auto bytes16 = static_cast<uint16_t>(maximumBytes); // max value indicates uncompressed
132 os.write(reinterpret_cast<const char*>(&bytes16), sizeof(uint16_t));
133 os.write(reinterpret_cast<const char*>(srcBuf), srcBytes);
134 }
135}
136
137template <typename T>
138inline void
139writeCompressedValuesSize(std::ostream& os, const T* srcBuf, Index srcCount)
140{
141 using compression::bloscCompressedSize;
142
143 const size_t srcBytes = srcCount*sizeof(T);
144 const size_t maximumBytes = std::numeric_limits<uint16_t>::max();
145 if (srcBytes >= maximumBytes) {
146 OPENVDB_THROW(openvdb::IoError, "Cannot write more than " <<
147 maximumBytes << " bytes in voxel values.")
148 }
149
150 const char* charBuffer = reinterpret_cast<const char*>(srcBuf);
151
152 // calculate voxel buffer size after compression
153 size_t compressedBytes = bloscCompressedSize(charBuffer, srcBytes);
154
155 if (compressedBytes > 0) {
156 auto bytes16 = static_cast<uint16_t>(compressedBytes); // clamp to 16-bit unsigned integer
157 os.write(reinterpret_cast<const char*>(&bytes16), sizeof(uint16_t));
158 }
159 else {
160 auto bytes16 = static_cast<uint16_t>(maximumBytes); // max value indicates uncompressed
161 os.write(reinterpret_cast<const char*>(&bytes16), sizeof(uint16_t));
162 }
163}
164
165} // namespace io
166
167
168// forward declaration
169 namespace tree {
170 template<Index, typename> struct SameLeafConfig;
171}
172
173
174////////////////////////////////////////
175
176
177namespace points {
178
179
180// forward declaration
181template<typename T, Index Log2Dim> class PointDataLeafNode;
182
183// these aliases are disabled in one of the unit tests to ensure that
184// they are not used by the Point headers
185
186#ifndef OPENVDB_DISABLE_POINT_DATA_TREE_ALIAS
187
188/// @brief Point index tree configured to match the default VDB configurations.
189 using PointDataTree = tree::Tree<tree::RootNode<tree::InternalNode<tree::InternalNode
190 <PointDataLeafNode<PointDataIndex32, 3>, 4>, 5>>>;
191
192
193/// @brief Point data grid.
194 using PointDataGrid = Grid<PointDataTree>;
195
196#endif
197
198/// @brief Deep copy the descriptor across all leaf nodes.
199///
200/// @param tree the PointDataTree.
201///
202/// @return the new descriptor.
203///
204/// @note This method will fail if the Descriptors in the tree are not all identical.
205template <typename PointDataTreeT>
206inline AttributeSet::Descriptor::Ptr
207 makeDescriptorUnique(PointDataTreeT& tree);
208
209
210/// @brief Toggle the streaming mode on all attributes in the tree to collapse the attributes
211/// after deconstructing a bound AttributeHandle to each array. This results in better
212/// memory efficiency when the data is streamed into another data structure
213/// (typically for rendering).
214///
215/// @param tree the PointDataTree.
216/// @param on @c true to enable streaming
217///
218/// @note Multiple threads cannot safely access the same AttributeArray when using streaming.
219template <typename PointDataTreeT>
220inline void
221 setStreamingMode(PointDataTreeT& tree, bool on = true);
222
223
224/// @brief Sequentially pre-fetch all delayed-load voxel and attribute data from disk in order
225/// to accelerate subsequent random access.
226///
227/// @param tree the PointDataTree.
228/// @param position if enabled, prefetch the position attribute (default is on)
229/// @param otherAttributes if enabled, prefetch all other attributes (default is on)
230template <typename PointDataTreeT>
231inline void
232 prefetch(PointDataTreeT& tree, bool position = true, bool otherAttributes = true);
233
234
235////////////////////////////////////////
236
237
238template <typename T, Index Log2Dim>
239 class PointDataLeafNode : public tree::LeafNode<T, Log2Dim>, io::MultiPass {
240
241public:
242 using LeafNodeType = PointDataLeafNode<T, Log2Dim>;
243 using Ptr = std::shared_ptr<PointDataLeafNode>;
244
245 using ValueType = T;
246 using ValueTypePair = std::pair<ValueType, ValueType>;
247 using IndexArray = std::vector<ValueType>;
248
249 using Descriptor = AttributeSet::Descriptor;
250
251 ////////////////////////////////////////
252
253 // The following methods had to be copied from the LeafNode class
254 // to make the derived PointDataLeafNode class compatible with the tree structure.
255
256 using BaseLeaf = tree::LeafNode<T, Log2Dim>;
257 using NodeMaskType = util::NodeMask<Log2Dim>;
258
259 using BaseLeaf::LOG2DIM;
260 using BaseLeaf::TOTAL;
261 using BaseLeaf::DIM;
262 using BaseLeaf::NUM_VALUES;
263 using BaseLeaf::NUM_VOXELS;
264 using BaseLeaf::SIZE;
265 using BaseLeaf::LEVEL;
266
267 /// Default constructor
268 PointDataLeafNode()
269 : mAttributeSet(new AttributeSet) { }
270
271 ~PointDataLeafNode() = default;
272
273 /// Construct using deep copy of other PointDataLeafNode
274 explicit PointDataLeafNode(const PointDataLeafNode& other)
275 : BaseLeaf(other)
276 , mAttributeSet(new AttributeSet(*other.mAttributeSet)) { }
277
278 /// Construct using supplied origin, value and active status
279 explicit
280 PointDataLeafNode(const Coord& coords, const T& value = zeroVal<T>(), bool active = false)
281 : BaseLeaf(coords, zeroVal<T>(), active)
282 , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
283
284 /// Construct using supplied origin, value and active status
285 /// use attribute map from another PointDataLeafNode
286 PointDataLeafNode(const PointDataLeafNode& other, const Coord& coords,
287 const T& value = zeroVal<T>(), bool active = false)
288 : BaseLeaf(coords, zeroVal<T>(), active)
289 , mAttributeSet(new AttributeSet(*other.mAttributeSet))
290 {
291 assertNonModifiableUnlessZero(value);
292 }
293
294 // Copy-construct from a PointIndexLeafNode with the same configuration but a different ValueType.
295 template<typename OtherValueType>
296 PointDataLeafNode(const tools::PointIndexLeafNode<OtherValueType, Log2Dim>& other)
297 : BaseLeaf(other)
298 , mAttributeSet(new AttributeSet) { }
299
300 // Copy-construct from a LeafNode with the same configuration but a different ValueType.
301 // Used for topology copies - explicitly sets the value (background) to zeroVal
302 template <typename ValueType>
303 PointDataLeafNode(const tree::LeafNode<ValueType, Log2Dim>& other, const T& value, TopologyCopy)
304 : BaseLeaf(other, zeroVal<T>(), TopologyCopy())
305 , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
306
307 // Copy-construct from a LeafNode with the same configuration but a different ValueType.
308 // Used for topology copies - explicitly sets the on and off value (background) to zeroVal
309 template <typename ValueType>
310 PointDataLeafNode(const tree::LeafNode<ValueType, Log2Dim>& other, const T& /*offValue*/, const T& /*onValue*/, TopologyCopy)
311 : BaseLeaf(other, zeroVal<T>(), zeroVal<T>(), TopologyCopy())
312 , mAttributeSet(new AttributeSet) { }
313
314 PointDataLeafNode(PartialCreate, const Coord& coords,
315 const T& value = zeroVal<T>(), bool active = false)
316 : BaseLeaf(PartialCreate(), coords, value, active)
317 , mAttributeSet(new AttributeSet) { assertNonModifiableUnlessZero(value); }
318
319public:
320
321 /// Retrieve the attribute set.
322 const AttributeSet& attributeSet() const { return *mAttributeSet; }
323
324 /// @brief Steal the attribute set, a new, empty attribute set is inserted in it's place.
325 AttributeSet::UniquePtr stealAttributeSet();
326
327 /// @brief Create a new attribute set. Existing attributes will be removed.
328 void initializeAttributes(const Descriptor::Ptr& descriptor, const Index arrayLength,
329 const AttributeArray::ScopedRegistryLock* lock = nullptr);
330 /// @brief Clear the attribute set.
331 void clearAttributes(const bool updateValueMask = true,
332 const AttributeArray::ScopedRegistryLock* lock = nullptr);
333
334 /// @brief Returns @c true if an attribute with this index exists.
335 /// @param pos Index of the attribute
336 bool hasAttribute(const size_t pos) const;
337 /// @brief Returns @c true if an attribute with this name exists.
338 /// @param attributeName Name of the attribute
339 bool hasAttribute(const Name& attributeName) const;
340
341 /// @brief Append an attribute to the leaf.
342 /// @param expected Existing descriptor is expected to match this parameter.
343 /// @param replacement New descriptor to replace the existing one.
344 /// @param pos Index of the new attribute in the descriptor replacement.
345 /// @param strideOrTotalSize Stride of the attribute array (if constantStride), total size otherwise
346 /// @param constantStride if @c false, stride is interpreted as total size of the array
347 /// @param metadata optional default value metadata
348 /// @param lock an optional scoped registry lock to avoid contention
349 AttributeArray::Ptr appendAttribute(const Descriptor& expected, Descriptor::Ptr& replacement,
350 const size_t pos, const Index strideOrTotalSize = 1,
351 const bool constantStride = true,
352 const Metadata* metadata = nullptr,
353 const AttributeArray::ScopedRegistryLock* lock = nullptr);
354
355 /// @brief Drop list of attributes.
356 /// @param pos vector of attribute indices to drop
357 /// @param expected Existing descriptor is expected to match this parameter.
358 /// @param replacement New descriptor to replace the existing one.
359 void dropAttributes(const std::vector<size_t>& pos,
360 const Descriptor& expected, Descriptor::Ptr& replacement);
361 /// @brief Reorder attribute set.
362 /// @param replacement New descriptor to replace the existing one.
363 void reorderAttributes(const Descriptor::Ptr& replacement);
364 /// @brief Rename attributes in attribute set (order must remain the same).
365 /// @param expected Existing descriptor is expected to match this parameter.
366 /// @param replacement New descriptor to replace the existing one.
367 void renameAttributes(const Descriptor& expected, Descriptor::Ptr& replacement);
368 /// @brief Compact all attributes in attribute set.
369 void compactAttributes();
370
371 /// @brief Replace the underlying attribute set with the given @a attributeSet.
372 /// @details This leaf will assume ownership of the given attribute set. The descriptors must
373 /// match and the voxel offsets values will need updating if the point order is different.
374 /// @throws ValueError if @a allowMismatchingDescriptors is @c false and the descriptors
375 /// do not match
376 void replaceAttributeSet(AttributeSet* attributeSet, bool allowMismatchingDescriptors = false);
377
378 /// @brief Replace the descriptor with a new one
379 /// The new Descriptor must exactly match the old one
380 void resetDescriptor(const Descriptor::Ptr& replacement);
381
382 /// @brief Sets all of the voxel offset values on this leaf, from the given vector
383 /// of @a offsets. If @a updateValueMask is true, then the active value mask will
384 /// be updated so voxels with points are active and empty voxels are inactive.
385 void setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask = true);
386
387 /// @brief Throws an error if the voxel values on this leaf are not monotonically
388 /// increasing or within the bounds of the attribute arrays
389 void validateOffsets() const;
390
391 /// @brief Read-write attribute array reference from index
392 /// @details Attribute arrays can be shared across leaf nodes, so non-const
393 /// access will deep-copy the array to make it unique. Always prefer
394 /// accessing const arrays where possible to eliminate this copying.
395 /// {
396 AttributeArray& attributeArray(const size_t pos);
397 const AttributeArray& attributeArray(const size_t pos) const;
398 const AttributeArray& constAttributeArray(const size_t pos) const;
399 /// }
400 /// @brief Read-write attribute array reference from name
401 /// @details Attribute arrays can be shared across leaf nodes, so non-const
402 /// access will deep-copy the array to make it unique. Always prefer
403 /// accessing const arrays where possible to eliminate this copying.
404 /// {
405 AttributeArray& attributeArray(const Name& attributeName);
406 const AttributeArray& attributeArray(const Name& attributeName) const;
407 const AttributeArray& constAttributeArray(const Name& attributeName) const;
408 /// }
409
410 /// @brief Read-only group handle from group index
411 GroupHandle groupHandle(const AttributeSet::Descriptor::GroupIndex& index) const;
412 /// @brief Read-only group handle from group name
413 GroupHandle groupHandle(const Name& group) const;
414 /// @brief Read-write group handle from group index
415 GroupWriteHandle groupWriteHandle(const AttributeSet::Descriptor::GroupIndex& index);
416 /// @brief Read-write group handle from group name
417 GroupWriteHandle groupWriteHandle(const Name& name);
418
419 /// @brief Compute the total point count for the leaf
420 Index64 pointCount() const;
421 /// @brief Compute the total active (on) point count for the leaf
422 Index64 onPointCount() const;
423 /// @brief Compute the total inactive (off) point count for the leaf
424 Index64 offPointCount() const;
425 /// @brief Compute the point count in a specific group for the leaf
426 Index64 groupPointCount(const Name& groupName) const;
427
428 /// @brief Activate voxels with non-zero points, deactivate voxels with zero points.
429 void updateValueMask();
430
431 ////////////////////////////////////////
432
433 void setOffsetOn(Index offset, const ValueType& val);
434 void setOffsetOnly(Index offset, const ValueType& val);
435
436 /// @brief Return @c true if the given node (which may have a different @c ValueType
437 /// than this node) has the same active value topology as this node.
438 template<typename OtherType, Index OtherLog2Dim>
439 bool hasSameTopology(const PointDataLeafNode<OtherType, OtherLog2Dim>* other) const {
440 return BaseLeaf::hasSameTopology(other);
441 }
442
443 /// Check for buffer, state and origin equivalence first.
444 /// If this returns true, do a deeper comparison on the attribute set to check
445 bool operator==(const PointDataLeafNode& other) const {
446 if(BaseLeaf::operator==(other) != true) return false;
447 return (*this->mAttributeSet == *other.mAttributeSet);
448 }
449
450 bool operator!=(const PointDataLeafNode& other) const { return !(other == *this); }
451
452 void addLeaf(PointDataLeafNode*) {}
453 template<typename AccessorT>
454 void addLeafAndCache(PointDataLeafNode*, AccessorT&) {}
455
456 //@{
457 /// @brief Return a pointer to this node.
458 PointDataLeafNode* touchLeaf(const Coord&) { return this; }
459 template<typename AccessorT>
460 PointDataLeafNode* touchLeafAndCache(const Coord&, AccessorT&) { return this; }
461
462 template<typename NodeT, typename AccessorT>
463 NodeT* probeNodeAndCache(const Coord&, AccessorT&)
464 {
465 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
466 if (!(std::is_same<NodeT,PointDataLeafNode>::value)) return nullptr;
467 return reinterpret_cast<NodeT*>(this);
468 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
469 }
470 PointDataLeafNode* probeLeaf(const Coord&) { return this; }
471 template<typename AccessorT>
472 PointDataLeafNode* probeLeafAndCache(const Coord&, AccessorT&) { return this; }
473 //@}
474
475 //@{
476 /// @brief Return a @const pointer to this node.
477 const PointDataLeafNode* probeConstLeaf(const Coord&) const { return this; }
478 template<typename AccessorT>
479 const PointDataLeafNode* probeConstLeafAndCache(const Coord&, AccessorT&) const { return this; }
480 template<typename AccessorT>
481 const PointDataLeafNode* probeLeafAndCache(const Coord&, AccessorT&) const { return this; }
482 const PointDataLeafNode* probeLeaf(const Coord&) const { return this; }
483 template<typename NodeT, typename AccessorT>
484 const NodeT* probeConstNodeAndCache(const Coord&, AccessorT&) const
485 {
486 OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
487 if (!(std::is_same<NodeT,PointDataLeafNode>::value)) return nullptr;
488 return reinterpret_cast<const NodeT*>(this);
489 OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
490 }
491 //@}
492
493 // I/O methods
494
495 void readTopology(std::istream& is, bool fromHalf = false);
496 void writeTopology(std::ostream& os, bool toHalf = false) const;
497
498 Index buffers() const;
499
500 void readBuffers(std::istream& is, bool fromHalf = false);
501 void readBuffers(std::istream& is, const CoordBBox&, bool fromHalf = false);
502 void writeBuffers(std::ostream& os, bool toHalf = false) const;
503
504
505 Index64 memUsage() const;
506#if OPENVDB_ABI_VERSION_NUMBER >= 10
507 Index64 memUsageIfLoaded() const;
508#endif
509
510 void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
511
512 /// @brief Return the bounding box of this node, i.e., the full index space
513 /// spanned by this leaf node.
514 CoordBBox getNodeBoundingBox() const;
515
516 ////////////////////////////////////////
517
518 // Disable all write methods to avoid unintentional changes
519 // to the point-array offsets.
520
521 void assertNonmodifiable() {
522 assert(false && "Cannot modify voxel values in a PointDataTree.");
523 }
524
525 // some methods silently ignore attempts to modify the
526 // point-array offsets if a zero value is used
527
528 void assertNonModifiableUnlessZero(const ValueType& value) {
529 if (value != zeroVal<T>()) this->assertNonmodifiable();
530 }
531
532 void setActiveState(const Coord& xyz, bool on) { BaseLeaf::setActiveState(xyz, on); }
533 void setActiveState(Index offset, bool on) { BaseLeaf::setActiveState(offset, on); }
534
535 void setValueOnly(const Coord&, const ValueType&) { assertNonmodifiable(); }
536 void setValueOnly(Index, const ValueType&) { assertNonmodifiable(); }
537
538 void setValueOff(const Coord& xyz) { BaseLeaf::setValueOff(xyz); }
539 void setValueOff(Index offset) { BaseLeaf::setValueOff(offset); }
540
541 void setValueOff(const Coord&, const ValueType&) { assertNonmodifiable(); }
542 void setValueOff(Index, const ValueType&) { assertNonmodifiable(); }
543
544 void setValueOn(const Coord& xyz) { BaseLeaf::setValueOn(xyz); }
545 void setValueOn(Index offset) { BaseLeaf::setValueOn(offset); }
546
547 void setValueOn(const Coord&, const ValueType&) { assertNonmodifiable(); }
548 void setValueOn(Index, const ValueType&) { assertNonmodifiable(); }
549
550 void setValue(const Coord&, const ValueType&) { assertNonmodifiable(); }
551
552 void setValuesOn() { BaseLeaf::setValuesOn(); }
553 void setValuesOff() { BaseLeaf::setValuesOff(); }
554
555 template<typename ModifyOp>
556 void modifyValue(Index, const ModifyOp&) { assertNonmodifiable(); }
557
558 template<typename ModifyOp>
559 void modifyValue(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
560
561 template<typename ModifyOp>
562 void modifyValueAndActiveState(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
563
564 // clipping is not yet supported
565 void clip(const CoordBBox&, const ValueType& value) { assertNonModifiableUnlessZero(value); }
566
567 void fill(const CoordBBox&, const ValueType&, bool);
568 void fill(const ValueType& value) { assertNonModifiableUnlessZero(value); }
569 void fill(const ValueType&, bool);
570
571 template<typename AccessorT>
572 void setValueOnlyAndCache(const Coord&, const ValueType&, AccessorT&) {assertNonmodifiable();}
573
574 template<typename ModifyOp, typename AccessorT>
575 void modifyValueAndActiveStateAndCache(const Coord&, const ModifyOp&, AccessorT&) {
576 assertNonmodifiable();
577 }
578
579 template<typename AccessorT>
580 void setValueOffAndCache(const Coord&, const ValueType&, AccessorT&) { assertNonmodifiable(); }
581
582 template<typename AccessorT>
583 void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& parent) {
584 BaseLeaf::setActiveStateAndCache(xyz, on, parent);
585 }
586
587 void resetBackground(const ValueType&, const ValueType& newBackground) {
588 assertNonModifiableUnlessZero(newBackground);
589 }
590
591 void signedFloodFill(const ValueType&) { assertNonmodifiable(); }
592 void signedFloodFill(const ValueType&, const ValueType&) { assertNonmodifiable(); }
593
594 void negate() { assertNonmodifiable(); }
595
596 friend class ::TestPointDataLeaf;
597
598 using ValueOn = typename BaseLeaf::ValueOn;
599 using ValueOff = typename BaseLeaf::ValueOff;
600 using ValueAll = typename BaseLeaf::ValueAll;
601
602private:
603 AttributeSet::UniquePtr mAttributeSet;
604 uint16_t mVoxelBufferSize = 0;
605
606protected:
607 using ChildOn = typename BaseLeaf::ChildOn;
608 using ChildOff = typename BaseLeaf::ChildOff;
609 using ChildAll = typename BaseLeaf::ChildAll;
610
611 using MaskOnIterator = typename NodeMaskType::OnIterator;
612 using MaskOffIterator = typename NodeMaskType::OffIterator;
613 using MaskDenseIterator = typename NodeMaskType::DenseIterator;
614
615 // During topology-only construction, access is needed
616 // to protected/private members of other template instances.
617 template<typename, Index> friend class PointDataLeafNode;
618
619 friend class tree::IteratorBase<MaskOnIterator, PointDataLeafNode>;
620 friend class tree::IteratorBase<MaskOffIterator, PointDataLeafNode>;
621 friend class tree::IteratorBase<MaskDenseIterator, PointDataLeafNode>;
622
623public:
624 /// @brief Leaf value voxel iterator
625 ValueVoxelCIter beginValueVoxel(const Coord& ijk) const;
626
627public:
628
629 using ValueOnIter = typename BaseLeaf::template ValueIter<
630 MaskOnIterator, PointDataLeafNode, const ValueType, ValueOn>;
631 using ValueOnCIter = typename BaseLeaf::template ValueIter<
632 MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn>;
633 using ValueOffIter = typename BaseLeaf::template ValueIter<
634 MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff>;
635 using ValueOffCIter = typename BaseLeaf::template ValueIter<
636 MaskOffIterator,const PointDataLeafNode,const ValueType,ValueOff>;
637 using ValueAllIter = typename BaseLeaf::template ValueIter<
638 MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll>;
639 using ValueAllCIter = typename BaseLeaf::template ValueIter<
640 MaskDenseIterator,const PointDataLeafNode,const ValueType,ValueAll>;
641 using ChildOnIter = typename BaseLeaf::template ChildIter<
642 MaskOnIterator, PointDataLeafNode, ChildOn>;
643 using ChildOnCIter = typename BaseLeaf::template ChildIter<
644 MaskOnIterator, const PointDataLeafNode, ChildOn>;
645 using ChildOffIter = typename BaseLeaf::template ChildIter<
646 MaskOffIterator, PointDataLeafNode, ChildOff>;
647 using ChildOffCIter = typename BaseLeaf::template ChildIter<
648 MaskOffIterator, const PointDataLeafNode, ChildOff>;
649 using ChildAllIter = typename BaseLeaf::template DenseIter<
650 PointDataLeafNode, ValueType, ChildAll>;
651 using ChildAllCIter = typename BaseLeaf::template DenseIter<
652 const PointDataLeafNode, const ValueType, ChildAll>;
653
654 using IndexVoxelIter = IndexIter<ValueVoxelCIter, NullFilter>;
655 using IndexAllIter = IndexIter<ValueAllCIter, NullFilter>;
656 using IndexOnIter = IndexIter<ValueOnCIter, NullFilter>;
657 using IndexOffIter = IndexIter<ValueOffCIter, NullFilter>;
658
659 /// @brief Leaf index iterator
660 IndexAllIter beginIndexAll() const
661 {
662 NullFilter filter;
663 return this->beginIndex<ValueAllCIter, NullFilter>(filter);
664 }
665 IndexOnIter beginIndexOn() const
666 {
667 NullFilter filter;
668 return this->beginIndex<ValueOnCIter, NullFilter>(filter);
669 }
670 IndexOffIter beginIndexOff() const
671 {
672 NullFilter filter;
673 return this->beginIndex<ValueOffCIter, NullFilter>(filter);
674 }
675
676 template<typename IterT, typename FilterT>
677 IndexIter<IterT, FilterT> beginIndex(const FilterT& filter) const;
678
679 /// @brief Filtered leaf index iterator
680 template<typename FilterT>
681 IndexIter<ValueAllCIter, FilterT> beginIndexAll(const FilterT& filter) const
682 {
683 return this->beginIndex<ValueAllCIter, FilterT>(filter);
684 }
685 template<typename FilterT>
686 IndexIter<ValueOnCIter, FilterT> beginIndexOn(const FilterT& filter) const
687 {
688 return this->beginIndex<ValueOnCIter, FilterT>(filter);
689 }
690 template<typename FilterT>
691 IndexIter<ValueOffCIter, FilterT> beginIndexOff(const FilterT& filter) const
692 {
693 return this->beginIndex<ValueOffCIter, FilterT>(filter);
694 }
695
696 /// @brief Leaf index iterator from voxel
697 IndexVoxelIter beginIndexVoxel(const Coord& ijk) const;
698
699 /// @brief Filtered leaf index iterator from voxel
700 template<typename FilterT>
701 IndexIter<ValueVoxelCIter, FilterT> beginIndexVoxel(const Coord& ijk, const FilterT& filter) const;
702
703#define VMASK_ this->getValueMask()
704 ValueOnCIter cbeginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
705 ValueOnCIter beginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
706 ValueOnIter beginValueOn() { return ValueOnIter(VMASK_.beginOn(), this); }
707 ValueOffCIter cbeginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
708 ValueOffCIter beginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
709 ValueOffIter beginValueOff() { return ValueOffIter(VMASK_.beginOff(), this); }
710 ValueAllCIter cbeginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
711 ValueAllCIter beginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
712 ValueAllIter beginValueAll() { return ValueAllIter(VMASK_.beginDense(), this); }
713
714 ValueOnCIter cendValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
715 ValueOnCIter endValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
716 ValueOnIter endValueOn() { return ValueOnIter(VMASK_.endOn(), this); }
717 ValueOffCIter cendValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
718 ValueOffCIter endValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
719 ValueOffIter endValueOff() { return ValueOffIter(VMASK_.endOff(), this); }
720 ValueAllCIter cendValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
721 ValueAllCIter endValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
722 ValueAllIter endValueAll() { return ValueAllIter(VMASK_.endDense(), this); }
723
724 ChildOnCIter cbeginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
725 ChildOnCIter beginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
726 ChildOnIter beginChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
727 ChildOffCIter cbeginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
728 ChildOffCIter beginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
729 ChildOffIter beginChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
730 ChildAllCIter cbeginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
731 ChildAllCIter beginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
732 ChildAllIter beginChildAll() { return ChildAllIter(VMASK_.beginDense(), this); }
733
734 ChildOnCIter cendChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
735 ChildOnCIter endChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
736 ChildOnIter endChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
737 ChildOffCIter cendChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
738 ChildOffCIter endChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
739 ChildOffIter endChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
740 ChildAllCIter cendChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
741 ChildAllCIter endChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
742 ChildAllIter endChildAll() { return ChildAllIter(VMASK_.endDense(), this); }
743#undef VMASK_
744}; // struct PointDataLeafNode
745
746////////////////////////////////////////
747
748// PointDataLeafNode implementation
749
750template<typename T, Index Log2Dim>
751inline AttributeSet::UniquePtr
752 PointDataLeafNode<T, Log2Dim>::stealAttributeSet()
753{
754 AttributeSet::UniquePtr ptr = std::make_unique<AttributeSet>();
755 std::swap(ptr, mAttributeSet);
756 return ptr;
757}
758
759template<typename T, Index Log2Dim>
760inline void
761 PointDataLeafNode<T, Log2Dim>::initializeAttributes(const Descriptor::Ptr& descriptor, const Index arrayLength,
762 const AttributeArray::ScopedRegistryLock* lock)
763{
764 if (descriptor->size() != 1 ||
765 descriptor->find("P") == AttributeSet::INVALID_POS ||
766 descriptor->valueType(0) != typeNameAsString<Vec3f>())
767 {
768 OPENVDB_THROW(IndexError, "Initializing attributes only allowed with one Vec3f position attribute.");
769 }
770
771 mAttributeSet.reset(new AttributeSet(descriptor, arrayLength, lock));
772}
773
774template<typename T, Index Log2Dim>
775inline void
776 PointDataLeafNode<T, Log2Dim>::clearAttributes(const bool updateValueMask,
777 const AttributeArray::ScopedRegistryLock* lock)
778{
779 mAttributeSet.reset(new AttributeSet(*mAttributeSet, 0, lock));
780
781 // zero voxel values
782
783 this->buffer().fill(ValueType(0));
784
785 // if updateValueMask, also de-activate all voxels
786
787 if (updateValueMask) this->setValuesOff();
788}
789
790template<typename T, Index Log2Dim>
791inline bool
792 PointDataLeafNode<T, Log2Dim>::hasAttribute(const size_t pos) const
793{
794 return pos < mAttributeSet->size();
795}
796
797template<typename T, Index Log2Dim>
798inline bool
799 PointDataLeafNode<T, Log2Dim>::hasAttribute(const Name& attributeName) const
800{
801 const size_t pos = mAttributeSet->find(attributeName);
802 return pos != AttributeSet::INVALID_POS;
803}
804
805template<typename T, Index Log2Dim>
806inline AttributeArray::Ptr
807 PointDataLeafNode<T, Log2Dim>::appendAttribute( const Descriptor& expected, Descriptor::Ptr& replacement,
808 const size_t pos, const Index strideOrTotalSize,
809 const bool constantStride,
810 const Metadata* metadata,
811 const AttributeArray::ScopedRegistryLock* lock)
812{
813 return mAttributeSet->appendAttribute(
814 expected, replacement, pos, strideOrTotalSize, constantStride, metadata, lock);
815}
816
817template<typename T, Index Log2Dim>
818inline void
819 PointDataLeafNode<T, Log2Dim>::dropAttributes(const std::vector<size_t>& pos,
820 const Descriptor& expected, Descriptor::Ptr& replacement)
821{
822 mAttributeSet->dropAttributes(pos, expected, replacement);
823}
824
825template<typename T, Index Log2Dim>
826inline void
827 PointDataLeafNode<T, Log2Dim>::reorderAttributes(const Descriptor::Ptr& replacement)
828{
829 mAttributeSet->reorderAttributes(replacement);
830}
831
832template<typename T, Index Log2Dim>
833inline void
834 PointDataLeafNode<T, Log2Dim>::renameAttributes(const Descriptor& expected, Descriptor::Ptr& replacement)
835{
836 mAttributeSet->renameAttributes(expected, replacement);
837}
838
839template<typename T, Index Log2Dim>
840inline void
841 PointDataLeafNode<T, Log2Dim>::compactAttributes()
842{
843 for (size_t i = 0; i < mAttributeSet->size(); i++) {
844 AttributeArray* array = mAttributeSet->get(i);
845 array->compact();
846 }
847}
848
849template<typename T, Index Log2Dim>
850inline void
851 PointDataLeafNode<T, Log2Dim>::replaceAttributeSet(AttributeSet* attributeSet, bool allowMismatchingDescriptors)
852{
853 if (!attributeSet) {
854 OPENVDB_THROW(ValueError, "Cannot replace with a null attribute set");
855 }
856
857 if (!allowMismatchingDescriptors && mAttributeSet->descriptor() != attributeSet->descriptor()) {
858 OPENVDB_THROW(ValueError, "Attribute set descriptors are not equal.");
859 }
860
861 mAttributeSet.reset(attributeSet);
862}
863
864template<typename T, Index Log2Dim>
865inline void
866 PointDataLeafNode<T, Log2Dim>::resetDescriptor(const Descriptor::Ptr& replacement)
867{
868 mAttributeSet->resetDescriptor(replacement);
869}
870
871template<typename T, Index Log2Dim>
872inline void
873 PointDataLeafNode<T, Log2Dim>::setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask)
874{
875 if (offsets.size() != LeafNodeType::NUM_VALUES) {
876 OPENVDB_THROW(ValueError, "Offset vector size doesn't match number of voxels.")
877 }
878
879 for (Index index = 0; index < offsets.size(); ++index) {
880 setOffsetOnly(index, offsets[index]);
881 }
882
883 if (updateValueMask) this->updateValueMask();
884}
885
886template<typename T, Index Log2Dim>
887inline void
888 PointDataLeafNode<T, Log2Dim>::validateOffsets() const
889{
890 // Ensure all of the offset values are monotonically increasing
891 for (Index index = 1; index < BaseLeaf::SIZE; ++index) {
892 if (this->getValue(index-1) > this->getValue(index)) {
893 OPENVDB_THROW(ValueError, "Voxel offset values are not monotonically increasing");
894 }
895 }
896
897 // Ensure all attribute arrays are of equal length
898 for (size_t attributeIndex = 1; attributeIndex < mAttributeSet->size(); ++attributeIndex ) {
899 if (mAttributeSet->getConst(attributeIndex-1)->size() != mAttributeSet->getConst(attributeIndex)->size()) {
900 OPENVDB_THROW(ValueError, "Attribute arrays have inconsistent length");
901 }
902 }
903
904 // Ensure the last voxel's offset value matches the size of each attribute array
905 if (mAttributeSet->size() > 0 && this->getValue(BaseLeaf::SIZE-1) != mAttributeSet->getConst(0)->size()) {
906 OPENVDB_THROW(ValueError, "Last voxel offset value does not match attribute array length");
907 }
908}
909
910template<typename T, Index Log2Dim>
911inline AttributeArray&
912 PointDataLeafNode<T, Log2Dim>::attributeArray(const size_t pos)
913{
914 if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
915 return *mAttributeSet->get(pos);
916}
917
918template<typename T, Index Log2Dim>
919inline const AttributeArray&
920 PointDataLeafNode<T, Log2Dim>::attributeArray(const size_t pos) const
921{
922 if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
923 return *mAttributeSet->getConst(pos);
924}
925
926template<typename T, Index Log2Dim>
927inline const AttributeArray&
928 PointDataLeafNode<T, Log2Dim>::constAttributeArray(const size_t pos) const
929{
930 return this->attributeArray(pos);
931}
932
933template<typename T, Index Log2Dim>
934inline AttributeArray&
935 PointDataLeafNode<T, Log2Dim>::attributeArray(const Name& attributeName)
936{
937 const size_t pos = mAttributeSet->find(attributeName);
938 if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
939 return *mAttributeSet->get(pos);
940}
941
942template<typename T, Index Log2Dim>
943inline const AttributeArray&
944 PointDataLeafNode<T, Log2Dim>::attributeArray(const Name& attributeName) const
945{
946 const size_t pos = mAttributeSet->find(attributeName);
947 if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
948 return *mAttributeSet->getConst(pos);
949}
950
951template<typename T, Index Log2Dim>
952inline const AttributeArray&
953 PointDataLeafNode<T, Log2Dim>::constAttributeArray(const Name& attributeName) const
954{
955 return this->attributeArray(attributeName);
956}
957
958template<typename T, Index Log2Dim>
959inline GroupHandle
960 PointDataLeafNode<T, Log2Dim>::groupHandle(const AttributeSet::Descriptor::GroupIndex& index) const
961{
962 const AttributeArray& array = this->attributeArray(index.first);
963 assert(isGroup(array));
964
965 const GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
966
967 return GroupHandle(groupArray, index.second);
968}
969
970template<typename T, Index Log2Dim>
971inline GroupHandle
972 PointDataLeafNode<T, Log2Dim>::groupHandle(const Name& name) const
973{
974 const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
975 return this->groupHandle(index);
976}
977
978template<typename T, Index Log2Dim>
979inline GroupWriteHandle
980 PointDataLeafNode<T, Log2Dim>::groupWriteHandle(const AttributeSet::Descriptor::GroupIndex& index)
981{
982 AttributeArray& array = this->attributeArray(index.first);
983 assert(isGroup(array));
984
985 GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
986
987 return GroupWriteHandle(groupArray, index.second);
988}
989
990template<typename T, Index Log2Dim>
991inline GroupWriteHandle
992 PointDataLeafNode<T, Log2Dim>::groupWriteHandle(const Name& name)
993{
994 const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
995 return this->groupWriteHandle(index);
996}
997
998template<typename T, Index Log2Dim>
999template<typename ValueIterT, typename FilterT>
1000inline IndexIter<ValueIterT, FilterT>
1001 PointDataLeafNode<T, Log2Dim>::beginIndex(const FilterT& filter) const
1002{
1003 // generate no-op iterator if filter evaluates no indices
1004
1005 if (filter.state() == index::NONE) {
1006 return IndexIter<ValueIterT, FilterT>(ValueIterT(), filter);
1007 }
1008
1009 // copy filter to ensure thread-safety
1010
1011 FilterT newFilter(filter);
1012 newFilter.reset(*this);
1013
1014 using IterTraitsT = tree::IterTraits<LeafNodeType, ValueIterT>;
1015
1016 // construct the value iterator and reset the filter to use this leaf
1017
1018 ValueIterT valueIter = IterTraitsT::begin(*this);
1019
1020 return IndexIter<ValueIterT, FilterT>(valueIter, newFilter);
1021}
1022
1023template<typename T, Index Log2Dim>
1024inline ValueVoxelCIter
1025 PointDataLeafNode<T, Log2Dim>::beginValueVoxel(const Coord& ijk) const
1026{
1027 const Index index = LeafNodeType::coordToOffset(ijk);
1028 assert(index < BaseLeaf::SIZE);
1029 const ValueType end = this->getValue(index);
1030 const ValueType start = (index == 0) ? ValueType(0) : this->getValue(index - 1);
1031 return ValueVoxelCIter(start, end);
1032}
1033
1034template<typename T, Index Log2Dim>
1035inline typename PointDataLeafNode<T, Log2Dim>::IndexVoxelIter
1036 PointDataLeafNode<T, Log2Dim>::beginIndexVoxel(const Coord& ijk) const
1037{
1038 ValueVoxelCIter iter = this->beginValueVoxel(ijk);
1039 return IndexVoxelIter(iter, NullFilter());
1040}
1041
1042template<typename T, Index Log2Dim>
1043template<typename FilterT>
1044inline IndexIter<ValueVoxelCIter, FilterT>
1045 PointDataLeafNode<T, Log2Dim>::beginIndexVoxel(const Coord& ijk, const FilterT& filter) const
1046{
1047 ValueVoxelCIter iter = this->beginValueVoxel(ijk);
1048 FilterT newFilter(filter);
1049 newFilter.reset(*this);
1050 return IndexIter<ValueVoxelCIter, FilterT>(iter, newFilter);
1051}
1052
1053template<typename T, Index Log2Dim>
1054inline Index64
1055 PointDataLeafNode<T, Log2Dim>::pointCount() const
1056{
1057 return this->getLastValue();
1058}
1059
1060template<typename T, Index Log2Dim>
1061inline Index64
1062 PointDataLeafNode<T, Log2Dim>::onPointCount() const
1063{
1064 if (this->isEmpty()) return 0;
1065 else if (this->isDense()) return this->pointCount();
1066 return iterCount(this->beginIndexOn());
1067}
1068
1069template<typename T, Index Log2Dim>
1070inline Index64
1071 PointDataLeafNode<T, Log2Dim>::offPointCount() const
1072{
1073 if (this->isEmpty()) return this->pointCount();
1074 else if (this->isDense()) return 0;
1075 return iterCount(this->beginIndexOff());
1076}
1077
1078template<typename T, Index Log2Dim>
1079inline Index64
1080 PointDataLeafNode<T, Log2Dim>::groupPointCount(const Name& groupName) const
1081{
1082 if (!this->attributeSet().descriptor().hasGroup(groupName)) {
1083 return Index64(0);
1084 }
1085 GroupFilter filter(groupName, this->attributeSet());
1086 if (filter.state() == index::ALL) {
1087 return this->pointCount();
1088 } else {
1089 return iterCount(this->beginIndexAll(filter));
1090 }
1091}
1092
1093template<typename T, Index Log2Dim>
1094inline void
1095 PointDataLeafNode<T, Log2Dim>::updateValueMask()
1096{
1097 ValueType start = 0, end = 0;
1098 for (Index n = 0; n < LeafNodeType::NUM_VALUES; n++) {
1099 end = this->getValue(n);
1100 this->setValueMask(n, (end - start) > 0);
1101 start = end;
1102 }
1103}
1104
1105template<typename T, Index Log2Dim>
1106inline void
1107 PointDataLeafNode<T, Log2Dim>::setOffsetOn(Index offset, const ValueType& val)
1108{
1109 this->buffer().setValue(offset, val);
1110 this->setValueMaskOn(offset);
1111}
1112
1113template<typename T, Index Log2Dim>
1114inline void
1115 PointDataLeafNode<T, Log2Dim>::setOffsetOnly(Index offset, const ValueType& val)
1116{
1117 this->buffer().setValue(offset, val);
1118}
1119
1120template<typename T, Index Log2Dim>
1121inline void
1122 PointDataLeafNode<T, Log2Dim>::readTopology(std::istream& is, bool fromHalf)
1123{
1124 BaseLeaf::readTopology(is, fromHalf);
1125}
1126
1127template<typename T, Index Log2Dim>
1128inline void
1129 PointDataLeafNode<T, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const
1130{
1131 BaseLeaf::writeTopology(os, toHalf);
1132}
1133
1134template<typename T, Index Log2Dim>
1135inline Index
1136 PointDataLeafNode<T, Log2Dim>::buffers() const
1137{
1138 return Index( /*voxel buffer sizes*/ 1 +
1139 /*voxel buffers*/ 1 +
1140 /*attribute metadata*/ 1 +
1141 /*attribute uniform values*/ mAttributeSet->size() +
1142 /*attribute buffers*/ mAttributeSet->size() +
1143 /*cleanup*/ 1);
1144}
1145
1146template<typename T, Index Log2Dim>
1147inline void
1148 PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
1149{
1150 this->readBuffers(is, CoordBBox::inf(), fromHalf);
1151}
1152
1153template<typename T, Index Log2Dim>
1154inline void
1155 PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& /*bbox*/, bool fromHalf)
1156{
1157 struct Local
1158 {
1159 static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1160 {
1161 // if paged stream exists, delete it
1162 std::string key("paged:" + std::to_string(index));
1163 auto it = auxData.find(key);
1164 if (it != auxData.end()) {
1165 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1166 }
1167 }
1168
1169 static compression::PagedInputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1170 const Index index)
1171 {
1172 std::string key("paged:" + std::to_string(index));
1173 auto it = auxData.find(key);
1174 if (it != auxData.end()) {
1175 return *(boost::any_cast<compression::PagedInputStream::Ptr>(it->second));
1176 }
1177 else {
1178 compression::PagedInputStream::Ptr pagedStream = std::make_shared<compression::PagedInputStream>();
1179 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1180 return *pagedStream;
1181 }
1182 }
1183
1184 static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1185 {
1186 std::string matchingKey("hasMatchingDescriptor");
1187 auto itMatching = auxData.find(matchingKey);
1188 return itMatching != auxData.end();
1189 }
1190
1191 static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1192 {
1193 std::string matchingKey("hasMatchingDescriptor");
1194 std::string descriptorKey("descriptorPtr");
1195 auto itMatching = auxData.find(matchingKey);
1196 auto itDescriptor = auxData.find(descriptorKey);
1197 if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1198 if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1199 }
1200
1201 static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1202 const Descriptor::Ptr descriptor)
1203 {
1204 std::string descriptorKey("descriptorPtr");
1205 std::string matchingKey("hasMatchingDescriptor");
1206 auto itMatching = auxData.find(matchingKey);
1207 if (itMatching == auxData.end()) {
1208 // if matching bool is not found, insert "true" and the descriptor
1209 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1210 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1211 }
1212 }
1213
1214 static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1215 {
1216 std::string descriptorKey("descriptorPtr");
1217 auto itDescriptor = auxData.find(descriptorKey);
1218 assert(itDescriptor != auxData.end());
1219 const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1220 return descriptor;
1221 }
1222 };
1223
1224 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(is);
1225
1226 if (!meta) {
1227 OPENVDB_THROW(IoError, "Cannot read in a PointDataLeaf without StreamMetadata.");
1228 }
1229
1230 const Index pass(static_cast<uint16_t>(meta->pass()));
1231 const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1232
1233 const Index attributes = (maximumPass - 4) / 2;
1234
1235 if (pass == 0) {
1236 // pass 0 - voxel data sizes
1237 is.read(reinterpret_cast<char*>(&mVoxelBufferSize), sizeof(uint16_t));
1238 Local::clearMatchingDescriptor(meta->auxData());
1239 }
1240 else if (pass == 1) {
1241 // pass 1 - descriptor and attribute metadata
1242 if (Local::hasMatchingDescriptor(meta->auxData())) {
1243 AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1244 mAttributeSet->resetDescriptor(descriptor, /*allowMismatchingDescriptors=*/true);
1245 }
1246 else {
1247 uint8_t header;
1248 is.read(reinterpret_cast<char*>(&header), sizeof(uint8_t));
1249 mAttributeSet->readDescriptor(is);
1250 if (header & uint8_t(1)) {
1251 AttributeSet::DescriptorPtr descriptor = mAttributeSet->descriptorPtr();
1252 Local::insertDescriptor(meta->auxData(), descriptor);
1253 }
1254 // a forwards-compatibility mechanism for future use,
1255 // if a 0x2 bit is set, read and skip over a specific number of bytes
1256 if (header & uint8_t(2)) {
1257 uint64_t bytesToSkip;
1258 is.read(reinterpret_cast<char*>(&bytesToSkip), sizeof(uint64_t));
1259 if (bytesToSkip > uint64_t(0)) {
1260 auto metadata = io::getStreamMetadataPtr(is);
1261 if (metadata && metadata->seekable()) {
1262 is.seekg(bytesToSkip, std::ios_base::cur);
1263 }
1264 else {
1265 std::vector<uint8_t> tempData(bytesToSkip);
1266 is.read(reinterpret_cast<char*>(&tempData[0]), bytesToSkip);
1267 }
1268 }
1269 }
1270 // this reader is only able to read headers with 0x1 and 0x2 bits set
1271 if (header > uint8_t(3)) {
1272 OPENVDB_THROW(IoError, "Unrecognised header flags in PointDataLeafNode");
1273 }
1274 }
1275 mAttributeSet->readMetadata(is);
1276 }
1277 else if (pass < (attributes + 2)) {
1278 // pass 2...n+2 - attribute uniform values
1279 const size_t attributeIndex = pass - 2;
1280 AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1281 mAttributeSet->get(attributeIndex) : nullptr;
1282 if (array) {
1283 compression::PagedInputStream& pagedStream =
1284 Local::getOrInsertPagedStream(meta->auxData(), static_cast<Index>(attributeIndex));
1285 pagedStream.setInputStream(is);
1286 pagedStream.setSizeOnly(true);
1287 array->readPagedBuffers(pagedStream);
1288 }
1289 }
1290 else if (pass == attributes + 2) {
1291 // pass n+2 - voxel data
1292
1293 const Index passValue(meta->pass());
1294
1295 // StreamMetadata pass variable used to temporarily store voxel buffer size
1296 io::StreamMetadata& nonConstMeta = const_cast<io::StreamMetadata&>(*meta);
1297 nonConstMeta.setPass(mVoxelBufferSize);
1298
1299 // readBuffers() calls readCompressedValues specialization above
1300 BaseLeaf::readBuffers(is, fromHalf);
1301
1302 // pass now reset to original value
1303 nonConstMeta.setPass(passValue);
1304 }
1305 else if (pass < (attributes*2 + 3)) {
1306 // pass n+2..2n+2 - attribute buffers
1307 const Index attributeIndex = pass - attributes - 3;
1308 AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1309 mAttributeSet->get(attributeIndex) : nullptr;
1310 if (array) {
1311 compression::PagedInputStream& pagedStream =
1312 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1313 pagedStream.setInputStream(is);
1314 pagedStream.setSizeOnly(false);
1315 array->readPagedBuffers(pagedStream);
1316 }
1317 // cleanup paged stream reference in auxiliary metadata
1318 if (pass > attributes + 3) {
1319 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1320 }
1321 }
1322 else if (pass < buffers()) {
1323 // pass 2n+3 - cleanup last paged stream
1324 const Index attributeIndex = pass - attributes - 4;
1325 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1326 }
1327}
1328
1329template<typename T, Index Log2Dim>
1330inline void
1331 PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
1332{
1333 struct Local
1334 {
1335 static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1336 {
1337 // if paged stream exists, flush and delete it
1338 std::string key("paged:" + std::to_string(index));
1339 auto it = auxData.find(key);
1340 if (it != auxData.end()) {
1341 compression::PagedOutputStream& stream = *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1342 stream.flush();
1343 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1344 }
1345 }
1346
1347 static compression::PagedOutputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1348 const Index index)
1349 {
1350 std::string key("paged:" + std::to_string(index));
1351 auto it = auxData.find(key);
1352 if (it != auxData.end()) {
1353 return *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1354 }
1355 else {
1356 compression::PagedOutputStream::Ptr pagedStream = std::make_shared<compression::PagedOutputStream>();
1357 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1358 return *pagedStream;
1359 }
1360 }
1361
1362 static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1363 const Descriptor::Ptr descriptor)
1364 {
1365 std::string descriptorKey("descriptorPtr");
1366 std::string matchingKey("hasMatchingDescriptor");
1367 auto itMatching = auxData.find(matchingKey);
1368 auto itDescriptor = auxData.find(descriptorKey);
1369 if (itMatching == auxData.end()) {
1370 // if matching bool is not found, insert "true" and the descriptor
1371 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1372 assert(itDescriptor == auxData.end());
1373 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1374 }
1375 else {
1376 // if matching bool is found and is false, early exit (a previous descriptor did not match)
1377 bool matching = boost::any_cast<bool>(itMatching->second);
1378 if (!matching) return;
1379 assert(itDescriptor != auxData.end());
1380 // if matching bool is true, check whether the existing descriptor matches the current one and set
1381 // matching bool to false if not
1382 const Descriptor::Ptr existingDescriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1383 if (*existingDescriptor != *descriptor) {
1384 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = false;
1385 }
1386 }
1387 }
1388
1389 static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1390 {
1391 std::string matchingKey("hasMatchingDescriptor");
1392 auto itMatching = auxData.find(matchingKey);
1393 // if matching key is not found, no matching descriptor
1394 if (itMatching == auxData.end()) return false;
1395 // if matching key is found and is false, no matching descriptor
1396 if (!boost::any_cast<bool>(itMatching->second)) return false;
1397 return true;
1398 }
1399
1400 static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1401 {
1402 std::string descriptorKey("descriptorPtr");
1403 auto itDescriptor = auxData.find(descriptorKey);
1404 // if matching key is true, however descriptor is not found, it has already been retrieved
1405 if (itDescriptor == auxData.end()) return nullptr;
1406 // otherwise remove it and return it
1407 const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1408 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1409 return descriptor;
1410 }
1411
1412 static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1413 {
1414 std::string matchingKey("hasMatchingDescriptor");
1415 std::string descriptorKey("descriptorPtr");
1416 auto itMatching = auxData.find(matchingKey);
1417 auto itDescriptor = auxData.find(descriptorKey);
1418 if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1419 if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1420 }
1421 };
1422
1423 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(os);
1424
1425 if (!meta) {
1426 OPENVDB_THROW(IoError, "Cannot write out a PointDataLeaf without StreamMetadata.");
1427 }
1428
1429 const Index pass(static_cast<uint16_t>(meta->pass()));
1430
1431 // leaf traversal analysis deduces the number of passes to perform for this leaf
1432 // then updates the leaf traversal value to ensure all passes will be written
1433
1434 if (meta->countingPasses()) {
1435 const Index requiredPasses = this->buffers();
1436 if (requiredPasses > pass) {
1437 meta->setPass(requiredPasses);
1438 }
1439 return;
1440 }
1441
1442 const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1443 const Index attributes = (maximumPass - 4) / 2;
1444
1445 if (pass == 0) {
1446 // pass 0 - voxel data sizes
1447 io::writeCompressedValuesSize(os, this->buffer().data(), SIZE);
1448 // track if descriptor is shared or not
1449 Local::insertDescriptor(meta->auxData(), mAttributeSet->descriptorPtr());
1450 }
1451 else if (pass == 1) {
1452 // pass 1 - descriptor and attribute metadata
1453 bool matchingDescriptor = Local::hasMatchingDescriptor(meta->auxData());
1454 if (matchingDescriptor) {
1455 AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1456 if (descriptor) {
1457 // write a header to indicate a shared descriptor
1458 uint8_t header(1);
1459 os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1460 mAttributeSet->writeDescriptor(os, /*transient=*/false);
1461 }
1462 }
1463 else {
1464 // write a header to indicate a non-shared descriptor
1465 uint8_t header(0);
1466 os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1467 mAttributeSet->writeDescriptor(os, /*transient=*/false);
1468 }
1469 mAttributeSet->writeMetadata(os, /*transient=*/false, /*paged=*/true);
1470 }
1471 else if (pass < attributes + 2) {
1472 // pass 2...n+2 - attribute buffer sizes
1473 const Index attributeIndex = pass - 2;
1474 // destroy previous paged stream
1475 if (pass > 2) {
1476 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1477 }
1478 const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1479 mAttributeSet->getConst(attributeIndex) : nullptr;
1480 if (array) {
1481 compression::PagedOutputStream& pagedStream =
1482 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1483 pagedStream.setOutputStream(os);
1484 pagedStream.setSizeOnly(true);
1485 array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1486 }
1487 }
1488 else if (pass == attributes + 2) {
1489 const Index attributeIndex = pass - 3;
1490 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1491 // pass n+2 - voxel data
1492 BaseLeaf::writeBuffers(os, toHalf);
1493 }
1494 else if (pass < (attributes*2 + 3)) {
1495 // pass n+3...2n+3 - attribute buffers
1496 const Index attributeIndex = pass - attributes - 3;
1497 // destroy previous paged stream
1498 if (pass > attributes + 2) {
1499 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1500 }
1501 const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1502 mAttributeSet->getConst(attributeIndex) : nullptr;
1503 if (array) {
1504 compression::PagedOutputStream& pagedStream =
1505 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1506 pagedStream.setOutputStream(os);
1507 pagedStream.setSizeOnly(false);
1508 array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1509 }
1510 }
1511 else if (pass < buffers()) {
1512 Local::clearMatchingDescriptor(meta->auxData());
1513 // pass 2n+3 - cleanup last paged stream
1514 const Index attributeIndex = pass - attributes - 4;
1515 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1516 }
1517}
1518
1519template<typename T, Index Log2Dim>
1520inline Index64
1521 PointDataLeafNode<T, Log2Dim>::memUsage() const
1522{
1523 return BaseLeaf::memUsage() + mAttributeSet->memUsage();
1524}
1525
1526#if OPENVDB_ABI_VERSION_NUMBER >= 10
1527template<typename T, Index Log2Dim>
1528inline Index64
1529 PointDataLeafNode<T, Log2Dim>::memUsageIfLoaded() const
1530{
1531 return BaseLeaf::memUsageIfLoaded() + mAttributeSet->memUsageIfLoaded();
1532}
1533#endif
1534
1535template<typename T, Index Log2Dim>
1536inline void
1537 PointDataLeafNode<T, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
1538{
1539 BaseLeaf::evalActiveBoundingBox(bbox, visitVoxels);
1540}
1541
1542template<typename T, Index Log2Dim>
1543inline CoordBBox
1544 PointDataLeafNode<T, Log2Dim>::getNodeBoundingBox() const
1545{
1546 return BaseLeaf::getNodeBoundingBox();
1547}
1548
1549template<typename T, Index Log2Dim>
1550inline void
1551 PointDataLeafNode<T, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1552{
1553 if (!this->allocate()) return;
1554
1555 this->assertNonModifiableUnlessZero(value);
1556
1557 // active state is permitted to be updated
1558
1559 for (Int32 x = bbox.min().x(); x <= bbox.max().x(); ++x) {
1560 const Index offsetX = (x & (DIM-1u)) << 2*Log2Dim;
1561 for (Int32 y = bbox.min().y(); y <= bbox.max().y(); ++y) {
1562 const Index offsetXY = offsetX + ((y & (DIM-1u)) << Log2Dim);
1563 for (Int32 z = bbox.min().z(); z <= bbox.max().z(); ++z) {
1564 const Index offset = offsetXY + (z & (DIM-1u));
1565 this->setValueMask(offset, active);
1566 }
1567 }
1568 }
1569}
1570
1571template<typename T, Index Log2Dim>
1572inline void
1573 PointDataLeafNode<T, Log2Dim>::fill(const ValueType& value, bool active)
1574{
1575 this->assertNonModifiableUnlessZero(value);
1576
1577 // active state is permitted to be updated
1578
1579 if (active) this->setValuesOn();
1580 else this->setValuesOff();
1581}
1582
1583
1584////////////////////////////////////////
1585
1586
1587template <typename PointDataTreeT>
1588inline AttributeSet::Descriptor::Ptr
1589makeDescriptorUnique(PointDataTreeT& tree)
1590{
1591 auto leafIter = tree.beginLeaf();
1592 if (!leafIter) return nullptr;
1593
1594 const AttributeSet::Descriptor& descriptor = leafIter->attributeSet().descriptor();
1595 auto newDescriptor = std::make_shared<AttributeSet::Descriptor>(descriptor);
1596 for (; leafIter; ++leafIter) {
1597 leafIter->resetDescriptor(newDescriptor);
1598 }
1599
1600 return newDescriptor;
1601}
1602
1603
1604template <typename PointDataTreeT>
1605inline void
1606setStreamingMode(PointDataTreeT& tree, bool on)
1607{
1608 auto leafIter = tree.beginLeaf();
1609 for (; leafIter; ++leafIter) {
1610 for (size_t i = 0; i < leafIter->attributeSet().size(); i++) {
1611 leafIter->attributeArray(i).setStreaming(on);
1612 }
1613 }
1614}
1615
1616
1617template <typename PointDataTreeT>
1618inline void
1619prefetch(PointDataTreeT& tree, bool position, bool otherAttributes)
1620{
1621 // NOTE: the following is intentionally not multi-threaded, as the I/O
1622 // is faster if done in the order in which it is stored in the file
1623
1624 auto leaf = tree.cbeginLeaf();
1625 if (!leaf) return;
1626
1627 const auto& attributeSet = leaf->attributeSet();
1628
1629 // pre-fetch leaf data
1630
1631 for ( ; leaf; ++leaf) {
1632 leaf->buffer().data();
1633 }
1634
1635 // pre-fetch position attribute data (position will typically have index 0)
1636
1637 size_t positionIndex = attributeSet.find("P");
1638
1639 if (position && positionIndex != AttributeSet::INVALID_POS) {
1640 for (leaf = tree.cbeginLeaf(); leaf; ++leaf) {
1641 assert(leaf->hasAttribute(positionIndex));
1642 leaf->constAttributeArray(positionIndex).loadData();
1643 }
1644 }
1645
1646 // pre-fetch other attribute data
1647
1648 if (otherAttributes) {
1649 const size_t attributes = attributeSet.size();
1650 for (size_t attributeIndex = 0; attributeIndex < attributes; attributeIndex++) {
1651 if (attributeIndex == positionIndex) continue;
1652 for (leaf = tree.cbeginLeaf(); leaf; ++leaf) {
1653 assert(leaf->hasAttribute(attributeIndex));
1654 leaf->constAttributeArray(attributeIndex).loadData();
1655 }
1656 }
1657 }
1658}
1659
1660
1661namespace internal {
1662
1663/// @brief Global registration of point data-related types
1664/// @note This is called from @c openvdb::initialize, so there is
1665/// no need to call it directly.
1666 void initialize();
1667
1668/// @brief Global deregistration of point data-related types
1669/// @note This is called from @c openvdb::uninitialize, so there is
1670/// no need to call it directly.
1671 void uninitialize();
1672
1673
1674/// @brief Recursive node chain which generates a openvdb::TypeList value
1675/// converted types of nodes to PointDataGrid nodes of the same configuration,
1676/// rooted at RootNodeType in reverse order, from LeafNode to RootNode.
1677/// See also TreeConverter<>.
1678template<typename HeadT, int HeadLevel>
1679 struct PointDataNodeChain
1680{
1681 using SubtreeT = typename PointDataNodeChain<typename HeadT::ChildNodeType, HeadLevel-1>::Type;
1682 using RootNodeT = tree::RootNode<typename SubtreeT::Back>;
1683 using Type = typename SubtreeT::template Append<RootNodeT>;
1684};
1685
1686// Specialization for internal nodes which require their embedded child type to
1687// be switched
1688template <typename ChildT, Index Log2Dim, int HeadLevel>
1689 struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, HeadLevel>
1690{
1691 using SubtreeT = typename PointDataNodeChain<ChildT, HeadLevel-1>::Type;
1692 using InternalNodeT = tree::InternalNode<typename SubtreeT::Back, Log2Dim>;
1693 using Type = typename SubtreeT::template Append<InternalNodeT>;
1694};
1695
1696// Specialization for the last internal node of a node chain, expected
1697// to be templated on a leaf node
1698template <typename ChildT, Index Log2Dim>
1699 struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, /*HeadLevel=*/1>
1700{
1701 using LeafNodeT = PointDataLeafNode<PointDataIndex32, ChildT::LOG2DIM>;
1702 using InternalNodeT = tree::InternalNode<LeafNodeT, Log2Dim>;
1703 using Type = TypeList<LeafNodeT, InternalNodeT>;
1704};
1705
1706} // namespace internal
1707
1708
1709/// @brief Similiar to ValueConverter, but allows for tree configuration conversion
1710/// to a PointDataTree. ValueConverter<PointDataIndex32> cannot be used as a
1711/// PointDataLeafNode is not a specialization of LeafNode
1712template <typename TreeType>
1713 struct TreeConverter {
1714 using RootNodeT = typename TreeType::RootNodeType;
1715 using NodeChainT = typename internal::PointDataNodeChain<RootNodeT, RootNodeT::LEVEL>::Type;
1716 using Type = tree::Tree<typename NodeChainT::Back>;
1717};
1718
1719
1720} // namespace points
1721
1722
1723////////////////////////////////////////
1724
1725
1726namespace tree
1727{
1728
1729/// Helper metafunction used to implement LeafNode::SameConfiguration
1730/// (which, as an inner class, can't be independently specialized)
1731template<Index Dim1, typename T2>
1732 struct SameLeafConfig<Dim1, points::PointDataLeafNode<T2, Dim1>> { static const bool value = true; };
1733
1734} // namespace tree
1735} // namespace OPENVDB_VERSION_NAME
1736} // namespace openvdb
1737
1738#endif // OPENVDB_POINTS_POINT_DATA_GRID_HAS_BEEN_INCLUDED
AttributeArrayString.h
Attribute array storage for string data using Descriptor Metadata.
AttributeArray.h
Attribute Array storage templated on type and compression codec.
AttributeGroup.h
Attribute Group access and filtering for iteration.
AttributeSet.h
Set of Attribute Arrays which tracks metadata about each array.
value
ValueT value
Definition: GridBuilder.h:1287
Grid.h
LeafNode.h
OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_END
Definition: Platform.h:116
OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
#define OPENVDB_NO_UNREACHABLE_CODE_WARNING_BEGIN
SIMD Intrinsic Headers.
Definition: Platform.h:115
VMASK_
#define VMASK_
Definition: PointDataGrid.h:703
PointIndexGrid.h
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
StreamCompression.h
Convenience wrappers to using Blosc and reading and writing of Paged data.
Tree.h
openvdb::v9_1::Grid
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:573
openvdb::v9_1::IndexError
Definition: Exceptions.h:57
openvdb::v9_1::IoError
Definition: Exceptions.h:58
openvdb::v9_1::LookupError
Definition: Exceptions.h:60
openvdb::v9_1::Metadata
Base class for storing metadata information in a grid.
Definition: Metadata.h:24
openvdb::v9_1::PartialCreate
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:650
openvdb::v9_1::TopologyCopy
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:644
openvdb::v9_1::ValueError
Definition: Exceptions.h:65
openvdb::v9_1::compression::PagedInputStream
A Paging wrapper to std::istream that is responsible for reading from a given input stream and creati...
Definition: StreamCompression.h:205
openvdb::v9_1::compression::PagedInputStream::setSizeOnly
void setSizeOnly(bool sizeOnly)
Size-only mode tags the stream as only reading size data.
Definition: StreamCompression.h:214
openvdb::v9_1::compression::PagedInputStream::setInputStream
void setInputStream(std::istream &is)
Definition: StreamCompression.h:219
openvdb::v9_1::compression::PagedInputStream::Ptr
std::shared_ptr< PagedInputStream > Ptr
Definition: StreamCompression.h:207
openvdb::v9_1::compression::PagedOutputStream
A Paging wrapper to std::ostream that is responsible for writing from a given output stream at interv...
Definition: StreamCompression.h:242
openvdb::v9_1::compression::PagedOutputStream::setSizeOnly
void setSizeOnly(bool sizeOnly)
Size-only mode tags the stream as only writing size data.
Definition: StreamCompression.h:251
openvdb::v9_1::compression::PagedOutputStream::setOutputStream
void setOutputStream(std::ostream &os)
Definition: StreamCompression.h:256
openvdb::v9_1::compression::PagedOutputStream::Ptr
std::shared_ptr< PagedOutputStream > Ptr
Definition: StreamCompression.h:244
openvdb::v9_1::compression::PagedOutputStream::flush
void flush()
Manually flushes the current page to disk if non-zero.
openvdb::v9_1::io::StreamMetadata
Container for metadata describing how to unserialize grids from and/or serialize grids to a stream (w...
Definition: io.h:31
openvdb::v9_1::io::StreamMetadata::Ptr
SharedPtr< StreamMetadata > Ptr
Definition: io.h:33
openvdb::v9_1::io::StreamMetadata::AuxDataMap
std::map< std::string, boost::any > AuxDataMap
Definition: io.h:92
openvdb::v9_1::io::StreamMetadata::setPass
void setPass(uint32_t)
openvdb::v9_1::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:249
openvdb::v9_1::math::CoordBBox::min
const Coord & min() const
Definition: Coord.h:321
openvdb::v9_1::math::CoordBBox::max
const Coord & max() const
Definition: Coord.h:322
openvdb::v9_1::math::CoordBBox::inf
static CoordBBox inf()
Return an "infinite" bounding box, as defined by the Coord value range.
Definition: Coord.h:319
openvdb::v9_1::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
openvdb::v9_1::math::Coord::y
Int32 y() const
Definition: Coord.h:131
openvdb::v9_1::math::Coord::x
Int32 x() const
Definition: Coord.h:130
openvdb::v9_1::math::Coord::z
Int32 z() const
Definition: Coord.h:132
openvdb::v9_1::points::AttributeArray::ScopedRegistryLock
Definition: AttributeArray.h:119
openvdb::v9_1::points::AttributeArray
Base class for storing attribute data.
Definition: AttributeArray.h:93
openvdb::v9_1::points::AttributeArray::Ptr
std::shared_ptr< AttributeArray > Ptr
Definition: AttributeArray.h:125
openvdb::v9_1::points::AttributeArray::size
virtual Index size() const =0
openvdb::v9_1::points::AttributeArray::compact
virtual bool compact()=0
Compact the existing array to become uniform if all values are identical.
openvdb::v9_1::points::AttributeArray::readPagedBuffers
virtual void readPagedBuffers(compression::PagedInputStream &)=0
Read attribute buffers from a paged stream.
openvdb::v9_1::points::AttributeArray::writePagedBuffers
virtual void writePagedBuffers(compression::PagedOutputStream &, bool outputTransient) const =0
openvdb::v9_1::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:39
openvdb::v9_1::points::AttributeSet::descriptor
Descriptor & descriptor()
Return a reference to this attribute set's descriptor, which might be shared with other sets.
Definition: AttributeSet.h:102
openvdb::v9_1::points::AttributeSet::UniquePtr
std::unique_ptr< AttributeSet > UniquePtr
Definition: AttributeSet.h:45
openvdb::v9_1::points::AttributeSet::DescriptorPtr
std::shared_ptr< Descriptor > DescriptorPtr
Definition: AttributeSet.h:49
openvdb::v9_1::points::GroupFilter
Index filtering on group membership.
Definition: AttributeGroup.h:135
openvdb::v9_1::points::GroupFilter::state
static index::State state()
Definition: AttributeGroup.h:145
openvdb::v9_1::points::GroupHandle
Definition: AttributeGroup.h:73
openvdb::v9_1::points::GroupWriteHandle
Definition: AttributeGroup.h:102
openvdb::v9_1::points::IndexIter
A forward iterator over array indices with filtering IteratorT can be either IndexIter or ValueIndexI...
Definition: IndexIterator.h:140
openvdb::v9_1::points::NullFilter
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:51
openvdb::v9_1::points::PointDataLeafNode
Definition: PointDataGrid.h:239
openvdb::v9_1::points::PointDataLeafNode::cbeginChildOn
ChildOnCIter cbeginChildOn() const
Definition: PointDataGrid.h:724
openvdb::v9_1::points::PointDataLeafNode::setValueOn
void setValueOn(Index offset)
Definition: PointDataGrid.h:545
openvdb::v9_1::points::PointDataLeafNode::setValueOff
void setValueOff(const Coord &, const ValueType &)
Definition: PointDataGrid.h:541
openvdb::v9_1::points::PointDataLeafNode::beginChildOn
ChildOnCIter beginChildOn() const
Definition: PointDataGrid.h:725
openvdb::v9_1::points::PointDataLeafNode::beginChildOn
ChildOnIter beginChildOn()
Definition: PointDataGrid.h:726
openvdb::v9_1::points::PointDataLeafNode::setActiveStateAndCache
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &parent)
Definition: PointDataGrid.h:583
openvdb::v9_1::points::PointDataLeafNode::endValueOn
ValueOnIter endValueOn()
Definition: PointDataGrid.h:716
openvdb::v9_1::points::PointDataLeafNode::touchLeaf
PointDataLeafNode * touchLeaf(const Coord &)
Return a pointer to this node.
Definition: PointDataGrid.h:458
openvdb::v9_1::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const tools::PointIndexLeafNode< OtherValueType, Log2Dim > &other)
Definition: PointDataGrid.h:296
openvdb::v9_1::points::PointDataLeafNode::cbeginValueOff
ValueOffCIter cbeginValueOff() const
Definition: PointDataGrid.h:707
openvdb::v9_1::points::PointDataLeafNode::ChildOnIter
typename BaseLeaf::template ChildIter< MaskOnIterator, PointDataLeafNode, ChildOn > ChildOnIter
Definition: PointDataGrid.h:642
openvdb::v9_1::points::PointDataLeafNode::touchLeafAndCache
PointDataLeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:460
openvdb::v9_1::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const PointDataLeafNode &other, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition: PointDataGrid.h:286
openvdb::v9_1::points::PointDataLeafNode::operator==
bool operator==(const PointDataLeafNode &other) const
Definition: PointDataGrid.h:445
openvdb::v9_1::points::PointDataLeafNode::hasSameTopology
bool hasSameTopology(const PointDataLeafNode< OtherType, OtherLog2Dim > *other) const
Return true if the given node (which may have a different ValueType than this node) has the same acti...
Definition: PointDataGrid.h:439
openvdb::v9_1::points::PointDataLeafNode::endChildOn
ChildOnIter endChildOn()
Definition: PointDataGrid.h:736
openvdb::v9_1::points::PointDataLeafNode::endValueAll
ValueAllIter endValueAll()
Definition: PointDataGrid.h:722
openvdb::v9_1::points::PointDataLeafNode::modifyValue
void modifyValue(Index, const ModifyOp &)
Definition: PointDataGrid.h:556
openvdb::v9_1::points::PointDataLeafNode::setValueOn
void setValueOn(Index, const ValueType &)
Definition: PointDataGrid.h:548
openvdb::v9_1::points::PointDataLeafNode::setValuesOff
void setValuesOff()
Definition: PointDataGrid.h:553
openvdb::v9_1::points::PointDataLeafNode::endValueAll
ValueAllCIter endValueAll() const
Definition: PointDataGrid.h:721
openvdb::v9_1::points::PointDataLeafNode::probeLeaf
const PointDataLeafNode * probeLeaf(const Coord &) const
Definition: PointDataGrid.h:482
openvdb::v9_1::points::PointDataLeafNode::endChildOff
ChildOffCIter endChildOff() const
Definition: PointDataGrid.h:738
openvdb::v9_1::points::PointDataLeafNode::setValueOff
void setValueOff(Index, const ValueType &)
Definition: PointDataGrid.h:542
openvdb::v9_1::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(PartialCreate, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition: PointDataGrid.h:314
openvdb::v9_1::points::PointDataLeafNode::cbeginValueAll
ValueAllCIter cbeginValueAll() const
Definition: PointDataGrid.h:710
openvdb::v9_1::points::PointDataLeafNode::ChildOff
typename BaseLeaf::ChildOff ChildOff
Definition: PointDataGrid.h:608
openvdb::v9_1::points::PointDataLeafNode::probeConstLeaf
const PointDataLeafNode * probeConstLeaf(const Coord &) const
Return a const pointer to this node.
Definition: PointDataGrid.h:477
openvdb::v9_1::points::PointDataLeafNode::setValueOnly
void setValueOnly(Index, const ValueType &)
Definition: PointDataGrid.h:536
openvdb::v9_1::points::PointDataLeafNode::Ptr
std::shared_ptr< PointDataLeafNode > Ptr
Definition: PointDataGrid.h:243
openvdb::v9_1::points::PointDataLeafNode::beginIndexAll
IndexAllIter beginIndexAll() const
Leaf index iterator.
Definition: PointDataGrid.h:660
openvdb::v9_1::points::PointDataLeafNode::beginValueOn
ValueOnCIter beginValueOn() const
Definition: PointDataGrid.h:705
openvdb::v9_1::points::PointDataLeafNode::ChildOn
typename BaseLeaf::ChildOn ChildOn
Definition: PointDataGrid.h:607
openvdb::v9_1::points::PointDataLeafNode::signedFloodFill
void signedFloodFill(const ValueType &, const ValueType &)
Definition: PointDataGrid.h:592
openvdb::v9_1::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const PointDataLeafNode &other)
Construct using deep copy of other PointDataLeafNode.
Definition: PointDataGrid.h:274
openvdb::v9_1::points::PointDataLeafNode::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &, const ModifyOp &)
Definition: PointDataGrid.h:562
openvdb::v9_1::points::PointDataLeafNode::ValueAllIter
typename BaseLeaf::template ValueIter< MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll > ValueAllIter
Definition: PointDataGrid.h:638
openvdb::v9_1::points::PointDataLeafNode::ChildAll
typename BaseLeaf::ChildAll ChildAll
Definition: PointDataGrid.h:609
openvdb::v9_1::points::PointDataLeafNode::beginIndex
IndexIter< IterT, FilterT > beginIndex(const FilterT &filter) const
openvdb::v9_1::points::PointDataLeafNode::ValueOffIter
typename BaseLeaf::template ValueIter< MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff > ValueOffIter
Definition: PointDataGrid.h:634
openvdb::v9_1::points::PointDataLeafNode::cendValueOn
ValueOnCIter cendValueOn() const
Definition: PointDataGrid.h:714
openvdb::v9_1::points::PointDataLeafNode::beginValueOff
ValueOffCIter beginValueOff() const
Definition: PointDataGrid.h:708
openvdb::v9_1::points::PointDataLeafNode::resetDescriptor
void resetDescriptor(const Descriptor::Ptr &replacement)
Replace the descriptor with a new one The new Descriptor must exactly match the old one.
Definition: PointDataGrid.h:866
openvdb::v9_1::points::PointDataLeafNode::beginIndexOff
IndexOffIter beginIndexOff() const
Definition: PointDataGrid.h:670
openvdb::v9_1::points::PointDataLeafNode::cbeginChildAll
ChildAllCIter cbeginChildAll() const
Definition: PointDataGrid.h:730
openvdb::v9_1::points::PointDataLeafNode::endChildOff
ChildOffIter endChildOff()
Definition: PointDataGrid.h:739
openvdb::v9_1::points::PointDataLeafNode::modifyValueAndActiveStateAndCache
void modifyValueAndActiveStateAndCache(const Coord &, const ModifyOp &, AccessorT &)
Definition: PointDataGrid.h:575
openvdb::v9_1::points::PointDataLeafNode::setValueOnly
void setValueOnly(const Coord &, const ValueType &)
Definition: PointDataGrid.h:535
openvdb::v9_1::points::PointDataLeafNode::beginChildAll
ChildAllIter beginChildAll()
Definition: PointDataGrid.h:732
openvdb::v9_1::points::PointDataLeafNode::probeConstLeafAndCache
const PointDataLeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:479
openvdb::v9_1::points::PointDataLeafNode::setActiveState
void setActiveState(const Coord &xyz, bool on)
Definition: PointDataGrid.h:532
openvdb::v9_1::points::PointDataLeafNode::beginValueOn
ValueOnIter beginValueOn()
Definition: PointDataGrid.h:706
openvdb::v9_1::points::PointDataLeafNode::ChildOffCIter
typename BaseLeaf::template ChildIter< MaskOffIterator, const PointDataLeafNode, ChildOff > ChildOffCIter
Definition: PointDataGrid.h:648
openvdb::v9_1::points::PointDataLeafNode::probeNodeAndCache
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:463
openvdb::v9_1::points::PointDataLeafNode::beginIndexAll
IndexIter< ValueAllCIter, FilterT > beginIndexAll(const FilterT &filter) const
Filtered leaf index iterator.
Definition: PointDataGrid.h:681
openvdb::v9_1::points::PointDataLeafNode::assertNonModifiableUnlessZero
void assertNonModifiableUnlessZero(const ValueType &value)
Definition: PointDataGrid.h:528
openvdb::v9_1::points::PointDataLeafNode::probeLeafAndCache
const PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:481
openvdb::v9_1::points::PointDataLeafNode::cbeginChildOff
ChildOffCIter cbeginChildOff() const
Definition: PointDataGrid.h:727
openvdb::v9_1::points::PointDataLeafNode::beginChildOff
ChildOffIter beginChildOff()
Definition: PointDataGrid.h:729
openvdb::v9_1::points::PointDataLeafNode::beginChildOff
ChildOffCIter beginChildOff() const
Definition: PointDataGrid.h:728
openvdb::v9_1::points::PointDataLeafNode::setValueOff
void setValueOff(const Coord &xyz)
Definition: PointDataGrid.h:538
openvdb::v9_1::points::PointDataLeafNode::operator!=
bool operator!=(const PointDataLeafNode &other) const
Definition: PointDataGrid.h:450
openvdb::v9_1::points::PointDataLeafNode::endValueOff
ValueOffIter endValueOff()
Definition: PointDataGrid.h:719
openvdb::v9_1::points::PointDataLeafNode::setValueOff
void setValueOff(Index offset)
Definition: PointDataGrid.h:539
openvdb::v9_1::points::PointDataLeafNode::beginIndexOn
IndexIter< ValueOnCIter, FilterT > beginIndexOn(const FilterT &filter) const
Definition: PointDataGrid.h:686
openvdb::v9_1::points::PointDataLeafNode::endChildAll
ChildAllCIter endChildAll() const
Definition: PointDataGrid.h:741
openvdb::v9_1::points::PointDataLeafNode::probeConstNodeAndCache
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:484
openvdb::v9_1::points::PointDataLeafNode::cbeginValueOn
ValueOnCIter cbeginValueOn() const
Definition: PointDataGrid.h:704
openvdb::v9_1::points::PointDataLeafNode::ChildAllCIter
typename BaseLeaf::template DenseIter< const PointDataLeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: PointDataGrid.h:652
openvdb::v9_1::points::PointDataLeafNode::clip
void clip(const CoordBBox &, const ValueType &value)
Definition: PointDataGrid.h:565
openvdb::v9_1::points::PointDataLeafNode::endChildOn
ChildOnCIter endChildOn() const
Definition: PointDataGrid.h:735
openvdb::v9_1::points::PointDataLeafNode::reorderAttributes
void reorderAttributes(const Descriptor::Ptr &replacement)
Reorder attribute set.
Definition: PointDataGrid.h:827
openvdb::v9_1::points::PointDataLeafNode::ValueOnCIter
typename BaseLeaf::template ValueIter< MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn > ValueOnCIter
Definition: PointDataGrid.h:632
openvdb::v9_1::points::PointDataLeafNode::cendChildOn
ChildOnCIter cendChildOn() const
Definition: PointDataGrid.h:734
openvdb::v9_1::points::PointDataLeafNode::cendChildAll
ChildAllCIter cendChildAll() const
Definition: PointDataGrid.h:740
openvdb::v9_1::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode()
Default constructor.
Definition: PointDataGrid.h:268
openvdb::v9_1::points::PointDataLeafNode::attributeSet
const AttributeSet & attributeSet() const
Retrieve the attribute set.
Definition: PointDataGrid.h:322
openvdb::v9_1::points::PointDataLeafNode::assertNonmodifiable
void assertNonmodifiable()
Definition: PointDataGrid.h:521
openvdb::v9_1::points::PointDataLeafNode::setValueOffAndCache
void setValueOffAndCache(const Coord &, const ValueType &, AccessorT &)
Definition: PointDataGrid.h:580
openvdb::v9_1::points::PointDataLeafNode::endChildAll
ChildAllIter endChildAll()
Definition: PointDataGrid.h:742
openvdb::v9_1::points::PointDataLeafNode::beginIndexOff
IndexIter< ValueOffCIter, FilterT > beginIndexOff(const FilterT &filter) const
Definition: PointDataGrid.h:691
openvdb::v9_1::points::PointDataLeafNode::resetBackground
void resetBackground(const ValueType &, const ValueType &newBackground)
Definition: PointDataGrid.h:587
openvdb::v9_1::points::PointDataLeafNode::MaskOffIterator
typename NodeMaskType::OffIterator MaskOffIterator
Definition: PointDataGrid.h:612
openvdb::v9_1::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &value, TopologyCopy)
Definition: PointDataGrid.h:303
openvdb::v9_1::points::PointDataLeafNode::setValue
void setValue(const Coord &, const ValueType &)
Definition: PointDataGrid.h:550
openvdb::v9_1::points::PointDataLeafNode::cendValueAll
ValueAllCIter cendValueAll() const
Definition: PointDataGrid.h:720
openvdb::v9_1::points::PointDataLeafNode::~PointDataLeafNode
~PointDataLeafNode()=default
openvdb::v9_1::points::PointDataLeafNode::negate
void negate()
Definition: PointDataGrid.h:594
openvdb::v9_1::points::PointDataLeafNode::beginChildAll
ChildAllCIter beginChildAll() const
Definition: PointDataGrid.h:731
openvdb::v9_1::points::PointDataLeafNode::ValueAll
typename BaseLeaf::ValueAll ValueAll
Definition: PointDataGrid.h:600
openvdb::v9_1::points::PointDataLeafNode::ValueTypePair
std::pair< ValueType, ValueType > ValueTypePair
Definition: PointDataGrid.h:246
openvdb::v9_1::points::PointDataLeafNode::setValuesOn
void setValuesOn()
Definition: PointDataGrid.h:552
openvdb::v9_1::points::PointDataLeafNode::Descriptor
AttributeSet::Descriptor Descriptor
Definition: PointDataGrid.h:249
openvdb::v9_1::points::PointDataLeafNode::ValueOn
typename BaseLeaf::ValueOn ValueOn
Definition: PointDataGrid.h:598
openvdb::v9_1::points::PointDataLeafNode::cendChildOff
ChildOffCIter cendChildOff() const
Definition: PointDataGrid.h:737
openvdb::v9_1::points::PointDataLeafNode::addLeafAndCache
void addLeafAndCache(PointDataLeafNode *, AccessorT &)
Definition: PointDataGrid.h:454
openvdb::v9_1::points::PointDataLeafNode::setValueOnlyAndCache
void setValueOnlyAndCache(const Coord &, const ValueType &, AccessorT &)
Definition: PointDataGrid.h:572
openvdb::v9_1::points::PointDataLeafNode::fill
void fill(const ValueType &value)
Definition: PointDataGrid.h:568
openvdb::v9_1::points::PointDataLeafNode::MaskOnIterator
typename NodeMaskType::OnIterator MaskOnIterator
Definition: PointDataGrid.h:611
openvdb::v9_1::points::PointDataLeafNode::ChildOffIter
typename BaseLeaf::template ChildIter< MaskOffIterator, PointDataLeafNode, ChildOff > ChildOffIter
Definition: PointDataGrid.h:646
openvdb::v9_1::points::PointDataLeafNode::addLeaf
void addLeaf(PointDataLeafNode *)
Definition: PointDataGrid.h:452
openvdb::v9_1::points::PointDataLeafNode::signedFloodFill
void signedFloodFill(const ValueType &)
Definition: PointDataGrid.h:591
openvdb::v9_1::points::PointDataLeafNode::beginValueOff
ValueOffIter beginValueOff()
Definition: PointDataGrid.h:709
openvdb::v9_1::points::PointDataLeafNode::setValueOn
void setValueOn(const Coord &xyz)
Definition: PointDataGrid.h:544
openvdb::v9_1::points::PointDataLeafNode::setActiveState
void setActiveState(Index offset, bool on)
Definition: PointDataGrid.h:533
openvdb::v9_1::points::PointDataLeafNode::ValueOffCIter
typename BaseLeaf::template ValueIter< MaskOffIterator, const PointDataLeafNode, const ValueType, ValueOff > ValueOffCIter
Definition: PointDataGrid.h:636
openvdb::v9_1::points::PointDataLeafNode::beginIndexOn
IndexOnIter beginIndexOn() const
Definition: PointDataGrid.h:665
openvdb::v9_1::points::PointDataLeafNode::ValueOff
typename BaseLeaf::ValueOff ValueOff
Definition: PointDataGrid.h:599
openvdb::v9_1::points::PointDataLeafNode::modifyValue
void modifyValue(const Coord &, const ModifyOp &)
Definition: PointDataGrid.h:559
openvdb::v9_1::points::PointDataLeafNode::cendValueOff
ValueOffCIter cendValueOff() const
Definition: PointDataGrid.h:717
openvdb::v9_1::points::PointDataLeafNode::ChildOnCIter
typename BaseLeaf::template ChildIter< MaskOnIterator, const PointDataLeafNode, ChildOn > ChildOnCIter
Definition: PointDataGrid.h:644
openvdb::v9_1::points::PointDataLeafNode::fill
void fill(const CoordBBox &, const ValueType &, bool)
Definition: PointDataGrid.h:1551
openvdb::v9_1::points::PointDataLeafNode::endValueOff
ValueOffCIter endValueOff() const
Definition: PointDataGrid.h:718
openvdb::v9_1::points::PointDataLeafNode::ValueOnIter
typename BaseLeaf::template ValueIter< MaskOnIterator, PointDataLeafNode, const ValueType, ValueOn > ValueOnIter
Definition: PointDataGrid.h:630
openvdb::v9_1::points::PointDataLeafNode::probeLeaf
PointDataLeafNode * probeLeaf(const Coord &)
Definition: PointDataGrid.h:470
openvdb::v9_1::points::PointDataLeafNode::ValueType
T ValueType
Definition: PointDataGrid.h:245
openvdb::v9_1::points::PointDataLeafNode::probeLeafAndCache
PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:472
openvdb::v9_1::points::PointDataLeafNode::endValueOn
ValueOnCIter endValueOn() const
Definition: PointDataGrid.h:715
openvdb::v9_1::points::PointDataLeafNode::MaskDenseIterator
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition: PointDataGrid.h:613
openvdb::v9_1::points::PointDataLeafNode::beginValueAll
ValueAllCIter beginValueAll() const
Definition: PointDataGrid.h:711
openvdb::v9_1::points::PointDataLeafNode::ChildAllIter
typename BaseLeaf::template DenseIter< PointDataLeafNode, ValueType, ChildAll > ChildAllIter
Definition: PointDataGrid.h:650
openvdb::v9_1::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Construct using supplied origin, value and active status.
Definition: PointDataGrid.h:280
openvdb::v9_1::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &, const T &, TopologyCopy)
Definition: PointDataGrid.h:310
openvdb::v9_1::points::PointDataLeafNode::ValueAllCIter
typename BaseLeaf::template ValueIter< MaskDenseIterator, const PointDataLeafNode, const ValueType, ValueAll > ValueAllCIter
Definition: PointDataGrid.h:640
openvdb::v9_1::points::PointDataLeafNode::setValueOn
void setValueOn(const Coord &, const ValueType &)
Definition: PointDataGrid.h:547
openvdb::v9_1::points::PointDataLeafNode::beginValueAll
ValueAllIter beginValueAll()
Definition: PointDataGrid.h:712
openvdb::v9_1::points::PointDataLeafNode::IndexArray
std::vector< ValueType > IndexArray
Definition: PointDataGrid.h:247
openvdb::v9_1::points::TypedAttributeArray
Typed class for storing attribute data.
Definition: AttributeArray.h:539
openvdb::v9_1::points::ValueVoxelCIter
A forward iterator over array indices in a single voxel.
Definition: IndexIterator.h:65
openvdb::v9_1::tree::InternalNode
Definition: InternalNode.h:34
openvdb::v9_1::tree::IteratorBase
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:30
openvdb::v9_1::tree::LeafNode
Templated block class to hold specific data types and a fixed number of values determined by Log2Dim....
Definition: LeafNode.h:38
openvdb::v9_1::tree::LeafNode::size
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:121
openvdb::v9_1::tree::RootNode
Definition: RootNode.h:39
openvdb::v9_1::tree::Tree
Definition: Tree.h:178
openvdb::v9_1::util::DenseMaskIterator
Definition: NodeMasks.h:271
openvdb::v9_1::util::NodeMask
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition: NodeMasks.h:308
openvdb::v9_1::util::OffMaskIterator
Definition: NodeMasks.h:240
openvdb::v9_1::util::OnMaskIterator
Definition: NodeMasks.h:209
openvdb::v9_1::compression::bloscCompress
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::v9_1::compression::bloscCompressedSize
OPENVDB_API size_t bloscCompressedSize(const char *buffer, const size_t uncompressedBytes)
Convenience wrapper to retrieve the compressed size of buffer when compressed.
openvdb::v9_1::compression::bloscDecompress
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::v9_1::io::writeCompressedValues
void writeCompressedValues(std::ostream &os, PointDataIndex32 *srcBuf, Index srcCount, const util::NodeMask< 3 > &, const util::NodeMask< 3 > &, bool)
openvdb::io::writeCompressedValues specialized on PointDataIndex32 arrays to ignore the value mask,...
Definition: PointDataGrid.h:106
openvdb::v9_1::io::writeCompressedValuesSize
void writeCompressedValuesSize(std::ostream &os, const T *srcBuf, Index srcCount)
Definition: PointDataGrid.h:139
openvdb::v9_1::io::getStreamMetadataPtr
OPENVDB_API SharedPtr< StreamMetadata > getStreamMetadataPtr(std::ios_base &)
Return a shared pointer to an object that stores metadata (file format, compression scheme,...
openvdb::v9_1::io::readCompressedValues
void readCompressedValues(std::istream &is, PointDataIndex32 *destBuf, Index destCount, const util::NodeMask< 3 > &, bool)
openvdb::io::readCompressedValues specialized on PointDataIndex32 arrays to ignore the value mask,...
Definition: PointDataGrid.h:46
openvdb::v9_1::points::index::ALL
@ ALL
Definition: IndexIterator.h:43
openvdb::v9_1::points::index::NONE
@ NONE
Definition: IndexIterator.h:42
openvdb::v9_1::points::internal::initialize
void initialize()
Global registration of point data-related types.
openvdb::v9_1::points::internal::uninitialize
void uninitialize()
Global deregistration of point data-related types.
openvdb::v9_1::points::setStreamingMode
void setStreamingMode(PointDataTreeT &tree, bool on=true)
Toggle the streaming mode on all attributes in the tree to collapse the attributes after deconstructi...
Definition: PointDataGrid.h:1606
openvdb::v9_1::points::prefetch
void prefetch(PointDataTreeT &tree, bool position=true, bool otherAttributes=true)
Sequentially pre-fetch all delayed-load voxel and attribute data from disk in order to accelerate sub...
Definition: PointDataGrid.h:1619
openvdb::v9_1::points::compactAttributes
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Definition: PointAttribute.h:527
openvdb::v9_1::points::pointCount
Index64 pointCount(const PointDataTreeT &tree, const FilterT &filter=NullFilter(), const bool inCoreOnly=false, const bool threaded=true)
Count the total number of points in a PointDataTree.
Definition: PointCount.h:88
openvdb::v9_1::points::appendAttribute
void appendAttribute(PointDataTreeT &tree, const Name &name, const NamePair &type, const Index strideOrTotalSize=1, const bool constantStride=true, const Metadata *defaultValue=nullptr, const bool hidden=false, const bool transient=false)
Appends a new attribute to the VDB tree (this method does not require a templated AttributeType)
Definition: PointAttribute.h:245
openvdb::v9_1::points::dropAttributes
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:380
openvdb::v9_1::points::renameAttributes
void renameAttributes(PointDataTreeT &tree, const std::vector< Name > &oldNames, const std::vector< Name > &newNames)
Rename attributes in a VDB tree.
Definition: PointAttribute.h:468
openvdb::v9_1::points::iterCount
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:314
openvdb::v9_1::points::makeDescriptorUnique
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1589
openvdb::v9_1::points::isGroup
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:63
openvdb::v9_1::tools::composite::max
const std::enable_if<!VecTraits< T >::IsVec, T >::type & max(const T &a, const T &b)
Definition: Composite.h:107
openvdb::v9_1::tools::memUsageIfLoaded
Index64 memUsageIfLoaded(const TreeT &tree, bool threaded=true)
Return the deserialized memory usage of this tree. This is not necessarily equal to the current memor...
Definition: Count.h:502
openvdb::v9_1::tools::memUsage
Index64 memUsage(const TreeT &tree, bool threaded=true)
Return the total amount of memory in bytes occupied by this tree.
Definition: Count.h:493
openvdb::v9_1::Name
std::string Name
Definition: Name.h:17
openvdb::v9_1::Index
Index32 Index
Definition: Types.h:54
openvdb::v9_1::zeroVal
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:69
openvdb::v9_1::typeNameAsString< Vec3f >
const char * typeNameAsString< Vec3f >()
Definition: Types.h:496
openvdb::v9_1::Int32
int32_t Int32
Definition: Types.h:56
openvdb::v9_1::Index64
uint64_t Index64
Definition: Types.h:53
openvdb::v9_1::PointDataIndex32
PointIndex< Index32, 1 > PointDataIndex32
Definition: Types.h:181
openvdb
Definition: Exceptions.h:13
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
allocate
static pnanovdb_uint32_t allocate(pnanovdb_uint32_t *poffset, pnanovdb_uint32_t size, pnanovdb_uint32_t alignment)
Definition: pnanovdb_validate_strides.h:20
openvdb::v9_1::PointIndex
Integer wrapper, required to distinguish PointIndexGrid and PointDataGrid from Int32Grid and Int64Gri...
Definition: Types.h:157
openvdb::v9_1::TypeList
A list of types (not necessarily unique)
Definition: TypeList.h:484
openvdb::v9_1::io::MultiPass
Leaf nodes that require multi-pass I/O must inherit from this struct.
Definition: io.h:124
openvdb::v9_1::points::TreeConverter
Similiar to ValueConverter, but allows for tree configuration conversion to a PointDataTree....
Definition: PointDataGrid.h:1713
openvdb::v9_1::points::TreeConverter::RootNodeT
typename TreeType::RootNodeType RootNodeT
Definition: PointDataGrid.h:1714
openvdb::v9_1::points::TreeConverter::NodeChainT
typename internal::PointDataNodeChain< RootNodeT, RootNodeT::LEVEL >::Type NodeChainT
Definition: PointDataGrid.h:1715
openvdb::v9_1::points::internal::PointDataNodeChain< tree::InternalNode< ChildT, Log2Dim >, HeadLevel >::SubtreeT
typename PointDataNodeChain< ChildT, HeadLevel-1 >::Type SubtreeT
Definition: PointDataGrid.h:1691
openvdb::v9_1::points::internal::PointDataNodeChain< tree::InternalNode< ChildT, Log2Dim >, HeadLevel >::Type
typename SubtreeT::template Append< InternalNodeT > Type
Definition: PointDataGrid.h:1693
openvdb::v9_1::points::internal::PointDataNodeChain
Recursive node chain which generates a openvdb::TypeList value converted types of nodes to PointDataG...
Definition: PointDataGrid.h:1680
openvdb::v9_1::points::internal::PointDataNodeChain::SubtreeT
typename PointDataNodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: PointDataGrid.h:1681
openvdb::v9_1::points::internal::PointDataNodeChain::Type
typename SubtreeT::template Append< RootNodeT > Type
Definition: PointDataGrid.h:1683
openvdb::v9_1::tools::PointIndexLeafNode
Definition: PointIndexGrid.h:1358
openvdb::v9_1::tree::IterTraits
Definition: TreeIterator.h:60
openvdb::v9_1::tree::LeafNode::ChildAll
Definition: LeafNode.h:212
openvdb::v9_1::tree::LeafNode::ChildIter
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:252
openvdb::v9_1::tree::LeafNode::ChildOff
Definition: LeafNode.h:212
openvdb::v9_1::tree::LeafNode::ChildOn
Definition: LeafNode.h:212
openvdb::v9_1::tree::LeafNode::DenseIter
Definition: LeafNode.h:261
openvdb::v9_1::tree::LeafNode::ValueAll
Definition: LeafNode.h:211
openvdb::v9_1::tree::LeafNode::ValueIter
Definition: LeafNode.h:220
openvdb::v9_1::tree::LeafNode::ValueOff
Definition: LeafNode.h:211
openvdb::v9_1::tree::LeafNode::ValueOn
Definition: LeafNode.h:211
openvdb::v9_1::tree::SameLeafConfig
Definition: LeafNode.h:924
OPENVDB_VERSION_NAME
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h.in:116
OPENVDB_USE_VERSION_NAMESPACE
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h.in:202