OpenVDB 11.0.0

Loading...
Searching...
No Matches
NanoToOpenVDB.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: MPL-2.0
3
4/*!
5 \file NanoToOpenVDB.h
6
7 \author Ken Museth
8
9 \date May 6, 2020
10
11 \brief This class will deserialize an NanoVDB grid into an OpenVDB grid.
12
13 \todo Add support for PointIndexGrid and PointDataGrid
14*/
15
16#include <nanovdb/NanoVDB.h> // manages and streams the raw memory buffer of a NanoVDB grid.
17#include <nanovdb/util/GridHandle.h>
18#include "ForEach.h"
19
20#include <openvdb/openvdb.h>
21
22#ifndef NANOVDB_NANOTOOPENVDB_H_HAS_BEEN_INCLUDED
23#define NANOVDB_NANOTOOPENVDB_H_HAS_BEEN_INCLUDED
24
25 template<typename T>
26 struct ConvertTrait {using Type = T;};
27
28 template<typename T>
29 struct ConvertTrait<nanovdb::Vec3<T>> {using Type = openvdb::math::Vec3<T>;};
30
31 template<typename T>
32 struct ConvertTrait<nanovdb::Vec4<T>> {using Type = openvdb::math::Vec4<T>;};
33
34 template<>
35 struct ConvertTrait<nanovdb::Fp4> {using Type = float;};
36
37 template<>
38 struct ConvertTrait<nanovdb::Fp8> {using Type = float;};
39
40 template<>
41 struct ConvertTrait<nanovdb::Fp16> {using Type = float;};
42
43 template<>
44 struct ConvertTrait<nanovdb::FpN> {using Type = float;};
45
46 template<>
47 struct ConvertTrait<nanovdb::ValueMask> {using Type = openvdb::ValueMask;};
48
49 namespace nanovdb {
50
51/// @brief Forward declaration of free-standing function that de-serializes a typed NanoVDB grid into an OpenVDB Grid
52 template<typename NanoBuildT>
53 typename openvdb::Grid<typename openvdb::tree::Tree4<typename ConvertTrait<NanoBuildT>::Type>::Type>::Ptr
54 nanoToOpenVDB(const NanoGrid<NanoBuildT>& grid, int verbose = 0);
55
56/// @brief Forward declaration of free-standing function that de-serializes a NanoVDB GridHandle into an OpenVDB GridBase
57 template<typename BufferT>
58openvdb::GridBase::Ptr
59 nanoToOpenVDB(const GridHandle<BufferT>& handle, int verbose = 0, uint32_t n = 0);
60
61/// @brief This class will serialize an OpenVDB grid into a NanoVDB grid managed by a GridHandle.
62 template<typename NanoBuildT>
63 class NanoToOpenVDB
64{
65 using NanoNode0 = LeafNode<NanoBuildT, openvdb::Coord, openvdb::util::NodeMask>; // note that it's using openvdb coord nd mask types!
66 using NanoNode1 = InternalNode<NanoNode0>;
67 using NanoNode2 = InternalNode<NanoNode1>;
68 using NanoRootT = RootNode<NanoNode2>;
69 using NanoTreeT = Tree<NanoRootT>;
70 using NanoGridT = Grid<NanoTreeT>;
71 using NanoValueT = typename NanoGridT::ValueType;
72
73 using OpenBuildT = typename ConvertTrait<NanoBuildT>::Type; // e.g. float -> float but nanovdb::Vec3<float> -> openvdb::Vec3<float>
74 using OpenNode0 = openvdb::tree::LeafNode<OpenBuildT, NanoNode0::LOG2DIM>; // leaf
75 using OpenNode1 = openvdb::tree::InternalNode<OpenNode0, NanoNode1::LOG2DIM>; // lower
76 using OpenNode2 = openvdb::tree::InternalNode<OpenNode1, NanoNode2::LOG2DIM>; // upper
77 using OpenRootT = openvdb::tree::RootNode<OpenNode2>;
78 using OpenTreeT = openvdb::tree::Tree<OpenRootT>;
79 using OpenGridT = openvdb::Grid<OpenTreeT>;
80 using OpenValueT = typename OpenGridT::ValueType;
81
82 public:
83 /// @brief Construction from an existing const OpenVDB Grid.
84 NanoToOpenVDB(){};
85
86 /// @brief Return a shared pointer to a NanoVDB grid constructed from the specified OpenVDB grid
87 typename OpenGridT::Ptr operator()(const NanoGrid<NanoBuildT>& grid, int verbose = 0);
88
89 private:
90
91 template<typename NanoNodeT, typename OpenNodeT>
92 OpenNodeT* processNode(const NanoNodeT*);
93
94 OpenNode2* process(const NanoNode2* node) {return this->template processNode<NanoNode2, OpenNode2>(node);}
95 OpenNode1* process(const NanoNode1* node) {return this->template processNode<NanoNode1, OpenNode1>(node);}
96
97 template <typename NanoLeafT>
98 typename std::enable_if<!std::is_same<bool, typename NanoLeafT::BuildType>::value &&
99 !std::is_same<ValueMask, typename NanoLeafT::BuildType>::value &&
100 !std::is_same<Fp4, typename NanoLeafT::BuildType>::value &&
101 !std::is_same<Fp8, typename NanoLeafT::BuildType>::value &&
102 !std::is_same<Fp16,typename NanoLeafT::BuildType>::value &&
103 !std::is_same<FpN, typename NanoLeafT::BuildType>::value,
104 OpenNode0*>::type
105 process(const NanoLeafT* node);
106
107 template <typename NanoLeafT>
108 typename std::enable_if<std::is_same<Fp4, typename NanoLeafT::BuildType>::value ||
109 std::is_same<Fp8, typename NanoLeafT::BuildType>::value ||
110 std::is_same<Fp16,typename NanoLeafT::BuildType>::value ||
111 std::is_same<FpN, typename NanoLeafT::BuildType>::value,
112 OpenNode0*>::type
113 process(const NanoLeafT* node);
114
115 template <typename NanoLeafT>
116 typename std::enable_if<std::is_same<ValueMask, typename NanoLeafT::BuildType>::value,
117 OpenNode0*>::type
118 process(const NanoLeafT* node);
119
120 template <typename NanoLeafT>
121 typename std::enable_if<std::is_same<bool, typename NanoLeafT::BuildType>::value,
122 OpenNode0*>::type
123 process(const NanoLeafT* node);
124
125 /// converts nanovdb value types to openvdb value types, e.g. nanovdb::Vec3f& -> openvdb::Vec3f&
126 static const OpenValueT& Convert(const NanoValueT &v) {return reinterpret_cast<const OpenValueT&>(v);}
127 static const OpenValueT* Convert(const NanoValueT *v) {return reinterpret_cast<const OpenValueT*>(v);}
128
129}; // NanoToOpenVDB class
130
131 template<typename NanoBuildT>
132 typename NanoToOpenVDB<NanoBuildT>::OpenGridT::Ptr
133 NanoToOpenVDB<NanoBuildT>::operator()(const NanoGrid<NanoBuildT>& grid, int /*verbose*/)
134{
135 // since the input nanovdb grid might use nanovdb types (Coord, Mask, Vec3) we cast to use openvdb types
136 const NanoGridT *srcGrid = reinterpret_cast<const NanoGridT*>(&grid);
137
138 auto dstGrid = openvdb::createGrid<OpenGridT>(Convert(srcGrid->tree().background()));
139 dstGrid->setName(srcGrid->gridName()); // set grid name
140 switch (srcGrid->gridClass()) { // set grid class
141 case nanovdb::GridClass::LevelSet:
142 dstGrid->setGridClass(openvdb::GRID_LEVEL_SET);
143 break;
144 case nanovdb::GridClass::FogVolume:
145 dstGrid->setGridClass(openvdb::GRID_FOG_VOLUME);
146 break;
147 case nanovdb::GridClass::Staggered:
148 dstGrid->setGridClass(openvdb::GRID_STAGGERED);
149 break;
150 case nanovdb::GridClass::PointIndex:
151 throw std::runtime_error("NanoToOpenVDB does not yet support PointIndexGrids");
152 case nanovdb::GridClass::PointData:
153 throw std::runtime_error("NanoToOpenVDB does not yet support PointDataGrids");
154 default:
155 dstGrid->setGridClass(openvdb::GRID_UNKNOWN);
156 }
157 // set transform
158 const nanovdb::Map& nanoMap = reinterpret_cast<const GridData*>(srcGrid)->mMap;
159 auto mat = openvdb::math::Mat4<double>::identity();
160 mat.setMat3(openvdb::math::Mat3<double>(nanoMap.mMatD));
161 mat.transpose(); // the 3x3 in nanovdb is transposed relative to openvdb's 3x3
162 mat.setTranslation(openvdb::math::Vec3<double>(nanoMap.mVecD));
163 dstGrid->setTransform(openvdb::math::Transform::createLinearTransform(mat)); // calls simplify!
164
165 // process root node
166 auto &root = dstGrid->tree().root();
167 auto *data = srcGrid->tree().root().data();
168 for (uint32_t i=0; i<data->mTableSize; ++i) {
169 auto *tile = data->tile(i);
170 if (tile->isChild()) {
171 root.addChild( this->process( data->getChild(tile)) );
172 } else {
173 root.addTile(tile->origin(), Convert(tile->value), tile->state);
174 }
175 }
176
177 return dstGrid;
178}
179
180 template<typename T>
181 template<typename SrcNodeT, typename DstNodeT>
182DstNodeT*
183 NanoToOpenVDB<T>::processNode(const SrcNodeT *srcNode)
184{
185 DstNodeT *dstNode = new DstNodeT(); // un-initialized for fast construction
186 dstNode->setOrigin(srcNode->origin());
187 const auto& childMask = srcNode->childMask();
188 const_cast<typename DstNodeT::NodeMaskType&>(dstNode->getValueMask()) = srcNode->valueMask();
189 const_cast<typename DstNodeT::NodeMaskType&>(dstNode->getChildMask()) = childMask;
190 auto* dstTable = const_cast<typename DstNodeT::UnionType*>(dstNode->getTable());
191 auto* srcData = srcNode->data();
192 std::vector<std::pair<uint32_t, const typename SrcNodeT::ChildNodeType*>> childNodes;
193 const auto childCount = childMask.countOn();
194 childNodes.reserve(childCount);
195 for (uint32_t n = 0; n < DstNodeT::NUM_VALUES; ++n) {
196 if (childMask.isOn(n)) {
197 childNodes.emplace_back(n, srcData->getChild(n));
198 } else {
199 dstTable[n].setValue(Convert(srcData->mTable[n].value));
200 }
201 }
202 auto kernel = [&](const auto& r) {
203 for (auto i = r.begin(); i != r.end(); ++i) {
204 auto &p = childNodes[i];
205 dstTable[p.first].setChild( this->process(p.second) );
206 }
207 };
208
209#if 0
210 kernel(Range1D(0, childCount));
211#else
212 forEach(0, childCount, 1, kernel);
213#endif
214 return dstNode;
215} // processNode
216
217 template<typename T>
218 template <typename NanoLeafT>
219 inline typename std::enable_if<!std::is_same<bool, typename NanoLeafT::BuildType>::value &&
220 !std::is_same<ValueMask, typename NanoLeafT::BuildType>::value &&
221 !std::is_same<Fp4, typename NanoLeafT::BuildType>::value &&
222 !std::is_same<Fp8, typename NanoLeafT::BuildType>::value &&
223 !std::is_same<Fp16,typename NanoLeafT::BuildType>::value &&
224 !std::is_same<FpN, typename NanoLeafT::BuildType>::value,
225 typename NanoToOpenVDB<T>::OpenNode0*>::type
226 NanoToOpenVDB<T>::process(const NanoLeafT *srcNode)
227{
228 static_assert(std::is_same<NanoLeafT, NanoNode0>::value, "NanoToOpenVDB<FpN>::process assert failed");
229 OpenNode0* dstNode = new OpenNode0(); // un-initialized for fast construction
230 dstNode->setOrigin(srcNode->origin());
231 dstNode->setValueMask(srcNode->valueMask());
232
233 const auto* src = Convert(srcNode->data()->mValues);// doesn't work for compressed data, bool or ValueMask
234 for (auto *dst = dstNode->buffer().data(), *end = dst + OpenNode0::SIZE; dst != end; dst += 4, src += 4) {
235 dst[0] = src[0];
236 dst[1] = src[1];
237 dst[2] = src[2];
238 dst[3] = src[3];
239 }
240
241 return dstNode;
242} // process(NanoNode0)
243
244 template<typename T>
245 template <typename NanoLeafT>
246 inline typename std::enable_if<std::is_same<Fp4, typename NanoLeafT::BuildType>::value ||
247 std::is_same<Fp8, typename NanoLeafT::BuildType>::value ||
248 std::is_same<Fp16,typename NanoLeafT::BuildType>::value ||
249 std::is_same<FpN, typename NanoLeafT::BuildType>::value,
250 typename NanoToOpenVDB<T>::OpenNode0*>::type
251NanoToOpenVDB<T>::process(const NanoLeafT *srcNode)
252{
253 static_assert(std::is_same<NanoLeafT, NanoNode0>::value, "NanoToOpenVDB<T>::process assert failed");
254 OpenNode0* dstNode = new OpenNode0(); // un-initialized for fast construction
255 dstNode->setOrigin(srcNode->origin());
256 dstNode->setValueMask(srcNode->valueMask());
257 float *dst = dstNode->buffer().data();
258 for (int i=0; i!=512; i+=4) {
259 *dst++ = srcNode->getValue(i);
260 *dst++ = srcNode->getValue(i+1);
261 *dst++ = srcNode->getValue(i+2);
262 *dst++ = srcNode->getValue(i+3);
263 }
264
265 return dstNode;
266} // process(NanoNode0)
267
268 template<typename T>
269 template <typename NanoLeafT>
270 inline typename std::enable_if<std::is_same<ValueMask, typename NanoLeafT::BuildType>::value,
271 typename NanoToOpenVDB<T>::OpenNode0*>::type
272NanoToOpenVDB<T>::process(const NanoLeafT *srcNode)
273{
274 static_assert(std::is_same<NanoLeafT, NanoNode0>::value, "NanoToOpenVDB<ValueMask>::process assert failed");
275 OpenNode0* dstNode = new OpenNode0(); // un-initialized for fast construction
276 dstNode->setOrigin(srcNode->origin());
277 dstNode->setValueMask(srcNode->valueMask());
278
279 return dstNode;
280} // process(NanoNode0)
281
282 template<typename T>
283 template <typename NanoLeafT>
284 inline typename std::enable_if<std::is_same<bool, typename NanoLeafT::BuildType>::value,
285 typename NanoToOpenVDB<T>::OpenNode0*>::type
286NanoToOpenVDB<T>::process(const NanoLeafT *srcNode)
287{
288 static_assert(std::is_same<NanoLeafT, NanoNode0>::value, "NanoToOpenVDB<ValueMask>::process assert failed");
289 OpenNode0* dstNode = new OpenNode0(); // un-initialized for fast construction
290 dstNode->setOrigin(srcNode->origin());
291 dstNode->setValueMask(srcNode->valueMask());
292 reinterpret_cast<openvdb::util::NodeMask<3>&>(dstNode->buffer()) = srcNode->data()->mValues;
293
294 return dstNode;
295} // process(NanoNode0)
296
297 template<typename NanoBuildT>
298 inline typename openvdb::Grid<typename openvdb::tree::Tree4<typename ConvertTrait<NanoBuildT>::Type>::Type>::Ptr
299 nanoToOpenVDB(const NanoGrid<NanoBuildT>& grid, int verbose)
300{
301 nanovdb::NanoToOpenVDB<NanoBuildT> tmp;
302 return tmp(grid, verbose);
303}
304
305 template<typename BufferT>
306openvdb::GridBase::Ptr
307 nanoToOpenVDB(const GridHandle<BufferT>& handle, int verbose, uint32_t n)
308{
309 if (auto grid = handle.template grid<float>(n)) {
310 return nanovdb::nanoToOpenVDB(*grid, verbose);
311 } else if (auto grid = handle.template grid<double>(n)) {
312 return nanovdb::nanoToOpenVDB(*grid, verbose);
313 } else if (auto grid = handle.template grid<int32_t>(n)) {
314 return nanovdb::nanoToOpenVDB(*grid, verbose);
315 } else if (auto grid = handle.template grid<int64_t>(n)) {
316 return nanovdb::nanoToOpenVDB(*grid, verbose);
317 } else if (auto grid = handle.template grid<bool>(n)) {
318 return nanovdb::nanoToOpenVDB(*grid, verbose);
319 } else if (auto grid = handle.template grid<nanovdb::Fp4>(n)) {
320 return nanovdb::nanoToOpenVDB(*grid, verbose);
321 } else if (auto grid = handle.template grid<nanovdb::Fp8>(n)) {
322 return nanovdb::nanoToOpenVDB(*grid, verbose);
323 } else if (auto grid = handle.template grid<nanovdb::Fp16>(n)) {
324 return nanovdb::nanoToOpenVDB(*grid, verbose);
325 } else if (auto grid = handle.template grid<nanovdb::FpN>(n)) {
326 return nanovdb::nanoToOpenVDB(*grid, verbose);
327 } else if (auto grid = handle.template grid<nanovdb::ValueMask>(n)) {
328 return nanovdb::nanoToOpenVDB(*grid, verbose);
329 } else if (auto grid = handle.template grid<nanovdb::Vec3f>(n)) {
330 return nanovdb::nanoToOpenVDB(*grid, verbose);
331 } else if (auto grid = handle.template grid<nanovdb::Vec3d>(n)) {
332 return nanovdb::nanoToOpenVDB(*grid, verbose);
333 } else if (auto grid = handle.template grid<nanovdb::Vec4f>(n)) {
334 return nanovdb::nanoToOpenVDB(*grid, verbose);
335 } else if (auto grid = handle.template grid<nanovdb::Vec4d>(n)) {
336 return nanovdb::nanoToOpenVDB(*grid, verbose);
337 } else {
338 OPENVDB_THROW(openvdb::RuntimeError, "Unsupported NanoVDB grid type!");
339 }
340}
341
342} // namespace nanovdb
343
344#endif // NANOVDB_NANOTOOPENVDB_H_HAS_BEEN_INCLUDED
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
ForEach.h
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
GridHandle.h
Defines GridHandle, which manages a host, and possibly a device, memory buffer containing one or more...
NanoVDB.h
Implements a light-weight self-contained VDB data-structure in a single file! In other words,...
nanovdb::GridHandle
This class serves to manage a buffer containing one or more NanoVDB Grids.
Definition GridHandle.h:38
nanovdb::Grid
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition NanoVDB.h:3699
nanovdb::Grid::ValueType
typename TreeT::ValueType ValueType
Definition NanoVDB.h:3708
nanovdb::Grid::gridClass
const GridClass & gridClass() const
Definition NanoVDB.h:3828
nanovdb::Grid::gridName
const char * gridName() const
Return a c-string with the name of this grid.
Definition NanoVDB.h:3858
nanovdb::Grid::tree
const TreeT & tree() const
Return a const reference to the tree.
Definition NanoVDB.h:3753
nanovdb::InternalNode
Internal nodes of a VDB treedim(),.
Definition NanoVDB.h:4969
nanovdb::LeafNode
Leaf nodes of the VDB tree. (defaults to 8x8x8 = 512 voxels)
Definition NanoVDB.h:6027
nanovdb::NanoToOpenVDB
This class will serialize an OpenVDB grid into a NanoVDB grid managed by a GridHandle.
Definition NanoToOpenVDB.h:64
nanovdb::NanoToOpenVDB::NanoToOpenVDB
NanoToOpenVDB()
Construction from an existing const OpenVDB Grid.
Definition NanoToOpenVDB.h:84
nanovdb::NanoToOpenVDB::operator()
OpenGridT::Ptr operator()(const NanoGrid< NanoBuildT > &grid, int verbose=0)
Return a shared pointer to a NanoVDB grid constructed from the specified OpenVDB grid.
Definition NanoToOpenVDB.h:133
nanovdb::RootNode
Top-most node of the VDB tree structure.
Definition NanoVDB.h:4330
nanovdb::Tree
VDB Tree, which is a thin wrapper around a RootNode.
Definition NanoVDB.h:3990
openvdb::v11_0::Grid
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
openvdb::v11_0::Grid::ValueType
typename _TreeType::ValueType ValueType
Definition Grid.h:579
openvdb::v11_0::Grid::Ptr
SharedPtr< Grid > Ptr
Definition Grid.h:573
openvdb::v11_0::RuntimeError
Definition Exceptions.h:63
openvdb::v11_0::ValueMask
Definition Types.h:111
nanovdb
Convert a base-pointer to an openvdb grid, denoted srcGrid, to a nanovdb grid of the same type,...
Definition NanoVDB.h:247
nanovdb::GridClass::FogVolume
@ FogVolume
nanovdb::GridClass::PointIndex
@ PointIndex
nanovdb::GridClass::PointData
@ PointData
nanovdb::GridClass::Staggered
@ Staggered
nanovdb::GridClass::LevelSet
@ LevelSet
nanovdb::nanoToOpenVDB
openvdb::Grid< typenameopenvdb::tree::Tree4< typenameConvertTrait< NanoBuildT >::Type >::Type >::Ptr nanoToOpenVDB(const NanoGrid< NanoBuildT > &grid, int verbose=0)
Forward declaration of free-standing function that de-serializes a typed NanoVDB grid into an OpenVDB...
Definition NanoToOpenVDB.h:299
nanovdb::forEach
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition ForEach.h:40
nanovdb::Range1D
Range< 1, size_t > Range1D
Definition Range.h:30
openvdb::v11_0::GRID_FOG_VOLUME
@ GRID_FOG_VOLUME
Definition Types.h:456
openvdb::v11_0::GRID_STAGGERED
@ GRID_STAGGERED
Definition Types.h:457
openvdb::v11_0::GRID_LEVEL_SET
@ GRID_LEVEL_SET
Definition Types.h:455
openvdb::v11_0::GRID_UNKNOWN
@ GRID_UNKNOWN
Definition Types.h:454
openvdb.h
ConvertTrait< nanovdb::Fp16 >::Type
float Type
Definition NanoToOpenVDB.h:41
ConvertTrait< nanovdb::Fp4 >::Type
float Type
Definition NanoToOpenVDB.h:35
ConvertTrait< nanovdb::Fp8 >::Type
float Type
Definition NanoToOpenVDB.h:38
ConvertTrait< nanovdb::FpN >::Type
float Type
Definition NanoToOpenVDB.h:44
ConvertTrait< nanovdb::Vec3< T > >::Type
openvdb::math::Vec3< T > Type
Definition NanoToOpenVDB.h:29
ConvertTrait< nanovdb::Vec4< T > >::Type
openvdb::math::Vec4< T > Type
Definition NanoToOpenVDB.h:32
ConvertTrait
Definition NanoToOpenVDB.h:26
ConvertTrait::Type
T Type
Definition NanoToOpenVDB.h:26
nanovdb::GridData
Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
Definition NanoVDB.h:3512
nanovdb::Map
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition NanoVDB.h:3158
nanovdb::Map::mVecD
double mVecD[3]
Definition NanoVDB.h:3165
nanovdb::Map::mMatD
double mMatD[9]
Definition NanoVDB.h:3163