[Bf-blender-cvs] [7c144ac1f9c] new-object-types: Volumes: cycles rendering support of volume object as dense grids

Brecht Van Lommel noreply at git.blender.org
Fri Jan 31 11:02:46 CET 2020


Commit: 7c144ac1f9cd1f343aa271b1ab8aa70b030da25f
Author: Brecht Van Lommel
Date:   Thu Jan 30 12:21:05 2020 +0100
Branches: new-object-types
https://developer.blender.org/rB7c144ac1f9cd1f343aa271b1ab8aa70b030da25f

Volumes: cycles rendering support of volume object as dense grids

This does not yet use OpenVDB grid transforms properly, in particular
it is assumed all grids have the same transform and do not contain
rotation or shear.

The conversion is also not optimized. Grid bounds are being computed
multiple times, and for the bounding mesh we should be using the VDB
tree directly.

===================================================================

M	intern/cycles/blender/blender_mesh.cpp
M	intern/cycles/blender/blender_object.cpp
M	intern/cycles/blender/blender_session.cpp
M	intern/cycles/blender/blender_util.h
M	intern/cycles/render/mesh_volume.cpp

===================================================================

diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index b18f9a37948..994d625cdd8 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -326,6 +326,90 @@ static void create_mesh_volume_attributes(Scene *scene, BL::Object &b_ob, Mesh *
         b_ob, mesh, scene->image_manager, ATTR_STD_VOLUME_VELOCITY, frame);
 }
 
