Blender V4.3
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/util/OpenToNanoVDB.h>
16#endif
17
19
20#ifdef WITH_OPENVDB
21struct NumChannelsOp {
22 int num_channels = 0;
23
24 template<typename GridType, typename FloatGridType, typename FloatDataType, int channels>
25 bool operator()(const openvdb::GridBase::ConstPtr &)
26 {
27 num_channels = channels;
28 return true;
29 }
30};
31
32struct ToDenseOp {
33 openvdb::CoordBBox bbox;
34 void *pixels;
35
36 template<typename GridType, typename FloatGridType, typename FloatDataType, int channels>
37 bool operator()(const openvdb::GridBase::ConstPtr &grid)
38 {
39 openvdb::tools::Dense<FloatDataType, openvdb::tools::LayoutXYZ> dense(bbox,
40 (FloatDataType *)pixels);
41 openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<GridType>(grid), dense);
42 return true;
43 }
44};
45
46# ifdef WITH_NANOVDB
47struct ToNanoOp {
48 nanovdb::GridHandle<> nanogrid;
49 int precision;
50
51 template<typename GridType, typename FloatGridType, typename FloatDataType, int channels>
52 bool operator()(const openvdb::GridBase::ConstPtr &grid)
53 {
54 if constexpr (!std::is_same_v<GridType, openvdb::MaskGrid>) {
55 try {
56# if NANOVDB_MAJOR_VERSION_NUMBER > 32 || \
57 (NANOVDB_MAJOR_VERSION_NUMBER == 32 && NANOVDB_MINOR_VERSION_NUMBER >= 6)
58# if NANOVDB_MAJOR_VERSION_NUMBER > 32 || \
59 (NANOVDB_MAJOR_VERSION_NUMBER == 32 && NANOVDB_MINOR_VERSION_NUMBER >= 7)
60 /* OpenVDB 12. */
61 using nanovdb::tools::createNanoGrid;
62 using nanovdb::tools::StatsMode;
63# else
64 /* OpenVDB 11. */
65 using nanovdb::createNanoGrid;
66 using nanovdb::StatsMode;
67# endif
68
69 if constexpr (std::is_same_v<FloatGridType, openvdb::FloatGrid>) {
70 openvdb::FloatGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
71 if (precision == 0) {
72 nanogrid = createNanoGrid<openvdb::FloatGrid, nanovdb::FpN>(floatgrid);
73 }
74 else if (precision == 16) {
75 nanogrid = createNanoGrid<openvdb::FloatGrid, nanovdb::Fp16>(floatgrid);
76 }
77 else {
78 nanogrid = createNanoGrid<openvdb::FloatGrid, float>(floatgrid);
79 }
80 }
81 else if constexpr (std::is_same_v<FloatGridType, openvdb::Vec3fGrid>) {
82 openvdb::Vec3fGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
83 nanogrid = createNanoGrid<openvdb::Vec3fGrid, nanovdb::Vec3f>(floatgrid,
84 StatsMode::Disable);
85 }
86# else
87 /* OpenVDB 10. */
88 if constexpr (std::is_same_v<FloatGridType, openvdb::FloatGrid>) {
89 openvdb::FloatGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
90 if (precision == 0) {
91 nanogrid =
92 nanovdb::openToNanoVDB<nanovdb::HostBuffer, openvdb::FloatTree, nanovdb::FpN>(
93 floatgrid);
94 }
95 else if (precision == 16) {
96 nanogrid =
97 nanovdb::openToNanoVDB<nanovdb::HostBuffer, openvdb::FloatTree, nanovdb::Fp16>(
98 floatgrid);
99 }
100 else {
101 nanogrid = nanovdb::openToNanoVDB(floatgrid);
102 }
103 }
104 else if constexpr (std::is_same_v<FloatGridType, openvdb::Vec3fGrid>) {
105 openvdb::Vec3fGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
106 nanogrid = nanovdb::openToNanoVDB(floatgrid);
107 }
108# endif
109 }
110 catch (const std::exception &e) {
111 VLOG_WARNING << "Error converting OpenVDB to NanoVDB grid: " << e.what();
112 }
113 catch (...) {
114 VLOG_WARNING << "Error converting OpenVDB to NanoVDB grid: Unknown error";
115 }
116 return true;
117 }
118 else {
119 return false;
120 }
121 }
122};
123# endif
124
125VDBImageLoader::VDBImageLoader(openvdb::GridBase::ConstPtr grid_, const string &grid_name)
126 : grid_name(grid_name), grid(grid_)
127{
128}
129#endif
130
132
134
136{
137#ifdef WITH_OPENVDB
138 if (!grid) {
139 return false;
140 }
141
142 /* Get number of channels from type. */
143 NumChannelsOp op;
144 if (!openvdb::grid_type_operation(grid, op)) {
145 return false;
146 }
147
148 metadata.channels = op.num_channels;
149
150 /* Set data type. */
151# ifdef WITH_NANOVDB
152 if (features.has_nanovdb) {
153 /* NanoVDB expects no inactive leaf nodes. */
154# if 0
155 openvdb::FloatGrid &pruned_grid = *openvdb::gridPtrCast<openvdb::FloatGrid>(grid);
156 openvdb::tools::pruneInactive(pruned_grid.tree());
157 nanogrid = nanovdb::openToNanoVDB(pruned_grid);
158# endif
159 ToNanoOp op;
160 op.precision = precision;
161 if (!openvdb::grid_type_operation(grid, op)) {
162 return false;
163 }
164 nanogrid = std::move(op.nanogrid);
165 }
166# endif
167
168 /* Set dimensions. */
169 bbox = grid->evalActiveVoxelBoundingBox();
170 if (bbox.empty()) {
171 return false;
172 }
173
174 openvdb::Coord dim = bbox.dim();
175 metadata.width = dim.x();
176 metadata.height = dim.y();
177 metadata.depth = dim.z();
178
179# ifdef WITH_NANOVDB
180 if (nanogrid) {
181 metadata.byte_size = nanogrid.size();
182 if (metadata.channels == 1) {
183 if (precision == 0) {
185 }
186 else if (precision == 16) {
188 }
189 else {
191 }
192 }
193 else {
195 }
196 }
197 else
198# endif
199 {
200 if (metadata.channels == 1) {
201 metadata.type = IMAGE_DATA_TYPE_FLOAT;
202 }
203 else {
204 metadata.type = IMAGE_DATA_TYPE_FLOAT4;
205 }
206 }
207
208 /* Set transform from object space to voxel index. */
209 openvdb::math::Mat4f grid_matrix = grid->transform().baseMap()->getAffineMap()->getMat4();
210 Transform index_to_object;
211 for (int col = 0; col < 4; col++) {
212 for (int row = 0; row < 3; row++) {
213 index_to_object[row][col] = (float)grid_matrix[col][row];
214 }
215 }
216
217 Transform texture_to_index;
218# ifdef WITH_NANOVDB
219 if (nanogrid) {
220 texture_to_index = transform_identity();
221 }
222 else
223# endif
224 {
225 openvdb::Coord min = bbox.min();
226 texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
227 transform_scale(dim.x(), dim.y(), dim.z());
228 }
229
230 metadata.transform_3d = transform_inverse(index_to_object * texture_to_index);
231 metadata.use_transform_3d = true;
232
233# ifndef WITH_NANOVDB
234 (void)features;
235# endif
236 return true;
237#else
238 (void)metadata;
239 (void)features;
240 return false;
241#endif
242}
243
244bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool)
245{
246#ifdef WITH_OPENVDB
247# ifdef WITH_NANOVDB
248 if (nanogrid) {
249 memcpy(pixels, nanogrid.data(), nanogrid.size());
250 }
251 else
252# endif
253 {
254 ToDenseOp op;
255 op.pixels = pixels;
256 op.bbox = bbox;
257 openvdb::grid_type_operation(grid, op);
258 }
259 return true;
260#else
261 (void)pixels;
262 return false;
263#endif
264}
265
267{
268 return grid_name;
269}
270
271bool VDBImageLoader::equals(const ImageLoader &other) const
272{
273#ifdef WITH_OPENVDB
274 const VDBImageLoader &other_loader = (const VDBImageLoader &)other;
275 return grid == other_loader.grid;
276#else
277 (void)other;
278 return true;
279#endif
280}
281
283{
284#ifdef WITH_OPENVDB
285 /* Free OpenVDB grid memory as soon as we can. */
286 grid.reset();
287#endif
288#ifdef WITH_NANOVDB
289 nanogrid.reset();
290#endif
291}
292
294{
295 return true;
296}
297
298#ifdef WITH_OPENVDB
299openvdb::GridBase::ConstPtr VDBImageLoader::get_grid()
300{
301 return grid;
302}
303#endif
304
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a producing a negative Combine Generate a color from its and blue channels(Deprecated)") DefNode(ShaderNode
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)
virtual bool equals(const ImageLoader &other) const override
string grid_name
Definition image_vdb.h:54
virtual bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override
virtual void cleanup() override
virtual bool is_vdb_loader() const override
virtual string name() const override
virtual bool load_pixels(const ImageMetaData &metadata, void *pixels, const size_t pixels_size, const bool associate_alpha) override
#define CCL_NAMESPACE_END
draw_view in_light_buf[] float
uint col
#define VLOG_WARNING
Definition log.h:70
#define min(a, b)
Definition sort.c:32
ccl_device_inline Transform transform_identity()
Definition transform.h:296
ccl_device_inline Transform transform_translate(float3 t)
Definition transform.h:244
ccl_device_inline Transform transform_inverse(const Transform tfm)
Definition transform.h:423
ccl_device_inline Transform transform_scale(float3 s)
Definition transform.h:254
@ 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