diff options
author | Brecht Van Lommel <brecht> | 2021-09-09 18:22:20 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2021-09-10 17:48:30 +0300 |
commit | 128eb6cbe928e58dfee1c64f340fd8d663134c26 (patch) | |
tree | 68c510ccb7bc3b60af06462392ec46da5baf53a6 /source/blender/io/alembic/intern/abc_reader_mesh.cc | |
parent | 42215d7cb8797ba5b631b9df93d07e895c4b1dda (diff) |
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
Diffstat (limited to 'source/blender/io/alembic/intern/abc_reader_mesh.cc')
-rw-r--r-- | source/blender/io/alembic/intern/abc_reader_mesh.cc | 80 |
1 files changed, 76 insertions, 4 deletions
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 77edd4908bd..dbccc8f2851 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -27,6 +27,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_customdata_types.h" #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -36,6 +37,7 @@ #include "BLI_listbase.h" #include "BLI_math_geom.h" +#include "BKE_attribute.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -43,8 +45,10 @@ #include "BKE_object.h" using Alembic::Abc::Int32ArraySamplePtr; +using Alembic::Abc::IV3fArrayProperty; using Alembic::Abc::P3fArraySamplePtr; using Alembic::Abc::PropertyHeader; +using Alembic::Abc::V3fArraySamplePtr; using Alembic::AbcGeom::IC3fGeomParam; using Alembic::AbcGeom::IC4fGeomParam; @@ -420,6 +424,52 @@ static void get_weight_and_index(CDStreamConfig &config, config.ceil_index = i1; } +static V3fArraySamplePtr get_velocity_prop(const ICompoundProperty &schema, + const ISampleSelector &selector, + const std::string &name) +{ + for (size_t i = 0; i < schema.getNumProperties(); i++) { + const PropertyHeader &header = schema.getPropertyHeader(i); + + if (header.isCompound()) { + const ICompoundProperty &prop = ICompoundProperty(schema, header.getName()); + + if (has_property(prop, name)) { + const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0); + if (velocity_prop) { + return velocity_prop.getValue(selector); + } + } + } + else if (header.isArray()) { + if (header.getName() == name) { + const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0); + return velocity_prop.getValue(selector); + } + } + } + + return V3fArraySamplePtr(); +} + +static void read_velocity(const V3fArraySamplePtr &velocities, + const CDStreamConfig &config, + const float velocity_scale) +{ + CustomDataLayer *velocity_layer = BKE_id_attribute_new( + &config.mesh->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT, NULL); + float(*velocity)[3] = (float(*)[3])velocity_layer->data; + + const int num_velocity_vectors = static_cast<int>(velocities->size()); + BLI_assert(num_velocity_vectors == config.mesh->totvert); + + for (int i = 0; i < num_velocity_vectors; i++) { + const Imath::V3f &vel_in = (*velocities)[i]; + copy_zup_from_yup(velocity[i], vel_in.getValue()); + mul_v3_fl(velocity[i], velocity_scale); + } +} + static void read_mesh_sample(const std::string &iobject_full_name, ImportSettings *settings, const IPolyMeshSchema &schema, @@ -458,6 +508,13 @@ static void read_mesh_sample(const std::string &iobject_full_name, if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { read_custom_data(iobject_full_name, schema.getArbGeomParams(), config, selector); } + + if (!settings->velocity_name.empty() && settings->velocity_scale != 0.0f) { + V3fArraySamplePtr velocities = get_velocity_prop(schema, selector, settings->velocity_name); + if (velocities) { + read_velocity(velocities, config, settings->velocity_scale); + } + } } CDStreamConfig get_config(Mesh *mesh, const bool use_vertex_interpolation) @@ -563,7 +620,7 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str()); m_object->data = mesh; - Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, nullptr); + Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr); if (read_mesh != mesh) { /* XXX FIXME: after 2.80; mesh->flag isn't copied by #BKE_mesh_nomain_to_mesh(). */ /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ @@ -630,7 +687,9 @@ bool AbcMeshReader::topology_changed(Mesh *existing_mesh, const ISampleSelector Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, const ISampleSelector &sample_sel, - int read_flag, + const int read_flag, + const char *velocity_name, + const float velocity_scale, const char **err_str) { IPolyMeshSchema::Sample sample; @@ -673,6 +732,8 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh, /* Only read point data when streaming meshes, unless we need to create new ones. */ ImportSettings settings; settings.read_flag |= read_flag; + settings.velocity_name = velocity_name; + settings.velocity_scale = velocity_scale; if (topology_changed(existing_mesh, sample_sel)) { new_mesh = BKE_mesh_new_nomain_from_template( @@ -829,6 +890,13 @@ static void read_subd_sample(const std::string &iobject_full_name, if ((settings->read_flag & (MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR)) != 0) { read_custom_data(iobject_full_name, schema.getArbGeomParams(), config, selector); } + + if (!settings->velocity_name.empty() && settings->velocity_scale != 0.0f) { + V3fArraySamplePtr velocities = get_velocity_prop(schema, selector, settings->velocity_name); + if (velocities) { + read_velocity(velocities, config, settings->velocity_scale); + } + } } /* ************************************************************************** */ @@ -876,7 +944,7 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec m_object = BKE_object_add_only_object(bmain, OB_MESH, m_object_name.c_str()); m_object->data = mesh; - Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, nullptr); + Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr); if (read_mesh != mesh) { BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true); } @@ -935,7 +1003,9 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh, const ISampleSelector &sample_sel, - int read_flag, + const int read_flag, + const char *velocity_name, + const float velocity_scale, const char **err_str) { ISubDSchema::Sample sample; @@ -962,6 +1032,8 @@ Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh, ImportSettings settings; settings.read_flag |= read_flag; + settings.velocity_name = velocity_name; + settings.velocity_scale = velocity_scale; if (existing_mesh->totvert != positions->size()) { new_mesh = BKE_mesh_new_nomain_from_template( |