[Bf-blender-cvs] [128eb6cbe92] master: Modifiers: export motion blur velocity through attribute

Brecht Van Lommel noreply at git.blender.org
Fri Sep 10 17:19:20 CEST 2021


Commit: 128eb6cbe928e58dfee1c64f340fd8d663134c26
Author: Brecht Van Lommel
Date:   Thu Sep 9 17:22:20 2021 +0200
Branches: master
https://developer.blender.org/rB128eb6cbe928e58dfee1c64f340fd8d663134c26

Modifiers: export motion blur velocity through attribute

Previously fluid simulation and Alembic modifiers had a dedicated function
to query the velocity for motion blur. Now use a more generic system where
those modifiers output a velocity attribute.

Advantages:
* Geometry and particle nodes can output velocity through the same mechanism,
  or read the attribute coming from earlier modifiers.
* The velocity can be preserved through modifiers like subdivision surface or
  auto smooth.
* USD and Alembic previously only output velocity from fluid simulation, now
  they work with velocity from other sources too.
* Simplifies the code for renderers like Cycles and exporters like
  Alembic and USD.

This breaks compatibility:
* External renderers and exporters accessing these velocities through the
  Python API now need to use the attribute instead.
* Existing modifier node setups that create an attribute named "velocity"
  will render differently with motion blur.

Differential Revision: https://developer.blender.org/D12305

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

M	intern/cycles/blender/blender_geometry.cpp
M	intern/cycles/blender/blender_mesh.cpp
M	intern/cycles/blender/blender_object.cpp
M	intern/cycles/blender/blender_sync.h
M	intern/cycles/blender/blender_util.h
M	source/blender/blenkernel/BKE_attribute.h
M	source/blender/blenkernel/intern/attribute.c
M	source/blender/blenkernel/intern/fluid.c
M	source/blender/blenkernel/intern/modifier.c
M	source/blender/blenloader/intern/versioning_290.c
M	source/blender/io/alembic/ABC_alembic.h
M	source/blender/io/alembic/exporter/abc_writer_mesh.cc
M	source/blender/io/alembic/exporter/abc_writer_mesh.h
M	source/blender/io/alembic/intern/abc_customdata.h
M	source/blender/io/alembic/intern/abc_reader_curves.cc
M	source/blender/io/alembic/intern/abc_reader_curves.h
M	source/blender/io/alembic/intern/abc_reader_mesh.cc
M	source/blender/io/alembic/intern/abc_reader_mesh.h
M	source/blender/io/alembic/intern/abc_reader_object.cc
M	source/blender/io/alembic/intern/abc_reader_object.h
M	source/blender/io/alembic/intern/alembic_capi.cc
M	source/blender/io/usd/intern/usd_writer_mesh.cc
M	source/blender/io/usd/intern/usd_writer_mesh.h
M	source/blender/makesdna/DNA_fluid_defaults.h
M	source/blender/makesdna/DNA_fluid_types.h
M	source/blender/makesdna/DNA_modifier_defaults.h
M	source/blender/makesdna/DNA_modifier_types.h
M	source/blender/makesrna/intern/rna_fluid.c
M	source/blender/makesrna/intern/rna_modifier.c
M	source/blender/modifiers/intern/MOD_meshsequencecache.c

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

diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp
index acc089a286c..b1de37dac10 100644
--- a/intern/cycles/blender/blender_geometry.cpp
+++ b/intern/cycles/blender/blender_geometry.cpp
@@ -189,8 +189,10 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
   /* Ensure we only sync instanced geometry once. */
   Geometry *geom = object->get_geometry();
 
-  if (geometry_motion_synced.find(geom) != geometry_motion_synced.end())
+  if (geometry_motion_synced.find(geom) != geometry_motion_synced.end() ||
+      geometry_motion_attribute_synced.find(geom) != geometry_motion_attribute_synced.end()) {
     return;
+  }
 
   geometry_motion_synced.insert(geom);
 
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 9bb3447f56b..7ec430eb7fe 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -347,16 +347,57 @@ static void fill_generic_attribute(BL::Mesh &b_mesh,
   }
 }
 
