[Bf-blender-cvs] [a9f6ab73572] sculpt-dev: Basic mask expand operation working

Pablo Dobarro noreply at git.blender.org
Thu Jan 14 01:07:00 CET 2021


Commit: a9f6ab735721e9242d3fc95f35c8e7ee69e42160
Author: Pablo Dobarro
Date:   Thu Jan 14 01:05:11 2021 +0100
Branches: sculpt-dev
https://developer.blender.org/rBa9f6ab735721e9242d3fc95f35c8e7ee69e42160

Basic mask expand operation working

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

M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_expand.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h

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

diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index fb1efd10e1f..174b06ce1a2 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -10561,6 +10561,8 @@ void ED_operatortypes_sculpt(void)
   WM_operatortype_append(SCULPT_OT_project_lasso_gesture);
   WM_operatortype_append(SCULPT_OT_project_box_gesture);
 
+  WM_operatortype_append(SCULPT_OT_expand);
+
   WM_operatortype_append(SCULPT_OT_sample_color);
   WM_operatortype_append(SCULPT_OT_loop_to_vertex_colors);
   WM_operatortype_append(SCULPT_OT_vertex_to_loop_colors);
diff --git a/source/blender/editors/sculpt_paint/sculpt_expand.c b/source/blender/editors/sculpt_paint/sculpt_expand.c
index 2c53e320522..465ed91bf1f 100644
--- a/source/blender/editors/sculpt_paint/sculpt_expand.c
+++ b/source/blender/editors/sculpt_paint/sculpt_expand.c
@@ -74,25 +74,149 @@ static EnumPropertyItem prop_sculpt_expand_faloff_type_items[] = {
     {SCULPT_EXPAND_FALLOFF_TOPOLOGY, "TOPOLOGY", 0, "Topology", ""},
     {SCULPT_EXPAND_FALLOFF_NORMALS, "NORMALS", 0, "Normals", ""},
     {SCULPT_EXPAND_FALLOFF_SPHERICAL, "SPHERICAL", 0, "Spherical", ""},
+    {SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY, "BOUNDARY_TOPOLOGY`", 0, "Boundary Topology", ""},
     {0, NULL, 0, NULL, NULL},
 };
 
-
-
 static float *sculpt_expand_geodesic_falloff_create(Sculpt *sd, Object *ob, const int vertex) {
     return SCULPT_geodesic_from_vertex_and_symm(sd, ob, vertex, FLT_MAX);
 }
 
