29#ifndef NANOVDB_OPENTONANOVDB_H_HAS_BEEN_INCLUDED
30#define NANOVDB_OPENTONANOVDB_H_HAS_BEEN_INCLUDED
42template<
typename BufferT = HostBuffer>
87 static_assert(
sizeof(
Type) ==
sizeof(openvdb::math::BBox<T>),
"Mismatching sizeof");
95 static_assert(
sizeof(
Type) ==
sizeof(openvdb::math::Vec3<T>),
"Mismatching sizeof");
103 static_assert(
sizeof(
Type) ==
sizeof(openvdb::math::Vec4<T>),
"Mismatching sizeof");
128template <
typename BuildT>
133 using RootT =
typename TreeT::RootNodeType;
134 using UpperT =
typename RootT::ChildNodeType;
135 using LowerT =
typename UpperT::ChildNodeType;
136 using LeafT =
typename LowerT::ChildNodeType;
137 using ValueT =
typename LeafT::ValueType;
144 using GridT = openvdb::tools::PointIndexGrid;
146 using RootT =
typename TreeT::RootNodeType;
147 using UpperT =
typename RootT::ChildNodeType;
148 using LowerT =
typename UpperT::ChildNodeType;
149 using LeafT =
typename LowerT::ChildNodeType;
150 using ValueT =
typename LeafT::ValueType;
157 using GridT = openvdb::points::PointDataGrid;
159 using RootT =
typename TreeT::RootNodeType;
160 using UpperT =
typename RootT::ChildNodeType;
161 using LowerT =
typename UpperT::ChildNodeType;
162 using LeafT =
typename LowerT::ChildNodeType;
163 using ValueT =
typename LeafT::ValueType;
181template<
typename OpenBuildT,
188 template <
typename NodeT>
struct NodePair;
189 struct Codec {
float min, max;
uint16_t log2, size;};
207 static_assert(
sizeof(NanoValueT) ==
sizeof(OpenValueT),
"Mismatching sizeof");
214 std::set<BlindMetaData> mBlindMetaData;
215 std::vector<NodePair<OpenLeafT >> mArray0;
216 std::vector<NodePair<OpenLowerT>> mArray1;
217 std::vector<NodePair<OpenUpperT>> mArray2;
218 std::unique_ptr<Codec[]> mCodec;
256 template <
typename T>
257 inline typename std::enable_if<!std::is_same<T, FpN>::value>::type
258 compression(
const OpenGridT&,
uint64_t&) {}
260 template <
typename T>
261 inline typename std::enable_if<std::is_same<T, FpN>::value>::type
262 compression(
const OpenGridT& openGrid, uint64_t &offset);
265 NanoGridT* processGrid(
const OpenGridT& openGrid);
268 NanoTreeT* processTree(
const OpenTreeT& openTree);
271 NanoRootT* processRoot(
const OpenRootT& openRoot);
273 template <
typename T>
274 void processNodes(std::vector<NodePair<T>> &nodes);
279 typename std::enable_if<!std::is_same<typename OpenGridType<openvdb::ValueMask>::LeafT,
typename T::OpenNodeT>
::value &&
280 !std::is_same<typename OpenGridType<bool>::LeafT,
typename T::OpenNodeT>
::value &&
281 !std::is_same<Fp4, typename T::NanoNodeT::BuildType>::value &&
282 !std::is_same<Fp8, typename T::NanoNodeT::BuildType>::value &&
283 !std::is_same<Fp16,typename T::NanoNodeT::BuildType>::value &&
284 !std::is_same<FpN, typename T::NanoNodeT::BuildType>::value>::type
285 processLeafs(std::vector<T> &leafs);
288 typename std::enable_if<std::is_same<Fp4, typename T::NanoNodeT::BuildType>::value ||
289 std::is_same<Fp8, typename T::NanoNodeT::BuildType>::value ||
290 std::is_same<Fp16, typename T::NanoNodeT::BuildType>::value>::type
291 processLeafs(std::vector<T> &leafs);
294 typename std::enable_if<std::is_same<FpN, typename T::NanoNodeT::BuildType>::value>::type
295 processLeafs(std::vector<T> &leafs);
298 typename std::enable_if<std::is_same<T, typename OpenGridType<openvdb::ValueMask>::LeafT>
::value>::type
299 processLeafs(std::vector<NodePair<T>> &leafs);
302 typename std::enable_if<std::is_same<T, typename OpenGridType<bool>::LeafT>
::value>::type
303 processLeafs(std::vector<NodePair<T>> &leafs);
308 template <
typename T>
309 typename std::enable_if<!std::is_same<T, openvdb::tools::PointIndexGrid>::value &&
310 !std::is_same<T, openvdb::points::PointDataGrid>::value>::type
311 preProcessMetadata(
const T& openGrid);
313 template <
typename T>
314 typename std::enable_if<std::is_same<T, openvdb::tools::PointIndexGrid>::value>::type
315 preProcessMetadata(
const T& openGrid);
317 template <
typename T>
318 typename std::enable_if<std::is_same<T, openvdb::points::PointDataGrid>::value>::type
319 preProcessMetadata(
const T& openGrid);
325 typename std::enable_if<!std::is_same<T, openvdb::tools::PointIndexGrid>::value &&
326 !std::is_same<T, openvdb::points::PointDataGrid>::value, GridBlindMetaData*>::type
327 processMetadata(
const T& openGrid);
330 typename std::enable_if<std::is_same<T, openvdb::tools::PointIndexGrid>::value, GridBlindMetaData*>::type
331 processMetadata(
const T& openGrid);
334 typename std::enable_if<std::is_same<T, openvdb::points::PointDataGrid>::value, GridBlindMetaData*>::type
335 processMetadata(
const T& openGrid);
339 uint64_t pointCount();
341 template<
typename AttT,
typename CodecT = openvdb::po
ints::UnknownCodec>
342 void copyPointAttribute(
size_t attIdx, AttT *attPtr);
346 template <
typename OpenNodeT,
typename NanoNodeT>
347 void encode(
const OpenNodeT *openNode, NanoNodeT *nanoNode);
352 template <
typename OpenNodeT>
353 typename NanoNode<NanoBuildT, OpenNodeT::LEVEL>::Type* decode(
const OpenNodeT *openNode);
359template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
371template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
380 this->setStats(
sMode);
381 this->setChecksum(
cMode);
388template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
395 std::unique_ptr<openvdb::util::CpuTimer>
timer(mVerbose > 1 ?
new openvdb::util::CpuTimer() :
nullptr);
397 if (
timer)
timer->start(
"Allocating memory for the NanoVDB buffer");
401 if (
timer)
timer->start(
"Processing leaf nodes");
402 this->processLeafs(mArray0);
405 if (
timer)
timer->start(
"Processing lower internal nodes");
406 this->processNodes(mArray1);
409 if (
timer)
timer->start(
"Processing upper internal nodes");
410 this->processNodes(mArray2);
413 if (
timer)
timer->start(
"Processing grid, tree and root node");
418 if (std::is_same<OpenBuildT, openvdb::PointIndex32>::value ||
419 std::is_same<OpenBuildT, openvdb::PointDataIndex32>::value) {
436template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
438inline typename std::enable_if<std::is_same<T, FpN>::value>::type
446 mOracle.setTolerance(0.1f *
float(
openGrid.voxelSize()[0]));
448 mOracle.setTolerance(0.01f);
450 mOracle.setTolerance(0.0f);
457 DitherLUT
lut(mDitherOn);
458 auto kernel = [&](
const auto &r) {
459 const OracleT oracle = mOracle;
460 for (
auto i=r.begin(); i!=r.end(); ++i) {
461 const float *
data = mArray0[i].node->
buffer().data();
462 float min = std::numeric_limits<float>::max(),
max = -
min;
463 for (
int j=0;
j<512; ++
j) {
470 const float range =
max -
min;
474 const float encode = mask/range;
475 const float decode = range/mask;
487 mCodec[i].size = NanoLeafT::DataType::memUsage(1u<<
logBitWidth);
495 for (
size_t i=1; i<
size; ++i) {
497 mArray0[i].offset = mArray0[i-1].offset + mCodec[i-1].size;
499 std::cout <<
"\n" << mOracle << std::endl;
500 std::cout <<
"Dithering: " << (mDitherOn ?
"enabled" :
"disabled") << std::endl;
504 avg += n *
float(1 << i);
505 printf(
"%2i bits: %6u leaf nodes, i.e. %4.1f%%\n",1<<i, n, 100.0f*n/
float(
size));
508 printf(
"%4.1f bits per value on average\n", avg/
float(
size));
510 for (
size_t i=1; i<
size; ++i) {
511 mArray0[i].offset = mArray0[i-1].offset + mCodec[i-1].size;
519template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
520GridHandle<BufferT> OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::
521 initHandle(
const OpenGridT& openGrid,
const BufferT& buffer)
529 std::vector<uint32_t> nodeCount =
openTree.nodeCount();
530 mArray0.reserve(nodeCount[0]);
531 mArray1.reserve(nodeCount[1]);
532 mArray2.reserve(nodeCount[2]);
536 mArray2.emplace_back(&(*
it2), offset[2]);
537 offset[2] += NanoUpperT::memUsage();
539 mArray1.emplace_back(&(*
it1), offset[1]);
540 offset[1] += NanoLowerT::memUsage();
542 mArray0.emplace_back(&(*
it0), offset[0]);
543 offset[0] +=
sizeof(NanoLeafT);
552 mBufferOffsets[0] = 0;
553 mBufferOffsets[1] = NanoGridT::memUsage();
554 mBufferOffsets[2] = NanoTreeT::memUsage();
555 mBufferOffsets[3] = NanoRootT::memUsage(
openTree.root().getTableSize());
556 mBufferOffsets[4] = offset[2];
557 mBufferOffsets[5] = offset[1];
558 mBufferOffsets[6] = offset[0];
560 mBufferOffsets[8] = 0;
561 for (
auto& i : mBlindMetaData) mBufferOffsets[8] += i.
size;
564 for (
int i = 2; i < 9; ++i) {
565 mBufferOffsets[i] += mBufferOffsets[i - 1];
569 std::cerr <<
"grid starts at " << mBufferOffsets[0] <<
" byte" << std::endl;
570 std::cerr <<
"tree starts at " << mBufferOffsets[1] <<
" byte" << std::endl;
571 std::cerr <<
"root starts at " << mBufferOffsets[2] <<
" byte" << std::endl;
572 std::cerr <<
"node starts at " << mBufferOffsets[3] <<
" byte" <<
" #" << mArray2.
size() << std::endl;
573 std::cerr <<
"node starts at " << mBufferOffsets[4] <<
" byte" <<
" #" << mArray1.
size() << std::endl;
574 std::cerr <<
"leaf starts at " << mBufferOffsets[5] <<
" byte" <<
" #" << mArray0.
size() << std::endl;
575 std::cerr <<
"meta starts at " << mBufferOffsets[6] <<
" byte" << std::endl;
576 std::cerr <<
"data starts at " << mBufferOffsets[7] <<
" byte" << std::endl;
577 std::cerr <<
"buffer ends at " << mBufferOffsets[8] <<
" byte" << std::endl;
578 std::cerr <<
"creating buffer of size " << (mBufferOffsets[8]>>20) <<
"MB" << std::endl;
590 std::memset(mBufferPtr+r.begin(),
'8', r.size());
599 openvdb::util::printBytes(std::cout, mBufferOffsets[8],
"Allocated",
" for the NanoVDB grid\n");
606template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
607NanoGrid<NanoBuildT>* OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::
608 processGrid(
const OpenGridT& openGrid)
610 auto *
nanoGrid =
reinterpret_cast<NanoGridT*
>(mBufferPtr + mBufferOffsets[0]);
611 if (!
openGrid.transform().baseMap()->isLinear()) {
615 const std::string gridName =
openGrid.getName();
619 data->mChecksum = 0u;
620 data->mVersion = Version();
622 data->mGridIndex = 0;
623 data->mGridCount = 1;
624 data->mGridSize = mBufferOffsets[8];
628 data->mBlindMetadataOffset = 0;
629 data->mBlindMetadataCount = 0;
632 data->setLongGridNameOn();
634 mDelta = NanoValueT(0);
640 mDelta = NanoValueT(
openGrid.voxelSize()[0]);
653 if (std::is_same<NanoBuildT, float>::value) {
655 }
else if (std::is_same<NanoBuildT, double>::value) {
657 }
else if (std::is_same<NanoBuildT, int16_t>::value) {
659 }
else if (std::is_same<NanoBuildT, int32_t>::value) {
661 }
else if (std::is_same<NanoBuildT, int64_t>::value) {
663 }
else if (std::is_same<NanoBuildT, Vec3f>::value) {
665 }
else if (std::is_same<OpenBuildT, openvdb::Index32>::value) {
667 }
else if (std::is_same<OpenBuildT, openvdb::PointIndex32>::value) {
670 }
else if (std::is_same<OpenBuildT, openvdb::PointDataIndex32>::value) {
673 }
else if (std::is_same<NanoBuildT, ValueMask>::value) {
676 }
else if (std::is_same<NanoBuildT, bool>::value) {
678 }
else if (std::is_same<NanoBuildT, Fp4>::value) {
680 }
else if (std::is_same<NanoBuildT, Fp8>::value) {
682 }
else if (std::is_same<NanoBuildT, Fp16>::value) {
684 }
else if (std::is_same<NanoBuildT, FpN>::value) {
686 }
else if (std::is_same<NanoBuildT, Vec4f>::value) {
688 }
else if (std::is_same<NanoBuildT, Vec4d>::value) {
701 data->mMap.set(mat, mat.inverse(), 1.0);
709 if (
auto size = mBlindMetaData.
size()) {
713 auto *blindData =
reinterpret_cast<char*
>(mBufferPtr + mBufferOffsets[7]);
722template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
723NanoTree<NanoBuildT>* OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::
724 processTree(
const OpenTreeT& openTree)
726 auto *
nanoTree =
reinterpret_cast<NanoTreeT*
>(mBufferPtr + mBufferOffsets[1]);
731 NanoUpperT *
nanoUpper = mArray2.empty() ?
nullptr :
reinterpret_cast<NanoUpperT*
>(mBufferPtr + mBufferOffsets[3]);
734 NanoLowerT *
nanoLower = mArray1.empty() ?
nullptr :
reinterpret_cast<NanoLowerT*
>(mBufferPtr + mBufferOffsets[4]);
737 NanoLeafT *
nanoLeaf = mArray0.empty() ?
nullptr :
reinterpret_cast<NanoLeafT*
>(mBufferPtr + mBufferOffsets[5]);
740 data->mNodeCount[0] =
static_cast<uint32_t>(mArray0.size());
741 data->mNodeCount[1] =
static_cast<uint32_t>(mArray1.size());
742 data->mNodeCount[2] =
static_cast<uint32_t>(mArray2.size());
748 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mArray1[i].node->getValueMask().countOn();
749 return sum;}, std::plus<uint32_t>());
753 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mArray2[i].node->getValueMask().countOn();
754 return sum;}, std::plus<uint32_t>());
759 data->mTileCount[2] = sum;
762 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mArray0[i].node->valueMask().countOn();
763 return sum;}, std::plus<uint64_t>());
765 data->mVoxelCount +=
data->mTileCount[0]*NanoLeafT::NUM_VALUES;
766 data->mVoxelCount +=
data->mTileCount[1]*NanoLowerT::NUM_VALUES;
767 data->mVoxelCount +=
data->mTileCount[2]*NanoUpperT::NUM_VALUES;
771 data->mTileCount[0] = 0;
772 data->mTileCount[1] = 0;
773 data->mTileCount[2] = 0;
774 data->mVoxelCount = 0;
783template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
784NanoRoot<NanoBuildT>* OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::
785 processRoot(
const OpenRootT& openRoot)
787 auto *
nanoRoot =
reinterpret_cast<NanoRootT*
>(mBufferPtr + mBufferOffsets[2]);
789 if (
data->padding()>0) {
791 std::memset(
data, 0, NanoRootT::memUsage(
openRoot.getTableSize()));
793 data->mTableSize = 0;
800 OpenValueT
value = openvdb::zeroVal<OpenValueT>();
801 for (
auto iter =
openRoot.cbeginChildAll(); iter; ++iter) {
802 auto* tile =
data->tile(
data->mTableSize++);
804 tile->setChild(iter.getCoord(), this->decode(
openChild),
data);
806 tile->setValue(iter.getCoord(), iter.isValueOn(),
value);
814template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
815template<
typename OpenNodeT>
821 static_assert(NanoNodeT::LEVEL == 1 || NanoNodeT::LEVEL == 2,
"Expected internal node");
823 uint8_t* ptr = mBufferPtr + mBufferOffsets[5 - NanoNodeT::LEVEL];
824 OpenValueT
value = openvdb::zeroVal<OpenValueT>();
825 for (
auto i = r.begin(); i != r.end(); ++i) {
829 if (NanoNodeT::DataType::padding()>0u) std::memset(
data, 0, NanoNodeT::DataType::memUsage());
833 for (
auto iter =
openNode->cbeginChildAll(); iter; ++iter) {
847template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
849inline typename std::enable_if<!std::is_same<typename OpenGridType<openvdb::ValueMask>::LeafT,
typename T::OpenNodeT>
::value &&
850 !std::is_same<typename OpenGridType<bool>::LeafT,
typename T::OpenNodeT>
::value &&
851 !std::is_same<Fp4, typename T::NanoNodeT::BuildType>::value &&
852 !std::is_same<Fp8, typename T::NanoNodeT::BuildType>::value &&
853 !std::is_same<Fp16,typename T::NanoNodeT::BuildType>::value &&
854 !std::is_same<FpN, typename T::NanoNodeT::BuildType>::value>::type
858 auto kernel = [&](
const auto& r) {
859 uint8_t* ptr = mBufferPtr + mBufferOffsets[5];
860 for (
auto i = r.begin(); i != r.end(); ++i) {
864 if (NanoLeafT::DataType::padding()>0u) {
865 std::memset(
data, 0, NanoLeafT::DataType::memUsage());
867 data->mFlags =
data->mBBoxDif[2] =
data->mBBoxDif[1] =
data->mBBoxDif[0] = 0u;
868 data->mMaximum =
data->mMinimum =
typename NanoLeafT::DataType::ValueType(0);
869 data->mStdDevi =
data->mAverage =
typename NanoLeafT::DataType::FloatType(0);
873 auto *
src =
reinterpret_cast<const NanoValueT*
>(
openLeaf->buffer().data());
874 for (NanoValueT *
dst =
data->mValues, *end =
dst + OpenLeafT::size();
dst != end;
dst += 4,
src += 4) {
887template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
889inline typename std::enable_if<std::is_same<Fp4, typename T::NanoNodeT::BuildType>::value ||
890 std::is_same<Fp8, typename T::NanoNodeT::BuildType>::value ||
891 std::is_same<Fp16, typename T::NanoNodeT::BuildType>::value>::type
892OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::processLeafs(std::vector<T>& openLeafs)
894 static_assert(NanoLeafT::DataType::padding()==0u,
"Expected no padding in LeafNode<Fp{4,8,16}>");
895 using ArrayT =
typename NanoLeafT::DataType::ArrayType;
896 using FloatT =
typename std::conditional<NanoLeafT::DataType::bitWidth()>=16,
double,
float>::type;
897 DitherLUT
lut(mDitherOn);
899 auto kernel = [&](
const auto& r) {
900 uint8_t* ptr = mBufferPtr + mBufferOffsets[5];
901 for (
auto i = r.begin(); i != r.end(); ++i) {
905 data->mFlags =
data->mBBoxDif[2] =
data->mBBoxDif[1] =
data->mBBoxDif[0] = 0u;
909 auto *
src =
reinterpret_cast<const float*
>(
openLeaf->buffer().data());
911 float min = std::numeric_limits<float>::max(),
max = -
min;
912 for (
int i=0; i<512; ++i) {
913 const float v =
src[i];
914 if (v < min)
min = v;
915 if (v > max)
max = v;
917 data->init(min, max, NanoLeafT::DataType::bitWidth());
922 if (std::is_same<Fp4, NanoBuildT>::value) {
923 for (
int i=0; i<128; ++i) {
930 for (
int i=0; i<128; ++i) {
944template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
946inline typename std::enable_if<std::is_same<FpN, typename T::NanoNodeT::BuildType>::value>::type
947OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::processLeafs(std::vector<T>& openLeafs)
950 static_assert(NanoLeafT::DataType::padding()==0u,
"Expected no padding in LeafNode<FpN>");
951 DitherLUT
lut(mDitherOn);
952 auto kernel = [&](
const auto& r) {
953 uint8_t* ptr = mBufferPtr + mBufferOffsets[5];
954 for (
auto i = r.begin(); i != r.end(); ++i) {
959 data->mBBoxDif[2] =
data->mBBoxDif[1] =
data->mBBoxDif[0] = 0u;
964 auto *
src =
reinterpret_cast<const float*
>(
openLeaf->buffer().data());
965 const float min = mCodec[i].min,
max = mCodec[i].max;
972 const float encode = 1.0f/(
max -
min);
973 for (
int j=0;
j<64; ++
j) {
975 for (
int k=0;
k<8; ++
k) {
984 const float encode = 3.0f/(
max -
min);
985 for (
int j=0;
j<128; ++
j) {
995 const float encode = 15.0f/(
max -
min);
996 for (
int j=0;
j<128; ++
j) {
1006 const float encode = 255.0f/(
max -
min);
1007 for (
int j=0;
j<128; ++
j) {
1017 const double encode = 65535.0/(
max -
min);
1018 for (
int j=0;
j<128; ++
j) {
1033template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1035inline typename std::enable_if<std::is_same<T, typename OpenGridType<bool>::LeafT>
::value>::type
1036OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::processLeafs(std::vector<NodePair<T>>& openLeafs)
1038 static_assert(NanoLeafT::DataType::padding()==0u,
"Expected no padding in LeafNode<bool>");
1039 auto kernel = [&](
const auto& r) {
1040 uint8_t* ptr = mBufferPtr + mBufferOffsets[5];
1041 for (
auto i = r.begin(); i != r.end(); ++i) {
1046 data->mFlags =
data->mBBoxDif[2] =
data->mBBoxDif[1] =
data->mBBoxDif[0] = 0u;
1049 data->mPadding[1] =
data->mPadding[0] = 0u;
1057template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1059inline typename std::enable_if<std::is_same<T, typename OpenGridType<openvdb::ValueMask>::LeafT>
::value>::type
1060OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::processLeafs(std::vector<NodePair<T>>& openLeafs)
1062 static_assert(NanoLeafT::DataType::padding()==0u,
"Expected no padding in LeafNode<ValueMask>");
1063 auto kernel = [&](
const auto& r) {
1064 uint8_t* ptr = mBufferPtr + mBufferOffsets[5];
1065 for (
auto i = r.begin(); i != r.end(); ++i) {
1070 data->mFlags =
data->mBBoxDif[2] =
data->mBBoxDif[1] =
data->mBBoxDif[0] = 0u;
1072 data->mPadding[1] =
data->mPadding[0] = 0u;
1080template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1081uint64_t OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::pointCount()
1084 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mArray0[i].node->getLastValue();
1085 return sum;}, std::plus<uint64_t>());
1092template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1093template <
typename OpenNodeT,
typename NanoNodeT>
1094inline void OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::
1095encode(
const OpenNodeT *openNode, NanoNodeT *nanoNode)
1108template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1109template <
typename OpenNodeT>
1110inline typename NanoNode<NanoBuildT, OpenNodeT::LEVEL>::Type* OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::
1111decode(
const OpenNodeT *openNode)
1113 using NanoNodeT =
typename NanoNode<NanoBuildT, OpenNodeT::LEVEL>::Type;
1125template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1126template <
typename NodeT>
1127struct OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::NodePair {
1128 using OpenNodeT = NodeT;
1129 using NanoNodeT =
typename NanoNode<NanoBuildT, OpenNodeT::LEVEL>::Type;
1130 NodePair(
const NodeT *ptr,
size_t n) : node(ptr), offset(n) {}
1137template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1140 BlindMetaData(
const std::string& n,
const std::string& t,
size_t i,
size_t c,
size_t s)
1155template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1156template <
typename T>
1157inline typename std::enable_if<!std::is_same<T, openvdb::tools::PointIndexGrid>::value &&
1158 !std::is_same<T, openvdb::points::PointDataGrid>::value>::type
1161 mBlindMetaData.clear();
1162 const size_t length =
openGrid.getName().length();
1164 mBlindMetaData.emplace(
"grid name",
"uint8_t", 0, 1, length + 1);
1170template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1171template <
typename T>
1172inline typename std::enable_if<std::is_same<T, openvdb::tools::PointIndexGrid>::value>::type
1173OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::preProcessMetadata(
const T& openGrid)
1175 mBlindMetaData.clear();
1177 mBlindMetaData.emplace(
"index",
"uint32_t", 0, pointCount,
sizeof(
uint32_t));
1179 const size_t length =
openGrid.getName().length();
1181 mBlindMetaData.emplace(
"grid name",
"uint8_t", mBlindMetaData.size(), 1, length + 1);
1187template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1188template <
typename T>
1189inline typename std::enable_if<std::is_same<T, openvdb::points::PointDataGrid>::value>::type
1190OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::preProcessMetadata(
const T& openGrid)
1192 mBlindMetaData.clear();
1196 const auto& attributeSet =
openLeaf->attributeSet();
1197 const auto& descriptor = attributeSet.descriptor();
1198 const auto&
nameMap = descriptor.map();
1200 const size_t index =
it->second;
1202 mBlindMetaData.emplace(
it->first, descriptor.valueType(index), index,
pointCount,
attArray.valueTypeSize());
1206 const size_t length =
openGrid.getName().length();
1208 mBlindMetaData.emplace(
"grid name",
"uint8_t",
counter, 1, length + 1);
1214template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1216inline typename std::enable_if<!std::is_same<T, openvdb::tools::PointIndexGrid>::value &&
1217 !std::is_same<T, openvdb::points::PointDataGrid>::value,GridBlindMetaData*>::type
1218OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::
1219 processMetadata(
const T& openGrid)
1221 if (mBlindMetaData.empty()) {
1224 assert(mBlindMetaData.size() == 1);
1225 auto it = mBlindMetaData.cbegin();
1226 assert(
it->name ==
"grid name" &&
it->typeName ==
"uint8_t" &&
it->index == 0);
1228 auto *
metaData =
reinterpret_cast<GridBlindMetaData*
>(mBufferPtr + mBufferOffsets[6]);
1229 auto *blindData =
reinterpret_cast<char*
>(mBufferPtr + mBufferOffsets[7]);
1244template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1246inline typename std::enable_if<std::is_same<T, openvdb::tools::PointIndexGrid>::value,GridBlindMetaData*>::type
1247OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::processMetadata(
const T& openGrid)
1249 if (mBlindMetaData.empty()) {
1252 assert(mBlindMetaData.size() == 1 || mBlindMetaData.size() == 2);
1253 auto *
metaData =
reinterpret_cast<GridBlindMetaData*
>(mBufferPtr + mBufferOffsets[6]);
1254 auto *blindData =
reinterpret_cast<char*
>(mBufferPtr + mBufferOffsets[7]);
1256 auto it = mBlindMetaData.cbegin();
1259 using LeafDataT =
typename NanoLeafT::DataType;
1260 uint8_t* ptr = mBufferPtr + mBufferOffsets[5];
1262 auto *
data0 =
reinterpret_cast<LeafDataT*
>(ptr + mArray0[0].offset);
1263 data0->mMinimum = 0;
1264 data0->mMaximum =
data0->mValues[NanoLeafT::SIZE - 1u];
1265 for (
uint32_t i = 1; i < leafCount; ++i) {
1266 auto *
data1 =
reinterpret_cast<LeafDataT*
>(ptr + mArray0[i].offset);
1268 data1->mMaximum =
data1->mValues[NanoLeafT::SIZE - 1u];
1274 assert(
it->name ==
"index" &&
it->typeName ==
"uint32_t" &&
it->index == 0);
1275 metaData[0].setBlindData( blindData );
1282 std::stringstream
ss;
1290 forEach(mArray0, 16, [&](
const auto& r) {
1291 for (
auto i = r.begin(); i != r.end(); ++i) {
1292 auto *
data =
reinterpret_cast<LeafDataT*
>(ptr + mArray0[i].offset);
1294 for (
uint32_t idx : mArray0[i].node->indices()) *
p++ = idx;
1301 if (
it != mBlindMetaData.end()) {
1302 assert(
it->name ==
"grid name" &&
it->typeName ==
"uint8_t" &&
it->index == 1);
1304 metaData[1].setBlindData( blindData );
1317template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1319inline typename std::enable_if<std::is_same<T, openvdb::points::PointDataGrid>::value,GridBlindMetaData*>::type
1320OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::processMetadata(
const T& openGrid)
1322 if (mBlindMetaData.empty()) {
1326 auto *
metaData =
reinterpret_cast<GridBlindMetaData*
>(mBufferPtr + mBufferOffsets[6]);
1327 auto *blindData =
reinterpret_cast<char*
>(mBufferPtr + mBufferOffsets[7]);
1331 using LeafDataT =
typename NanoLeafT::DataType;
1332 uint8_t* ptr = mBufferPtr + mBufferOffsets[5];
1334 auto *
data0 =
reinterpret_cast<LeafDataT*
>(ptr + mArray0[0].offset);
1335 data0->mMinimum = 0;
1336 data0->mMaximum =
data0->mValues[NanoLeafT::SIZE - 1u];
1337 for (
uint32_t i = 1; i < leafCount; ++i) {
1338 auto *
data1 =
reinterpret_cast<LeafDataT*
>(ptr + mArray0[i].offset);
1340 data1->mMaximum =
data1->mValues[NanoLeafT::SIZE - 1u];
1345 for (
auto it = mBlindMetaData.cbegin();
it != mBlindMetaData.end(); ++
it, ++i) {
1346 metaData[i].setBlindData( blindData );
1349 if (
it->name ==
"grid name") {
1359 std::stringstream
ss;
1366 if (
it->typeName ==
"vec3s") {
1369 if (
it->name ==
"P") {
1371 }
else if (
it->name ==
"V") {
1373 }
else if (
it->name ==
"Cd") {
1375 }
else if (
it->name ==
"N") {
1380 }
else if (
it->typeName ==
"int32") {
1382 this->copyPointAttribute(
it->index, (
int32_t*)blindData);
1383 if (
it->name ==
"id") {
1388 }
else if (
it->typeName ==
"int64") {
1390 this->copyPointAttribute(
it->index, (
int64_t*)blindData);
1391 if (
it->name ==
"id") {
1396 }
else if (
it->typeName ==
"float") {
1399 this->copyPointAttribute(
it->index, (
float*)blindData);
1401 std::stringstream
ss;
1402 ss <<
"Unsupported point attribute type: \"" <<
it->typeName <<
"\"";
1406 blindData +=
it->size;
1414template<
typename OpenBuildT,
typename NanoBuildT,
typename OracleT,
typename BufferT>
1415template<
typename AttT,
typename CodecT>
1416inline void OpenToNanoVDB<OpenBuildT, NanoBuildT, OracleT, BufferT>::
1417 copyPointAttribute(
size_t attIdx, AttT *attPtr)
1419 static_assert(std::is_same<typename OpenLeafT::ValueType, openvdb::PointDataIndex32>::value,
"Expected value to openvdb::PointData");
1420 using LeafDataT =
typename NanoLeafT::DataType;
1421 using HandleT = openvdb::points::AttributeHandle<AttT, CodecT>;
1422 forEach(mArray0, 16, [&](
const auto& r) {
1423 uint8_t* ptr = mBufferPtr + mBufferOffsets[5];
1424 for (
auto i = r.begin(); i != r.end(); ++i) {
1429 for (
auto iter =
openLeaf->beginIndexOn(); iter; ++iter) {
1438template<
typename BufferT,
typename OpenTreeT,
typename NanoBuildT>
1445 using OpenBuildT =
typename OpenTreeT::BuildType;
1452template<
typename BufferT>
1460 using openvdb_Vec4fTree =
typename openvdb::tree::Tree4<openvdb::Vec4f, 5, 4, 3>::Type;
1461 using openvdb_Vec4dTree =
typename openvdb::tree::Tree4<openvdb::Vec4d, 5, 4, 3>::Type;
1465 if (
auto grid = openvdb::GridBase::grid<openvdb::FloatGrid>(
base)) {
1467 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::DoubleGrid>(
base)) {
1469 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int32Grid>(
base)) {
1471 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int64Grid>(
base)) {
1475 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3fGrid>(
base)) {
1477 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3dGrid>(
base)) {
1479 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::tools::PointIndexGrid>(
base)) {
1481 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::points::PointDataGrid>(
base)) {
1483 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::MaskGrid>(
base)) {
1485 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::BoolGrid>(
base)) {
1487 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4fGrid>(
base)) {
1489 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4dGrid>(
base)) {
Defines look up table to do dithering of 8^3 leaf nodes.
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
Generates a NanoVDB grid from any volume or function.
ValueT value
Definition GridBuilder.h:1290
Computes a pair of 32bit checksums, og a Grid, by means of Cyclic Redundancy Check (CRC)
Defines two classes, a GridRegister the defines the value type (e.g. Double, Float etc) of a NanoVDB ...
Re-computes min/max/avg/var/bbox information for each node in a pre-existing NanoVDB grid.
A unified wrapper for tbb::parallel_invoke and a naive std::thread analog.
#define NANOVDB_DATA_ALIGNMENT
Definition NanoVDB.h:137
#define NANOVDB_MAGIC_NUMBER
Definition NanoVDB.h:121
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
A unified wrapper for tbb::parallel_reduce and a naive std::future analog.
Compression oracle based on absolute difference.
Definition GridBuilder.h:39
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition NanoVDB.h:967
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
void reset()
Definition DenseGrid.h:424
This is a buffer that contains a shared or private pool to either externally or internally managed ho...
Definition HostBuffer.h:115
This class will convert an OpenVDB grid into a NanoVDB grid managed by a GridHandle.
Definition OpenToNanoVDB.h:186
void setStats(StatsMode mode=StatsMode::Default)
Definition OpenToNanoVDB.h:237
void setChecksum(ChecksumMode mode=ChecksumMode::Default)
Definition OpenToNanoVDB.h:239
void enableDithering(bool on=true)
Definition OpenToNanoVDB.h:235
OracleT & oracle()
return a reference to the compression oracle
Definition OpenToNanoVDB.h:231
void setVerbose(int mode=1)
Definition OpenToNanoVDB.h:233
GridHandle< BufferT > operator()(const OpenGridT &grid, const BufferT &allocator=BufferT())
Return a shared pointer to a NanoVDB grid handle constructed from the specified OpenVDB grid.
Definition OpenToNanoVDB.h:391
OpenToNanoVDB()
Default c-tor.
Definition OpenToNanoVDB.h:360
Dummy type for a voxel whose value equals its binary active state.
Definition NanoVDB.h:216
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
_TreeType TreeType
Definition Grid.h:576
Definition Exceptions.h:63
Definition Exceptions.h:65
Axis-aligned bounding box of signed integer coordinates.
Definition Coord.h:249
Signed (x, y, z) 32-bit integer coordinates.
Definition Coord.h:25
static Coord min()
Return the smallest possible coordinate.
Definition Coord.h:43
static Coord max()
Return the largest possible coordinate.
Definition Coord.h:46
const Int32 * data() const
Definition Coord.h:139
uint64_t AlignUp(uint64_t byteCount)
round up byteSize to the nearest wordSize, e.g. to align to machine word: AlignUp<sizeof(size_t)(n)
Definition NanoVDB.h:954
static int64_t PtrDiff(const T1 *p, const T2 *q)
Definition NanoVDB.h:535
T reduce(RangeT range, const T &identity, const FuncT &func, const JoinT &join)
Definition Reduce.h:42
Vec3< double > Vec3R
Definition NanoVDB.h:1287
BBox< Coord > CoordBBox
Definition NanoVDB.h:1809
StatsMode
Grid flags which indicate what extra information is present in the grid buffer.
Definition GridStats.h:32
void updateChecksum(NanoGrid< ValueT > &grid, ChecksumMode mode=ChecksumMode::Default)
Updates the checksum of a grid.
Definition GridChecksum.h:277
void gridStats(NanoGrid< BuildT > &grid, StatsMode mode=StatsMode::Default)
Re-computes the min/max, stats and bbox information for an existing NanoVDB Grid.
Definition GridStats.h:713
ChecksumMode
List of different modes for computing for a checksum.
Definition GridChecksum.h:33
GridHandle< BufferT > openToNanoVDB(const openvdb::GridBase::Ptr &base, StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, int verbose=0)
Forward declaration of free-standing function that converts an OpenVDB GridBase into a NanoVDB GridHa...
Definition OpenToNanoVDB.h:1454
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition ForEach.h:40
Range< 1, size_t > Range1D
Definition Range.h:30
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
@ GRID_FOG_VOLUME
Definition Types.h:417
@ GRID_STAGGERED
Definition Types.h:418
@ GRID_LEVEL_SET
Definition Types.h:416
tree::Tree4< float, 5, 4, 3 >::Type FloatTree
Definition openvdb.h:55
Definition Exceptions.h:13
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
static const int MaxNameSize
Definition NanoVDB.h:2433
Trait to map from LEVEL to node type.
Definition NanoVDB.h:4567
typename LowerT::ChildNodeType LeafT
Definition OpenToNanoVDB.h:162
typename TreeT::RootNodeType RootT
Definition OpenToNanoVDB.h:159
typename GridT::TreeType TreeT
Definition OpenToNanoVDB.h:158
typename UpperT::ChildNodeType LowerT
Definition OpenToNanoVDB.h:161
typename RootT::ChildNodeType UpperT
Definition OpenToNanoVDB.h:160
openvdb::points::PointDataGrid GridT
Definition OpenToNanoVDB.h:157
typename LeafT::ValueType ValueT
Definition OpenToNanoVDB.h:163
typename LowerT::ChildNodeType LeafT
Definition OpenToNanoVDB.h:149
typename TreeT::RootNodeType RootT
Definition OpenToNanoVDB.h:146
typename GridT::TreeType TreeT
Definition OpenToNanoVDB.h:145
typename UpperT::ChildNodeType LowerT
Definition OpenToNanoVDB.h:148
typename RootT::ChildNodeType UpperT
Definition OpenToNanoVDB.h:147
typename LeafT::ValueType ValueT
Definition OpenToNanoVDB.h:150
openvdb::tools::PointIndexGrid GridT
Definition OpenToNanoVDB.h:144
Grid trait that defines OpenVDB grids with the exact same configuration as NanoVDB grids.
Definition OpenToNanoVDB.h:130
typename LowerT::ChildNodeType LeafT
Definition OpenToNanoVDB.h:136
typename TreeT::RootNodeType RootT
Definition OpenToNanoVDB.h:133
typename GridT::TreeType TreeT
Definition OpenToNanoVDB.h:132
typename UpperT::ChildNodeType LowerT
Definition OpenToNanoVDB.h:135
typename RootT::ChildNodeType UpperT
Definition OpenToNanoVDB.h:134
typename LeafT::ValueType ValueT
Definition OpenToNanoVDB.h:137
Converts OpenVDB types to NanoVDB types, e.g. openvdb::Vec3f to nanovdb::Vec3f Template specializatio...
Definition OpenToNanoVDB.h:37
T Type
Definition OpenToNanoVDB.h:37
static const bool value
Definition NanoVDB.h:415
C++11 implementation of std::is_same.
Definition NanoVDB.h:357
static constexpr bool value
Definition NanoVDB.h:358