[Bf-blender-cvs] [5e3d84eed79] sculpt-dev: Sculpt: fix multires crashing

Joseph Eagar noreply at git.blender.org
Thu Sep 30 19:54:23 CEST 2021


Commit: 5e3d84eed792edf278b5b59b7843757d2a49d324
Author: Joseph Eagar
Date:   Thu Sep 30 10:54:11 2021 -0700
Branches: sculpt-dev
https://developer.blender.org/rB5e3d84eed792edf278b5b59b7843757d2a49d324

Sculpt: fix multires crashing

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

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/BKE_pbvh.h
M	source/blender/blenkernel/intern/paint.c
M	source/blender/blenkernel/intern/pbvh.c

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

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 31aa0b3d2b5..4700fd7fb9e 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -791,7 +791,7 @@ void BKE_sculptsession_free_deformMats(struct SculptSession *ss);
 void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss);
 void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder);
 void BKE_sculptsession_bm_to_me_for_render(struct Object *object);
-bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert);
+bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, struct PBVH *pbvh, int totvert);
 
 /* Create new color layer on object if it doesn't have one and if experimental feature set has
  * sculpt vertex color enabled. Returns truth if new layer has been added, false otherwise. */
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index f4cb0dac6ed..f081b810733 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -135,6 +135,7 @@ struct MPoly;
 struct MVert;
 struct Mesh;
 struct PBVH;
+struct MEdge;
 struct PBVHNode;
 struct SubdivCCG;
 struct TaskParallelSettings;
@@ -933,6 +934,11 @@ void BKE_pbvh_update_vert_boundary_faces(int *face_sets,
                                          struct MDynTopoVert *mdyntopo_verts,
                                          struct MeshElemMap *pmap,
                                          SculptVertRef vertex);
+void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
+                                         struct SubdivCCG *subdiv_ccg,
+                                         SculptVertRef vertex);
+
+void BKE_pbvh_set_mdyntopo_verts(PBVH *pbvh, struct MDynTopoVert *mdyntopoverts);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 61e83f4d090..e4d65963772 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -86,7 +86,7 @@ void SCULPT_dyntopo_node_layers_add(SculptSession *ss);
 BMesh *SCULPT_dyntopo_empty_bmesh();
 void SCULPT_undo_ensure_bmlog(Object *ob);
 
-static void init_mdyntopo_layer(SculptSession *ss, int totvert);
+static void init_mdyntopo_layer(SculptSession *ss, PBVH *pbvh, int totvert);
 
 static void palette_init_data(ID *id)
 {
@@ -2201,7 +2201,9 @@ static PBVH *build_pbvh_for_dynamic_topology(Object *ob)
   return pbvh;
 }
 
-static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool respect_hide)
+ATTR_NO_OPT static PBVH *build_pbvh_from_regular_mesh(Object *ob,
+                                                      Mesh *me_eval_deform,
+                                                      bool respect_hide)
 {
   SculptSession *ss = ob->sculpt;
   Mesh *me = BKE_object_get_original_mesh(ob);
@@ -2228,7 +2230,7 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform, bool
                                   false);
   }
 
-  BKE_sculptsession_check_mdyntopo(ob->sculpt, me->totvert);
+  BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, me->totvert);
 
   BKE_pbvh_build_mesh(pbvh,
                       me,
@@ -2277,24 +2279,24 @@ static PBVH *build_pbvh_from_ccg(Object *ob, SubdivCCG *subdiv_ccg, bool respect
                        subdiv_ccg->grid_hidden,
                        ob->sculpt->fast_draw);
 
-  BKE_sculptsession_check_mdyntopo(ob->sculpt, BKE_pbvh_get_grid_num_vertices(pbvh));
+  BKE_sculptsession_check_mdyntopo(ob->sculpt, pbvh, BKE_pbvh_get_grid_num_vertices(pbvh));
 
   pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
   pbvh_show_face_sets_set(pbvh, ob->sculpt->show_face_sets);
   return pbvh;
 }
 
-bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, int totvert)
+ATTR_NO_OPT bool BKE_sculptsession_check_mdyntopo(SculptSession *ss, PBVH *pbvh, int totvert)
 {
   if (!ss->bm && (!ss->mdyntopo_verts || totvert != ss->mdyntopo_verts_size)) {
-    init_mdyntopo_layer(ss, totvert);
+    init_mdyntopo_layer(ss, pbvh, totvert);
     return true;
   }
 
   return false;
 }
 
