[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