75#ifndef NANOVDB_CREATE_NANOGRID_H_HAS_BEEN_INCLUDED
76#define NANOVDB_CREATE_NANOGRID_H_HAS_BEEN_INCLUDED
78#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
100#include <type_traits>
105template <
typename>
class CreateNanoGrid;
107template <
typename>
struct MapToNano;
111#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
119template<
typename BufferT = HostBuffer>
121openToNanoVDB(
const openvdb::GridBase::ConstPtr& base,
139template<
typename SrcGridT,
141 typename BufferT = HostBuffer>
147 const BufferT &buffer = BufferT());
164template<
typename SrcGridT,
166 typename BufferT = HostBuffer>
167typename enable_if<BuildTraits<DstBuildT>::is_index, GridHandle<BufferT>>::type
169 uint32_t channels = 0u,
170 bool includeStats =
true,
171 bool includeTiles =
true,
173 const BufferT &buffer = BufferT());
190template<
typename SrcGridT,
192 typename OracleT = AbsDiff,
193 typename BufferT = HostBuffer>
194typename enable_if<is_same<FpN, DstBuildT>::value, GridHandle<BufferT>>::type
198 bool ditherOn =
false,
200 const OracleT &oracle = OracleT(),
201 const BufferT &buffer = BufferT());
216template<
typename SrcGridT,
218 typename BufferT = HostBuffer>
219typename enable_if<BuildTraits<DstBuildT>::is_FpX, GridHandle<BufferT>>::type
223 bool ditherOn =
false,
225 const BufferT &buffer = BufferT());
235 AbsDiff(
float tolerance = -1.0f) : mTolerance(tolerance) {}
238 operator bool()
const {
return mTolerance>=0.0f;}
241 static const float halfWidth = 3.0f;
242 mTolerance = 0.1f * background / halfWidth;
257 return Abs(exact - approx) <= mTolerance;
275 RelDiff(
float tolerance = -1.0f) : mTolerance(tolerance) {}
278 operator bool()
const {
return mTolerance>=0.0f;}
287 return Abs(exact - approx)/
Max(
Abs(exact),
Abs(approx)) <= mTolerance;
302template <
typename Gr
idT>
319 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
322 const std::string&
getName()
const {
return this->
grid().getName();};
334template <
typename BuildT>
350 , mMgr(*(mHandle.template mgr<BuildT>())) {}
354 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
357 std::string
getName()
const {
return std::string(this->
grid().gridName());};
373#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
387template <
typename BuildT>
388using OpenLeaf = openvdb::tree::LeafNode<BuildT,3>;
389template <
typename BuildT>
390using OpenLower = openvdb::tree::InternalNode<OpenLeaf<BuildT>,4>;
391template <
typename BuildT>
392using OpenUpper = openvdb::tree::InternalNode<OpenLower<BuildT>,5>;
393template <
typename BuildT>
394using OpenRoot = openvdb::tree::RootNode<OpenUpper<BuildT>>;
395template <
typename BuildT>
396using OpenTree = openvdb::tree::Tree<OpenRoot<BuildT>>;
397template <
typename BuildT>
403template <
typename BuildT>
404class NodeAccessor<OpenGrid<BuildT>>
411 using ValueType =
typename GridType::ValueType;
415 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
417 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
418 mMap.set(mat4, mat4.inverse());
423 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
426 std::string
getName()
const {
return this->
grid().getName(); };
443 build::NodeManager<GridType> mMgr;
451class NodeAccessor<
openvdb::tools::PointIndexGrid>
457 using GridType = openvdb::tools::PointIndexGrid;
458 using TreeType = openvdb::tools::PointIndexTree;
459 using RootType =
typename TreeType::RootNodeType;
460 using ValueType =
typename GridType::ValueType;
462 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
464 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
465 mMap.set(mat4, mat4.inverse());
470 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
473 std::string
getName()
const {
return this->
grid().getName(); };
478 build::NodeManager<GridType> mMgr;
486class NodeAccessor<
openvdb::points::PointDataGrid>
492 using GridType = openvdb::points::PointDataGrid;
493 using TreeType = openvdb::points::PointDataTree;
494 using RootType =
typename TreeType::RootNodeType;
495 using ValueType =
typename GridType::ValueType;
497 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
499 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
500 mMap.set(mat4, mat4.inverse());
505 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
508 std::string
getName()
const {
return this->
grid().getName(); };
513 build::NodeManager<GridType> mMgr;
522template <
typename SrcGr
idT>
566 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename BufferT =
HostBuffer>
569 getHandle(
const BufferT &buffer = BufferT());
579 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename OracleT =
AbsDiff,
typename BufferT =
HostBuffer>
581 getHandle(
const OracleT &oracle = OracleT(),
582 const BufferT &buffer = BufferT());
592 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename BufferT =
HostBuffer>
595 bool includeStats =
true,
596 bool includeTiles =
true,
597 const BufferT &buffer = BufferT());
611 size_t count,
size_t size)
613 const size_t order = mBlindMetaData.size();
614 mBlindMetaData.emplace(name, dataSemantic, dataClass, dataType, order, count, size);
621 uint64_t
valueCount()
const {
return mValIdx[0].empty() ? 0u : mValIdx[0].back();}
626 template <
typename DstBuildT>
634 template <
typename T,
int LEVEL>
636 dstNode(uint64_t i)
const {
637 static_assert(LEVEL==0 || LEVEL==1 || LEVEL==2,
"Expected LEVEL== {0,1,2}");
641 template <
typename T,
int LEVEL>
642 typename enable_if<is_same<T,FpN>::value && LEVEL==0,
NanoLeaf<FpN>*>::type
652 template <
typename DstBuildT>
656 template <
typename DstBuildT>
657 typename enable_if<BuildTraits<DstBuildT>::is_index>::type
658 preProcess(uint32_t channels);
660 template <
typename DstBuildT,
typename OracleT>
661 typename enable_if<is_same<FpN, DstBuildT>::value>::type
662 preProcess(OracleT oracle);
667 template<
typename DstBuildT,
typename BufferT>
668 GridHandle<BufferT> initHandle(
const BufferT& buffer);
672 template <
typename DstBuildT>
673 inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
674 postProcess(uint32_t channels);
676 template <
typename DstBuildT>
677 inline typename disable_if<BuildTraits<DstBuildT>::is_index>::type
682 template<
typename DstBuildT>
683 typename disable_if<BuildTraits<DstBuildT>::is_special>::type
686 template<
typename DstBuildT>
687 typename enable_if<BuildTraits<DstBuildT>::is_index>::type
690 template<
typename DstBuildT>
691 typename enable_if<BuildTraits<DstBuildT>::is_FpX>::type
694 template<
typename DstBuildT>
695 typename enable_if<is_same<FpN, DstBuildT>::value>::type
698 template<
typename DstBuildT>
699 typename enable_if<is_same<bool, DstBuildT>::value>::type
702 template<
typename DstBuildT>
703 typename enable_if<is_same<ValueMask, DstBuildT>::value>::type
708 template<
typename DstBuildT,
int LEVEL>
709 typename enable_if<BuildTraits<DstBuildT>::is_index>::type
710 processInternalNodes();
712 template<
typename DstBuildT,
int LEVEL>
713 typename enable_if<!BuildTraits<DstBuildT>::is_index>::type
714 processInternalNodes();
718 template <
typename DstBuildT>
719 typename enable_if<BuildTraits<DstBuildT>::is_index>::type
722 template <
typename DstBuildT>
723 typename enable_if<!BuildTraits<DstBuildT>::is_index>::type
728 template<
typename DstBuildT>
731 template<
typename DstBuildT>
734 template <
typename DstBuildT,
int LEVEL>
735 typename enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
738 template <
typename DstBuildT>
739 typename enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
742#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
743 template<
typename T = SrcGr
idT>
744 typename disable_if<is_same<T, openvdb::tools::PointIndexGrid>::value ||
748 template<
typename T = SrcGr
idT>
749 typename enable_if<is_same<T, openvdb::tools::PointIndexGrid>::value ||
753 template<
typename DstBuildT,
typename AttT,
typename CodecT = openvdb::po
ints::UnknownCodec,
typename T = SrcGr
idT>
754 typename enable_if<is_same<openvdb::points::PointDataGrid, T>::value>::type
755 copyPointAttribute(
size_t attIdx, AttT *attPtr);
757 uint64_t countPoints()
const {
return 0u;}
761 struct BufferOffsets {
762 uint64_t grid, tree, root, upper, lower, leaf, meta, blind, size;
763 uint64_t operator[](
int i)
const {
return *(
reinterpret_cast<const uint64_t*
>(
this)+i); }
766 uint64_t mLeafNodeSize;
768 std::unique_ptr<SrcNodeAccT> mSrcNodeAccPtr;
770 struct BlindMetaData;
771 std::set<BlindMetaData> mBlindMetaData;
772 struct Codec {
float min, max; uint64_t offset; uint8_t log2; };
773 std::unique_ptr<Codec[]> mCodec;
776 bool mDitherOn, mIncludeStats, mIncludeTiles;
777 std::vector<uint64_t> mValIdx[3];
782template <
typename SrcGr
idT>
786 , mSrcNodeAcc(*mSrcNodeAccPtr)
790 , mIncludeStats(true)
791 , mIncludeTiles(true)
797template <
typename SrcGr
idT>
800 , mSrcNodeAccPtr(nullptr)
801 , mSrcNodeAcc(srcNodeAcc)
805 , mIncludeStats(true)
806 , mIncludeTiles(true)
812template <
typename SrcGr
idT>
816 const std::string& type,
818 size_t i,
size_t valueCount,
size_t valueSize)
825 std::memcpy(metaData->mName, name.c_str(), name.length() + 1);
828 metaData->mDataClass = dataClass;
830 metaData->mValueSize = valueSize;
837 size_t i,
size_t valueCount,
size_t valueSize)
843 if (name.length()>=
GridData::MaxNameSize)
throw std::runtime_error(
"blind data name exceeds character limit");
844 std::memcpy(metaData->mName, name.c_str(), name.length() + 1);
846 metaData->mSemantic = dataSemantic;
847 metaData->mDataClass = dataClass;
848 metaData->mDataType = dataType;
849 metaData->mValueSize = valueSize;
857 if (
"uint32_t" == name) {
859 }
else if (
"float" == name) {
861 }
else if (
"vec3s"== name) {
863 }
else if (
"int32" == name) {
865 }
else if (
"int64" == name) {
875 }
else if (
"V" == name) {
877 }
else if (
"Cd" == name) {
879 }
else if (
"N" == name) {
881 }
else if (
"id" == name) {
892template <
typename SrcGr
idT>
893template<
typename DstBuildT,
typename BufferT>
898 this->
template preProcess<DstBuildT>();
899 auto handle = this->
template initHandle<DstBuildT>(pool);
900 this->
template postProcess<DstBuildT>();
906template <
typename SrcGr
idT>
907template<
typename DstBuildT,
typename OracleT,
typename BufferT>
911 this->
template preProcess<DstBuildT, OracleT>(oracle);
912 auto handle = this->
template initHandle<DstBuildT>(pool);
913 this->
template postProcess<DstBuildT>();
919template <
typename SrcGr
idT>
920template<
typename DstBuildT,
typename BufferT>
927 mIncludeStats = includeStats;
928 mIncludeTiles = includeTiles;
929 this->
template preProcess<DstBuildT>(channels);
930 auto handle = this->
template initHandle<DstBuildT>(pool);
931 this->
template postProcess<DstBuildT>(channels);
937template <
typename SrcGr
idT>
938template <
typename DstBuildT,
typename BufferT>
947 mOffset.meta = mOffset.leaf + mLeafNodeSize;
949 mOffset.size = mOffset.blind;
950 for (
const auto& b : mBlindMetaData) mOffset.size += b.size;
952 auto buffer = BufferT::create(mOffset.size, &pool);
953 mBufferPtr = buffer.data();
956 invoke( [&](){this->
template processLeafs<DstBuildT>();},
957 [&](){this->
template processInternalNodes<DstBuildT, 1>();},
958 [&](){this->
template processInternalNodes<DstBuildT, 2>();},
959 [&](){this->
template processRoot<DstBuildT>();},
960 [&](){this->
template processTree<DstBuildT>();},
961 [&](){this->
template processGrid<DstBuildT>();} );
963 return GridHandle<BufferT>(std::move(buffer));
968template <
typename SrcGr
idT>
969template <
typename DstBuildT>
971CreateNanoGrid<SrcGridT>::preProcess()
973 if (
const uint64_t pointCount = this->countPoints()) {
974#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
976 if (!mBlindMetaData.empty())
throw std::runtime_error(
"expected no blind meta data");
977 this->addBlindData(
"index",
984 if (!mBlindMetaData.empty())
throw std::runtime_error(
"expected no blind meta data");
985 auto &srcLeaf = mSrcNodeAcc.template node<0>(0);
986 const auto& attributeSet = srcLeaf.attributeSet();
987 const auto& descriptor = attributeSet.descriptor();
988 const auto& nameMap = descriptor.map();
989 for (
auto it = nameMap.begin(); it != nameMap.end(); ++it) {
990 const size_t index = it->second;
991 auto& attArray = srcLeaf.constAttributeArray(index);
992 mBlindMetaData.emplace(it->first,
993 descriptor.valueType(index),
997 attArray.valueTypeSize());
1002 if (mSrcNodeAcc.hasLongGridName()) {
1003 this->addBlindData(
"grid name",
1007 mSrcNodeAcc.getName().length() + 1, 1);
1014template <
typename SrcGr
idT>
1015template <
typename DstBuildT,
typename OracleT>
1016inline typename enable_if<is_same<FpN, DstBuildT>::value>::type
1017CreateNanoGrid<SrcGridT>::preProcess(OracleT oracle)
1021 const size_t leafCount = mSrcNodeAcc.nodeCount(0);
1026 mCodec.reset(
new Codec[leafCount]);
1029 if (!oracle) oracle.init(mSrcNodeAcc.gridClass(), mSrcNodeAcc.root().background());
1032 DitherLUT lut(mDitherOn);
1034 for (
auto i=r.begin(); i!=r.end(); ++i) {
1035 const auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1036 float &
min = mCodec[i].min = std::numeric_limits<float>::max();
1037 float &
max = mCodec[i].max = -
min;
1038 for (
int j=0; j<512; ++j) {
1039 float v = srcLeaf.getValue(j);
1043 const float range =
max -
min;
1044 uint8_t &logBitWidth = mCodec[i].log2 = 0;
1045 while (range > 0.0f && logBitWidth < 4u) {
1046 const uint32_t mask = (uint32_t(1) << (uint32_t(1) << logBitWidth)) - 1u;
1047 const float encode = mask/range;
1048 const float decode = range/mask;
1051 const float exact = srcLeaf.getValue(j);
1052 const uint32_t code = uint32_t(encode*(exact - min) + lut(j));
1053 const float approx = code * decode +
min;
1054 j += oracle(exact, approx) ? 1 : 513;
1056 if (j == 512)
break;
1062 auto getOffset = [&](
size_t i){
1071 for (
size_t i=1; i<leafCount; ++i) mCodec[i].offset = getOffset(i);
1072 mLeafNodeSize = getOffset(leafCount);
1075 uint32_t counters[5+1] = {0};
1076 ++counters[mCodec[0].log2];
1077 for (
size_t i=1; i<leafCount; ++i) ++counters[mCodec[i].log2];
1078 std::cout <<
"\n" << oracle << std::endl;
1079 std::cout <<
"Dithering: " << (mDitherOn ?
"enabled" :
"disabled") << std::endl;
1081 for (uint32_t i=0; i<=5; ++i) {
1082 if (uint32_t n = counters[i]) {
1083 avg += n * float(1 << i);
1084 printf(
"%2i bits: %6u leaf nodes, i.e. %4.1f%%\n",1<<i, n, 100.0f*n/
float(leafCount));
1087 printf(
"%4.1f bits per value on average\n", avg/
float(leafCount));
1090 if (mSrcNodeAcc.hasLongGridName()) {
1091 this->addBlindData(
"grid name",
1095 mSrcNodeAcc.getName().length() + 1, 1);
1101template <
typename SrcGr
idT>
1102template <
typename DstBuildT,
int LEVEL>
1103inline typename enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
1104CreateNanoGrid<SrcGridT>::countTileValues(uint64_t valueCount)
1106 const uint64_t stats = mIncludeStats ? 4u : 0u;
1107 mValIdx[LEVEL].clear();
1108 mValIdx[LEVEL].resize(mSrcNodeAcc.nodeCount(LEVEL) + 1, stats);
1110 for (
auto i = r.begin(); i!=r.end(); ++i) {
1111 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(i-1);
1113 mValIdx[LEVEL][i] += srcNode.getValueMask().countOn();
1115 static const uint64_t maxTileCount = uint64_t(1u) << 3*srcNode.LOG2DIM;
1116 mValIdx[LEVEL][i] += maxTileCount - srcNode.getChildMask().countOn();
1120 mValIdx[LEVEL][0] = valueCount;
1121 for (
size_t i=1; i<mValIdx[LEVEL].size(); ++i) mValIdx[LEVEL][i] += mValIdx[LEVEL][i-1];
1122 return mValIdx[LEVEL].back();
1127template <
typename SrcGr
idT>
1128template <
typename DstBuildT>
1129inline typename enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
1130CreateNanoGrid<SrcGridT>::countValues()
1132 const uint64_t stats = mIncludeStats ? 4u : 0u;
1133 uint64_t valueCount = 1u;
1134 if (mIncludeTiles) {
1136 for (
auto it = mSrcNodeAcc.root().cbeginValueOn(); it; ++it) ++valueCount;
1138 for (
auto it = mSrcNodeAcc.root().cbeginValueAll(); it; ++it) ++valueCount;
1140 valueCount += stats;
1141 valueCount = countTileValues<DstBuildT, 2>(valueCount);
1142 valueCount = countTileValues<DstBuildT, 1>(valueCount);
1145 mValIdx[0].resize(mSrcNodeAcc.nodeCount(0) + 1, 512u + stats);
1148 for (
auto i = r.begin(); i != r.end(); ++i) {
1149 mValIdx[0][i] = stats;
1150 mValIdx[0][i] += mSrcNodeAcc.template node<0>(i-1).getValueMask().countOn();
1154 mValIdx[0][0] = valueCount;
1156 return mValIdx[0].back();
1161template <
typename SrcGr
idT>
1162template <
typename DstBuildT>
1163inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1164CreateNanoGrid<SrcGridT>::preProcess(uint32_t channels)
1166 const uint64_t valueCount = this->
template countValues<DstBuildT>();
1169 uint32_t order = mBlindMetaData.size();
1170 for (uint32_t i=0; i<channels; ++i) {
1171 mBlindMetaData.emplace(
"channel_"+std::to_string(i),
1178 if (mSrcNodeAcc.hasLongGridName()) {
1179 this->addBlindData(
"grid name",
1183 mSrcNodeAcc.getName().length() + 1, 1);
1189template <
typename SrcGr
idT>
1190template <
typename DstBuildT>
1191inline typename disable_if<BuildTraits<DstBuildT>::is_special>::type
1192CreateNanoGrid<SrcGridT>::processLeafs()
1195 using DstValueT =
typename DstDataT::ValueType;
1196 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<T> to have fixed size");
1198 auto *dstData = this->template dstNode<DstBuildT,0>(r.begin())->data();
1199 for (auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1200 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1201 if (DstDataT::padding()>0u) {
1203 std::memset(reinterpret_cast<void*>(dstData), 0, DstDataT::memUsage());
1205 dstData->mBBoxDif[0] = dstData->mBBoxDif[1] = dstData->mBBoxDif[2] = 0u;
1206 dstData->mFlags = 0u;
1207 dstData->mMinimum = dstData->mMaximum = typename DstDataT::ValueType();
1208 dstData->mAverage = dstData->mStdDevi = 0;
1210 dstData->mBBoxMin = srcLeaf.origin();
1211 dstData->mValueMask = srcLeaf.getValueMask();
1212 DstValueT *dst = dstData->mValues;
1213 if constexpr(is_same<DstValueT, SrcValueT>::value && SrcNodeAccT::IS_OPENVDB) {
1214 const SrcValueT *src = srcLeaf.buffer().data();
1215 for (auto *end = dst + 512u; dst != end; dst += 4, src += 4) {
1222 for (uint32_t j=0; j<512u; ++j) *dst++ = static_cast<DstValueT>(srcLeaf.getValue(j));
1230template <
typename SrcGr
idT>
1231template <
typename DstBuildT>
1232inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1233CreateNanoGrid<SrcGridT>::processLeafs()
1235 using DstDataT =
typename NanoLeaf<DstBuildT>::DataType;
1236 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<ValueIndex> to have fixed size");
1237 static_assert(DstDataT::padding()==0u,
"Expected leaf nodes to have no padding");
1239 forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const Range1D& r) {
1240 const uint8_t flags = mIncludeStats ? 16u : 0u;
1241 DstDataT *dstData = this->template dstNode<DstBuildT,0>(r.begin())->data();
1242 for (auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1243 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1244 dstData->mBBoxMin = srcLeaf.origin();
1245 dstData->mBBoxDif[0] = dstData->mBBoxDif[1] = dstData->mBBoxDif[2] = 0u;
1246 dstData->mFlags = flags;
1247 dstData->mValueMask = srcLeaf.getValueMask();
1248 dstData->mOffset = mValIdx[0][i];
1249 if constexpr(BuildTraits<DstBuildT>::is_onindex) {
1250 const uint64_t *w = dstData->mValueMask.words();
1251#ifdef USE_OLD_VALUE_ON_INDEX
1252 int32_t sum = CountOn(*w++);
1253 uint8_t *p = reinterpret_cast<uint8_t*>(&dstData->mPrefixSum), *q = p + 7;
1254 for (int j=0; j<7; ++j) {
1256 *q |= (sum >> 8) << j;
1257 sum += CountOn(*w++);
1260 uint64_t &prefixSum = dstData->mPrefixSum, sum = CountOn(*w++);
1262 for (int n = 9; n < 55; n += 9) {
1263 sum += CountOn(*w++);
1264 prefixSum |= sum << n;
1268 dstData->mPrefixSum = 0u;
1270 if constexpr(BuildTraits<DstBuildT>::is_indexmask) dstData->mMask = dstData->mValueMask;
1277template <
typename SrcGr
idT>
1278template <
typename DstBuildT>
1279inline typename enable_if<is_same<ValueMask, DstBuildT>::value>::type
1280CreateNanoGrid<SrcGridT>::processLeafs()
1282 using DstDataT =
typename NanoLeaf<ValueMask>::DataType;
1283 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<ValueMask> to have fixed size");
1284 forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const Range1D& r) {
1285 auto *dstData = this->template dstNode<DstBuildT,0>(r.begin())->data();
1286 for (auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1287 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1288 if (DstDataT::padding()>0u) {
1290 std::memset(reinterpret_cast<void*>(dstData), 0, DstDataT::memUsage());
1292 dstData->mBBoxDif[0] = dstData->mBBoxDif[1] = dstData->mBBoxDif[2] = 0u;
1293 dstData->mFlags = 0u;
1294 dstData->mPadding[0] = dstData->mPadding[1] = 0u;
1296 dstData->mBBoxMin = srcLeaf.origin();
1297 dstData->mValueMask = srcLeaf.getValueMask();
1304template <
typename SrcGr
idT>
1305template <
typename DstBuildT>
1306inline typename enable_if<is_same<bool, DstBuildT>::value>::type
1307CreateNanoGrid<SrcGridT>::processLeafs()
1309 using DstDataT =
typename NanoLeaf<bool>::DataType;
1310 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<bool> to have fixed size");
1311 forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const Range1D& r) {
1312 auto *dstData = this->template dstNode<DstBuildT,0>(r.begin())->data();
1313 for (auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1314 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1315 if (DstDataT::padding()>0u) {
1317 std::memset(reinterpret_cast<void*>(dstData), 0, DstDataT::memUsage());
1319 dstData->mBBoxDif[0] = dstData->mBBoxDif[1] = dstData->mBBoxDif[2] = 0u;
1320 dstData->mFlags = 0u;
1322 dstData->mBBoxMin = srcLeaf.origin();
1323 dstData->mValueMask = srcLeaf.getValueMask();
1324 if constexpr(!is_same<bool, SrcBuildT>::value) {
1325 for (int j=0; j<512; ++j) dstData->mValues.set(j, static_cast<bool>(srcLeaf.getValue(j)));
1326 } else if constexpr(SrcNodeAccT::IS_OPENVDB) {
1327 dstData->mValues = *reinterpret_cast<const Mask<3>*>(srcLeaf.buffer().data());
1328 } else if constexpr(SrcNodeAccT::IS_NANOVDB) {
1329 dstData->mValues = srcLeaf.data()->mValues;
1331 dstData->mValues = srcLeaf.mValues;
1339template <
typename SrcGr
idT>
1340template <
typename DstBuildT>
1341inline typename enable_if<BuildTraits<DstBuildT>::is_FpX>::type
1342CreateNanoGrid<SrcGridT>::processLeafs()
1344 using DstDataT =
typename NanoLeaf<DstBuildT>::DataType;
1345 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<Fp4|Fp8|Fp16> to have fixed size");
1346 using ArrayT =
typename DstDataT::ArrayType;
1347 static_assert(is_same<float, SrcValueT>::value,
"Expected ValueT == float");
1348 using FloatT =
typename std::conditional<DstDataT::bitWidth()>=16, double,
float>::type;
1349 static constexpr FloatT UNITS = FloatT((1 << DstDataT::bitWidth()) - 1);
1350 DitherLUT lut(mDitherOn);
1352 forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const Range1D& r) {
1353 auto *dstData = this->template dstNode<DstBuildT,0>(r.begin())->data();
1354 for (auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1355 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1356 if (DstDataT::padding()>0u) {
1358 std::memset(reinterpret_cast<void*>(dstData), 0, DstDataT::memUsage());
1360 dstData->mFlags = dstData->mBBoxDif[2] = dstData->mBBoxDif[1] = dstData->mBBoxDif[0] = 0u;
1361 dstData->mDev = dstData->mAvg = dstData->mMax = dstData->mMin = 0u;
1363 dstData->mBBoxMin = srcLeaf.origin();
1364 dstData->mValueMask = srcLeaf.getValueMask();
1366 float min = std::numeric_limits<float>::max(), max = -min;
1367 for (uint32_t j=0; j<512u; ++j) {
1368 const float v = srcLeaf.getValue(j);
1369 if (v < min) min = v;
1370 if (v > max) max = v;
1372 dstData->init(min, max, DstDataT::bitWidth());
1374 const FloatT encode = UNITS/(max-min);
1375 uint32_t offset = 0;
1376 auto quantize = [&]()->ArrayT{
1377 const ArrayT tmp = static_cast<ArrayT>(encode * (srcLeaf.getValue(offset) - min) + lut(offset));
1381 auto *code = reinterpret_cast<ArrayT*>(dstData->mCode);
1382 if (is_same<Fp4, DstBuildT>::value) {
1383 for (uint32_t j=0; j<128u; ++j) {
1384 auto tmp = quantize();
1385 *code++ = quantize() << 4 | tmp;
1387 *code++ = quantize() << 4 | tmp;
1390 for (uint32_t j=0; j<128u; ++j) {
1391 *code++ = quantize();
1392 *code++ = quantize();
1393 *code++ = quantize();
1394 *code++ = quantize();
1403template <
typename SrcGr
idT>
1404template <
typename DstBuildT>
1405inline typename enable_if<is_same<FpN, DstBuildT>::value>::type
1406CreateNanoGrid<SrcGridT>::processLeafs()
1408 static_assert(is_same<float, SrcValueT>::value,
"Expected SrcValueT == float");
1409 DitherLUT lut(mDitherOn);
1410 forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const Range1D& r) {
1411 for (auto i = r.begin(); i != r.end(); ++i) {
1412 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1413 auto *dstData = this->template dstNode<DstBuildT,0>(i)->data();
1414 dstData->mBBoxMin = srcLeaf.origin();
1415 dstData->mBBoxDif[0] = dstData->mBBoxDif[1] = dstData->mBBoxDif[2] = 0u;
1416 const uint8_t logBitWidth = mCodec[i].log2;
1417 dstData->mFlags = logBitWidth << 5;
1418 dstData->mValueMask = srcLeaf.getValueMask();
1419 const float min = mCodec[i].min, max = mCodec[i].max;
1420 dstData->init(min, max, uint8_t(1) << logBitWidth);
1422 uint32_t offset = 0;
1423 float encode = 0.0f;
1424 auto quantize = [&]()->uint8_t{
1425 const uint8_t tmp = static_cast<uint8_t>(encode * (srcLeaf.getValue(offset) - min) + lut(offset));
1429 auto *dst = reinterpret_cast<uint8_t*>(dstData+1);
1430 switch (logBitWidth) {
1432 encode = 1.0f/(max - min);
1433 for (int j=0; j<64; ++j) {
1435 for (int k=0; k<8; ++k) a |= quantize() << k;
1441 encode = 3.0f/(max - min);
1442 for (int j=0; j<128; ++j) {
1443 auto a = quantize();
1444 a |= quantize() << 2;
1445 a |= quantize() << 4;
1446 *dst++ = quantize() << 6 | a;
1451 encode = 15.0f/(max - min);
1452 for (int j=0; j<128; ++j) {
1453 auto a = quantize();
1454 *dst++ = quantize() << 4 | a;
1456 *dst++ = quantize() << 4 | a;
1461 encode = 255.0f/(max - min);
1462 for (int j=0; j<128; ++j) {
1463 *dst++ = quantize();
1464 *dst++ = quantize();
1465 *dst++ = quantize();
1466 *dst++ = quantize();
1471 auto *dst = reinterpret_cast<uint16_t*>(dstData+1);
1472 const double encode = 65535.0/(max - min);
1473 for (int j=0; j<128; ++j) {
1474 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1475 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1476 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1477 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1487template <
typename SrcGr
idT>
1488template <
typename DstBuildT,
int LEVEL>
1489inline typename enable_if<!BuildTraits<DstBuildT>::is_index>::type
1490CreateNanoGrid<SrcGridT>::processInternalNodes()
1492 using DstNodeT =
typename NanoNode<DstBuildT, LEVEL>::type;
1493 using DstValueT =
typename DstNodeT::ValueType;
1494 using DstChildT =
typename NanoNode<DstBuildT, LEVEL-1>::type;
1495 static_assert(LEVEL == 1 || LEVEL == 2,
"Expected internal node");
1497 const uint64_t nodeCount = mSrcNodeAcc.nodeCount(LEVEL);
1498 if (nodeCount > 0) {
1499 uint64_t childCount = 0;
1500 auto *dstData = this->
template dstNode<DstBuildT,LEVEL>(0)->data();
1501 for (uint64_t i=0; i<nodeCount; ++i) {
1502 dstData[i].mFlags = childCount;
1503 childCount += mSrcNodeAcc.template node<LEVEL>(i).getChildMask().countOn();
1507 forEach(0, nodeCount, 4, [&](
const Range1D& r) {
1508 auto *dstData = this->
template dstNode<DstBuildT,LEVEL>(r.begin())->data();
1509 for (
auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1510 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(i);
1511 uint64_t childID = dstData->mFlags;
1512 if (DstNodeT::DataType::padding()>0u) {
1514 std::memset(
reinterpret_cast<void*
>(dstData), 0, DstNodeT::memUsage());
1516 dstData->mFlags = 0;
1517 dstData->mMinimum = dstData->mMaximum =
typename DstNodeT::ValueType();
1518 dstData->mAverage = dstData->mStdDevi = 0;
1520 dstData->mBBox[0] = srcNode.origin();
1521 dstData->mValueMask = srcNode.getValueMask();
1522 dstData->mChildMask = srcNode.getChildMask();
1523 for (
auto it = srcNode.cbeginChildAll(); it; ++it) {
1525 if (it.probeChild(value)) {
1526 DstChildT *dstChild = this->
template dstNode<DstBuildT,LEVEL-1>(childID++);
1527 dstData->setChild(it.pos(), dstChild);
1529 dstData->setValue(it.pos(),
static_cast<DstValueT
>(value));
1538template <
typename SrcGr
idT>
1539template <
typename DstBuildT,
int LEVEL>
1540inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1541CreateNanoGrid<SrcGridT>::processInternalNodes()
1543 using DstNodeT =
typename NanoNode<DstBuildT, LEVEL>::type;
1544 using DstChildT =
typename NanoNode<DstBuildT, LEVEL-1>::type;
1545 static_assert(LEVEL == 1 || LEVEL == 2,
"Expected internal node");
1546 static_assert(DstNodeT::DataType::padding()==0u,
"Expected internal nodes to have no padding");
1548 const uint64_t nodeCount = mSrcNodeAcc.nodeCount(LEVEL);
1549 if (nodeCount > 0) {
1550 uint64_t childCount = 0;
1551 auto *dstData = this->
template dstNode<DstBuildT,LEVEL>(0)->data();
1552 for (uint64_t i=0; i<nodeCount; ++i) {
1553 dstData[i].mFlags = childCount;
1554 childCount += mSrcNodeAcc.template node<LEVEL>(i).getChildMask().countOn();
1558 forEach(0, nodeCount, 4, [&](
const Range1D& r) {
1559 auto *dstData = this->
template dstNode<DstBuildT,LEVEL>(r.begin())->data();
1560 for (
auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1561 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(i);
1562 uint64_t childID = dstData->mFlags;
1563 dstData->mFlags = 0u;
1564 dstData->mBBox[0] = srcNode.origin();
1565 dstData->mValueMask = srcNode.getValueMask();
1566 dstData->mChildMask = srcNode.getChildMask();
1567 uint64_t n = mIncludeTiles ? mValIdx[LEVEL][i] : 0u;
1568 for (
auto it = srcNode.cbeginChildAll(); it; ++it) {
1570 if (it.probeChild(value)) {
1571 DstChildT *dstChild = this->
template dstNode<DstBuildT,LEVEL-1>(childID++);
1572 dstData->setChild(it.pos(), dstChild);
1575 if (mIncludeTiles && !((BuildTraits<DstBuildT>::is_onindex) && dstData->mValueMask.isOff(it.pos()))) m = n++;
1576 dstData->setValue(it.pos(), m);
1579 if (mIncludeTiles && mIncludeStats) {
1580 dstData->mMinimum = n++;
1581 dstData->mMaximum = n++;
1582 dstData->mAverage = n++;
1583 dstData->mStdDevi = n++;
1585 dstData->mMinimum = 0u;
1586 dstData->mMaximum = 0u;
1587 dstData->mAverage = 0u;
1588 dstData->mStdDevi = 0u;
1596template <
typename SrcGr
idT>
1597template <
typename DstBuildT>
1598inline typename enable_if<!BuildTraits<DstBuildT>::is_index>::type
1599CreateNanoGrid<SrcGridT>::processRoot()
1601 using DstRootT = NanoRoot<DstBuildT>;
1602 using DstValueT =
typename DstRootT::ValueType;
1603 auto &srcRoot = mSrcNodeAcc.root();
1604 auto *dstData = this->
template dstRoot<DstBuildT>()->data();
1605 const uint32_t tableSize = srcRoot.getTableSize();
1607 if (DstRootT::DataType::padding()>0) std::memset(
reinterpret_cast<void*
>(dstData), 0, DstRootT::memUsage(tableSize));
1608 dstData->mTableSize = tableSize;
1609 dstData->mMinimum = dstData->mMaximum = dstData->mBackground = srcRoot.background();
1611 if (tableSize==0)
return;
1612 auto *dstChild = this->
template dstNode<DstBuildT, 2>(0);
1613 auto *dstTile = dstData->tile(0);
1614 for (
auto it = srcRoot.cbeginChildAll(); it; ++it, ++dstTile) {
1616 if (it.probeChild(value)) {
1617 dstTile->setChild(it.getCoord(), dstChild++, dstData);
1619 dstTile->setValue(it.getCoord(), it.isValueOn(),
static_cast<DstValueT
>(value));
1626template <
typename SrcGr
idT>
1627template <
typename DstBuildT>
1628inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1629CreateNanoGrid<SrcGridT>::processRoot()
1631 using DstRootT = NanoRoot<DstBuildT>;
1632 auto &srcRoot = mSrcNodeAcc.root();
1633 auto *dstData = this->
template dstRoot<DstBuildT>()->data();
1634 const uint32_t tableSize = srcRoot.getTableSize();
1636 if (DstRootT::DataType::padding()>0) std::memset(
reinterpret_cast<void*
>(dstData), 0, DstRootT::memUsage(tableSize));
1637 dstData->mTableSize = tableSize;
1638 dstData->mBackground = 0u;
1639 uint64_t valueCount = 0u;
1643 auto *dstChild = this->
template dstNode<DstBuildT, 2>(0);
1644 auto *dstTile = dstData->tile(0);
1645 for (
auto it = srcRoot.cbeginChildAll(); it; ++it, ++dstTile) {
1647 if (it.probeChild(tmp)) {
1648 dstTile->setChild(it.getCoord(), dstChild++, dstData);
1650 dstTile->setValue(it.getCoord(), it.isValueOn(), 0u);
1651 if (mIncludeTiles && !((BuildTraits<DstBuildT>::is_onindex) && !dstTile->state)) dstTile->value = ++valueCount;
1655 if (mIncludeTiles && mIncludeStats) {
1656 dstData->mMinimum = ++valueCount;
1657 dstData->mMaximum = ++valueCount;
1658 dstData->mAverage = ++valueCount;
1659 dstData->mStdDevi = ++valueCount;
1660 }
else if (dstData->padding()==0) {
1661 dstData->mMinimum = 0u;
1662 dstData->mMaximum = 0u;
1663 dstData->mAverage = 0u;
1664 dstData->mStdDevi = 0u;
1670template <
typename SrcGr
idT>
1671template <
typename DstBuildT>
1672void CreateNanoGrid<SrcGridT>::processTree()
1674 const uint64_t nodeCount[3] = {mSrcNodeAcc.nodeCount(0), mSrcNodeAcc.nodeCount(1), mSrcNodeAcc.nodeCount(2)};
1675 auto *dstTree = this->
template dstTree<DstBuildT>();
1676 auto *dstData = dstTree->data();
1677 dstData->setRoot( this->
template dstRoot<DstBuildT>() );
1679 dstData->setFirstNode(nodeCount[2] ? this->
template dstNode<DstBuildT, 2>(0) : nullptr);
1680 dstData->setFirstNode(nodeCount[1] ? this->
template dstNode<DstBuildT, 1>(0) : nullptr);
1681 dstData->setFirstNode(nodeCount[0] ? this->
template dstNode<DstBuildT, 0>(0) : nullptr);
1683 dstData->mNodeCount[0] =
static_cast<uint32_t
>(nodeCount[0]);
1684 dstData->mNodeCount[1] =
static_cast<uint32_t
>(nodeCount[1]);
1685 dstData->mNodeCount[2] =
static_cast<uint32_t
>(nodeCount[2]);
1688 dstData->mTileCount[0] =
reduce(
Range1D(0,nodeCount[1]), uint32_t(0), [&](Range1D &r, uint32_t sum){
1689 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<1>(i).getValueMask().countOn();
1690 return sum;}, std::plus<uint32_t>());
1693 dstData->mTileCount[1] =
reduce(
Range1D(0,nodeCount[2]), uint32_t(0), [&](Range1D &r, uint32_t sum){
1694 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<2>(i).getValueMask().countOn();
1695 return sum;}, std::plus<uint32_t>());
1698 dstData->mTileCount[2] = 0;
1699 for (
auto it = mSrcNodeAcc.root().cbeginValueOn(); it; ++it) dstData->mTileCount[2] += 1;
1702 dstData->mVoxelCount =
reduce(
Range1D(0, nodeCount[0]), uint64_t(0), [&](Range1D &r, uint64_t sum){
1703 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<0>(i).getValueMask().countOn();
1704 return sum;}, std::plus<uint64_t>());
1706 dstData->mVoxelCount += uint64_t(dstData->mTileCount[0]) << 9;
1707 dstData->mVoxelCount += uint64_t(dstData->mTileCount[1]) << 21;
1708 dstData->mVoxelCount += uint64_t(dstData->mTileCount[2]) << 36;
1714template <
typename SrcGr
idT>
1715template <
typename DstBuildT>
1716void CreateNanoGrid<SrcGridT>::processGrid()
1718 auto* dstData = this->
template dstGrid<DstBuildT>()->data();
1719 dstData->init({GridFlags::IsBreadthFirst}, mOffset.size, mSrcNodeAcc.map(),
1720 mapToGridType<DstBuildT>(), mapToGridClass<DstBuildT>(mSrcNodeAcc.gridClass()));
1721 dstData->mBlindMetadataCount =
static_cast<uint32_t
>(mBlindMetaData.size());
1722 dstData->mData1 = this->valueCount();
1724 if (!
isValid(dstData->mGridType, dstData->mGridClass)) {
1726 fprintf(stderr,
"Warning: Strange combination of GridType(\"%s\") and GridClass(\"%s\"). Consider changing GridClass to \"Unknown\"\n",
1727 toStr(dstData->mGridType),
toStr(dstData->mGridClass));
1729 throw std::runtime_error(
"Invalid combination of GridType("+std::to_string(
int(dstData->mGridType))+
1730 ") and GridClass("+std::to_string(
int(dstData->mGridClass))+
"). See NanoVDB.h for details!");
1734 std::memset(dstData->mGridName,
'\0', GridData::MaxNameSize);
1735 strncpy(dstData->mGridName, mSrcNodeAcc.getName().c_str(), GridData::MaxNameSize-1);
1736 if (mSrcNodeAcc.hasLongGridName()) dstData->setLongGridNameOn();
1739 if (mBlindMetaData.size()>0) {
1740 auto *metaData = this->dstMeta(0);
1741 dstData->mBlindMetadataOffset = PtrDiff(metaData, dstData);
1742 dstData->mBlindMetadataCount =
static_cast<uint32_t
>(mBlindMetaData.size());
1743 char *blindData = PtrAdd<char>(mBufferPtr, mOffset.blind);
1744 for (
const auto &b : mBlindMetaData) {
1745 std::memcpy(metaData, b.metaData,
sizeof(GridBlindMetaData));
1746 metaData->setBlindData(blindData);
1747 if (metaData->mDataClass == GridBlindDataClass::GridName) strcpy(blindData, mSrcNodeAcc.getName().c_str());
1749 blindData += b.size;
1751 mBlindMetaData.clear();
1757template <
typename SrcGr
idT>
1758template <
typename DstBuildT>
1759inline typename disable_if<BuildTraits<DstBuildT>::is_index>::type
1760CreateNanoGrid<SrcGridT>::postProcess()
1762 if constexpr(is_same<FpN, DstBuildT>::value) mCodec.reset();
1763 auto *dstGrid = this->
template dstGrid<DstBuildT>();
1765#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1766 auto *metaData = this->dstMeta(0);
1767 if constexpr(is_same<openvdb::tools::PointIndexGrid, SrcGridT>::value ||
1768 is_same<openvdb::points::PointDataGrid, SrcGridT>::value) {
1769 static_assert(is_same<DstBuildT, uint32_t>::value,
"expected DstBuildT==uint32_t");
1770 auto *dstData0 = this->
template dstNode<DstBuildT,0>(0)->data();
1771 dstData0->mMinimum = 0;
1772 dstData0->mMaximum = dstData0->mValues[511u];
1773 for (uint32_t i=1, n=mSrcNodeAcc.nodeCount(0); i<n; ++i) {
1774 auto *dstData1 = dstData0 + 1;
1775 dstData1->mMinimum = dstData0->mMinimum + dstData0->mMaximum;
1776 dstData1->mMaximum = dstData1->mValues[511u];
1777 dstData0 = dstData1;
1779 for (
size_t i = 0, n = dstGrid->blindDataCount(); i < n; ++i, ++metaData) {
1780 if constexpr(is_same<openvdb::tools::PointIndexGrid, SrcGridT>::value) {
1781 if (metaData->mDataClass != GridBlindDataClass::IndexArray)
continue;
1782 if (metaData->mDataType == GridType::UInt32) {
1783 uint32_t *blindData =
const_cast<uint32_t*
>(metaData->template getBlindData<uint32_t>());
1784 forEach(0, mSrcNodeAcc.nodeCount(0), 16, [&](
const auto& r) {
1785 auto *dstData = this->template dstNode<DstBuildT,0>(r.begin())->data();
1786 for (auto j = r.begin(); j != r.end(); ++j, ++dstData) {
1787 uint32_t* p = blindData + dstData->mMinimum;
1788 for (uint32_t idx : mSrcNodeAcc.template node<0>(j).indices()) *p++ = idx;
1793 if (metaData->mDataClass != GridBlindDataClass::AttributeArray)
continue;
1794 if (
auto *blindData = dstGrid->template getBlindData<float>(i)) {
1795 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1796 }
else if (
auto *blindData = dstGrid->template getBlindData<nanovdb::Vec3f>(i)) {
1797 this->
template copyPointAttribute<DstBuildT>(i,
reinterpret_cast<openvdb::Vec3f*
>(blindData));
1798 }
else if (
auto *blindData = dstGrid->template getBlindData<int32_t>(i)) {
1799 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1800 }
else if (
auto *blindData = dstGrid->template getBlindData<int64_t>(i)) {
1801 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1803 std::cerr <<
"unsupported point attribute \"" <<
toStr(metaData->mDataType) <<
"\"\n";
1816template <
typename SrcGr
idT>
1817template <
typename DstBuildT>
1818inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1819CreateNanoGrid<SrcGridT>::postProcess(uint32_t channels)
1821 const std::string typeName =
toStr(mapToGridType<SrcValueT>());
1822 const uint64_t valueCount = this->valueCount();
1823 auto *dstGrid = this->
template dstGrid<DstBuildT>();
1824 for (uint32_t i=0; i<channels; ++i) {
1825 const std::string name =
"channel_"+std::to_string(i);
1826 int j = dstGrid->findBlindData(name.c_str());
1827 if (j<0)
throw std::runtime_error(
"missing " + name);
1828 auto *metaData = this->dstMeta(j);
1829 metaData->mDataClass = GridBlindDataClass::ChannelArray;
1830 metaData->mDataType = mapToGridType<SrcValueT>();
1831 SrcValueT *blindData =
const_cast<SrcValueT*
>(metaData->template getBlindData<SrcValueT>());
1834 SrcValueT *dst=blindData+r.begin(), *end=dst+r.size(), *src=dst-valueCount;
1835 while(dst!=end) *dst++ = *src++;
1838 this->
template copyValues<DstBuildT>(blindData);
1841 gridStats(*(this->
template dstGrid<DstBuildT>()), std::min(StatsMode::BBox, mStats));
1847template <
typename SrcGr
idT>
1848template <
typename DstBuildT>
1849typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1852 assert(mBufferPtr && buffer);
1855 if (this->valueCount()==0) this->
template countValues<DstBuildT>();
1857 auto copyNodeValues = [&](
const auto &node,
SrcValueT *v) {
1859 for (
auto it = node.cbeginValueOn(); it; ++it) *v++ = *it;
1861 for (
auto it = node.cbeginValueAll(); it; ++it) *v++ = *it;
1863 if (mIncludeStats) {
1864 if constexpr(SrcNodeAccT::IS_NANOVDB) {
1865 *v++ = node.minimum();
1866 *v++ = node.maximum();
1868 *v++ = node.average();
1869 *v++ = node.stdDeviation();
1883 const SrcRootT &root = mSrcNodeAcc.root();
1884 buffer[0] = root.background();
1885 if (mIncludeTiles) {
1886 copyNodeValues(root, buffer + 1u);
1888 for (auto i = r.begin(); i!=r.end(); ++i) {
1889 copyNodeValues(mSrcNodeAcc.template node<2>(i), buffer + mValIdx[2][i]);
1893 for (auto i = r.begin(); i!=r.end(); ++i) {
1894 copyNodeValues(mSrcNodeAcc.template node<1>(i), buffer + mValIdx[1][i]);
1898 forEach(0, mSrcNodeAcc.nodeCount(0), 4, [&](
const Range1D& r) {
1899 for (auto i = r.begin(); i!=r.end(); ++i) {
1900 copyNodeValues(mSrcNodeAcc.template node<0>(i), buffer + mValIdx[0][i]);
1908#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1910template <
typename SrcGr
idT>
1912typename disable_if<is_same<T, openvdb::tools::PointIndexGrid>::value ||
1913 is_same<T, openvdb::points::PointDataGrid>::value, uint64_t>::type
1914CreateNanoGrid<SrcGridT>::countPoints()
const
1916 static_assert(is_same<T, SrcGridT>::value,
"expected default template parameter");
1920template <
typename SrcGr
idT>
1922typename enable_if<is_same<T, openvdb::tools::PointIndexGrid>::value ||
1923 is_same<T, openvdb::points::PointDataGrid>::value, uint64_t>::type
1924CreateNanoGrid<SrcGridT>::countPoints()
const
1926 static_assert(is_same<T, SrcGridT>::value,
"expected default template parameter");
1927 return reduce(0, mSrcNodeAcc.nodeCount(0), 8, uint64_t(0), [&](
auto &r, uint64_t sum) {
1928 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<0>(i).getLastValue();
1929 return sum;}, std::plus<uint64_t>());
1932template <
typename SrcGr
idT>
1933template<
typename DstBuildT,
typename AttT,
typename CodecT,
typename T>
1934typename enable_if<is_same<openvdb::points::PointDataGrid, T>::value>::type
1935CreateNanoGrid<SrcGridT>::copyPointAttribute(
size_t attIdx, AttT *attPtr)
1937 static_assert(std::is_same<SrcGridT, T>::value,
"Expected default parameter");
1938 using HandleT = openvdb::points::AttributeHandle<AttT, CodecT>;
1939 forEach(0, mSrcNodeAcc.nodeCount(0), 16, [&](
const auto& r) {
1940 auto *dstData = this->template dstNode<DstBuildT,0>(r.begin())->data();
1941 for (auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1942 auto& srcLeaf = mSrcNodeAcc.template node<0>(i);
1943 HandleT handle(srcLeaf.constAttributeArray(attIdx));
1944 AttT *p = attPtr + dstData->mMinimum;
1945 for (auto iter = srcLeaf.beginIndexOn(); iter; ++iter) *p++ = handle.get(*iter);
1954template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1955typename disable_if<BuildTraits<DstBuildT>::is_index || BuildTraits<DstBuildT>::is_Fp, GridHandle<BufferT>>::type
1960 const BufferT &buffer)
1966 return converter.template getHandle<DstBuildT, BufferT>(buffer);
1971template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1972typename enable_if<BuildTraits<DstBuildT>::is_index, GridHandle<BufferT>>::type
1978 const BufferT &buffer)
1982 return converter.template getHandle<DstBuildT, BufferT>(channels, includeStats, includeTiles, buffer);
1987template<
typename SrcGr
idT,
typename DstBuildT,
typename OracleT,
typename BufferT>
1988typename enable_if<is_same<FpN, DstBuildT>::value, GridHandle<BufferT>>::type
1994 const OracleT &oracle,
1995 const BufferT &buffer)
2002 return converter.template getHandle<DstBuildT, OracleT, BufferT>(oracle, buffer);
2007template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
2008typename enable_if<BuildTraits<DstBuildT>::is_FpX, GridHandle<BufferT>>::type
2014 const BufferT &buffer)
2021 return converter.template getHandle<DstBuildT, BufferT>(buffer);
2026#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
2027template<
typename BufferT>
2029openToNanoVDB(
const openvdb::GridBase::ConstPtr& base,
2035 using openvdb_Vec4fTree =
typename openvdb::tree::Tree4<openvdb::Vec4f, 5, 4, 3>::Type;
2036 using openvdb_Vec4dTree =
typename openvdb::tree::Tree4<openvdb::Vec4d, 5, 4, 3>::Type;
2041 if (
auto grid = openvdb::GridBase::grid<openvdb::FloatGrid>(base)) {
2042 return createNanoGrid<openvdb::FloatGrid, float, BufferT>(*grid, sMode, cMode, verbose);
2043 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::DoubleGrid>(base)) {
2044 return createNanoGrid<openvdb::DoubleGrid, double, BufferT>(*grid, sMode, cMode, verbose);
2045 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int32Grid>(base)) {
2046 return createNanoGrid<openvdb::Int32Grid, int32_t,BufferT>(*grid, sMode, cMode, verbose);
2047 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int64Grid>(base)) {
2048 return createNanoGrid<openvdb::Int64Grid, int64_t, BufferT>(*grid, sMode, cMode, verbose);
2049 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_UInt32Grid>(base)) {
2050 return createNanoGrid<openvdb_UInt32Grid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2051 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3fGrid>(base)) {
2052 return createNanoGrid<openvdb::Vec3fGrid, nanovdb::Vec3f, BufferT>(*grid, sMode, cMode, verbose);
2053 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3dGrid>(base)) {
2054 return createNanoGrid<openvdb::Vec3dGrid, nanovdb::Vec3d, BufferT>(*grid, sMode, cMode, verbose);
2055 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::tools::PointIndexGrid>(base)) {
2056 return createNanoGrid<openvdb::tools::PointIndexGrid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2057 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::points::PointDataGrid>(base)) {
2058 return createNanoGrid<openvdb::points::PointDataGrid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2059 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::MaskGrid>(base)) {
2060 return createNanoGrid<openvdb::MaskGrid, nanovdb::ValueMask, BufferT>(*grid, sMode, cMode, verbose);
2061 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::BoolGrid>(base)) {
2062 return createNanoGrid<openvdb::BoolGrid, bool, BufferT>(*grid, sMode, cMode, verbose);
2063 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4fGrid>(base)) {
2064 return createNanoGrid<openvdb_Vec4fGrid, nanovdb::Vec4f, BufferT>(*grid, sMode, cMode, verbose);
2065 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4dGrid>(base)) {
2066 return createNanoGrid<openvdb_Vec4dGrid, nanovdb::Vec4d, BufferT>(*grid, sMode, cMode, verbose);
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.
This file defines a minimum set of tree nodes and tools that can be used (instead of OpenVDB) to buil...
Computes a pair of 32bit checksums, of a Grid, by means of Cyclic Redundancy Check (CRC)
Defines GridHandle, which manages a host, and possibly a device, memory buffer containing one or more...
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:154
#define NANOVDB_ASSERT(x)
Definition NanoVDB.h:190
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
Multi-threaded implementations of inclusive prefix sum.
Custom Range class that is compatible with the tbb::blocked_range classes.
A unified wrapper for tbb::parallel_reduce and a naive std::future analog.
Compression oracle based on absolute difference.
Definition CreateNanoGrid.h:231
bool operator()(float exact, float approx) const
Return true if the approximate value is within the accepted absolute error bounds of the exact value.
Definition CreateNanoGrid.h:255
float getTolerance() const
Definition CreateNanoGrid.h:250
AbsDiff(float tolerance=-1.0f)
Definition CreateNanoGrid.h:235
void init(nanovdb::GridClass gClass, float background)
Definition CreateNanoGrid.h:239
AbsDiff(const AbsDiff &)=default
void setTolerance(float tolerance)
Definition CreateNanoGrid.h:249
Creates any nanovdb Grid from any source grid (certain combinations are obviously not allowed)
Definition CreateNanoGrid.h:524
uint64_t addBlindData(const std::string &name, GridBlindDataSemantic dataSemantic, GridBlindDataClass dataClass, GridType dataType, size_t count, size_t size)
Add blind data to the destination grid.
Definition CreateNanoGrid.h:607
typename SrcNodeAccT::BuildType SrcBuildT
Definition CreateNanoGrid.h:528
void setStats(StatsMode mode=StatsMode::Default)
Set the mode used for computing statistics of the destination grid.
Definition CreateNanoGrid.h:554
typename SrcNodeAccT::TreeType SrcTreeT
Definition CreateNanoGrid.h:530
void setChecksum(ChecksumMode mode=ChecksumMode::Default)
Set the mode used for computing checksums of the destination grid.
Definition CreateNanoGrid.h:558
enable_if< BuildTraits< DstBuildT >::is_index >::type copyValues(SrcValueT *buffer)
Copy values from the source grid into a provided buffer.
Definition CreateNanoGrid.h:1850
typename SrcNodeAccT::RootType SrcRootT
Definition CreateNanoGrid.h:531
void enableDithering(bool on=true)
Enable or disable dithering, i.e. randomization of the quantization error.
Definition CreateNanoGrid.h:550
disable_if< is_same< DstBuildT, FpN >::value||BuildTraits< DstBuildT >::is_index, GridHandle< BufferT > >::type getHandle(const BufferT &buffer=BufferT())
Converts the source grid into a nanovdb grid with the specified destination build type.
Definition CreateNanoGrid.h:896
typename NodeTrait< SrcRootT, LEVEL >::type SrcNodeT
Definition CreateNanoGrid.h:533
void setVerbose(int mode=1)
Set the level of verbosity.
Definition CreateNanoGrid.h:545
CreateNanoGrid(const SrcGridT &srcGrid)
Constructor from a source grid.
Definition CreateNanoGrid.h:783
NodeAccessor< SrcGridT > SrcNodeAccT
Definition CreateNanoGrid.h:527
uint64_t valueCount() const
This method only has affect when getHandle was called with DstBuildT = ValueIndex or ValueOnIndex.
Definition CreateNanoGrid.h:621
typename SrcNodeAccT::ValueType SrcValueT
Definition CreateNanoGrid.h:529
This class serves to manage a buffer containing one or more NanoVDB Grids.
Definition GridHandle.h:38
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition NanoVDB.h:3699
typename TreeT::ValueType ValueType
Definition NanoVDB.h:3708
TreeT TreeType
Definition NanoVDB.h:3701
This is a buffer that contains a shared or private pool to either externally or internally managed ho...
Definition HostBuffer.h:115
static size_t memUsage()
Return memory usage in bytes for the class.
Definition NanoVDB.h:5169
LeafData< BuildT, CoordT, MaskT, Log2Dim > DataType
Definition NanoVDB.h:6036
uint64_t memUsage() const
return memory usage in bytes for the leaf node
Definition NanoVDB.h:6242
const TreeType & tree() const
Definition CreateNanoGrid.h:352
uint64_t nodeCount(int level) const
Definition CreateNanoGrid.h:354
const NodeType< LEVEL > & node(uint32_t i) const
Definition CreateNanoGrid.h:356
NodeAccessor(const GridType &grid)
Definition CreateNanoGrid.h:348
typename NodeTrait< TreeType, LEVEL >::type NodeType
Definition CreateNanoGrid.h:347
typename GridType::ValueType ValueType
Definition CreateNanoGrid.h:343
typename GridType::TreeType TreeType
Definition CreateNanoGrid.h:344
std::string getName() const
Definition CreateNanoGrid.h:357
typename TreeType::RootType RootType
Definition CreateNanoGrid.h:345
const RootType & root() const
Definition CreateNanoGrid.h:353
bool hasLongGridName() const
Definition CreateNanoGrid.h:358
const GridType & grid() const
Definition CreateNanoGrid.h:351
GridClass gridClass() const
Definition CreateNanoGrid.h:360
BuildT BuildType
Definition CreateNanoGrid.h:340
const nanovdb::Map & map() const
Definition CreateNanoGrid.h:359
The NodeAccessor provides a uniform API for accessing nodes got NanoVDB, OpenVDB and build Grids.
Definition CreateNanoGrid.h:304
const TreeType & tree() const
Definition CreateNanoGrid.h:317
static constexpr bool IS_NANOVDB
Definition CreateNanoGrid.h:307
uint64_t nodeCount(int level) const
Definition CreateNanoGrid.h:319
const NodeType< LEVEL > & node(uint32_t i) const
Definition CreateNanoGrid.h:321
const std::string & getName() const
Definition CreateNanoGrid.h:322
static constexpr bool IS_OPENVDB
Definition CreateNanoGrid.h:306
typename TreeType::RootNodeType RootType
Definition CreateNanoGrid.h:312
typename GridT::BuildType BuildType
Definition CreateNanoGrid.h:308
typename NodeTrait< const TreeType, LEVEL >::type NodeType
Definition CreateNanoGrid.h:314
const RootType & root() const
Definition CreateNanoGrid.h:318
typename GridT::TreeType TreeType
Definition CreateNanoGrid.h:311
typename GridT::ValueType ValueType
Definition CreateNanoGrid.h:309
bool hasLongGridName() const
Definition CreateNanoGrid.h:323
const GridType & grid() const
Definition CreateNanoGrid.h:316
NodeAccessor(const GridT &grid)
Definition CreateNanoGrid.h:315
GridClass gridClass() const
Definition CreateNanoGrid.h:325
GridT GridType
Definition CreateNanoGrid.h:310
const nanovdb::Map & map() const
Definition CreateNanoGrid.h:324
NodeManagerHandle manages the memory of a NodeManager.
Definition NodeManager.h:55
NodeManager allows for sequential access to nodes.
Definition NodeManager.h:180
Compression oracle based on relative difference.
Definition CreateNanoGrid.h:271
RelDiff(float tolerance=-1.0f)
Definition CreateNanoGrid.h:275
bool operator()(float exact, float approx) const
Return true if the approximate value is within the accepted relative error bounds of the exact value.
Definition CreateNanoGrid.h:285
RelDiff(const RelDiff &)=default
float getTolerance() const
Definition CreateNanoGrid.h:280
void setTolerance(float tolerance)
Definition CreateNanoGrid.h:279
Top-most node of the VDB tree structure.
Definition NanoVDB.h:4330
uint64_t memUsage() const
Return the actual memory footprint of this root node.
Definition NanoVDB.h:4625
static uint64_t memUsage()
return memory usage in bytes for the class
Definition NanoVDB.h:4024
Dummy type for a voxel whose value equals its binary active state.
Definition NanoVDB.h:273
A simple vector class with three components, similar to openvdb::math::Vec3.
Definition NanoVDB.h:1530
A simple vector class with four components, similar to openvdb::math::Vec4.
Definition NanoVDB.h:1728
Definition GridBuilder.h:2055
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
Definition Exceptions.h:63
Definition Exceptions.h:65
Codec
Define compression codecs.
Definition NanoVDB.h:7839
Convert a base-pointer to an openvdb grid, denoted srcGrid, to a nanovdb grid of the same type,...
Definition NanoVDB.h:247
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:1288
const char * toStr(GridType gridType)
Maps a GridType to a c-string.
Definition NanoVDB.h:349
Grid< NanoTree< BuildT > > NanoGrid
Definition NanoVDB.h:6449
T Abs(T x)
Definition NanoVDB.h:1185
disable_if< BuildTraits< DstBuildT >::is_index||BuildTraits< DstBuildT >::is_Fp, GridHandle< BufferT > >::type createNanoGrid(const SrcGridT &srcGrid, StatsMode sMode=StatsMode::Default, ChecksumMode cMode=ChecksumMode::Default, int verbose=0, const BufferT &buffer=BufferT())
Freestanding function that creates a NanoGrid<T> from any source grid.
Definition CreateNanoGrid.h:1956
static DstT * PtrAdd(SrcT *p, int64_t offset)
Adds a byte offset of a non-const pointer to produce another non-const pointer.
Definition NanoVDB.h:795
T reduce(RangeT range, const T &identity, const FuncT &func, const JoinT &join)
Definition Reduce.h:42
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
Definition NanoVDB.h:362
GridType
List of types that are currently supported by NanoVDB.
Definition NanoVDB.h:317
RootNode< NanoUpper< BuildT > > NanoRoot
Definition NanoVDB.h:6445
Tree< NanoRoot< BuildT > > NanoTree
Definition NanoVDB.h:6447
LeafNode< BuildT, Coord, Mask, 3 > NanoLeaf
Template specializations to the default configuration used in OpenVDB: Root -> 32^3 -> 16^3 -> 8^3.
Definition NanoVDB.h:6439
GridBlindDataClass
Blind-data Classes that are currently supported by NanoVDB.
Definition NanoVDB.h:416
BBox< Coord > CoordBBox
Definition NanoVDB.h:2535
StatsMode
Grid flags which indicate what extra information is present in the grid buffer.
Definition GridStats.h:38
GridType mapToGridType()
Maps from a templated build type to a GridType enum.
Definition NanoVDB.h:2050
int invoke(const Func &taskFunc1, Rest... taskFuncN)
Definition Invoke.h:64
std::ostream & operator<<(std::ostream &os, const AbsDiff &diff)
Definition CreateNanoGrid.h:261
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:722
ChecksumMode
List of different modes for computing for a checksum.
Definition GridChecksum.h:38
T prefixSum(std::vector< T > &vec, bool threaded=true, OpT op=OpT())
Computes inclusive prefix sum of a vector.
Definition PrefixSum.h:71
GridBlindDataSemantic
Blind-data Semantics that are currently understood by NanoVDB.
Definition NanoVDB.h:424
Type Max(Type a, Type b)
Definition NanoVDB.h:1110
void updateChecksum(NanoGrid< BuildT > &grid, ChecksumMode mode=ChecksumMode::Default)
Updates the checksum of a grid.
bool isValid(GridType gridType, GridClass gridClass)
return true if the combination of GridType and GridClass is valid.
Definition NanoVDB.h:883
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:284
Range< 1, size_t > Range1D
Definition Range.h:30
OPENVDB_API uint32_t getGridClass(std::ios_base &)
Return the class (GRID_LEVEL_SET, GRID_UNKNOWN, etc.) of the grid currently being read from or writte...
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 PointCountImpl.h:18
@ GRID_FOG_VOLUME
Definition Types.h:456
@ GRID_STAGGERED
Definition Types.h:457
@ GRID_LEVEL_SET
Definition Types.h:455
PointIndex< Index32, 0 > PointIndex32
Definition Types.h:178
PointIndex< Index32, 1 > PointDataIndex32
Definition Types.h:181
Definition Exceptions.h:13
This class allows for sequential access to nodes in a NanoVDB tree on both the host and device.
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
Define static boolean tests for template build types.
Definition NanoVDB.h:472
static constexpr bool is_onindex
Definition NanoVDB.h:475
static constexpr bool is_index
Definition NanoVDB.h:474
static constexpr bool is_Fp
Definition NanoVDB.h:481
float FloatType
Definition NanoVDB.h:1995
static uint64_t memUsage()
Return memory usage in bytes for this class only.
Definition NanoVDB.h:3661
static const int MaxNameSize
Definition NanoVDB.h:3513
Trait that maps any type to the corresponding nanovdb type.
Definition CreateNanoGrid.h:371
T type
Definition CreateNanoGrid.h:371
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition NanoVDB.h:3158
Struct to derive node type from its level in a given grid, tree or root while preserving constness.
Definition NanoVDB.h:3404
C++11 implementation of std::enable_if.
Definition NanoVDB.h:493
static constexpr bool value
Definition NanoVDB.h:464
C++11 implementation of std::is_same.
Definition NanoVDB.h:442
static constexpr bool value
Definition NanoVDB.h:443