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:
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
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue