[Bf-blender-cvs] [fdf89acc863] master: Sculpt: Pose Brush with Inverse Kinematics

Pablo Dobarro noreply at git.blender.org
Tue Jan 7 16:54:15 CET 2020


Commit: fdf89acc8634ecba4dfe66e20ff595c0c24ffdee
Author: Pablo Dobarro
Date:   Tue Jan 7 16:46:56 2020 +0100
Branches: master
https://developer.blender.org/rBfdf89acc8634ecba4dfe66e20ff595c0c24ffdee

Sculpt: Pose Brush with Inverse Kinematics

This commits introduces the pose_ik_segments brush property in the Pose Brush. When increasing the IK segments count, the brush generates more segments and weights associations following the topology of the mesh. When moving the brush, these segments are transformed using an IK solver and they are used to deform the mesh.

When pressing Ctrl, the brush controls the segments' roll rotation instead of using the IK solver. The brush falloff controls how much rotation is propagated from the first to the last segment in the chain.

Reviewed By: jbakker

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

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

M	release/scripts/startup/bl_ui/properties_paint_common.py
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/intern/brush.c
M	source/blender/blenkernel/intern/paint.c
M	source/blender/blenloader/intern/versioning_280.c
M	source/blender/editors/sculpt_paint/paint_cursor.c
M	source/blender/editors/sculpt_paint/paint_intern.h
M	source/blender/editors/sculpt_paint/paint_utils.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
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 327df079d3b..b15a244eefd 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -616,9 +616,12 @@ def brush_settings(layout, context, brush, popover=False):
             layout.separator()
 
         if brush.sculpt_tool == 'POSE':
-            row = layout.row()
-            row.prop(brush, "pose_offset")
-
+            layout.separator()
+            layout.prop(brush, "pose_offset")
+            layout.prop(brush, "pose_smooth_iterations")
+            layout.prop(brush, "pose_ik_segments")
+            layout.separator()
+        
         if brush.sculpt_tool == 'SCRAPE':
             row = layout.row()
             row.prop(brush, "invert_to_scrape_fill", text="Invert to Fill")
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index fdd3bd7cd86..6089db5ed46 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -98,6 +98,20 @@ typedef enum eOverlayControlFlags {
   (PAINT_OVERLAY_OVERRIDE_SECONDARY | PAINT_OVERLAY_OVERRIDE_PRIMARY | \
    PAINT_OVERLAY_OVERRIDE_CURSOR)
 
+/* Defines 8 areas resulting of splitting the object space by the XYZ axis planes. This is used to
+ * flip or mirror transform values depending on where the vertex is and where the transform
+ * operation started to support XYZ symmetry on those operations in a predictable way. */
+
+#define AREA_SYMM_DEFAULT 0
+
+typedef enum ePaintSymmetryAreas {
+  AREA_SYMM_X = (1 << 0),
+  AREA_SYMM_Y = (1 << 1),
+  AREA_SYMM_Z = (1 << 2),
+} ePaintSymmetryAreas;
+
+#define PAINT_SYMM_AREAS 8
+
 void BKE_paint_invalidate_overlay_tex(struct Scene *scene,
                                       struct ViewLayer *view_layer,
                                       const struct Tex *tex);
@@ -211,6 +225,29 @@ struct SculptVertexPaintGeomMap {
   struct MeshElemMap *vert_to_poly;
 };
 
+/* Pose Brush IK Chain */
+typedef struct PoseIKChainSegment {
+  float orig[3];
+  float head[3];
+
+  float initial_orig[3];
+  float initial_head[3];
+  float len;
+  float rot[4];
+  float *weights;
+
+  /* Store a 4x4 transform matrix for each of the possible combinations of enabled XYZ symmetry
+   * axis. */
+  float trans_mat[PAINT_SYMM_AREAS][4][4];
+  float pivot_mat[PAINT_SYMM_AREAS][4][4];
+  float pivot_mat_inv[PAINT_SYMM_AREAS][4][4];
+} PoseIKChainSegment;
+
+typedef struct PoseIKChain {
+  PoseIKChainSegment *segments;
+  int tot_segments;
+} PoseIKChain;
+
 /* Session data (mode-specific) */
 
 typedef struct SculptSession {
@@ -273,7 +310,10 @@ typedef struct SculptSession {
   /* Dynamic mesh preview */
   int *preview_vert_index_list;
   int preview_vert_index_count;
+
+  /* Pose Brush Preview */
   float pose_origin[3];
+  PoseIKChain *pose_ik_chain_preview;
 
   /* Transform operator */
   float pivot_pos[3];
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index e9760f76cfc..8d49ab39bab 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -992,6 +992,7 @@ void BKE_brush_sculpt_reset(Brush *br)
       break;
     case SCULPT_TOOL_POSE:
       br->pose_smooth_iterations = 4;
+      br->pose_ik_segments = 1;
       br->flag &= ~BRUSH_ALPHA_PRESSURE;
       br->flag &= ~BRUSH_SPACE;
       br->flag &= ~BRUSH_SPACE_ATTEN;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 584f1ab1b0c..0c03f1db729 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1096,6 +1096,14 @@ void BKE_sculptsession_free(Object *ob)
       MEM_freeN(ss->preview_vert_index_list);
     }
 
+    if (ss->pose_ik_chain_preview) {
+      for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
+        MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments[i].weights);
+      }
+      MEM_SAFE_FREE(ss->pose_ik_chain_preview->segments);
+      MEM_SAFE_FREE(ss->pose_ik_chain_preview);
+    }
+
     BKE_sculptsession_free_vwpaint_data(ob->sculpt);
 
     MEM_freeN(ss);
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index bf53d6f216b..ee4e62f19d1 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -4323,5 +4323,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
       br->add_col[3] = 0.9f;
       br->sub_col[3] = 0.9f;
     }
