[Bf-blender-cvs] [9120191fe2a] master: Sculpt: Pose Brush Face Sets origin mode

Pablo Dobarro noreply at git.blender.org
Fri Mar 27 18:16:13 CET 2020


Commit: 9120191fe2a28a3d01a51f536df7b433a7764803
Author: Pablo Dobarro
Date:   Fri Mar 27 18:14:14 2020 +0100
Branches: master
https://developer.blender.org/rB9120191fe2a28a3d01a51f536df7b433a7764803

Sculpt: Pose Brush Face Sets origin mode

This commit introduces a new mode for calculating the positions and
weights of the IK segments in the Pose Brush based on the Face Sets.

The first segment of the chain will always include all face sets inside
the brush radius and it will propagate until the boundary of the last
face sets added in the flood fill. Then consecutive connected face sets
are added to the chain until the chain length limit is reached or all
face sets of the mesh are already part of the chain.

This feature enables complete control over the pose brush origins in
case that is needed. Also, with this mode, the user can have a library
of base meshes with face sets already configured to get to the initial
pose as fast as possible.

Reviewed By: jbakker

Differential Revision: https://developer.blender.org/D7235

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

M	release/scripts/startup/bl_ui/properties_paint_common.py
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/editors/sculpt_paint/sculpt_pose.c
M	source/blender/makesdna/DNA_brush_types.h
M	source/blender/makesrna/intern/rna_brush.c

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

diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 3d2474d006a..6e0613874d1 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -626,6 +626,7 @@ def brush_settings(layout, context, brush, popover=False):
 
         if brush.sculpt_tool == 'POSE':
             layout.separator()
+            layout.prop(brush, "pose_origin_type")
             layout.prop(brush, "pose_offset")
             layout.prop(brush, "pose_smooth_iterations")
             layout.prop(brush, "pose_ik_segments")
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index fe4aa971b55..6ccd197c908 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -196,21 +196,15 @@ float SCULPT_vertex_mask_get(SculptSession *ss, int index)
   return 0.0f;
 }
 
-static int SCULPT_active_vertex_get(SculptSession *ss)
+int SCULPT_active_vertex_get(SculptSession *ss)
 {
-  switch (BKE_pbvh_type(ss->pbvh)) {
-    case PBVH_FACES:
-      return ss->active_vertex_index;
-    case PBVH_BMESH:
-      return ss->active_vertex_index;
-    case PBVH_GRIDS:
-      return ss->active_vertex_index;
+  if (ELEM(BKE_pbvh_type(ss->pbvh), PBVH_FACES, PBVH_BMESH, PBVH_GRIDS)) {
+    return ss->active_vertex_index;
   }
-
   return 0;
 }
 
-static const float *SCULPT_active_vertex_co_get(SculptSession *ss)
+const float *SCULPT_active_vertex_co_get(SculptSession *ss)
 {
   return SCULPT_vertex_co_get(ss, SCULPT_active_vertex_get(ss));
 }
@@ -373,7 +367,7 @@ static void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_se
   }
 }
 
-static int SCULPT_vertex_face_set_get(SculptSession *ss, int index)
+int SCULPT_vertex_face_set_get(SculptSession *ss, int index)
 {
   switch (BKE_pbvh_type(ss->pbvh)) {
     case PBVH_FACES: {
@@ -394,7 +388,7 @@ static int SCULPT_vertex_face_set_get(SculptSession *ss, int index)
   return 0;
 }
 
-static bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set)
+bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set)
 {
   switch (BKE_pbvh_type(ss->pbvh)) {
     case PBVH_FACES: {
@@ -464,7 +458,7 @@ void SCULPT_visibility_sync_all_vertex_to_face_sets(SculptSession *ss)
   }
 }
 
-static bool sculpt_vertex_has_unique_face_set(SculptSession *ss, int index)
+bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index)
 {
   switch (BKE_pbvh_type(ss->pbvh)) {
     case PBVH_FACES: {
@@ -819,11 +813,35 @@ void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
   flood->visited_vertices = MEM_callocN(vertex_count * sizeof(char), "visited vertices");
 }
 
-static void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index)
+void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index)
 {
   BLI_gsqueue_push(flood->queue, &index);
 }
 
