OpenVDB: openvdb/points/PointDataGrid.h Source File

OpenVDB 9.0.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
507 void evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels = true) const;
508
509 /// @brief Return the bounding box of this node, i.e., the full index space
510 /// spanned by this leaf node.
511 CoordBBox getNodeBoundingBox() const;
512
513 ////////////////////////////////////////
514
515 // Disable all write methods to avoid unintentional changes
516 // to the point-array offsets.
517
518 void assertNonmodifiable() {
519 assert(false && "Cannot modify voxel values in a PointDataTree.");
520 }
521
522 // some methods silently ignore attempts to modify the
523 // point-array offsets if a zero value is used
524
525 void assertNonModifiableUnlessZero(const ValueType& value) {
526 if (value != zeroVal<T>()) this->assertNonmodifiable();
527 }
528
529 void setActiveState(const Coord& xyz, bool on) { BaseLeaf::setActiveState(xyz, on); }
530 void setActiveState(Index offset, bool on) { BaseLeaf::setActiveState(offset, on); }
531
532 void setValueOnly(const Coord&, const ValueType&) { assertNonmodifiable(); }
533 void setValueOnly(Index, const ValueType&) { assertNonmodifiable(); }
534
535 void setValueOff(const Coord& xyz) { BaseLeaf::setValueOff(xyz); }
536 void setValueOff(Index offset) { BaseLeaf::setValueOff(offset); }
537
538 void setValueOff(const Coord&, const ValueType&) { assertNonmodifiable(); }
539 void setValueOff(Index, const ValueType&) { assertNonmodifiable(); }
540
541 void setValueOn(const Coord& xyz) { BaseLeaf::setValueOn(xyz); }
542 void setValueOn(Index offset) { BaseLeaf::setValueOn(offset); }
543
544 void setValueOn(const Coord&, const ValueType&) { assertNonmodifiable(); }
545 void setValueOn(Index, const ValueType&) { assertNonmodifiable(); }
546
547 void setValue(const Coord&, const ValueType&) { assertNonmodifiable(); }
548
549 void setValuesOn() { BaseLeaf::setValuesOn(); }
550 void setValuesOff() { BaseLeaf::setValuesOff(); }
551
552 template<typename ModifyOp>
553 void modifyValue(Index, const ModifyOp&) { assertNonmodifiable(); }
554
555 template<typename ModifyOp>
556 void modifyValue(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
557
558 template<typename ModifyOp>
559 void modifyValueAndActiveState(const Coord&, const ModifyOp&) { assertNonmodifiable(); }
560
561 // clipping is not yet supported
562 void clip(const CoordBBox&, const ValueType& value) { assertNonModifiableUnlessZero(value); }
563
564 void fill(const CoordBBox&, const ValueType&, bool);
565 void fill(const ValueType& value) { assertNonModifiableUnlessZero(value); }
566 void fill(const ValueType&, bool);
567
568 template<typename AccessorT>
569 void setValueOnlyAndCache(const Coord&, const ValueType&, AccessorT&) {assertNonmodifiable();}
570
571 template<typename ModifyOp, typename AccessorT>
572 void modifyValueAndActiveStateAndCache(const Coord&, const ModifyOp&, AccessorT&) {
573 assertNonmodifiable();
574 }
575
576 template<typename AccessorT>
577 void setValueOffAndCache(const Coord&, const ValueType&, AccessorT&) { assertNonmodifiable(); }
578
579 template<typename AccessorT>
580 void setActiveStateAndCache(const Coord& xyz, bool on, AccessorT& parent) {
581 BaseLeaf::setActiveStateAndCache(xyz, on, parent);
582 }
583
584 void resetBackground(const ValueType&, const ValueType& newBackground) {
585 assertNonModifiableUnlessZero(newBackground);
586 }
587
588 void signedFloodFill(const ValueType&) { assertNonmodifiable(); }
589 void signedFloodFill(const ValueType&, const ValueType&) { assertNonmodifiable(); }
590
591 void negate() { assertNonmodifiable(); }
592
593 friend class ::TestPointDataLeaf;
594
595 using ValueOn = typename BaseLeaf::ValueOn;
596 using ValueOff = typename BaseLeaf::ValueOff;
597 using ValueAll = typename BaseLeaf::ValueAll;
598
599private:
600 AttributeSet::UniquePtr mAttributeSet;
601 uint16_t mVoxelBufferSize = 0;
602
603protected:
604 using ChildOn = typename BaseLeaf::ChildOn;
605 using ChildOff = typename BaseLeaf::ChildOff;
606 using ChildAll = typename BaseLeaf::ChildAll;
607
608 using MaskOnIterator = typename NodeMaskType::OnIterator;
609 using MaskOffIterator = typename NodeMaskType::OffIterator;
610 using MaskDenseIterator = typename NodeMaskType::DenseIterator;
611
612 // During topology-only construction, access is needed
613 // to protected/private members of other template instances.
614 template<typename, Index> friend class PointDataLeafNode;
615
616 friend class tree::IteratorBase<MaskOnIterator, PointDataLeafNode>;
617 friend class tree::IteratorBase<MaskOffIterator, PointDataLeafNode>;
618 friend class tree::IteratorBase<MaskDenseIterator, PointDataLeafNode>;
619
620public:
621 /// @brief Leaf value voxel iterator
622 ValueVoxelCIter beginValueVoxel(const Coord& ijk) const;
623
624public:
625
626 using ValueOnIter = typename BaseLeaf::template ValueIter<
627 MaskOnIterator, PointDataLeafNode, const ValueType, ValueOn>;
628 using ValueOnCIter = typename BaseLeaf::template ValueIter<
629 MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn>;
630 using ValueOffIter = typename BaseLeaf::template ValueIter<
631 MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff>;
632 using ValueOffCIter = typename BaseLeaf::template ValueIter<
633 MaskOffIterator,const PointDataLeafNode,const ValueType,ValueOff>;
634 using ValueAllIter = typename BaseLeaf::template ValueIter<
635 MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll>;
636 using ValueAllCIter = typename BaseLeaf::template ValueIter<
637 MaskDenseIterator,const PointDataLeafNode,const ValueType,ValueAll>;
638 using ChildOnIter = typename BaseLeaf::template ChildIter<
639 MaskOnIterator, PointDataLeafNode, ChildOn>;
640 using ChildOnCIter = typename BaseLeaf::template ChildIter<
641 MaskOnIterator, const PointDataLeafNode, ChildOn>;
642 using ChildOffIter = typename BaseLeaf::template ChildIter<
643 MaskOffIterator, PointDataLeafNode, ChildOff>;
644 using ChildOffCIter = typename BaseLeaf::template ChildIter<
645 MaskOffIterator, const PointDataLeafNode, ChildOff>;
646 using ChildAllIter = typename BaseLeaf::template DenseIter<
647 PointDataLeafNode, ValueType, ChildAll>;
648 using ChildAllCIter = typename BaseLeaf::template DenseIter<
649 const PointDataLeafNode, const ValueType, ChildAll>;
650
651 using IndexVoxelIter = IndexIter<ValueVoxelCIter, NullFilter>;
652 using IndexAllIter = IndexIter<ValueAllCIter, NullFilter>;
653 using IndexOnIter = IndexIter<ValueOnCIter, NullFilter>;
654 using IndexOffIter = IndexIter<ValueOffCIter, NullFilter>;
655
656 /// @brief Leaf index iterator
657 IndexAllIter beginIndexAll() const
658 {
659 NullFilter filter;
660 return this->beginIndex<ValueAllCIter, NullFilter>(filter);
661 }
662 IndexOnIter beginIndexOn() const
663 {
664 NullFilter filter;
665 return this->beginIndex<ValueOnCIter, NullFilter>(filter);
666 }
667 IndexOffIter beginIndexOff() const
668 {
669 NullFilter filter;
670 return this->beginIndex<ValueOffCIter, NullFilter>(filter);
671 }
672
673 template<typename IterT, typename FilterT>
674 IndexIter<IterT, FilterT> beginIndex(const FilterT& filter) const;
675
676 /// @brief Filtered leaf index iterator
677 template<typename FilterT>
678 IndexIter<ValueAllCIter, FilterT> beginIndexAll(const FilterT& filter) const
679 {
680 return this->beginIndex<ValueAllCIter, FilterT>(filter);
681 }
682 template<typename FilterT>
683 IndexIter<ValueOnCIter, FilterT> beginIndexOn(const FilterT& filter) const
684 {
685 return this->beginIndex<ValueOnCIter, FilterT>(filter);
686 }
687 template<typename FilterT>
688 IndexIter<ValueOffCIter, FilterT> beginIndexOff(const FilterT& filter) const
689 {
690 return this->beginIndex<ValueOffCIter, FilterT>(filter);
691 }
692
693 /// @brief Leaf index iterator from voxel
694 IndexVoxelIter beginIndexVoxel(const Coord& ijk) const;
695
696 /// @brief Filtered leaf index iterator from voxel
697 template<typename FilterT>
698 IndexIter<ValueVoxelCIter, FilterT> beginIndexVoxel(const Coord& ijk, const FilterT& filter) const;
699
700#define VMASK_ this->getValueMask()
701 ValueOnCIter cbeginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
702 ValueOnCIter beginValueOn() const { return ValueOnCIter(VMASK_.beginOn(), this); }
703 ValueOnIter beginValueOn() { return ValueOnIter(VMASK_.beginOn(), this); }
704 ValueOffCIter cbeginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
705 ValueOffCIter beginValueOff() const { return ValueOffCIter(VMASK_.beginOff(), this); }
706 ValueOffIter beginValueOff() { return ValueOffIter(VMASK_.beginOff(), this); }
707 ValueAllCIter cbeginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
708 ValueAllCIter beginValueAll() const { return ValueAllCIter(VMASK_.beginDense(), this); }
709 ValueAllIter beginValueAll() { return ValueAllIter(VMASK_.beginDense(), this); }
710
711 ValueOnCIter cendValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
712 ValueOnCIter endValueOn() const { return ValueOnCIter(VMASK_.endOn(), this); }
713 ValueOnIter endValueOn() { return ValueOnIter(VMASK_.endOn(), this); }
714 ValueOffCIter cendValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
715 ValueOffCIter endValueOff() const { return ValueOffCIter(VMASK_.endOff(), this); }
716 ValueOffIter endValueOff() { return ValueOffIter(VMASK_.endOff(), this); }
717 ValueAllCIter cendValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
718 ValueAllCIter endValueAll() const { return ValueAllCIter(VMASK_.endDense(), this); }
719 ValueAllIter endValueAll() { return ValueAllIter(VMASK_.endDense(), this); }
720
721 ChildOnCIter cbeginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
722 ChildOnCIter beginChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
723 ChildOnIter beginChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
724 ChildOffCIter cbeginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
725 ChildOffCIter beginChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
726 ChildOffIter beginChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
727 ChildAllCIter cbeginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
728 ChildAllCIter beginChildAll() const { return ChildAllCIter(VMASK_.beginDense(), this); }
729 ChildAllIter beginChildAll() { return ChildAllIter(VMASK_.beginDense(), this); }
730
731 ChildOnCIter cendChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
732 ChildOnCIter endChildOn() const { return ChildOnCIter(VMASK_.endOn(), this); }
733 ChildOnIter endChildOn() { return ChildOnIter(VMASK_.endOn(), this); }
734 ChildOffCIter cendChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
735 ChildOffCIter endChildOff() const { return ChildOffCIter(VMASK_.endOff(), this); }
736 ChildOffIter endChildOff() { return ChildOffIter(VMASK_.endOff(), this); }
737 ChildAllCIter cendChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
738 ChildAllCIter endChildAll() const { return ChildAllCIter(VMASK_.endDense(), this); }
739 ChildAllIter endChildAll() { return ChildAllIter(VMASK_.endDense(), this); }
740#undef VMASK_
741}; // struct PointDataLeafNode
742
743////////////////////////////////////////
744
745// PointDataLeafNode implementation
746
747template<typename T, Index Log2Dim>
748inline AttributeSet::UniquePtr
749 PointDataLeafNode<T, Log2Dim>::stealAttributeSet()
750{
751 AttributeSet::UniquePtr ptr = std::make_unique<AttributeSet>();
752 std::swap(ptr, mAttributeSet);
753 return ptr;
754}
755
756template<typename T, Index Log2Dim>
757inline void
758 PointDataLeafNode<T, Log2Dim>::initializeAttributes(const Descriptor::Ptr& descriptor, const Index arrayLength,
759 const AttributeArray::ScopedRegistryLock* lock)
760{
761 if (descriptor->size() != 1 ||
762 descriptor->find("P") == AttributeSet::INVALID_POS ||
763 descriptor->valueType(0) != typeNameAsString<Vec3f>())
764 {
765 OPENVDB_THROW(IndexError, "Initializing attributes only allowed with one Vec3f position attribute.");
766 }
767
768 mAttributeSet.reset(new AttributeSet(descriptor, arrayLength, lock));
769}
770
771template<typename T, Index Log2Dim>
772inline void
773 PointDataLeafNode<T, Log2Dim>::clearAttributes(const bool updateValueMask,
774 const AttributeArray::ScopedRegistryLock* lock)
775{
776 mAttributeSet.reset(new AttributeSet(*mAttributeSet, 0, lock));
777
778 // zero voxel values
779
780 this->buffer().fill(ValueType(0));
781
782 // if updateValueMask, also de-activate all voxels
783
784 if (updateValueMask) this->setValuesOff();
785}
786
787template<typename T, Index Log2Dim>
788inline bool
789 PointDataLeafNode<T, Log2Dim>::hasAttribute(const size_t pos) const
790{
791 return pos < mAttributeSet->size();
792}
793
794template<typename T, Index Log2Dim>
795inline bool
796 PointDataLeafNode<T, Log2Dim>::hasAttribute(const Name& attributeName) const
797{
798 const size_t pos = mAttributeSet->find(attributeName);
799 return pos != AttributeSet::INVALID_POS;
800}
801
802template<typename T, Index Log2Dim>
803inline AttributeArray::Ptr
804 PointDataLeafNode<T, Log2Dim>::appendAttribute( const Descriptor& expected, Descriptor::Ptr& replacement,
805 const size_t pos, const Index strideOrTotalSize,
806 const bool constantStride,
807 const Metadata* metadata,
808 const AttributeArray::ScopedRegistryLock* lock)
809{
810 return mAttributeSet->appendAttribute(
811 expected, replacement, pos, strideOrTotalSize, constantStride, metadata, lock);
812}
813
814template<typename T, Index Log2Dim>
815inline void
816 PointDataLeafNode<T, Log2Dim>::dropAttributes(const std::vector<size_t>& pos,
817 const Descriptor& expected, Descriptor::Ptr& replacement)
818{
819 mAttributeSet->dropAttributes(pos, expected, replacement);
820}
821
822template<typename T, Index Log2Dim>
823inline void
824 PointDataLeafNode<T, Log2Dim>::reorderAttributes(const Descriptor::Ptr& replacement)
825{
826 mAttributeSet->reorderAttributes(replacement);
827}
828
829template<typename T, Index Log2Dim>
830inline void
831 PointDataLeafNode<T, Log2Dim>::renameAttributes(const Descriptor& expected, Descriptor::Ptr& replacement)
832{
833 mAttributeSet->renameAttributes(expected, replacement);
834}
835
836template<typename T, Index Log2Dim>
837inline void
838 PointDataLeafNode<T, Log2Dim>::compactAttributes()
839{
840 for (size_t i = 0; i < mAttributeSet->size(); i++) {
841 AttributeArray* array = mAttributeSet->get(i);
842 array->compact();
843 }
844}
845
846template<typename T, Index Log2Dim>
847inline void
848 PointDataLeafNode<T, Log2Dim>::replaceAttributeSet(AttributeSet* attributeSet, bool allowMismatchingDescriptors)
849{
850 if (!attributeSet) {
851 OPENVDB_THROW(ValueError, "Cannot replace with a null attribute set");
852 }
853
854 if (!allowMismatchingDescriptors && mAttributeSet->descriptor() != attributeSet->descriptor()) {
855 OPENVDB_THROW(ValueError, "Attribute set descriptors are not equal.");
856 }
857
858 mAttributeSet.reset(attributeSet);
859}
860
861template<typename T, Index Log2Dim>
862inline void
863 PointDataLeafNode<T, Log2Dim>::resetDescriptor(const Descriptor::Ptr& replacement)
864{
865 mAttributeSet->resetDescriptor(replacement);
866}
867
868template<typename T, Index Log2Dim>
869inline void
870 PointDataLeafNode<T, Log2Dim>::setOffsets(const std::vector<ValueType>& offsets, const bool updateValueMask)
871{
872 if (offsets.size() != LeafNodeType::NUM_VALUES) {
873 OPENVDB_THROW(ValueError, "Offset vector size doesn't match number of voxels.")
874 }
875
876 for (Index index = 0; index < offsets.size(); ++index) {
877 setOffsetOnly(index, offsets[index]);
878 }
879
880 if (updateValueMask) this->updateValueMask();
881}
882
883template<typename T, Index Log2Dim>
884inline void
885 PointDataLeafNode<T, Log2Dim>::validateOffsets() const
886{
887 // Ensure all of the offset values are monotonically increasing
888 for (Index index = 1; index < BaseLeaf::SIZE; ++index) {
889 if (this->getValue(index-1) > this->getValue(index)) {
890 OPENVDB_THROW(ValueError, "Voxel offset values are not monotonically increasing");
891 }
892 }
893
894 // Ensure all attribute arrays are of equal length
895 for (size_t attributeIndex = 1; attributeIndex < mAttributeSet->size(); ++attributeIndex ) {
896 if (mAttributeSet->getConst(attributeIndex-1)->size() != mAttributeSet->getConst(attributeIndex)->size()) {
897 OPENVDB_THROW(ValueError, "Attribute arrays have inconsistent length");
898 }
899 }
900
901 // Ensure the last voxel's offset value matches the size of each attribute array
902 if (mAttributeSet->size() > 0 && this->getValue(BaseLeaf::SIZE-1) != mAttributeSet->getConst(0)->size()) {
903 OPENVDB_THROW(ValueError, "Last voxel offset value does not match attribute array length");
904 }
905}
906
907template<typename T, Index Log2Dim>
908inline AttributeArray&
909 PointDataLeafNode<T, Log2Dim>::attributeArray(const size_t pos)
910{
911 if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
912 return *mAttributeSet->get(pos);
913}
914
915template<typename T, Index Log2Dim>
916inline const AttributeArray&
917 PointDataLeafNode<T, Log2Dim>::attributeArray(const size_t pos) const
918{
919 if (pos >= mAttributeSet->size()) OPENVDB_THROW(LookupError, "Attribute Out Of Range - " << pos);
920 return *mAttributeSet->getConst(pos);
921}
922
923template<typename T, Index Log2Dim>
924inline const AttributeArray&
925 PointDataLeafNode<T, Log2Dim>::constAttributeArray(const size_t pos) const
926{
927 return this->attributeArray(pos);
928}
929
930template<typename T, Index Log2Dim>
931inline AttributeArray&
932 PointDataLeafNode<T, Log2Dim>::attributeArray(const Name& attributeName)
933{
934 const size_t pos = mAttributeSet->find(attributeName);
935 if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
936 return *mAttributeSet->get(pos);
937}
938
939template<typename T, Index Log2Dim>
940inline const AttributeArray&
941 PointDataLeafNode<T, Log2Dim>::attributeArray(const Name& attributeName) const
942{
943 const size_t pos = mAttributeSet->find(attributeName);
944 if (pos == AttributeSet::INVALID_POS) OPENVDB_THROW(LookupError, "Attribute Not Found - " << attributeName);
945 return *mAttributeSet->getConst(pos);
946}
947
948template<typename T, Index Log2Dim>
949inline const AttributeArray&
950 PointDataLeafNode<T, Log2Dim>::constAttributeArray(const Name& attributeName) const
951{
952 return this->attributeArray(attributeName);
953}
954
955template<typename T, Index Log2Dim>
956inline GroupHandle
957 PointDataLeafNode<T, Log2Dim>::groupHandle(const AttributeSet::Descriptor::GroupIndex& index) const
958{
959 const AttributeArray& array = this->attributeArray(index.first);
960 assert(isGroup(array));
961
962 const GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
963
964 return GroupHandle(groupArray, index.second);
965}
966
967template<typename T, Index Log2Dim>
968inline GroupHandle
969 PointDataLeafNode<T, Log2Dim>::groupHandle(const Name& name) const
970{
971 const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
972 return this->groupHandle(index);
973}
974
975template<typename T, Index Log2Dim>
976inline GroupWriteHandle
977 PointDataLeafNode<T, Log2Dim>::groupWriteHandle(const AttributeSet::Descriptor::GroupIndex& index)
978{
979 AttributeArray& array = this->attributeArray(index.first);
980 assert(isGroup(array));
981
982 GroupAttributeArray& groupArray = GroupAttributeArray::cast(array);
983
984 return GroupWriteHandle(groupArray, index.second);
985}
986
987template<typename T, Index Log2Dim>
988inline GroupWriteHandle
989 PointDataLeafNode<T, Log2Dim>::groupWriteHandle(const Name& name)
990{
991 const AttributeSet::Descriptor::GroupIndex index = this->attributeSet().groupIndex(name);
992 return this->groupWriteHandle(index);
993}
994
995template<typename T, Index Log2Dim>
996template<typename ValueIterT, typename FilterT>
997inline IndexIter<ValueIterT, FilterT>
998 PointDataLeafNode<T, Log2Dim>::beginIndex(const FilterT& filter) const
999{
1000 // generate no-op iterator if filter evaluates no indices
1001
1002 if (filter.state() == index::NONE) {
1003 return IndexIter<ValueIterT, FilterT>(ValueIterT(), filter);
1004 }
1005
1006 // copy filter to ensure thread-safety
1007
1008 FilterT newFilter(filter);
1009 newFilter.reset(*this);
1010
1011 using IterTraitsT = tree::IterTraits<LeafNodeType, ValueIterT>;
1012
1013 // construct the value iterator and reset the filter to use this leaf
1014
1015 ValueIterT valueIter = IterTraitsT::begin(*this);
1016
1017 return IndexIter<ValueIterT, FilterT>(valueIter, newFilter);
1018}
1019
1020template<typename T, Index Log2Dim>
1021inline ValueVoxelCIter
1022 PointDataLeafNode<T, Log2Dim>::beginValueVoxel(const Coord& ijk) const
1023{
1024 const Index index = LeafNodeType::coordToOffset(ijk);
1025 assert(index < BaseLeaf::SIZE);
1026 const ValueType end = this->getValue(index);
1027 const ValueType start = (index == 0) ? ValueType(0) : this->getValue(index - 1);
1028 return ValueVoxelCIter(start, end);
1029}
1030
1031template<typename T, Index Log2Dim>
1032inline typename PointDataLeafNode<T, Log2Dim>::IndexVoxelIter
1033 PointDataLeafNode<T, Log2Dim>::beginIndexVoxel(const Coord& ijk) const
1034{
1035 ValueVoxelCIter iter = this->beginValueVoxel(ijk);
1036 return IndexVoxelIter(iter, NullFilter());
1037}
1038
1039template<typename T, Index Log2Dim>
1040template<typename FilterT>
1041inline IndexIter<ValueVoxelCIter, FilterT>
1042 PointDataLeafNode<T, Log2Dim>::beginIndexVoxel(const Coord& ijk, const FilterT& filter) const
1043{
1044 ValueVoxelCIter iter = this->beginValueVoxel(ijk);
1045 FilterT newFilter(filter);
1046 newFilter.reset(*this);
1047 return IndexIter<ValueVoxelCIter, FilterT>(iter, newFilter);
1048}
1049
1050template<typename T, Index Log2Dim>
1051inline Index64
1052 PointDataLeafNode<T, Log2Dim>::pointCount() const
1053{
1054 return this->getLastValue();
1055}
1056
1057template<typename T, Index Log2Dim>
1058inline Index64
1059 PointDataLeafNode<T, Log2Dim>::onPointCount() const
1060{
1061 if (this->isEmpty()) return 0;
1062 else if (this->isDense()) return this->pointCount();
1063 return iterCount(this->beginIndexOn());
1064}
1065
1066template<typename T, Index Log2Dim>
1067inline Index64
1068 PointDataLeafNode<T, Log2Dim>::offPointCount() const
1069{
1070 if (this->isEmpty()) return this->pointCount();
1071 else if (this->isDense()) return 0;
1072 return iterCount(this->beginIndexOff());
1073}
1074
1075template<typename T, Index Log2Dim>
1076inline Index64
1077 PointDataLeafNode<T, Log2Dim>::groupPointCount(const Name& groupName) const
1078{
1079 if (!this->attributeSet().descriptor().hasGroup(groupName)) {
1080 return Index64(0);
1081 }
1082 GroupFilter filter(groupName, this->attributeSet());
1083 if (filter.state() == index::ALL) {
1084 return this->pointCount();
1085 } else {
1086 return iterCount(this->beginIndexAll(filter));
1087 }
1088}
1089
1090template<typename T, Index Log2Dim>
1091inline void
1092 PointDataLeafNode<T, Log2Dim>::updateValueMask()
1093{
1094 ValueType start = 0, end = 0;
1095 for (Index n = 0; n < LeafNodeType::NUM_VALUES; n++) {
1096 end = this->getValue(n);
1097 this->setValueMask(n, (end - start) > 0);
1098 start = end;
1099 }
1100}
1101
1102template<typename T, Index Log2Dim>
1103inline void
1104 PointDataLeafNode<T, Log2Dim>::setOffsetOn(Index offset, const ValueType& val)
1105{
1106 this->buffer().setValue(offset, val);
1107 this->setValueMaskOn(offset);
1108}
1109
1110template<typename T, Index Log2Dim>
1111inline void
1112 PointDataLeafNode<T, Log2Dim>::setOffsetOnly(Index offset, const ValueType& val)
1113{
1114 this->buffer().setValue(offset, val);
1115}
1116
1117template<typename T, Index Log2Dim>
1118inline void
1119 PointDataLeafNode<T, Log2Dim>::readTopology(std::istream& is, bool fromHalf)
1120{
1121 BaseLeaf::readTopology(is, fromHalf);
1122}
1123
1124template<typename T, Index Log2Dim>
1125inline void
1126 PointDataLeafNode<T, Log2Dim>::writeTopology(std::ostream& os, bool toHalf) const
1127{
1128 BaseLeaf::writeTopology(os, toHalf);
1129}
1130
1131template<typename T, Index Log2Dim>
1132inline Index
1133 PointDataLeafNode<T, Log2Dim>::buffers() const
1134{
1135 return Index( /*voxel buffer sizes*/ 1 +
1136 /*voxel buffers*/ 1 +
1137 /*attribute metadata*/ 1 +
1138 /*attribute uniform values*/ mAttributeSet->size() +
1139 /*attribute buffers*/ mAttributeSet->size() +
1140 /*cleanup*/ 1);
1141}
1142
1143template<typename T, Index Log2Dim>
1144inline void
1145 PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, bool fromHalf)
1146{
1147 this->readBuffers(is, CoordBBox::inf(), fromHalf);
1148}
1149
1150template<typename T, Index Log2Dim>
1151inline void
1152 PointDataLeafNode<T, Log2Dim>::readBuffers(std::istream& is, const CoordBBox& /*bbox*/, bool fromHalf)
1153{
1154 struct Local
1155 {
1156 static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1157 {
1158 // if paged stream exists, delete it
1159 std::string key("paged:" + std::to_string(index));
1160 auto it = auxData.find(key);
1161 if (it != auxData.end()) {
1162 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1163 }
1164 }
1165
1166 static compression::PagedInputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1167 const Index index)
1168 {
1169 std::string key("paged:" + std::to_string(index));
1170 auto it = auxData.find(key);
1171 if (it != auxData.end()) {
1172 return *(boost::any_cast<compression::PagedInputStream::Ptr>(it->second));
1173 }
1174 else {
1175 compression::PagedInputStream::Ptr pagedStream = std::make_shared<compression::PagedInputStream>();
1176 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1177 return *pagedStream;
1178 }
1179 }
1180
1181 static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1182 {
1183 std::string matchingKey("hasMatchingDescriptor");
1184 auto itMatching = auxData.find(matchingKey);
1185 return itMatching != auxData.end();
1186 }
1187
1188 static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1189 {
1190 std::string matchingKey("hasMatchingDescriptor");
1191 std::string descriptorKey("descriptorPtr");
1192 auto itMatching = auxData.find(matchingKey);
1193 auto itDescriptor = auxData.find(descriptorKey);
1194 if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1195 if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1196 }
1197
1198 static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1199 const Descriptor::Ptr descriptor)
1200 {
1201 std::string descriptorKey("descriptorPtr");
1202 std::string matchingKey("hasMatchingDescriptor");
1203 auto itMatching = auxData.find(matchingKey);
1204 if (itMatching == auxData.end()) {
1205 // if matching bool is not found, insert "true" and the descriptor
1206 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1207 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1208 }
1209 }
1210
1211 static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1212 {
1213 std::string descriptorKey("descriptorPtr");
1214 auto itDescriptor = auxData.find(descriptorKey);
1215 assert(itDescriptor != auxData.end());
1216 const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1217 return descriptor;
1218 }
1219 };
1220
1221 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(is);
1222
1223 if (!meta) {
1224 OPENVDB_THROW(IoError, "Cannot read in a PointDataLeaf without StreamMetadata.");
1225 }
1226
1227 const Index pass(static_cast<uint16_t>(meta->pass()));
1228 const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1229
1230 const Index attributes = (maximumPass - 4) / 2;
1231
1232 if (pass == 0) {
1233 // pass 0 - voxel data sizes
1234 is.read(reinterpret_cast<char*>(&mVoxelBufferSize), sizeof(uint16_t));
1235 Local::clearMatchingDescriptor(meta->auxData());
1236 }
1237 else if (pass == 1) {
1238 // pass 1 - descriptor and attribute metadata
1239 if (Local::hasMatchingDescriptor(meta->auxData())) {
1240 AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1241 mAttributeSet->resetDescriptor(descriptor, /*allowMismatchingDescriptors=*/true);
1242 }
1243 else {
1244 uint8_t header;
1245 is.read(reinterpret_cast<char*>(&header), sizeof(uint8_t));
1246 mAttributeSet->readDescriptor(is);
1247 if (header & uint8_t(1)) {
1248 AttributeSet::DescriptorPtr descriptor = mAttributeSet->descriptorPtr();
1249 Local::insertDescriptor(meta->auxData(), descriptor);
1250 }
1251 // a forwards-compatibility mechanism for future use,
1252 // if a 0x2 bit is set, read and skip over a specific number of bytes
1253 if (header & uint8_t(2)) {
1254 uint64_t bytesToSkip;
1255 is.read(reinterpret_cast<char*>(&bytesToSkip), sizeof(uint64_t));
1256 if (bytesToSkip > uint64_t(0)) {
1257 auto metadata = io::getStreamMetadataPtr(is);
1258 if (metadata && metadata->seekable()) {
1259 is.seekg(bytesToSkip, std::ios_base::cur);
1260 }
1261 else {
1262 std::vector<uint8_t> tempData(bytesToSkip);
1263 is.read(reinterpret_cast<char*>(&tempData[0]), bytesToSkip);
1264 }
1265 }
1266 }
1267 // this reader is only able to read headers with 0x1 and 0x2 bits set
1268 if (header > uint8_t(3)) {
1269 OPENVDB_THROW(IoError, "Unrecognised header flags in PointDataLeafNode");
1270 }
1271 }
1272 mAttributeSet->readMetadata(is);
1273 }
1274 else if (pass < (attributes + 2)) {
1275 // pass 2...n+2 - attribute uniform values
1276 const size_t attributeIndex = pass - 2;
1277 AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1278 mAttributeSet->get(attributeIndex) : nullptr;
1279 if (array) {
1280 compression::PagedInputStream& pagedStream =
1281 Local::getOrInsertPagedStream(meta->auxData(), static_cast<Index>(attributeIndex));
1282 pagedStream.setInputStream(is);
1283 pagedStream.setSizeOnly(true);
1284 array->readPagedBuffers(pagedStream);
1285 }
1286 }
1287 else if (pass == attributes + 2) {
1288 // pass n+2 - voxel data
1289
1290 const Index passValue(meta->pass());
1291
1292 // StreamMetadata pass variable used to temporarily store voxel buffer size
1293 io::StreamMetadata& nonConstMeta = const_cast<io::StreamMetadata&>(*meta);
1294 nonConstMeta.setPass(mVoxelBufferSize);
1295
1296 // readBuffers() calls readCompressedValues specialization above
1297 BaseLeaf::readBuffers(is, fromHalf);
1298
1299 // pass now reset to original value
1300 nonConstMeta.setPass(passValue);
1301 }
1302 else if (pass < (attributes*2 + 3)) {
1303 // pass n+2..2n+2 - attribute buffers
1304 const Index attributeIndex = pass - attributes - 3;
1305 AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1306 mAttributeSet->get(attributeIndex) : nullptr;
1307 if (array) {
1308 compression::PagedInputStream& pagedStream =
1309 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1310 pagedStream.setInputStream(is);
1311 pagedStream.setSizeOnly(false);
1312 array->readPagedBuffers(pagedStream);
1313 }
1314 // cleanup paged stream reference in auxiliary metadata
1315 if (pass > attributes + 3) {
1316 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1317 }
1318 }
1319 else if (pass < buffers()) {
1320 // pass 2n+3 - cleanup last paged stream
1321 const Index attributeIndex = pass - attributes - 4;
1322 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1323 }
1324}
1325
1326template<typename T, Index Log2Dim>
1327inline void
1328 PointDataLeafNode<T, Log2Dim>::writeBuffers(std::ostream& os, bool toHalf) const
1329{
1330 struct Local
1331 {
1332 static void destroyPagedStream(const io::StreamMetadata::AuxDataMap& auxData, const Index index)
1333 {
1334 // if paged stream exists, flush and delete it
1335 std::string key("paged:" + std::to_string(index));
1336 auto it = auxData.find(key);
1337 if (it != auxData.end()) {
1338 compression::PagedOutputStream& stream = *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1339 stream.flush();
1340 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(it);
1341 }
1342 }
1343
1344 static compression::PagedOutputStream& getOrInsertPagedStream( const io::StreamMetadata::AuxDataMap& auxData,
1345 const Index index)
1346 {
1347 std::string key("paged:" + std::to_string(index));
1348 auto it = auxData.find(key);
1349 if (it != auxData.end()) {
1350 return *(boost::any_cast<compression::PagedOutputStream::Ptr>(it->second));
1351 }
1352 else {
1353 compression::PagedOutputStream::Ptr pagedStream = std::make_shared<compression::PagedOutputStream>();
1354 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[key] = pagedStream;
1355 return *pagedStream;
1356 }
1357 }
1358
1359 static void insertDescriptor( const io::StreamMetadata::AuxDataMap& auxData,
1360 const Descriptor::Ptr descriptor)
1361 {
1362 std::string descriptorKey("descriptorPtr");
1363 std::string matchingKey("hasMatchingDescriptor");
1364 auto itMatching = auxData.find(matchingKey);
1365 auto itDescriptor = auxData.find(descriptorKey);
1366 if (itMatching == auxData.end()) {
1367 // if matching bool is not found, insert "true" and the descriptor
1368 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = true;
1369 assert(itDescriptor == auxData.end());
1370 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[descriptorKey] = descriptor;
1371 }
1372 else {
1373 // if matching bool is found and is false, early exit (a previous descriptor did not match)
1374 bool matching = boost::any_cast<bool>(itMatching->second);
1375 if (!matching) return;
1376 assert(itDescriptor != auxData.end());
1377 // if matching bool is true, check whether the existing descriptor matches the current one and set
1378 // matching bool to false if not
1379 const Descriptor::Ptr existingDescriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1380 if (*existingDescriptor != *descriptor) {
1381 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData))[matchingKey] = false;
1382 }
1383 }
1384 }
1385
1386 static bool hasMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1387 {
1388 std::string matchingKey("hasMatchingDescriptor");
1389 auto itMatching = auxData.find(matchingKey);
1390 // if matching key is not found, no matching descriptor
1391 if (itMatching == auxData.end()) return false;
1392 // if matching key is found and is false, no matching descriptor
1393 if (!boost::any_cast<bool>(itMatching->second)) return false;
1394 return true;
1395 }
1396
1397 static AttributeSet::Descriptor::Ptr retrieveMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1398 {
1399 std::string descriptorKey("descriptorPtr");
1400 auto itDescriptor = auxData.find(descriptorKey);
1401 // if matching key is true, however descriptor is not found, it has already been retrieved
1402 if (itDescriptor == auxData.end()) return nullptr;
1403 // otherwise remove it and return it
1404 const Descriptor::Ptr descriptor = boost::any_cast<AttributeSet::Descriptor::Ptr>(itDescriptor->second);
1405 (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1406 return descriptor;
1407 }
1408
1409 static void clearMatchingDescriptor(const io::StreamMetadata::AuxDataMap& auxData)
1410 {
1411 std::string matchingKey("hasMatchingDescriptor");
1412 std::string descriptorKey("descriptorPtr");
1413 auto itMatching = auxData.find(matchingKey);
1414 auto itDescriptor = auxData.find(descriptorKey);
1415 if (itMatching != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itMatching);
1416 if (itDescriptor != auxData.end()) (const_cast<io::StreamMetadata::AuxDataMap&>(auxData)).erase(itDescriptor);
1417 }
1418 };
1419
1420 const io::StreamMetadata::Ptr meta = io::getStreamMetadataPtr(os);
1421
1422 if (!meta) {
1423 OPENVDB_THROW(IoError, "Cannot write out a PointDataLeaf without StreamMetadata.");
1424 }
1425
1426 const Index pass(static_cast<uint16_t>(meta->pass()));
1427
1428 // leaf traversal analysis deduces the number of passes to perform for this leaf
1429 // then updates the leaf traversal value to ensure all passes will be written
1430
1431 if (meta->countingPasses()) {
1432 const Index requiredPasses = this->buffers();
1433 if (requiredPasses > pass) {
1434 meta->setPass(requiredPasses);
1435 }
1436 return;
1437 }
1438
1439 const Index maximumPass(static_cast<uint16_t>(meta->pass() >> 16));
1440 const Index attributes = (maximumPass - 4) / 2;
1441
1442 if (pass == 0) {
1443 // pass 0 - voxel data sizes
1444 io::writeCompressedValuesSize(os, this->buffer().data(), SIZE);
1445 // track if descriptor is shared or not
1446 Local::insertDescriptor(meta->auxData(), mAttributeSet->descriptorPtr());
1447 }
1448 else if (pass == 1) {
1449 // pass 1 - descriptor and attribute metadata
1450 bool matchingDescriptor = Local::hasMatchingDescriptor(meta->auxData());
1451 if (matchingDescriptor) {
1452 AttributeSet::Descriptor::Ptr descriptor = Local::retrieveMatchingDescriptor(meta->auxData());
1453 if (descriptor) {
1454 // write a header to indicate a shared descriptor
1455 uint8_t header(1);
1456 os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1457 mAttributeSet->writeDescriptor(os, /*transient=*/false);
1458 }
1459 }
1460 else {
1461 // write a header to indicate a non-shared descriptor
1462 uint8_t header(0);
1463 os.write(reinterpret_cast<const char*>(&header), sizeof(uint8_t));
1464 mAttributeSet->writeDescriptor(os, /*transient=*/false);
1465 }
1466 mAttributeSet->writeMetadata(os, /*transient=*/false, /*paged=*/true);
1467 }
1468 else if (pass < attributes + 2) {
1469 // pass 2...n+2 - attribute buffer sizes
1470 const Index attributeIndex = pass - 2;
1471 // destroy previous paged stream
1472 if (pass > 2) {
1473 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1474 }
1475 const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1476 mAttributeSet->getConst(attributeIndex) : nullptr;
1477 if (array) {
1478 compression::PagedOutputStream& pagedStream =
1479 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1480 pagedStream.setOutputStream(os);
1481 pagedStream.setSizeOnly(true);
1482 array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1483 }
1484 }
1485 else if (pass == attributes + 2) {
1486 const Index attributeIndex = pass - 3;
1487 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1488 // pass n+2 - voxel data
1489 BaseLeaf::writeBuffers(os, toHalf);
1490 }
1491 else if (pass < (attributes*2 + 3)) {
1492 // pass n+3...2n+3 - attribute buffers
1493 const Index attributeIndex = pass - attributes - 3;
1494 // destroy previous paged stream
1495 if (pass > attributes + 2) {
1496 Local::destroyPagedStream(meta->auxData(), attributeIndex-1);
1497 }
1498 const AttributeArray* array = attributeIndex < mAttributeSet->size() ?
1499 mAttributeSet->getConst(attributeIndex) : nullptr;
1500 if (array) {
1501 compression::PagedOutputStream& pagedStream =
1502 Local::getOrInsertPagedStream(meta->auxData(), attributeIndex);
1503 pagedStream.setOutputStream(os);
1504 pagedStream.setSizeOnly(false);
1505 array->writePagedBuffers(pagedStream, /*outputTransient*/false);
1506 }
1507 }
1508 else if (pass < buffers()) {
1509 Local::clearMatchingDescriptor(meta->auxData());
1510 // pass 2n+3 - cleanup last paged stream
1511 const Index attributeIndex = pass - attributes - 4;
1512 Local::destroyPagedStream(meta->auxData(), attributeIndex);
1513 }
1514}
1515
1516template<typename T, Index Log2Dim>
1517inline Index64
1518 PointDataLeafNode<T, Log2Dim>::memUsage() const
1519{
1520 return BaseLeaf::memUsage() + mAttributeSet->memUsage();
1521}
1522
1523template<typename T, Index Log2Dim>
1524inline void
1525 PointDataLeafNode<T, Log2Dim>::evalActiveBoundingBox(CoordBBox& bbox, bool visitVoxels) const
1526{
1527 BaseLeaf::evalActiveBoundingBox(bbox, visitVoxels);
1528}
1529
1530template<typename T, Index Log2Dim>
1531inline CoordBBox
1532 PointDataLeafNode<T, Log2Dim>::getNodeBoundingBox() const
1533{
1534 return BaseLeaf::getNodeBoundingBox();
1535}
1536
1537template<typename T, Index Log2Dim>
1538inline void
1539 PointDataLeafNode<T, Log2Dim>::fill(const CoordBBox& bbox, const ValueType& value, bool active)
1540{
1541 if (!this->allocate()) return;
1542
1543 this->assertNonModifiableUnlessZero(value);
1544
1545 // active state is permitted to be updated
1546
1547 for (Int32 x = bbox.min().x(); x <= bbox.max().x(); ++x) {
1548 const Index offsetX = (x & (DIM-1u)) << 2*Log2Dim;
1549 for (Int32 y = bbox.min().y(); y <= bbox.max().y(); ++y) {
1550 const Index offsetXY = offsetX + ((y & (DIM-1u)) << Log2Dim);
1551 for (Int32 z = bbox.min().z(); z <= bbox.max().z(); ++z) {
1552 const Index offset = offsetXY + (z & (DIM-1u));
1553 this->setValueMask(offset, active);
1554 }
1555 }
1556 }
1557}
1558
1559template<typename T, Index Log2Dim>
1560inline void
1561 PointDataLeafNode<T, Log2Dim>::fill(const ValueType& value, bool active)
1562{
1563 this->assertNonModifiableUnlessZero(value);
1564
1565 // active state is permitted to be updated
1566
1567 if (active) this->setValuesOn();
1568 else this->setValuesOff();
1569}
1570
1571
1572////////////////////////////////////////
1573
1574
1575template <typename PointDataTreeT>
1576inline AttributeSet::Descriptor::Ptr
1577makeDescriptorUnique(PointDataTreeT& tree)
1578{
1579 auto leafIter = tree.beginLeaf();
1580 if (!leafIter) return nullptr;
1581
1582 const AttributeSet::Descriptor& descriptor = leafIter->attributeSet().descriptor();
1583 auto newDescriptor = std::make_shared<AttributeSet::Descriptor>(descriptor);
1584 for (; leafIter; ++leafIter) {
1585 leafIter->resetDescriptor(newDescriptor);
1586 }
1587
1588 return newDescriptor;
1589}
1590
1591
1592template <typename PointDataTreeT>
1593inline void
1594setStreamingMode(PointDataTreeT& tree, bool on)
1595{
1596 auto leafIter = tree.beginLeaf();
1597 for (; leafIter; ++leafIter) {
1598 for (size_t i = 0; i < leafIter->attributeSet().size(); i++) {
1599 leafIter->attributeArray(i).setStreaming(on);
1600 }
1601 }
1602}
1603
1604
1605template <typename PointDataTreeT>
1606inline void
1607prefetch(PointDataTreeT& tree, bool position, bool otherAttributes)
1608{
1609 // NOTE: the following is intentionally not multi-threaded, as the I/O
1610 // is faster if done in the order in which it is stored in the file
1611
1612 auto leaf = tree.cbeginLeaf();
1613 if (!leaf) return;
1614
1615 const auto& attributeSet = leaf->attributeSet();
1616
1617 // pre-fetch leaf data
1618
1619 for ( ; leaf; ++leaf) {
1620 leaf->buffer().data();
1621 }
1622
1623 // pre-fetch position attribute data (position will typically have index 0)
1624
1625 size_t positionIndex = attributeSet.find("P");
1626
1627 if (position && positionIndex != AttributeSet::INVALID_POS) {
1628 for (leaf = tree.cbeginLeaf(); leaf; ++leaf) {
1629 assert(leaf->hasAttribute(positionIndex));
1630 leaf->constAttributeArray(positionIndex).loadData();
1631 }
1632 }
1633
1634 // pre-fetch other attribute data
1635
1636 if (otherAttributes) {
1637 const size_t attributes = attributeSet.size();
1638 for (size_t attributeIndex = 0; attributeIndex < attributes; attributeIndex++) {
1639 if (attributeIndex == positionIndex) continue;
1640 for (leaf = tree.cbeginLeaf(); leaf; ++leaf) {
1641 assert(leaf->hasAttribute(attributeIndex));
1642 leaf->constAttributeArray(attributeIndex).loadData();
1643 }
1644 }
1645 }
1646}
1647
1648
1649namespace internal {
1650
1651/// @brief Global registration of point data-related types
1652/// @note This is called from @c openvdb::initialize, so there is
1653/// no need to call it directly.
1654 void initialize();
1655
1656/// @brief Global deregistration of point data-related types
1657/// @note This is called from @c openvdb::uninitialize, so there is
1658/// no need to call it directly.
1659 void uninitialize();
1660
1661
1662/// @brief Recursive node chain which generates a openvdb::TypeList value
1663/// converted types of nodes to PointDataGrid nodes of the same configuration,
1664/// rooted at RootNodeType in reverse order, from LeafNode to RootNode.
1665/// See also TreeConverter<>.
1666template<typename HeadT, int HeadLevel>
1667 struct PointDataNodeChain
1668{
1669 using SubtreeT = typename PointDataNodeChain<typename HeadT::ChildNodeType, HeadLevel-1>::Type;
1670 using RootNodeT = tree::RootNode<typename SubtreeT::Back>;
1671 using Type = typename SubtreeT::template Append<RootNodeT>;
1672};
1673
1674// Specialization for internal nodes which require their embedded child type to
1675// be switched
1676template <typename ChildT, Index Log2Dim, int HeadLevel>
1677 struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, HeadLevel>
1678{
1679 using SubtreeT = typename PointDataNodeChain<ChildT, HeadLevel-1>::Type;
1680 using InternalNodeT = tree::InternalNode<typename SubtreeT::Back, Log2Dim>;
1681 using Type = typename SubtreeT::template Append<InternalNodeT>;
1682};
1683
1684// Specialization for the last internal node of a node chain, expected
1685// to be templated on a leaf node
1686template <typename ChildT, Index Log2Dim>
1687 struct PointDataNodeChain<tree::InternalNode<ChildT, Log2Dim>, /*HeadLevel=*/1>
1688{
1689 using LeafNodeT = PointDataLeafNode<PointDataIndex32, ChildT::LOG2DIM>;
1690 using InternalNodeT = tree::InternalNode<LeafNodeT, Log2Dim>;
1691 using Type = TypeList<LeafNodeT, InternalNodeT>;
1692};
1693
1694} // namespace internal
1695
1696
1697/// @brief Similiar to ValueConverter, but allows for tree configuration conversion
1698/// to a PointDataTree. ValueConverter<PointDataIndex32> cannot be used as a
1699/// PointDataLeafNode is not a specialization of LeafNode
1700template <typename TreeType>
1701 struct TreeConverter {
1702 using RootNodeT = typename TreeType::RootNodeType;
1703 using NodeChainT = typename internal::PointDataNodeChain<RootNodeT, RootNodeT::LEVEL>::Type;
1704 using Type = tree::Tree<typename NodeChainT::Back>;
1705};
1706
1707
1708} // namespace points
1709
1710
1711////////////////////////////////////////
1712
1713
1714namespace tree
1715{
1716
1717/// Helper metafunction used to implement LeafNode::SameConfiguration
1718/// (which, as an inner class, can't be independently specialized)
1719template<Index Dim1, typename T2>
1720 struct SameLeafConfig<Dim1, points::PointDataLeafNode<T2, Dim1>> { static const bool value = true; };
1721
1722} // namespace tree
1723} // namespace OPENVDB_VERSION_NAME
1724} // namespace openvdb
1725
1726#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:700
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_0::Grid
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:577
openvdb::v9_0::IndexError
Definition: Exceptions.h:57
openvdb::v9_0::IoError
Definition: Exceptions.h:58
openvdb::v9_0::LookupError
Definition: Exceptions.h:60
openvdb::v9_0::Metadata
Base class for storing metadata information in a grid.
Definition: Metadata.h:24
openvdb::v9_0::PartialCreate
Tag dispatch class that distinguishes constructors during file input.
Definition: Types.h:570
openvdb::v9_0::TopologyCopy
Tag dispatch class that distinguishes topology copy constructors from deep copy constructors.
Definition: Types.h:564
openvdb::v9_0::ValueError
Definition: Exceptions.h:65
openvdb::v9_0::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_0::compression::PagedInputStream::setSizeOnly
void setSizeOnly(bool sizeOnly)
Size-only mode tags the stream as only reading size data.
Definition: StreamCompression.h:214
openvdb::v9_0::compression::PagedInputStream::setInputStream
void setInputStream(std::istream &is)
Definition: StreamCompression.h:219
openvdb::v9_0::compression::PagedInputStream::Ptr
std::shared_ptr< PagedInputStream > Ptr
Definition: StreamCompression.h:207
openvdb::v9_0::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_0::compression::PagedOutputStream::setSizeOnly
void setSizeOnly(bool sizeOnly)
Size-only mode tags the stream as only writing size data.
Definition: StreamCompression.h:251
openvdb::v9_0::compression::PagedOutputStream::setOutputStream
void setOutputStream(std::ostream &os)
Definition: StreamCompression.h:256
openvdb::v9_0::compression::PagedOutputStream::Ptr
std::shared_ptr< PagedOutputStream > Ptr
Definition: StreamCompression.h:244
openvdb::v9_0::compression::PagedOutputStream::flush
void flush()
Manually flushes the current page to disk if non-zero.
openvdb::v9_0::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_0::io::StreamMetadata::Ptr
SharedPtr< StreamMetadata > Ptr
Definition: io.h:33
openvdb::v9_0::io::StreamMetadata::AuxDataMap
std::map< std::string, boost::any > AuxDataMap
Definition: io.h:92
openvdb::v9_0::io::StreamMetadata::setPass
void setPass(uint32_t)
openvdb::v9_0::math::CoordBBox
Axis-aligned bounding box of signed integer coordinates.
Definition: Coord.h:248
openvdb::v9_0::math::CoordBBox::min
const Coord & min() const
Definition: Coord.h:320
openvdb::v9_0::math::CoordBBox::max
const Coord & max() const
Definition: Coord.h:321
openvdb::v9_0::math::CoordBBox::inf
static CoordBBox inf()
Return an "infinite" bounding box, as defined by the Coord value range.
Definition: Coord.h:318
openvdb::v9_0::math::Coord
Signed (x, y, z) 32-bit integer coordinates.
Definition: Coord.h:25
openvdb::v9_0::math::Coord::y
Int32 y() const
Definition: Coord.h:131
openvdb::v9_0::math::Coord::x
Int32 x() const
Definition: Coord.h:130
openvdb::v9_0::math::Coord::z
Int32 z() const
Definition: Coord.h:132
openvdb::v9_0::points::AttributeArray::ScopedRegistryLock
Definition: AttributeArray.h:119
openvdb::v9_0::points::AttributeArray
Base class for storing attribute data.
Definition: AttributeArray.h:93
openvdb::v9_0::points::AttributeArray::Ptr
std::shared_ptr< AttributeArray > Ptr
Definition: AttributeArray.h:125
openvdb::v9_0::points::AttributeArray::size
virtual Index size() const =0
openvdb::v9_0::points::AttributeArray::compact
virtual bool compact()=0
Compact the existing array to become uniform if all values are identical.
openvdb::v9_0::points::AttributeArray::readPagedBuffers
virtual void readPagedBuffers(compression::PagedInputStream &)=0
Read attribute buffers from a paged stream.
openvdb::v9_0::points::AttributeArray::writePagedBuffers
virtual void writePagedBuffers(compression::PagedOutputStream &, bool outputTransient) const =0
openvdb::v9_0::points::AttributeSet
Ordered collection of uniquely-named attribute arrays.
Definition: AttributeSet.h:39
openvdb::v9_0::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_0::points::AttributeSet::UniquePtr
std::unique_ptr< AttributeSet > UniquePtr
Definition: AttributeSet.h:45
openvdb::v9_0::points::AttributeSet::DescriptorPtr
std::shared_ptr< Descriptor > DescriptorPtr
Definition: AttributeSet.h:49
openvdb::v9_0::points::GroupFilter
Index filtering on group membership.
Definition: AttributeGroup.h:135
openvdb::v9_0::points::GroupFilter::state
static index::State state()
Definition: AttributeGroup.h:145
openvdb::v9_0::points::GroupHandle
Definition: AttributeGroup.h:73
openvdb::v9_0::points::GroupWriteHandle
Definition: AttributeGroup.h:102
openvdb::v9_0::points::IndexIter
A forward iterator over array indices with filtering IteratorT can be either IndexIter or ValueIndexI...
Definition: IndexIterator.h:140
openvdb::v9_0::points::NullFilter
A no-op filter that can be used when iterating over all indices.
Definition: IndexIterator.h:51
openvdb::v9_0::points::PointDataLeafNode
Definition: PointDataGrid.h:239
openvdb::v9_0::points::PointDataLeafNode::cbeginChildOn
ChildOnCIter cbeginChildOn() const
Definition: PointDataGrid.h:721
openvdb::v9_0::points::PointDataLeafNode::setValueOn
void setValueOn(Index offset)
Definition: PointDataGrid.h:542
openvdb::v9_0::points::PointDataLeafNode::setValueOff
void setValueOff(const Coord &, const ValueType &)
Definition: PointDataGrid.h:538
openvdb::v9_0::points::PointDataLeafNode::beginChildOn
ChildOnCIter beginChildOn() const
Definition: PointDataGrid.h:722
openvdb::v9_0::points::PointDataLeafNode::beginChildOn
ChildOnIter beginChildOn()
Definition: PointDataGrid.h:723
openvdb::v9_0::points::PointDataLeafNode::setActiveStateAndCache
void setActiveStateAndCache(const Coord &xyz, bool on, AccessorT &parent)
Definition: PointDataGrid.h:580
openvdb::v9_0::points::PointDataLeafNode::endValueOn
ValueOnIter endValueOn()
Definition: PointDataGrid.h:713
openvdb::v9_0::points::PointDataLeafNode::touchLeaf
PointDataLeafNode * touchLeaf(const Coord &)
Return a pointer to this node.
Definition: PointDataGrid.h:458
openvdb::v9_0::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const tools::PointIndexLeafNode< OtherValueType, Log2Dim > &other)
Definition: PointDataGrid.h:296
openvdb::v9_0::points::PointDataLeafNode::cbeginValueOff
ValueOffCIter cbeginValueOff() const
Definition: PointDataGrid.h:704
openvdb::v9_0::points::PointDataLeafNode::ChildOnIter
typename BaseLeaf::template ChildIter< MaskOnIterator, PointDataLeafNode, ChildOn > ChildOnIter
Definition: PointDataGrid.h:639
openvdb::v9_0::points::PointDataLeafNode::touchLeafAndCache
PointDataLeafNode * touchLeafAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:460
openvdb::v9_0::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const PointDataLeafNode &other, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition: PointDataGrid.h:286
openvdb::v9_0::points::PointDataLeafNode::operator==
bool operator==(const PointDataLeafNode &other) const
Definition: PointDataGrid.h:445
openvdb::v9_0::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_0::points::PointDataLeafNode::endChildOn
ChildOnIter endChildOn()
Definition: PointDataGrid.h:733
openvdb::v9_0::points::PointDataLeafNode::endValueAll
ValueAllIter endValueAll()
Definition: PointDataGrid.h:719
openvdb::v9_0::points::PointDataLeafNode::modifyValue
void modifyValue(Index, const ModifyOp &)
Definition: PointDataGrid.h:553
openvdb::v9_0::points::PointDataLeafNode::setValueOn
void setValueOn(Index, const ValueType &)
Definition: PointDataGrid.h:545
openvdb::v9_0::points::PointDataLeafNode::setValuesOff
void setValuesOff()
Definition: PointDataGrid.h:550
openvdb::v9_0::points::PointDataLeafNode::endValueAll
ValueAllCIter endValueAll() const
Definition: PointDataGrid.h:718
openvdb::v9_0::points::PointDataLeafNode::probeLeaf
const PointDataLeafNode * probeLeaf(const Coord &) const
Definition: PointDataGrid.h:482
openvdb::v9_0::points::PointDataLeafNode::endChildOff
ChildOffCIter endChildOff() const
Definition: PointDataGrid.h:735
openvdb::v9_0::points::PointDataLeafNode::setValueOff
void setValueOff(Index, const ValueType &)
Definition: PointDataGrid.h:539
openvdb::v9_0::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(PartialCreate, const Coord &coords, const T &value=zeroVal< T >(), bool active=false)
Definition: PointDataGrid.h:314
openvdb::v9_0::points::PointDataLeafNode::cbeginValueAll
ValueAllCIter cbeginValueAll() const
Definition: PointDataGrid.h:707
openvdb::v9_0::points::PointDataLeafNode::ChildOff
typename BaseLeaf::ChildOff ChildOff
Definition: PointDataGrid.h:605
openvdb::v9_0::points::PointDataLeafNode::probeConstLeaf
const PointDataLeafNode * probeConstLeaf(const Coord &) const
Return a const pointer to this node.
Definition: PointDataGrid.h:477
openvdb::v9_0::points::PointDataLeafNode::setValueOnly
void setValueOnly(Index, const ValueType &)
Definition: PointDataGrid.h:533
openvdb::v9_0::points::PointDataLeafNode::Ptr
std::shared_ptr< PointDataLeafNode > Ptr
Definition: PointDataGrid.h:243
openvdb::v9_0::points::PointDataLeafNode::beginIndexAll
IndexAllIter beginIndexAll() const
Leaf index iterator.
Definition: PointDataGrid.h:657
openvdb::v9_0::points::PointDataLeafNode::beginValueOn
ValueOnCIter beginValueOn() const
Definition: PointDataGrid.h:702
openvdb::v9_0::points::PointDataLeafNode::ChildOn
typename BaseLeaf::ChildOn ChildOn
Definition: PointDataGrid.h:604
openvdb::v9_0::points::PointDataLeafNode::signedFloodFill
void signedFloodFill(const ValueType &, const ValueType &)
Definition: PointDataGrid.h:589
openvdb::v9_0::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const PointDataLeafNode &other)
Construct using deep copy of other PointDataLeafNode.
Definition: PointDataGrid.h:274
openvdb::v9_0::points::PointDataLeafNode::modifyValueAndActiveState
void modifyValueAndActiveState(const Coord &, const ModifyOp &)
Definition: PointDataGrid.h:559
openvdb::v9_0::points::PointDataLeafNode::ValueAllIter
typename BaseLeaf::template ValueIter< MaskDenseIterator, PointDataLeafNode, const ValueType, ValueAll > ValueAllIter
Definition: PointDataGrid.h:635
openvdb::v9_0::points::PointDataLeafNode::ChildAll
typename BaseLeaf::ChildAll ChildAll
Definition: PointDataGrid.h:606
openvdb::v9_0::points::PointDataLeafNode::beginIndex
IndexIter< IterT, FilterT > beginIndex(const FilterT &filter) const
openvdb::v9_0::points::PointDataLeafNode::ValueOffIter
typename BaseLeaf::template ValueIter< MaskOffIterator, PointDataLeafNode, const ValueType, ValueOff > ValueOffIter
Definition: PointDataGrid.h:631
openvdb::v9_0::points::PointDataLeafNode::cendValueOn
ValueOnCIter cendValueOn() const
Definition: PointDataGrid.h:711
openvdb::v9_0::points::PointDataLeafNode::beginValueOff
ValueOffCIter beginValueOff() const
Definition: PointDataGrid.h:705
openvdb::v9_0::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:863
openvdb::v9_0::points::PointDataLeafNode::beginIndexOff
IndexOffIter beginIndexOff() const
Definition: PointDataGrid.h:667
openvdb::v9_0::points::PointDataLeafNode::cbeginChildAll
ChildAllCIter cbeginChildAll() const
Definition: PointDataGrid.h:727
openvdb::v9_0::points::PointDataLeafNode::endChildOff
ChildOffIter endChildOff()
Definition: PointDataGrid.h:736
openvdb::v9_0::points::PointDataLeafNode::modifyValueAndActiveStateAndCache
void modifyValueAndActiveStateAndCache(const Coord &, const ModifyOp &, AccessorT &)
Definition: PointDataGrid.h:572
openvdb::v9_0::points::PointDataLeafNode::setValueOnly
void setValueOnly(const Coord &, const ValueType &)
Definition: PointDataGrid.h:532
openvdb::v9_0::points::PointDataLeafNode::beginChildAll
ChildAllIter beginChildAll()
Definition: PointDataGrid.h:729
openvdb::v9_0::points::PointDataLeafNode::probeConstLeafAndCache
const PointDataLeafNode * probeConstLeafAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:479
openvdb::v9_0::points::PointDataLeafNode::setActiveState
void setActiveState(const Coord &xyz, bool on)
Definition: PointDataGrid.h:529
openvdb::v9_0::points::PointDataLeafNode::beginValueOn
ValueOnIter beginValueOn()
Definition: PointDataGrid.h:703
openvdb::v9_0::points::PointDataLeafNode::ChildOffCIter
typename BaseLeaf::template ChildIter< MaskOffIterator, const PointDataLeafNode, ChildOff > ChildOffCIter
Definition: PointDataGrid.h:645
openvdb::v9_0::points::PointDataLeafNode::probeNodeAndCache
NodeT * probeNodeAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:463
openvdb::v9_0::points::PointDataLeafNode::beginIndexAll
IndexIter< ValueAllCIter, FilterT > beginIndexAll(const FilterT &filter) const
Filtered leaf index iterator.
Definition: PointDataGrid.h:678
openvdb::v9_0::points::PointDataLeafNode::assertNonModifiableUnlessZero
void assertNonModifiableUnlessZero(const ValueType &value)
Definition: PointDataGrid.h:525
openvdb::v9_0::points::PointDataLeafNode::probeLeafAndCache
const PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:481
openvdb::v9_0::points::PointDataLeafNode::cbeginChildOff
ChildOffCIter cbeginChildOff() const
Definition: PointDataGrid.h:724
openvdb::v9_0::points::PointDataLeafNode::beginChildOff
ChildOffIter beginChildOff()
Definition: PointDataGrid.h:726
openvdb::v9_0::points::PointDataLeafNode::beginChildOff
ChildOffCIter beginChildOff() const
Definition: PointDataGrid.h:725
openvdb::v9_0::points::PointDataLeafNode::setValueOff
void setValueOff(const Coord &xyz)
Definition: PointDataGrid.h:535
openvdb::v9_0::points::PointDataLeafNode::operator!=
bool operator!=(const PointDataLeafNode &other) const
Definition: PointDataGrid.h:450
openvdb::v9_0::points::PointDataLeafNode::endValueOff
ValueOffIter endValueOff()
Definition: PointDataGrid.h:716
openvdb::v9_0::points::PointDataLeafNode::setValueOff
void setValueOff(Index offset)
Definition: PointDataGrid.h:536
openvdb::v9_0::points::PointDataLeafNode::beginIndexOn
IndexIter< ValueOnCIter, FilterT > beginIndexOn(const FilterT &filter) const
Definition: PointDataGrid.h:683
openvdb::v9_0::points::PointDataLeafNode::endChildAll
ChildAllCIter endChildAll() const
Definition: PointDataGrid.h:738
openvdb::v9_0::points::PointDataLeafNode::probeConstNodeAndCache
const NodeT * probeConstNodeAndCache(const Coord &, AccessorT &) const
Definition: PointDataGrid.h:484
openvdb::v9_0::points::PointDataLeafNode::cbeginValueOn
ValueOnCIter cbeginValueOn() const
Definition: PointDataGrid.h:701
openvdb::v9_0::points::PointDataLeafNode::ChildAllCIter
typename BaseLeaf::template DenseIter< const PointDataLeafNode, const ValueType, ChildAll > ChildAllCIter
Definition: PointDataGrid.h:649
openvdb::v9_0::points::PointDataLeafNode::clip
void clip(const CoordBBox &, const ValueType &value)
Definition: PointDataGrid.h:562
openvdb::v9_0::points::PointDataLeafNode::endChildOn
ChildOnCIter endChildOn() const
Definition: PointDataGrid.h:732
openvdb::v9_0::points::PointDataLeafNode::reorderAttributes
void reorderAttributes(const Descriptor::Ptr &replacement)
Reorder attribute set.
Definition: PointDataGrid.h:824
openvdb::v9_0::points::PointDataLeafNode::ValueOnCIter
typename BaseLeaf::template ValueIter< MaskOnIterator, const PointDataLeafNode, const ValueType, ValueOn > ValueOnCIter
Definition: PointDataGrid.h:629
openvdb::v9_0::points::PointDataLeafNode::cendChildOn
ChildOnCIter cendChildOn() const
Definition: PointDataGrid.h:731
openvdb::v9_0::points::PointDataLeafNode::cendChildAll
ChildAllCIter cendChildAll() const
Definition: PointDataGrid.h:737
openvdb::v9_0::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode()
Default constructor.
Definition: PointDataGrid.h:268
openvdb::v9_0::points::PointDataLeafNode::attributeSet
const AttributeSet & attributeSet() const
Retrieve the attribute set.
Definition: PointDataGrid.h:322
openvdb::v9_0::points::PointDataLeafNode::assertNonmodifiable
void assertNonmodifiable()
Definition: PointDataGrid.h:518
openvdb::v9_0::points::PointDataLeafNode::setValueOffAndCache
void setValueOffAndCache(const Coord &, const ValueType &, AccessorT &)
Definition: PointDataGrid.h:577
openvdb::v9_0::points::PointDataLeafNode::endChildAll
ChildAllIter endChildAll()
Definition: PointDataGrid.h:739
openvdb::v9_0::points::PointDataLeafNode::beginIndexOff
IndexIter< ValueOffCIter, FilterT > beginIndexOff(const FilterT &filter) const
Definition: PointDataGrid.h:688
openvdb::v9_0::points::PointDataLeafNode::resetBackground
void resetBackground(const ValueType &, const ValueType &newBackground)
Definition: PointDataGrid.h:584
openvdb::v9_0::points::PointDataLeafNode::MaskOffIterator
typename NodeMaskType::OffIterator MaskOffIterator
Definition: PointDataGrid.h:609
openvdb::v9_0::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &value, TopologyCopy)
Definition: PointDataGrid.h:303
openvdb::v9_0::points::PointDataLeafNode::setValue
void setValue(const Coord &, const ValueType &)
Definition: PointDataGrid.h:547
openvdb::v9_0::points::PointDataLeafNode::cendValueAll
ValueAllCIter cendValueAll() const
Definition: PointDataGrid.h:717
openvdb::v9_0::points::PointDataLeafNode::~PointDataLeafNode
~PointDataLeafNode()=default
openvdb::v9_0::points::PointDataLeafNode::negate
void negate()
Definition: PointDataGrid.h:591
openvdb::v9_0::points::PointDataLeafNode::beginChildAll
ChildAllCIter beginChildAll() const
Definition: PointDataGrid.h:728
openvdb::v9_0::points::PointDataLeafNode::ValueAll
typename BaseLeaf::ValueAll ValueAll
Definition: PointDataGrid.h:597
openvdb::v9_0::points::PointDataLeafNode::ValueTypePair
std::pair< ValueType, ValueType > ValueTypePair
Definition: PointDataGrid.h:246
openvdb::v9_0::points::PointDataLeafNode::setValuesOn
void setValuesOn()
Definition: PointDataGrid.h:549
openvdb::v9_0::points::PointDataLeafNode::Descriptor
AttributeSet::Descriptor Descriptor
Definition: PointDataGrid.h:249
openvdb::v9_0::points::PointDataLeafNode::ValueOn
typename BaseLeaf::ValueOn ValueOn
Definition: PointDataGrid.h:595
openvdb::v9_0::points::PointDataLeafNode::cendChildOff
ChildOffCIter cendChildOff() const
Definition: PointDataGrid.h:734
openvdb::v9_0::points::PointDataLeafNode::addLeafAndCache
void addLeafAndCache(PointDataLeafNode *, AccessorT &)
Definition: PointDataGrid.h:454
openvdb::v9_0::points::PointDataLeafNode::setValueOnlyAndCache
void setValueOnlyAndCache(const Coord &, const ValueType &, AccessorT &)
Definition: PointDataGrid.h:569
openvdb::v9_0::points::PointDataLeafNode::fill
void fill(const ValueType &value)
Definition: PointDataGrid.h:565
openvdb::v9_0::points::PointDataLeafNode::MaskOnIterator
typename NodeMaskType::OnIterator MaskOnIterator
Definition: PointDataGrid.h:608
openvdb::v9_0::points::PointDataLeafNode::ChildOffIter
typename BaseLeaf::template ChildIter< MaskOffIterator, PointDataLeafNode, ChildOff > ChildOffIter
Definition: PointDataGrid.h:643
openvdb::v9_0::points::PointDataLeafNode::addLeaf
void addLeaf(PointDataLeafNode *)
Definition: PointDataGrid.h:452
openvdb::v9_0::points::PointDataLeafNode::signedFloodFill
void signedFloodFill(const ValueType &)
Definition: PointDataGrid.h:588
openvdb::v9_0::points::PointDataLeafNode::beginValueOff
ValueOffIter beginValueOff()
Definition: PointDataGrid.h:706
openvdb::v9_0::points::PointDataLeafNode::setValueOn
void setValueOn(const Coord &xyz)
Definition: PointDataGrid.h:541
openvdb::v9_0::points::PointDataLeafNode::setActiveState
void setActiveState(Index offset, bool on)
Definition: PointDataGrid.h:530
openvdb::v9_0::points::PointDataLeafNode::ValueOffCIter
typename BaseLeaf::template ValueIter< MaskOffIterator, const PointDataLeafNode, const ValueType, ValueOff > ValueOffCIter
Definition: PointDataGrid.h:633
openvdb::v9_0::points::PointDataLeafNode::beginIndexOn
IndexOnIter beginIndexOn() const
Definition: PointDataGrid.h:662
openvdb::v9_0::points::PointDataLeafNode::ValueOff
typename BaseLeaf::ValueOff ValueOff
Definition: PointDataGrid.h:596
openvdb::v9_0::points::PointDataLeafNode::modifyValue
void modifyValue(const Coord &, const ModifyOp &)
Definition: PointDataGrid.h:556
openvdb::v9_0::points::PointDataLeafNode::cendValueOff
ValueOffCIter cendValueOff() const
Definition: PointDataGrid.h:714
openvdb::v9_0::points::PointDataLeafNode::ChildOnCIter
typename BaseLeaf::template ChildIter< MaskOnIterator, const PointDataLeafNode, ChildOn > ChildOnCIter
Definition: PointDataGrid.h:641
openvdb::v9_0::points::PointDataLeafNode::fill
void fill(const CoordBBox &, const ValueType &, bool)
Definition: PointDataGrid.h:1539
openvdb::v9_0::points::PointDataLeafNode::endValueOff
ValueOffCIter endValueOff() const
Definition: PointDataGrid.h:715
openvdb::v9_0::points::PointDataLeafNode::ValueOnIter
typename BaseLeaf::template ValueIter< MaskOnIterator, PointDataLeafNode, const ValueType, ValueOn > ValueOnIter
Definition: PointDataGrid.h:627
openvdb::v9_0::points::PointDataLeafNode::probeLeaf
PointDataLeafNode * probeLeaf(const Coord &)
Definition: PointDataGrid.h:470
openvdb::v9_0::points::PointDataLeafNode::ValueType
T ValueType
Definition: PointDataGrid.h:245
openvdb::v9_0::points::PointDataLeafNode::probeLeafAndCache
PointDataLeafNode * probeLeafAndCache(const Coord &, AccessorT &)
Definition: PointDataGrid.h:472
openvdb::v9_0::points::PointDataLeafNode::endValueOn
ValueOnCIter endValueOn() const
Definition: PointDataGrid.h:712
openvdb::v9_0::points::PointDataLeafNode::MaskDenseIterator
typename NodeMaskType::DenseIterator MaskDenseIterator
Definition: PointDataGrid.h:610
openvdb::v9_0::points::PointDataLeafNode::beginValueAll
ValueAllCIter beginValueAll() const
Definition: PointDataGrid.h:708
openvdb::v9_0::points::PointDataLeafNode::ChildAllIter
typename BaseLeaf::template DenseIter< PointDataLeafNode, ValueType, ChildAll > ChildAllIter
Definition: PointDataGrid.h:647
openvdb::v9_0::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_0::points::PointDataLeafNode::PointDataLeafNode
PointDataLeafNode(const tree::LeafNode< ValueType, Log2Dim > &other, const T &, const T &, TopologyCopy)
Definition: PointDataGrid.h:310
openvdb::v9_0::points::PointDataLeafNode::ValueAllCIter
typename BaseLeaf::template ValueIter< MaskDenseIterator, const PointDataLeafNode, const ValueType, ValueAll > ValueAllCIter
Definition: PointDataGrid.h:637
openvdb::v9_0::points::PointDataLeafNode::setValueOn
void setValueOn(const Coord &, const ValueType &)
Definition: PointDataGrid.h:544
openvdb::v9_0::points::PointDataLeafNode::beginValueAll
ValueAllIter beginValueAll()
Definition: PointDataGrid.h:709
openvdb::v9_0::points::PointDataLeafNode::IndexArray
std::vector< ValueType > IndexArray
Definition: PointDataGrid.h:247
openvdb::v9_0::points::TypedAttributeArray
Typed class for storing attribute data.
Definition: AttributeArray.h:533
openvdb::v9_0::points::ValueVoxelCIter
A forward iterator over array indices in a single voxel.
Definition: IndexIterator.h:65
openvdb::v9_0::tree::InternalNode
Definition: InternalNode.h:34
openvdb::v9_0::tree::IteratorBase
Base class for iterators over internal and leaf nodes.
Definition: Iterator.h:30
openvdb::v9_0::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_0::tree::LeafNode::size
static Index size()
Return the total number of voxels represented by this LeafNode.
Definition: LeafNode.h:121
openvdb::v9_0::tree::RootNode
Definition: RootNode.h:39
openvdb::v9_0::tree::Tree
Definition: Tree.h:176
openvdb::v9_0::util::DenseMaskIterator
Definition: NodeMasks.h:271
openvdb::v9_0::util::NodeMask
Bit mask for the internal and leaf nodes of VDB. This is a 64-bit implementation.
Definition: NodeMasks.h:308
openvdb::v9_0::util::OffMaskIterator
Definition: NodeMasks.h:240
openvdb::v9_0::util::OnMaskIterator
Definition: NodeMasks.h:209
openvdb::v9_0::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_0::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_0::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_0::io::writeCompressedValuesSize
void writeCompressedValuesSize(std::ostream &os, const T *srcBuf, Index srcCount)
Definition: PointDataGrid.h:139
openvdb::v9_0::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_0::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_0::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_0::points::index::ALL
@ ALL
Definition: IndexIterator.h:43
openvdb::v9_0::points::index::NONE
@ NONE
Definition: IndexIterator.h:42
openvdb::v9_0::points::internal::uninitialize
void uninitialize()
Global deregistration of point data-related types.
openvdb::v9_0::points::internal::initialize
void initialize()
Global registration of point data-related types.
openvdb::v9_0::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:1594
openvdb::v9_0::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:1607
openvdb::v9_0::points::compactAttributes
void compactAttributes(PointDataTreeT &tree)
Compact attributes in a VDB tree (if possible).
Definition: PointAttribute.h:527
openvdb::v9_0::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_0::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_0::points::dropAttributes
void dropAttributes(PointDataTreeT &tree, const std::vector< size_t > &indices)
Drops attributes from the VDB tree.
Definition: PointAttribute.h:380
openvdb::v9_0::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_0::points::isGroup
bool isGroup(const AttributeArray &array)
Definition: AttributeGroup.h:63
openvdb::v9_0::points::iterCount
Index64 iterCount(const IterT &iter)
Count up the number of times the iterator can iterate.
Definition: IndexIterator.h:314
openvdb::v9_0::points::makeDescriptorUnique
AttributeSet::Descriptor::Ptr makeDescriptorUnique(PointDataTreeT &tree)
Deep copy the descriptor across all leaf nodes.
Definition: PointDataGrid.h:1577
openvdb::v9_0::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_0::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:408
openvdb::v9_0::Name
std::string Name
Definition: Name.h:17
openvdb::v9_0::typeNameAsString< Vec3f >
const char * typeNameAsString< Vec3f >()
Definition: Types.h:417
openvdb::v9_0::Index
Index32 Index
Definition: Types.h:54
openvdb::v9_0::Int32
int32_t Int32
Definition: Types.h:56
openvdb::v9_0::Index64
uint64_t Index64
Definition: Types.h:53
openvdb::v9_0::zeroVal
T zeroVal()
Return the value of type T that corresponds to zero.
Definition: Math.h:69
openvdb::v9_0::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_0::PointIndex
Integer wrapper, required to distinguish PointIndexGrid and PointDataGrid from Int32Grid and Int64Gri...
Definition: Types.h:157
openvdb::v9_0::TypeList
A list of types (not necessarily unique)
Definition: TypeList.h:366
openvdb::v9_0::io::MultiPass
Leaf nodes that require multi-pass I/O must inherit from this struct.
Definition: io.h:124
openvdb::v9_0::points::TreeConverter
Similiar to ValueConverter, but allows for tree configuration conversion to a PointDataTree....
Definition: PointDataGrid.h:1701
openvdb::v9_0::points::TreeConverter::RootNodeT
typename TreeType::RootNodeType RootNodeT
Definition: PointDataGrid.h:1702
openvdb::v9_0::points::TreeConverter::NodeChainT
typename internal::PointDataNodeChain< RootNodeT, RootNodeT::LEVEL >::Type NodeChainT
Definition: PointDataGrid.h:1703
openvdb::v9_0::points::internal::PointDataNodeChain< tree::InternalNode< ChildT, Log2Dim >, HeadLevel >::SubtreeT
typename PointDataNodeChain< ChildT, HeadLevel-1 >::Type SubtreeT
Definition: PointDataGrid.h:1679
openvdb::v9_0::points::internal::PointDataNodeChain< tree::InternalNode< ChildT, Log2Dim >, HeadLevel >::Type
typename SubtreeT::template Append< InternalNodeT > Type
Definition: PointDataGrid.h:1681
openvdb::v9_0::points::internal::PointDataNodeChain
Recursive node chain which generates a openvdb::TypeList value converted types of nodes to PointDataG...
Definition: PointDataGrid.h:1668
openvdb::v9_0::points::internal::PointDataNodeChain::SubtreeT
typename PointDataNodeChain< typename HeadT::ChildNodeType, HeadLevel-1 >::Type SubtreeT
Definition: PointDataGrid.h:1669
openvdb::v9_0::points::internal::PointDataNodeChain::Type
typename SubtreeT::template Append< RootNodeT > Type
Definition: PointDataGrid.h:1671
openvdb::v9_0::tools::PointIndexLeafNode
Definition: PointIndexGrid.h:1358
openvdb::v9_0::tree::IterTraits
Definition: TreeIterator.h:60
openvdb::v9_0::tree::LeafNode::ChildAll
Definition: LeafNode.h:211
openvdb::v9_0::tree::LeafNode::ChildIter
Leaf nodes have no children, so their child iterators have no get/set accessors.
Definition: LeafNode.h:251
openvdb::v9_0::tree::LeafNode::ChildOff
Definition: LeafNode.h:211
openvdb::v9_0::tree::LeafNode::ChildOn
Definition: LeafNode.h:211
openvdb::v9_0::tree::LeafNode::DenseIter
Definition: LeafNode.h:260
openvdb::v9_0::tree::LeafNode::ValueAll
Definition: LeafNode.h:210
openvdb::v9_0::tree::LeafNode::ValueIter
Definition: LeafNode.h:219
openvdb::v9_0::tree::LeafNode::ValueOff
Definition: LeafNode.h:210
openvdb::v9_0::tree::LeafNode::ValueOn
Definition: LeafNode.h:210
openvdb::v9_0::tree::SameLeafConfig
Definition: LeafNode.h:923
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