-static void attr_create_generic(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision)
+static void attr_create_motion(Mesh *mesh, BL::Attribute &b_attribute, const float motion_scale)
+{
+  if (!(b_attribute.domain() == BL::Attribute::domain_POINT) &&
+      (b_attribute.data_type() == BL::Attribute::data_type_FLOAT_VECTOR)) {
+    return;
+  }
+
+  BL::FloatVectorAttribute b_vector_attribute(b_attribute);
+  const int numverts = mesh->get_verts().size();
+
+  /* Find or add attribute */
+  float3 *P = &mesh->get_verts()[0];
+  Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
+
+  if (!attr_mP) {
+    attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
+  }
+
+  /* Only export previous and next frame, we don't have any in between data. */
+  float motion_times[2] = {-1.0f, 1.0f};
+  for (int step = 0; step < 2; step++) {
+    const float relative_time = motion_times[step] * 0.5f * motion_scale;
+    float3 *mP = attr_mP->data_float3() + step * numverts;
+
+    for (int i = 0; i < numverts; i++) {
+      mP[i] = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
+    }
+  }
+}
+
+static void attr_create_generic(Scene *scene,
+                                Mesh *mesh,
+                                BL::Mesh &b_mesh,
+                                const bool subdivision,
+                                const bool need_motion,
+                                const float motion_scale)
 {
   if (subdivision) {
     /* TODO: Handle subdivision correctly. */
     return;
   }
   AttributeSet &attributes = mesh->attributes;
+  static const ustring u_velocity("velocity");
 
   for (BL::Attribute &b_attribute : b_mesh.attributes) {
     const ustring name{b_attribute.name().c_str()};
+
+    if (need_motion && name == u_velocity) {
+      attr_create_motion(mesh, b_attribute, motion_scale);
+    }
+
     if (!mesh->need_attribute(scene, name)) {
       continue;
     }
@@ -859,8 +900,10 @@ static void create_mesh(Scene *scene,
                         Mesh *mesh,
                         BL::Mesh &b_mesh,
                         const array<Node *> &used_shaders,
-                        bool subdivision = false,
-                        bool subdivide_uvs = true)
+                        const bool need_motion,
+                        const float motion_scale,
+                        const bool subdivision = false,
+                        const bool subdivide_uvs = true)
 {
   /* count vertices and faces */
   int numverts = b_mesh.vertices.length();
@@ -974,7 +1017,7 @@ static void create_mesh(Scene *scene,
   attr_create_vertex_color(scene, mesh, b_mesh, subdivision);
   attr_create_sculpt_vertex_color(scene, mesh, b_mesh, subdivision);
   attr_create_random_per_island(scene, mesh, b_mesh, subdivision);
-  attr_create_generic(scene, mesh, b_mesh, subdivision);
+  attr_create_generic(scene, mesh, b_mesh, subdivision, need_motion, motion_scale);
 
   if (subdivision) {
     attr_create_subd_uv_map(scene, mesh, b_mesh, subdivide_uvs);
@@ -1002,6 +1045,8 @@ static void create_subd_mesh(Scene *scene,
                              BObjectInfo &b_ob_info,
                              BL::Mesh &b_mesh,
                              const array<Node *> &used_shaders,
+                             const bool need_motion,
+                             const float motion_scale,
                              float dicing_rate,
                              int max_subdivisions)
 {
@@ -1010,7 +1055,7 @@ static void create_subd_mesh(Scene *scene,
   BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]);
   bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE;
 
-  create_mesh(scene, mesh, b_mesh, used_shaders, true, subdivide_uvs);
+  create_mesh(scene, mesh, b_mesh, used_shaders, need_motion, motion_scale, true, subdivide_uvs);
 
   /* export creases */
   size_t num_creases = 0;
@@ -1074,96 +1119,6 @@ static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene)
   return true;
 }
 
-static void sync_mesh_cached_velocities(BObjectInfo &b_ob_info, Scene *scene, Mesh *mesh)
-{
-  if (!mesh_need_motion_attribute(b_ob_info, scene)) {
-    return;
-  }
-
-  BL::Object b_ob = b_ob_info.real_object;
-  BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob, true, nullptr);
-
-  if (!b_mesh_cache) {
-    return;
-  }
-
-  if (!MeshSequenceCacheModifier_read_velocity_get(&b_mesh_cache.ptr)) {
-    return;
-  }
-
-  const size_t numverts = mesh->get_verts().size();
-
-  if (b_mesh_cache.vertex_velocities.length() != numverts) {
-    return;
-  }
-
-  /* Find or add attribute */
-  float3 *P = &mesh->get_verts()[0];
-  Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
-  if (!attr_mP) {
-    attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
-  }
-
-  /* Only export previous and next frame, we don't have any in between data. */
-  float motion_times[2] = {-1.0f, 1.0f};
-  for (int step = 0; step < 2; step++) {
-    const float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
-    float3 *mP = attr_mP->data_float3() + step * numverts;
-
-    BL::MeshSequenceCacheModifier::vertex_velocities_iterator vvi;
-    int i = 0;
-
-    for (b_mesh_cache.vertex_velocities.begin(vvi); vvi != b_mesh_cache.vertex_velocities.end();
-         ++vvi, ++i) {
-      mP[i] = P[i] + get_float3(vvi->velocity()) * relative_time;
-    }
-  }
-}
-
-static void sync_mesh_fluid_motion(BObjectInfo &b_ob_info, Scene *scene, Mesh *mesh)
-{
-  if (!b_ob_info.is_real_object_data()) {
-    return;
-  }
-  if (!mesh_need_motion_attribute(b_ob_info, scene)) {
-    return;
-  }
-
-  BL::Object b_ob = b_ob_info.real_object;
-  BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob);
-
-  if (!b_fluid_domain)
-    return;
-
-  /* If the mesh has modifiers following the fluid domain we can't export motion. */
-  if (b_fluid_domain.mesh_vertices.length() != mesh->get_verts().size())
-    return;
-
-  /* Find or add attribute */
-  float3 *P = &mesh->get_verts()[0];
-  Attribute *attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
-
-  if (!attr_mP) {
-    attr_mP = mesh->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION);
-  }
-
-  /* Only export previous and next frame, we don't have any in between data. */
-  float motion_times[2] = {-1.0f, 1.0f};
-  for (int step = 0; step < 2; step++) {
-    float relative_time = motion_times[step] * scene->motion_shutter_time() * 0.5f;
-    float3 *mP = attr_mP->data_float3() + step * mesh->get_verts().size();
-
-    BL::FluidDomainSettings::mesh_vertices_iterator svi;
-    int i = 0;
-
-    for (b_fluid_domain.mesh_vertices.begin(svi); svi != b_fluid_domain.mesh_vertices.end();
-         ++svi, ++i) {
-      mP[i] = P[i] + get_float3(svi->velocity()) * relative_time;
-    }
-  }
-}
-
 void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh)
 {
   /* make a copy of the shaders as the caller in the main thread still need them for syncing the
@@ -1187,6 +1142,13 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
         b_data, b_ob_info, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type());
 
     if (b_mesh) {
+      /* Motion blur attribute is relative to seconds, we need it relative to frames. */
+      const bool need_motion = mesh_need_motion_attribute(b_ob_info, scene);
+      const float motion_scale = (need_motion) ?
+                                     scene->motion_shutter_time() /
+                                         (b_scene.render().fps() / b_scene.render().fps_base()) :
+                                     0.0f;
+
       /* Sync mesh itself. */
       if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE)
         create_subd_mesh(scene,
@@ -1194,21 +1156,23 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, M
                          b_ob_info,
                          b_mesh,
                          new_mesh.get_used_shaders(),
+                         need_motion,
+                         motion_scale,
                          dicing_rate,
                          max_subdivisions);
       else
-        create_mesh(scene, &new_mesh, b_mesh, new_mesh.get_used_shaders(), false);
+        create_mesh(scene,
+                    &new_mesh,
+                    b_mesh,
+                    new_mesh.get_used_shaders(),
+                    need_motion,
+                    motion_scale,
+                    false);
 
       free_object_to_mesh(b_data, b_ob_info, b_mesh);
     }
   }
 
-  /* cached velocities (e.g. from alembic archive) */
-  sync_mesh_cached_velocities(b_ob_info, scene, &new_mesh);
-
-  /* mesh fluid motion mantaflow */
-  sync_mesh_fluid_motion(b_ob_info, scene, &new_mesh);
-
   /* update original sockets */
 
   mesh->clear_non_sockets();
@@ -1242,19 +1206,6 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph,
                                    Mesh *mesh,
                                    int motion_step)
 {
-  /* Flui

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list