diff options
-rw-r--r-- | source/blender/blenkernel/BKE_modifier.h | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 20 | ||||
-rw-r--r-- | source/blender/editors/armature/meshlaplacian.c | 16 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 92 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_correctivesmooth.c | 27 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_meshdeform.c | 18 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_surfacedeform.c | 36 |
7 files changed, 130 insertions, 89 deletions
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index a375ed3044c..9f522c11733 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -403,6 +403,16 @@ void modifier_path_init(char *path, int path_maxlen, const char *name); const char *modifier_path_relbase(struct Main *bmain, struct Object *ob); const char *modifier_path_relbase_from_global(struct Object *ob); +/* Accessors of original/evaluated modifiers. */ + +/* For a given modifier data, get corresponding original one. + * If the modifier data is already original, return it as-is. */ +struct ModifierData *modifier_get_original(struct ModifierData *md); +struct ModifierData *modifier_get_evaluated( + struct Depsgraph* depsgraph, + struct Object *object, + struct ModifierData *md); + /* wrappers for modifier callbacks that ensure valid normals */ struct Mesh *modwrap_applyModifier( diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index fe955ced5f5..8f52e579a91 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -885,3 +885,23 @@ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval, con return me; } + +ModifierData *modifier_get_original(ModifierData *md) +{ + if (md->orig_modifier_data == NULL) { + return md; + } + return md->orig_modifier_data; +} + +struct ModifierData *modifier_get_evaluated( + Depsgraph* depsgraph, + Object *object, + ModifierData *md) +{ + Object *object_eval = DEG_get_evaluated_object(depsgraph, object); + if (object_eval == object) { + return md; + } + return modifiers_findByName(object_eval, md->name); +} diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 34fea2e0996..66bd7a8db80 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -1577,6 +1577,8 @@ void ED_mesh_deform_bind_callback( MeshDeformModifierData *mmd, Mesh *cagemesh, float *vertexcos, int totvert, float cagemat[4][4]) { + MeshDeformModifierData *mmd_orig = + (MeshDeformModifierData *)modifier_get_original(&mmd->modifier); MeshDeformBind mdb; MVert *mvert; int a; @@ -1602,23 +1604,23 @@ void ED_mesh_deform_bind_callback( mul_v3_m4v3(mdb.vertexcos[a], mdb.cagemat, vertexcos + a * 3); /* solve */ - harmonic_coordinates_bind(mmd, &mdb); + harmonic_coordinates_bind(mmd_orig, &mdb); /* assign bind variables */ - mmd->bindcagecos = (float *)mdb.cagecos; - mmd->totvert = mdb.totvert; - mmd->totcagevert = mdb.totcagevert; - copy_m4_m4(mmd->bindmat, mmd->object->obmat); + mmd_orig->bindcagecos = (float *)mdb.cagecos; + mmd_orig->totvert = mdb.totvert; + mmd_orig->totcagevert = mdb.totcagevert; + copy_m4_m4(mmd_orig->bindmat, mmd_orig->object->obmat); /* transform bindcagecos to world space */ for (a = 0; a < mdb.totcagevert; a++) - mul_m4_v3(mmd->object->obmat, mmd->bindcagecos + a * 3); + mul_m4_v3(mmd_orig->object->obmat, mmd_orig->bindcagecos + a * 3); /* free */ MEM_freeN(mdb.vertexcos); /* compact weights */ - modifier_mdef_compact_influences((ModifierData *)mmd); + modifier_mdef_compact_influences((ModifierData *)mmd_orig); end_progress_bar(); waitcursor(0); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index c3a562df037..1944d2989ac 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -93,23 +93,38 @@ static void modifier_skin_customdata_delete(struct Object *ob); /******************************** API ****************************/ -static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Scene *scene, Object *ob) +static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *ob) { + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); + BKE_object_eval_reset(ob_eval); if (ob->type == OB_MESH) { - Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene, ob, &CD_MASK_BAREMESH); + Mesh *me_eval = mesh_create_eval_final_view(depsgraph, scene_eval, ob_eval, &CD_MASK_BAREMESH); BKE_id_free(NULL, me_eval); } else if (ob->type == OB_LATTICE) { - BKE_lattice_modifiers_calc(depsgraph, scene, ob); + BKE_lattice_modifiers_calc(depsgraph, scene_eval, ob_eval); } else if (ob->type == OB_MBALL) { - BKE_displist_make_mball(depsgraph, scene, ob); + BKE_displist_make_mball(depsgraph, scene_eval, ob_eval); } else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - BKE_displist_make_curveTypes(depsgraph, scene, ob, false, false, NULL); + BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false, NULL); } } +static void object_force_modifier_bind_simple_options( + Depsgraph *depsgraph, + Object *object, + ModifierData *md) +{ + ModifierData *md_eval = (ModifierData *)modifier_get_evaluated(depsgraph, object, md); + const int mode = md_eval->mode; + md_eval->mode |= eModifierMode_Realtime; + object_force_modifier_update_for_bind(depsgraph, object); + md_eval->mode = mode; +} + ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type) { ModifierData *md = NULL, *new_md = NULL; @@ -1926,19 +1941,17 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) csmd->bind_coords_num = 0; } else { - /* signal to modifier to recalculate */ - csmd->bind_coords_num = (unsigned int)-1; + /* Signal to modifier to recalculate. */ + CorrectiveSmoothModifierData *csmd_eval = + (CorrectiveSmoothModifierData *)modifier_get_evaluated(depsgraph, ob, &csmd->modifier); + csmd_eval->bind_coords_num = (unsigned int)-1; /* Force modifier to run, it will call binding routine * (this has to happen outside of depsgraph evaluation). */ - const int mode = csmd->modifier.mode; - csmd->modifier.mode |= eModifierMode_Realtime; - object_force_modifier_update_for_bind(depsgraph, scene, ob); - csmd->modifier.mode = mode; + object_force_modifier_bind_simple_options(depsgraph, ob, &csmd->modifier); } - /* We need ID_RECALC_COPY_ON_WRITE to ensure (un)binding is flushed to CoW copies of the object... */ - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; @@ -1979,7 +1992,6 @@ static bool meshdeform_poll(bContext *C) static int meshdeform_bind_exec(bContext *C, wmOperator *op) { Depsgraph *depsgraph = CTX_data_depsgraph(C); - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); MeshDeformModifierData *mmd = (MeshDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_MeshDeform); @@ -2002,16 +2014,14 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) } else { /* Force modifier to run, it will call binding routine (this has to happen outside of depsgraph evaluation). */ - const int mode = mmd->modifier.mode; - mmd->modifier.mode |= eModifierMode_Realtime; - mmd->bindfunc = ED_mesh_deform_bind_callback; - object_force_modifier_update_for_bind(depsgraph, scene, ob); - mmd->modifier.mode = mode; - mmd->bindfunc = NULL; + MeshDeformModifierData *mmd_eval = + (MeshDeformModifierData *)modifier_get_evaluated(depsgraph, ob, &mmd->modifier); + mmd_eval->bindfunc = ED_mesh_deform_bind_callback; + object_force_modifier_bind_simple_options(depsgraph, ob, &mmd->modifier); + mmd_eval->bindfunc = NULL; } - /* We need ID_RECALC_COPY_ON_WRITE to ensure (un)binding is flushed to CoW copies of the object... */ - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; } @@ -2188,7 +2198,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) if (free) { BKE_ocean_free_modifier_cache(omd); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; } @@ -2288,7 +2298,6 @@ static bool laplaciandeform_poll(bContext *C) static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); LaplacianDeformModifierData *lmd = (LaplacianDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_LaplacianDeform); @@ -2304,15 +2313,25 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) lmd->flag |= MOD_LAPLACIANDEFORM_BIND; } + LaplacianDeformModifierData *lmd_eval = + (LaplacianDeformModifierData *)modifier_get_evaluated(depsgraph, ob, &lmd->modifier); + lmd_eval->flag = lmd->flag; + /* Force modifier to run, it will call binding routine * (this has to happen outside of depsgraph evaluation). */ - const int mode = lmd->modifier.mode; - lmd->modifier.mode |= eModifierMode_Realtime; - object_force_modifier_update_for_bind(depsgraph, scene, ob); - lmd->modifier.mode = mode; + object_force_modifier_bind_simple_options(depsgraph, ob, &lmd->modifier); - /* We need ID_RECALC_COPY_ON_WRITE to ensure (un)binding is flushed to CoW copies of the object... */ - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + /* This is hard to know from the modifier itself whether the evaluation is + * happening for binding or not. So we copy all the required data here. */ + lmd->total_verts = lmd_eval->total_verts; + if (lmd_eval->vertexco == NULL) { + MEM_SAFE_FREE(lmd->vertexco); + } + else { + lmd->vertexco = MEM_dupallocN(lmd_eval->vertexco); + } + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; } @@ -2351,7 +2370,6 @@ static bool surfacedeform_bind_poll(bContext *C) static int surfacedeform_bind_exec(bContext *C, wmOperator *op) { - Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); Depsgraph *depsgraph = CTX_data_depsgraph(C); SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)edit_modifier_property_get(op, ob, eModifierType_SurfaceDeform); @@ -2367,15 +2385,15 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op) smd->flags |= MOD_SDEF_BIND; } + SurfaceDeformModifierData *smd_eval = + (SurfaceDeformModifierData *)modifier_get_evaluated(depsgraph, ob, &smd->modifier); + smd_eval->flags = smd->flags; + /* Force modifier to run, it will call binding routine * (this has to happen outside of depsgraph evaluation). */ - const int mode = smd->modifier.mode; - smd->modifier.mode |= eModifierMode_Realtime; - object_force_modifier_update_for_bind(depsgraph, scene, ob); - smd->modifier.mode = mode; + object_force_modifier_bind_simple_options(depsgraph, ob, &smd->modifier); - /* We need ID_RECALC_COPY_ON_WRITE to ensure (un)binding is flushed to CoW copies of the object... */ - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); return OPERATOR_FINISHED; } diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index ac1c0d46d7b..d9e6ed78070 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -45,6 +45,9 @@ #include "BLI_strict_flags.h" +#include "DEG_depsgraph_query.h" + + // #define DEBUG_TIME #include "PIL_time.h" @@ -558,7 +561,7 @@ static void calc_deltas( static void correctivesmooth_modifier_do( - ModifierData *md, Object *ob, Mesh *mesh, + ModifierData *md, Depsgraph *depsgraph, Object *ob, Mesh *mesh, float (*vertexCos)[3], unsigned int numVerts, struct BMEditMesh *em) { @@ -580,10 +583,20 @@ static void correctivesmooth_modifier_do( /* signal to recalculate, whoever sets MUST also free bind coords */ (csmd->bind_coords_num == (unsigned int)-1)) { - BLI_assert(csmd->bind_coords == NULL); - csmd->bind_coords = MEM_dupallocN(vertexCos); - csmd->bind_coords_num = numVerts; - BLI_assert(csmd->bind_coords != NULL); + if (DEG_is_active(depsgraph)) { + BLI_assert(csmd->bind_coords == NULL); + csmd->bind_coords = MEM_dupallocN(vertexCos); + csmd->bind_coords_num = numVerts; + BLI_assert(csmd->bind_coords != NULL); + /* Copy bound data to the original modifier. */ + CorrectiveSmoothModifierData *csmd_orig = + (CorrectiveSmoothModifierData *)modifier_get_original(&csmd->modifier); + csmd_orig->bind_coords = MEM_dupallocN(csmd->bind_coords); + csmd_orig->bind_coords_num = csmd->bind_coords_num; + } + else { + modifier_setError(md, "Attempt to bind from inactive dependency graph"); + } } if (UNLIKELY(use_only_smooth)) { @@ -711,7 +724,7 @@ static void deformVerts( { Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false); - correctivesmooth_modifier_do(md, ctx->object, mesh_src, vertexCos, (unsigned int)numVerts, NULL); + correctivesmooth_modifier_do(md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (unsigned int)numVerts, NULL); if (mesh_src != mesh) { BKE_id_free(NULL, mesh_src); @@ -725,7 +738,7 @@ static void deformVertsEM( { Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, editData, mesh, NULL, numVerts, false, false); - correctivesmooth_modifier_do(md, ctx->object, mesh_src, vertexCos, (unsigned int)numVerts, editData); + correctivesmooth_modifier_do(md, ctx->depsgraph, ctx->object, mesh_src, vertexCos, (unsigned int)numVerts, editData); if (mesh_src != mesh) { BKE_id_free(NULL, mesh_src); diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 310b05d4580..7ae03cc43f3 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -298,14 +298,6 @@ static void meshdeformModifier_do( */ Object *ob_target = mmd->object; cagemesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); -#if 0 /* This shall not be needed if we always get evaluated target object... */ - if (cagemesh == NULL && mmd->bindcagecos == NULL && ob == DEG_get_original_object(ob)) { - /* Special case, binding happens outside of depsgraph evaluation, so we can build our own - * target mesh if needed. */ - cagemesh = mesh_create_eval_final_view(ctx->depsgraph, DEG_get_input_scene(ctx->depsgraph), mmd->object, &CD_MASK_BAREMESH); - free_cagemesh = cagemesh != NULL; - } -#endif if (cagemesh == NULL) { modifier_setError(md, "Cannot get mesh from cage object"); return; @@ -321,13 +313,11 @@ static void meshdeformModifier_do( /* bind weights if needed */ if (!mmd->bindcagecos) { /* progress bar redraw can make this recursive .. */ + if (!DEG_is_active(ctx->depsgraph)) { + modifier_setError(md, "Attempt to bind from inactive dependency graph"); + goto finally; + } if (!recursive_bind_sentinel) { - if (ob != DEG_get_original_object(ob)) { - BLI_assert(!"Trying to bind inside of depsgraph evaluation"); - modifier_setError(md, "Trying to bind inside of depsgraph evaluation"); - goto finally; - } - recursive_bind_sentinel = 1; mmd->bindfunc(mmd, cagemesh, (float *)vertexCos, numVerts, cagemat); recursive_bind_sentinel = 0; diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 44307b4271e..46f4f9c78e9 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -1124,7 +1124,7 @@ static void deformVert( static void surfacedeformModifier_do( ModifierData *md, - const ModifierEvalContext *UNUSED(ctx), + const ModifierEvalContext *ctx, float (*vertexCos)[3], unsigned int numverts, Object *ob) { SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md; @@ -1133,30 +1133,19 @@ static void surfacedeformModifier_do( /* Exit function if bind flag is not set (free bind data if any). */ if (!(smd->flags & MOD_SDEF_BIND)) { - /* Note: with new CoW system, we expect unbinding to be done by a special call from main thread, - * outside of depsgraph evaluation (see object_force_modifier_update_for_bind() in object_modifier.c). */ if (smd->verts != NULL) { - if (ob != DEG_get_original_object(ob)) { - BLI_assert(!"Trying to unbind inside of depsgraph evaluation"); - modifier_setError(md, "Trying to unbind inside of depsgraph evaluation"); - } - else { - freeData(md); + if (!DEG_is_active(ctx->depsgraph)) { + modifier_setError(md, "Attempt to bind from inactive dependency graph"); + return; } + ModifierData *md_orig = modifier_get_original(md); + freeData(md_orig); } return; } Object *ob_target = smd->target; target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); -#if 0 /* Should not be needed anymore since we always get that mesh from eval object ? */ - if (target == NULL && smd->verts == NULL && ob == DEG_get_original_object(ob)) { - /* Special case, binding happens outside of depsgraph evaluation, so we can build our own - * target mesh if needed. */ - target = mesh_create_eval_final_view(ctx->depsgraph, DEG_get_input_scene(ctx->depsgraph), smd->target, CD_MASK_BAREMESH); - free_target = target != NULL; - } -#endif if (!target) { modifier_setError(md, "No valid target mesh"); return; @@ -1166,20 +1155,19 @@ static void surfacedeformModifier_do( tnumpoly = target->totpoly; /* If not bound, execute bind. */ - /* Note: with new CoW system, we expect binding to be done by a special call from main thread, - * outside of depsgraph evaluation (see object_force_modifier_update_for_bind() in object_modifier.c). */ if (smd->verts == NULL) { - if (ob != DEG_get_original_object(ob)) { - BLI_assert(!"Trying to bind inside of depsgraph evaluation"); - modifier_setError(md, "Trying to bind inside of depsgraph evaluation"); + if (!DEG_is_active(ctx->depsgraph)) { + modifier_setError(md, "Attempt to unbind from inactive dependency graph"); return; } + + SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)modifier_get_original(md); float tmp_mat[4][4]; invert_m4_m4(tmp_mat, ob->obmat); - mul_m4_m4m4(smd->mat, tmp_mat, ob_target->obmat); + mul_m4_m4m4(smd_orig->mat, tmp_mat, ob_target->obmat); - if (!surfacedeformBind(smd, vertexCos, numverts, tnumpoly, tnumverts, target)) { + if (!surfacedeformBind(smd_orig, vertexCos, numverts, tnumpoly, tnumverts, target)) { smd->flags &= ~MOD_SDEF_BIND; } /* Early abort, this is binding 'call', no need to perform whole evaluation. */ |