113#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
121template<
typename BufferT = HostBuffer>
123openToNanoVDB(
const openvdb::GridBase::Ptr& base,
137template<
typename DstBuildT = nanovdb::ValueOnIndex,
typename BufferT = HostBuffer>
139openToIndexVDB(
const openvdb::GridBase::Ptr& base,
140 uint32_t channels = 1u,
141 bool includeStats =
true,
142 bool includeTiles =
true,
158template<
typename SrcGridT,
166 const BufferT &buffer = BufferT());
184template<
typename SrcGridT,
189 uint32_t channels = 0u,
190 bool includeStats =
true,
191 bool includeTiles =
true,
193 const BufferT &buffer = BufferT());
210template<
typename SrcGridT,
218 bool ditherOn =
false,
220 const OracleT &oracle = OracleT(),
221 const BufferT &buffer = BufferT());
236template<
typename SrcGridT,
243 bool ditherOn =
false,
245 const BufferT &buffer = BufferT());
255 AbsDiff(
float tolerance = -1.0f) : mTolerance(tolerance) {}
258 operator bool()
const {
return mTolerance>=0.0f;}
261 static const float halfWidth = 3.0f;
262 mTolerance = 0.1f * background / halfWidth;
277 return math::Abs(exact - approx) <= mTolerance;
289 RelDiff(
float tolerance = -1.0f) : mTolerance(tolerance) {}
292 operator bool()
const {
return mTolerance>=0.0f;}
310template <
typename Gr
idT>
327 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
330 const std::string&
getName()
const {
return this->
grid().getName();};
342template <
typename BuildT>
358 , mMgr(*(mHandle.template mgr<BuildT>())) {}
362 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
365 std::string
getName()
const {
return std::string(this->
grid().gridName());};
381#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
395template <
typename BuildT>
396using OpenLeaf = openvdb::tree::LeafNode<BuildT,3>;
397template <
typename BuildT>
398using OpenLower = openvdb::tree::InternalNode<OpenLeaf<BuildT>,4>;
399template <
typename BuildT>
400using OpenUpper = openvdb::tree::InternalNode<OpenLower<BuildT>,5>;
401template <
typename BuildT>
402using OpenRoot = openvdb::tree::RootNode<OpenUpper<BuildT>>;
403template <
typename BuildT>
404using OpenTree = openvdb::tree::Tree<OpenRoot<BuildT>>;
405template <
typename BuildT>
406using OpenGrid = openvdb::Grid<OpenTree<BuildT>>;
411template <
typename BuildT>
419 using ValueType =
typename GridType::ValueType;
423 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
425 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
426 mMap.set(mat4, mat4.inverse());
431 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
434 std::string
getName()
const {
return this->
grid().getName(); };
436 const nanovdb::Map&
map()
const {
return mMap;}
451 build::NodeManager<GridType> mMgr;
465 using GridType = openvdb::tools::PointIndexGrid;
466 using TreeType = openvdb::tools::PointIndexTree;
467 using RootType =
typename TreeType::RootNodeType;
468 using ValueType =
typename GridType::ValueType;
470 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
472 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
473 mMap.set(mat4, mat4.inverse());
478 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
481 std::string
getName()
const {
return this->
grid().getName(); };
483 const nanovdb::Map&
map()
const {
return mMap;}
486 build::NodeManager<GridType> mMgr;
500 using GridType = openvdb::points::PointDataGrid;
501 using TreeType = openvdb::points::PointDataTree;
502 using RootType =
typename TreeType::RootNodeType;
503 using ValueType =
typename GridType::ValueType;
505 using NodeType =
typename NodeTrait<const TreeType, LEVEL>::type;
507 const auto mat4 = this->
grid().transform().baseMap()->getAffineMap()->getMat4();
508 mMap.set(mat4, mat4.inverse());
513 uint64_t
nodeCount(
int level)
const {
return mMgr.nodeCount(level); }
516 std::string
getName()
const {
return this->
grid().getName(); };
518 const nanovdb::Map&
map()
const {
return mMap;}
521 build::NodeManager<GridType> mMgr;
530template <
typename SrcGr
idT>
574 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename BufferT =
HostBuffer>
577 getHandle(
const BufferT &buffer = BufferT());
587 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename OracleT =
AbsDiff,
typename BufferT =
HostBuffer>
589 getHandle(
const OracleT &oracle = OracleT(),
590 const BufferT &buffer = BufferT());
600 template<typename DstBuildT = typename MapToNano<SrcBuildT>::type,
typename BufferT =
HostBuffer>
603 bool includeStats =
true,
604 bool includeTiles =
true,
605 const BufferT &buffer = BufferT());
619 size_t count,
size_t size)
621 const size_t order = mBlindMetaData.size();
622 mBlindMetaData.emplace(name, dataSemantic, dataClass, dataType, order, count, size);
629 uint64_t
valueCount()
const {
return mValIdx[0].empty() ? 0u : mValIdx[0].back();}
634 template <
typename DstBuildT>
642 template <
typename T,
int LEVEL>
644 dstNode(uint64_t i)
const {
645 static_assert(LEVEL==0 || LEVEL==1 || LEVEL==2,
"Expected LEVEL== {0,1,2}");
649 template <
typename T,
int LEVEL>
660 template <
typename DstBuildT>
664 template <
typename DstBuildT>
665 typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
666 preProcess(uint32_t channels);
668 template <
typename DstBuildT,
typename OracleT>
669 typename util::enable_if<util::is_same<FpN, DstBuildT>::value>::type
670 preProcess(OracleT oracle);
675 template<
typename DstBuildT,
typename BufferT>
676 GridHandle<BufferT> initHandle(
const BufferT& buffer);
680 template <
typename DstBuildT>
681 inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
682 postProcess(uint32_t channels);
684 template <
typename DstBuildT>
685 inline typename util::disable_if<BuildTraits<DstBuildT>::is_index>::type
690 template<
typename DstBuildT>
691 typename util::disable_if<BuildTraits<DstBuildT>::is_special>::type
694 template<
typename DstBuildT>
695 typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
698 template<
typename DstBuildT>
699 typename util::enable_if<BuildTraits<DstBuildT>::is_FpX>::type
702 template<
typename DstBuildT>
703 typename util::enable_if<util::is_same<FpN, DstBuildT>::value>::type
706 template<
typename DstBuildT>
707 typename util::enable_if<util::is_same<bool, DstBuildT>::value>::type
710 template<
typename DstBuildT>
711 typename util::enable_if<util::is_same<ValueMask, DstBuildT>::value>::type
716 template<
typename DstBuildT,
int LEVEL>
717 typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
718 processInternalNodes();
720 template<
typename DstBuildT,
int LEVEL>
721 typename util::enable_if<!BuildTraits<DstBuildT>::is_index>::type
722 processInternalNodes();
726 template <
typename DstBuildT>
727 typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
730 template <
typename DstBuildT>
731 typename util::enable_if<!BuildTraits<DstBuildT>::is_index>::type
736 template<
typename DstBuildT>
739 template<
typename DstBuildT>
742 template <
typename DstBuildT,
int LEVEL>
743 typename util::enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
746 template <
typename DstBuildT>
747 typename util::enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
750#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
751 template<
typename T = SrcGr
idT>
752 typename util::disable_if<util::is_same<T, openvdb::tools::PointIndexGrid>::value ||
756 template<
typename T = SrcGr
idT>
757 typename util::enable_if<util::is_same<T, openvdb::tools::PointIndexGrid>::value ||
761 template<
typename DstBuildT,
typename AttT,
typename CodecT = openvdb::po
ints::UnknownCodec,
typename T = SrcGr
idT>
762 typename util::enable_if<util::is_same<openvdb::points::PointDataGrid, T>::value>::type
763 copyPointAttribute(
size_t attIdx, AttT *attPtr);
765 uint64_t countPoints()
const {
return 0u;}
769 struct BufferOffsets {
770 uint64_t grid, tree, root, upper, lower, leaf, meta, blind, size;
771 uint64_t operator[](
int i)
const {
return *(
reinterpret_cast<const uint64_t*
>(
this)+i); }
774 uint64_t mLeafNodeSize;
776 std::unique_ptr<SrcNodeAccT> mSrcNodeAccPtr;
779 std::set<OrderedBlindMetaData> mBlindMetaData;
780 struct Codec {
float min, max; uint64_t offset; uint8_t log2; };
781 std::unique_ptr<Codec[]> mCodec;
784 bool mDitherOn, mIncludeStats, mIncludeTiles;
785 std::vector<uint64_t> mValIdx[3];
790template <
typename SrcGr
idT>
794 , mSrcNodeAcc(*mSrcNodeAccPtr)
798 , mIncludeStats(true)
799 , mIncludeTiles(true)
805template <
typename SrcGr
idT>
808 , mSrcNodeAccPtr(nullptr)
809 , mSrcNodeAcc(srcNodeAcc)
813 , mIncludeStats(true)
814 , mIncludeTiles(true)
820template <
typename SrcGr
idT>
824 const std::string& type,
826 size_t i,
size_t valueCount,
size_t valueSize)
830 if (!
metaData->setName(name.c_str()))
throw std::runtime_error(
"blind data name exceeds character limit");
837 size_t i,
size_t valueCount,
size_t valueSize)
841 if (!
metaData->setName(name.c_str()))
throw std::runtime_error(
"blind data name exceeds character limit");
849 if (
"uint32_t" == name) {
851 }
else if (
"float" == name) {
853 }
else if (
"vec3s"== name) {
855 }
else if (
"int32" == name) {
857 }
else if (
"int64" == name) {
870 }
else if (
"V" == name) {
872 }
else if (
"Cd" == name) {
874 }
else if (
"N" == name) {
876 }
else if (
"id" == name) {
888template <
typename SrcGr
idT>
889template<
typename DstBuildT,
typename BufferT>
894 this->
template preProcess<DstBuildT>();
895 auto handle = this->
template initHandle<DstBuildT>(pool);
896 this->
template postProcess<DstBuildT>();
902template <
typename SrcGr
idT>
903template<
typename DstBuildT,
typename OracleT,
typename BufferT>
907 this->
template preProcess<DstBuildT, OracleT>(oracle);
908 auto handle = this->
template initHandle<DstBuildT>(pool);
909 this->
template postProcess<DstBuildT>();
915template <
typename SrcGr
idT>
916template<
typename DstBuildT,
typename BufferT>
923 mIncludeStats = includeStats;
924 mIncludeTiles = includeTiles;
925 this->
template preProcess<DstBuildT>(channels);
926 auto handle = this->
template initHandle<DstBuildT>(pool);
927 this->
template postProcess<DstBuildT>(channels);
933template <
typename SrcGr
idT>
934template <
typename DstBuildT,
typename BufferT>
943 mOffset.meta = mOffset.leaf + mLeafNodeSize;
945 mOffset.size = mOffset.blind;
946 for (
const auto& b : mBlindMetaData) mOffset.size += b.memUsage();
948 auto buffer = BufferT::create(mOffset.size, &pool);
949 mBufferPtr = buffer.data();
952 util::invoke( [&](){this->
template processLeafs<DstBuildT>();},
953 [&](){this->
template processInternalNodes<DstBuildT, 1>();},
954 [&](){this->
template processInternalNodes<DstBuildT, 2>();},
955 [&](){this->
template processRoot<DstBuildT>();},
956 [&](){this->
template processTree<DstBuildT>();},
957 [&](){this->
template processGrid<DstBuildT>();} );
959 return GridHandle<BufferT>(std::move(buffer));
964template <
typename SrcGr
idT>
965template <
typename DstBuildT>
967CreateNanoGrid<SrcGridT>::preProcess()
969 if (
const uint64_t pointCount = this->countPoints()) {
970#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
972 if (!mBlindMetaData.empty())
throw std::runtime_error(
"expected no blind meta data");
973 this->addBlindData(
"index",
980 if (!mBlindMetaData.empty())
throw std::runtime_error(
"expected no blind meta data");
981 auto &srcLeaf = mSrcNodeAcc.template node<0>(0);
982 const auto& attributeSet = srcLeaf.attributeSet();
983 const auto& descriptor = attributeSet.descriptor();
984 const auto& nameMap = descriptor.map();
985 for (
auto it = nameMap.begin(); it != nameMap.end(); ++it) {
986 const size_t index = it->second;
987 auto& attArray = srcLeaf.constAttributeArray(index);
988 mBlindMetaData.emplace(it->first,
989 descriptor.valueType(index),
993 attArray.valueTypeSize());
998 if (mSrcNodeAcc.hasLongGridName()) {
999 this->addBlindData(
"grid name",
1003 mSrcNodeAcc.getName().length() + 1, 1);
1010template <
typename SrcGr
idT>
1011template <
typename DstBuildT,
typename OracleT>
1012inline typename util::enable_if<util::is_same<FpN, DstBuildT>::value>::type
1013CreateNanoGrid<SrcGridT>::preProcess(OracleT oracle)
1017 const size_t leafCount = mSrcNodeAcc.nodeCount(0);
1022 mCodec.
reset(
new Codec[leafCount]);
1025 if (!oracle) oracle.init(mSrcNodeAcc.gridClass(), mSrcNodeAcc.root().background());
1028 math::DitherLUT lut(mDitherOn);
1030 for (
auto i=r.begin(); i!=r.end(); ++i) {
1031 const auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1032 float &
min = mCodec[i].min = std::numeric_limits<float>::max();
1033 float &
max = mCodec[i].max = -
min;
1034 for (
int j=0; j<512; ++j) {
1035 float v = srcLeaf.getValue(j);
1039 const float range =
max -
min;
1040 uint8_t &logBitWidth = mCodec[i].log2 = 0;
1041 while (range > 0.0f && logBitWidth < 4u) {
1042 const uint32_t mask = (uint32_t(1) << (uint32_t(1) << logBitWidth)) - 1u;
1043 const float encode = mask/range;
1044 const float decode = range/mask;
1047 const float exact = srcLeaf.getValue(j);
1048 const uint32_t code = uint32_t(encode*(exact - min) + lut(j));
1049 const float approx = code * decode +
min;
1050 j += oracle(exact, approx) ? 1 : 513;
1052 if (j == 512)
break;
1058 auto getOffset = [&](
size_t i){
1067 for (
size_t i=1; i<leafCount; ++i) mCodec[i].offset = getOffset(i);
1068 mLeafNodeSize = getOffset(leafCount);
1071 uint32_t counters[5+1] = {0};
1072 ++counters[mCodec[0].log2];
1073 for (
size_t i=1; i<leafCount; ++i) ++counters[mCodec[i].log2];
1074 std::cout <<
"\n" << oracle << std::endl;
1075 std::cout <<
"Dithering: " << (mDitherOn ?
"enabled" :
"disabled") << std::endl;
1077 for (uint32_t i=0; i<=5; ++i) {
1078 if (uint32_t n = counters[i]) {
1079 avg += n * float(1 << i);
1080 printf(
"%2i bits: %6u leaf nodes, i.e. %4.1f%%\n",1<<i, n, 100.0f*n/
float(leafCount));
1083 printf(
"%4.1f bits per value on average\n", avg/
float(leafCount));
1086 if (mSrcNodeAcc.hasLongGridName()) {
1087 this->addBlindData(
"grid name",
1091 mSrcNodeAcc.getName().length() + 1, 1);
1097template <
typename SrcGr
idT>
1098template <
typename DstBuildT,
int LEVEL>
1099inline typename util::enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
1100CreateNanoGrid<SrcGridT>::countTileValues(uint64_t valueCount)
1102 const uint64_t stats = mIncludeStats ? 4u : 0u;
1103 mValIdx[LEVEL].clear();
1104 mValIdx[LEVEL].resize(mSrcNodeAcc.nodeCount(LEVEL) + 1, stats);
1106 for (
auto i = r.begin(); i!=r.end(); ++i) {
1107 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(i-1);
1109 mValIdx[LEVEL][i] += srcNode.getValueMask().countOn();
1111 static const uint64_t maxTileCount = uint64_t(1u) << 3*srcNode.LOG2DIM;
1112 mValIdx[LEVEL][i] += maxTileCount - srcNode.getChildMask().countOn();
1116 mValIdx[LEVEL][0] = valueCount;
1117 for (
size_t i=1; i<mValIdx[LEVEL].size(); ++i) mValIdx[LEVEL][i] += mValIdx[LEVEL][i-1];
1118 return mValIdx[LEVEL].back();
1123template <
typename SrcGr
idT>
1124template <
typename DstBuildT>
1125inline typename util::enable_if<BuildTraits<DstBuildT>::is_index, uint64_t>::type
1126CreateNanoGrid<SrcGridT>::countValues()
1128 const uint64_t stats = mIncludeStats ? 4u : 0u;
1129 uint64_t valueCount = 1u;
1130 if (mIncludeTiles) {
1132 for (
auto it = mSrcNodeAcc.root().cbeginValueOn(); it; ++it) ++valueCount;
1134 for (
auto it = mSrcNodeAcc.root().cbeginValueAll(); it; ++it) ++valueCount;
1136 valueCount += stats;
1137 valueCount = countTileValues<DstBuildT, 2>(valueCount);
1138 valueCount = countTileValues<DstBuildT, 1>(valueCount);
1141 mValIdx[0].resize(mSrcNodeAcc.nodeCount(0) + 1, 512u + stats);
1144 for (
auto i = r.begin(); i != r.end(); ++i) {
1145 mValIdx[0][i] = stats;
1146 mValIdx[0][i] += mSrcNodeAcc.template node<0>(i-1).getValueMask().countOn();
1150 mValIdx[0][0] = valueCount;
1152 return mValIdx[0].back();
1157template <
typename SrcGr
idT>
1158template <
typename DstBuildT>
1159inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1160CreateNanoGrid<SrcGridT>::preProcess(uint32_t channels)
1162 const uint64_t valueCount = this->
template countValues<DstBuildT>();
1165 uint32_t order = mBlindMetaData.size();
1167 for (uint32_t i=0; i<channels; ++i) {
1168 mBlindMetaData.emplace(
"channel_" + std::to_string(i),
1175 if (mSrcNodeAcc.hasLongGridName()) {
1176 this->addBlindData(
"grid name",
1180 mSrcNodeAcc.getName().length() + 1, 1);
1186template <
typename SrcGr
idT>
1187template <
typename DstBuildT>
1188inline typename util::disable_if<BuildTraits<DstBuildT>::is_special>::type
1189CreateNanoGrid<SrcGridT>::processLeafs()
1192 using DstValueT =
typename DstDataT::ValueType;
1193 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<T> to have fixed size");
1195 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1196 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1197 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1198 if (DstDataT::padding()>0u) {
1199 util::memzero(dstLeaf, DstDataT::memUsage());
1201 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1202 dstLeaf->mFlags = 0u;
1203 dstLeaf->mMinimum = dstLeaf->mMaximum = typename DstDataT::ValueType();
1204 dstLeaf->mAverage = dstLeaf->mStdDevi = 0;
1206 dstLeaf->mBBoxMin = srcLeaf.origin();
1207 dstLeaf->mValueMask = srcLeaf.getValueMask();
1208 DstValueT *dst = dstLeaf->mValues;
1209 if constexpr(util::is_same<DstValueT, SrcValueT>::value && SrcNodeAccT::IS_OPENVDB) {
1210 const SrcValueT *src = srcLeaf.buffer().data();
1211 for (auto *end = dst + 512u; dst != end; dst += 4, src += 4) {
1218 for (uint32_t j=0; j<512u; ++j) *dst++ = static_cast<DstValueT>(srcLeaf.getValue(j));
1226template <
typename SrcGr
idT>
1227template <
typename DstBuildT>
1229CreateNanoGrid<SrcGridT>::processLeafs()
1232 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<ValueIndex> to have fixed size");
1233 static_assert(DstDataT::padding()==0u,
"Expected leaf nodes to have no padding");
1236 const uint8_t flags = mIncludeStats ? 16u : 0u;
1237 DstDataT *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1238 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1239 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1240 dstLeaf->mBBoxMin = srcLeaf.origin();
1241 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1242 dstLeaf->mFlags = flags;
1243 dstLeaf->mValueMask = srcLeaf.getValueMask();
1244 dstLeaf->mOffset = mValIdx[0][i];
1245 if constexpr(BuildTraits<DstBuildT>::is_onindex) {
1246 const uint64_t *w = dstLeaf->mValueMask.words();
1247#ifdef USE_OLD_VALUE_ON_INDEX
1248 int32_t sum = CountOn(*w++);
1249 uint8_t *p = reinterpret_cast<uint8_t*>(&dstLeaf->mPrefixSum), *q = p + 7;
1250 for (int j=0; j<7; ++j) {
1252 *q |= (sum >> 8) << j;
1253 sum += CountOn(*w++);
1256 uint64_t &prefixSum = dstLeaf->mPrefixSum, sum = util::countOn(*w++);
1258 for (int n = 9; n < 55; n += 9) {
1259 sum += util::countOn(*w++);
1260 prefixSum |= sum << n;
1264 dstLeaf->mPrefixSum = 0u;
1272template <
typename SrcGr
idT>
1273template <
typename DstBuildT>
1274inline typename util::enable_if<util::is_same<ValueMask, DstBuildT>::value>::type
1275CreateNanoGrid<SrcGridT>::processLeafs()
1277 using DstDataT =
typename NanoLeaf<ValueMask>::DataType;
1278 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<ValueMask> to have fixed size");
1279 util::forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const util::Range1D& r) {
1280 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1281 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1282 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1283 if (DstDataT::padding()>0u) {
1284 util::memzero(dstLeaf, DstDataT::memUsage());
1286 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1287 dstLeaf->mFlags = 0u;
1288 dstLeaf->mPadding[0] = dstLeaf->mPadding[1] = 0u;
1290 dstLeaf->mBBoxMin = srcLeaf.origin();
1291 dstLeaf->mValueMask = srcLeaf.getValueMask();
1298template <
typename SrcGr
idT>
1299template <
typename DstBuildT>
1300inline typename util::enable_if<util::is_same<bool, DstBuildT>::value>::type
1301CreateNanoGrid<SrcGridT>::processLeafs()
1303 using DstDataT =
typename NanoLeaf<bool>::DataType;
1304 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<bool> to have fixed size");
1305 util::forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const util::Range1D& r) {
1306 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1307 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1308 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1309 if (DstDataT::padding()>0u) {
1310 util::memzero(dstLeaf, DstDataT::memUsage());
1312 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1313 dstLeaf->mFlags = 0u;
1315 dstLeaf->mBBoxMin = srcLeaf.origin();
1316 dstLeaf->mValueMask = srcLeaf.getValueMask();
1317 if constexpr(!util::is_same<bool, SrcBuildT>::value) {
1318 for (int j=0; j<512; ++j) dstLeaf->mValues.set(j, static_cast<bool>(srcLeaf.getValue(j)));
1319 } else if constexpr(SrcNodeAccT::IS_OPENVDB) {
1320 dstLeaf->mValues = *reinterpret_cast<const Mask<3>*>(srcLeaf.buffer().data());
1321 } else if constexpr(SrcNodeAccT::IS_NANOVDB) {
1322 dstLeaf->mValues = srcLeaf.data()->mValues;
1324 dstLeaf->mValues = srcLeaf.mValues;
1332template <
typename SrcGr
idT>
1333template <
typename DstBuildT>
1334inline typename util::enable_if<BuildTraits<DstBuildT>::is_FpX>::type
1335CreateNanoGrid<SrcGridT>::processLeafs()
1337 using DstDataT =
typename NanoLeaf<DstBuildT>::DataType;
1338 static_assert(DstDataT::FIXED_SIZE,
"Expected destination LeafNode<Fp4|Fp8|Fp16> to have fixed size");
1339 using ArrayT =
typename DstDataT::ArrayType;
1340 static_assert(util::is_same<float, SrcValueT>::value,
"Expected ValueT == float");
1341 using FloatT =
typename std::conditional<DstDataT::bitWidth()>=16, double,
float>::type;
1342 static constexpr FloatT UNITS = FloatT((1 << DstDataT::bitWidth()) - 1);
1343 math::DitherLUT lut(mDitherOn);
1345 util::forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const util::Range1D& r) {
1346 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1347 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1348 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1349 if (DstDataT::padding()>0u) {
1350 util::memzero(dstLeaf, DstDataT::memUsage());
1352 dstLeaf->mFlags = dstLeaf->mBBoxDif[2] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[0] = 0u;
1353 dstLeaf->mDev = dstLeaf->mAvg = dstLeaf->mMax = dstLeaf->mMin = 0u;
1355 dstLeaf->mBBoxMin = srcLeaf.origin();
1356 dstLeaf->mValueMask = srcLeaf.getValueMask();
1358 float min = std::numeric_limits<float>::max(), max = -min;
1359 for (uint32_t j=0; j<512u; ++j) {
1360 const float v = srcLeaf.getValue(j);
1361 if (v < min) min = v;
1362 if (v > max) max = v;
1364 dstLeaf->init(min, max, DstDataT::bitWidth());
1366 const FloatT encode = UNITS/(max-min);
1367 uint32_t offset = 0;
1368 auto quantize = [&]()->ArrayT{
1369 const ArrayT tmp = static_cast<ArrayT>(encode * (srcLeaf.getValue(offset) - min) + lut(offset));
1373 auto *code = reinterpret_cast<ArrayT*>(dstLeaf->mCode);
1374 if (util::is_same<Fp4, DstBuildT>::value) {
1375 for (uint32_t j=0; j<128u; ++j) {
1376 auto tmp = quantize();
1377 *code++ = quantize() << 4 | tmp;
1379 *code++ = quantize() << 4 | tmp;
1382 for (uint32_t j=0; j<128u; ++j) {
1383 *code++ = quantize();
1384 *code++ = quantize();
1385 *code++ = quantize();
1386 *code++ = quantize();
1395template <
typename SrcGr
idT>
1396template <
typename DstBuildT>
1397inline typename util::enable_if<util::is_same<FpN, DstBuildT>::value>::type
1398CreateNanoGrid<SrcGridT>::processLeafs()
1400 static_assert(util::is_same<float, SrcValueT>::value,
"Expected SrcValueT == float");
1401 math::DitherLUT lut(mDitherOn);
1402 util::forEach(0, mSrcNodeAcc.nodeCount(0), 8, [&](
const util::Range1D& r) {
1403 for (auto i = r.begin(); i != r.end(); ++i) {
1404 auto &srcLeaf = mSrcNodeAcc.template node<0>(i);
1405 auto *dstLeaf = this->template dstNode<DstBuildT,0>(i);
1406 dstLeaf->mBBoxMin = srcLeaf.origin();
1407 dstLeaf->mBBoxDif[0] = dstLeaf->mBBoxDif[1] = dstLeaf->mBBoxDif[2] = 0u;
1408 const uint8_t logBitWidth = mCodec[i].log2;
1409 dstLeaf->mFlags = logBitWidth << 5;
1410 dstLeaf->mValueMask = srcLeaf.getValueMask();
1411 const float min = mCodec[i].min, max = mCodec[i].max;
1412 dstLeaf->init(min, max, uint8_t(1) << logBitWidth);
1414 uint32_t offset = 0;
1415 float encode = 0.0f;
1416 auto quantize = [&]()->uint8_t{
1417 const uint8_t tmp = static_cast<uint8_t>(encode * (srcLeaf.getValue(offset) - min) + lut(offset));
1421 auto *dst = reinterpret_cast<uint8_t*>(dstLeaf+1);
1422 switch (logBitWidth) {
1424 encode = 1.0f/(max - min);
1425 for (int j=0; j<64; ++j) {
1427 for (int k=0; k<8; ++k) a |= quantize() << k;
1433 encode = 3.0f/(max - min);
1434 for (int j=0; j<128; ++j) {
1435 auto a = quantize();
1436 a |= quantize() << 2;
1437 a |= quantize() << 4;
1438 *dst++ = quantize() << 6 | a;
1443 encode = 15.0f/(max - min);
1444 for (int j=0; j<128; ++j) {
1445 auto a = quantize();
1446 *dst++ = quantize() << 4 | a;
1448 *dst++ = quantize() << 4 | a;
1453 encode = 255.0f/(max - min);
1454 for (int j=0; j<128; ++j) {
1455 *dst++ = quantize();
1456 *dst++ = quantize();
1457 *dst++ = quantize();
1458 *dst++ = quantize();
1463 auto *dst = reinterpret_cast<uint16_t*>(dstLeaf+1);
1464 const double encode = 65535.0/(max - min);
1465 for (int j=0; j<128; ++j) {
1466 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1467 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1468 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1469 *dst++ = uint16_t(encode * (srcLeaf.getValue(offset) - min) + lut(offset)); ++offset;
1479template <
typename SrcGr
idT>
1480template <
typename DstBuildT,
int LEVEL>
1481inline typename util::enable_if<!BuildTraits<DstBuildT>::is_index>::type
1482CreateNanoGrid<SrcGridT>::processInternalNodes()
1484 using DstNodeT =
typename NanoNode<DstBuildT, LEVEL>::type;
1485 using DstValueT =
typename DstNodeT::ValueType;
1486 using DstChildT =
typename NanoNode<DstBuildT, LEVEL-1>::type;
1487 static_assert(LEVEL == 1 || LEVEL == 2,
"Expected internal node");
1489 const uint64_t nodeCount = mSrcNodeAcc.nodeCount(LEVEL);
1490 if (nodeCount > 0) {
1491 uint64_t childCount = 0;
1492 auto *dstNode = this->
template dstNode<DstBuildT,LEVEL>(0);
1493 for (uint64_t i=0; i<nodeCount; ++i) {
1494 dstNode[i].mFlags = childCount;
1495 childCount += mSrcNodeAcc.template node<LEVEL>(
static_cast<uint32_t
>(i)).getChildMask().countOn();
1499 util::forEach(0, nodeCount, 4, [&](
const util::Range1D& r) {
1500 auto *dstNode = this->
template dstNode<DstBuildT,LEVEL>(r.begin());
1501 for (
auto i = r.begin(); i != r.end(); ++i, ++dstNode) {
1502 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(i);
1503 uint64_t childID = dstNode->mFlags;
1504 if (DstNodeT::DataType::padding()>0u) {
1505 util::memzero(dstNode, DstNodeT::memUsage());
1507 dstNode->mFlags = 0;
1508 dstNode->mMinimum = dstNode->mMaximum =
typename DstNodeT::ValueType();
1509 dstNode->mAverage = dstNode->mStdDevi = 0;
1511 dstNode->mBBox[0] = srcNode.origin();
1512 dstNode->mValueMask = srcNode.getValueMask();
1513 dstNode->mChildMask = srcNode.getChildMask();
1514 for (
auto it = srcNode.cbeginChildAll(); it; ++it) {
1516 if (it.probeChild(value)) {
1517 DstChildT *dstChild = this->
template dstNode<DstBuildT,LEVEL-1>(childID++);
1518 dstNode->setChild(it.pos(), dstChild);
1520 dstNode->setValue(it.pos(),
static_cast<DstValueT
>(value));
1529template <
typename SrcGr
idT>
1530template <
typename DstBuildT,
int LEVEL>
1531inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1532CreateNanoGrid<SrcGridT>::processInternalNodes()
1534 using DstNodeT =
typename NanoNode<DstBuildT, LEVEL>::type;
1535 using DstChildT =
typename NanoNode<DstBuildT, LEVEL-1>::type;
1536 static_assert(LEVEL == 1 || LEVEL == 2,
"Expected internal node");
1537 static_assert(DstNodeT::DataType::padding()==0u,
"Expected internal nodes to have no padding");
1539 const uint64_t nodeCount = mSrcNodeAcc.nodeCount(LEVEL);
1540 if (nodeCount > 0) {
1541 uint64_t childCount = 0;
1542 auto *dstNode = this->
template dstNode<DstBuildT,LEVEL>(0);
1543 for (uint64_t i=0; i<nodeCount; ++i) {
1544 dstNode[i].mFlags = childCount;
1545 childCount += mSrcNodeAcc.template node<LEVEL>(i).getChildMask().countOn();
1549 util::forEach(0, nodeCount, 4, [&](
const util::Range1D& r) {
1550 auto *dstNode = this->
template dstNode<DstBuildT,LEVEL>(r.begin());
1551 for (
auto i = r.begin(); i != r.end(); ++i, ++dstNode) {
1552 auto &srcNode = mSrcNodeAcc.template node<LEVEL>(i);
1553 uint64_t childID = dstNode->mFlags;
1554 dstNode->mFlags = 0u;
1555 dstNode->mBBox[0] = srcNode.origin();
1556 dstNode->mValueMask = srcNode.getValueMask();
1557 dstNode->mChildMask = srcNode.getChildMask();
1558 uint64_t n = mIncludeTiles ? mValIdx[LEVEL][i] : 0u;
1559 for (
auto it = srcNode.cbeginChildAll(); it; ++it) {
1561 if (it.probeChild(value)) {
1562 DstChildT *dstChild = this->
template dstNode<DstBuildT,LEVEL-1>(childID++);
1563 dstNode->setChild(it.pos(), dstChild);
1566 if (mIncludeTiles && !((BuildTraits<DstBuildT>::is_onindex) && dstNode->mValueMask.isOff(it.pos()))) m = n++;
1567 dstNode->setValue(it.pos(), m);
1570 if (mIncludeTiles && mIncludeStats) {
1571 dstNode->mMinimum = n++;
1572 dstNode->mMaximum = n++;
1573 dstNode->mAverage = n++;
1574 dstNode->mStdDevi = n++;
1576 dstNode->mMinimum = 0u;
1577 dstNode->mMaximum = 0u;
1578 dstNode->mAverage = 0u;
1579 dstNode->mStdDevi = 0u;
1587template <
typename SrcGr
idT>
1588template <
typename DstBuildT>
1589inline typename util::enable_if<!BuildTraits<DstBuildT>::is_index>::type
1590CreateNanoGrid<SrcGridT>::processRoot()
1592 using DstRootT = NanoRoot<DstBuildT>;
1593 using DstValueT =
typename DstRootT::ValueType;
1594 auto &srcRoot = mSrcNodeAcc.root();
1595 auto *dstRoot = this->
template dstRoot<DstBuildT>();
1596 const uint32_t tableSize = srcRoot.getTableSize();
1597 if (DstRootT::DataType::padding()>0) util::memzero(dstRoot, DstRootT::memUsage(tableSize));
1598 dstRoot->mTableSize = tableSize;
1599 dstRoot->mMinimum = dstRoot->mMaximum = dstRoot->mBackground = srcRoot.background();
1601 if (tableSize==0)
return;
1602 auto *dstChild = this->
template dstNode<DstBuildT, 2>(0);
1603 auto *dstTile = dstRoot->tile(0);
1604 for (
auto it = srcRoot.cbeginChildAll(); it; ++it, ++dstTile) {
1606 if (it.probeChild(value)) {
1607 dstTile->setChild(it.getCoord(), dstChild++, dstRoot);
1609 dstTile->setValue(it.getCoord(), it.isValueOn(),
static_cast<DstValueT
>(value));
1616template <
typename SrcGr
idT>
1617template <
typename DstBuildT>
1618inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1619CreateNanoGrid<SrcGridT>::processRoot()
1621 using DstRootT = NanoRoot<DstBuildT>;
1622 auto &srcRoot = mSrcNodeAcc.root();
1623 auto *dstRoot = this->
template dstRoot<DstBuildT>();
1624 const uint32_t tableSize = srcRoot.getTableSize();
1625 if (DstRootT::DataType::padding()>0) util::memzero(dstRoot, DstRootT::memUsage(tableSize));
1626 dstRoot->mTableSize = tableSize;
1627 dstRoot->mBackground = 0u;
1628 uint64_t valueCount = 0u;
1632 auto *dstChild = this->
template dstNode<DstBuildT, 2>(0);
1633 auto *dstTile = dstRoot->tile(0);
1634 for (
auto it = srcRoot.cbeginChildAll(); it; ++it, ++dstTile) {
1636 if (it.probeChild(tmp)) {
1637 dstTile->setChild(it.getCoord(), dstChild++, dstRoot);
1639 dstTile->setValue(it.getCoord(), it.isValueOn(), 0u);
1640 if (mIncludeTiles && !((BuildTraits<DstBuildT>::is_onindex) && !dstTile->state)) dstTile->value = ++valueCount;
1644 if (mIncludeTiles && mIncludeStats) {
1645 dstRoot->mMinimum = ++valueCount;
1646 dstRoot->mMaximum = ++valueCount;
1647 dstRoot->mAverage = ++valueCount;
1648 dstRoot->mStdDevi = ++valueCount;
1649 }
else if (dstRoot->padding()==0) {
1650 dstRoot->mMinimum = 0u;
1651 dstRoot->mMaximum = 0u;
1652 dstRoot->mAverage = 0u;
1653 dstRoot->mStdDevi = 0u;
1659template <
typename SrcGr
idT>
1660template <
typename DstBuildT>
1661void CreateNanoGrid<SrcGridT>::processTree()
1663 const uint64_t nodeCount[3] = {mSrcNodeAcc.nodeCount(0), mSrcNodeAcc.nodeCount(1), mSrcNodeAcc.nodeCount(2)};
1664 auto *dstTree = this->
template dstTree<DstBuildT>();
1665 dstTree->setRoot( this->
template dstRoot<DstBuildT>() );
1666 dstTree->setFirstNode(nodeCount[2] ? this->
template dstNode<DstBuildT, 2>(0) :
nullptr);
1667 dstTree->setFirstNode(nodeCount[1] ? this->
template dstNode<DstBuildT, 1>(0) :
nullptr);
1668 dstTree->setFirstNode(nodeCount[0] ? this->
template dstNode<DstBuildT, 0>(0) :
nullptr);
1670 dstTree->mNodeCount[0] =
static_cast<uint32_t
>(nodeCount[0]);
1671 dstTree->mNodeCount[1] =
static_cast<uint32_t
>(nodeCount[1]);
1672 dstTree->mNodeCount[2] =
static_cast<uint32_t
>(nodeCount[2]);
1675 dstTree->mTileCount[0] = util::reduce(util::Range1D(0,nodeCount[1]), uint32_t(0), [&](
const util::Range1D &r, uint32_t sum){
1676 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<1>(i).getValueMask().countOn();
1677 return sum;}, std::plus<uint32_t>());
1680 dstTree->mTileCount[1] = util::reduce(util::Range1D(0,nodeCount[2]), uint32_t(0), [&](
const util::Range1D &r, uint32_t sum){
1681 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<2>(i).getValueMask().countOn();
1682 return sum;}, std::plus<uint32_t>());
1685 dstTree->mTileCount[2] = 0;
1686 for (
auto it = mSrcNodeAcc.root().cbeginValueOn(); it; ++it) dstTree->mTileCount[2] += 1;
1689 dstTree->mVoxelCount = util::reduce(util::Range1D(0, nodeCount[0]), uint64_t(0), [&](
const util::Range1D &r, uint64_t sum){
1690 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<0>(i).getValueMask().countOn();
1691 return sum;}, std::plus<uint64_t>());
1693 dstTree->mVoxelCount += uint64_t(dstTree->mTileCount[0]) << 9;
1694 dstTree->mVoxelCount += uint64_t(dstTree->mTileCount[1]) << 21;
1695 dstTree->mVoxelCount += uint64_t(dstTree->mTileCount[2]) << 36;
1701template <
typename SrcGr
idT>
1702template <
typename DstBuildT>
1703void CreateNanoGrid<SrcGridT>::processGrid()
1705 auto* dstGrid = this->
template dstGrid<DstBuildT>();
1706 dstGrid->init({GridFlags::IsBreadthFirst}, mOffset.size, mSrcNodeAcc.map(),
1707 toGridType<DstBuildT>(), toGridClass<DstBuildT>(mSrcNodeAcc.gridClass()));
1708 dstGrid->mBlindMetadataCount =
static_cast<uint32_t
>(mBlindMetaData.size());
1709 dstGrid->mData1 = this->valueCount();
1711 util::memzero(dstGrid->mGridName, GridData::MaxNameSize);
1712 strncpy(dstGrid->mGridName, mSrcNodeAcc.getName().c_str(), GridData::MaxNameSize-1);
1713 if (mSrcNodeAcc.hasLongGridName()) dstGrid->setLongGridNameOn();
1716 if (mBlindMetaData.size()>0) {
1717 auto *metaData = this->dstMeta(0);
1718 dstGrid->mBlindMetadataOffset = util::PtrDiff(metaData, dstGrid);
1719 dstGrid->mBlindMetadataCount =
static_cast<uint32_t
>(mBlindMetaData.size());
1720 char *blindData = util::PtrAdd<char>(mBufferPtr, mOffset.blind);
1721 for (
const auto &b : mBlindMetaData) {
1722 *metaData = *b.metaData;
1723 metaData->setBlindData(blindData);
1724 if (metaData->mDataClass == GridBlindDataClass::GridName)
strcpy(blindData, mSrcNodeAcc.getName().c_str());
1726 blindData += b.memUsage();
1728 mBlindMetaData.clear();
1734template <
typename SrcGr
idT>
1735template <
typename DstBuildT>
1736inline typename util::disable_if<BuildTraits<DstBuildT>::is_index>::type
1737CreateNanoGrid<SrcGridT>::postProcess()
1739 if constexpr(util::is_same<FpN, DstBuildT>::value) mCodec.reset();
1740 auto *dstGrid = this->
template dstGrid<DstBuildT>();
1742#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1743 auto *metaData = this->dstMeta(0);
1744 if constexpr(util::is_same<openvdb::tools::PointIndexGrid, SrcGridT>::value ||
1745 util::is_same<openvdb::points::PointDataGrid, SrcGridT>::value) {
1746 static_assert(util::is_same<DstBuildT, uint32_t>::value,
"expected DstBuildT==uint32_t");
1747 auto *dstData0 = this->
template dstNode<DstBuildT,0>(0)->data();
1748 dstData0->mMinimum = 0;
1749 dstData0->mMaximum = dstData0->mValues[511u];
1750 for (uint64_t i=1, n=mSrcNodeAcc.nodeCount(0); i<n; ++i) {
1751 auto *dstData1 = dstData0 + 1;
1752 dstData1->mMinimum = dstData0->mMinimum + dstData0->mMaximum;
1753 dstData1->mMaximum = dstData1->mValues[511u];
1754 dstData0 = dstData1;
1756 for (
size_t i = 0, n = dstGrid->blindDataCount(); i < n; ++i, ++metaData) {
1757 if constexpr(util::is_same<openvdb::tools::PointIndexGrid, SrcGridT>::value) {
1758 if (metaData->mDataClass != GridBlindDataClass::IndexArray)
continue;
1759 if (metaData->mDataType == GridType::UInt32) {
1760 uint32_t *blindData =
const_cast<uint32_t*
>(metaData->template getBlindData<uint32_t>());
1761 util::forEach(0, mSrcNodeAcc.nodeCount(0), 16, [&](
const auto& r) {
1762 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1763 for (auto j = r.begin(); j != r.end(); ++j, ++dstLeaf) {
1764 uint32_t* p = blindData + dstLeaf->mMinimum;
1765 for (uint32_t idx : mSrcNodeAcc.template node<0>(j).indices()) *p++ = idx;
1770 if (metaData->mDataClass != GridBlindDataClass::AttributeArray)
continue;
1771 if (
auto *blindData = dstGrid->template getBlindData<float>(i)) {
1772 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1773 }
else if (
auto *blindData = dstGrid->template getBlindData<nanovdb::Vec3f>(i)) {
1774 this->
template copyPointAttribute<DstBuildT>(i,
reinterpret_cast<openvdb::Vec3f*
>(blindData));
1775 }
else if (
auto *blindData = dstGrid->template getBlindData<int32_t>(i)) {
1776 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1777 }
else if (
auto *blindData = dstGrid->template getBlindData<int64_t>(i)) {
1778 this->
template copyPointAttribute<DstBuildT>(i, blindData);
1781 std::cerr <<
"unsupported point attribute \"" <<
toStr(str, metaData->mDataType) <<
"\"\n";
1794template <
typename SrcGr
idT>
1795template <
typename DstBuildT>
1796inline typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1797CreateNanoGrid<SrcGridT>::postProcess(uint32_t channels)
1800 const std::string typeName =
toStr(str, toGridType<SrcValueT>());
1801 const uint64_t valueCount = this->valueCount();
1802 auto *dstGrid = this->
template dstGrid<DstBuildT>();
1803 for (uint32_t i=0; i<channels; ++i) {
1804 const std::string name =
"channel_"+std::to_string(i);
1805 int j = dstGrid->findBlindData(name.c_str());
1806 if (j<0)
throw std::runtime_error(
"CreateNanoGrid::postProcess: missing " + name);
1807 auto *metaData = this->dstMeta(j);
1808 metaData->mDataClass = GridBlindDataClass::ChannelArray;
1809 metaData->mDataType = toGridType<SrcValueT>();
1810 if (metaData->mSemantic == GridBlindDataSemantic::Unknown) {
1811 metaData->mSemantic =
toSemantic( mSrcNodeAcc.gridClass());
1813 SrcValueT *blindData =
const_cast<SrcValueT*
>(metaData->template getBlindData<SrcValueT>());
1815 util::forEach(0,valueCount,1024,[&](
const util::Range1D &r){
1816 SrcValueT *dst=blindData+r.begin(), *end=dst+r.size(), *src=dst-valueCount;
1817 while(dst!=end) *dst++ = *src++;
1820 this->
template copyValues<DstBuildT>(blindData);
1823 updateGridStats(this->
template dstGrid<DstBuildT>(), std::min(StatsMode::BBox, mStats));
1829template <
typename SrcGr
idT>
1830template <
typename DstBuildT>
1831typename util::enable_if<BuildTraits<DstBuildT>::is_index>::type
1834 assert(mBufferPtr && buffer);
1837 if (this->valueCount()==0) this->
template countValues<DstBuildT>();
1839 auto copyNodeValues = [&](
const auto &node,
SrcValueT *v) {
1841 for (
auto it = node.cbeginValueOn(); it; ++it) *v++ = *it;
1843 for (
auto it = node.cbeginValueAll(); it; ++it) *v++ = *it;
1845 if (mIncludeStats) {
1847 *v++ = node.minimum();
1848 *v++ = node.maximum();
1850 *v++ = node.average();
1851 *v++ = node.stdDeviation();
1865 const SrcRootT &root = mSrcNodeAcc.root();
1866 buffer[0] = root.background();
1867 if (mIncludeTiles) {
1868 copyNodeValues(root, buffer + 1u);
1870 for (auto i = r.begin(); i!=r.end(); ++i) {
1871 copyNodeValues(mSrcNodeAcc.template node<2>(i), buffer + mValIdx[2][i]);
1875 for (auto i = r.begin(); i!=r.end(); ++i) {
1876 copyNodeValues(mSrcNodeAcc.template node<1>(i), buffer + mValIdx[1][i]);
1881 for (auto i = r.begin(); i!=r.end(); ++i) {
1882 copyNodeValues(mSrcNodeAcc.template node<0>(i), buffer + mValIdx[0][i]);
1890#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
1892template <
typename SrcGr
idT>
1894typename util::disable_if<util::is_same<T, openvdb::tools::PointIndexGrid>::value ||
1895 util::is_same<T, openvdb::points::PointDataGrid>::value, uint64_t>::type
1896CreateNanoGrid<SrcGridT>::countPoints()
const
1898 static_assert(util::is_same<T, SrcGridT>::value,
"expected default template parameter");
1902template <
typename SrcGr
idT>
1904typename util::enable_if<util::is_same<T, openvdb::tools::PointIndexGrid>::value ||
1905 util::is_same<T, openvdb::points::PointDataGrid>::value, uint64_t>::type
1906CreateNanoGrid<SrcGridT>::countPoints()
const
1908 static_assert(util::is_same<T, SrcGridT>::value,
"expected default template parameter");
1909 return util::reduce(0, mSrcNodeAcc.nodeCount(0), 8, uint64_t(0), [&](
auto &r, uint64_t sum) {
1910 for (
auto i=r.begin(); i!=r.end(); ++i) sum += mSrcNodeAcc.template node<0>(i).getLastValue();
1911 return sum;}, std::plus<uint64_t>());
1914template <
typename SrcGr
idT>
1915template<
typename DstBuildT,
typename AttT,
typename CodecT,
typename T>
1916typename util::enable_if<util::is_same<openvdb::points::PointDataGrid, T>::value>::type
1917CreateNanoGrid<SrcGridT>::copyPointAttribute(
size_t attIdx, AttT *attPtr)
1919 static_assert(util::is_same<SrcGridT, T>::value,
"Expected default parameter");
1920 using HandleT = openvdb::points::AttributeHandle<AttT, CodecT>;
1921 util::forEach(0, mSrcNodeAcc.nodeCount(0), 16, [&](
const auto& r) {
1922 auto *dstLeaf = this->template dstNode<DstBuildT,0>(r.begin());
1923 for (auto i = r.begin(); i != r.end(); ++i, ++dstLeaf) {
1924 auto& srcLeaf = mSrcNodeAcc.template node<0>(i);
1925 HandleT handle(srcLeaf.constAttributeArray(attIdx));
1926 AttT *p = attPtr + dstLeaf->mMinimum;
1927 for (auto iter = srcLeaf.beginIndexOn(); iter; ++iter) *p++ = handle.get(*iter);
1936template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1937typename util::disable_if<BuildTraits<DstBuildT>::is_index || BuildTraits<DstBuildT>::is_Fp, GridHandle<BufferT>>::type
1942 const BufferT &buffer)
1948 return converter.template getHandle<DstBuildT, BufferT>(buffer);
1953template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1960 const BufferT &buffer)
1964 return converter.template getHandle<DstBuildT, BufferT>(channels, includeStats, includeTiles, buffer);
1969template<
typename SrcGr
idT,
typename DstBuildT,
typename OracleT,
typename BufferT>
1976 const OracleT &oracle,
1977 const BufferT &buffer)
1984 return converter.template getHandle<DstBuildT, OracleT, BufferT>(oracle, buffer);
1989template<
typename SrcGr
idT,
typename DstBuildT,
typename BufferT>
1996 const BufferT &buffer)
2003 return converter.template getHandle<DstBuildT, BufferT>(buffer);
2008#if defined(NANOVDB_USE_OPENVDB) && !defined(__CUDACC__)
2009template<
typename BufferT>
2011openToNanoVDB(
const openvdb::GridBase::Ptr& base,
2017 using openvdb_Vec4fTree =
typename openvdb::tree::Tree4<openvdb::Vec4f, 5, 4, 3>::Type;
2018 using openvdb_Vec4dTree =
typename openvdb::tree::Tree4<openvdb::Vec4d, 5, 4, 3>::Type;
2023 if (
auto grid = openvdb::GridBase::grid<openvdb::FloatGrid>(base)) {
2024 return createNanoGrid<openvdb::FloatGrid, float, BufferT>(*grid, sMode, cMode, verbose);
2025 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::DoubleGrid>(base)) {
2026 return createNanoGrid<openvdb::DoubleGrid, double, BufferT>(*grid, sMode, cMode, verbose);
2027 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int32Grid>(base)) {
2028 return createNanoGrid<openvdb::Int32Grid, int32_t,BufferT>(*grid, sMode, cMode, verbose);
2029 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int64Grid>(base)) {
2030 return createNanoGrid<openvdb::Int64Grid, int64_t, BufferT>(*grid, sMode, cMode, verbose);
2031 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_UInt32Grid>(base)) {
2032 return createNanoGrid<openvdb_UInt32Grid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2033 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3fGrid>(base)) {
2034 return createNanoGrid<openvdb::Vec3fGrid, nanovdb::Vec3f, BufferT>(*grid, sMode, cMode, verbose);
2035 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3dGrid>(base)) {
2036 return createNanoGrid<openvdb::Vec3dGrid, nanovdb::Vec3d, BufferT>(*grid, sMode, cMode, verbose);
2037 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::tools::PointIndexGrid>(base)) {
2038 return createNanoGrid<openvdb::tools::PointIndexGrid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2039 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::points::PointDataGrid>(base)) {
2040 return createNanoGrid<openvdb::points::PointDataGrid, uint32_t, BufferT>(*grid, sMode, cMode, verbose);
2041 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::MaskGrid>(base)) {
2042 return createNanoGrid<openvdb::MaskGrid, nanovdb::ValueMask, BufferT>(*grid, sMode, cMode, verbose);
2043 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::BoolGrid>(base)) {
2044 return createNanoGrid<openvdb::BoolGrid, bool, BufferT>(*grid, sMode, cMode, verbose);
2045 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4fGrid>(base)) {
2046 return createNanoGrid<openvdb_Vec4fGrid, nanovdb::Vec4f, BufferT>(*grid, sMode, cMode, verbose);
2047 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4dGrid>(base)) {
2048 return createNanoGrid<openvdb_Vec4dGrid, nanovdb::Vec4d, BufferT>(*grid, sMode, cMode, verbose);
2054template<
typename DstBuildT,
typename BufferT>
2055typename util::enable_if<BuildTraits<DstBuildT>::is_index, GridHandle<BufferT>>::type
2056openToIndexVDB(
const openvdb::GridBase::Ptr& base,
2063 using openvdb_Vec4fTree =
typename openvdb::tree::Tree4<openvdb::Vec4f, 5, 4, 3>::Type;
2064 using openvdb_Vec4dTree =
typename openvdb::tree::Tree4<openvdb::Vec4d, 5, 4, 3>::Type;
2069 if (
auto grid = openvdb::GridBase::grid<openvdb::FloatGrid>(base)) {
2070 return createNanoGrid<openvdb::FloatGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2071 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::DoubleGrid>(base)) {
2072 return createNanoGrid<openvdb::DoubleGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2073 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int32Grid>(base)) {
2074 return createNanoGrid<openvdb::Int32Grid, DstBuildT,BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2075 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Int64Grid>(base)) {
2076 return createNanoGrid<openvdb::Int64Grid, DstBuildT, BufferT>(*grid, includeStats, includeTiles, verbose);
2077 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_UInt32Grid>(base)) {
2078 return createNanoGrid<openvdb_UInt32Grid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2079 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3fGrid>(base)) {
2080 return createNanoGrid<openvdb::Vec3fGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2081 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::Vec3dGrid>(base)) {
2082 return createNanoGrid<openvdb::Vec3dGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2083 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::tools::PointIndexGrid>(base)) {
2084 return createNanoGrid<openvdb::tools::PointIndexGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2085 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::points::PointDataGrid>(base)) {
2086 return createNanoGrid<openvdb::points::PointDataGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2087 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::MaskGrid>(base)) {
2088 return createNanoGrid<openvdb::MaskGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2089 }
else if (
auto grid = openvdb::GridBase::grid<openvdb::BoolGrid>(base)) {
2090 return createNanoGrid<openvdb::BoolGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2091 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4fGrid>(base)) {
2092 return createNanoGrid<openvdb_Vec4fGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);
2093 }
else if (
auto grid = openvdb::GridBase::grid<openvdb_Vec4dGrid>(base)) {
2094 return createNanoGrid<openvdb_Vec4dGrid, DstBuildT, BufferT>(*grid, channels, includeStats, includeTiles, verbose);