Blender  V2.93
image_vdb.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2020 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "render/image_vdb.h"
18 
19 #ifdef WITH_OPENVDB
20 # include <openvdb/openvdb.h>
21 # include <openvdb/tools/Dense.h>
22 #endif
23 #ifdef WITH_NANOVDB
24 # include <nanovdb/util/OpenToNanoVDB.h>
25 #endif
26 
28 
29 VDBImageLoader::VDBImageLoader(const string &grid_name) : grid_name(grid_name)
30 {
31 }
32 
34 {
35 }
36 
38 {
39 #ifdef WITH_OPENVDB
40  if (!grid) {
41  return false;
42  }
43 
44  bbox = grid->evalActiveVoxelBoundingBox();
45  if (bbox.empty()) {
46  return false;
47  }
48 
49  /* Set dimensions. */
50  openvdb::Coord dim = bbox.dim();
51  metadata.width = dim.x();
52  metadata.height = dim.y();
53  metadata.depth = dim.z();
54 
55  /* Set data type. */
56  if (grid->isType<openvdb::FloatGrid>()) {
57  metadata.channels = 1;
58 # ifdef WITH_NANOVDB
59  if (features.has_nanovdb) {
60  nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid));
61  }
62 # endif
63  }
64  else if (grid->isType<openvdb::Vec3fGrid>()) {
65  metadata.channels = 3;
66 # ifdef WITH_NANOVDB
67  if (features.has_nanovdb) {
68  nanogrid = nanovdb::openToNanoVDB(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid));
69  }
70 # endif
71  }
72  else if (grid->isType<openvdb::BoolGrid>()) {
73  metadata.channels = 1;
74 # ifdef WITH_NANOVDB
75  if (features.has_nanovdb) {
76  nanogrid = nanovdb::openToNanoVDB(
77  openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid)));
78  }
79 # endif
80  }
81  else if (grid->isType<openvdb::DoubleGrid>()) {
82  metadata.channels = 1;
83 # ifdef WITH_NANOVDB
84  if (features.has_nanovdb) {
85  nanogrid = nanovdb::openToNanoVDB(
86  openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid)));
87  }
88 # endif
89  }
90  else if (grid->isType<openvdb::Int32Grid>()) {
91  metadata.channels = 1;
92 # ifdef WITH_NANOVDB
93  if (features.has_nanovdb) {
94  nanogrid = nanovdb::openToNanoVDB(
95  openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid)));
96  }
97 # endif
98  }
99  else if (grid->isType<openvdb::Int64Grid>()) {
100  metadata.channels = 1;
101 # ifdef WITH_NANOVDB
102  if (features.has_nanovdb) {
103  nanogrid = nanovdb::openToNanoVDB(
104  openvdb::FloatGrid(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid)));
105  }
106 # endif
107  }
108  else if (grid->isType<openvdb::Vec3IGrid>()) {
109  metadata.channels = 3;
110 # ifdef WITH_NANOVDB
111  if (features.has_nanovdb) {
112  nanogrid = nanovdb::openToNanoVDB(
113  openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid)));
114  }
115 # endif
116  }
117  else if (grid->isType<openvdb::Vec3dGrid>()) {
118  metadata.channels = 3;
119 # ifdef WITH_NANOVDB
120  if (features.has_nanovdb) {
121  nanogrid = nanovdb::openToNanoVDB(
122  openvdb::Vec3fGrid(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid)));
123  }
124 # endif
125  }
126  else if (grid->isType<openvdb::MaskGrid>()) {
127  metadata.channels = 1;
128 # ifdef WITH_NANOVDB
129  return false; // Unsupported
130 # endif
131  }
132  else {
133  return false;
134  }
135 
136 # ifdef WITH_NANOVDB
137  if (nanogrid) {
138  metadata.byte_size = nanogrid.size();
139  if (metadata.channels == 1) {
141  }
142  else {
144  }
145  }
146  else
147 # endif
148  {
149  if (metadata.channels == 1) {
150  metadata.type = IMAGE_DATA_TYPE_FLOAT;
151  }
152  else {
153  metadata.type = IMAGE_DATA_TYPE_FLOAT4;
154  }
155  }
156 
157  /* Set transform from object space to voxel index. */
158  openvdb::math::Mat4f grid_matrix = grid->transform().baseMap()->getAffineMap()->getMat4();
159  Transform index_to_object;
160  for (int col = 0; col < 4; col++) {
161  for (int row = 0; row < 3; row++) {
162  index_to_object[row][col] = (float)grid_matrix[col][row];
163  }
164  }
165 
166  Transform texture_to_index;
167 # ifdef WITH_NANOVDB
168  if (nanogrid) {
169  texture_to_index = transform_identity();
170  }
171  else
172 # endif
173  {
174  openvdb::Coord min = bbox.min();
175  texture_to_index = transform_translate(min.x(), min.y(), min.z()) *
176  transform_scale(dim.x(), dim.y(), dim.z());
177  }
178 
179  metadata.transform_3d = transform_inverse(index_to_object * texture_to_index);
180  metadata.use_transform_3d = true;
181 
182 # ifndef WITH_NANOVDB
183  (void)features;
184 # endif
185  return true;
186 #else
187  (void)metadata;
188  (void)features;
189  return false;
190 #endif
191 }
192 
193 bool VDBImageLoader::load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool)
194 {
195 #ifdef WITH_OPENVDB
196 # ifdef WITH_NANOVDB
197  if (nanogrid) {
198  memcpy(pixels, nanogrid.data(), nanogrid.size());
199  }
200  else
201 # endif
202  {
203  if (grid->isType<openvdb::FloatGrid>()) {
204  openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
205  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::FloatGrid>(grid), dense);
206  }
207  else if (grid->isType<openvdb::Vec3fGrid>()) {
208  openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
209  bbox, (openvdb::Vec3f *)pixels);
210  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3fGrid>(grid), dense);
211  }
212  else if (grid->isType<openvdb::BoolGrid>()) {
213  openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
214  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::BoolGrid>(grid), dense);
215  }
216  else if (grid->isType<openvdb::DoubleGrid>()) {
217  openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
218  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::DoubleGrid>(grid), dense);
219  }
220  else if (grid->isType<openvdb::Int32Grid>()) {
221  openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
222  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int32Grid>(grid), dense);
223  }
224  else if (grid->isType<openvdb::Int64Grid>()) {
225  openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
226  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Int64Grid>(grid), dense);
227  }
228  else if (grid->isType<openvdb::Vec3IGrid>()) {
229  openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
230  bbox, (openvdb::Vec3f *)pixels);
231  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3IGrid>(grid), dense);
232  }
233  else if (grid->isType<openvdb::Vec3dGrid>()) {
234  openvdb::tools::Dense<openvdb::Vec3f, openvdb::tools::LayoutXYZ> dense(
235  bbox, (openvdb::Vec3f *)pixels);
236  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::Vec3dGrid>(grid), dense);
237  }
238  else if (grid->isType<openvdb::MaskGrid>()) {
239  openvdb::tools::Dense<float, openvdb::tools::LayoutXYZ> dense(bbox, (float *)pixels);
240  openvdb::tools::copyToDense(*openvdb::gridConstPtrCast<openvdb::MaskGrid>(grid), dense);
241  }
242  }
243  return true;
244 #else
245  (void)pixels;
246  return false;
247 #endif
248 }
249 
250 string VDBImageLoader::name() const
251 {
252  return grid_name;
253 }
254 
255 bool VDBImageLoader::equals(const ImageLoader &other) const
256 {
257 #ifdef WITH_OPENVDB
258  const VDBImageLoader &other_loader = (const VDBImageLoader &)other;
259  return grid == other_loader.grid;
260 #else
261  (void)other;
262  return true;
263 #endif
264 }
265 
267 {
268 #ifdef WITH_OPENVDB
269  /* Free OpenVDB grid memory as soon as we can. */
270  grid.reset();
271 #endif
272 #ifdef WITH_NANOVDB
273  nanogrid.reset();
274 #endif
275 }
276 
278 {
279  return true;
280 }
281 
282 #ifdef WITH_OPENVDB
283 openvdb::GridBase::ConstPtr VDBImageLoader::get_grid()
284 {
285  return grid;
286 }
287 #endif
288 
typedef float(TangentPoint)[2]
ImageDataType type
Transform transform_3d
VDBImageLoader(const string &grid_name)
Definition: image_vdb.cpp:29
virtual bool equals(const ImageLoader &other) const override
Definition: image_vdb.cpp:255
string grid_name
Definition: image_vdb.h:57
virtual bool load_metadata(const ImageDeviceFeatures &features, ImageMetaData &metadata) override
Definition: image_vdb.cpp:37
virtual void cleanup() override
Definition: image_vdb.cpp:266
virtual bool is_vdb_loader() const override
Definition: image_vdb.cpp:277
virtual string name() const override
Definition: image_vdb.cpp:250
virtual bool load_pixels(const ImageMetaData &metadata, void *pixels, const size_t pixels_size, const bool associate_alpha) override
Definition: image_vdb.cpp:193
struct Vec3f Vec3f
uint col
#define CCL_NAMESPACE_END
Eigen::Matrix< float, 4, 4 > Mat4f
Definition: numeric.h:85
#define min(a, b)
Definition: sort.c:51
@ IMAGE_DATA_TYPE_FLOAT
Definition: util_texture.h:55
@ IMAGE_DATA_TYPE_FLOAT4
Definition: util_texture.h:52
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT
Definition: util_texture.h:60
@ IMAGE_DATA_TYPE_NANOVDB_FLOAT3
Definition: util_texture.h:61
Transform transform_inverse(const Transform &tfm)
ccl_device_inline Transform transform_identity()
ccl_device_inline Transform transform_translate(float3 t)
ccl_device_inline Transform transform_scale(float3 s)