16#ifndef NANOVDB_INDEXGRIDBUILDER_H_HAS_BEEN_INCLUDED
17#define NANOVDB_INDEXGRIDBUILDER_H_HAS_BEEN_INCLUDED
34template <
typename SrcValueT>
40 using SrcData0 =
typename SrcNode0::DataType;
41 using SrcData1 =
typename SrcNode1::DataType;
42 using SrcData2 =
typename SrcNode2::DataType;
59 std::vector<uint64_t> mValIdx2, mValIdx1, mValIdx0;
63 const bool mIsSparse, mIncludeStats;
76 template<
typename BufferT>
111 template<
typename BufferT = HostBuffer>
121 template<
typename BufferT = HostBuffer>
130template<
typename SrcValueT>
131template<
typename BufferT>
139 this->processLeafs();
141 this->processLower();
143 this->processUpper();
158template<
typename SrcValueT>
161 const uint64_t stats = mIncludeStats ? 4u : 0u;
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>
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();
246 SrcValueT *v = buffer + (mIncludeStats ? 5u : 1u);
257 DstData2 *
dstData = this->getUpper(r.begin())->
data();
258 for (
auto i = r.begin(); i != r.end(); ++i, ++
dstData) {
275 if (
srcData->mChildMask.isOn(
j))
continue;
287 DstData1 *
dstData = this->getLower(r.begin())->
data();
288 for (
auto i = r.begin(); i != r.end(); ++i, ++
dstData) {
305 if (
srcData->mChildMask.isOn(
j))
continue;
316 DstData0 *
dstLeaf = this->getLeaf(r.begin())->
data();
317 for (
auto i = r.begin(); i != r.end(); ++i, ++
dstLeaf) {
345template<
typename SrcValueT>
346template<
typename BufferT>
352 if (!this->copyValues(
p, mValueCount)) {
353 throw std::runtime_error(
"getValues: insufficient channels");
366template<
typename SrcValueT>
367template<
typename BufferT>
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);
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;
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++);
536 forEach(0, mSrcMgr->nodeCount(2), 1, kernel);
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++);
581 forEach(0, mSrcMgr->nodeCount(1), 4, kernel);
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];
613 forEach(0, mSrcMgr->nodeCount(0), 8, kernel);
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.
Definition DenseGrid.h:402
BufferT & buffer()
Definition DenseGrid.h:426
DenseGridHandle()=default
uint64_t size() const
Returns the size in bytes of the raw memory buffer managed by this DenseGridHandle's allocator.
Definition DenseGrid.h:440
uint8_t * data()
Returns a non-const pointer to the data.
Definition DenseGrid.h:432
const DenseGrid< ValueT > * grid() const
Returns a const pointer to the NanoVDB grid encoded in the DenseGridHandle.
Definition DenseGrid.h:447
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
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...