OpenVDB 10.0.1
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.
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
25template<typename T>
26struct ConvertTrait {using Type = T;};
27
28template<typename T>
29struct ConvertTrait<nanovdb::Vec3<T>> {using Type = openvdb::math::Vec3<T>;};
30
31template<typename T>
32struct ConvertTrait<nanovdb::Vec4<T>> {using Type = openvdb::math::Vec4<T>;};
33
34template<>
35struct ConvertTrait<nanovdb::Fp4> {using Type = float;};
36
37template<>
38struct ConvertTrait<nanovdb::Fp8> {using Type = float;};
39
40template<>
41struct ConvertTrait<nanovdb::Fp16> {using Type = float;};
42
43template<>
44struct ConvertTrait<nanovdb::FpN> {using Type = float;};
45
46template<>
47struct ConvertTrait<nanovdb::ValueMask> {using Type = openvdb::ValueMask;};
48
49namespace nanovdb {
50
51/// @brief Forward declaration of free-standing function that de-serializes a typed NanoVDB grid into an OpenVDB Grid
52template<typename NanoBuildT>
54nanoToOpenVDB(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
57template<typename BufferT>
58openvdb::GridBase::Ptr
59nanoToOpenVDB(const GridHandle<BufferT>& handle, int verbose = 0);
60
61/// @brief This class will serialize an OpenVDB grid into a NanoVDB grid managed by a GridHandle.
62template<typename NanoBuildT>
64{
65 using NanoNode0 = LeafNode<NanoBuildT, openvdb::Coord, openvdb::util::NodeMask>; // note that it's using openvdb coord nd mask types!
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>;
80 using OpenValueT = typename OpenGridT::ValueType;
81
82public:
83 /// @brief Construction from an existing const OpenVDB Grid.
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
89private:
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
131template<typename NanoBuildT>
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
142 dstGrid->setGridClass(openvdb::GRID_LEVEL_SET);
143 break;
145 dstGrid->setGridClass(openvdb::GRID_FOG_VOLUME);
146 break;
148 dstGrid->setGridClass(openvdb::GRID_STAGGERED);
149 break;
151 throw std::runtime_error("NanoToOpenVDB does not yet support PointIndexGrids");
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
180template<typename T>
181template<typename SrcNodeT, typename DstNodeT>
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
217template<typename T>
218template <typename NanoLeafT>
219inline 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
226NanoToOpenVDB<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
244template<typename T>
245template <typename NanoLeafT>
246inline 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
268template<typename T>
269template <typename NanoLeafT>
270inline 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
282template<typename T>
283template <typename NanoLeafT>
284inline 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
297template<typename NanoBuildT>
304
305template<typename BufferT>
306openvdb::GridBase::Ptr
308{
309 if (auto grid = handle.template grid<float>()) {
310 return nanovdb::nanoToOpenVDB(*grid, verbose);
311 } else if (auto grid = handle.template grid<double>()) {
312 return nanovdb::nanoToOpenVDB(*grid, verbose);
313 } else if (auto grid = handle.template grid<int32_t>()) {
314 return nanovdb::nanoToOpenVDB(*grid, verbose);
315 } else if (auto grid = handle.template grid<int64_t>()) {
316 return nanovdb::nanoToOpenVDB(*grid, verbose);
317 } else if (auto grid = handle.template grid<bool>()) {
318 return nanovdb::nanoToOpenVDB(*grid, verbose);
319 } else if (auto grid = handle.template grid<nanovdb::Fp4>()) {
320 return nanovdb::nanoToOpenVDB(*grid, verbose);
321 } else if (auto grid = handle.template grid<nanovdb::Fp8>()) {
322 return nanovdb::nanoToOpenVDB(*grid, verbose);
323 } else if (auto grid = handle.template grid<nanovdb::Fp16>()) {
324 return nanovdb::nanoToOpenVDB(*grid, verbose);
325 } else if (auto grid = handle.template grid<nanovdb::FpN>()) {
326 return nanovdb::nanoToOpenVDB(*grid, verbose);
327 } else if (auto grid = handle.template grid<nanovdb::ValueMask>()) {
328 return nanovdb::nanoToOpenVDB(*grid, verbose);
329 } else if (auto grid = handle.template grid<nanovdb::Vec3f>()) {
330 return nanovdb::nanoToOpenVDB(*grid, verbose);
331 } else if (auto grid = handle.template grid<nanovdb::Vec3d>()) {
332 return nanovdb::nanoToOpenVDB(*grid, verbose);
333 } else if (auto grid = handle.template grid<nanovdb::Vec4f>()) {
334 return nanovdb::nanoToOpenVDB(*grid, verbose);
335 } else if (auto grid = handle.template grid<nanovdb::Vec4d>()) {
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
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
Defines two classes, a GridRegister the defines the value type (e.g. Double, Float etc) of a NanoVDB ...
Implements a light-weight self-contained VDB data-structure in a single file! In other words,...
Definition DenseGrid.h:402
BufferT & buffer()
Definition DenseGrid.h:426
uint8_t * data()
Returns a non-const pointer to the data.
Definition DenseGrid.h:432
const DenseGrid< ValueT > * grid() const
Returns a const pointer to the NanoVDB grid encoded in the DenseGridHandle.
Definition DenseGrid.h:447
Internal nodes of a VDB treedim(),.
Definition NanoVDB.h:3521
This class will serialize an OpenVDB grid into a NanoVDB grid managed by a GridHandle.
Definition NanoToOpenVDB.h:64
NanoToOpenVDB()
Construction from an existing const OpenVDB Grid.
Definition NanoToOpenVDB.h:84
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
Container class that associates a tree with a transform and metadata.
Definition Grid.h:571
typename _TreeType::ValueType ValueType
Definition Grid.h:579
SharedPtr< Grid > Ptr
Definition Grid.h:573
Definition Exceptions.h:63
Definition Types.h:111
Definition NanoVDB.h:208
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
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition ForEach.h:40
Range< 1, size_t > Range1D
Definition Range.h:30
@ GRID_FOG_VOLUME
Definition Types.h:417
@ GRID_STAGGERED
Definition Types.h:418
@ GRID_LEVEL_SET
Definition Types.h:416
@ GRID_UNKNOWN
Definition Types.h:415
#define OPENVDB_THROW(exception, message)
Definition Exceptions.h:74
float Type
Definition NanoToOpenVDB.h:41
float Type
Definition NanoToOpenVDB.h:35
float Type
Definition NanoToOpenVDB.h:38
float Type
Definition NanoToOpenVDB.h:44
openvdb::math::Vec3< T > Type
Definition NanoToOpenVDB.h:29
openvdb::math::Vec4< T > Type
Definition NanoToOpenVDB.h:32
Definition NanoToOpenVDB.h:26
T Type
Definition NanoToOpenVDB.h:26
Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
Definition NanoVDB.h:2432
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition NanoVDB.h:2224