From 6672cbeb236444541037e728759792b1208df0da Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Tue, 29 Dec 2020 14:43:12 +0100 Subject: Fix T84202: Sculpt lasso mask crash after remesh. 'Caused'/revealed by rBd29a720c45e5: Operators that fully re-create the mesh would previously rely on `sculpt_update_object` called from update code to get required sculpt-specific data layers re-added to the new mesh. Now instead put all code adding data to orig mesh for sculpt purpose into a new util function (`BKE_sculpt_ensure_orig_mesh_data`), and call that function when entering sculpt mode, and from voxel remesher code. This is contonuing effort to more clearly separate orig data from evaluated data handling/usage in sculpt code. TODO: there are likely other code paths that would need to call that new function? Reviewers: @sergey, @pablodp606 Subscribers: --- source/blender/editors/object/object_remesh.c | 4 +++ source/blender/editors/sculpt_paint/sculpt.c | 50 ++++++++------------------- 2 files changed, 18 insertions(+), 36 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 058c34fb977..d560d347217 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -190,6 +190,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) } if (ob->mode == OB_MODE_SCULPT) { + BKE_sculpt_ensure_orig_mesh_data(CTX_data_scene(C), ob); ED_sculpt_undo_geometry_end(ob); } @@ -645,6 +646,7 @@ typedef struct QuadriFlowJob { short *stop, *do_update; float *progress; + Scene *scene; int target_faces; int seed; bool use_mesh_symmetry; @@ -892,6 +894,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update } if (ob->mode == OB_MODE_SCULPT) { + BKE_sculpt_ensure_orig_mesh_data(qj->scene, ob); ED_sculpt_undo_geometry_end(ob); } @@ -935,6 +938,7 @@ static int quadriflow_remesh_exec(bContext *C, wmOperator *op) QuadriFlowJob *job = MEM_mallocN(sizeof(QuadriFlowJob), "QuadriFlowJob"); job->owner = CTX_data_active_object(C); + job->scene = CTX_data_scene(C); job->target_faces = RNA_int_get(op->ptr, "target_faces"); job->seed = RNA_int_get(op->ptr, "seed"); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 7b3dc5cd8e3..5070dba14ea 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -8257,14 +8257,23 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot) /**** Toggle operator for turning sculpt mode on or off ****/ -/** \warning Expects a fully evaluated depsgraph. */ -static void sculpt_init_session(Depsgraph *depsgraph, Scene *scene, Object *ob) +static void sculpt_init_session(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob) { /* Create persistent sculpt mode data. */ BKE_sculpt_toolsettings_data_ensure(scene); + /* Create sculpt mode session data. */ + if (ob->sculpt != NULL) { + BKE_sculptsession_free(ob); + } ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); ob->sculpt->mode_type = OB_MODE_SCULPT; + + BKE_sculpt_ensure_orig_mesh_data(scene, ob); + + BKE_scene_graph_evaluated_ensure(depsgraph, bmain); + + /* This function expects a fully evaluated depsgraph. */ BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false, false); /* Here we can detect geometry that was just added to Sculpt Mode as it has the @@ -8299,40 +8308,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain, /* Enter sculpt mode. */ ob->mode |= mode_flag; - MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); - - /* Create sculpt mode session data. */ - if (ob->sculpt) { - BKE_sculptsession_free(ob); - } - - /* Copy the current mesh visibility to the Face Sets. */ - BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(me); - - /* Mask layer is required for Multires. */ - BKE_sculpt_mask_layers_ensure(ob, mmd); - - /* Tessfaces aren't used and will become invalid. */ - BKE_mesh_tessface_clear(me); - - /* We always need to flush updates from depsgraph here, since at the very least - * `BKE_sculpt_face_sets_ensure_from_base_mesh_visibility()` will have updated some data layer of - * the mesh. - * - * All known potential sources of updates: - * - Addition of, or changes to, the `CD_SCULPT_FACE_SETS` data layer - * (`BKE_sculpt_face_sets_ensure_from_base_mesh_visibility`). - * - Addition of a `CD_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`). - * - Object has any active modifier (modifier stack can be different in Sculpt mode). - * - Multires: - * + Differences of subdiv levels between sculpt and object modes - * (`mmd->sculptlvl != mmd->lvl`). - * + Addition of a `CD_GRID_PAINT_MASK` data layer (`BKE_sculpt_mask_layers_ensure`). - */ - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - BKE_scene_graph_evaluated_ensure(depsgraph, bmain); - - sculpt_init_session(depsgraph, scene, ob); + sculpt_init_session(bmain, depsgraph, scene, ob); if (!(fabsf(ob->scale[0] - ob->scale[1]) < 1e-4f && fabsf(ob->scale[1] - ob->scale[2]) < 1e-4f)) { @@ -8351,6 +8327,8 @@ void ED_object_sculptmode_enter_ex(Main *bmain, /* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes, * As long as no data was added that is not supported. */ if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) { + MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); + const char *message_unsupported = NULL; if (me->totloop != me->totpoly * 3) { message_unsupported = TIP_("non-triangle face"); -- cgit v1.2.3