Fix T71981: Alembic vertex interpolation can jumble mesh

Add an option to disable Alembic vertex interpolation.
Bump subversion from 5 to 6.

Alembic stores mesh samples at specific time keys; when a frame in
Blender maps to a timecode between two samples, Blender will interpolate
the mesh vertex positions. This interpolation only happens when the mesh
has a constant topology, but sometimes this was not detected properly
when the vertices change order, but the number of mesh elements remains
the same. This would result in a mesh with jumbled up vertices (T71981).
With this patch, users have the ability to disable vertex interpolation.

An alternative would be to have better detection of topology changes,
but that that'll cause a considerable slowdown.

Maniphest Tasks: T71981

Differential Revision: https://developer.blender.org/D9041
This commit is contained in:
Sybren A. Stüvel 2020-09-29 14:34:01 +02:00 committed by Sybren A. Stüvel
parent 5845c06a63
commit bab2260b59
Notes: blender-bot 2023-02-14 05:44:22 +01:00
Referenced by commit fcc3227efd, Fix T86654: wrong Vertex Interpolation option default when importing alembic caches
Referenced by issue #94013, Bad frames importing Alembic file.
Referenced by issue #86654, Bad motion blur from alembic animation import in v2.92. Works as expected in v2.83.13
Referenced by issue #71981, Alembic override frame causes fluid sim mesh to have artifacts
9 changed files with 58 additions and 24 deletions

View File

@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 5
#define BLENDER_FILE_SUBVERSION 6
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file

View File

@ -724,18 +724,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
if (!MAIN_VERSION_ATLEAST(bmain, 291, 6)) {
/* Darken Inactive Overlay. */
if (!DNA_struct_elem_find(fd->filesdna, "View3DOverlay", "float", "fade_alpha")) {
for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
@ -759,5 +748,30 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
mesh->symmetry = mesh->editflag & (ME_SYMMETRY_X | ME_SYMMETRY_Y | ME_SYMMETRY_Z);
}
}
/* Alembic importer: allow vertex interpolation by default. */
for (Object *object = bmain->objects.first; object != NULL; object = object->id.next) {
LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
if (md->type != eModifierType_MeshSequenceCache) {
continue;
}
MeshSeqCacheModifierData *data = (MeshSeqCacheModifierData *)md;
data->read_flag |= MOD_MESHSEQ_INTERPOLATE_VERTICES;
}
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
}
}

View File

@ -66,6 +66,7 @@ struct CDStreamConfig {
float weight;
float time;
bool use_vertex_interpolation;
Alembic::AbcGeom::index_t index;
Alembic::AbcGeom::index_t ceil_index;

View File

@ -155,8 +155,8 @@ static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data)
MVert *mverts = config.mvert;
const P3fArraySamplePtr &positions = mesh_data.positions;
if (config.weight != 0.0f && mesh_data.ceil_positions != NULL &&
mesh_data.ceil_positions->size() == positions->size()) {
if (config.use_vertex_interpolation && config.weight != 0.0f &&
mesh_data.ceil_positions != NULL && mesh_data.ceil_positions->size() == positions->size()) {
read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight);
return;
}
@ -457,7 +457,7 @@ static void read_mesh_sample(const std::string &iobject_full_name,
}
}
CDStreamConfig get_config(Mesh *mesh)
CDStreamConfig get_config(Mesh *mesh, const bool use_vertex_interpolation)
{
CDStreamConfig config;
@ -471,6 +471,7 @@ CDStreamConfig get_config(Mesh *mesh)
config.totpoly = mesh->totpoly;
config.loopdata = &mesh->ldata;
config.add_customdata_cb = add_customdata_cb;
config.use_vertex_interpolation = use_vertex_interpolation;
return config;
}
@ -646,7 +647,9 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
}
}
CDStreamConfig config = get_config(new_mesh ? new_mesh : existing_mesh);
Mesh *mesh_to_export = new_mesh ? new_mesh : existing_mesh;
const bool use_vertex_interpolation = read_flag & MOD_MESHSEQ_INTERPOLATE_VERTICES;
CDStreamConfig config = get_config(mesh_to_export, use_vertex_interpolation);
config.time = sample_sel.getRequestedTime();
config.modifier_error_message = err_str;
@ -936,11 +939,13 @@ Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh,
}
/* Only read point data when streaming meshes, unless we need to create new ones. */
CDStreamConfig config = get_config(new_mesh ? new_mesh : existing_mesh);
Mesh *mesh_to_export = new_mesh ? new_mesh : existing_mesh;
const bool use_vertex_interpolation = read_flag & MOD_MESHSEQ_INTERPOLATE_VERTICES;
CDStreamConfig config = get_config(mesh_to_export, use_vertex_interpolation);
config.time = sample_sel.getRequestedTime();
read_subd_sample(m_iobject.getFullName(), &settings, m_schema, sample_sel, config);
return config.mesh;
return mesh_to_export;
}
} // namespace blender::io::alembic

