[Bf-blender-cvs] [5d7f7b7065c] sculpt-dev: Sculpt: Initial support for bend deformations in Pose

Pablo Dobarro noreply at git.blender.org
Tue Feb 23 17:33:46 CET 2021


Commit: 5d7f7b7065c13920cbd5c76e321402eb6d46ef24
Author: Pablo Dobarro
Date:   Tue Feb 23 17:33:21 2021 +0100
Branches: sculpt-dev
https://developer.blender.org/rB5d7f7b7065c13920cbd5c76e321402eb6d46ef24

Sculpt: Initial support for bend deformations in Pose

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

M	source/blender/blenkernel/BKE_paint.h
M	source/blender/editors/sculpt_paint/sculpt_pose.c
M	source/blender/makesdna/DNA_brush_enums.h
M	source/blender/makesdna/DNA_object_types.h
M	source/blender/makesrna/intern/rna_brush.c

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

diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 605b16f1575..f1cb15d3ed5 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -260,6 +260,11 @@ typedef struct SculptPoseIKChain {
   SculptPoseIKChainSegment *segments;
   int tot_segments;
   float grab_delta_offset[3];
+  float bend_mat[4][4];
+  float bend_mat_inv[4][4];
+  float bend_factor;
+  float bend_limit;
+  float bend_upper_limit;
 } SculptPoseIKChain;
 
 /* Cloth Brush */
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index a85f805894b..e4c0cceb0d6 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -157,6 +157,76 @@ static void pose_solve_scale_chain(SculptPoseIKChain *ik_chain, const float scal
   }
 }
 
+static void do_pose_brush_bend_task_cb_ex(void *__restrict userdata,
+                                          const int n,
+                                          const TaskParallelTLS *__restrict UNUSED(tls))
+{
+  SculptThreadedTaskData *data = userdata;
+  SculptSession *ss = data->ob->sculpt;
+  SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
+  SculptPoseIKChainSegment *segments = ik_chain->segments;
+  const Brush *brush = data->brush;
+
+  if (fabsf(ik_chain->bend_factor) <= 0.00001f) {
+    return;
+  }
+
+  float final_pos[3];
+
+  SculptOrigVertData orig_data;
+  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
+
+  PBVHVertexIter vd;
+  BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+  {
+    SCULPT_orig_vert_data_update(&orig_data, &vd);
+
+    const float ik_chain_weight = segments[0].weights[vd.index] *
+                                  (1.0f - SCULPT_vertex_mask_get(ss, vd.index));
+    if (ik_chain_weight == 0.0f) {
+      continue;
+    }
+
+    float orig_co[3];
+    mul_v3_m4v3(orig_co, ik_chain->bend_mat_inv, orig_data.co);
+
+    const float bend_factor = ik_chain->bend_factor;
+
+    if (fabsf(bend_factor) <= 0.0000001f) {
+      continue;
+    }
+
+    if (orig_co[0] < 0.0f) {
+      continue;
+    }
+
+    const float theta = orig_co[0] * bend_factor;
+    const float sint = sinf(theta);
+    const float cost = cosf(theta);
+
+    float new_co[3];
+    new_co[0] = -(orig_co[1] - 1.0f / bend_factor) * sint;
+    new_co[1] = (orig_co[1] - 1.0f / bend_factor) * cost + 1.0f / bend_factor;
+    new_co[2] = orig_co[2];
+
+    float final_co[3];
+    float disp[3];
+    mul_v3_m4v3(final_co, ik_chain->bend_mat, new_co);
+
+    sub_v3_v3v3(disp, final_co, orig_data.co);
+    mul_v3_fl(disp, ik_chain_weight);
+    add_v3_v3v3(final_pos, orig_data.co, disp);
+
+    float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
+    copy_v3_v3(target_co, final_pos);
+
+    if (vd.mvert) {
+      vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
+    }
+  }
+  BKE_pbvh_vertex_iter_end;
+}
+
 static void do_pose_brush_task_cb_ex(void *__restrict userdata,
                                      const int n,
                                      const TaskParallelTLS *__restrict UNUSED(tls))
@@ -667,6 +737,7 @@ static int pose_brush_num_effective_segments(const Brush *brush)
    * artifacts in the areas affected by multiple segments. */
   if (ELEM(brush->pose_deform_type,
            BRUSH_POSE_DEFORM_SCALE_TRASLATE,
+           BRUSH_POSE_DEFORM_BEND,
            BRUSH_POSE_DEFORM_SQUASH_STRETCH)) {
     return 1;
   }
@@ -1111,6 +1182,59 @@ static void sculpt_pose_do_squash_stretch_deform(SculptSession *ss, Brush *UNUSE
   pose_solve_scale_chain(ik_chain, scale);
 }
 
