Commit: b5dcf746369e51c08285292cd78f621999dd09e9 Author: Kévin Dietrich Date: Mon Aug 3 03:28:04 2020 +0200 Branches: master https://developer.blender.org/rBb5dcf746369e51c08285292cd78f621999dd09e9
Cycles: add support for rendering deformation motion blur from Alembic caches. This patch adds the ability to render motion blur from Alembic caches. The motion blur data is derived from a velocity attribute whose name has to be defined by the user through the MeshSequenceCache modifier, with a default value of ".velocities", which is the standard name in Alembic for the velocity property, although other software may ignore it and write velocity with their own naming convention (e.g. "v" in Houdini). Furthermore, a property was added to define how the velocity vectors are interpreted with regard to time : frame or second. "Frame" means that the velocity is already scaled by the time step and we do not need to modify it for it to look proper. "Second" means that the unit the velocity was measured in is in seconds and so has to be scaled by some time step computed here as being the time between two frames (1 / FPS, which would be typical for a simulation). This appears to be common, and is the default behavior. Another property was added to control the scale of the velocity to further modify the look of the motion blur. Reviewed By: brecht, sybren Differential Revision: https://developer.blender.org/D2388 =================================================================== M intern/cycles/blender/blender_mesh.cpp M source/blender/blenkernel/intern/cachefile.c M source/blender/blenloader/intern/versioning_290.c M source/blender/editors/interface/interface_templates.c M source/blender/io/alembic/ABC_alembic.h M source/blender/io/alembic/intern/alembic_capi.cc M source/blender/makesdna/DNA_cachefile_types.h M source/blender/makesdna/DNA_modifier_types.h M source/blender/makesrna/intern/rna_cachefile.c M source/blender/makesrna/intern/rna_modifier.c M source/blender/modifiers/intern/MOD_meshsequencecache.c =================================================================== diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 49407799fcd..9043cd81293 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -923,6 +923,73 @@ static void create_subd_mesh(Scene *scene, /* Sync */ +static BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob, BL::Scene b_scene) +{ + BL::Object::modifiers_iterator b_mod; + + for (b_ob.modifiers.begin(b_mod); b_mod != b_ob.modifiers.end(); ++b_mod) { + if (!b_mod->is_a(&RNA_MeshSequenceCacheModifier)) { + continue; + } + + BL::MeshSequenceCacheModifier mesh_cache = BL::MeshSequenceCacheModifier(*b_mod); + + if (MeshSequenceCacheModifier_has_velocity_get(&mesh_cache.ptr)) { + return mesh_cache; + } + } + + return BL::MeshSequenceCacheModifier(PointerRNA_NULL); +} + +static void sync_mesh_cached_velocities(BL::Object &b_ob, + BL::Scene b_scene, + Scene *scene, + Mesh *mesh) +{ + if (scene->need_motion() == Scene::MOTION_NONE) + return; + + BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob, b_scene); + + if (!b_mesh_cache) { + return; + } + + /* Find or add attribute */ + float3 *P = &mesh->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); + } + + if (!MeshSequenceCacheModifier_read_velocity_get(&b_mesh_cache.ptr)) { + return; + } + + const size_t numverts = mesh->verts.size(); + + if (b_mesh_cache.vertex_velocities.length() != numverts) { + return; + } + + /* 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(BL::Object &b_ob, Scene *scene, Mesh *mesh) { if (scene->need_motion() == Scene::MOTION_NONE) @@ -1002,6 +1069,9 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, } } + /* cached velocities (e.g. from alembic archive) */ + sync_mesh_cached_velocities(b_ob, b_depsgraph.scene(), scene, mesh); + /* mesh fluid motion mantaflow */ sync_mesh_fluid_motion(b_ob, scene, mesh); @@ -1023,6 +1093,12 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, return; } + /* Cached motion blur already exported. */ + BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(b_ob, b_scene); + if (mesh_cache) { + return; + } + /* Skip if no vertices were exported. */ size_t numverts = mesh->verts.size(); if (numverts == 0) { diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index da9dab36044..9ad6ae84c5c 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -61,6 +61,8 @@ static void cache_file_init_data(ID *id) BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(cache_file, id)); cache_file->scale = 1.0f; + cache_file->velocity_unit = CACHEFILE_VELOCITY_UNIT_SECOND; + BLI_strncpy(cache_file->velocity_name, ".velocities", sizeof(cache_file->velocity_name)); } static void cache_file_copy_data(Main *UNUSED(bmain), diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c index b6caa018756..c4c697254bd 100644 --- a/source/blender/blenloader/intern/versioning_290.c +++ b/source/blender/blenloader/intern/versioning_290.c @@ -22,9 +22,11 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "DNA_brush_types.h" +#include "DNA_cachefile_types.h" #include "DNA_constraint_types.h" #include "DNA_genfile.h" #include "DNA_gpencil_modifier_types.h" @@ -427,5 +429,28 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Initialise additional velocity parameter for CacheFiles. */ + if (!DNA_struct_elem_find( + fd->filesdna, "MeshSeqCacheModifierData", "float", "velocity_scale")) { + for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) { + LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { + if (md->type == eModifierType_MeshSequenceCache) { + MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; + mcmd->velocity_scale = 1.0f; + mcmd->vertex_velocities = NULL; + mcmd->num_vertices = 0; + } + } + } + } + + if (!DNA_struct_elem_find(fd->filesdna, "CacheFile", "char", "velocity_unit")) { + for (CacheFile *cache_file = bmain->cachefiles.first; cache_file != NULL; + cache_file = cache_file->id.next) { + BLI_strncpy(cache_file->velocity_name, ".velocities", sizeof(cache_file->velocity_name)); + cache_file->velocity_unit = CACHEFILE_VELOCITY_UNIT_SECOND; + } + } } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index d3487b635ce..fcafa88a806 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -7348,6 +7348,9 @@ void uiTemplateCacheFile(uiLayout *layout, uiItemR(row, &fileptr, "scale", 0, IFACE_("Manual Scale"), ICON_NONE); } + uiItemR(layout, &fileptr, "velocity_name", 0, NULL, ICON_NONE); + uiItemR(layout, &fileptr, "velocity_unit", 0, NULL, ICON_NONE); + /* TODO: unused for now, so no need to expose. */ #if 0 row = uiLayoutRow(layout, false); diff --git a/source/blender/io/alembic/ABC_alembic.h b/source/blender/io/alembic/ABC_alembic.h index ddf75aa3258..67f8aeb0a67 100644 --- a/source/blender/io/alembic/ABC_alembic.h +++ b/source/blender/io/alembic/ABC_alembic.h @@ -128,6 +128,16 @@ struct CacheReader *CacheReader_open_alembic_object(struct AbcArchiveHandle *han 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 fps, + int num_vertices, + float *r_vertex_velocities); + #ifdef __cplusplus } #endif diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc index 7cde2d4fe73..89eb9ed41a1 100644 --- a/source/blender/io/alembic/intern/alembic_capi.cc +++ b/source/blender/io/alembic/intern/alembic_capi.cc @@ -22,6 +22,7 @@ #include <Alembic/AbcMaterial/IMaterial.h> +#include "abc_axis_conversion.h" #include "abc_reader_archive.h" #include "abc_reader_camera.h" #include "abc_reader_curves.h" @@ -70,7 +71,10 @@ #include "WM_api.h" #include "WM_types.h" +using Alembic::Abc::IV3fArrayProperty; using Alembic::Abc::ObjectHeader; +using Alembic::Abc::PropertyHeader; +using Alembic::Abc::V3fArraySamplePtr; using Alembic::AbcGeom::ICamera; using Alembic::AbcGeom::ICurves; using Alembic::AbcGeom::IFaceSet; @@ -79,9 +83,11 @@ using Alembic::AbcGeom::INuPatch; using Alembic::AbcGeom::IObject; using Alembic::AbcGeom::IPoints; using Alembic::AbcGeom::IPolyMesh; +using Alembic::AbcGeom::IPolyMeshSchema; using Alembic::AbcGeom::ISampleSelector; using Alembic::AbcGeom::ISubD; using Alembic::AbcGeom::IXform; +using Alembic::AbcGeom::kWrapExisting; using Alembic::AbcGeom::MetaData; using Alembic::AbcMaterial::IMaterial; @@ -859,3 +865,136 @@ CacheReader *CacheReader_open_alembic_object(AbcArchiveHandle *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 pro @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] https://lists.blender.org/mailman/listinfo/bf-blender-cvs
