Fix T69542: Corrective Smooth modifier breaks when drivers are involved

Previously the cache for the modifier would not be invalidated if
modifier settings were changed with drivers or keyframes.

Now we compare the current setting with the ones used to generate the
cache and invalidate the cache if they differ.

Reviewed By: Sybren

Differential Revision: http://developer.blender.org/D5694
This commit is contained in:
2019-09-25 16:45:05 +02:00
parent b393b13524
commit 9e62cca29d
5 changed files with 55 additions and 24 deletions

View File

@@ -5744,8 +5744,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
}
/* runtime only */
csmd->delta_cache = NULL;
csmd->delta_cache_num = 0;
csmd->delta_cache.deltas = NULL;
csmd->delta_cache.totverts = 0;
}
else if (md->type == eModifierType_MeshSequenceCache) {
MeshSeqCacheModifierData *msmcd = (MeshSeqCacheModifierData *)md;

View File

@@ -2022,7 +2022,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op)
is_bind = (csmd->bind_coords != NULL);
MEM_SAFE_FREE(csmd->bind_coords);
MEM_SAFE_FREE(csmd->delta_cache);
MEM_SAFE_FREE(csmd->delta_cache.deltas);
if (is_bind) {
/* toggle off */

View File

@@ -1594,6 +1594,19 @@ enum {
MOD_LAPLACIANSMOOTH_NORMALIZED = (1 << 5),
};
typedef struct CorrectiveSmoothDeltaCache {
/* delta's between the original positions and the smoothed positions */
float (*deltas)[3];
unsigned int totverts;
/* Value of settings when creating the cache.
* These are used to check if the cache should be recomputed. */
float lambda;
short repeat, flag;
char smooth_type, rest_source;
char _pad[2];
} CorrectiveSmoothDeltaCache;
typedef struct CorrectiveSmoothModifierData {
ModifierData modifier;
@@ -1612,11 +1625,8 @@ typedef struct CorrectiveSmoothModifierData {
/** MAX_VGROUP_NAME. */
char defgrp_name[64];
/* runtime-only cache (delta's between),
* delta's between the original positions and the smoothed positions */
float (*delta_cache)[3];
unsigned int delta_cache_num;
char _pad2[4];
/* runtime-only cache */
CorrectiveSmoothDeltaCache delta_cache;
} CorrectiveSmoothModifierData;
enum {

View File

@@ -1387,7 +1387,7 @@ static void rna_CorrectiveSmoothModifier_update(Main *bmain, Scene *scene, Point
{
CorrectiveSmoothModifierData *csmd = (CorrectiveSmoothModifierData *)ptr->data;
MEM_SAFE_FREE(csmd->delta_cache);
MEM_SAFE_FREE(csmd->delta_cache.deltas);
rna_Modifier_update(bmain, scene, ptr);
}

View File

@@ -70,7 +70,7 @@ static void initData(ModifierData *md)
csmd->defgrp_name[0] = '\0';
csmd->delta_cache = NULL;
csmd->delta_cache.deltas = NULL;
}
static void copyData(const ModifierData *md, ModifierData *target, const int flag)
@@ -84,14 +84,14 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla
tcsmd->bind_coords = MEM_dupallocN(csmd->bind_coords);
}
tcsmd->delta_cache = NULL;
tcsmd->delta_cache_num = 0;
tcsmd->delta_cache.deltas = NULL;
tcsmd->delta_cache.totverts = 0;
}
static void freeBind(CorrectiveSmoothModifierData *csmd)
{
MEM_SAFE_FREE(csmd->bind_coords);
MEM_SAFE_FREE(csmd->delta_cache);
MEM_SAFE_FREE(csmd->delta_cache.deltas);
csmd->bind_coords_num = 0;
}
@@ -502,6 +502,23 @@ static void calc_tangent_spaces(Mesh *mesh, float (*vertexCos)[3], float (*r_tan
#endif
}
static void store_cache_settings(CorrectiveSmoothModifierData *csmd)
{
csmd->delta_cache.lambda = csmd->lambda;
csmd->delta_cache.repeat = csmd->repeat;
csmd->delta_cache.flag = csmd->flag;
csmd->delta_cache.smooth_type = csmd->smooth_type;
csmd->delta_cache.rest_source = csmd->rest_source;
}
static bool cache_settings_equal(CorrectiveSmoothModifierData *csmd)
{
return (csmd->delta_cache.lambda == csmd->lambda && csmd->delta_cache.repeat == csmd->repeat &&
csmd->delta_cache.flag == csmd->flag &&
csmd->delta_cache.smooth_type == csmd->smooth_type &&
csmd->delta_cache.rest_source == csmd->rest_source);
}
/**
* This calculates #CorrectiveSmoothModifierData.delta_cache
* It's not run on every update (during animation for example).
@@ -519,14 +536,14 @@ static void calc_deltas(CorrectiveSmoothModifierData *csmd,
tangent_spaces = MEM_calloc_arrayN(numVerts, sizeof(float[3][3]), __func__);
if (csmd->delta_cache_num != numVerts) {
MEM_SAFE_FREE(csmd->delta_cache);
if (csmd->delta_cache.totverts != numVerts) {
MEM_SAFE_FREE(csmd->delta_cache.deltas);
}
/* allocate deltas if they have not yet been allocated, otherwise we will just write over them */
if (!csmd->delta_cache) {
csmd->delta_cache_num = numVerts;
csmd->delta_cache = MEM_malloc_arrayN(numVerts, sizeof(float[3]), __func__);
if (!csmd->delta_cache.deltas) {
csmd->delta_cache.totverts = numVerts;
csmd->delta_cache.deltas = MEM_malloc_arrayN(numVerts, sizeof(float[3]), __func__);
}
smooth_verts(csmd, mesh, dvert, defgrp_index, smooth_vertex_coords, numVerts);
@@ -544,7 +561,7 @@ static void calc_deltas(CorrectiveSmoothModifierData *csmd,
if (UNLIKELY(!invert_m3_m3(imat, tangent_spaces[i]))) {
transpose_m3_m3(imat, tangent_spaces[i]);
}
mul_v3_m3v3(csmd->delta_cache[i], imat, delta);
mul_v3_m3v3(csmd->delta_cache.deltas[i], imat, delta);
}
MEM_freeN(tangent_spaces);
@@ -563,6 +580,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
const bool force_delta_cache_update =
/* XXX, take care! if mesh data its self changes we need to forcefully recalculate deltas */
!cache_settings_equal(csmd) ||
((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO) &&
(((ID *)ob->data)->recalc & ID_RECALC_ALL));
@@ -627,10 +645,13 @@ static void correctivesmooth_modifier_do(ModifierData *md,
}
/* check to see if our deltas are still valid */
if (!csmd->delta_cache || (csmd->delta_cache_num != numVerts) || force_delta_cache_update) {
if (!csmd->delta_cache.deltas || (csmd->delta_cache.totverts != numVerts) ||
force_delta_cache_update) {
const float(*rest_coords)[3];
bool is_rest_coords_alloc = false;
store_cache_settings(csmd);
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
/* caller needs to do sanity check here */
csmd->bind_coords_num = numVerts;
@@ -661,7 +682,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
/* this could be a check, but at this point it _must_ be valid */
BLI_assert(csmd->bind_coords_num == numVerts && csmd->delta_cache);
BLI_assert(csmd->bind_coords_num == numVerts && csmd->delta_cache.deltas);
}
#ifdef DEBUG_TIME
@@ -688,7 +709,7 @@ static void correctivesmooth_modifier_do(ModifierData *md,
calc_tangent_ortho(tangent_spaces[i]);
#endif
mul_v3_m3v3(delta, tangent_spaces[i], csmd->delta_cache[i]);
mul_v3_m3v3(delta, tangent_spaces[i], csmd->delta_cache.deltas[i]);
add_v3_v3(vertexCos[i], delta);
}
@@ -703,8 +724,8 @@ static void correctivesmooth_modifier_do(ModifierData *md,
/* when the modifier fails to execute */
error:
MEM_SAFE_FREE(csmd->delta_cache);
csmd->delta_cache_num = 0;
MEM_SAFE_FREE(csmd->delta_cache.deltas);
csmd->delta_cache.totverts = 0;
}
static void deformVerts(ModifierData *md,