115#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
123template<
typename BufferT = HostBuffer>
125openToNanoVDB(
const openvdb::GridBase::Ptr& base,
139template<
typename DstBuildT = nanovdb::ValueOnIndex,
typename BufferT = HostBuffer>
141openToIndexVDB(
const openvdb::GridBase::Ptr& base,
142 uint32_t channels = 1u,
143 bool includeStats =
true,
144 bool includeTiles =
true,
160template<
typename SrcGridT,
168 const BufferT &buffer = BufferT());
186template<
typename SrcGridT,
191 uint32_t channels = 0u,
192 bool includeStats =
true,
193 bool includeTiles =
true,
195 const BufferT &buffer = BufferT());
212template<
typename SrcGridT,
220 bool ditherOn =
false,
222 const OracleT &oracle = OracleT(),
223 const BufferT &buffer = BufferT());
238template<
typename SrcGridT,
245 bool ditherOn =
false,
247 const BufferT &buffer = BufferT());
257 AbsDiff(
float tolerance = -1.0f) : mTolerance(tolerance) {}
260 operator bool()
const {
return mTolerance>=0.0f;}
263 static const float halfWidth = 3.0f;
264 mTolerance = 0.1f * background / halfWidth;
279 return math::Abs(exact - approx) <= mTolerance;
291 RelDiff(
float tolerance = -1.0f) : mTolerance(tolerance) {}
294 operator bool()
const {
return mTolerance>=0.0f;}
312template <
typename Gr
idT>
329 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
332 const std::string&
getName()
const {
return this->
grid().getName();};
344template <
typename BuildT>
360 , mMgr(*(mHandle.template mgr<BuildT>())) {}
364 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
367 std::string
getName()
const {
return std::string(this->
grid().gridName());};
383#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
397template <
typename BuildT>
398using OpenLeaf = openvdb::tree::LeafNode<BuildT,3>;
399template <
typename BuildT>
400using OpenLower = openvdb::tree::InternalNode<OpenLeaf<BuildT>,4>;
401template <
typename BuildT>
402using OpenUpper = openvdb::tree::InternalNode<OpenLower<BuildT>,5>;
403template <
typename BuildT>
404using OpenRoot = openvdb::tree::RootNode<OpenUpper<BuildT>>;
405template <
typename BuildT>
406using OpenTree = openvdb::tree::Tree<OpenRoot<BuildT>>;
407template <
typename BuildT>
408using OpenGrid = openvdb::Grid<OpenTree<BuildT>>;
413template <
typename BuildT>
421 using ValueType =
typename GridType::ValueType;
425 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
427 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
428 mMap.set(mat4, mat4.inverse());
433 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
436 std::string
getName()
const {
return this->
grid().getName(); };
438 const nanovdb::Map&
map()
const {
return mMap;}
453 build::NodeManager<GridType> mMgr;
467 using GridType = openvdb::tools::PointIndexGrid;
468 using TreeType = openvdb::tools::PointIndexTree;
469 using RootType =
typename TreeType::RootNodeType;
470 using ValueType =
typename GridType::ValueType;
472 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
474 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
475 mMap.set(mat4, mat4.inverse());
480 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
483 std::string
getName()
const {
return this->
grid().getName(); };
485 const nanovdb::Map&
map()
const {
return mMap;}
488 build::NodeManager<GridType> mMgr;
502 using GridType = openvdb::points::PointDataGrid;
503 using TreeType = openvdb::points::PointDataTree;
504 using RootType =
typename TreeType::RootNodeType;
505 using ValueType =
typename GridType::ValueType;
507 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
509 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
510 mMap.set(mat4, mat4.inverse());
515 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
518 std::string
getName()
const {
return this->
grid().getName(); };
520 const nanovdb::Map&
map()
const {
return mMap;}
523 build::NodeManager<GridType> mMgr;
532template <
typename SrcGr
idT>
576 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename BufferT =
HostBuffer>
579 getHandle(
const BufferT &buffer = BufferT());
589 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename OracleT =
AbsDiff,
typename BufferT =
HostBuffer>
591 getHandle(
const OracleT &oracle = OracleT(),
592 const BufferT &buffer = BufferT());
602 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename BufferT =
HostBuffer>
605 bool includeStats =
true,
606 bool includeTiles =
true,
607 const BufferT &buffer = BufferT());
621 size_t count,
size_t size)
623 const size_t order = mBlindMetaData.size();
624 mBlindMetaData.emplace(name, dataSemantic, dataClass, dataType, order, count, size);
631 uint64_t
valueCount()
const {
return mValIdx[0].empty() ? 0u : mValIdx[0].back();}
636 template <
typename DstBuildT>
644 template <
typename T,
int LEVEL>
646 dstNode(uint64_t i)
const {
647 static_assert(LEVEL==0 || LEVEL==1 || LEVEL==2,
"Expected LEVEL== {0,1,2}");
651 template <
typename T,
int LEVEL>
662 template <
typename DstBuildT>
666 template <
typename DstBuildT>
667 typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
668 preProcess(uint32_t channels);
670 template <
typename DstBuildT,
typename OracleT>
671 typename util::enable_if<util::is_same<FpN, DstBuildT>::value>::type
672 preProcess(OracleT oracle);
677 template<
typename DstBuildT,
typename BufferT>
678 GridHandle<BufferT> initHandle(
const BufferT& buffer);
682 template <
typename DstBuildT>
683 inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
684 postProcess(uint32_t channels);
686 template <
typename DstBuildT>
687 inline typename util::disable_if<BuildTraits<DstBuildT>::is_index>::type
692 template<
typename DstBuildT>
693 typename util::disable_if<BuildTraits<DstBuildT>::is_special>::type
696 template<
typename DstBuildT>
697 typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
700 template<
typename DstBuildT>
701 typename util::enable_if<BuildTraits<DstBuildT>::is_FpX>::type
704 template<
typename DstBuildT>
705 typename util::enable_if<util::is_same<FpN, DstBuildT>::value>::type
708 template<
typename DstBuildT>
709 typename util::enable_if<util::is_same<bool, DstBuildT>::value>::type
712 template<
typename DstBuildT>
713 typename util::enable_if<util::is_same<ValueMask, DstBuildT>::value>::type
718 template<
typename DstBuildT,
int LEVEL>
719 typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
720 processInternalNodes();
722 template<
typename DstBuildT,
int LEVEL>
723 typename util::enable_if<!BuildTraits<DstBuildT>::is_index>::type
724 processInternalNodes();
728 template <
typename DstBuildT>
729 typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
732 template <
typename DstBuildT>
733 typename util::enable_if<!BuildTraits<DstBuildT>::is_index>::type
738 template<
typename DstBuildT>
741 template<
typename DstBuildT>
744 template <
typename DstBuildT,
int LEVEL>
745 typename util::enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
748 template <
typename DstBuildT>
749 typename util::enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
752#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
753 template<
typename T = SrcGr
idT>
754 typename util::disable_if<util::is_same<T, openvdb::tools::PointIndexGrid>::value ||
758 template<
typename T = SrcGr
idT>
759 typename util::enable_if<util::is_same<T, openvdb::tools::PointIndexGrid>::value ||
763 template<
typename DstBuildT,
typename AttT,
typename CodecT = openvdb::po
ints::UnknownCodec,
typename T = SrcGr
idT>
764 typename util::enable_if<util::is_same<openvdb::points::PointDataGrid, T>::value>::type
765 copyPointAttribute(
size_t attIdx, AttT *attPtr);
767 uint64_t countPoints()
const {
return 0u;}
771 struct BufferOffsets {
772 uint64_t grid, tree, root, upper, lower, leaf, meta, blind, size;
773 uint64_t operator[](
int i)
const {
return *(
reinterpret_cast<const uint64_t*
>(
this)+i); }
776 uint64_t mLeafNodeSize;
778 std::unique_ptr<SrcNodeAccT> mSrcNodeAccPtr;
781 std::set<OrderedBlindMetaData> mBlindMetaData;
782 struct Codec {
float min, max; uint64_t offset; uint8_t log2; };
783 std::unique_ptr<Codec[]> mCodec;
786 bool mDitherOn, mIncludeStats, mIncludeTiles;
787 std::vector<uint64_t> mValIdx[3];
790template <
typename DstT,
typename SrcT>
793 return static_cast<DstT
>(val);
823template <
typename SrcGr
idT>
827 , mSrcNodeAcc(*mSrcNodeAccPtr)
831 , mIncludeStats(true)
832 , mIncludeTiles(true)
838template <
typename SrcGr
idT>
841 , mSrcNodeAccPtr(nullptr)
842 , mSrcNodeAcc(srcNodeAcc)
846 , mIncludeStats(true)
847 , mIncludeTiles(true)
853template <
typename SrcGr
idT>
857 const std::string& type,
859 size_t i,
size_t valueCount,
size_t valueSize)
863 if (!
metaData->setName(name.c_str()))
throw std::runtime_error(
"blind data name exceeds character limit");
870 size_t i,
size_t valueCount,
size_t valueSize)
874 if (!
metaData->setName(name.c_str()))
throw std::runtime_error(
"blind data name exceeds character limit");
882 if (
"uint32_t" == name) {
884 }
else if (
"float" == name) {
886 }
else if (
"vec3s"== name) {
888 }
else if (
"int32" == name) {
890 }
else if (
"int64" == name) {
903 }
else if (
"V" == name) {
905 }
else if (
"Cd" == name) {
907 }
else if (
"N" == name) {
909 }
else if (
"id" == name) {
921template <
typename SrcGr
idT>
922template<
typename DstBuildT,
typename BufferT>
927 this->
template preProcess<DstBuildT>();
928 auto handle = this->
template initHandle<DstBuildT>(pool);
929 this->
template postProcess<DstBuildT>();
935template <
typename SrcGr
idT>
936template<
typename DstBuildT,
typename OracleT,
typename BufferT>
940 this->
template preProcess<DstBuildT, OracleT>(oracle);
941 auto handle = this->
template initHandle<DstBuildT>(pool);
942 this->
template postProcess<DstBuildT>();
948template <
typename SrcGr
idT>
949template<
typename DstBuildT,
typename BufferT>
956 mIncludeStats = includeStats;
957 mIncludeTiles = includeTiles;
958 this->
template preProcess<DstBuildT>(channels);
959 auto handle = this->
template initHandle<DstBuildT>(pool);
960 this->
template postProcess<DstBuildT>(channels);
966template <
typename SrcGr
idT>
967template <
typename DstBuildT,
typename BufferT>
976 mOffset.meta = mOffset.leaf + mLeafNodeSize;
978 mOffset.size = mOffset.blind;
979 for (
const auto& b : mBlindMetaData) mOffset.size += b.memUsage();
981 auto buffer = BufferT::create(mOffset.size, &pool);
982 mBufferPtr = buffer.data();
985 util::invoke( [&](){this->
template processLeafs<DstBuildT>();},
986 [&](){this->
template processInternalNodes<DstBuildT, 1>();},
987 [&](){this->
template processInternalNodes<DstBuildT, 2>();},
988 [&](){this->
template processRoot<DstBuildT>();},
989 [&](){this->
template processTree<DstBuildT>();},
990 [&](){this->
template processGrid<DstBuildT>();} );
992 return GridHandle<BufferT>(std::move(buffer));
997template <
typename SrcGr
idT>
998template <
typename DstBuildT>
1000CreateNanoGrid<SrcGridT>::preProcess()
1002 if (
const uint64_t pointCount = this->countPoints()) {
1003#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1005 if (!mBlindMetaData.empty())
throw std::runtime_error(
"expected no blind meta data");
1006 this->addBlindData(
"index",
1013 if (!mBlindMetaData.empty())
throw std::runtime_error(
"expected no blind meta data");
1014 auto &srcLeaf = mSrcNodeAcc.template node<0>(0);
1015 const auto& attributeSet = srcLeaf.attributeSet();
1016 const auto& descriptor = attributeSet.descriptor();
1017 const auto& nameMap = descriptor.map();
1018 for (
auto it = nameMap.begin(); it != nameMap.end(); ++it) {
1019 const size_t index = it->second;
1020 auto& attArray = srcLeaf.constAttributeArray(index);
1021 mBlindMetaData.emplace(it->first,
1022 descriptor.valueType(index),
1026 attArray.valueTypeSize());
1031 if (mSrcNodeAcc.hasLongGridName()) {
1032 this->addBlindData(
"grid name",
1036 mSrcNodeAcc.getName().length() + 1, 1);
1043template <
typename SrcGr
idT>
1044template <
typename DstBuildT,
typename OracleT>
1045inline typename util::enable_if<util::is_same<FpN, DstBuildT>::value>::type
1046CreateNanoGrid<SrcGridT>::preProcess(OracleT oracle)
1050 const size_t leafCount = mSrcNodeAcc.nodeCount(0);
1055 mCodec.
reset(
new Codec[leafCount]);
1058 if (!oracle) oracle.init(mSrcNodeAcc.gridClass(), mSrcNodeAcc.root().background());
1061 math::DitherLUT lut(mDitherOn);
1063 for (
auto i=r.begin(); i!=r.end(); ++i) {
1064 const auto &srcLeaf = mSrcNodeAcc.template node<0>(
static_cast<uint32_t
>(i));
1065 float &
min = mCodec[i].min = std::numeric_limits<float>::max();
1066 float &
max = mCodec[i].max = -
min;
1067 for (
int j=0; j<512; ++j) {
1068 float v = srcLeaf.getValue(j);
1072 const float range =
max -
min;
1073 uint8_t &logBitWidth = mCodec[i].log2 = 0;
1074 while (range > 0.0f && logBitWidth < 4u) {
1075 const uint32_t mask = (uint32_t(1) << (uint32_t(1) << logBitWidth)) - 1u;
1076 const float encode = float(mask)/range;
1077 const float decode = range/float(mask);
1080 const float exact = srcLeaf.getValue(j);
1081 const uint32_t code = uint32_t(encode*(exact - min) + lut(j));
1082 const float approx = float(code) * decode +
min;
1083 j += oracle(exact, approx) ? 1 : 513;
1085 if (j == 512)
break;
1091 auto getOffset = [&](
size_t i){
1100 for (
size_t i=1; i<leafCount; ++i) mCodec[i].offset = getOffset(i);
1101 mLeafNodeSize = getOffset(leafCount);
1104 uint32_t counters[5+1] = {0};
1105 ++counters[mCodec[0].log2];
1106 for (
size_t i=1; i<leafCount; ++i) ++counters[mCodec[i].log2];
1107 std::cout <<
"\n" << oracle << std::endl;
1108 std::cout <<
"Dithering: " << (mDitherOn ?
"enabled" :
"disabled") << std::endl;
1110 for (uint32_t i=0; i<=5; ++i) {
1111 if (uint32_t n = counters[i]) {
1112 avg += float(n) * float(1 << i);
1113 printf(
"%2i bits: %6u leaf nodes, i.e. %4.1f%%\n",1<<i, n, 100.0f*
float(n)/
float(leafCount));
1116 printf(
"%4.1f bits per value on average\n", avg/
float(leafCount));
1119 if (mSrcNodeAcc.hasLongGridName()) {
1120 this->addBlindData(
"grid name",
1124 mSrcNodeAcc.getName().length() + 1, 1);
1130template <
typename SrcGr
idT>
1131template <
typename DstBuildT,
int LEVEL>
1132inline typename util::enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
1133CreateNanoGrid<SrcGridT>::countTileValues(uint64_t valueCount)
1135 const uint64_t stats = mIncludeStats ? 4u : 0u;
1136 mValIdx[LEVEL].clear();
1137 mValIdx[LEVEL].resize(mSrcNodeAcc.nodeCount(LEVEL) + 1, stats);
1139 for (
auto i = r.begin(); i!=r.end(); ++i) {
1140 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(
static_cast<uint32_t
>(i-1));
1142 mValIdx[LEVEL][i] += srcNode.getValueMask().countOn();
1144 static const uint64_t maxTileCount = uint64_t(1u) << 3*srcNode.LOG2DIM;
1145 mValIdx[LEVEL][i] += maxTileCount - srcNode.getChildMask().countOn();
1149 mValIdx[LEVEL][0] = valueCount;
1150 for (
size_t i=1; i<mValIdx[LEVEL].size(); ++i) mValIdx[LEVEL][i] += mValIdx[LEVEL][i-1];
1151 return mValIdx[LEVEL].back();
1156template <
typename SrcGr
idT>
1157template <
typename DstBuildT>
1158inline typename util::enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
1159CreateNanoGrid<SrcGridT>::countValues()
1161 const uint64_t stats = mIncludeStats ? 4u : 0u;
1162 uint64_t valueCount = 1u;
1163 if (mIncludeTiles) {
1165 for (
auto it = mSrcNodeAcc.root().cbeginValueOn(); it; ++it) ++valueCount;
1167 for (
auto it = mSrcNodeAcc.root().cbeginValueAll(); it; ++it) ++valueCount;
1169 valueCount += stats;
1170 valueCount = countTileValues<DstBuildT, 2>(valueCount);
1171 valueCount = countTileValues<DstBuildT, 1>(valueCount);
1174 mValIdx[0].resize(mSrcNodeAcc.nodeCount(0) + 1, 512u + stats);
1177 for (
auto i = r.begin(); i != r.end(); ++i) {
1178 mValIdx[0][i] = stats;
1179 mValIdx[0][i] += mSrcNodeAcc.template node<0>(
static_cast<uint32_t
>(i-1)).getValueMask().countOn();
1183 mValIdx[0][0] = valueCount;
1185 return mValIdx[0].back();
1190template <
typename SrcGr
idT>
1191template <
typename DstBuildT>
1192inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1193CreateNanoGrid<SrcGridT>::preProcess(uint32_t channels)
1195 const uint64_t valueCount = this->
template countValues<DstBuildT>();
1198 size_t order = mBlindMetaData.size();
1200 for (uint32_t i=0; i<channels; ++i) {
1201 mBlindMetaData.emplace(
"channel_" + std::to_string(i),
1208 if (mSrcNodeAcc.hasLongGridName()) {
1209 this->addBlindData(
"grid name",
1213 mSrcNodeAcc.getName().length() + 1, 1);
1219template <
typename SrcGr
idT>
1220template <
typename DstBuildT>
1221inline typename util::disable_if<BuildTraits<DstBuildT>::is_special>::type
1222CreateNanoGrid<SrcGridT>::processLeafs()
1225 using DstValueT =
typename DstDataT::ValueType;
1226 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<T> to have fixed size");
1228 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1229 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1230 auto &srcLeaf = mSrcNodeAcc.template node<0>(static_cast<uint32_t>(i));
1231 if (DstDataT::padding()>0u) {
1232 util::memzero(dstLeaf, DstDataT::memUsage());
1234 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1235 dstLeaf->mFlags = 0u;
1236 dstLeaf->mMinimum = dstLeaf->mMaximum = typename DstDataT::ValueType();
1237 dstLeaf->mAverage = dstLeaf->mStdDevi = 0;
1239 dstLeaf->mBBoxMin = srcLeaf.origin();
1240 dstLeaf->mValueMask = srcLeaf.getValueMask();
1241 DstValueT *dst = dstLeaf->mValues;
1242 if constexpr(util::is_same<DstValueT, SrcValueT>::value && SrcNodeAccT::IS_OPENVDB) {
1243 const SrcValueT *src = srcLeaf.buffer().data();
1244 for (auto *end = dst + 512u; dst != end; dst += 4, src += 4) {
1251 for (uint32_t j=0; j<512u; ++j) *dst++ = CreateNanoGridValueCast<DstValueT>(srcLeaf.getValue(j));
1259template <
typename SrcGr
idT>
1260template <
typename DstBuildT>
1262CreateNanoGrid<SrcGridT>::processLeafs()
1265 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<ValueIndex> to have fixed size");
1266 static_assert(DstDataT::padding()==0u,
"Expected leaf nodes to have no padding");
1269 const uint8_t flags = mIncludeStats ? 16u : 0u;
1270 DstDataT *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1271 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1272 auto &srcLeaf = mSrcNodeAcc.template node<0>(static_cast<uint32_t>(i));
1273 dstLeaf->mBBoxMin = srcLeaf.origin();
1274 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1275 dstLeaf->mFlags = flags;
1276 dstLeaf->mValueMask = srcLeaf.getValueMask();
1277 dstLeaf->mOffset = mValIdx[0][i];
1278 if constexpr(BuildTraits<DstBuildT>::is_onindex) {
1279 const uint64_t *w = dstLeaf->mValueMask.words();
1280#ifdef USE_OLD_VALUE_ON_INDEX
1281 int32_t sum = util::countOn(*w++);
1282 uint8_t *p = reinterpret_cast<uint8_t*>(&dstLeaf->mPrefixSum), *q = p + 7;
1283 for (int j=0; j<7; ++j) {
1285 *q |= (sum >> 8) << j;
1286 sum += util::countOn(*w++);
1289 uint64_t &prefixSum = dstLeaf->mPrefixSum, sum = util::countOn(*w++);
1291 for (int n = 9; n < 55; n += 9) {
1292 sum += util::countOn(*w++);
1293 prefixSum |= sum << n;
1297 dstLeaf->mPrefixSum = 0u;
1305template <
typename SrcGr
idT>
1306template <
typename DstBuildT>
1307inline typename util::enable_if<util::is_same<ValueMask, DstBuildT>::value>::type
1308CreateNanoGrid<SrcGridT>::processLeafs()
1310 using DstDataT =
typename NanoLeaf<ValueMask>::DataType;
1311 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<ValueMask> to have fixed size");
1312 util::forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const util::Range1D& r) {
1313 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1314 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1315 auto &srcLeaf = mSrcNodeAcc.template node<0>(static_cast<uint32_t>(i));
1316 if (DstDataT::padding()>0u) {
1317 util::memzero(dstLeaf, DstDataT::memUsage());
1319 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1320 dstLeaf->mFlags = 0u;
1321 dstLeaf->mPadding[0] = dstLeaf->mPadding[1] = 0u;
1323 dstLeaf->mBBoxMin = srcLeaf.origin();
1324 dstLeaf->mValueMask = srcLeaf.getValueMask();
1331template <
typename SrcGr
idT>
1332template <
typename DstBuildT>
1333inline typename util::enable_if<util::is_same<bool, DstBuildT>::value>::type
1334CreateNanoGrid<SrcGridT>::processLeafs()
1336 using DstDataT =
typename NanoLeaf<bool>::DataType;
1337 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<bool> to have fixed size");
1338 util::forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const util::Range1D& r) {
1339 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1340 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1341 auto &srcLeaf = mSrcNodeAcc.template node<0>(static_cast<uint32_t>(i));
1342 if (DstDataT::padding()>0u) {
1343 util::memzero(dstLeaf, DstDataT::memUsage());
1345 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1346 dstLeaf->mFlags = 0u;
1348 dstLeaf->mBBoxMin = srcLeaf.origin();
1349 dstLeaf->mValueMask = srcLeaf.getValueMask();
1350 if constexpr(!util::is_same<bool, SrcBuildT>::value) {
1351 for (int j=0; j<512; ++j) dstLeaf->mValues.set(j, static_cast<bool>(srcLeaf.getValue(j)));
1352 } else if constexpr(SrcNodeAccT::IS_OPENVDB) {
1353 dstLeaf->mValues = *reinterpret_cast<const Mask<3>*>(srcLeaf.buffer().data());
1354 } else if constexpr(SrcNodeAccT::IS_NANOVDB) {
1355 dstLeaf->mValues = srcLeaf.data()->mValues;
1357 dstLeaf->mValues = srcLeaf.mValues;
1365template <
typename SrcGr
idT>
1366template <
typename DstBuildT>
1367inline typename util::enable_if<BuildTraits<DstBuildT>::is_FpX>::type
1368CreateNanoGrid<SrcGridT>::processLeafs()
1370 using DstDataT =
typename NanoLeaf<DstBuildT>::DataType;
1371 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<Fp4|Fp8|Fp16> to have fixed size");
1372 using ArrayT =
typename DstDataT::ArrayType;
1373 static_assert(util::is_same<float, SrcValueT>::value,
"Expected ValueT == float");
1374 using FloatT =
typename std::conditional<DstDataT::bitWidth()>=16, double,
float>::type;
1375 static constexpr FloatT UNITS = FloatT((1 << DstDataT::bitWidth()) - 1);
1376 math::DitherLUT lut(mDitherOn);
1378 util::forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const util::Range1D& r) {
1379 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1380 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1381 auto &srcLeaf = mSrcNodeAcc.template node<0>(static_cast<uint32_t>(i));
1382 if (DstDataT::padding()>0u) {
1383 util::memzero(dstLeaf, DstDataT::memUsage());
1385 dstLeaf->mFlags = dstLeaf->mBBoxDif[2] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[0] = 0u;
1386 dstLeaf->mDev = dstLeaf->mAvg = dstLeaf->mMax = dstLeaf->mMin = 0u;
1388 dstLeaf->mBBoxMin = srcLeaf.origin();
1389 dstLeaf->mValueMask = srcLeaf.getValueMask();
1391 float min = std::numeric_limits<float>::max(), max = -min;
1392 for (uint32_t j=0; j<512u; ++j) {
1393 const float v = srcLeaf.getValue(j);
1394 if (v < min) min = v;
1395 if (v > max) max = v;
1397 dstLeaf->init(min, max, DstDataT::bitWidth());
1399 const FloatT encode = UNITS/(max-min);
1400 uint32_t offset = 0;
1401 auto quantize = [&]()->ArrayT{
1402 const ArrayT tmp = static_cast<ArrayT>(encode * (srcLeaf.getValue(offset) - min) + lut(offset));
1406 auto *code = reinterpret_cast<ArrayT*>(dstLeaf->mCode);
1407 if (util::is_same<Fp4, DstBuildT>::value) {
1408 for (uint32_t j=0; j<128u; ++j) {
1409 auto tmp = quantize();
1410 *code++ = static_cast<ArrayT>(quantize() << 4 | tmp);
1412 *code++ = static_cast<ArrayT>(quantize() << 4 | tmp);
1415 for (uint32_t j=0; j<128u; ++j) {
1416 *code++ = quantize();
1417 *code++ = quantize();
1418 *code++ = quantize();
1419 *code++ = quantize();
1428template <
typename SrcGr
idT>
1429template <
typename DstBuildT>
1430inline typename util::enable_if<util::is_same<FpN, DstBuildT>::value>::type
1431CreateNanoGrid<SrcGridT>::processLeafs()
1433 static_assert(util::is_same<float, SrcValueT>::value,
"Expected SrcValueT == float");
1434 math::DitherLUT lut(mDitherOn);
1435 util::forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const util::Range1D& r) {
1436 for (auto i = r.begin(); i != r.end(); ++i) {
1437 auto &srcLeaf = mSrcNodeAcc.template node<0>(static_cast<uint32_t>(i));
1438 auto *dstLeaf = this->template dstNode<DstBuildT,0>(i);
1439 dstLeaf->mBBoxMin = srcLeaf.origin();
1440 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1441 const uint8_t logBitWidth = mCodec[i].log2;
1442 dstLeaf->mFlags = static_cast<uint8_t>(logBitWidth << 5);
1443 dstLeaf->mValueMask = srcLeaf.getValueMask();
1444 const float min = mCodec[i].min, max = mCodec[i].max;
1445 dstLeaf->init(min, max, static_cast<uint8_t>(1u << logBitWidth));
1447 uint32_t offset = 0;
1448 float encode = 0.0f;
1449 auto quantize = [&]()->uint8_t{
1450 const uint8_t tmp = static_cast<uint8_t>(encode * (srcLeaf.getValue(offset) - min) + lut(offset));
1454 auto *dst = reinterpret_cast<uint8_t*>(dstLeaf+1);
1455 switch (logBitWidth) {
1457 encode = 1.0f/(max - min);
1458 for (int j=0; j<64; ++j) {
1460 for (int k=0; k<8; ++k) a |= quantize() << k;
1466 encode = 3.0f/(max - min);
1467 for (int j=0; j<128; ++j) {
1468 auto a = quantize();
1469 a |= quantize() << 2;
1470 a |= quantize() << 4;
1471 *dst++ = static_cast<uint8_t>(quantize() << 6 | a);
1476 encode = 15.0f/(max - min);
1477 for (int j=0; j<128; ++j) {
1478 auto a = quantize();
1479 *dst++ = static_cast<uint8_t>(quantize() << 4 | a);
1481 *dst++ = static_cast<uint8_t>(quantize() << 4 | a);
1486 encode = 255.0f/(max - min);
1487 for (int j=0; j<128; ++j) {
1488 *dst++ = quantize();
1489 *dst++ = quantize();
1490 *dst++ = quantize();
1491 *dst++ = quantize();
1496 auto *dst = reinterpret_cast<uint16_t*>(dstLeaf+1);
1497 const double encode = 65535.0/(max - min);
1498 for (int j=0; j<128; ++j) {
1499 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1500 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1501 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1502 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1512template <
typename SrcGr
idT>
1513template <
typename DstBuildT,
int LEVEL>
1514inline typename util::enable_if<!BuildTraits<DstBuildT>::is_index>::type
1515CreateNanoGrid<SrcGridT>::processInternalNodes()
1517 using DstNodeT =
typename NanoNode<DstBuildT, LEVEL>::type;
1518 using DstValueT =
typename DstNodeT::ValueType;
1519 using DstChildT =
typename NanoNode<DstBuildT, LEVEL-1>::type;
1520 static_assert(LEVEL == 1 || LEVEL == 2,
"Expected internal node");
1522 const uint64_t nodeCount = mSrcNodeAcc.nodeCount(LEVEL);
1523 if (nodeCount > 0) {
1524 uint64_t childCount = 0;
1525 auto *dstNode = this->
template dstNode<DstBuildT,LEVEL>(0);
1526 for (uint64_t i=0; i<nodeCount; ++i) {
1527 dstNode[i].mFlags = childCount;
1528 childCount += mSrcNodeAcc.template node<LEVEL>(
static_cast<uint32_t
>(i)).getChildMask().countOn();
1532 util::forEach(0, nodeCount, 4, [&](
const util::Range1D& r) {
1533 auto *dstNode = this->
template dstNode<DstBuildT,LEVEL>(r.begin());
1534 for (
auto i = r.begin(); i != r.end(); ++i, ++dstNode) {
1535 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(
static_cast<uint32_t
>(i));
1536 uint64_t childID = dstNode->mFlags;
1537 if (DstNodeT::DataType::padding()>0u) {
1538 util::memzero(dstNode, DstNodeT::memUsage());
1540 dstNode->mFlags = 0;
1541 dstNode->mMinimum = dstNode->mMaximum =
typename DstNodeT::ValueType();
1542 dstNode->mAverage = dstNode->mStdDevi = 0;
1544 dstNode->mBBox[0] = srcNode.origin();
1545 dstNode->mValueMask = srcNode.getValueMask();
1546 dstNode->mChildMask = srcNode.getChildMask();
1547 for (
auto it = srcNode.cbeginChildAll(); it; ++it) {
1549 if (it.probeChild(value)) {
1550 DstChildT *dstChild = this->
template dstNode<DstBuildT,LEVEL-1>(childID++);
1551 dstNode->setChild(it.pos(), dstChild);
1553 dstNode->setValue(it.pos(), CreateNanoGridValueCast<DstValueT>(value));
1562template <
typename SrcGr
idT>
1563template <
typename DstBuildT,
int LEVEL>
1564inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1565CreateNanoGrid<SrcGridT>::processInternalNodes()
1567 using DstNodeT =
typename NanoNode<DstBuildT, LEVEL>::type;
1568 using DstChildT =
typename NanoNode<DstBuildT, LEVEL-1>::type;
1569 static_assert(LEVEL == 1 || LEVEL == 2,
"Expected internal node");
1570 static_assert(DstNodeT::DataType::padding()==0u,
"Expected internal nodes to have no padding");
1572 const uint64_t nodeCount = mSrcNodeAcc.nodeCount(LEVEL);
1573 if (nodeCount > 0) {
1574 uint64_t childCount = 0;
1575 auto *dstNode = this->
template dstNode<DstBuildT,LEVEL>(0);
1576 for (uint64_t i=0; i<nodeCount; ++i) {
1577 dstNode[i].mFlags = childCount;
1578 childCount += mSrcNodeAcc.template node<LEVEL>(
static_cast<uint32_t
>(i)).getChildMask().countOn();
1582 util::forEach(0, nodeCount, 4, [&](
const util::Range1D& r) {
1583 auto *dstNode = this->
template dstNode<DstBuildT,LEVEL>(r.begin());
1584 for (
auto i = r.begin(); i != r.end(); ++i, ++dstNode) {
1585 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(
static_cast<uint32_t
>(i));
1586 uint64_t childID = dstNode->mFlags;
1587 dstNode->mFlags = 0u;
1588 dstNode->mBBox[0] = srcNode.origin();
1589 dstNode->mValueMask = srcNode.getValueMask();
1590 dstNode->mChildMask = srcNode.getChildMask();
1591 uint64_t n = mIncludeTiles ? mValIdx[LEVEL][i] : 0u;
1592 for (
auto it = srcNode.cbeginChildAll(); it; ++it) {
1594 if (it.probeChild(value)) {
1595 DstChildT *dstChild = this->
template dstNode<DstBuildT,LEVEL-1>(childID++);
1596 dstNode->setChild(it.pos(), dstChild);
1599 if (mIncludeTiles && !((BuildTraits<DstBuildT>::is_onindex) && dstNode->mValueMask.isOff(it.pos()))) m = n++;
1600 dstNode->setValue(it.pos(), m);
1603 if (mIncludeTiles && mIncludeStats) {
1604 dstNode->mMinimum = n++;
1605 dstNode->mMaximum = n++;
1606 dstNode->mAverage = n++;
1607 dstNode->mStdDevi = n++;
1609 dstNode->mMinimum = 0u;
1610 dstNode->mMaximum = 0u;
1611 dstNode->mAverage = 0u;
1612 dstNode->mStdDevi = 0u;
1620template <
typename SrcGr
idT>
1621template <
typename DstBuildT>
1622inline typename util::enable_if<!BuildTraits<DstBuildT>::is_index>::type
1623CreateNanoGrid<SrcGridT>::processRoot()
1625 using DstRootT = NanoRoot<DstBuildT>;
1626 using DstValueT =
typename DstRootT::ValueType;
1627 auto &srcRoot = mSrcNodeAcc.root();
1628 auto *dstRoot = this->
template dstRoot<DstBuildT>();
1629 const uint32_t tableSize = srcRoot.getTableSize();
1630 if (DstRootT::DataType::padding()>0) util::memzero(dstRoot, DstRootT::memUsage(tableSize));
1631 dstRoot->mTableSize = tableSize;
1632 dstRoot->mMinimum = dstRoot->mMaximum = dstRoot->mBackground = CreateNanoGridValueCast<DstValueT>(srcRoot.background());
1634 if (tableSize==0)
return;
1635 auto *dstChild = this->
template dstNode<DstBuildT, 2>(0);
1636 auto *dstTile = dstRoot->tile(0);
1637 for (
auto it = srcRoot.cbeginChildAll(); it; ++it, ++dstTile) {
1639 if (it.probeChild(value)) {
1640 dstTile->setChild(it.getCoord(), dstChild++, dstRoot);
1642 dstTile->setValue(it.getCoord(), it.isValueOn(), CreateNanoGridValueCast<DstValueT>(value));
1649template <
typename SrcGr
idT>
1650template <
typename DstBuildT>
1651inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1652CreateNanoGrid<SrcGridT>::processRoot()
1654 using DstRootT = NanoRoot<DstBuildT>;
1655 auto &srcRoot = mSrcNodeAcc.root();
1656 auto *dstRoot = this->
template dstRoot<DstBuildT>();
1657 const uint32_t tableSize = srcRoot.getTableSize();
1658 if (DstRootT::DataType::padding()>0) util::memzero(dstRoot, DstRootT::memUsage(tableSize));
1659 dstRoot->mTableSize = tableSize;
1660 dstRoot->mBackground = 0u;
1661 uint64_t valueCount = 0u;
1665 auto *dstChild = this->
template dstNode<DstBuildT, 2>(0);
1666 auto *dstTile = dstRoot->tile(0);
1667 for (
auto it = srcRoot.cbeginChildAll(); it; ++it, ++dstTile) {
1669 if (it.probeChild(tmp)) {
1670 dstTile->setChild(it.getCoord(), dstChild++, dstRoot);
1672 dstTile->setValue(it.getCoord(), it.isValueOn(), 0u);
1673 if (mIncludeTiles && !((BuildTraits<DstBuildT>::is_onindex) && !dstTile->state)) dstTile->value = ++valueCount;
1677 if (mIncludeTiles && mIncludeStats) {
1678 dstRoot->mMinimum = ++valueCount;
1679 dstRoot->mMaximum = ++valueCount;
1680 dstRoot->mAverage = ++valueCount;
1681 dstRoot->mStdDevi = ++valueCount;
1682 }
else if (dstRoot->padding()==0) {
1683 dstRoot->mMinimum = 0u;
1684 dstRoot->mMaximum = 0u;
1685 dstRoot->mAverage = 0u;
1686 dstRoot->mStdDevi = 0u;
1692template <
typename SrcGr
idT>
1693template <
typename DstBuildT>
1694void CreateNanoGrid<SrcGridT>::processTree()
1696 const uint64_t nodeCount[3] = {mSrcNodeAcc.nodeCount(0), mSrcNodeAcc.nodeCount(1), mSrcNodeAcc.nodeCount(2)};
1697 auto *dstTree = this->
template dstTree<DstBuildT>();
1698 dstTree->setRoot( this->
template dstRoot<DstBuildT>() );
1699 dstTree->setFirstNode(nodeCount[2] ? this->
template dstNode<DstBuildT, 2>(0) :
nullptr);
1700 dstTree->setFirstNode(nodeCount[1] ? this->
template dstNode<DstBuildT, 1>(0) :
nullptr);
1701 dstTree->setFirstNode(nodeCount[0] ? this->
template dstNode<DstBuildT, 0>(0) :
nullptr);
1703 dstTree->mNodeCount[0] =
static_cast<uint32_t
>(nodeCount[0]);
1704 dstTree->mNodeCount[1] =
static_cast<uint32_t
>(nodeCount[1]);
1705 dstTree->mNodeCount[2] =
static_cast<uint32_t
>(nodeCount[2]);
1708 dstTree->mTileCount[0] = util::reduce(util::Range1D(0,nodeCount[1]), uint32_t(0), [&](
const util::Range1D &r, uint32_t sum){
1709 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<1>(
static_cast<uint32_t
>(i)).getValueMask().countOn();
1710 return sum;}, std::plus<uint32_t>());
1713 dstTree->mTileCount[1] = util::reduce(util::Range1D(0,nodeCount[2]), uint32_t(0), [&](
const util::Range1D &r, uint32_t sum){
1714 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<2>(
static_cast<uint32_t
>(i)).getValueMask().countOn();
1715 return sum;}, std::plus<uint32_t>());
1718 dstTree->mTileCount[2] = 0;
1719 for (
auto it = mSrcNodeAcc.root().cbeginValueOn(); it; ++it) dstTree->mTileCount[2] += 1;
1722 dstTree->mVoxelCount = util::reduce(util::Range1D(0, nodeCount[0]), uint64_t(0), [&](
const util::Range1D &r, uint64_t sum){
1723 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<0>(
static_cast<uint32_t
>(i)).getValueMask().countOn();
1724 return sum;}, std::plus<uint64_t>());
1726 dstTree->mVoxelCount += uint64_t(dstTree->mTileCount[0]) << 9;
1727 dstTree->mVoxelCount += uint64_t(dstTree->mTileCount[1]) << 21;
1728 dstTree->mVoxelCount += uint64_t(dstTree->mTileCount[2]) << 36;
1734template <
typename SrcGr
idT>
1735template <
typename DstBuildT>
1736void CreateNanoGrid<SrcGridT>::processGrid()
1738 auto* dstGrid = this->
template dstGrid<DstBuildT>();
1739 dstGrid->init({GridFlags::IsBreadthFirst}, mOffset.size, mSrcNodeAcc.map(),
1740 toGridType<DstBuildT>(), toGridClass<DstBuildT>(mSrcNodeAcc.gridClass()));
1741 dstGrid->mBlindMetadataCount =
static_cast<uint32_t
>(mBlindMetaData.size());
1742 dstGrid->mData1 = this->valueCount();
1744 util::memzero(dstGrid->mGridName, GridData::MaxNameSize);
1745 strncpy(dstGrid->mGridName, mSrcNodeAcc.getName().c_str(), GridData::MaxNameSize-1);
1746 if (mSrcNodeAcc.hasLongGridName()) dstGrid->setLongGridNameOn();
1749 if (mBlindMetaData.size()>0) {
1750 auto *metaData = this->dstMeta(0);
1751 dstGrid->mBlindMetadataOffset = util::PtrDiff(metaData, dstGrid);
1752 dstGrid->mBlindMetadataCount =
static_cast<uint32_t
>(mBlindMetaData.size());
1753 char *blindData = util::PtrAdd<char>(mBufferPtr, mOffset.blind);
1754 for (
const auto &b : mBlindMetaData) {
1755 *metaData = *b.metaData;
1756 metaData->setBlindData(blindData);
1757 if (metaData->mDataClass == GridBlindDataClass::GridName)
strcpy(blindData, mSrcNodeAcc.getName().c_str());
1759 blindData += b.memUsage();
1761 mBlindMetaData.clear();
1767template <
typename SrcGr
idT>
1768template <
typename DstBuildT>
1769inline typename util::disable_if<BuildTraits<DstBuildT>::is_index>::type
1770CreateNanoGrid<SrcGridT>::postProcess()
1772 if constexpr(util::is_same<FpN, DstBuildT>::value) mCodec.reset();
1773 auto *dstGrid = this->
template dstGrid<DstBuildT>();
1775#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1776 auto *metaData = this->dstMeta(0);
1777 if constexpr(util::is_same<openvdb::tools::PointIndexGrid, SrcGridT>::value ||
1778 util::is_same<openvdb::points::PointDataGrid, SrcGridT>::value) {
1779 static_assert(util::is_same<DstBuildT, uint32_t>::value,
"expected DstBuildT==uint32_t");
1780 auto *dstData0 = this->
template dstNode<DstBuildT,0>(0)->data();
1781 dstData0->mMinimum = 0;
1782 dstData0->mMaximum = dstData0->mValues[511u];
1783 for (uint64_t i=1, n=mSrcNodeAcc.nodeCount(0); i<n; ++i) {
1784 auto *dstData1 = dstData0 + 1;
1785 dstData1->mMinimum = dstData0->mMinimum + dstData0->mMaximum;
1786 dstData1->mMaximum = dstData1->mValues[511u];
1787 dstData0 = dstData1;
1789 for (uint32_t i = 0, n = dstGrid->blindDataCount(); i < n; ++i, ++metaData) {
1790 if constexpr(util::is_same<openvdb::tools::PointIndexGrid, SrcGridT>::value) {
1791 if (metaData->mDataClass != GridBlindDataClass::IndexArray)
continue;
1792 if (metaData->mDataType == GridType::UInt32) {
1793 uint32_t *blindData =
const_cast<uint32_t*
>(metaData->template getBlindData<uint32_t>());
1794 util::forEach(0, mSrcNodeAcc.nodeCount(0), 16, [&](
const auto& r) {
1795 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1796 for (auto j = r.begin(); j != r.end(); ++j, ++dstLeaf) {
1797 uint32_t* p = blindData + dstLeaf->mMinimum;
1798 for (uint32_t idx : mSrcNodeAcc.template node<0>(static_cast<uint32_t>(j)).indices()) *p++ = idx;
1803 if (metaData->mDataClass != GridBlindDataClass::AttributeArray)
continue;
1804 if (
auto *blindData = dstGrid->template getBlindData<float>(i)) {
1805 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1806 }
else if (
auto *blindData = dstGrid->template getBlindData<nanovdb::Vec3f>(i)) {
1807 this->
template copyPointAttribute<DstBuildT>(i,
reinterpret_cast<openvdb::Vec3f*
>(blindData));
1808 }
else if (
auto *blindData = dstGrid->template getBlindData<int32_t>(i)) {
1809 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1810 }
else if (
auto *blindData = dstGrid->template getBlindData<int64_t>(i)) {
1811 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1814 std::cerr <<
"unsupported point attribute \"" <<
toStr(str, metaData->mDataType) <<
"\"\n";
1827template <
typename SrcGr
idT>
1828template <
typename DstBuildT>
1829inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1830CreateNanoGrid<SrcGridT>::postProcess(uint32_t channels)
1833 const std::string typeName =
toStr(str, toGridType<SrcValueT>());
1834 const uint64_t valueCount = this->valueCount();
1835 auto *dstGrid = this->
template dstGrid<DstBuildT>();
1836 for (uint32_t i=0; i<channels; ++i) {
1837 const std::string name =
"channel_"+std::to_string(i);
1838 int j = dstGrid->findBlindData(name.c_str());
1839 if (j<0)
throw std::runtime_error(
"CreateNanoGrid::postProcess: missing " + name);
1840 auto *metaData = this->dstMeta(j);
1841 metaData->mDataClass = GridBlindDataClass::ChannelArray;
1842 metaData->mDataType = toGridType<SrcValueT>();
1843 if (metaData->mSemantic == GridBlindDataSemantic::Unknown) {
1844 metaData->mSemantic =
toSemantic( mSrcNodeAcc.gridClass());
1846 SrcValueT *blindData =
const_cast<SrcValueT*
>(metaData->template getBlindData<SrcValueT>());
1848 util::forEach(0,valueCount,1024,[&](
const util::Range1D &r){
1849 SrcValueT *dst=blindData+r.begin(), *end=dst+r.size(), *src=dst-valueCount;
1850 while(dst!=end) *dst++ = *src++;
1853 this->
template copyValues<DstBuildT>(blindData);
1856 updateGridStats(this->
template dstGrid<DstBuildT>(), std::min(StatsMode::BBox, mStats));
1862template <
typename SrcGr
idT>
1863template <
typename DstBuildT>
1864typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1867 assert(mBufferPtr && buffer);
1870 if (this->valueCount()==0) this->
template countValues<DstBuildT>();
1872 auto copyNodeValues = [&](
const auto &node,
SrcValueT *v) {
1874 for (
auto it = node.cbeginValueOn(); it; ++it) *v++ = *it;
1876 for (
auto it = node.cbeginValueAll(); it; ++it) *v++ = *it;
1878 if (mIncludeStats) {
1880 *v++ = node.minimum();
1881 *v++ = node.maximum();
1883 *v++ = node.average();
1884 *v++ = node.stdDeviation();
1898 const SrcRootT &root = mSrcNodeAcc.root();
1899 buffer[0] = root.background();
1900 if (mIncludeTiles) {
1901 copyNodeValues(root, buffer + 1u);
1903 for (auto i = r.begin(); i!=r.end(); ++i) {
1904 copyNodeValues(mSrcNodeAcc.template node<2>(static_cast<uint32_t>(i)), buffer + mValIdx[2][i]);
1908 for (auto i = r.begin(); i!=r.end(); ++i) {
1909 copyNodeValues(mSrcNodeAcc.template node<1>(static_cast<uint32_t>(i)), buffer + mValIdx[1][i]);
1914 for (auto i = r.begin(); i!=r.end(); ++i) {
1915 copyNodeValues(mSrcNodeAcc.template node<0>(static_cast<uint32_t>(i)), buffer + mValIdx[0][i]);
1923#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1925template <
typename SrcGr
idT>
1927typename util::disable_if<util::is_same<T, openvdb::tools::PointIndexGrid>::value ||
1928 util::is_same<T, openvdb::points::PointDataGrid>::value, uint64_t>::type
1929CreateNanoGrid<SrcGridT>::countPoints()
const
1931 static_assert(util::is_same<T, SrcGridT>::value,
"expected default template parameter");
1935template <
typename SrcGr
idT>
1937typename util::enable_if<util::is_same<T, openvdb::tools::PointIndexGrid>::value ||
1938 util::is_same<T, openvdb::points::PointDataGrid>::value, uint64_t>::type
1939CreateNanoGrid<SrcGridT>::countPoints()
const
1941 static_assert(util::is_same<T, SrcGridT>::value,
"expected default template parameter");
1942 return util::reduce(0, mSrcNodeAcc.nodeCount(0), 8, uint64_t(0), [&](
auto &r, uint64_t sum) {
1943 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<0>(
static_cast<uint32_t
>(i)).getLastValue();
1944 return sum;}, std::plus<uint64_t>());
1947template <
typename SrcGr
idT>
1948template<
typename DstBuildT,
typename AttT,
typename CodecT,
typename T>
1949typename util::enable_if<util::is_same<openvdb::points::PointDataGrid, T>::value>::type
1950CreateNanoGrid<SrcGridT>::copyPointAttribute(
size_t attIdx, AttT *attPtr)
1952 static_assert(util::is_same<SrcGridT, T>::value,
"Expected default parameter");
1953 using HandleT = openvdb::points::AttributeHandle<AttT, CodecT>;
1954 util::forEach(0, mSrcNodeAcc.nodeCount(0), 16, [&](
const auto& r) {
1955 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1956 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1957 auto& srcLeaf = mSrcNodeAcc.template node<0>(static_cast<uint32_t>(i));
1958 HandleT handle(srcLeaf.constAttributeArray(attIdx));
1959 AttT *p = attPtr + dstLeaf->mMinimum;
1960 for (auto iter = srcLeaf.beginIndexOn(); iter; ++iter) *p++ = handle.get(*iter);
1969template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1970typename util::disable_if<BuildTraits<DstBuildT>::is_index || BuildTraits<DstBuildT>::is_Fp, GridHandle<BufferT>>::type
1975 const BufferT &buffer)
1981 return converter.template getHandle<DstBuildT, BufferT>(buffer);
1986template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1993 const BufferT &buffer)
1997 return converter.template getHandle<DstBuildT, BufferT>(channels, includeStats, includeTiles, buffer);
2002template<
typename SrcGr
idT,
typename DstBuildT,
typename OracleT,
typename BufferT>
2009 const OracleT &oracle,
2010 const BufferT &buffer)
2017 return converter.template getHandle<DstBuildT, OracleT, BufferT>(oracle, buffer);
2022template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
2029 const BufferT &buffer)
2036 return converter.template getHandle<DstBuildT, BufferT>(buffer);
2041#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
2042template<
typename BufferT>
2044openToNanoVDB(
const openvdb::GridBase::Ptr& base,
2050 using openvdb_Vec4fTree =
typename openvdb::tree::Tree4<openvdb::Vec4f, 5, 4, 3>::Type;
2051 using openvdb_Vec4dTree =
typename openvdb::tree::Tree4<openvdb::Vec4d, 5, 4, 3>::Type;
2056 if (
auto grid = openvdb::GridBase::grid<openvdb::FloatGrid>(base)) {
2057 return createNanoGrid<openvdb::FloatGrid, float, BufferT>(*grid, sMode, cMode, verbose);
2058 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::DoubleGrid>(base)) {
2059 return createNanoGrid<openvdb::DoubleGrid, double, BufferT>(*grid, sMode, cMode, verbose);
2060 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int32Grid>(base)) {
2061 return createNanoGrid<openvdb::Int32Grid, int32_t,BufferT>(*grid, sMode, cMode, verbose);
2062 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int64Grid>(base)) {
2063 return createNanoGrid<openvdb::Int64Grid, int64_t, BufferT>(*grid, sMode, cMode, verbose);
2064 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_UInt32Grid>(base)) {
2065 return createNanoGrid<openvdb_UInt32Grid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2066 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3fGrid>(base)) {
2067 return createNanoGrid<openvdb::Vec3fGrid, nanovdb::Vec3f, BufferT>(*grid, sMode, cMode, verbose);
2068 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3dGrid>(base)) {
2069 return createNanoGrid<openvdb::Vec3dGrid, nanovdb::Vec3d, BufferT>(*grid, sMode, cMode, verbose);
2070 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::tools::PointIndexGrid>(base)) {
2071 return createNanoGrid<openvdb::tools::PointIndexGrid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2072 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::points::PointDataGrid>(base)) {
2073 return createNanoGrid<openvdb::points::PointDataGrid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2074 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::MaskGrid>(base)) {
2075 return createNanoGrid<openvdb::MaskGrid, nanovdb::ValueMask, BufferT>(*grid, sMode, cMode, verbose);
2076 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::BoolGrid>(base)) {
2077 return createNanoGrid<openvdb::BoolGrid, bool, BufferT>(*grid, sMode, cMode, verbose);
2078 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4fGrid>(base)) {
2079 return createNanoGrid<openvdb_Vec4fGrid, nanovdb::Vec4f, BufferT>(*grid, sMode, cMode, verbose);
2080 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4dGrid>(base)) {
2081 return createNanoGrid<openvdb_Vec4dGrid, nanovdb::Vec4d, BufferT>(*grid, sMode, cMode, verbose);
2087template<
typename DstBuildT,
typename BufferT>
2088typename util::enable_if<BuildTraits<DstBuildT>::is_index, GridHandle<BufferT>>::type
2089openToIndexVDB(
const openvdb::GridBase::Ptr& base,
2096 using openvdb_Vec4fTree =
typename openvdb::tree::Tree4<openvdb::Vec4f, 5, 4, 3>::Type;
2097 using openvdb_Vec4dTree =
typename openvdb::tree::Tree4<openvdb::Vec4d, 5, 4, 3>::Type;
2102 if (
auto grid = openvdb::GridBase::grid<openvdb::FloatGrid>(base)) {
2103 return createNanoGrid<openvdb::FloatGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2104 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::DoubleGrid>(base)) {
2105 return createNanoGrid<openvdb::DoubleGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2106 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int32Grid>(base)) {
2107 return createNanoGrid<openvdb::Int32Grid, DstBuildT,BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2108 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int64Grid>(base)) {
2109 return createNanoGrid<openvdb::Int64Grid, DstBuildT, BufferT>(*grid, includeStats, includeTiles, verbose);
2110 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_UInt32Grid>(base)) {
2111 return createNanoGrid<openvdb_UInt32Grid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2112 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3fGrid>(base)) {
2113 return createNanoGrid<openvdb::Vec3fGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2114 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3dGrid>(base)) {
2115 return createNanoGrid<openvdb::Vec3dGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2116 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::tools::PointIndexGrid>(base)) {
2117 return createNanoGrid<openvdb::tools::PointIndexGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2118 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::points::PointDataGrid>(base)) {
2119 return createNanoGrid<openvdb::points::PointDataGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2120 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::MaskGrid>(base)) {
2121 return createNanoGrid<openvdb::MaskGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2122 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::BoolGrid>(base)) {
2123 return createNanoGrid<openvdb::BoolGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2124 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4fGrid>(base)) {
2125 return createNanoGrid<openvdb_Vec4fGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2126 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4dGrid>(base)) {
2127 return createNanoGrid<openvdb_Vec4dGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);