OpenVDB  9.0.1
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 
25 namespace nanovdb {
26 
27 template<typename T>
28 struct ConvertTrait;
29 
30 /// @brief Forward declaration of free-standing function that de-serializes a typed NanoVDB grid into an OpenVDB Grid
31 template<typename ValueT>
33 nanoToOpenVDB(const NanoGrid<ValueT>& grid, int verbose = 0);
34 
35 /// @brief Forward declaration of free-standing function that de-serializes a NanoVDB GridHandle into an OpenVDB GridBase
36 template<typename BufferT>
38 nanoToOpenVDB(const GridHandle<BufferT>& handle, int verbose = 0);
39 
40 /// @brief This class will serialize an OpenVDB grid into a NanoVDB grid managed by a GridHandle.
41 template<typename ValueType>
43 {
44  using ValueT = typename ConvertTrait<ValueType>::Type; // e.g. float -> float but nanovdb::Vec3<float> -> openvdb::Vec3<float>
45  using SrcNode0 = LeafNode<ValueT, openvdb::Coord, openvdb::util::NodeMask>; // note that it's using openvdb types!
49  using SrcTreeT = Tree<SrcRootT>;
50  using SrcGridT = Grid<SrcTreeT>;
51 
52  using DstNode0 = openvdb::tree::LeafNode<ValueT, SrcNode0::LOG2DIM>; // leaf
53  using DstNode1 = openvdb::tree::InternalNode<DstNode0, SrcNode1::LOG2DIM>; // lower
54  using DstNode2 = openvdb::tree::InternalNode<DstNode1, SrcNode2::LOG2DIM>; // upper
55  using DstRootT = openvdb::tree::RootNode<DstNode2>;
56  using DstTreeT = openvdb::tree::Tree<DstRootT>;
58 
59 public:
60  /// @brief Construction from an existing const OpenVDB Grid.
62 
63  /// @brief Return a shared pointer to a NanoVDB grid constructed from the specified OpenVDB grid
64  typename DstGridT::Ptr operator()(const NanoGrid<ValueType>& grid, int verbose = 0);
65 
66 private:
67 
68  template<typename SrcNodeT, typename DstNodeT>
69  DstNodeT* processNode(const SrcNodeT*);
70 
71  DstNode2* process(const SrcNode2* node) {return this->template processNode<SrcNode2, DstNode2>(node);}
72  DstNode1* process(const SrcNode1* node) {return this->template processNode<SrcNode1, DstNode1>(node);}
73  DstNode0* process(const SrcNode0* node);
74 }; // NanoToOpenVDB class
75 
76 template<typename T>
77 struct ConvertTrait
78 {
79  using Type = T;
80 };
81 
82 template<typename T>
84 {
85  using Type = openvdb::math::Vec3<T>;
86 };
87 
88 template<typename T>
89 struct ConvertTrait< Vec4<T> >
90 {
91  using Type = openvdb::math::Vec4<T>;
92 };
93 
94 template<typename T>
96 NanoToOpenVDB<T>::operator()(const NanoGrid<T>& grid, int /*verbose*/)
97 {
98  // since the input nanovdb grid might use nanovdb types (Coord, Mask, Vec3) we cast to use openvdb types
99  const SrcGridT *srcGrid = reinterpret_cast<const SrcGridT*>(&grid);
100  auto dstGrid = openvdb::createGrid<DstGridT>(srcGrid->tree().background());
101  dstGrid->setName(srcGrid->gridName()); // set grid name
102  switch (srcGrid->gridClass()) { // set grid class
104  dstGrid->setGridClass(openvdb::GRID_LEVEL_SET);
105  break;
107  dstGrid->setGridClass(openvdb::GRID_FOG_VOLUME);
108  break;
110  dstGrid->setGridClass(openvdb::GRID_STAGGERED);
111  break;
113  throw std::runtime_error("NanoToOpenVDB does not yet support PointIndexGrids");
115  throw std::runtime_error("NanoToOpenVDB does not yet support PointDataGrids");
117  throw std::runtime_error("NanoToOpenVDB does not yet support Mask (or Topology) Grids");
118  default:
119  dstGrid->setGridClass(openvdb::GRID_UNKNOWN);
120  }
121  // set transform
122  const nanovdb::Map& nanoMap = reinterpret_cast<const GridData*>(srcGrid)->mMap;
123  auto mat = openvdb::math::Mat4<double>::identity();
124  mat.setMat3(openvdb::math::Mat3<double>(nanoMap.mMatD));
125  mat.transpose(); // the 3x3 in nanovdb is transposed relative to openvdb's 3x3
126  mat.setTranslation(openvdb::math::Vec3<double>(nanoMap.mVecD));
127  dstGrid->setTransform(openvdb::math::Transform::createLinearTransform(mat)); // calls simplify!
128 
129  // process root node
130  auto &root = dstGrid->tree().root();
131  auto *data = srcGrid->tree().root().data();
132  for (uint32_t i=0; i<data->mTableSize; ++i) {
133  auto *tile = data->tile(i);
134  if (tile->isChild()) {
135 #if OPENVDB_ABI_VERSION_NUMBER >= 7
136  root.addChild( this->process( data->getChild(tile)) );
137 #else// hack since RootNode::addChild is not available in older versions
138  root.addTile(tile->origin(), root.background(), false);//dummy tile
139  auto it = root.beginChildAll();
140  while(it.getCoord() != tile->origin()) ++it;// find tile
141  it.setChild(this->process( data->getChild(tile)) );//replace tile with child
142 #endif
143  } else {
144  root.addTile(tile->origin(), tile->value, tile->state);
145  }
146  }
147 
148  return dstGrid;
149 }
150 
151 template<typename T>
152 template<typename SrcNodeT, typename DstNodeT>
153 DstNodeT*
154 NanoToOpenVDB<T>::processNode(const SrcNodeT *srcNode)
155 {
156  DstNodeT *dstNode = new DstNodeT(); // un-initialized for fast construction
157  dstNode->setOrigin(srcNode->origin());
158  const auto& childMask = srcNode->childMask();
159  const_cast<typename DstNodeT::NodeMaskType&>(dstNode->getValueMask()) = srcNode->valueMask();
160  const_cast<typename DstNodeT::NodeMaskType&>(dstNode->getChildMask()) = childMask;
161  auto* dstTable = const_cast<typename DstNodeT::UnionType*>(dstNode->getTable());
162  auto* srcData = srcNode->data();
163  std::vector<std::pair<uint32_t, const typename SrcNodeT::ChildNodeType*>> childNodes;
164  const auto childCount = childMask.countOn();
165  childNodes.reserve(childCount);
166  for (uint32_t n = 0; n < DstNodeT::NUM_VALUES; ++n) {
167  if (childMask.isOn(n)) {
168  childNodes.emplace_back(n, srcData->getChild(n));
169  } else {
170  dstTable[n].setValue(srcData->mTable[n].value);
171  }
172  }
173  auto kernel = [&](const auto& r) {
174  for (auto i = r.begin(); i != r.end(); ++i) {
175  auto &p = childNodes[i];
176  dstTable[p.first].setChild( this->process(p.second) );
177  }
178  };
179 
180 #if 0
181  kernel(Range1D(0, childCount));
182 #else
183  forEach(0, childCount, 1, kernel);
184 #endif
185  return dstNode;
186 } // processNode
187 
188 template<typename T>
189 typename NanoToOpenVDB<T>::DstNode0*
190 NanoToOpenVDB<T>::process(const SrcNode0 *srcNode)
191 {
192  DstNode0* dstNode = new DstNode0(); // un-initialized for fast construction
193  dstNode->setOrigin(srcNode->origin());
194  dstNode->setValueMask(srcNode->valueMask());
195 
196  const ValueT* src = srcNode->data()->mValues;// doesn't work for compressed data, bool or ValueMask
197  for (ValueT *dst = dstNode->buffer().data(), *end = dst + DstNode0::SIZE; dst != end; dst += 4, src += 4) {
198  dst[0] = src[0];
199  dst[1] = src[1];
200  dst[2] = src[2];
201  dst[3] = src[3];
202  }
203 
204  return dstNode;
205 } // process(SrcNode0)
206 
207 template<typename ValueT>
209 nanoToOpenVDB(const NanoGrid<ValueT>& grid, int verbose)
210 {
212  return tmp(grid, verbose);
213 }
214 
215 template<typename BufferT>
217 nanoToOpenVDB(const GridHandle<BufferT>& handle, int verbose)
218 {
219  if (auto grid = handle.template grid<float>()) {
220  return nanovdb::nanoToOpenVDB(*grid, verbose);
221  } else if (auto grid = handle.template grid<double>()) {
222  return nanovdb::nanoToOpenVDB(*grid, verbose);
223  } else if (auto grid = handle.template grid<int32_t>()) {
224  return nanovdb::nanoToOpenVDB(*grid, verbose);
225  } else if (auto grid = handle.template grid<int64_t>()) {
226  return nanovdb::nanoToOpenVDB(*grid, verbose);
227  } else if (auto grid = handle.template grid<nanovdb::Vec3f>()) {
228  return nanovdb::nanoToOpenVDB(*grid, verbose);
229  } else if (auto grid = handle.template grid<nanovdb::Vec3d>()) {
230  return nanovdb::nanoToOpenVDB(*grid, verbose);
231  } else if (auto grid = handle.template grid<nanovdb::Vec4f>()) {
232  return nanovdb::nanoToOpenVDB(*grid, verbose);
233  } else if (auto grid = handle.template grid<nanovdb::Vec4d>()) {
234  return nanovdb::nanoToOpenVDB(*grid, verbose);
235  } else {
236  OPENVDB_THROW(openvdb::RuntimeError, "Unsupported NanoVDB grid type");
237  }
238 }
239 
240 } // namespace nanovdb
241 
242 #endif // NANOVDB_NANOTOOPENVDB_H_HAS_BEEN_INCLUDED
VDB Tree, which is a thin wrapper around a RootNode.
Definition: NanoVDB.h:2542
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition: NanoVDB.h:2307
SharedPtr< Grid > Ptr
Definition: Grid.h:579
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
double mVecD[3]
Definition: NanoVDB.h:2005
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 ...
SharedPtr< GridBase > Ptr
Definition: Grid.h:80
A simple vector class with three double components, similar to openvdb::math::Vec4.
Definition: NanoVDB.h:1188
const TreeT & tree() const
Return a const reference to the tree.
Definition: NanoVDB.h:2344
void forEach(RangeT range, const FuncT &func)
simple wrapper for tbb::parallel_for with a naive std fallback
Definition: ForEach.h:40
Definition: NanoToOpenVDB.h:28
This class serves to manage a raw memory buffer of a NanoVDB Grid.
Definition: GridHandle.h:70
Implements a light-weight self-contained VDB data-structure in a single file! In other words...
Definition: NanoVDB.h:184
Top-most node of the VDB tree structure.
Definition: NanoVDB.h:2798
DataType * data()
Definition: NanoVDB.h:3709
double mMatD[9]
Definition: NanoVDB.h:2003
ValueType mValues[1u<< 3 *LOG2DIM]
Definition: NanoVDB.h:3373
DstGridT::Ptr operator()(const NanoGrid< ValueType > &grid, int verbose=0)
Return a shared pointer to a NanoVDB grid constructed from the specified OpenVDB grid.
Definition: NanoToOpenVDB.h:96
NanoToOpenVDB()
Construction from an existing const OpenVDB Grid.
Definition: NanoToOpenVDB.h:61
openvdb::math::Vec3< T > Type
Definition: NanoToOpenVDB.h:85
openvdb::math::Vec4< T > Type
Definition: NanoToOpenVDB.h:91
Definition: Exceptions.h:63
This class will serialize an OpenVDB grid into a NanoVDB grid managed by a GridHandle.
Definition: NanoToOpenVDB.h:42
Range< 1, size_t > Range1D
Definition: Range.h:30
Definition: Types.h:417
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:28
const char * gridName() const
Return a c-string with the name of this grid.
Definition: NanoVDB.h:2445
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation...
Definition: NanoVDB.h:1997
const GridClass & gridClass() const
Definition: NanoVDB.h:2419
const MaskType< LOG2DIM > & valueMask() const
Return a const reference to the bit mask of active voxels in this leaf node.
Definition: NanoVDB.h:3714
Internal nodes of a VDB treedim(),.
Definition: NanoVDB.h:3120
T Type
Definition: NanoToOpenVDB.h:79
Definition: Types.h:416
Struct with all the member data of the Grid (useful during serialization of an openvdb grid) ...
Definition: NanoVDB.h:2184
Definition: Types.h:415
Definition: Types.h:418
CoordT origin() const
Return the origin in index space of this leaf node.
Definition: NanoVDB.h:3734
Leaf nodes of the VDB tree. (defaults to 8x8x8 = 512 voxels)
Definition: NanoVDB.h:3683
openvdb::Grid< typename openvdb::tree::Tree4< typename ConvertTrait< ValueT >::Type >::Type >::Ptr nanoToOpenVDB(const NanoGrid< ValueT > &grid, int verbose=0)
Forward declaration of free-standing function that de-serializes a typed NanoVDB grid into an OpenVDB...
Definition: NanoToOpenVDB.h:209