[Bf-blender-cvs] [6672cbeb236] master: Fix T84202: Sculpt lasso mask crash after remesh.

Bastien Montagne noreply at git.blender.org
Wed Jan 6 16:47:14 CET 2021


Commit: 6672cbeb236444541037e728759792b1208df0da
Author: Bastien Montagne
Date:   Tue Dec 29 14:43:12 2020 +0100
Branches: master
https://developer.blender.org/rB6672cbeb236444541037e728759792b1208df0da

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:

===================================================================

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/intern/paint.c
M	source/blender/editors/object/object_remesh.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/makesrna/intern/rna_object.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index bd2ac3da21b..0a35658464a 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -637,6 +637,8 @@ void BKE_sculpt_sync_face_sets_visibility_to_grids(struct Mesh *mesh,
 
 void BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(struct Mesh *mesh);
 
+void BKE_sculpt_ensure_orig_mesh_data(struct Scene *scene, struct Object *object);
+
 bool BKE_sculptsession_use_pbvh_draw(const struct Object *ob, const struct View3D *v3d);
 
 enum {
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 7c2fc40d537..4eecf3a3a87 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -2021,6 +2021,51 @@ void BKE_sculpt_sync_face_set_visibility(struct Mesh *mesh, struct SubdivCCG *su
   BKE_sculpt_sync_face_sets_visibility_to_grids(mesh, subdiv_ccg);
 }
 
+/**
+ * Ensures we do have expected mesh data in original mesh for the sculpt mode.
+ *
+ * \note IDs are expected to be original ones here, and calling code should ensure it updates its
+ * depsgraph properly after calling this function if it needs up-to-date evaluated data.
+ */
+void BKE_sculpt_ensure_orig_mesh_data(Scene *scene, Object *object)
+{
+  Mesh *mesh = BKE_mesh_from_object(object);
+  MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, object);
+
+  BLI_assert(object->mode == OB_MODE_SCULPT);
+
+  /* Copy the current mesh visibility to the Face Sets. */
+  BKE_sculpt_face_sets_ensure_from_base_mesh_visibility(mesh);
+  if (object->sculpt != NULL) {
+    /* If a sculpt session is active, ensure we have its faceset data porperly up-to-date. */
+    object->sculpt->face_sets = CustomData_get_layer(&mesh->pdata, CD_SCULPT_FACE_SETS);
+
+    /* Note: In theory we could add that on the fly when required by sculpt code.
+     * But this then requires proper update of depsgraph etc. For now we play safe, optimization is
+     * always possible later if it's worth it. */
+    BKE_sculpt_mask_layers_ensure(object, mmd);
+  }
+
+  /* Tessfaces aren't used and will become invalid. */
+  BKE_mesh_tessface_clear(mesh);
+
+  /* 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(&object->id, ID_RECALC_GEOMETRY);
+}
+
 static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
 {
   PBVH *pbvh = BKE_pbvh_new();
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");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index e8f1c26d17f..faa20e642cf 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -483,6 +483,17 @@ static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), Poin
   WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->owner_id);
 }
 
+void rna_Object_data_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+  Object *object = (Object *)ptr->data;
+
+  if (object->mode == OB_MODE_SCULPT) {
+    BKE_sculpt_ensure_orig_mesh_data(scene, object);
+  }
+
+  rna_Object_internal_update_data_dependency(bmain, scene, ptr);
+}
+
 static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)
 {
   Object *ob = (Object *)ptr->data;
@@ -2679,7 +2690,7 @@ static void rna_def_object(BlenderRNA *brna)
       prop, NULL, "rna_Object_data_set", "rna_Object_data_typef", "rna_Object_data_poll");
   RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK);
   RNA_def_property_ui_text(prop, "Data", "Object data");
-  RNA_def_property_update(prop, 0, "rna_Object_internal_update_data_dependency");
+  RNA_def_property_update(prop, 0, "rna_Object_data_update");
 
   prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
   RNA_def_property_enum_sdna(prop, NULL, "type");



More information about the Bf-blender-cvs mailing list