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 | |
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')
25 files changed, 218 insertions, 426 deletions
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h index 5fda30224c6..7476474258b 100644 --- a/source/blender/blenkernel/BKE_attribute.h +++ b/source/blender/blenkernel/BKE_attribute.h @@ -66,6 +66,11 @@ bool BKE_id_attribute_remove(struct ID *id, struct CustomDataLayer *layer, struct ReportList *reports); +struct CustomDataLayer *BKE_id_attribute_find(const struct ID *id, + const char *name, + const int type, + const AttributeDomain domain); + AttributeDomain BKE_id_attribute_domain(struct ID *id, struct CustomDataLayer *layer); int BKE_id_attribute_data_length(struct ID *id, struct CustomDataLayer *layer); bool BKE_id_attribute_required(struct ID *id, struct CustomDataLayer *layer); diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c index e9444cf88a6..ee8ef5e97f7 100644 --- a/source/blender/blenkernel/intern/attribute.c +++ b/source/blender/blenkernel/intern/attribute.c @@ -51,7 +51,7 @@ typedef struct DomainInfo { int length; } DomainInfo; -static void get_domains(ID *id, DomainInfo info[ATTR_DOMAIN_NUM]) +static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM]) { memset(info, 0, sizeof(DomainInfo) * ATTR_DOMAIN_NUM); @@ -223,6 +223,29 @@ bool BKE_id_attribute_remove(ID *id, CustomDataLayer *layer, ReportList *reports return true; } +CustomDataLayer *BKE_id_attribute_find(const ID *id, + const char *name, + const int type, + const AttributeDomain domain) +{ + DomainInfo info[ATTR_DOMAIN_NUM]; + get_domains(id, info); + + CustomData *customdata = info[domain].customdata; + if (customdata == NULL) { + return NULL; + } + + for (int i = 0; i < customdata->totlayer; i++) { + CustomDataLayer *layer = &customdata->layers[i]; + if (layer->type == type && STREQ(layer->name, name)) { + return layer; + } + } + + return NULL; +} + int BKE_id_attributes_length(ID *id, const CustomDataMask mask) { DomainInfo info[ATTR_DOMAIN_NUM]; diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 5a5e1208ff0..f13ed1f2bf7 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -39,6 +39,7 @@ #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" +#include "BKE_attribute.h" #include "BKE_effect.h" #include "BKE_fluid.h" #include "BKE_global.h" @@ -529,8 +530,7 @@ static bool BKE_fluid_modifier_init( copy_v3_v3_int(fds->res_max, res); /* Set time, frame length = 0.1 is at 25fps. */ - float fps = scene->r.frs_sec / scene->r.frs_sec_base; - fds->frame_length = DT_DEFAULT * (25.0f / fps) * fds->time_scale; + fds->frame_length = DT_DEFAULT * (25.0f / FPS) * fds->time_scale; /* Initially dt is equal to frame length (dt can change with adaptive-time stepping though). */ fds->dt = fds->frame_length; fds->time_per_frame = 0; @@ -3256,7 +3256,10 @@ static void update_effectors( BKE_effectors_free(effectors); } -static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Object *ob) +static Mesh *create_liquid_geometry(FluidDomainSettings *fds, + Scene *scene, + Mesh *orgmesh, + Object *ob) { Mesh *me; MVert *mverts; @@ -3303,22 +3306,6 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obj /* Normals are per vertex, so these must match. */ BLI_assert(num_verts == num_normals); - /* If needed, vertex velocities will be read too. */ - bool use_speedvectors = fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS; - FluidDomainVertexVelocity *velarray = NULL; - float time_mult = 25.0f * DT_DEFAULT; - - if (use_speedvectors) { - if (fds->mesh_velocities) { - MEM_freeN(fds->mesh_velocities); - } - - fds->mesh_velocities = MEM_calloc_arrayN( - num_verts, sizeof(FluidDomainVertexVelocity), "fluid_mesh_vertvelocities"); - fds->totvert = num_verts; - velarray = fds->mesh_velocities; - } - me = BKE_mesh_new_nomain(num_verts, 0, 0, num_faces * 3, num_faces); if (!me) { return NULL; @@ -3350,6 +3337,18 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obj /* Normals. */ normals = MEM_callocN(sizeof(short[3]) * num_normals, "Fluidmesh_tmp_normals"); + /* Velocities. */ + /* If needed, vertex velocities will be read too. */ + bool use_speedvectors = fds->flags & FLUID_DOMAIN_USE_SPEED_VECTORS; + float(*velarray)[3] = NULL; + float time_mult = fds->dx / (DT_DEFAULT * (25.0f / FPS)); + + if (use_speedvectors) { + CustomDataLayer *velocity_layer = BKE_id_attribute_new( + &me->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT, NULL); + velarray = velocity_layer->data; + } + /* Loop for vertices and normals. */ for (i = 0, no_s = normals; i < num_verts && i < num_normals; i++, mverts++, no_s += 3) { @@ -3389,18 +3388,18 @@ static Mesh *create_liquid_geometry(FluidDomainSettings *fds, Mesh *orgmesh, Obj # endif if (use_speedvectors) { - velarray[i].vel[0] = manta_liquid_get_vertvel_x_at(fds->fluid, i) * (fds->dx / time_mult); - velarray[i].vel[1] = manta_liquid_get_vertvel_y_at(fds->fluid, i) * (fds->dx / time_mult); - velarray[i].vel[2] = manta_liquid_get_vertvel_z_at(fds->fluid, i) * (fds->dx / time_mult); + velarray[i][0] = manta_liquid_get_vertvel_x_at(fds->fluid, i) * time_mult; + velarray[i][1] = manta_liquid_get_vertvel_y_at(fds->fluid, i) * time_mult; + velarray[i][2] = manta_liquid_get_vertvel_z_at(fds->fluid, i) * time_mult; # ifdef DEBUG_PRINT /* Debugging: Print velocities of vertices. */ - printf("velarray[%d].vel[0]: %f, velarray[%d].vel[1]: %f, velarray[%d].vel[2]: %f\n", + printf("velarray[%d][0]: %f, velarray[%d][1]: %f, velarray[%d][2]: %f\n", i, - velarray[i].vel[0], + velarray[i][0], i, - velarray[i].vel[1], + velarray[i][1], i, - velarray[i].vel[2]); + velarray[i][2]); # endif } } @@ -3670,8 +3669,7 @@ static void manta_guiding( Depsgraph *depsgraph, Scene *scene, Object *ob, FluidModifierData *fmd, int frame) { FluidDomainSettings *fds = fmd->domain; - float fps = scene->r.frs_sec / scene->r.frs_sec_base; - float dt = DT_DEFAULT * (25.0f / fps) * fds->time_scale; + float dt = DT_DEFAULT * (25.0f / FPS) * fds->time_scale; BLI_mutex_lock(&object_update_lock); @@ -3842,8 +3840,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd, copy_v3_v3_int(o_shift, fds->shift); /* Ensure that time parameters are initialized correctly before every step. */ - float fps = scene->r.frs_sec / scene->r.frs_sec_base; - fds->frame_length = DT_DEFAULT * (25.0f / fps) * fds->time_scale; + fds->frame_length = DT_DEFAULT * (25.0f / FPS) * fds->time_scale; fds->dt = fds->frame_length; fds->time_per_frame = 0; @@ -4216,7 +4213,7 @@ struct Mesh *BKE_fluid_modifier_do( if (needs_viewport_update) { /* Return generated geometry depending on domain type. */ if (fmd->domain->type == FLUID_DOMAIN_TYPE_LIQUID) { - result = create_liquid_geometry(fmd->domain, me, ob); + result = create_liquid_geometry(fmd->domain, scene, me, ob); } if (fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) { result = create_smoke_geometry(fmd->domain, me, ob); @@ -4773,8 +4770,6 @@ static void BKE_fluid_modifier_freeDomain(FluidModifierData *fmd) fmd->domain->point_cache[0] = NULL; } - MEM_SAFE_FREE(fmd->domain->mesh_velocities); - if (fmd->domain->coba) { MEM_freeN(fmd->domain->coba); } @@ -5010,16 +5005,12 @@ void BKE_fluid_modifier_copy(const struct FluidModifierData *fmd, tfds->viscosity_exponent = fds->viscosity_exponent; /* mesh options */ - if (fds->mesh_velocities) { - tfds->mesh_velocities = MEM_dupallocN(fds->mesh_velocities); - } tfds->mesh_concave_upper = fds->mesh_concave_upper; tfds->mesh_concave_lower = fds->mesh_concave_lower; tfds->mesh_particle_radius = fds->mesh_particle_radius; tfds->mesh_smoothen_pos = fds->mesh_smoothen_pos; tfds->mesh_smoothen_neg = fds->mesh_smoothen_neg; tfds->mesh_scale = fds->mesh_scale; - tfds->totvert = fds->totvert; tfds->mesh_generator = fds->mesh_generator; /* secondary particle options */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index b328a31cda5..b55b02c7bf2 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -1473,7 +1473,6 @@ void BKE_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb, Object fmd->domain->tex_velocity_y = NULL; fmd->domain->tex_velocity_z = NULL; fmd->domain->tex_wt = NULL; - fmd->domain->mesh_velocities = NULL; BLO_read_data_address(reader, &fmd->domain->coba); BLO_read_data_address(reader, &fmd->domain->effector_weights); diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index cb7a8ad592a..0e89c15ca1e 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -1092,8 +1092,6 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) if (md->type == eModifierType_MeshSequenceCache) { MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; mcmd->velocity_scale = 1.0f; - mcmd->vertex_velocities = NULL; - mcmd->num_vertices = 0; } } } diff --git a/source/blender/io/alembic/ABC_alembic.h b/source/blender/io/alembic/ABC_alembic.h index 0a3a43bb21f..0b5e927f02f 100644 --- a/source/blender/io/alembic/ABC_alembic.h +++ b/source/blender/io/alembic/ABC_alembic.h @@ -117,7 +117,9 @@ struct Mesh *ABC_read_mesh(struct CacheReader *reader, struct Mesh *existing_mesh, const float time, const char **err_str, - int read_flags); + const int read_flags, + const char *velocity_name, + const float velocity_scale); bool ABC_mesh_topology_changed(struct CacheReader *reader, struct Object *ob, @@ -133,16 +135,6 @@ struct CacheReader *CacheReader_open_alembic_object(struct CacheArchiveHandle *h struct Object *object, const char *object_path); -bool ABC_has_vec3_array_property_named(struct CacheReader *reader, const char *name); - -/* r_vertex_velocities should point to a preallocated array of num_vertices floats */ -int ABC_read_velocity_cache(struct CacheReader *reader, - const char *velocity_name, - float time, - float velocity_scale, - int num_vertices, - float *r_vertex_velocities); - #ifdef __cplusplus } #endif diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc index 131b60b90fb..8f410978211 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc @@ -25,6 +25,7 @@ #include "BLI_assert.h" #include "BLI_math_vector.h" +#include "BKE_attribute.h" #include "BKE_customdata.h" #include "BKE_lib_id.h" #include "BKE_material.h" @@ -108,9 +109,6 @@ void ABCGenericMeshWriter::create_alembic_objects(const HierarchyContext *contex OBoolProperty type(typeContainer, "meshtype"); type.set(subsurf_modifier_ == nullptr); } - - Scene *scene_eval = DEG_get_evaluated_scene(args_.depsgraph); - liquid_sim_modifier_ = get_liquid_sim_modifier(scene_eval, context->object); } Alembic::Abc::OObject ABCGenericMeshWriter::get_alembic_object() const @@ -144,21 +142,6 @@ bool ABCGenericMeshWriter::export_as_subdivision_surface(Object *ob_eval) const return false; } -ModifierData *ABCGenericMeshWriter::get_liquid_sim_modifier(Scene *scene, Object *ob) -{ - ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluidsim); - - if (md && (BKE_modifier_is_enabled(scene, md, eModifierMode_Render))) { - FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md); - - if (fsmd->fss && fsmd->fss->type == OB_FLUIDSIM_DOMAIN) { - return md; - } - } - - return nullptr; -} - bool ABCGenericMeshWriter::is_supported(const HierarchyContext *context) const { if (args_.export_params->visible_objects_only) { @@ -284,8 +267,7 @@ void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) write_generated_coordinates(abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config); } - if (liquid_sim_modifier_ != nullptr) { - get_velocities(mesh, velocities); + if (get_velocities(mesh, velocities)) { mesh_sample.setVelocities(V3fArraySample(velocities)); } @@ -368,11 +350,6 @@ void ABCGenericMeshWriter::write_face_sets(Object *object, struct Mesh *mesh, Sc void ABCGenericMeshWriter::write_arb_geo_params(struct Mesh *me) { - if (liquid_sim_modifier_ != nullptr) { - /* We don't need anything more for liquid meshes. */ - return; - } - if (frame_has_been_written_ || !args_.export_params->vcolors) { return; } @@ -387,27 +364,28 @@ void ABCGenericMeshWriter::write_arb_geo_params(struct Mesh *me) write_custom_data(arb_geom_params, m_custom_data_config, &me->ldata, CD_MLOOPCOL); } -void ABCGenericMeshWriter::get_velocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels) +bool ABCGenericMeshWriter::get_velocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels) { + /* Export velocity attribute output by fluid sim, sequence cache modifier + * and geometry nodes. */ + CustomDataLayer *velocity_layer = BKE_id_attribute_find( + &mesh->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT); + + if (velocity_layer == nullptr) { + return false; + } + const int totverts = mesh->totvert; + const float(*mesh_velocities)[3] = reinterpret_cast<float(*)[3]>(velocity_layer->data); vels.clear(); vels.resize(totverts); - FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(liquid_sim_modifier_); - FluidsimSettings *fss = fmd->fss; - - if (fss->meshVelocities) { - float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities); - - for (int i = 0; i < totverts; i++) { - copy_yup_from_zup(vels[i].getValue(), mesh_vels); - mesh_vels += 3; - } - } - else { - std::fill(vels.begin(), vels.end(), Imath::V3f(0.0f)); + for (int i = 0; i < totverts; i++) { + copy_yup_from_zup(vels[i].getValue(), mesh_velocities[i]); } + + return true; } void ABCGenericMeshWriter::get_geo_groups(Object *object, diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.h b/source/blender/io/alembic/exporter/abc_writer_mesh.h index 0e1792b9dab..fb8a01a3bbf 100644 --- a/source/blender/io/alembic/exporter/abc_writer_mesh.h +++ b/source/blender/io/alembic/exporter/abc_writer_mesh.h @@ -45,7 +45,6 @@ class ABCGenericMeshWriter : public ABCAbstractWriter { * exported object. */ bool is_subd_; ModifierData *subsurf_modifier_; - ModifierData *liquid_sim_modifier_; CDStreamConfig m_custom_data_config; @@ -70,10 +69,8 @@ class ABCGenericMeshWriter : public ABCAbstractWriter { void write_subd(HierarchyContext &context, Mesh *mesh); template<typename Schema> void write_face_sets(Object *object, Mesh *mesh, Schema &schema); - ModifierData *get_liquid_sim_modifier(Scene *scene_eval, Object *ob_eval); - void write_arb_geo_params(Mesh *me); - void get_velocities(Mesh *mesh, std::vector<Imath::V3f> &vels); + bool get_velocities(Mesh *mesh, std::vector<Imath::V3f> &vels); void get_geo_groups(Object *object, Mesh *mesh, std::map<std::string, std::vector<int32_t>> &geo_groups); diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h index e9736555ead..4fba6a2f0f7 100644 --- a/source/blender/io/alembic/intern/abc_customdata.h +++ b/source/blender/io/alembic/intern/abc_customdata.h @@ -122,6 +122,12 @@ void read_custom_data(const std::string &iobject_full_name, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss); +void read_velocity(const Alembic::Abc::ICompoundProperty &prop, + const Alembic::Abc::PropertyHeader *prop_header, + const Alembic::Abc::ISampleSelector &selector, + const CDStreamConfig &config, + const char *velocity_name, + const float velocity_scale); typedef enum { ABC_UV_SCOPE_NONE, ABC_UV_SCOPE_LOOP, diff --git a/source/blender/io/alembic/intern/abc_reader_curves.cc b/source/blender/io/alembic/intern/abc_reader_curves.cc index 27ee35d1b39..688ba23333a 100644 --- a/source/blender/io/alembic/intern/abc_reader_curves.cc +++ b/source/blender/io/alembic/intern/abc_reader_curves.cc @@ -283,6 +283,8 @@ void AbcCurveReader::read_curve_sample(Curve *cu, Mesh *AbcCurveReader::read_mesh(Mesh *existing_mesh, const ISampleSelector &sample_sel, int /*read_flag*/, + const char * /*velocity_name*/, + const float /*velocity_scale*/, const char **err_str) { ICurvesSchema::Sample sample; diff --git a/source/blender/io/alembic/intern/abc_reader_curves.h b/source/blender/io/alembic/intern/abc_reader_curves.h index 075ed5ca6a1..11b23c8a8cf 100644 --- a/source/blender/io/alembic/intern/abc_reader_curves.h +++ b/source/blender/io/alembic/intern/abc_reader_curves.h @@ -45,7 +45,9 @@ class AbcCurveReader : public AbcObjectReader { void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); struct Mesh *read_mesh(struct Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &sample_sel, - int read_flag, + const int read_flag, + const char *velocity_name, + const float velocity_scale, const char **err_str); void read_curve_sample(Curve *cu, 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( diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.h b/source/blender/io/alembic/intern/abc_reader_mesh.h index 3329b723b77..d9f89cc8085 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.h +++ b/source/blender/io/alembic/intern/abc_reader_mesh.h @@ -42,7 +42,9 @@ class AbcMeshReader : public AbcObjectReader { struct Mesh *read_mesh(struct Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &sample_sel, - int read_flag, + const int read_flag, + const char *velocity_name, + const float velocity_scale, const char **err_str) override; bool topology_changed(Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &sample_sel) override; @@ -73,7 +75,9 @@ class AbcSubDReader : public AbcObjectReader { void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel); struct Mesh *read_mesh(struct Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &sample_sel, - int read_flag, + const int read_flag, + const char *velocity_name, + const float velocity_scale, const char **err_str); }; diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc index 9a5ffd04bd1..a6d46c4b42a 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.cc +++ b/source/blender/io/alembic/intern/abc_reader_object.cc @@ -167,6 +167,8 @@ Imath::M44d get_matrix(const IXformSchema &schema, const float time) struct Mesh *AbcObjectReader::read_mesh(struct Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &UNUSED(sample_sel), int UNUSED(read_flag), + const char *UNUSED(velocity_name), + const float UNUSED(velocity_scale), const char **UNUSED(err_str)) { return existing_mesh; diff --git a/source/blender/io/alembic/intern/abc_reader_object.h b/source/blender/io/alembic/intern/abc_reader_object.h index 89590b26b61..6e97f841a88 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.h +++ b/source/blender/io/alembic/intern/abc_reader_object.h @@ -50,6 +50,10 @@ struct ImportSettings { /* From MeshSeqCacheModifierData.read_flag */ int read_flag; + /* From CacheFile and MeshSeqCacheModifierData */ + std::string velocity_name; + float velocity_scale; + bool validate_meshes; bool always_add_cache_reader; @@ -65,6 +69,8 @@ struct ImportSettings { sequence_len(1), sequence_offset(0), read_flag(0), + velocity_name(""), + velocity_scale(1.0f), validate_meshes(false), always_add_cache_reader(false), cache_file(NULL) @@ -143,7 +149,9 @@ class AbcObjectReader { virtual struct Mesh *read_mesh(struct Mesh *mesh, const Alembic::Abc::ISampleSelector &sample_sel, - int read_flag, + const int read_flag, + const char *velocity_name, + const float velocity_scale, const char **err_str); virtual bool topology_changed(Mesh *existing_mesh, const Alembic::Abc::ISampleSelector &sample_sel); diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc index deb945b767c..63565b902f3 100644 --- a/source/blender/io/alembic/intern/alembic_capi.cc +++ b/source/blender/io/alembic/intern/alembic_capi.cc @@ -786,7 +786,9 @@ Mesh *ABC_read_mesh(CacheReader *reader, Mesh *existing_mesh, const float time, const char **err_str, - int read_flag) + const int read_flag, + const char *velocity_name, + const float velocity_scale) { AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str); if (abc_reader == nullptr) { @@ -794,7 +796,8 @@ Mesh *ABC_read_mesh(CacheReader *reader, } ISampleSelector sample_sel = sample_selector_for_time(time); - return abc_reader->read_mesh(existing_mesh, sample_sel, read_flag, err_str); + return abc_reader->read_mesh( + existing_mesh, sample_sel, read_flag, velocity_name, velocity_scale, err_str); } bool ABC_mesh_topology_changed( @@ -860,136 +863,3 @@ CacheReader *CacheReader_open_alembic_object(CacheArchiveHandle *handle, return reinterpret_cast<CacheReader *>(abc_reader); } - -/* ************************************************************************** */ - -static const PropertyHeader *get_property_header(const IPolyMeshSchema &schema, const char *name) -{ - const PropertyHeader *prop_header = schema.getPropertyHeader(name); - - if (prop_header) { - return prop_header; - } - - ICompoundProperty prop = schema.getArbGeomParams(); - - if (!has_property(prop, name)) { - return nullptr; - } - - return prop.getPropertyHeader(name); -} - -bool ABC_has_vec3_array_property_named(struct CacheReader *reader, const char *name) -{ - AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader); - - if (!abc_reader) { - return false; - } - - IObject iobject = abc_reader->iobject(); - - if (!iobject.valid()) { - return false; - } - - const ObjectHeader &header = iobject.getHeader(); - - if (!IPolyMesh::matches(header)) { - return false; - } - - IPolyMesh mesh(iobject, kWrapExisting); - IPolyMeshSchema schema = mesh.getSchema(); - - const PropertyHeader *prop_header = get_property_header(schema, name); - - if (!prop_header) { - return false; - } - - return IV3fArrayProperty::matches(prop_header->getMetaData()); -} - -static V3fArraySamplePtr get_velocity_prop(const IPolyMeshSchema &schema, - const ISampleSelector &iss, - const std::string &name) -{ - const PropertyHeader *prop_header = schema.getPropertyHeader(name); - - if (prop_header) { - const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(schema, name, 0); - return velocity_prop.getValue(iss); - } - - ICompoundProperty prop = schema.getArbGeomParams(); - - if (!has_property(prop, name)) { - return V3fArraySamplePtr(); - } - - const IV3fArrayProperty &velocity_prop = IV3fArrayProperty(prop, name, 0); - - if (velocity_prop) { - return velocity_prop.getValue(iss); - } - - return V3fArraySamplePtr(); -} - -int ABC_read_velocity_cache(CacheReader *reader, - const char *velocity_name, - const float time, - float velocity_scale, - int num_vertices, - float *r_vertex_velocities) -{ - AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader); - - if (!abc_reader) { - return -1; - } - - IObject iobject = abc_reader->iobject(); - - if (!iobject.valid()) { - return -1; - } - - const ObjectHeader &header = iobject.getHeader(); - - if (!IPolyMesh::matches(header)) { - return -1; - } - - IPolyMesh mesh(iobject, kWrapExisting); - IPolyMeshSchema schema = mesh.getSchema(); - ISampleSelector sample_sel(time); - const IPolyMeshSchema::Sample sample = schema.getValue(sample_sel); - - V3fArraySamplePtr velocities = get_velocity_prop(schema, sample_sel, velocity_name); - - if (!velocities) { - return -1; - } - - float vel[3]; - - int num_velocity_vectors = static_cast<int>(velocities->size()); - - if (num_velocity_vectors != num_vertices) { - return -1; - } - - for (size_t i = 0; i < velocities->size(); ++i) { - const Imath::V3f &vel_in = (*velocities)[i]; - copy_zup_from_yup(vel, vel_in.getValue()); - - mul_v3_fl(vel, velocity_scale); - - copy_v3_v3(r_vertex_velocities + i * 3, vel); - } - - return num_vertices; -} diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 54316e56867..61b14155dd0 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -26,6 +26,7 @@ #include "BLI_assert.h" #include "BLI_math_vector.h" +#include "BKE_attribute.h" #include "BKE_customdata.h" #include "BKE_lib_id.h" #include "BKE_material.h" @@ -219,7 +220,7 @@ void USDGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh) if (usd_export_context_.export_params.export_normals) { write_normals(mesh, usd_mesh); } - write_surface_velocity(context.object, mesh, usd_mesh); + write_surface_velocity(mesh, usd_mesh); /* TODO(Sybren): figure out what happens when the face groups change. */ if (frame_has_been_written_) { @@ -409,42 +410,25 @@ void USDGenericMeshWriter::write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_ usd_mesh.SetNormalsInterpolation(pxr::UsdGeomTokens->faceVarying); } -void USDGenericMeshWriter::write_surface_velocity(Object *object, - const Mesh *mesh, - pxr::UsdGeomMesh usd_mesh) +void USDGenericMeshWriter::write_surface_velocity(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh) { - /* Only velocities from the fluid simulation are exported. This is the most important case, - * though, as the baked mesh changes topology all the time, and thus computing the velocities - * at import time in a post-processing step is hard. */ - ModifierData *md = BKE_modifiers_findby_type(object, eModifierType_Fluidsim); - if (md == nullptr) { - return; - } + /* Export velocity attribute output by fluid sim, sequence cache modifier + * and geometry nodes. */ + CustomDataLayer *velocity_layer = BKE_id_attribute_find( + &mesh->id, "velocity", CD_PROP_FLOAT3, ATTR_DOMAIN_POINT); - /* Check that the fluid sim modifier is enabled and has useful data. */ - const bool use_render = (DEG_get_mode(usd_export_context_.depsgraph) == DAG_EVAL_RENDER); - const ModifierMode required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; - const Scene *scene = DEG_get_evaluated_scene(usd_export_context_.depsgraph); - if (!BKE_modifier_is_enabled(scene, md, required_mode)) { - return; - } - FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md); - if (!fsmd->fss || fsmd->fss->type != OB_FLUIDSIM_DOMAIN) { - return; - } - FluidsimSettings *fss = fsmd->fss; - if (!fss->meshVelocities) { + if (velocity_layer == nullptr) { return; } + const float(*velocities)[3] = reinterpret_cast<float(*)[3]>(velocity_layer->data); + /* Export per-vertex velocity vectors. */ pxr::VtVec3fArray usd_velocities; usd_velocities.reserve(mesh->totvert); - FluidVertexVelocity *mesh_velocities = fss->meshVelocities; - for (int vertex_idx = 0, totvert = mesh->totvert; vertex_idx < totvert; - ++vertex_idx, ++mesh_velocities) { - usd_velocities.push_back(pxr::GfVec3f(mesh_velocities->vel)); + for (int vertex_idx = 0, totvert = mesh->totvert; vertex_idx < totvert; ++vertex_idx) { + usd_velocities.push_back(pxr::GfVec3f(velocities[vertex_idx])); } pxr::UsdTimeCode timecode = get_export_time_code(); diff --git a/source/blender/io/usd/intern/usd_writer_mesh.h b/source/blender/io/usd/intern/usd_writer_mesh.h index 6345f2d4240..d60a6c4a59b 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.h +++ b/source/blender/io/usd/intern/usd_writer_mesh.h @@ -49,7 +49,7 @@ class USDGenericMeshWriter : public USDAbstractWriter { const MaterialFaceGroups &usd_face_groups); void write_uv_maps(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh); void write_normals(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh); - void write_surface_velocity(Object *object, const Mesh *mesh, pxr::UsdGeomMesh usd_mesh); + void write_surface_velocity(const Mesh *mesh, pxr::UsdGeomMesh usd_mesh); }; class USDMeshWriter : public USDGenericMeshWriter { diff --git a/source/blender/makesdna/DNA_fluid_defaults.h b/source/blender/makesdna/DNA_fluid_defaults.h index 95f5b8b66b0..4135c4d40a8 100644 --- a/source/blender/makesdna/DNA_fluid_defaults.h +++ b/source/blender/makesdna/DNA_fluid_defaults.h @@ -50,7 +50,6 @@ .tex_flags = NULL, \ .tex_range_field = NULL, \ .guide_parent = NULL, \ - .mesh_velocities = NULL, \ .effector_weights = NULL, /* #BKE_effector_add_weights. */ \ .p0 = {0.0f, 0.0f, 0.0f}, \ .p1 = {0.0f, 0.0f, 0.0f}, \ @@ -122,7 +121,6 @@ .mesh_smoothen_pos = 1, \ .mesh_smoothen_neg = 1, \ .mesh_scale = 2, \ - .totvert = 0, \ .mesh_generator = FLUID_DOMAIN_MESH_IMPROVED, \ .particle_type = 0, \ .particle_scale = 1, \ diff --git a/source/blender/makesdna/DNA_fluid_types.h b/source/blender/makesdna/DNA_fluid_types.h index 835af3c6ff8..0cbef540306 100644 --- a/source/blender/makesdna/DNA_fluid_types.h +++ b/source/blender/makesdna/DNA_fluid_types.h @@ -480,10 +480,6 @@ enum { SM_HRES_FULLSAMPLE = 2, }; -typedef struct FluidDomainVertexVelocity { - float vel[3]; -} FluidDomainVertexVelocity; - typedef struct FluidDomainSettings { /* -- Runtime-only fields (from here on). -- */ @@ -509,8 +505,6 @@ typedef struct FluidDomainSettings { struct GPUTexture *tex_flags; struct GPUTexture *tex_range_field; struct Object *guide_parent; - /** Vertex velocities of simulated fluid mesh. */ - struct FluidDomainVertexVelocity *mesh_velocities; struct EffectorWeights *effector_weights; /* Domain object data. */ @@ -607,9 +601,8 @@ typedef struct FluidDomainSettings { int mesh_smoothen_pos; int mesh_smoothen_neg; int mesh_scale; - int totvert; short mesh_generator; - char _pad6[6]; /* Unused. */ + char _pad6[2]; /* Unused. */ /* Secondary particle options. */ int particle_type; diff --git a/source/blender/makesdna/DNA_modifier_defaults.h b/source/blender/makesdna/DNA_modifier_defaults.h index 1b3dbd148df..5b2694f420b 100644 --- a/source/blender/makesdna/DNA_modifier_defaults.h +++ b/source/blender/makesdna/DNA_modifier_defaults.h @@ -419,10 +419,6 @@ .velocity_scale = 1.0f, \ .reader = NULL, \ .reader_object_path = "", \ - .vertex_velocities = NULL, \ - .num_vertices = 0, \ - .velocity_delta = 0.0f, \ - .last_lookup_time = 0.0f, \ } #define _DNA_DEFAULT_MirrorModifierData \ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 8520786a030..31daa778b03 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -2144,10 +2144,6 @@ enum { MOD_NORMALEDIT_MIX_MUL = 3, }; -typedef struct MeshCacheVertexVelocity { - float vel[3]; -} MeshCacheVertexVelocity; - typedef struct MeshSeqCacheModifierData { ModifierData modifier; @@ -2163,25 +2159,6 @@ typedef struct MeshSeqCacheModifierData { /* Runtime. */ struct CacheReader *reader; char reader_object_path[1024]; - - /* Vertex velocities read from the cache. The velocities are not automatically read during - * modifier execution, and therefore have to manually be read when needed. This is only used - * through the RNA for now. */ - struct MeshCacheVertexVelocity *vertex_velocities; - - /* The number of vertices of the Alembic mesh, set when the modifier is executed. */ - int num_vertices; - - /* Time (in frames or seconds) between two velocity samples. Automatically computed to - * scale the velocity vectors at render time for generating proper motion blur data. */ - float velocity_delta; - - /* Caches the scene time (in seconds) used to lookup data in the Alembic archive when the - * modifier was last executed. Used to access Alembic samples through the RNA. */ - float last_lookup_time; - - int _pad1; - void *_pad2; } MeshSeqCacheModifierData; /* MeshSeqCacheModifierData.read_flag */ diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 10e899b7ee3..90e77406f23 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -1242,22 +1242,6 @@ static void rna_Fluid_flowtype_set(struct PointerRNA *ptr, int value) #else -static void rna_def_fluid_mesh_vertices(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "FluidDomainVertexVelocity", NULL); - RNA_def_struct_ui_text(srna, "Fluid Mesh Velocity", "Velocity of a simulated fluid mesh"); - RNA_def_struct_ui_icon(srna, ICON_VERTEXSEL); - - prop = RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VELOCITY); - RNA_def_property_array(prop, 3); - RNA_def_property_float_sdna(prop, NULL, "vel"); - RNA_def_property_ui_text(prop, "Velocity", ""); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); -} - static void rna_def_fluid_domain_settings(BlenderRNA *brna) { StructRNA *srna; @@ -2019,14 +2003,6 @@ static void rna_def_fluid_domain_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Mesh generator", "Which particle level set generator to use"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Fluid_update"); - prop = RNA_def_property(srna, "mesh_vertices", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "mesh_velocities", "totvert"); - RNA_def_property_struct_type(prop, "FluidDomainVertexVelocity"); - RNA_def_property_ui_text( - prop, "Fluid Mesh Vertices", "Vertices of the fluid mesh generated by simulation"); - - rna_def_fluid_mesh_vertices(brna); - prop = RNA_def_property(srna, "use_mesh", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FLUID_DOMAIN_USE_MESH); RNA_def_property_ui_text(prop, "Use Mesh", "Enable fluid mesh (using amplification)"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index fb4fd4528d6..c99dfea524f 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1601,51 +1601,6 @@ static bool rna_Modifier_show_expanded_get(PointerRNA *ptr) return md->ui_expand_flag & UI_PANEL_DATA_EXPAND_ROOT; } -static int rna_MeshSequenceCacheModifier_has_velocity_get(PointerRNA *ptr) -{ -# ifdef WITH_ALEMBIC - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)ptr->data; - return ABC_has_vec3_array_property_named(mcmd->reader, mcmd->cache_file->velocity_name); -# else - return false; - UNUSED_VARS(ptr); -# endif -} - -static int rna_MeshSequenceCacheModifier_read_velocity_get(PointerRNA *ptr) -{ -# ifdef WITH_ALEMBIC - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)ptr->data; - - if (mcmd->num_vertices == 0) { - return 0; - } - - if (mcmd->vertex_velocities) { - MEM_freeN(mcmd->vertex_velocities); - } - - mcmd->vertex_velocities = MEM_mallocN(sizeof(MeshCacheVertexVelocity) * mcmd->num_vertices, - "Mesh Cache Velocities"); - - int num_read = ABC_read_velocity_cache(mcmd->reader, - mcmd->cache_file->velocity_name, - mcmd->last_lookup_time, - mcmd->velocity_scale * mcmd->velocity_delta, - mcmd->num_vertices, - (float *)mcmd->vertex_velocities); - - if (num_read == -1 || num_read != mcmd->num_vertices) { - return false; - } - - return true; -# else - return false; - UNUSED_VARS(ptr); -# endif -} - static bool rna_NodesModifier_node_group_poll(PointerRNA *UNUSED(ptr), PointerRNA value) { bNodeTree *ntree = value.data; @@ -6118,22 +6073,6 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna) RNA_define_lib_overridable(false); } -static void rna_def_mesh_cache_velocities(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "MeshCacheVertexVelocity", NULL); - RNA_def_struct_ui_text(srna, "Mesh Cache Velocity", "Velocity attribute of an Alembic mesh"); - RNA_def_struct_ui_icon(srna, ICON_VERTEXSEL); - - prop = RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VELOCITY); - RNA_def_property_array(prop, 3); - RNA_def_property_float_sdna(prop, NULL, "vel"); - RNA_def_property_ui_text(prop, "Velocity", ""); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); -} - static void rna_def_modifier_meshseqcache(BlenderRNA *brna) { StructRNA *srna; @@ -6190,26 +6129,6 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna) "Multiplier used to control the magnitude of the velocity vectors for time effects"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - /* -------------------------- Velocity Vectors -------------------------- */ - - prop = RNA_def_property(srna, "vertex_velocities", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "vertex_velocities", "num_vertices"); - RNA_def_property_struct_type(prop, "MeshCacheVertexVelocity"); - RNA_def_property_ui_text( - prop, "Fluid Mesh Vertices", "Vertices of the fluid mesh generated by simulation"); - - rna_def_mesh_cache_velocities(brna); - - prop = RNA_def_property(srna, "has_velocity", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_ui_text(prop, "Has Velocity Cache", ""); - RNA_def_property_boolean_funcs(prop, "rna_MeshSequenceCacheModifier_has_velocity_get", NULL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "read_velocity", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_ui_text(prop, "Read Velocity Cache", ""); - RNA_def_property_boolean_funcs(prop, "rna_MeshSequenceCacheModifier_read_velocity_get", NULL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_define_lib_overridable(false); } diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 259c1cb2417..bcaf294ec8b 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -105,10 +105,6 @@ static void freeData(ModifierData *md) mcmd->reader_object_path[0] = '\0'; BKE_cachefile_reader_free(mcmd->cache_file, &mcmd->reader); } - - if (mcmd->vertex_velocities) { - MEM_freeN(mcmd->vertex_velocities); - } } static bool isDisabled(const struct Scene *UNUSED(scene), @@ -233,11 +229,26 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * Mesh *result = NULL; switch (cache_file->type) { - case CACHEFILE_TYPE_ALEMBIC: + case CACHEFILE_TYPE_ALEMBIC: { # ifdef WITH_ALEMBIC - result = ABC_read_mesh(mcmd->reader, ctx->object, mesh, time, &err_str, mcmd->read_flag); + /* Time (in frames or seconds) between two velocity samples. Automatically computed to + * scale the velocity vectors at render time for generating proper motion blur data. */ + float velocity_scale = mcmd->velocity_scale; + if (mcmd->cache_file->velocity_unit == CACHEFILE_VELOCITY_UNIT_FRAME) { + velocity_scale *= FPS; + } + + result = ABC_read_mesh(mcmd->reader, + ctx->object, + mesh, + time, + &err_str, + mcmd->read_flag, + mcmd->cache_file->velocity_name, + velocity_scale); # endif break; + } case CACHEFILE_TYPE_USD: # ifdef WITH_USD result = USD_read_mesh( @@ -248,17 +259,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * break; } - mcmd->velocity_delta = 1.0f; - if (mcmd->cache_file->velocity_unit == CACHEFILE_VELOCITY_UNIT_SECOND) { - mcmd->velocity_delta /= FPS; - } - - mcmd->last_lookup_time = time; - - if (result != NULL) { - mcmd->num_vertices = result->totvert; - } - if (err_str) { BKE_modifier_set_error(ctx->object, md, "%s", err_str); } |