-static void init_mdyntopo_layer(SculptSession *ss, int totvert)
+ATTR_NO_OPT static void init_mdyntopo_layer_faces(SculptSession *ss, PBVH *pbvh, int totvert)
 {
   if (ss->mdyntopo_verts) {
     MEM_freeN(ss->mdyntopo_verts);
@@ -2303,6 +2305,8 @@ static void init_mdyntopo_layer(SculptSession *ss, int totvert)
   ss->mdyntopo_verts = MEM_calloc_arrayN(totvert, sizeof(*ss->mdyntopo_verts), "mdyntopo_verts");
   ss->mdyntopo_verts_size = totvert;
 
+  BKE_pbvh_set_mdyntopo_verts(pbvh, ss->mdyntopo_verts);
+
   MDynTopoVert *mv = ss->mdyntopo_verts;
 
   for (int i = 0; i < totvert; i++, mv++) {
@@ -2310,6 +2314,7 @@ static void init_mdyntopo_layer(SculptSession *ss, int totvert)
     mv->stroke_id = -1;
 
     SculptVertRef vertex = {.i = i};
+
     BKE_pbvh_update_vert_boundary_faces(ss->face_sets,
                                         ss->mvert,
                                         ss->medge,
@@ -2320,6 +2325,40 @@ static void init_mdyntopo_layer(SculptSession *ss, int totvert)
                                         vertex);
   }
 }
+
+ATTR_NO_OPT static void init_mdyntopo_layer_grids(SculptSession *ss, PBVH *pbvh, int totvert)
+{
+  if (ss->mdyntopo_verts) {
+    MEM_freeN(ss->mdyntopo_verts);
+  }
+
+  ss->mdyntopo_verts = MEM_calloc_arrayN(totvert, sizeof(*ss->mdyntopo_verts), "mdyntopo_verts");
+  ss->mdyntopo_verts_size = totvert;
+
+  BKE_pbvh_set_mdyntopo_verts(pbvh, ss->mdyntopo_verts);
+
+  MDynTopoVert *mv = ss->mdyntopo_verts;
+
+  for (int i = 0; i < totvert; i++, mv++) {
+    mv->flag = DYNVERT_NEED_BOUNDARY | DYNVERT_NEED_VALENCE | DYNVERT_NEED_DISK_SORT;
+    mv->stroke_id = -1;
+
+    SculptVertRef vertex = {.i = i};
+
+    BKE_pbvh_update_vert_boundary_grids(pbvh, ss->subdiv_ccg, vertex);
+  }
+}
+
+ATTR_NO_OPT static void init_mdyntopo_layer(SculptSession *ss, PBVH *pbvh, int totvert)
+{
+  if (BKE_pbvh_type(pbvh) == PBVH_FACES) {
+    init_mdyntopo_layer_faces(ss, pbvh, totvert);
+  }
+  else if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
+    init_mdyntopo_layer_grids(ss, pbvh, totvert);
+  }
+}
+
 PBVH *BKE_sculpt_object_pbvh_ensure(Depsgraph *depsgraph, Object *ob)
 {
   if (ob == NULL || ob->sculpt == NULL) {
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index e1e07093ba8..dea4d48a6d8 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -4127,6 +4127,47 @@ void BKE_pbvh_set_symmetry(PBVH *pbvh, int symmetry, int boundary_symmetry)
   }
 }
 
+void BKE_pbvh_set_mdyntopo_verts(PBVH *pbvh, struct MDynTopoVert *mdyntopoverts)
+{
+  pbvh->mdyntopo_verts = mdyntopoverts;
+}
+
+void BKE_pbvh_update_vert_boundary_grids(PBVH *pbvh,
+                                         struct SubdivCCG *subdiv_ccg,
+                                         SculptVertRef vertex)
+{
+  MDynTopoVert *mv = pbvh->mdyntopo_verts + vertex.i;
+
+  int last_fset = 0;
+  int last_fset2 = 0;
+
+  mv->flag &= ~(DYNVERT_BOUNDARY | DYNVERT_FSET_BOUNDARY | DYNVERT_NEED_BOUNDARY |
+                DYNVERT_FSET_CORNER | DYNVERT_CORNER | DYNVERT_SEAM_BOUNDARY |
+                DYNVERT_SHARP_BOUNDARY | DYNVERT_SEAM_CORNER | DYNVERT_SHARP_CORNER);
+
+  int totsharp = 0, totseam = 0;
+  int visible = false;
+
+  int index = (int)vertex.i;
+
+  /* TODO: optimize this. We could fill #SculptVertexNeighborIter directly,
+   * maybe provide coordinate and mask pointers directly rather than converting
+   * back and forth between #CCGElem and global index. */
+  const CCGKey *key = BKE_pbvh_get_grid_key(pbvh);
+  const int grid_index = index / key->grid_area;
+  const int vertex_index = index - grid_index * key->grid_area;
+
+  SubdivCCGCoord coord = {.grid_index = grid_index,
+                          .x = vertex_index % key->grid_size,
+                          .y = vertex_index / key->grid_size};
+
+  SubdivCCGNeighbors neighbors;
+  BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, &coord, false, &neighbors);
+
+  mv->valence = neighbors.size;
+  mv->flag &= ~DYNVERT_NEED_VALENCE;
+}
+
 void BKE_pbvh_update_vert_boundary_faces(int *face_sets,
                                          MVert *mvert,
                                          MEdge *medge,



More information about the Bf-blender-cvs mailing list