OpenVDB: nanovdb/util/NanoToOpenVDB.h Source File

OpenVDB 9.0.0

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
25namespace nanovdb {
26
27template<typename T>
28struct ConvertTrait;
29
30/// @brief Forward declaration of free-standing function that de-serializes a typed NanoVDB grid into an OpenVDB Grid
31template<typename ValueT>
32typename openvdb::Grid<typename openvdb::tree::Tree4<typename ConvertTrait<ValueT>::Type>::Type>::Ptr
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
36template<typename BufferT>
37 openvdb::GridBase::Ptr
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.
41template<typename ValueType>
42 class NanoToOpenVDB
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!
46 using SrcNode1 = InternalNode<SrcNode0>;
47 using SrcNode2 = InternalNode<SrcNode1>;
48 using SrcRootT = RootNode<SrcNode2>;
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>;
57 using DstGridT = openvdb::Grid<DstTreeT>;
58
59public:
60 /// @brief Construction from an existing const OpenVDB Grid.
61 NanoToOpenVDB(){};
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
66private:
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
76template<typename T>
77 struct ConvertTrait
78{
79 using Type = T;
80};
81
82template<typename T>
83 struct ConvertTrait< Vec3<T> >
84{
85 using Type = openvdb::math::Vec3<T>;
86};
87
88template<typename T>
89 struct ConvertTrait< Vec4<T> >
90{
91 using Type = openvdb::math::Vec4<T>;
92};
93
94template<typename T>
95typename NanoToOpenVDB<T>::DstGridT::Ptr
96NanoToOpenVDB<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
103 case nanovdb::GridClass::LevelSet:
104 dstGrid->setGridClass(openvdb::GRID_LEVEL_SET);
105 break;
106 case nanovdb::GridClass::FogVolume:
107 dstGrid->setGridClass(openvdb::GRID_FOG_VOLUME);
108 break;
109 case nanovdb::GridClass::Staggered:
110 dstGrid->setGridClass(openvdb::GRID_STAGGERED);
111 break;
112 case nanovdb::GridClass::PointIndex:
113 throw std::runtime_error("NanoToOpenVDB does not yet support PointIndexGrids");
114 case nanovdb::GridClass::PointData:
115 throw std::runtime_error("NanoToOpenVDB does not yet support PointDataGrids");
116 case nanovdb::GridClass::Topology:
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
151template<typename T>
152template<typename SrcNodeT, typename DstNodeT>
153DstNodeT*
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
188template<typename T>
189typename NanoToOpenVDB<T>::DstNode0*
190NanoToOpenVDB<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
207template<typename ValueT>
208typename openvdb::Grid<typename openvdb::tree::Tree4<typename ConvertTrait<ValueT>::Type>::Type>::Ptr
209nanoToOpenVDB(const NanoGrid<ValueT>& grid, int verbose)
210{
211 nanovdb::NanoToOpenVDB<ValueT> tmp;
212 return tmp(grid, verbose);
213}
214
215template<typename BufferT>
216 openvdb::GridBase::Ptr
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
ForEach.h
A unified wrapper for tbb::parallel_for and a naive std::thread fallback.
GridHandle.h
Defines two classes, a GridRegister the defines the value type (e.g. Double, Float etc) of a NanoVDB ...
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 raw memory buffer of a NanoVDB Grid.
Definition: GridHandle.h:71
nanovdb::Grid
Highest level of the data structure. Contains a tree and a world->index transform (that currently onl...
Definition: NanoVDB.h:2308
nanovdb::Grid::gridClass
const GridClass & gridClass() const
Definition: NanoVDB.h:2419
nanovdb::Grid::gridName
const char * gridName() const
Return a c-string with the name of this grid.
Definition: NanoVDB.h:2445
nanovdb::Grid::tree
const TreeT & tree() const
Return a const reference to the tree.
Definition: NanoVDB.h:2344
nanovdb::InternalNode
Internal nodes of a VDB treedim(),.
Definition: NanoVDB.h:3121
nanovdb::LeafNode
Leaf nodes of the VDB tree. (defaults to 8x8x8 = 512 voxels)
Definition: NanoVDB.h:3684
nanovdb::NanoToOpenVDB
This class will serialize an OpenVDB grid into a NanoVDB grid managed by a GridHandle.
Definition: NanoToOpenVDB.h:43
nanovdb::NanoToOpenVDB::NanoToOpenVDB
NanoToOpenVDB()
Construction from an existing const OpenVDB Grid.
Definition: NanoToOpenVDB.h:61
nanovdb::NanoToOpenVDB::operator()
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
nanovdb::RootNode
Top-most node of the VDB tree structure.
Definition: NanoVDB.h:2799
nanovdb::Tree
VDB Tree, which is a thin wrapper around a RootNode.
Definition: NanoVDB.h:2543
nanovdb::Vec4
A simple vector class with three double components, similar to openvdb::math::Vec4.
Definition: NanoVDB.h:1189
openvdb::v9_0::GridBase::Ptr
SharedPtr< GridBase > Ptr
Definition: Grid.h:80
openvdb::v9_0::Grid
Container class that associates a tree with a transform and metadata.
Definition: Grid.h:577
openvdb::v9_0::Grid::Ptr
SharedPtr< Grid > Ptr
Definition: Grid.h:579
openvdb::v9_0::RuntimeError
Definition: Exceptions.h:63
nanovdb
Definition: Camera.h:16
nanovdb::GridClass::FogVolume
@ FogVolume
nanovdb::GridClass::Topology
@ Topology
nanovdb::GridClass::PointIndex
@ PointIndex
nanovdb::GridClass::PointData
@ PointData
nanovdb::GridClass::Staggered
@ Staggered
nanovdb::GridClass::LevelSet
@ LevelSet
nanovdb::nanoToOpenVDB
openvdb::Grid< typenameopenvdb::tree::Tree4< typenameConvertTrait< 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
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::v9_0::GRID_FOG_VOLUME
@ GRID_FOG_VOLUME
Definition: Types.h:338
openvdb::v9_0::GRID_STAGGERED
@ GRID_STAGGERED
Definition: Types.h:339
openvdb::v9_0::GRID_LEVEL_SET
@ GRID_LEVEL_SET
Definition: Types.h:337
openvdb::v9_0::GRID_UNKNOWN
@ GRID_UNKNOWN
Definition: Types.h:336
OPENVDB_THROW
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:74
openvdb.h
nanovdb::ConvertTrait< Vec3< T > >::Type
openvdb::math::Vec3< T > Type
Definition: NanoToOpenVDB.h:85
nanovdb::ConvertTrait< Vec4< T > >::Type
openvdb::math::Vec4< T > Type
Definition: NanoToOpenVDB.h:91
nanovdb::ConvertTrait
Definition: NanoToOpenVDB.h:78
nanovdb::ConvertTrait::Type
T Type
Definition: NanoToOpenVDB.h:79
nanovdb::GridData
Struct with all the member data of the Grid (useful during serialization of an openvdb grid)
Definition: NanoVDB.h:2185
nanovdb::Map
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition: NanoVDB.h:1998
nanovdb::Map::mVecD
double mVecD[3]
Definition: NanoVDB.h:2005
nanovdb::Map::mMatD
double mMatD[9]
Definition: NanoVDB.h:2003