+
+    /* Pose brush IK segments. */
+    if (!DNA_struct_elem_find(fd->filesdna, "Brush", "int", "pose_ik_segments")) {
+      for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
+        br->pose_ik_segments = 1;
+      }
+    }
   }
 }
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 9021666c001..9bc587de6da 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1461,15 +1461,30 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
             cursor_draw_point_with_symmetry(pos, ar, gi.active_vertex_co, sd, vc.obact, rds);
           }
 
-          /* Draw pose brush origin */
+          /* Draw pose brush origins. */
           if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
             immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
             if (update_previews) {
               BKE_sculpt_update_object_for_edit(depsgraph, vc.obact, true, false);
-              sculpt_pose_calc_pose_data(
-                  sd, vc.obact, ss, gi.location, rds, brush->pose_offset, ss->pose_origin, NULL);
+
+              /* Free the previous pose brush preview. */
+              if (ss->pose_ik_chain_preview) {
+                sculpt_pose_ik_chain_free(ss->pose_ik_chain_preview);
+              }
+
+              /* Generate a new pose brush preview from the current cursor location. */
+              ss->pose_ik_chain_preview = sculpt_pose_ik_chain_init(
+                  sd, vc.obact, ss, brush, gi.location, rds);
+            }
+
+            /* Draw the pose brush rotation origins. */
+            for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
+              cursor_draw_point_screen_space(pos,
+                                             ar,
+                                             ss->pose_ik_chain_preview->segments[i].initial_orig,
+                                             vc.obact->obmat,
+                                             3);
             }
-            cursor_draw_point_screen_space(pos, ar, ss->pose_origin, vc.obact->obmat, 5);
           }
 
           /* Draw 3D brush cursor */
@@ -1518,9 +1533,13 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
           if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
             immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
             GPU_line_width(2.0f);
-            immBegin(GPU_PRIM_LINES, 2);
-            immVertex3fv(pos, ss->pose_origin);
-            immVertex3fv(pos, gi.location);
+
+            immBegin(GPU_PRIM_LINES, ss->pose_ik_chain_preview->tot_segments * 2);
+            for (int i = 0; i < ss->pose_ik_chain_preview->tot_segments; i++) {
+              immVertex3fv(pos, ss->pose_ik_chain_preview->segments[i].initial_orig);
+              immVertex3fv(pos, ss->pose_ik_chain_preview->segments[i].initial_head);
+            }
+
             immEnd();
           }
 
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 53beb981522..6f2e4a0055d 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -45,6 +45,7 @@ struct wmOperator;
 struct wmOperatorType;
 struct wmWindowManager;
 enum ePaintMode;
+enum ePaintSymmetryFlags;
 
 typedef struct CoNo {
   float co[3];
@@ -306,8 +307,8 @@ bool mask_paint_poll(struct bContext *C);
 bool paint_curve_poll(struct bContext *C);
 
 bool facemask_paint_poll(struct bContext *C);
-void flip_v3_v3(float out[3], const float in[3], const char symm);
-void flip_qt_qt(float out[3], const float in[3], const char symm);
+void flip_v3_v3(float out[3], const float in[3], const enum ePaintSymmetryFlags symm);
+void flip_qt_qt(float out[3], const float in[3], const enum ePaintSymmetryFlags symm);
 
 /* stroke operator */
 typedef enum BrushStrokeMode {
diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c
index a014fe7fdff..4a1b329fce5 100644
--- a/source/blender/editors/sculpt_paint/paint_utils.c
+++ b/source/blender/editors/sculpt_paint/paint_utils.c
@@ -412,7 +412,7 @@ static Image *imapaint_face_image(Object *ob, Mesh *me, int face_index)
 }
 
 /* Uses symm to selectively flip any axis of a coordinate. */
-void flip_v3_v3(float out[3], const float in[3], const char symm)
+void flip_v3_v3(float out[3], const float in[3], const ePaintSymmetryFlags symm)
 {
   if (symm & PAINT_SYMM_X) {
     out[0] = -in[0];
@@ -434,7 +434,7 @@ void flip_v3_v3(float out[3], const float in[3], const char symm)
   }
 }
 
-void flip_qt_qt(float out[4], const float in[4], const char symm)
+void flip_qt_qt(float out[4], const float in[4], const ePaintSymmetryFlags symm)
 {
   float axis[3], angle;
 
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 10772fa68ba..a96ca07cc9b 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -443,7 +443,7 @@ static void nearest_vertex_get_reduce(const void *__restrict UNUSED(userdata),
 }
 
 static int sculpt_nearest_vertex_get(
-    Sculpt *sd, Object *ob, float co[3], float max_distance, bool use_original)
+    Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original)
 {
   SculptSession *ss = ob->sculpt;
   PBVHNode **nodes = NULL;
@@ -1330,11 +1330,16 @@ static v

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list