+static void create_volume_object(BL::BlendData &b_data, BL::Object &b_ob, Scene *scene, Mesh *mesh)
+{
+  BL::Volume b_volume(b_ob.data());
+  b_volume.grids.load(b_data.ptr.data);
+
+  bool transform_added = false;
+
+  mesh->volume_isovalue = 1e-3f; /* TODO: make user setting. */
+
+  /* Find grid with matching name. */
+  BL::Volume::grids_iterator b_grid_iter;
+  for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) {
+    BL::VolumeGrid b_grid = *b_grid_iter;
+    ustring name = ustring(b_grid.name());
+    AttributeStandard std = ATTR_STD_NONE;
+
+    /* TODO: find nicer solution to detect standard attribute. */
+    if (name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) {
+      std = ATTR_STD_VOLUME_DENSITY;
+    }
+    else if (name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
+      std = ATTR_STD_VOLUME_COLOR;
+    }
+    else if (name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) {
+      std = ATTR_STD_VOLUME_FLAME;
+    }
+    else if (name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT)) {
+      std = ATTR_STD_VOLUME_HEAT;
+    }
+    else if (name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
+      std = ATTR_STD_VOLUME_TEMPERATURE;
+    }
+    else if (name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
+      std = ATTR_STD_VOLUME_VELOCITY;
+    }
+
+    if ((std != ATTR_STD_NONE && mesh->need_attribute(scene, std)) ||
+        mesh->need_attribute(scene, name)) {
+      Attribute *attr = (std != ATTR_STD_NONE) ?
+                            mesh->attributes.add(std) :
+                            mesh->attributes.add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
+      VoxelAttribute *volume_data = attr->data_voxel();
+      ImageMetaData metadata;
+      const bool animated = false;
+      const float frame = 0.0f;
+
+      volume_data->manager = scene->image_manager;
+      volume_data->slot = scene->image_manager->add_image(name.c_str(),
+                                                          b_volume.ptr.data,
+                                                          animated,
+                                                          frame,
+                                                          INTERPOLATION_LINEAR,
+                                                          EXTENSION_CLIP,
+                                                          IMAGE_ALPHA_AUTO,
+                                                          u_colorspace_raw,
+                                                          metadata);
+
+      /* TODO: support each grid having own transform. */
+      /* TODO: support full transform instead of only using boundbox. */
+      /* TODO: avoid computing bounds multiple times, perhaps by postponing
+       * setting this transform until voxels are loaded. */
+      if (!transform_added && mesh->need_attribute(scene, ATTR_STD_GENERATED_TRANSFORM)) {
+        Attribute *attr = mesh->attributes.add(ATTR_STD_GENERATED_TRANSFORM);
+        Transform *tfm = attr->data_transform();
+
+        b_grid.load();
+
+        VolumeGrid *volume_grid = (VolumeGrid *)b_grid.ptr.data;
+        size_t min[3], max[3];
+        if (BKE_volume_grid_dense_bounds(volume_grid, min, max)) {
+          float mat[4][4];
+          BKE_volume_grid_dense_transform_matrix(volume_grid, min, max, mat);
+          *tfm = transform_inverse(get_transform(mat));
+        }
+        else {
+          *tfm = transform_identity();
+        }
+
+        transform_added = true;
+      }
+    }
+  }
+}
+
 /* Create vertex color attributes. */
 static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
 {
@@ -1060,7 +1144,13 @@ Mesh *BlenderSync::sync_mesh(BL::Depsgraph &b_depsgraph,
   mesh->used_shaders = used_shaders;
   mesh->name = ustring(b_ob_data.name().c_str());
 
-  if (requested_geometry_flags != Mesh::GEOMETRY_NONE) {
+  if (b_ob.type() == BL::Object::type_VOLUME) {
+    /* Volume object. Create only attributes, bounding mesh will then
+     * be automatically generated later. */
+    /* TODO: support disabling volumes in view layer. */
+    create_volume_object(b_data, b_ob, scene, mesh);
+  }
+  else if (requested_geometry_flags != Mesh::GEOMETRY_NONE) {
     /* Adaptive subdivision setup. Not for baking since that requires
      * exact mapping to the Blender mesh. */
     if (scene->bake_manager->get_baking()) {
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 6981412bb88..1d14bfd962c 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -67,7 +67,11 @@ bool BlenderSync::object_is_mesh(BL::Object &b_ob)
     return false;
   }
 
-  if (b_ob.type() == BL::Object::type_CURVE) {
+  if (b_ob.type() == BL::Object::type_VOLUME) {
+    /* Will be exported as mesh bounding box. */
+    return true;
+  }
+  else if (b_ob.type() == BL::Object::type_CURVE) {
     /* Skip exporting curves without faces, overhead can be
      * significant if there are many for path animation. */
     BL::Curve b_curve(b_ob.data());
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index e2dea24fdd1..f0fa66c0b22 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -1156,6 +1156,43 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
       metadata.colorspace = u_colorspace_raw;
     }
   }
+  else if (b_id.is_a(&RNA_Volume)) {
+    /* Volume datablock. */
+    BL::Volume b_volume(b_id);
+
+    /* Find grid with matching name. */
+    BL::Volume::grids_iterator b_grid_iter;
+    for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) {
+      BL::VolumeGrid b_grid = *b_grid_iter;
+
+      if (b_grid.name() == builtin_name) {
+        VolumeGrid *volume_grid = (VolumeGrid *)b_grid.ptr.data;
+
+        /* Skip grid that we can parse as float channels. */
+        if (b_grid.channels() == 0) {
+          return;
+        }
+
+        /* Load grid, and free after reading voxels if it wasn't already loaded. */
+        metadata.builtin_free_cache = !b_grid.is_loaded();
+        b_grid.load();
+
+        /* Compute grid dimensions. */
+        size_t min[3], max[3];
+        if (!BKE_volume_grid_dense_bounds(volume_grid, min, max)) {
+          return;
+        }
+
+        /* Set metadata. */
+        metadata.width = max[0] - min[0];
+        metadata.height = max[1] - min[1];
+        metadata.depth = max[2] - min[2];
+        metadata.is_float = true;
+        metadata.channels = b_grid.channels();
+        return;
+      }
+    }
+  }
   else if (b_id.is_a(&RNA_Object)) {
     /* smoke volume data */
     BL::Object b_ob(b_id);
@@ -1337,6 +1374,32 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
 
     return true;
   }
+  else if (b_id.is_a(&RNA_Volume)) {
+    /* Volume datablock. */
+    BL::Volume b_volume(b_id);
+
+    /* Find grid with matching name. */
+    BL::Volume::grids_iterator b_grid_iter;
+    for (b_volume.grids.begin(b_grid_iter); b_grid_iter != b_volume.grids.end(); ++b_grid_iter) {
+      BL::VolumeGrid b_grid = *b_grid_iter;
+
+      if (b_grid.name() == builtin_name) {
+        VolumeGrid *volume_grid = (VolumeGrid *)b_grid.ptr.data;
+
+        /* TODO: don't compute resolution twice */
+        size_t min[3], max[3];
+        if (BKE_volume_grid_dense_bounds(volume_grid, min, max)) {
+          BKE_volume_grid_dense_voxels(volume_grid, min, max, pixels);
+        }
+
+        if (free_cache) {
+          b_grid.unload();
+        }
+
+        return true;
+      }
+    }
+  }
   else if (b_id.is_a(&RNA_Object)) {
     /* smoke volume data */
     BL::Object b_ob(b_id);
diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h
index bea30a20b8c..14b0a176660 100644
--- a/intern/cycles/blender/blender_util.h
+++ b/intern/cycles/blender/blender_util.h
@@ -36,6 +36,17 @@ void BKE_image_user_frame_calc(void *ima, void *iuser, int cfra);
 void BKE_image_user_file_path(void *iuser, void *ima, char *path);
 unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame, int tile);
 float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
+
+struct VolumeGrid;
+bool BKE_volume_grid_dense_bounds(const VolumeGrid *volume_grid, size_t min[3], size_t max[3]);
+void BKE_volume_grid_dense_transform_matrix(const VolumeGrid *volume_grid,
+                                            const size_t min[3],
+                                            const size_t max[3],
+                                            float mat[4][4]);
+void BKE_volume_grid_dense_voxels(const VolumeGrid *volume_grid,
+                                  const size_t min[3],
+                                  const size_t max[3],
+                                  float *voxels);
 }
 
 CCL_NAMESPACE_BEGIN
@@ -271,6 +282,19 @@ static inline void render_add_metadata(BL::RenderResult &b_rr, string name, stri
 
 /* Utilities */
 
+static inline Transform get_transform(float mat[4][4])
+{
+  ProjectionTransform projection;
+
+  /* We assume both types to be just 16 floats, and transpose because blender
+   * use column major matrix order while we use row major. */
+  memcpy((void *)&projection, mat, sizeof(float) * 16);
+  projection = projection_transpose(projection);
+
+  /* Drop last row, matrix is assumed to be affine transform. */
+  return projection_to_transform(projection);
+}
+
 static inline Transform get_transform(const BL::Array<float, 16> &array)
 {
   ProjectionTransform projection;
diff --git a/intern/cycles/render/mesh_volume.cpp b/intern/cycles/render/mesh_volume.cpp
index f451b58e92a..413d4692

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list