Blender  V2.93
blender_volume.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 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/colorspace.h"
18 #include "render/image.h"
19 #include "render/image_vdb.h"
20 #include "render/object.h"
21 #include "render/volume.h"
22 
23 #include "blender/blender_sync.h"
24 #include "blender/blender_util.h"
25 
26 #ifdef WITH_OPENVDB
27 # include <openvdb/openvdb.h>
28 openvdb::GridBase::ConstPtr BKE_volume_grid_openvdb_for_read(const struct Volume *volume,
29  const struct VolumeGrid *grid);
30 #endif
31 
33 
34 /* TODO: verify this is not loading unnecessary attributes. */
36  public:
39  {
40  BL::Mesh b_mesh(b_ob.data());
42  }
43 
44  bool load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) override
45  {
46  if (!b_domain) {
47  return false;
48  }
49 
52  metadata.type = IMAGE_DATA_TYPE_FLOAT;
53  metadata.channels = 1;
54  }
55  else if (attribute == ATTR_STD_VOLUME_COLOR) {
56  metadata.type = IMAGE_DATA_TYPE_FLOAT4;
57  metadata.channels = 4;
58  }
59  else if (attribute == ATTR_STD_VOLUME_VELOCITY) {
60  metadata.type = IMAGE_DATA_TYPE_FLOAT4;
61  metadata.channels = 3;
62  }
63  else {
64  return false;
65  }
66 
67  int3 resolution = get_int3(b_domain.domain_resolution());
68  int amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1;
69 
70  /* Velocity and heat data is always low-resolution. */
72  amplify = 1;
73  }
74 
75  metadata.width = resolution.x * amplify;
76  metadata.height = resolution.y * amplify;
77  metadata.depth = resolution.z * amplify;
78 
79  /* Create a matrix to transform from object space to mesh texture space.
80  * This does not work with deformations but that can probably only be done
81  * well with a volume grid mapping of coordinates. */
83  metadata.use_transform_3d = true;
84 
85  return true;
86  }
87 
88  bool load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool) override
89  {
90  if (!b_domain) {
91  return false;
92  }
93 #ifdef WITH_FLUID
94  int3 resolution = get_int3(b_domain.domain_resolution());
95  int length, amplify = (b_domain.use_noise()) ? b_domain.noise_scale() : 1;
96 
97  /* Velocity and heat data is always low-resolution. */
99  amplify = 1;
100  }
101 
102  const int width = resolution.x * amplify;
103  const int height = resolution.y * amplify;
104  const int depth = resolution.z * amplify;
105  const size_t num_pixels = ((size_t)width) * height * depth;
106 
107  float *fpixels = (float *)pixels;
108 
110  FluidDomainSettings_density_grid_get_length(&b_domain.ptr, &length);
111  if (length == num_pixels) {
112  FluidDomainSettings_density_grid_get(&b_domain.ptr, fpixels);
113  return true;
114  }
115  }
116  else if (attribute == ATTR_STD_VOLUME_FLAME) {
117  /* this is in range 0..1, and interpreted by the OpenGL smoke viewer
118  * as 1500..3000 K with the first part faded to zero density */
119  FluidDomainSettings_flame_grid_get_length(&b_domain.ptr, &length);
120  if (length == num_pixels) {
121  FluidDomainSettings_flame_grid_get(&b_domain.ptr, fpixels);
122  return true;
123  }
124  }
125  else if (attribute == ATTR_STD_VOLUME_COLOR) {
126  /* the RGB is "premultiplied" by density for better interpolation results */
127  FluidDomainSettings_color_grid_get_length(&b_domain.ptr, &length);
128  if (length == num_pixels * 4) {
129  FluidDomainSettings_color_grid_get(&b_domain.ptr, fpixels);
130  return true;
131  }
132  }
133  else if (attribute == ATTR_STD_VOLUME_VELOCITY) {
134  FluidDomainSettings_velocity_grid_get_length(&b_domain.ptr, &length);
135  if (length == num_pixels * 3) {
136  FluidDomainSettings_velocity_grid_get(&b_domain.ptr, fpixels);
137  return true;
138  }
139  }
140  else if (attribute == ATTR_STD_VOLUME_HEAT) {
141  FluidDomainSettings_heat_grid_get_length(&b_domain.ptr, &length);
142  if (length == num_pixels) {
143  FluidDomainSettings_heat_grid_get(&b_domain.ptr, fpixels);
144  return true;
145  }
146  }
148  FluidDomainSettings_temperature_grid_get_length(&b_domain.ptr, &length);
149  if (length == num_pixels) {
150  FluidDomainSettings_temperature_grid_get(&b_domain.ptr, fpixels);
151  return true;
152  }
153  }
154  else {
155  fprintf(stderr,
156  "Cycles error: unknown volume attribute %s, skipping\n",
158  fpixels[0] = 0.0f;
159  return false;
160  }
161 #else
162  (void)pixels;
163 #endif
164  fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n");
165  return false;
166  }
167 
168  string name() const override
169  {
171  }
172 
173  bool equals(const ImageLoader &other) const override
174  {
175  const BlenderSmokeLoader &other_loader = (const BlenderSmokeLoader &)other;
176  return b_domain == other_loader.b_domain && attribute == other_loader.attribute;
177  }
178 
182 };
183 
184 static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, float frame)
185 {
187  if (!b_domain) {
188  return;
189  }
190 
197  ATTR_STD_NONE};
198 
199  for (int i = 0; attributes[i] != ATTR_STD_NONE; i++) {
200  AttributeStandard std = attributes[i];
201  if (!volume->need_attribute(scene, std)) {
202  continue;
203  }
204 
205  volume->set_clipping(b_domain.clipping());
206 
207  Attribute *attr = volume->attributes.add(std);
208 
209  ImageLoader *loader = new BlenderSmokeLoader(b_ob, std);
211  params.frame = frame;
212 
213  attr->data_voxel() = scene->image_manager->add_image(loader, params);
214  }
215 }
216 
218  public:
219  BlenderVolumeLoader(BL::BlendData &b_data, BL::Volume &b_volume, const string &grid_name)
221  {
222  b_volume.grids.load(b_data.ptr.data);
223 
224 #ifdef WITH_OPENVDB
225  for (BL::VolumeGrid &b_volume_grid : b_volume.grids) {
226  if (b_volume_grid.name() == grid_name) {
227  const bool unload = !b_volume_grid.is_loaded();
228 
229  ::Volume *volume = (::Volume *)b_volume.ptr.data;
230  const VolumeGrid *volume_grid = (VolumeGrid *)b_volume_grid.ptr.data;
231  grid = BKE_volume_grid_openvdb_for_read(volume, volume_grid);
232 
233  if (unload) {
234  b_volume_grid.unload();
235  }
236 
237  break;
238  }
239  }
240 #endif
241  }
242 
244 };
245 
246 static void sync_volume_object(BL::BlendData &b_data,
247  BL::Object &b_ob,
248  Scene *scene,
249  Volume *volume)
250 {
251  BL::Volume b_volume(b_ob.data());
252  b_volume.grids.load(b_data.ptr.data);
253 
254  BL::VolumeRender b_render(b_volume.render());
255 
256  volume->set_clipping(b_render.clipping());
257  volume->set_step_size(b_render.step_size());
258  volume->set_object_space((b_render.space() == BL::VolumeRender::space_OBJECT));
259 
260  /* Find grid with matching name. */
261  for (BL::VolumeGrid &b_grid : b_volume.grids) {
262  ustring name = ustring(b_grid.name());
264 
267  }
270  }
273  }
276  }
279  }
282  }
283 
284  if ((std != ATTR_STD_NONE && volume->need_attribute(scene, std)) ||
285  volume->need_attribute(scene, name)) {
286  Attribute *attr = (std != ATTR_STD_NONE) ?
287  volume->attributes.add(std) :
288  volume->attributes.add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
289 
290  ImageLoader *loader = new BlenderVolumeLoader(b_data, b_volume, name.string());
292  params.frame = b_volume.grids.frame();
293 
294  attr->data_voxel() = scene->image_manager->add_image(loader, params, false);
295  }
296  }
297 }
298 
299 void BlenderSync::sync_volume(BL::Object &b_ob, Volume *volume)
300 {
301  volume->clear(true);
302 
303  if (view_layer.use_volumes) {
304  if (b_ob.type() == BL::Object::type_VOLUME) {
305  /* Volume object. Create only attributes, bounding mesh will then
306  * be automatically generated later. */
307  sync_volume_object(b_data, b_ob, scene, volume);
308  }
309  else {
310  /* Smoke domain. */
311  sync_smoke_volume(scene, b_ob, volume, b_scene.frame_current());
312  }
313  }
314 
315  /* Tag update. */
316  volume->tag_update(scene, true);
317 }
318 
struct VolumeGrid VolumeGrid
Definition: BKE_volume.h:79
struct FluidDomainSettings FluidDomainSettings
struct Mesh Mesh
struct Object Object
struct VolumeRender VolumeRender
struct Volume Volume
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
static int3 get_int3(const BL::Array< int, 3 > &array)
Definition: blender_util.h:315
static BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b_ob)
Definition: blender_util.h:555
static void mesh_texture_space(BL::Mesh &b_mesh, float3 &loc, float3 &size)
Definition: blender_util.h:473
static void sync_volume_object(BL::BlendData &b_data, BL::Object &b_ob, Scene *scene, Volume *volume)
static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, float frame)
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
Attribute * add(ustring name, TypeDesc type, AttributeElement element)
Definition: attribute.cpp:428
ImageHandle & data_voxel()
Definition: attribute.h:113
static const char * standard_name(AttributeStandard std)
Definition: attribute.cpp:311
bool load_pixels(const ImageMetaData &, void *pixels, const size_t, const bool) override
string name() const override
bool load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) override
BlenderSmokeLoader(BL::Object &b_ob, AttributeStandard attribute)
BL::FluidDomainSettings b_domain
bool equals(const ImageLoader &other) const override
AttributeStandard attribute
BlenderVolumeLoader(BL::BlendData &b_data, BL::Volume &b_volume, const string &grid_name)
bool need_attribute(Scene *scene, AttributeStandard std)
Definition: geometry.cpp:102
void tag_update(Scene *scene, bool rebuild)
Definition: geometry.cpp:271
AttributeSet attributes
Definition: geometry.h:81
ImageHandle add_image(const string &filename, const ImageParams &params)
Definition: image.cpp:368
ImageDataType type
Transform transform_3d
string grid_name
Definition: image_vdb.h:57
Scene scene
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define CCL_NAMESPACE_END
AttributeStandard
Definition: kernel_types.h:744
@ ATTR_STD_VOLUME_TEMPERATURE
Definition: kernel_types.h:767
@ ATTR_STD_NONE
Definition: kernel_types.h:745
@ ATTR_STD_VOLUME_DENSITY
Definition: kernel_types.h:763
@ ATTR_STD_VOLUME_FLAME
Definition: kernel_types.h:765
@ ATTR_STD_VOLUME_VELOCITY
Definition: kernel_types.h:768
@ ATTR_STD_VOLUME_COLOR
Definition: kernel_types.h:764
@ ATTR_STD_VOLUME_HEAT
Definition: kernel_types.h:766
@ ATTR_ELEMENT_VOXEL
Definition: kernel_types.h:741
ImageManager * image_manager
Definition: scene.h:243
virtual void clear(bool preserve_shaders=false) override
Definition: volume.cpp:55
@ IMAGE_DATA_TYPE_FLOAT
Definition: util_texture.h:55
@ IMAGE_DATA_TYPE_FLOAT4
Definition: util_texture.h:52
ccl_device_inline Transform transform_translate(float3 t)
ccl_device_inline Transform transform_scale(float3 s)