+void SCULPT_floodfill_add_initial_with_symmetry(
+    Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, int index, float radius)
+{
+  /* Add active vertex and symmetric vertices to the queue. */
+  const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+  for (char i = 0; i <= symm; ++i) {
+    if (SCULPT_is_symmetry_iteration_valid(i, symm)) {
+      int v = -1;
+      if (i == 0) {
+        v = index;
+      }
+      else if (radius > 0.0f) {
+        float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius;
+        float location[3];
+        flip_v3_v3(location, SCULPT_vertex_co_get(ss, index), i);
+        v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false);
+      }
+      if (v != -1) {
+        sculpt_floodfill_add_initial(flood, v);
+      }
+    }
+  }
+}
+
 void SCULPT_floodfill_add_active(
     Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius)
 {
@@ -3639,7 +3657,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
   BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
   {
     if (sculpt_brush_test_sq_fn(&test, vd.co)) {
-      if (relax_face_sets != sculpt_vertex_has_unique_face_set(ss, vd.index)) {
+      if (relax_face_sets != SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
         const float fade = bstrength * SCULPT_brush_strength_factor(ss,
                                                                     brush,
                                                                     vd.co,
@@ -3856,7 +3874,7 @@ void SCULPT_relax_vertex(SculptSession *ss,
   SculptVertexNeighborIter ni;
   SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, vd->index, ni) {
     if (!filter_boundary_face_sets ||
-        (filter_boundary_face_sets && !sculpt_vertex_has_unique_face_set(ss, ni.index))) {
+        (filter_boundary_face_sets && !SCULPT_vertex_has_unique_face_set(ss, ni.index))) {
       add_v3_v3(smooth_pos, SCULPT_vertex_co_get(ss, ni.index));
       count++;
     }
@@ -9478,7 +9496,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
       /* Skip the edges of the face set when relaxing or smoothing. There is a relax face set
        * option to relax the boindaries independently. */
       if (filter_type == MESH_FILTER_RELAX) {
-        if (!sculpt_vertex_has_unique_face_set(ss, vd.index)) {
+        if (!SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
           continue;
         }
       }
@@ -9492,7 +9510,7 @@ static void mesh_filter_task_cb(void *__restrict userdata,
     }
 
     if (filter_type == MESH_FILTER_RELAX_FACE_SETS) {
-      if (relax_face_sets == sculpt_vertex_has_unique_face_set(ss, vd.index)) {
+      if (relax_face_sets == SCULPT_vertex_has_unique_face_set(ss, vd.index)) {
         continue;
       }
     }
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 7f93355e269..fe56283dbcb 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -125,6 +125,9 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
   } \
   ((void)0)
 
+int SCULPT_active_vertex_get(SculptSession *ss);
+const float *SCULPT_active_vertex_co_get(SculptSession *ss);
+
 /* Sculpt Original Data */
 typedef struct {
   struct BMLog *bm_log;
@@ -143,6 +146,11 @@ typedef struct {
 void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node);
 void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter);
 
+/* Face Sets */
+int SCULPT_vertex_face_set_get(SculptSession *ss, int index);
+bool SCULPT_vertex_has_face_set(SculptSession *ss, int index, int face_set);
+bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, int index);
+
 /* Dynamic topology */
 void sculpt_pbvh_clear(Object *ob);
 void sculpt_dyntopo_node_layers_add(struct SculptSession *ss);
@@ -196,6 +204,13 @@ void SCULPT_floodfill_add_active(struct Sculpt *sd,
                                  struct SculptSession *ss,
                                  SculptFloodFill *flood,
                                  float radius);
+void SCULPT_floodfill_add_initial_with_symmetry(struct Sculpt *sd,
+                                                struct Object *ob,
+                                                struct SculptSession *ss,
+                                                SculptFloodFill *flood,
+                                                int index,
+                                                float radius);
+void sculpt_floodfill_add_initial(SculptFloodFill *flood, int index);
 void SCULPT_floodfill_execute(
     struct SculptSession *ss,
     SculptFloodFill *flood,
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index 8b842c07e79..8342c6c9d1b 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -351,9 +351,29 @@ typedef struct PoseFloodFillData {
   float *pose_factor;
   float pose_origin[3];
   int tot_co;
+
+  int current_face_set;
+  int next_face_set;
+  int prev_face_set;
+  int next_vertex;
+
+  bool next_face_set_found;
+
+  /* Store the visited face sets to avoid going back when calculating the chain. */
+  GSet *visited_face_sets;
+
+  /* In face sets origin mode, each vertex can only be assigned to one face set. */
+  bool *is_weighted;
+
+  bool is_first_iteration;
+
+  /* Fallback origin. If we can't find any face set to continue, use the position of all vertices
+   * that have the current face set. */
+  float fallback_origin[3];
+  int fallback_count;
 } PoseFloodFillData;
 
-static bool pose_floodfill_cb(
+static bool pose_topology_floodfill_cb(
     SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
 {
   PoseFloodFillData *data = userdata;
@@ -377,6 +397,100 @@ static bool pose_floodfill_cb(
   return false;
 }
 
+static bool pose_face_sets_floodfill_cb(
+    SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
+{
+  PoseFloodFillData *data = userdata;
+
+  const int index = to_v;
+  bool visit_next = false;
+
+  const float *co = SCULPT_vertex_co_get(ss, index);
+  const bool symmetry_check = SCULPT_check_vertex_pivot_symmetry(
+                                  co, data->pose_initial_co, data->symm) &&
+                              !is_duplicate;
+
+  /* First iteration. Continue expanding using topology until a vertex is outside the brush radius
+   * to determine the first face set. */
+  if (data->current_face_set == SCULPT_FACE_SET_NONE) {
+
+    data->pose_factor[index] = 1.0f;
+    data->is_weighted[index] = true;
+
+    if (sculpt_pose_brush_is_vertex_inside_brush_radius(
+            co, data->pose_initial_co, data->radius, data->symm)) {
+      const int visited_face_set = SCULPT_vertex_face_set_get(ss, index);
+      BLI_gset_add(data->visited_face_sets, visited_face_set);
+    }
+    else if (symmetry_check) {
+      data->current_face_set = SCULPT_vertex_face_set_get(ss, index);
+      BLI_gset_add(data->visited_face_sets, data-

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list