Blender V4.5
image_vdb.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "scene/image_vdb.h"
6
7#include "util/log.h"
8#include "util/openvdb.h"
9
10#ifdef WITH_OPENVDB
11# include <openvdb/tools/Dense.h>
12#endif
13#ifdef WITH_NANOVDB
14# define NANOVDB_USE_OPENVDB
15# include <nanovdb/NanoVDB.h>
16# if NANOVDB_MAJOR_VERSION_NUMBER > 32 || \
17 (NANOVDB_MAJOR_VERSION_NUMBER == 32 && NANOVDB_MINOR_VERSION_NUMBER >= 7)
18# include <nanovdb/tools/CreateNanoGrid.h>
19# else
20# include <nanovdb/util/OpenToNanoVDB.h>
21# endif
22#endif
23
25
26#ifdef WITH_OPENVDB
27struct NumChannelsOp {
28 int num_channels = 0;
29
30 template<typename GridType, typename FloatGridType, typename FloatDataType, const int channels>
31 bool operator()(const openvdb::GridBase::ConstPtr & /*unused*/)
32 {
33 num_channels = channels;
34 return true;
35 }
36};
37
38struct ToDenseOp {
39 openvdb::CoordBBox bbox;
40 void *pixels;
41
42 template<typename GridType, typename FloatGridType, typename FloatDataType, const int channels>
43 bool operator()(const openvdb::GridBase::ConstPtr &grid)
44 {
45 openvdb::tools::Dense<FloatDataType, openvdb::tools::LayoutXYZ> dense(bbox,
46 (FloatDataType *)pixels);
47 openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<GridType>(grid), dense);
48 return true;
49 }
50};
51
52# ifdef WITH_NANOVDB
53struct ToNanoOp {
54 nanovdb::GridHandle<> nanogrid;
55 int precision;
56
57 template<typename GridType, typename FloatGridType, typename FloatDataType, const int channels>
58 bool operator()(const openvdb::GridBase::ConstPtr &grid)
59 {
60 if constexpr (!std::is_same_v<GridType, openvdb::MaskGrid>) {
61 try {
62# if NANOVDB_MAJOR_VERSION_NUMBER > 32 || \
63 (NANOVDB_MAJOR_VERSION_NUMBER == 32 && NANOVDB_MINOR_VERSION_NUMBER >= 6)
64# if NANOVDB_MAJOR_VERSION_NUMBER > 32 || \
65 (NANOVDB_MAJOR_VERSION_NUMBER == 32 && NANOVDB_MINOR_VERSION_NUMBER >= 7)
66 /* OpenVDB 12. */
67 using nanovdb::tools::createNanoGrid;
68 using nanovdb::tools::StatsMode;
69# else
70 /* OpenVDB 11. */
71 using nanovdb::createNanoGrid;
72 using nanovdb::StatsMode;
73# endif
74
75 if constexpr (std::is_same_v<FloatGridType, openvdb::FloatGrid>) {
76 const openvdb::FloatGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
77 if (precision == 0) {
78 nanogrid = createNanoGrid<openvdb::FloatGrid, nanovdb::FpN>(floatgrid);
79 }
80 else if (precision == 16) {
81 nanogrid = createNanoGrid<openvdb::FloatGrid, nanovdb::Fp16>(floatgrid);
82 }
83 else {
84 nanogrid = createNanoGrid<openvdb::FloatGrid, float>(floatgrid);
85 }
86 }
87 else if constexpr (std::is_same_v<FloatGridType, openvdb::Vec3fGrid>) {
88 const openvdb::Vec3fGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
89 nanogrid = createNanoGrid<openvdb::Vec3fGrid, nanovdb::Vec3f>(floatgrid,
90 StatsMode::Disable);
91 }
92# else
93 /* OpenVDB 10. */
94 if constexpr (std::is_same_v<FloatGridType, openvdb::FloatGrid>) {
95 openvdb::FloatGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
96 if (precision == 0) {
97 nanogrid =
98 nanovdb::openToNanoVDB<nanovdb::HostBuffer, openvdb::FloatTree, nanovdb::FpN>(
99 floatgrid);
100 }
101 else if (precision == 16) {
102 nanogrid =
103 nanovdb::openToNanoVDB<nanovdb::HostBuffer, openvdb::FloatTree, nanovdb::Fp16>(
104 floatgrid);
105 }
106 else {
107 nanogrid = nanovdb::openToNanoVDB(floatgrid);
108 }
109 }
110 else if constexpr (std::is_same_v<FloatGridType, openvdb::Vec3fGrid>) {
111 openvdb::Vec3fGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
112 nanogrid = nanovdb::openToNanoVDB(floatgrid);
113 }
114# endif
115 }
116 catch (const std::exception &e) {
117 VLOG_WARNING << "Error converting OpenVDB to NanoVDB grid: " << e.what();
118 }
119 catch (...) {
120 VLOG_WARNING << "Error converting OpenVDB to NanoVDB grid: Unknown error";
121 }
122 return true;
123 }
124 else {
125 return false;
126 }
127 }
128};
129# endif
130
131VDBImageLoader::VDBImageLoader(openvdb::GridBase::ConstPtr grid_, const string &grid_name)
132 : grid_name(grid_name), grid(grid_)
133{
134}
135#endif
136
138
140
142{
143#ifdef WITH_OPENVDB
144 if (!grid) {
145 return false;
146 }
147
148 /* Get number of channels from type. */
149 NumChannelsOp op;
150 if (!openvdb::grid_type_operation(grid, op)) {
151 return false;
152 }
153
154 metadata.channels = op.num_channels;
155
156 /* Set data type. */
157# ifdef WITH_NANOVDB
158 if (features.has_nanovdb) {
159 /* NanoVDB expects no inactive leaf nodes. */
160# if 0
161 openvdb::FloatGrid &pruned_grid = *openvdb::gridPtrCast<openvdb::FloatGrid>(grid);
162 openvdb::tools::pruneInactive(pruned_grid.tree());
163 nanogrid = nanovdb::openToNanoVDB(pruned_grid);
164# endif
165 ToNanoOp op;
166 op.precision = precision;
167 if (!openvdb::grid_type_operation(grid, op)) {
168 return false;
169 }
170 nanogrid = std::move(op.nanogrid);
171 }
172# endif
173
174 /* Set dimensions. */
175 bbox = grid->evalActiveVoxelBoundingBox();
176 if (bbox.empty()) {
177 return false;
178 }
179
180 openvdb::Coord dim = bbox.dim();
181 metadata.width = dim.x();
182 metadata.height = dim.y();
183 metadata.depth = dim.z();
184
185# ifdef WITH_NANOVDB
186 if (nanogrid) {
187 metadata.byte_size = nanogrid.size();
188 if (metadata.channels == 1) {
189 if (precision == 0) {
191 }
192 else if (precision == 16) {
194 }
195 else {
197 }
198 }
199 else {
201 }
202 }
203 else
204# endif
205 {
206 if (metadata.channels == 1) {
207 metadata.type = IMAGE_DATA_TYPE_FLOAT;
208 }
209 else {
210 metadata.type = IMAGE_DATA_TYPE_FLOAT4;
211 }
212 }
213
214 /* Set transform from object space to voxel index. */
215 openvdb::math::Mat4f grid_matrix = grid->transform().baseMap()->getAffineMap()->getMat4();
216 Transform index_to_object;
217 for (int col = 0; col < 4; col++) {
218 for (int row = 0; row < 3; row++) {
219 index_to_object[row][col] = (float)grid_matrix[col][row];
220 }
221 }
222
223 Transform texture_to_index;
224# ifdef WITH_NANOVDB
225 if (nanogrid) {
226 texture_to_index = transform_identity();
227 }
228 else
229# endif
230 {
231 openvdb::Coord min = bbox.min();
232 texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
233 transform_scale(dim.x(), dim.y(), dim.z());
234 }
235
236 metadata.transform_3d = transform_inverse(index_to_object * texture_to_index);
237 metadata.use_transform_3d = true;
238
239# ifndef WITH_NANOVDB
240 (void)features;
241# endif
242 return true;
243#else
244 (void)metadata;
245 (void)features;
246 return false;
247#endif
248}
249
251 void *pixels,
252 const size_t /*pixels_size*/,
253 const bool /*associate_alpha*/)
254{
255#ifdef WITH_OPENVDB
256# ifdef WITH_NANOVDB
257 if (nanogrid) {
258 memcpy(pixels, nanogrid.data(), nanogrid.size());
259 }
260 else
261# endif
262 {
263 ToDenseOp op;
264 op.pixels = pixels;
265 op.bbox = bbox;
266 openvdb::grid_type_operation(grid, op);
267 }
268 return true;
269#else
270 (void)pixels;
271 return false;
272#endif
273}
274
276{
277 return grid_name;
278}
279
280bool VDBImageLoader::equals(const ImageLoader &other) const
281{
282#ifdef WITH_OPENVDB
283 const VDBImageLoader &other_loader = (const VDBImageLoader &)other;
284 return grid == other_loader.grid;
285#else
286 (void)other;
287 return true;
288#endif
289}
290
292{
293#ifdef WITH_OPENVDB
294 /* Free OpenVDB grid memory as soon as we can. */
295 grid.reset();
296#endif
297#ifdef WITH_NANOVDB
298 nanogrid.reset();
299#endif
300}
301
303{
304 return true;
305}
306
307#ifdef WITH_OPENVDB
308openvdb::GridBase::ConstPtr VDBImageLoader::get_grid()
309{
310 return grid;
311}
312#endif
313
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE btVector3 operator()(const btVector3 &x) const
Return the transform of the vector.
Definition btTransform.h:90
ImageDataType type
VDBImageLoader(const string &grid_name)
bool equals(const ImageLoader &other) const override
string grid_name
Definition image_vdb.h:52
~VDBImageLoader() override
bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override
void cleanup() override
bool is_vdb_loader() const override
string name() const override
bool load_pixels(const ImageMetaData &metadata, void *pixels, const size_t pixels_size, const bool associate_alpha) override
#define CCL_NAMESPACE_END
uint col
#define VLOG_WARNING
Definition log.h:69
#define min(a, b)
Definition sort.cc:36
ccl_device_inline Transform transform_identity()
Definition transform.h:289
ccl_device_inline Transform transform_scale(const float3 s)
Definition transform.h:247
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:492
ccl_device_inline Transform transform_translate(const float3 t)
Definition transform.h:237
@ IMAGE_DATA_TYPE_FLOAT
@ IMAGE_DATA_TYPE_NANOVDB_FP16
@ IMAGE_DATA_TYPE_FLOAT4
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT3
@ IMAGE_DATA_TYPE_NANOVDB_FPN