View File

@ -81,6 +81,6 @@ void read_mverts(MVert *mverts,
const Alembic::AbcGeom::P3fArraySamplePtr positions,
const Alembic::AbcGeom::N3fArraySamplePtr normals);
CDStreamConfig get_config(struct Mesh *mesh);
CDStreamConfig get_config(struct Mesh *mesh, bool use_vertex_interpolation);
} // namespace blender::io::alembic

View File

@ -27,6 +27,7 @@
#include "abc_util.h"
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "BKE_customdata.h"
@ -125,7 +126,7 @@ void read_points_sample(const IPointsSchema &schema,
struct Mesh *AbcPointsReader::read_mesh(struct Mesh *existing_mesh,
const ISampleSelector &sample_sel,
int /*read_flag*/,
int read_flag,
const char **err_str)
{
IPointsSchema::Sample sample;
@ -150,10 +151,12 @@ struct Mesh *AbcPointsReader::read_mesh(struct Mesh *existing_mesh,
new_mesh = BKE_mesh_new_nomain(positions->size(), 0, 0, 0, 0);
}
CDStreamConfig config = get_config(new_mesh ? new_mesh : existing_mesh);
Mesh *mesh_to_export = new_mesh ? new_mesh : existing_mesh;
const bool use_vertex_interpolation = read_flag & MOD_MESHSEQ_INTERPOLATE_VERTICES;
CDStreamConfig config = get_config(mesh_to_export, use_vertex_interpolation);
read_points_sample(m_schema, sample_sel, config);
return new_mesh ? new_mesh : existing_mesh;
return mesh_to_export;
}
} // namespace blender::io::alembic

View File

@ -2121,6 +2121,11 @@ enum {
MOD_MESHSEQ_READ_POLY = (1 << 1),
MOD_MESHSEQ_READ_UV = (1 << 2),
MOD_MESHSEQ_READ_COLOR = (1 << 3),
/* Allow interpolation of mesh vertex positions. There is a heuristic to avoid interpolation when
* the mesh topology changes, but this heuristic sometimes fails. In these cases, users can
* disable interpolation with this flag. */
MOD_MESHSEQ_INTERPOLATE_VERTICES = (1 << 4),
};
typedef struct SDefBind {

View File

@ -6134,7 +6134,12 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "read_flag");
RNA_def_property_enum_items(prop, read_flag_items);
RNA_def_property_ui_text(prop, "Read Data", "Data to read from the cache");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "use_vertex_interpolation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "read_flag", MOD_MESHSEQ_INTERPOLATE_VERTICES);
RNA_def_property_ui_text(
prop, "Vertex Interpolation", "Allow interpolation of vertex positions.");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "velocity_scale", PROP_FLOAT, PROP_NONE);

View File

@ -66,7 +66,7 @@ static void initData(ModifierData *md)
mcmd->cache_file = NULL;
mcmd->object_path[0] = '\0';
mcmd->read_flag = MOD_MESHSEQ_READ_ALL;
mcmd->read_flag = MOD_MESHSEQ_READ_ALL | MOD_MESHSEQ_INTERPOLATE_VERTICES;
mcmd->velocity_scale = 1.0f;
mcmd->vertex_velocities = NULL;
mcmd->num_vertices = 0;
@ -238,6 +238,7 @@ static void panel_draw(const bContext *C, Panel *panel)
if (RNA_enum_get(&ob_ptr, "type") == OB_MESH) {
uiItemR(layout, ptr, "read_data", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
uiItemR(layout, ptr, "use_vertex_interpolation", 0, NULL, ICON_NONE);
}
uiItemR(layout, ptr, "velocity_scale", 0, NULL, ICON_NONE);