+static void sculpt_pose_do_bend_deform(SculptSession *ss, Brush *UNUSED(brush))
+{
+  const int totvert = SCULPT_vertex_count_get(ss);
+  SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
+
+  if (SCULPT_stroke_is_first_brush_step_of_symmetry_pass(ss->cache)) {
+    sub_v3_v3v3(ik_chain->bend_mat[0],
+                ik_chain->segments[0].initial_head,
+                ik_chain->segments[0].initial_orig);
+    normalize_v3(ik_chain->bend_mat[0]);
+    copy_v3_v3(ik_chain->bend_mat[2], ss->cache->view_normal);
+    normalize_v3(ik_chain->bend_mat[2]);
+    cross_v3_v3v3(ik_chain->bend_mat[1], ik_chain->bend_mat[0], ik_chain->bend_mat[2]);
+    normalize_v3(ik_chain->bend_mat[1]);
+    copy_v3_v3(ik_chain->bend_mat[3], ik_chain->segments[0].initial_orig);
+    ik_chain->bend_mat[3][3] = 1.0f;
+    invert_m4_m4(ik_chain->bend_mat_inv, ik_chain->bend_mat);
+
+    float lower = FLT_MAX;
+    float upper = -FLT_MAX;
+
+    float smd_limit[2];
+
+    for (int i = 0; i < totvert; i++) {
+      if (ik_chain->segments[0].weights[i] == 0.0f) {
+        continue;
+      }
+      float bend_space_vert_co[3];
+      mul_v3_m4v3(bend_space_vert_co, ik_chain->bend_mat_inv, SCULPT_vertex_co_get(ss, i));
+      lower = min_ff(lower, bend_space_vert_co[0]);
+      upper = max_ff(upper, bend_space_vert_co[0]);
+    }
+
+    ik_chain->bend_upper_limit = upper;
+    smd_limit[1] = lower + (upper - lower) * 1.0f;
+    smd_limit[0] = lower + (upper - lower) * 0.0f;
+    ik_chain->bend_limit = max_ff(FLT_EPSILON, smd_limit[1] - smd_limit[0]);
+  }
+
+  float *original_dir = ik_chain->bend_mat[0];
+  float current_dir[3];
+  float brush_location[3];
+  add_v3_v3v3(brush_location, ss->cache->initial_location, ss->cache->grab_delta);
+  sub_v3_v3v3(current_dir, brush_location, ik_chain->segments[0].initial_orig);
+  ik_chain->bend_factor = angle_signed_on_axis_v3v3_v3(
+      original_dir, current_dir, ss->cache->view_normal);
+  if (ik_chain->bend_factor > M_PI) {
+    ik_chain->bend_factor = ik_chain->bend_factor - (M_PI * 2.0f);
+  }
+
+  ik_chain->bend_factor = 2.0f * (ik_chain->bend_factor / ik_chain->bend_limit);
+}
+
 static void sculpt_pose_align_pivot_local_space(float r_mat[4][4],
                                                 ePaintSymmetryFlags symm,
                                                 ePaintSymmetryAreas symm_area,
@@ -1159,6 +1283,9 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
     case BRUSH_POSE_DEFORM_SQUASH_STRETCH:
       sculpt_pose_do_squash_stretch_deform(ss, brush);
       break;
+    case BRUSH_POSE_DEFORM_BEND:
+      sculpt_pose_do_bend_deform(ss, brush);
+      break;
   }
 
   /* Flip the segment chain in all symmetry axis and calculate the transform matrices for each
@@ -1229,7 +1356,13 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
 
   TaskParallelSettings settings;
   BKE_pbvh_parallel_range_settings(&settings, true, totnode);
-  BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
+
+  if (brush->pose_deform_type == BRUSH_POSE_DEFORM_BEND) {
+    BLI_task_parallel_range(0, totnode, &data, do_pose_brush_bend_task_cb_ex, &settings);
+  }
+  else {
+    BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings);
+  }
 }
 
 void SCULPT_pose_ik_chain_free(SculptPoseIKChain *ik_chain)
diff --git a/source/blender/makesdna/DNA_brush_enums.h b/source/blender/makesdna/DNA_brush_enums.h
index e64a5bc4ea7..9db37306af2 100644
--- a/source/blender/makesdna/DNA_brush_enums.h
+++ b/source/blender/makesdna/DNA_brush_enums.h
@@ -252,6 +252,7 @@ typedef enum eBrushPoseDeformType {
   BRUSH_POSE_DEFORM_ROTATE_TWIST = 0,
   BRUSH_POSE_DEFORM_SCALE_TRASLATE = 1,
   BRUSH_POSE_DEFORM_SQUASH_STRETCH = 2,
+  BRUSH_POSE_DEFORM_BEND = 3,
 } eBrushPoseDeformType;
 
 typedef enum eBrushPoseOriginType {
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 5f414aa2bdd..f6372a0c240 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -630,7 +630,7 @@ enum {
  */
 #define BA_TRANSFORM_LOCKED_IN_PLACE (1 << 7)
 
-#define BA_TRANSFORM_CHILD (1 << 8) /* child of a transformed object */
+#define BA_TRANSFORM_CHILD (1 << 8)   /* child of a transformed object */
 #define BA_TRANSFORM_PARENT (1 << 13) /* parent of a transformed object */
 
 #define OB_FROMDUPLI (1 << 9)
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 90444e7f4ce..165f3f342d7 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -2197,6 +2197,7 @@ static void rna_def_brush(BlenderRNA *brna)
       {BRUSH_POSE_DEFORM_ROTATE_TWIST, "ROTATE_TWIST", 0, "Rotate/Twist", ""},
       {BRUSH_POSE_DEFORM_SCALE_TRASLATE, "SCALE_TRANSLATE", 0, "Scale/Translate", ""},
       {BRUSH_POSE_DEFORM_SQUASH_STRETCH, "SQUASH_STRETCH", 0, "Squash & Stretch", ""},
+      {BRUSH_POSE_DEFORM_BEND, "BEND", 0, "Bend", ""},
       {0, NULL, 0, NULL, NULL},
   };



More information about the Bf-blender-cvs mailing list