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>
111 #if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
119 template<
typename BufferT = HostBuffer>
121 openToNanoVDB(
const openvdb::GridBase::Ptr& base,
139 template<
typename SrcGridT,
147 const BufferT &
buffer = BufferT());
164 template<
typename SrcGridT,
170 bool includeStats =
true,
171 bool includeTiles =
true,
173 const BufferT &
buffer = BufferT());
190 template<
typename SrcGridT,
198 bool ditherOn =
false,
200 const OracleT &oracle = OracleT(),
201 const BufferT &
buffer = BufferT());
216 template<
typename SrcGridT,
223 bool ditherOn =
false,
225 const BufferT &
buffer = BufferT());
235 AbsDiff(
float tolerance = -1.0
f) : 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.0
f) : mTolerance(tolerance) {}
278 operator bool()
const {
return mTolerance>=0.0f;}
287 return Abs(exact - approx)/
Max(
Abs(exact),
Abs(approx)) <= mTolerance;
302 template <
typename Gr
idT>
334 template <
typename BuildT>
350 , mMgr(*(mHandle.template mgr<BuildT>())) {}
373 #if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
387 template <
typename BuildT>
388 using OpenLeaf = openvdb::tree::LeafNode<BuildT,3>;
389 template <
typename BuildT>
390 using OpenLower = openvdb::tree::InternalNode<OpenLeaf<BuildT>,4>;
391 template <
typename BuildT>
392 using OpenUpper = openvdb::tree::InternalNode<OpenLower<BuildT>,5>;
393 template <
typename BuildT>
394 using OpenRoot = openvdb::tree::RootNode<OpenUpper<BuildT>>;
395 template <
typename BuildT>
396 using OpenTree = openvdb::tree::Tree<OpenRoot<BuildT>>;
397 template <
typename BuildT>
398 using OpenGrid = openvdb::Grid<OpenTree<BuildT>>;
403 template <
typename BuildT>
404 class NodeAccessor<OpenGrid<BuildT>>
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); }
425 const NodeType<LEVEL>&
node(uint32_t i)
const {
return mMgr.template node<LEVEL>(i); }
427 bool hasLongGridName()
const {
return this->
grid().getName().length() >= GridData::MaxNameSize;}
443 build::NodeManager<GridType> mMgr;
459 using RootType =
typename TreeType::RootNodeType;
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); }
472 const NodeType<LEVEL>&
node(uint32_t i)
const {
return mMgr.template node<LEVEL>(i); }
474 bool hasLongGridName()
const {
return this->
grid().getName().length() >= GridData::MaxNameSize;}
478 build::NodeManager<GridType> mMgr;
494 using RootType =
typename TreeType::RootNodeType;
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); }
507 const NodeType<LEVEL>&
node(uint32_t i)
const {
return mMgr.template node<LEVEL>(i); }
509 bool hasLongGridName()
const {
return this->
grid().getName().length() >= GridData::MaxNameSize;}
513 build::NodeManager<GridType> mMgr;
517 #endif// NANOVDB_USE_OPENVDB
522 template <
typename SrcGr
idT>
581 getHandle(
const OracleT &oracle = OracleT(),
582 const BufferT &
buffer = BufferT());
595 bool includeStats =
true,
596 bool includeTiles =
true,
597 const BufferT &
buffer = BufferT());
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}");
639 return PtrAdd<NodeT>(mBufferPtr, mOffset[5-LEVEL]) + i;
641 template <
typename T,
int LEVEL>
643 dstNode(uint64_t i)
const {
return PtrAdd<NanoLeaf<FpN>>(mBufferPtr, mCodec[i].offset);}
645 template <
typename T> NanoRoot<T>* dstRoot()
const {
return PtrAdd<NanoRoot<T>>(mBufferPtr, mOffset.root);}
646 template <
typename T> NanoTree<T>* dstTree()
const {
return PtrAdd<NanoTree<T>>(mBufferPtr, mOffset.tree);}
647 template <
typename T> NanoGrid<T>* dstGrid()
const {
return PtrAdd<NanoGrid<T>>(mBufferPtr, mOffset.grid);}
648 GridBlindMetaData* dstMeta(uint32_t i)
const {
return PtrAdd<GridBlindMetaData>(mBufferPtr, mOffset.meta) + i;};
652 template <
typename DstBuildT>
656 template <
typename DstBuildT>
657 typename enable_if<BuildTraits<DstBuildT>::is_index>
::type
660 template <
typename DstBuildT,
typename OracleT>
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
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>
698 template<
typename DstBuildT>
702 template<
typename DstBuildT>
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>
748 template<
typename T = SrcGr
idT>
753 template<
typename DstBuildT,
typename AttT,
typename CodecT = openvdb::po
ints::UnknownCodec,
typename T = SrcGr
idT>
755 copyPointAttribute(
size_t attIdx, AttT *attPtr);
757 uint64_t countPoints()
const {
return 0u;}
761 struct BufferOffsets {
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;
773 std::unique_ptr<Codec[]> mCodec;
776 bool mDitherOn, mIncludeStats, mIncludeTiles;
777 std::vector<uint64_t> mValIdx[3];
782 template <
typename SrcGr
idT>
786 , mSrcNodeAcc(*mSrcNodeAccPtr)
790 , mIncludeStats(true)
791 , mIncludeTiles(true)
797 template <
typename SrcGr
idT>
800 , mSrcNodeAccPtr(nullptr)
801 , mSrcNodeAcc(srcNodeAcc)
805 , mIncludeStats(true)
806 , mIncludeTiles(true)
812 template <
typename SrcGr
idT>
818 size_t i,
size_t valueCount,
size_t valueSize)
819 : metaData(reinterpret_cast<GridBlindMetaData*>(new char[sizeof(GridBlindMetaData)]))
823 std::memset(metaData, 0,
sizeof(GridBlindMetaData));
824 if (name.length()>=GridData::MaxNameSize)
throw std::runtime_error(
"blind data name exceeds limit");
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)
838 : metaData(reinterpret_cast<GridBlindMetaData*>(new char[sizeof(GridBlindMetaData)]))
842 std::memset(metaData, 0,
sizeof(GridBlindMetaData));
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;
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) {
892 template <
typename SrcGr
idT>
893 template<
typename DstBuildT,
typename BufferT>
898 this->
template preProcess<DstBuildT>();
899 auto handle = this->
template initHandle<DstBuildT>(
pool);
900 this->
template postProcess<DstBuildT>();
906 template <
typename SrcGr
idT>
907 template<
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>();
919 template <
typename SrcGr
idT>
920 template<
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);
937 template <
typename SrcGr
idT>
938 template <
typename DstBuildT,
typename BufferT>
948 mOffset.blind =
mOffset.meta +
sizeof(GridBlindMetaData)*mBlindMetaData.size();
950 for (
const auto&
b : mBlindMetaData)
mOffset.size +=
b.size;
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));
968 template <
typename SrcGr
idT>
969 template <
typename DstBuildT>
971 CreateNanoGrid<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());
1000 #endif// end NANOVDB_USE_OPENVDB
1002 if (mSrcNodeAcc.hasLongGridName()) {
1003 this->addBlindData(
"grid name",
1007 mSrcNodeAcc.getName().length() + 1, 1);
1009 mLeafNodeSize = mSrcNodeAcc.nodeCount(0)*NanoLeaf<DstBuildT>::DataType::memUsage();
1014 template <
typename SrcGr
idT>
1015 template <
typename DstBuildT,
typename OracleT>
1017 CreateNanoGrid<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);
1037 float &
max = mCodec[i].max = -
min;
1038 for (
int j=0;
j<512; ++
j) {
1039 float v = srcLeaf.getValue(
j);
1044 uint8_t &logBitWidth = mCodec[i].log2 = 0;
1045 while (range > 0.0
f && 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){
1064 return mCodec[i].offset + NanoLeaf<DstBuildT>::DataType::memUsage(1u << mCodec[i].
log2);
1066 mCodec[0].offset = NanoGrid<FpN>::memUsage() +
1069 NanoUpper<FpN>::memUsage()*mSrcNodeAcc.nodeCount(2) +
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.0
f*
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);
1101 template <
typename SrcGr
idT>
1102 template <
typename DstBuildT,
int LEVEL>
1103 inline typename enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>
::type
1104 CreateNanoGrid<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);
1112 if constexpr(BuildTraits<DstBuildT>::is_onindex) {
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();
1127 template <
typename SrcGr
idT>
1128 template <
typename DstBuildT>
1129 inline typename enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>
::type
1130 CreateNanoGrid<SrcGridT>::countValues()
1132 const uint64_t stats = mIncludeStats ? 4u : 0u;
1133 uint64_t valueCount = 1u;
1134 if (mIncludeTiles) {
1135 if constexpr(BuildTraits<DstBuildT>::is_onindex) {
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);
1146 if constexpr(BuildTraits<DstBuildT>::is_onindex) {
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();
1161 template <
typename SrcGr
idT>
1162 template <
typename DstBuildT>
1163 inline typename enable_if<BuildTraits<DstBuildT>::is_index>
::type
1164 CreateNanoGrid<SrcGridT>::preProcess(uint32_t
channels)
1166 const uint64_t valueCount = this->
template countValues<DstBuildT>();
1167 mLeafNodeSize = mSrcNodeAcc.nodeCount(0)*NanoLeaf<DstBuildT>::DataType::memUsage();
1169 uint32_t
order = mBlindMetaData.size();
1170 for (uint32_t i=0; i<
channels; ++i) {
1172 toStr(mapToGridType<SrcValueT>()),
1178 if (mSrcNodeAcc.hasLongGridName()) {
1179 this->addBlindData(
"grid name",
1183 mSrcNodeAcc.getName().length() + 1, 1);
1189 template <
typename SrcGr
idT>
1190 template <
typename DstBuildT>
1191 inline typename disable_if<BuildTraits<DstBuildT>::is_special>
::type
1192 CreateNanoGrid<SrcGridT>::processLeafs()
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;
1208 dstData->mAverage = dstData->mStdDevi = 0;
1210 dstData->mBBoxMin = srcLeaf.origin();
1211 dstData->mValueMask = srcLeaf.getValueMask();
1212 DstValueT *
dst = dstData->mValues;
1214 const SrcValueT *
src = srcLeaf.buffer().data();
1215 for (
auto *
end = dst + 512u; dst !=
end; dst += 4, src += 4) {
1230 template <
typename SrcGr
idT>
1231 template <
typename DstBuildT>
1232 inline typename enable_if<BuildTraits<DstBuildT>::is_index>
::type
1233 CreateNanoGrid<SrcGridT>::processLeafs()
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");
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
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;
1262 for (
int n = 9;
n < 55;
n += 9) {
1264 prefixSum |= sum <<
n;
1268 dstData->mPrefixSum = 0u;
1270 if constexpr(BuildTraits<DstBuildT>::is_indexmask) dstData->
mMask = dstData->
mValueMask;
1277 template <typename SrcGridT>
1278 template <typename DstBuildT>
1279 inline typename enable_if<is_same<ValueMask, DstBuildT>::
value>::
type
1280 CreateNanoGrid<SrcGridT>::processLeafs()
1283 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<ValueMask> to have fixed size");
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();
1304 template <
typename SrcGr
idT>
1305 template <
typename DstBuildT>
1307 CreateNanoGrid<SrcGridT>::processLeafs()
1310 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<bool> to have fixed size");
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();
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;
1339 template <
typename SrcGr
idT>
1340 template <
typename DstBuildT>
1341 inline typename enable_if<BuildTraits<DstBuildT>::is_FpX>
::type
1342 CreateNanoGrid<SrcGridT>::processLeafs()
1345 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<Fp4|Fp8|Fp16> to have fixed size");
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);
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();
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);
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);
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();
1403 template <
typename SrcGr
idT>
1404 template <
typename DstBuildT>
1406 CreateNanoGrid<SrcGridT>::processLeafs()
1409 DitherLUT lut(mDitherOn);
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;
1487 template <
typename SrcGr
idT>
1488 template <
typename DstBuildT,
int LEVEL>
1489 inline typename enable_if<!BuildTraits<DstBuildT>::is_index>::type
1490 CreateNanoGrid<SrcGridT>::processInternalNodes()
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();
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;
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));
1538 template <
typename SrcGr
idT>
1539 template <
typename DstBuildT,
int LEVEL>
1540 inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1541 CreateNanoGrid<SrcGridT>::processInternalNodes()
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();
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;
1596 template <
typename SrcGr
idT>
1597 template <
typename DstBuildT>
1598 inline typename enable_if<!BuildTraits<DstBuildT>::is_index>::type
1599 CreateNanoGrid<SrcGridT>::processRoot()
1601 using DstRootT = NanoRoot<DstBuildT>;
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));
1626 template <
typename SrcGr
idT>
1627 template <
typename DstBuildT>
1628 inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1629 CreateNanoGrid<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;
1670 template <
typename SrcGr
idT>
1671 template <
typename DstBuildT>
1672 void 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;
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;
1714 template <
typename SrcGr
idT>
1715 template <
typename DstBuildT>
1716 void CreateNanoGrid<SrcGridT>::processGrid()
1718 auto* dstData = this->
template dstGrid<DstBuildT>()->
data();
1720 mapToGridType<DstBuildT>(), mapToGridClass<DstBuildT>(mSrcNodeAcc.gridClass()));
1721 dstData->mBlindMetadataCount =
static_cast<uint32_t
>(mBlindMetaData.size());
1722 dstData->mData1 = this->valueCount();
1724 std::memset(dstData->mGridName,
'\0', GridData::MaxNameSize);
1725 strncpy(dstData->mGridName, mSrcNodeAcc.getName().c_str(), GridData::MaxNameSize-1);
1726 if (mSrcNodeAcc.hasLongGridName()) dstData->setLongGridNameOn();
1729 if (mBlindMetaData.size()>0) {
1730 auto *metaData = this->dstMeta(0);
1731 dstData->mBlindMetadataOffset = PtrDiff(metaData, dstData);
1732 dstData->mBlindMetadataCount =
static_cast<uint32_t
>(mBlindMetaData.size());
1733 char *blindData = PtrAdd<char>(mBufferPtr,
mOffset.blind);
1734 for (
const auto &
b : mBlindMetaData) {
1735 std::memcpy(metaData,
b.metaData,
sizeof(GridBlindMetaData));
1736 metaData->setBlindData(blindData);
1739 blindData +=
b.size;
1741 mBlindMetaData.clear();
1747 template <
typename SrcGr
idT>
1748 template <
typename DstBuildT>
1749 inline typename disable_if<BuildTraits<DstBuildT>::is_index>::type
1750 CreateNanoGrid<SrcGridT>::postProcess()
1753 auto *dstGrid =
this->template dstGrid<DstBuildT>();
1755 #if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1756 auto *metaData = this->dstMeta(0);
1760 auto *dstData0 = this->
template dstNode<DstBuildT,0>(0)->
data();
1761 dstData0->mMinimum = 0;
1762 dstData0->mMaximum = dstData0->mValues[511u];
1763 for (uint32_t i=1, n=mSrcNodeAcc.nodeCount(0); i<
n; ++i) {
1764 auto *dstData1 = dstData0 + 1;
1765 dstData1->mMinimum = dstData0->mMinimum + dstData0->mMaximum;
1766 dstData1->mMaximum = dstData1->mValues[511u];
1767 dstData0 = dstData1;
1769 for (
size_t i = 0, n = dstGrid->blindDataCount(); i <
n; ++i, ++metaData) {
1773 uint32_t *blindData =
const_cast<uint32_t*
>(metaData->template getBlindData<uint32_t>());
1774 forEach(0, mSrcNodeAcc.nodeCount(0), 16, [&](
const auto&
r) {
1775 auto *dstData = this->
template dstNode<DstBuildT,0>(r.begin())->
data();
1776 for (
auto j = r.begin(); j != r.end(); ++
j, ++dstData) {
1777 uint32_t* p = blindData + dstData->mMinimum;
1778 for (uint32_t idx : mSrcNodeAcc.template node<0>(j).indices()) *p++ = idx;
1784 if (
auto *blindData = dstGrid->template getBlindData<float>(i)) {
1785 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1786 }
else if (
auto *blindData = dstGrid->template getBlindData<nanovdb::Vec3f>(i)) {
1787 this->
template copyPointAttribute<DstBuildT>(i,
reinterpret_cast<openvdb::Vec3f*
>(blindData));
1788 }
else if (
auto *blindData = dstGrid->template getBlindData<int32_t>(i)) {
1789 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1790 }
else if (
auto *blindData = dstGrid->template getBlindData<int64_t>(i)) {
1791 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1793 std::cerr <<
"unsupported point attribute \"" <<
toStr(metaData->mDataType) <<
"\"\n";
1806 template <
typename SrcGr
idT>
1807 template <
typename DstBuildT>
1808 inline typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1809 CreateNanoGrid<SrcGridT>::postProcess(uint32_t channels)
1812 const uint64_t valueCount = this->valueCount();
1813 auto *dstGrid = this->
template dstGrid<DstBuildT>();
1814 for (uint32_t i=0; i<
channels; ++i) {
1816 int j = dstGrid->findBlindData(name.c_str());
1817 if (j<0)
throw std::runtime_error(
"missing " + name);
1818 auto *metaData = this->dstMeta(j);
1820 metaData->mDataType = mapToGridType<SrcValueT>();
1821 SrcValueT *blindData =
const_cast<SrcValueT*
>(metaData->template getBlindData<SrcValueT>());
1824 SrcValueT *dst=blindData+r.begin(), *
end=dst+r.size(), *src=dst-valueCount;
1825 while(dst!=
end) *dst++ = *src++;
1828 this->
template copyValues<DstBuildT>(blindData);
1837 template <
typename SrcGr
idT>
1838 template <
typename DstBuildT>
1839 typename enable_if<BuildTraits<DstBuildT>::is_index>::type
1842 assert(mBufferPtr && buffer);
1845 if (this->valueCount()==0) this->
template countValues<DstBuildT>();
1847 auto copyNodeValues = [&](
const auto &node,
SrcValueT *
v) {
1849 for (
auto it = node.cbeginValueOn(); it; ++it) *v++ = *it;
1851 for (
auto it = node.cbeginValueAll(); it; ++it) *v++ = *it;
1853 if (mIncludeStats) {
1854 if constexpr(SrcNodeAccT::IS_NANOVDB) {
1855 *v++ = node.minimum();
1856 *v++ = node.maximum();
1858 *v++ = node.average();
1859 *v++ = node.stdDeviation();
1873 const SrcRootT &root = mSrcNodeAcc.root();
1874 buffer[0] = root.background();
1875 if (mIncludeTiles) {
1876 copyNodeValues(root, buffer + 1u);
1878 for (
auto i = r.begin(); i!=r.end(); ++i) {
1879 copyNodeValues(mSrcNodeAcc.template node<2>(i), buffer + mValIdx[2][i]);
1883 for (
auto i = r.begin(); i!=r.end(); ++i) {
1884 copyNodeValues(mSrcNodeAcc.template node<1>(i), buffer + mValIdx[1][i]);
1889 for (
auto i = r.begin(); i!=r.end(); ++i) {
1890 copyNodeValues(mSrcNodeAcc.template node<0>(i), buffer + mValIdx[0][i]);
1898 #if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1900 template <
typename SrcGr
idT>
1901 template<
typename T>
1910 template <
typename SrcGr
idT>
1911 template<
typename T>
1914 CreateNanoGrid<SrcGridT>::countPoints()
const
1917 return reduce(0, mSrcNodeAcc.nodeCount(0), 8, uint64_t(0), [&](
auto &
r, uint64_t sum) {
1918 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<0>(i).getLastValue();
1919 return sum;}, std::plus<uint64_t>());
1922 template <
typename SrcGr
idT>
1923 template<
typename DstBuildT,
typename AttT,
typename CodecT,
typename T>
1925 CreateNanoGrid<SrcGridT>::copyPointAttribute(
size_t attIdx, AttT *attPtr)
1928 using HandleT = openvdb::points::AttributeHandle<AttT, CodecT>;
1929 forEach(0, mSrcNodeAcc.nodeCount(0), 16, [&](
const auto&
r) {
1930 auto *dstData = this->
template dstNode<DstBuildT,0>(r.begin())->
data();
1931 for (
auto i = r.begin(); i != r.end(); ++i, ++dstData) {
1932 auto& srcLeaf = mSrcNodeAcc.template node<0>(i);
1933 HandleT
handle(srcLeaf.constAttributeArray(attIdx));
1934 AttT *p = attPtr + dstData->mMinimum;
1935 for (
auto iter = srcLeaf.beginIndexOn(); iter; ++iter) *p++ =
handle.get(*iter);
1944 template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1945 typename disable_if<BuildTraits<DstBuildT>::is_index || BuildTraits<DstBuildT>::is_Fp, GridHandle<BufferT>>::type
1953 converter.setStats(sMode);
1954 converter.setChecksum(cMode);
1955 converter.setVerbose(verbose);
1956 return converter.template getHandle<DstBuildT, BufferT>(
buffer);
1961 template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1962 typename enable_if<BuildTraits<DstBuildT>::is_index, GridHandle<BufferT>>::type
1971 converter.setVerbose(verbose);
1972 return converter.template getHandle<DstBuildT, BufferT>(
channels, includeStats, includeTiles,
buffer);
1977 template<
typename SrcGr
idT,
typename DstBuildT,
typename OracleT,
typename BufferT>
1984 const OracleT &oracle,
1988 converter.setStats(sMode);
1989 converter.setChecksum(cMode);
1990 converter.enableDithering(ditherOn);
1991 converter.setVerbose(verbose);
1992 return converter.template getHandle<DstBuildT, OracleT, BufferT>(oracle,
buffer);
1997 template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1998 typename enable_if<BuildTraits<DstBuildT>::is_FpX, GridHandle<BufferT>>::type
2007 converter.setStats(sMode);
2008 converter.setChecksum(cMode);
2009 converter.enableDithering(ditherOn);
2010 converter.setVerbose(verbose);
2011 return converter.template getHandle<DstBuildT, BufferT>(
buffer);
2016 #if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
2017 template<
typename BufferT>
2019 openToNanoVDB(
const openvdb::GridBase::Ptr& base,
2027 using openvdb_Vec4fGrid = openvdb::Grid<openvdb_Vec4fTree>;
2028 using openvdb_Vec4dGrid = openvdb::Grid<openvdb_Vec4dTree>;
2029 using openvdb_UInt32Grid = openvdb::Grid<openvdb::UInt32Tree>;
2031 if (
auto grid = openvdb::GridBase::grid<openvdb::FloatGrid>(base)) {
2032 return createNanoGrid<openvdb::FloatGrid, float, BufferT>(*grid, sMode, cMode, verbose);
2033 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::DoubleGrid>(base)) {
2034 return createNanoGrid<openvdb::DoubleGrid, double, BufferT>(*grid, sMode, cMode, verbose);
2035 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int32Grid>(base)) {
2036 return createNanoGrid<openvdb::Int32Grid, int32_t,BufferT>(*grid, sMode, cMode, verbose);
2037 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int64Grid>(base)) {
2038 return createNanoGrid<openvdb::Int64Grid, int64_t, BufferT>(*grid, sMode, cMode, verbose);
2039 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_UInt32Grid>(base)) {
2040 return createNanoGrid<openvdb_UInt32Grid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2041 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3fGrid>(base)) {
2042 return createNanoGrid<openvdb::Vec3fGrid, nanovdb::Vec3f, BufferT>(*grid, sMode, cMode, verbose);
2043 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3dGrid>(base)) {
2044 return createNanoGrid<openvdb::Vec3dGrid, nanovdb::Vec3d, BufferT>(*grid, sMode, cMode, verbose);
2045 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::tools::PointIndexGrid>(base)) {
2046 return createNanoGrid<openvdb::tools::PointIndexGrid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2047 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::points::PointDataGrid>(base)) {
2048 return createNanoGrid<openvdb::points::PointDataGrid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2049 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::MaskGrid>(base)) {
2050 return createNanoGrid<openvdb::MaskGrid, nanovdb::ValueMask, BufferT>(*grid, sMode, cMode, verbose);
2051 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::BoolGrid>(base)) {
2052 return createNanoGrid<openvdb::BoolGrid, bool, BufferT>(*grid, sMode, cMode, verbose);
2053 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4fGrid>(base)) {
2054 return createNanoGrid<openvdb_Vec4fGrid, nanovdb::Vec4f, BufferT>(*grid, sMode, cMode, verbose);
2055 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4dGrid>(base)) {
2056 return createNanoGrid<openvdb_Vec4dGrid, nanovdb::Vec4d, BufferT>(*grid, sMode, cMode, verbose);
2058 OPENVDB_THROW(openvdb::RuntimeError,
"Unrecognized OpenVDB grid type");
2065 #endif // NANOVDB_CREATE_NANOGRID_H_HAS_BEEN_INCLUDED
PointIndex< Index32, 1 > PointDataIndex32
This file defines a minimum set of tree nodes and tools that can be used (instead of OpenVDB) to buil...
float getTolerance() const
auto data() FMT_NOEXCEPT-> T *
A simple vector class with three components, similar to openvdb::math::Vec3.
GridBlindDataClass
Blind-data Classes that are currently supported by NanoVDB.
bool operator()(float exact, float approx) const
Return true if the approximate value is within the accepted relative error bounds of the exact value...
__hostdev__ uint64_t pointCount() const
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...
std::string upper(string_view a)
Return an all-upper case version of a (locale-independent).
bool hasLongGridName() const
NodeManagerHandle manages the memory of a NodeManager.
gridName(grid.gridName())
Compression oracle based on absolute difference.
const TreeType & tree() const
float getTolerance() const
const RootType & root() const
GridType
List of types that are currently supported by NanoVDB.
uint64_t nodeCount(int level) const
Struct to derive node type from its level in a given grid, tree or root while preserving constness...
bool hasLongGridName() const
GridClass
Classes (superset of OpenVDB) that are currently supported by NanoVDB.
A unified wrapper for tbb::parallel_reduce and a naive std::future analog.
auto printf(const S &fmt, const T &...args) -> int
Creates any nanovdb Grid from any source grid (certain combinations are obviously not allowed) ...
typename GridType::ValueType ValueType
static constexpr bool IS_NANOVDB
GLsizei const GLchar *const * string
GLsizei const GLfloat * value
enable_if< BuildTraits< DstBuildT >::is_index >::type copyValues(SrcValueT *buffer)
Copy values from the source grid into a provided buffer.
NodeAccessor(const GridType &grid)
const nanovdb::Map & map() const
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
StatsMode
Grid flags which indicate what extra information is present in the grid buffer.
GLboolean GLboolean GLboolean GLboolean a
const std::string & getName() const
This is a buffer that contains a shared or private pool to either externally or internally managed ho...
T prefixSum(std::vector< T > &vec, bool threaded=true, OpT op=OpT())
Computes inclusive prefix sum of a vector.
ImageBuf OIIO_API min(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
**But if you need a or simply need to know when the task has note that the like this
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
void setTolerance(float tolerance)
NodeManager allows for sequential access to nodes.
GLdouble GLdouble GLdouble q
GridClass gridClass() const
Codec
Define compression codecs.
The NodeAccessor provides a uniform API for accessing nodes got NanoVDB, OpenVDB and build Grids...
typename GridT::TreeType TreeType
RelDiff(float tolerance=-1.0f)
Compression oracle based on relative difference.
typename GridType::TreeType TreeType
const nanovdb::Map & map() const
NANOVDB_HOSTDEV_DISABLE_WARNING __hostdev__ uint32_t CountOn(uint64_t v)
#define NANOVDB_ASSERT(x)
Defines GridHandle, which manages a host, and possibly a device, memory buffer containing one or more...
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.
__hostdev__ uint64_t memUsage() const
Return the actual memory footprint of this root node.
This class serves to manage a buffer containing one or more NanoVDB Grids.
Define static boolean tests for template build types.
CreateNanoGrid(const SrcGridT &srcGrid)
Constructor from a source grid.
Computes a pair of 32bit checksums, of a Grid, by means of Cyclic Redundancy Check (CRC) ...
typename TreeType::RootNodeType RootType
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
#define NANOVDB_DATA_ALIGNMENT
typename SrcNodeAccT::TreeType SrcTreeT
__hostdev__ uint64_t offset() const
GridBlindDataSemantic
Blind-data Semantics that are currently understood by NanoVDB.
void setVerbose(int mode=1)
Set the level of verbosity.
IMATH_NAMESPACE::V2f float
Defines look up table to do dithering of 8^3 leaf nodes.
std::ostream & operator<<(std::ostream &os, const AbsDiff &diff)
T reduce(RangeT range, const T &identity, const FuncT &func, const JoinT &join)
GridClass gridClass() const
__hostdev__ 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) ...
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation...
const TreeType & tree() const
Grid< PointDataTree > PointDataGrid
Point data grid.
void updateChecksum(NanoGrid< BuildT > &grid, ChecksumMode mode=ChecksumMode::Default)
Updates the checksum of a grid.
static __hostdev__ size_t memUsage()
Return memory usage in bytes for the class.
Range< 1, size_t > Range1D
GLdouble GLdouble GLint GLint order
void setStats(StatsMode mode=StatsMode::Default)
Set the mode used for computing statistics of the destination grid.
SYS_FORCE_INLINE float log2(float x)
GLuint const GLchar * name
Custom Range class that is compatible with the tbb::blocked_range classes.
typename GridT::BuildType BuildType
GLboolean GLboolean GLboolean b
NodeManagerHandle< BufferT > createNodeManager(const NanoGrid< BuildT > &grid, const BufferT &buffer=BufferT())
brief Construct a NodeManager and return its handle
MaskT< LOG2DIM > mValueMask
typename TreeType::RootType RootType
typename NodeTrait< SrcRootT, LEVEL >::type SrcNodeT
__hostdev__ Type Max(Type a, Type b)
const GridType & grid() const
const char * toStr(GridType gridType)
Maps a GridType to a c-string.
void enableDithering(bool on=true)
Enable or disable dithering, i.e. randomization of the quantization error.
ChecksumMode
List of different modes for computing for a checksum.
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...
bool operator()(float exact, float approx) const
Return true if the approximate value is within the accepted absolute error bounds of the exact value...
std::string lower(string_view a)
Return an all-upper case version of a (locale-independent).
NodeAccessor(const GridT &grid)
void init(nanovdb::GridClass gClass, float background)
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.
typename NodeTrait< const TreeType, LEVEL >::type NodeType
const NodeType< LEVEL > & node(uint32_t i) const
Space-partitioning acceleration structure for points. Partitions the points into voxels to accelerate...
Multi-threaded implementations of inclusive prefix sum.
Dummy type for a voxel whose value equals its binary active state.
Top-most node of the VDB tree structure.
typename SrcNodeAccT::ValueType SrcValueT
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
const RootType & root() const
typename NodeTrait< TreeType, LEVEL >::type NodeType
A simple vector class with four components, similar to openvdb::math::Vec4.
void setTolerance(float tolerance)
void setChecksum(ChecksumMode mode=ChecksumMode::Default)
Set the mode used for computing checksums of the destination grid.
uint64_t nodeCount(int level) const
static __hostdev__ uint64_t memUsage()
return memory usage in bytes for the class
GLubyte GLubyte GLubyte GLubyte w
tree::Tree< tree::RootNode< tree::InternalNode< tree::InternalNode< PointDataLeafNode< PointDataIndex32, 3 >, 4 >, 5 >>> PointDataTree
Point index tree configured to match the default VDB configurations.
typename SrcNodeAccT::RootType SrcRootT
const GridType & grid() const
typename GridT::ValueType ValueType
PointIndex< Index32, 0 > PointIndex32
Re-computes min/max/avg/var/bbox information for each node in a pre-existing NanoVDB grid...
uint64_t valueCount() const
This method only has affect when getHandle was called with DstBuildT = ValueIndex or ValueOnIndex...
Trait that maps any type to the corresponding nanovdb type.
Attribute-owned data structure for points. Point attributes are stored in leaf nodes and ordered by v...
typename SrcNodeAccT::BuildType SrcBuildT
HUSD_API const char * dataType()
A unified wrapper for tbb::parallel_invoke and a naive std::thread analog.
std::string getName() const
const NodeType< LEVEL > & node(uint32_t i) const
C++11 implementation of std::enable_if.
void gridStats(NanoGrid< BuildT > &grid, StatsMode mode=StatsMode::Default)
Re-computes the min/max, stats and bbox information for an existing NanoVDB Grid. ...
static constexpr bool IS_OPENVDB
NodeAccessor< SrcGridT > SrcNodeAccT
int invoke(const Func &taskFunc1, Rest...taskFuncN)
C++11 implementation of std::is_same.
#define OPENVDB_THROW(exception, message)
ImageBuf OIIO_API channels(const ImageBuf &src, int nchannels, cspan< int > channelorder, cspan< float > channelvalues={}, cspan< std::string > newchannelnames={}, bool shuffle_channel_names=false, int nthreads=0)
**Note that the tasks the is the thread number *for the pool
AbsDiff(float tolerance=-1.0f)