-static float *sculpt_expand_topology_falloff_create() {
-    return NULL;
+typedef struct ExpandFloodFillData {
+  float original_normal[3];
+  float edge_sensitivity;
+  float *dists;
+  float *edge_factor;
+} ExpandFloodFillData;
+
+static bool mask_expand_topology_floodfill_cb(
+    SculptSession *UNUSED(ss), int from_v, int to_v, bool is_duplicate, void *userdata)
+{
+  ExpandFloodFillData *data = userdata;
+  if (!is_duplicate) {
+    const int to_it = data->dists[from_v] + 1;
+    data->dists[to_v] = to_it;
+  }
+  else {
+    data->dists[to_v] = data->dists[from_v];
+  }
+  return true;
 }
 
-static float *sculpt_expand_spherical_falloff_create() {
-    return NULL;
+static float *sculpt_expand_topology_falloff_create(Sculpt *sd, Object *ob, const int vertex) {
+  SculptSession *ss = ob->sculpt;
+  const int totvert = SCULPT_vertex_count_get(ss);
+  float *dists = MEM_malloc_arrayN(sizeof (float), totvert, "spherical dist");
+
+  SculptFloodFill flood;
+  SCULPT_floodfill_init(ss, &flood);
+  SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, vertex, FLT_MAX);
+
+  ExpandFloodFillData fdata;
+  fdata.dists = dists;
+
+  SCULPT_floodfill_execute(ss, &flood, mask_expand_topology_floodfill_cb, &fdata);
+  SCULPT_floodfill_free(&flood);
+
+  return dists;
 }
 
-static float *sculpt_expand_normal_falloff_create() {
-    return NULL;
+static bool mask_expand_normals_floodfill_cb(
+    SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+{
+  ExpandFloodFillData *data = userdata;
+  if (!is_duplicate) {
+      float current_normal[3], prev_normal[3];
+      SCULPT_vertex_normal_get(ss, to_v, current_normal);
+      SCULPT_vertex_normal_get(ss, from_v, prev_normal);
+      const float from_edge_factor = data->edge_factor[from_v];
+      data->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) *
+                                            from_edge_factor;
+      data->dists[to_v] = dot_v3v3(data->original_normal, current_normal) *
+                                              powf(from_edge_factor, data->edge_sensitivity);
+      CLAMP(data->dists[to_v], 0.0f, 1.0f);
+  }
+  else {
+    /* PBVH_GRIDS duplicate handling. */
+    data->edge_factor[to_v] = data->edge_factor[from_v];
+    data->dists[to_v] = data->dists[from_v];
+  }
+
+  return true;
+}
+
+static float *sculpt_expand_normal_falloff_create(Sculpt *sd, Object *ob, const int vertex, const float edge_sensitivity) {
+  SculptSession *ss = ob->sculpt;
+  const int totvert = SCULPT_vertex_count_get(ss);
+  float *dists = MEM_malloc_arrayN(sizeof (float), totvert, "normal dist");
+   float *edge_factor = MEM_callocN(sizeof(float) * totvert,
+                                                "mask edge factor");
+    for (int i = 0; i < totvert; i++) {
+      edge_factor[i] = 1.0f;
+    }
+
+  SculptFloodFill flood;
+  SCULPT_floodfill_init(ss, &flood);
+  SCULPT_floodfill_add_initial_with_symmetry(sd, ob, ss, &flood, vertex, FLT_MAX);
+
+  ExpandFloodFillData fdata;
+  fdata.dists = dists;
+  fdata.edge_factor = edge_factor;
+  fdata.edge_sensitivity = edge_sensitivity;
+  SCULPT_vertex_normal_get(ss, vertex, fdata.original_normal);
+
+  SCULPT_floodfill_execute(ss, &flood, mask_expand_topology_floodfill_cb, &fdata);
+  SCULPT_floodfill_free(&flood);
+
+    for (int repeat = 0; repeat < 2; repeat++) {
+      for (int i = 0; i < totvert; i++) {
+        float avg = 0.0f;
+        SculptVertexNeighborIter ni;
+        SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, i, ni) {
+          avg += dists[ni.index];
+        }
+        SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
+        dists[i] = avg / ni.size;
+      }
+    }
+
+    MEM_SAFE_FREE(edge_factor);
+
+  return dists;
+}
+
+
+static float *sculpt_expand_spherical_falloff_create(Sculpt *sd, Object *ob, const int vertex) {
+  SculptSession *ss = ob->sculpt;
+  const int totvert = SCULPT_vertex_count_get(ss);
+
+  float *dists = MEM_malloc_arrayN(sizeof (float), totvert, "spherical dist");
+  for (int i = 0; i < totvert; i++) {
+     dists[i] = FLT_MAX;
+  }
+  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
+
+  for (char symm_it = 0; symm_it <= symm; symm_it++) {
+    if (SCULPT_is_symmetry_iteration_valid(symm_it, symm)) {
+      int v = -1;
+      if (symm_it == 0) {
+        v = vertex;
+      }
+      else {
+        float location[3];
+        flip_v3_v3(location, SCULPT_vertex_co_get(ss, vertex), symm_it);
+        v = SCULPT_nearest_vertex_get(sd, ob, location, FLT_MAX, false);
+      }
+      if (v != -1) {
+          const float *co = SCULPT_vertex_co_get(ss, v);
+          for (int i = 0; i < totvert; i++) {
+              dists[i] = min_ff(dists[i], len_v3v3(co, SCULPT_vertex_co_get(ss, i)));
+          }
+      }
+    }
+  }
+
+  return dists;
 }
 
 static void sculpt_expand_update_max_falloff_factor(SculptSession *ss, ExpandCache *expand_cache) {
@@ -110,19 +234,22 @@ static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(ExpandCach
         return;
     }
 
+    if (expand_cache->falloff_factor) {
+        MEM_freeN(expand_cache->falloff_factor);
+    }
 
     switch (falloff_type) {
     case SCULPT_EXPAND_FALLOFF_GEODESICS:
         expand_cache->falloff_factor = sculpt_expand_geodesic_falloff_create(sd, ob, vertex);
         break;
     case SCULPT_EXPAND_FALLOFF_TOPOLOGY:
-
+        expand_cache->falloff_factor = sculpt_expand_topology_falloff_create(sd, ob, vertex);
         break;
     case SCULPT_EXPAND_FALLOFF_NORMALS:
-
+        expand_cache->falloff_factor = sculpt_expand_normal_falloff_create(sd, ob, vertex, 300.0f);
         break;
     case SCULPT_EXPAND_FALLOFF_SPHERICAL:
-
+        expand_cache->falloff_factor = sculpt_expand_spherical_falloff_create(sd, ob, vertex);
         break;
     case SCULPT_EXPAND_FALLOFF_BOUNDARY_TOPOLOGY:
 
@@ -135,15 +262,11 @@ static void sculpt_expand_falloff_factors_from_vertex_and_symm_create(ExpandCach
     sculpt_expand_update_max_falloff_factor(ss, expand_cache);
 }
 
-
-float *sculpt_expand_falloff_factors_update() {
-    return NULL;
-}
-
-
 void sculpt_expand_cache_free(ExpandCache *expand_cache) {
-
-
+    MEM_SAFE_FREE(expand_cache->nodes);
+    MEM_SAFE_FREE(expand_cache->falloff_factor);
+    MEM_SAFE_FREE(expand_cache->initial_mask);
+    MEM_SAFE_FREE(expand_cache->initial_face_sets);
     MEM_SAFE_FREE(expand_cache);
 }
 
@@ -187,263 +310,96 @@ static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op)
 
 
 static void sculpt_expand_cancel(bContext *C, wmOperator *op) {
+  Object *ob = CTX_data_active_object(C);
+  SculptSession *ss = ob->sculpt;
 
+  sculpt_expand_cache_free(ss->expand_cache);
   ED_workspace_status_text(C, NULL);
 }
 
 
-static void sculpt_expand_task_cb(void *__restrict userdata,
+static bool sculpt_expand_state_get(ExpandCache *expand_cache, int i) {
+    bool enabled = expand_cache->falloff_factor[i] <= expand_cache->active_factor;
+    if (expand_cache->invert) {
+        enabled = !enabled;
+    }
+    return enabled;
+}
+
+
+static void sculpt_expand_mask_update_task_cb(void *__restrict userdata,
                                   const int i,
                                   const TaskParallelTLS *__restrict UNUSED(tls))
 {
   SculptThreadedTaskData *data = userdata;
   SculptSession *ss = data->ob->sculpt;
   PBVHNode *node = data->nodes[i];
-  PBVHVertexIter vd;
-  int update_it = data->mask_expand_update_it;
+  ExpandCache *expand_cache = ss->expand_cache;
 
+  bool any_changed = false;
+
+  PBVHVertexIter vd;
   BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_ALL)
   {
-    int vi = vd.index;
-    float final_mask = *vd.mask;
-    if (data->mask_expand_use_normals) {
-      if (ss->filter_cache->normal_factor[SCULPT_active_vertex_get(ss)] <
-          ss->filter_cache->normal_factor[vd.index]) {
-        final_mask = 1.0f;
+      const float initial_mask = *vd.mask;
+      const bool enabled = sculpt_expand_state_get(expand_cache, vd.index);
+
+      if (enabled){
+        if (expand_cache->mask_preserve_previous) {
+          *vd.mask = max_ff(initial_mask, expand_cache->initial_mask[vd.index]);
       }
       else {
-        final_mask = 0.0f;
+          *vd.mask = 1.0f;
       }
-    }
-    else {
-      if (ss->filter_cache->mask_update_it[vi] <= update_it &&
-          ss->filter_cache->mask_update_it[vi] != 0) {
-        final_mask = 1.0f;
       }
       else {
-        final_mask = 0.0f;
-      }
-    }
-
-    if (data->mask_expand_create_face_set) {
-      if (final_mask == 1.0f) {
-        SCULPT_vertex_face_set_set(ss, vd.index, ss->filter_cache->new_face_set);
-      }
-      BKE_pbvh_node_mark_redraw(node);
-    }
-    else {
-
-      if (data->mask_expa

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list