16#ifndef NANOVDB_INDEXGRIDBUILDER_H_HAS_BEEN_INCLUDED
17#define NANOVDB_INDEXGRIDBUILDER_H_HAS_BEEN_INCLUDED
34template <
typename SrcValueT>
59 std::vector<uint64_t> mValIdx2, mValIdx1, mValIdx0;
61 uint64_t mBufferOffsets[9];
63 const bool mIsSparse, mIncludeStats;
65 DstNode0* getLeaf(
int i=0)
const {
return PtrAdd<DstNode0>(mBufferPtr, mBufferOffsets[5]) + i;}
66 DstNode1* getLower(
int i=0)
const {
return PtrAdd<DstNode1>(mBufferPtr, mBufferOffsets[4]) + i;}
67 DstNode2* getUpper(
int i=0)
const {
return PtrAdd<DstNode2>(mBufferPtr, mBufferOffsets[3]) + i;}
68 DstRootT* getRoot()
const {
return PtrAdd<DstRootT>(mBufferPtr, mBufferOffsets[2]);}
69 DstTreeT* getTree()
const {
return PtrAdd<DstTreeT>(mBufferPtr, mBufferOffsets[1]);}
70 DstGridT* getGrid()
const {
return PtrAdd<DstGridT>(mBufferPtr, mBufferOffsets[0]);}
76 template<
typename BufferT>
89 void processGrid(
const std::string& name, uint32_t channels);
91 void processChannels(uint32_t channels);
104 , mSrcMgr(mSrcMgrHandle.template mgr<SrcValueT>())
106 , mIsSparse(!includeInactive)
107 , mIncludeStats(includeStats)
111 template<
typename BufferT = HostBuffer>
121 template<
typename BufferT = HostBuffer>
122 BufferT
getValues(uint32_t channels = 1u,
const BufferT &buffer = BufferT());
125 uint64_t
copyValues(SrcValueT *buffer,
size_t maxValueCount = -1);
130template<
typename SrcValueT>
131template<
typename BufferT>
133getHandle(
const std::string &name, uint32_t channels,
const BufferT &buffer)
137 auto handle = this->
template initHandle<BufferT>(channels, buffer);
139 this->processLeafs();
141 this->processLower();
143 this->processUpper();
149 this->processGrid(name, channels);
151 this->processChannels(channels);
158template<
typename SrcValueT>
161 const uint64_t stats = mIncludeStats ? 4u : 0u;
163 uint64_t valueCount = 1u + stats;
167 for (
auto it = mSrcMgr->
root().beginValueOn(); it; ++it) ++valueCount;
169 for (
auto it = mSrcMgr->
root().beginValue(); it; ++it) ++valueCount;
173 mValIdx2.resize(mSrcMgr->
nodeCount(2) + 1);
176 for (auto i = r.begin(); i!=r.end(); ++i) {
177 mValIdx2[i] = stats + mSrcMgr->upper(i-1).data()->mValueMask.countOn();
182 const uint64_t n = 32768u + stats;
183 for (auto i = r.begin(); i!=r.end(); ++i) {
184 mValIdx2[i] = n - mSrcMgr->upper(i-1).data()->mChildMask.countOn();
188 mValIdx2[0] = valueCount;
189 for (
size_t i=1; i<mValIdx2.size(); ++i) mValIdx2[i] += mValIdx2[i-1];
190 valueCount = mValIdx2.back();
193 mValIdx1.resize(mSrcMgr->
nodeCount(1) + 1);
195 forEach(1, mValIdx1.size(), 8, [&](
const Range1D& r){
196 for (auto i = r.begin(); i!=r.end(); ++i) {
197 mValIdx1[i] = stats + mSrcMgr->lower(i-1).data()->mValueMask.countOn();
201 forEach(1, mValIdx1.size(), 8, [&](
const Range1D& r){
202 const uint64_t n = 4096u + stats;
203 for (auto i = r.begin(); i!=r.end(); ++i) {
204 mValIdx1[i] = n - mSrcMgr->lower(i-1).data()->mChildMask.countOn();
208 mValIdx1[0] = valueCount;
209 for (
size_t i=1; i<mValIdx1.size(); ++i) mValIdx1[i] += mValIdx1[i-1];
210 valueCount = mValIdx1.back();
214 mValIdx0.resize(mSrcMgr->
nodeCount(0) + 1, 512u + stats);
216 forEach(1, mValIdx0.size(), 8, [&](
const Range1D& r) {
217 for (auto i = r.begin(); i != r.end(); ++i) {
218 mValIdx0[i] = stats + mSrcMgr->leaf(i-1).data()->mValueMask.countOn();
222 mValIdx0[0] = valueCount;
223 for (
size_t i=1; i<mValIdx0.size(); ++i) mValIdx0[i] += mValIdx0[i-1];
225 mValueCount = mValIdx0.back();
230template<
typename SrcValueT>
234 if (maxValueCount < mValueCount)
return 0;
237 buffer[0] = mSrcMgr->
root().background();
239 buffer[1] = mSrcMgr->
root().minimum();
240 buffer[2] = mSrcMgr->
root().maximum();
241 buffer[3] = mSrcMgr->
root().average();
242 buffer[4] = mSrcMgr->
root().stdDeviation();
245 auto *srcData = mSrcMgr->
root().data();
246 SrcValueT *v = buffer + (mIncludeStats ? 5u : 1u);
247 for (uint32_t tileID = 0; tileID < srcData->mTableSize; ++tileID) {
248 auto *srcTile = srcData->tile(tileID);
249 if (srcTile->isChild() ||(mIsSparse&&!srcTile->state))
continue;
251 *v++ = srcTile->value;
256 auto kernel = [&](
const Range1D& r) {
257 DstData2 *dstData = this->getUpper(r.begin())->data();
258 for (
auto i = r.begin(); i != r.end(); ++i, ++dstData) {
259 SrcValueT *v = buffer + mValIdx2[i];
273 auto *srcData = srcNode.
data();
274 for (uint32_t j = 0; j != 32768; ++j) {
275 if (srcData->mChildMask.isOn(j))
continue;
277 *v++ = srcData->getValue(j);
286 auto kernel = [&](
const Range1D& r) {
287 DstData1 *dstData = this->getLower(r.begin())->data();
288 for (
auto i = r.begin(); i != r.end(); ++i, ++dstData) {
289 SrcValueT *v = buffer + mValIdx1[i];
303 auto *srcData = srcNode.
data();
304 for (uint32_t j = 0; j != 4096; ++j) {
305 if (srcData->mChildMask.isOn(j))
continue;
307 *v++ = srcData->getValue(j);
315 auto kernel = [&](
const Range1D& r) {
316 DstData0 *dstLeaf = this->getLeaf(r.begin())->data();
317 for (
auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
318 SrcValueT *v = buffer + mValIdx0[i];
332 const SrcData0 *srcData = srcLeaf.
data();
333 for (uint32_t j = 0; j != 512; ++j) {
335 *v++ = srcData->getValue(j);
345template<
typename SrcValueT>
346template<
typename BufferT>
349 assert(channels > 0);
350 auto values = BufferT::create(channels*
sizeof(SrcValueT)*mValueCount, &buffer);
351 SrcValueT *p =
reinterpret_cast<SrcValueT*
>(values.data());
352 if (!this->copyValues(p, mValueCount)) {
353 throw std::runtime_error(
"getValues: insufficient channels");
355 for (uint32_t i=1; i<channels; ++i) {
357 SrcValueT *dst=p+i*mValueCount+r.begin(), *end=dst+r.size(), *src=dst-mValueCount;
358 while(dst!=end) *dst++ = *src++;
366template<
typename SrcValueT>
367template<
typename BufferT>
369initHandle(uint32_t channels,
const BufferT& buffer)
371 const SrcTreeT &srcTree = mSrcMgr->
tree();
372 mBufferOffsets[0] = 0;
373 mBufferOffsets[1] = DstGridT::memUsage();
374 mBufferOffsets[2] = mBufferOffsets[1] + DstTreeT::memUsage();
375 mBufferOffsets[3] = mBufferOffsets[2] + DstRootT::memUsage(srcTree.root().tileCount());
376 mBufferOffsets[4] = mBufferOffsets[3] + srcTree.nodeCount(2)*
sizeof(DstData2);
377 mBufferOffsets[5] = mBufferOffsets[4] + srcTree.nodeCount(1)*
sizeof(DstData1);
378 mBufferOffsets[6] = mBufferOffsets[5] + srcTree.nodeCount(0)*
sizeof(DstData0);
379 mBufferOffsets[7] = mBufferOffsets[6] + GridBlindMetaData::memUsage(channels);
380 mBufferOffsets[8] = mBufferOffsets[7] + channels*mValueCount*
sizeof(SrcValueT);
382 std::cerr <<
"grid starts at " << mBufferOffsets[0] <<
" byte" << std::endl;
383 std::cerr <<
"tree starts at " << mBufferOffsets[1] <<
" byte" << std::endl;
384 std::cerr <<
"root starts at " << mBufferOffsets[2] <<
" byte" << std::endl;
385 std::cerr <<
"node starts at " << mBufferOffsets[3] <<
" byte" <<
" #" << srcTree.nodeCount(2) << std::endl;
386 std::cerr <<
"node starts at " << mBufferOffsets[4] <<
" byte" <<
" #" << srcTree.nodeCount(1) << std::endl;
387 std::cerr <<
"leaf starts at " << mBufferOffsets[5] <<
" byte" <<
" #" << srcTree.nodeCount(0) << std::endl;
388 std::cerr <<
"meta starts at " << mBufferOffsets[6] <<
" byte" << std::endl;
389 std::cerr <<
"data starts at " << mBufferOffsets[7] <<
" byte" << std::endl;
390 std::cerr <<
"buffer ends at " << mBufferOffsets[8] <<
" byte" << std::endl;
391 std::cerr <<
"creating buffer of size " << (mBufferOffsets[8]>>20) <<
"MB" << std::endl;
394 mBufferPtr = handle.data();
401template<
typename SrcValueT>
402void IndexGridBuilder<SrcValueT>::processGrid(
const std::string& name, uint32_t channels)
404 auto *srcData = mSrcMgr->
grid().
data();
405 auto *dstData = this->getGrid()->data();
408 dstData->mChecksum = 0u;
409 dstData->mVersion = Version();
410 dstData->mFlags =
static_cast<uint32_t
>(GridFlags::IsBreadthFirst);
411 dstData->mGridIndex = 0;
412 dstData->mGridCount = 1;
413 dstData->mGridSize = mBufferOffsets[8];
414 std::memset(dstData->mGridName,
'\0', GridData::MaxNameSize);
415 strncpy(dstData->mGridName, name.c_str(), GridData::MaxNameSize-1);
416 dstData->mMap = srcData->mMap;
417 dstData->mWorldBBox = srcData->mWorldBBox;
418 dstData->mVoxelSize = srcData->mVoxelSize;
419 dstData->mGridClass = GridClass::IndexGrid;
420 dstData->mGridType = mapToGridType<ValueIndex>();
421 dstData->mBlindMetadataOffset = mBufferOffsets[6];
422 dstData->mBlindMetadataCount = channels;
423 dstData->mData0 = 0u;
424 dstData->mData1 = mValueCount;
425 dstData->mData2 = 0u;
427 if (name.length() >= GridData::MaxNameSize) {
428 std::stringstream ss;
429 ss <<
"Grid name \"" << name <<
"\" is more then " << GridData::MaxNameSize <<
" characters";
430 throw std::runtime_error(ss.str());
436template<
typename SrcValueT>
437void IndexGridBuilder<SrcValueT>::processTree()
439 auto *srcData = mSrcMgr->
tree().data();
440 auto *dstData = this->getTree()->data();
441 for (
int i=0; i<4; ++i) dstData->mNodeOffset[i] = mBufferOffsets[5-i] - mBufferOffsets[1];
442 for (
int i=0; i<3; ++i) {
443 dstData->mNodeCount[i] = srcData->mNodeCount[i];
444 dstData->mTileCount[i] = srcData->mTileCount[i];
446 dstData->mVoxelCount = srcData->mVoxelCount;
451template<
typename SrcValueT>
452void IndexGridBuilder<SrcValueT>::processRoot()
454 auto *srcData = mSrcMgr->
root().data();
455 auto *dstData = this->getRoot()->data();
457 if (dstData->padding()>0) std::memset(dstData, 0, DstRootT::memUsage(mSrcMgr->
root().tileCount()));
458 dstData->mBBox = srcData->mBBox;
459 dstData->mTableSize = srcData->mTableSize;
460 dstData->mBackground = 0u;
461 uint64_t valueCount = 1u;
464 dstData->mMinimum = 1u;
465 dstData->mMaximum = 2u;
466 dstData->mAverage = 3u;
467 dstData->mStdDevi = 4u;
468 }
else if (dstData->padding()==0) {
469 dstData->mMinimum = 0u;
470 dstData->mMaximum = 0u;
471 dstData->mAverage = 0u;
472 dstData->mStdDevi = 0u;
475 for (uint32_t tileID = 0, childID = 0; tileID < dstData->mTableSize; ++tileID) {
476 auto *srcTile = srcData->tile(tileID);
477 auto *dstTile = dstData->tile(tileID);
478 dstTile->key = srcTile->key;
479 if (srcTile->isChild()) {
480 dstTile->child = childID *
sizeof(DstNode2) + mBufferOffsets[3] - mBufferOffsets[2];
481 dstTile->state =
false;
482 dstTile->value = std::numeric_limits<uint64_t>::max();
486 dstTile->state = srcTile->state;
487 if (!(mIsSparse && !dstTile->state)) dstTile->value = valueCount++;
494template<
typename SrcValueT>
495void IndexGridBuilder<SrcValueT>::processUpper()
497 static_assert(DstData2::padding()==0u,
"Expected upper internal nodes to have no padding");
498 auto kernel = [&](
const Range1D& r) {
499 const bool activeOnly = mIsSparse;
500 const bool hasStats = mIncludeStats;
501 auto *dstData1 = this->getLower()->data();
502 auto *dstData2 = this->getUpper(r.begin())->data();
503 for (
auto i = r.begin(); i != r.end(); ++i, ++dstData2) {
504 SrcData2 *srcData2 = mSrcMgr->
upper(i).data();
505 dstData2->mBBox = srcData2->mBBox;
506 dstData2->mFlags = srcData2->mFlags;
507 srcData2->mFlags = i;
508 dstData2->mChildMask = srcData2->mChildMask;
509 dstData2->mValueMask = srcData2->mValueMask;
510 uint64_t n = mValIdx2[i];
512 dstData2->mMinimum = n++;
513 dstData2->mMaximum = n++;
514 dstData2->mAverage = n++;
515 dstData2->mStdDevi = n++;
517 dstData2->mMinimum = 0u;
518 dstData2->mMaximum = 0u;
519 dstData2->mAverage = 0u;
520 dstData2->mStdDevi = 0u;
522 for (uint32_t j = 0; j != 32768; ++j) {
523 if (dstData2->isChild(j)) {
524 SrcData1 *srcChild = srcData2->getChild(j)->data();
525 DstData1 *dstChild = dstData1 + srcChild->mFlags;
526 dstData2->setChild(j, dstChild);
527 srcChild->mFlags = dstChild->mFlags;
529 const bool test = activeOnly && !srcData2->mValueMask.isOn(j);
530 dstData2->setValue(j, test ? 0 : n++);
541template<
typename SrcValueT>
542void IndexGridBuilder<SrcValueT>::processLower()
544 static_assert(DstData1::padding()==0u,
"Expected lower internal nodes to have no padding");
545 auto kernel = [&](
const Range1D& r) {
546 const bool activeOnly = mIsSparse;
547 DstData0 *dstData0 = this->getLeaf()->data();
548 DstData1 *dstData1 = this->getLower(r.begin())->data();
549 for (
auto i = r.begin(); i != r.end(); ++i, ++dstData1) {
550 SrcData1 *srcData1 = mSrcMgr->
lower(i).data();
551 dstData1->mBBox = srcData1->mBBox;
552 dstData1->mFlags = srcData1->mFlags;
553 srcData1->mFlags = i;
554 dstData1->mChildMask = srcData1->mChildMask;
555 dstData1->mValueMask = srcData1->mValueMask;
556 uint64_t n = mValIdx1[i];
558 dstData1->mMinimum = n++;
559 dstData1->mMaximum = n++;
560 dstData1->mAverage = n++;
561 dstData1->mStdDevi = n++;
563 dstData1->mMinimum = 0u;
564 dstData1->mMaximum = 0u;
565 dstData1->mAverage = 0u;
566 dstData1->mStdDevi = 0u;
568 for (uint32_t j = 0; j != 4096; ++j) {
569 if (dstData1->isChild(j)) {
570 SrcData0 *srcChild = srcData1->getChild(j)->data();
571 DstData0 *dstChild = dstData0 + srcChild->mBBoxMin[0];
572 dstData1->setChild(j, dstChild);
573 srcChild->mBBoxMin[0] = dstChild->mBBoxMin[0];
575 const bool test = activeOnly && !srcData1->mValueMask.isOn(j);
576 dstData1->setValue(j, test ? 0 : n++);
586template<
typename SrcValueT>
587void IndexGridBuilder<SrcValueT>::processLeafs()
589 static_assert(DstData0::padding()==0u,
"Expected leaf nodes to have no padding");
591 auto kernel = [&](
const Range1D& r) {
592 DstData0 *dstData0 = this->getLeaf(r.begin())->data();
593 const uint8_t flags = mIsSparse ? 16u : 0u;
594 for (
auto i = r.begin(); i != r.end(); ++i, ++dstData0) {
595 SrcData0 *srcData0 = mSrcMgr->
leaf(i).data();
596 dstData0->mBBoxMin = srcData0->mBBoxMin;
597 srcData0->mBBoxMin[0] = int(i);
598 dstData0->mBBoxDif[0] = srcData0->mBBoxDif[0];
599 dstData0->mBBoxDif[1] = srcData0->mBBoxDif[1];
600 dstData0->mBBoxDif[2] = srcData0->mBBoxDif[2];
601 dstData0->mFlags = flags | (srcData0->mFlags & 2u);
602 dstData0->mValueMask = srcData0->mValueMask;
605 dstData0->mStatsOff = mValIdx0[i];
606 dstData0->mValueOff = mValIdx0[i] + 4u;
608 dstData0->mStatsOff = 0u;
609 dstData0->mValueOff = mValIdx0[i];
618template<
typename SrcValueT>
619void IndexGridBuilder<SrcValueT>::processChannels(uint32_t channels)
621 for (uint32_t i=0; i<channels; ++i) {
622 auto *metaData = PtrAdd<GridBlindMetaData>(mBufferPtr, mBufferOffsets[6]) + i;
623 auto *blindData = PtrAdd<SrcValueT>(mBufferPtr, mBufferOffsets[7]) + i*mValueCount;
624 metaData->setBlindData(blindData);
625 metaData->mElementCount = mValueCount;
626 metaData->mFlags = 0;
627 metaData->mSemantic = GridBlindDataSemantic::Unknown;
628 metaData->mDataClass = GridBlindDataClass::ChannelArray;
629 metaData->mDataType = mapToGridType<SrcValueT>();
630 std::memset(metaData->mName,
'\0', GridBlindMetaData::MaxNameSize);
631 std::stringstream ss;
632 ss <<
toStr(metaData->mDataType) <<
"_channel_" << i;
633 strncpy(metaData->mName, ss.str().c_str(), GridBlindMetaData::MaxNameSize-1);
636 this->copyValues(blindData, mValueCount);
640 SrcValueT *dst=blindData+r.begin(), *end=dst+r.size(), *src=dst-mValueCount;
641 while(dst!=end) *dst++ = *src++;
645 this->copyValues(blindData, mValueCount);
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
Defines two classes, a GridRegister the defines the value type (e.g. Double, Float etc) of a NanoVDB ...
#define NANOVDB_ASSERT(x)
Definition: NanoVDB.h:173
#define NANOVDB_MAGIC_NUMBER
Definition: NanoVDB.h:121
Custom Range class that is compatible with the tbb::blocked_range classes.
This class serves to manage a raw memory buffer of a NanoVDB Grid.
Definition: GridHandle.h:71
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition: NanoVDB.h:2556
DataType * data()
Definition: NanoVDB.h:2575
Allows for the construction of NanoVDB grids without any dependency.
Definition: IndexGridBuilder.h:36
uint64_t getValueCount() const
return the total number of values located in the source grid.
Definition: IndexGridBuilder.h:118
IndexGridBuilder(const SrcGridT &srcGrid, bool includeInactive=true, bool includeStats=true)
Constructor based on a source grid.
Definition: IndexGridBuilder.h:102
BufferT getValues(uint32_t channels=1u, const BufferT &buffer=BufferT())
return a buffer with all the values in the source grid
Definition: IndexGridBuilder.h:347
GridHandle< BufferT > getHandle(const std::string &name="", uint32_t channels=0u, const BufferT &buffer=BufferT())
Return an instance of a GridHandle (invoking move semantics)
Definition: IndexGridBuilder.h:133
uint64_t copyValues(SrcValueT *buffer, size_t maxValueCount=-1)
copy values from the source grid into the provided array and returns number of values copied
Definition: IndexGridBuilder.h:231
Internal nodes of a VDB treedim(),.
Definition: NanoVDB.h:3521
InternalData< ChildT, Log2Dim > DataType
Definition: NanoVDB.h:3523
const FloatType & average() const
Return a const reference to the average of all the active values encoded in this internal node and an...
Definition: NanoVDB.h:3623
DataType * data()
Definition: NanoVDB.h:3597
const FloatType & stdDeviation() const
Return a const reference to the standard deviation of all the active values encoded in this internal ...
Definition: NanoVDB.h:3629
const ValueType & maximum() const
Return a const reference to the maximum active value encoded in this internal node and any of its chi...
Definition: NanoVDB.h:3620
const ValueType & minimum() const
Return a const reference to the minimum active value encoded in this internal node and any of its chi...
Definition: NanoVDB.h:3617
ValueOnIterator beginValueOn() const
Definition: NanoVDB.h:3589
Leaf nodes of the VDB tree. (defaults to 8x8x8 = 512 voxels)
Definition: NanoVDB.h:4252
LeafData< BuildT, CoordT, MaskT, Log2Dim > DataType
Definition: NanoVDB.h:4261
DataType * data()
Definition: NanoVDB.h:4334
ValueType maximum() const
Return a const reference to the maximum active value encoded in this leaf node.
Definition: NanoVDB.h:4345
FloatType average() const
Return a const reference to the average of all the active values encoded in this leaf node.
Definition: NanoVDB.h:4348
ValueType minimum() const
Return a const reference to the minimum active value encoded in this leaf node.
Definition: NanoVDB.h:4342
ValueOnIterator beginValueOn() const
Definition: NanoVDB.h:4285
FloatType stdDeviation() const
Return a const reference to the standard deviation of all the active values encoded in this leaf node...
Definition: NanoVDB.h:4354
NodeManagerHandle manages the memory of a NodeManager.
Definition: NodeManager.h:55
NodeManager allows for sequential access to nodes.
Definition: NodeManager.h:189
uint64_t nodeCount(int level) const
Return the number of tree nodes at the specified level.
Definition: NodeManager.h:244
const Node2 & upper(uint32_t i) const
Return the i'th upper internal node with respect to breadth-first ordering.
Definition: NodeManager.h:283
const Node0 & leaf(uint32_t i) const
Return the i'th leaf node with respect to breadth-first ordering.
Definition: NodeManager.h:275
GridT & grid()
Return a reference to the grid.
Definition: NodeManager.h:231
RootT & root()
Return a reference to the root.
Definition: NodeManager.h:239
TreeT & tree()
Return a reference to the tree.
Definition: NodeManager.h:235
const Node1 & lower(uint32_t i) const
Return the i'th lower internal node with respect to breadth-first ordering.
Definition: NodeManager.h:279
Top-most node of the VDB tree structure.
Definition: NanoVDB.h:3074
VDB Tree, which is a thin wrapper around a RootNode.
Definition: NanoVDB.h:2799
Definition: NanoVDB.h:208
const char * toStr(GridType gridType)
Retuns a c-string used to describe a GridType.
Definition: NanoVDB.h:267
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition: ForEach.h:40
NodeManagerHandle< BufferT > createNodeManager(const NanoGrid< BuildT > &grid, const BufferT &buffer=BufferT())
brief Construct a NodeManager and return its handle
Definition: NodeManager.h:289
Range< 1, size_t > Range1D
Definition: Range.h:30
NodeManager produces linear arrays of all tree nodes allowing for efficient threading and bottom-up p...
uint64_t mMagic
Definition: NanoVDB.h:2434
Struct with all the member data of the InternalNode (useful during serialization of an openvdb Intern...
Definition: NanoVDB.h:3418
Stuct with all the member data of the LeafNode (useful during serialization of an openvdb LeafNode)
Definition: NanoVDB.h:3810