Pose brush: Smooth Iterations Brush Property
authorPablo Dobarro <pablodp606@gmail.com>
Sun, 17 Nov 2019 00:09:08 +0000 (01:09 +0100)
committerPablo Dobarro <pablodp606@gmail.com>
Thu, 21 Nov 2019 17:41:58 +0000 (18:41 +0100)
The smooth iterations of the pose factor were hardcoded to 4. This works fine in most situations when you are posing a low poly mesh, which is the main use case of this tool. I added the smooth iterations as a brush property in case you need to pose a high poly mesh directly without producing artifacts.

Reviewed By: jbakker

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

release/scripts/startup/bl_ui/space_view3d_toolbar.py
source/blender/blenkernel/intern/brush.c
source/blender/blenloader/intern/versioning_280.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/makesdna/DNA_brush_defaults.h
source/blender/makesdna/DNA_brush_types.h
source/blender/makesrna/intern/rna_brush.c

index 63e5aa53077372cfa99cb80a3353b9a1c86b38f0..2f260b59c4fa1d6f6d3b6f23c0a0febd72ab702b 100644 (file)
@@ -426,6 +426,8 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
             elif brush.sculpt_tool == 'POSE':
                 row = col.row()
                 row.prop(brush, "pose_offset")
+                row = col.row()
+                row.prop(brush, "pose_smooth_iterations")
             elif brush.sculpt_tool == 'GRAB':
                 col.separator()
                 row = col.row()
index 794876ec444c3f7163cb0c8969563b14de76d900..15a9b0b9c6a1d096ff6e7da70118f166c76dd7c4 100644 (file)
@@ -981,6 +981,7 @@ void BKE_brush_sculpt_reset(Brush *br)
       br->flag &= ~BRUSH_SPACE_ATTEN;
       break;
     case SCULPT_TOOL_POSE:
+      br->pose_smooth_iterations = 4;
       br->flag &= ~BRUSH_ALPHA_PRESSURE;
       br->flag &= ~BRUSH_SPACE;
       br->flag &= ~BRUSH_SPACE_ATTEN;
index 488cf6b02133fede80625f62353afbc31d5f181d..33a0da7457f67dca5bbcb36331044ac8fe3cf4a5 100644 (file)
@@ -3934,7 +3934,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
 
   {
     /* Versioning code until next subversion bump goes here. */
-
     for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
       for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
         sa->flag &= ~AREA_FLAG_UNUSED_6;
@@ -3972,5 +3971,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
         br->dash_samples = 20;
       }
     }
+
+    /* Pose brush smooth iterations */
+    if (!DNA_struct_elem_find(fd->filesdna, "Brush", "float", "pose_smooth_itereations")) {
+      for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
+        br->pose_smooth_iterations = 4;
+      }
+    }
   }
 }
index 6cda6ccac067f06a578eb7ad93568d1f44bc47e7..b7fb49d357fdedf163772fb714d1ae3db40221eb 100644 (file)
@@ -3940,7 +3940,7 @@ static void sculpt_pose_brush_init(
   };
 
   /* Smooth the pose brush factor for cleaner deformation */
-  for (int i = 0; i < 4; i++) {
+  for (int i = 0; i < br->pose_smooth_iterations; i++) {
     PBVHParallelSettings settings;
     BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode);
     BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings);
@@ -5705,7 +5705,12 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
     BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
   }
   else if (brush->sculpt_tool == SCULPT_TOOL_POSE) {
-    float final_radius = ss->cache->radius * (1 + brush->pose_offset);
+    /* After smoothing the pose factor an arbitrary number of times, the pose factor values can
+     * expand to nodes that are not inside the original radius of the brush. Using a slightly
+     * bigger radius should prevent those artifacts. */
+    /* We can optimize this further by removing the nodes that have all 0 values in the pose factor
+     * after calculating it. */
+    float final_radius = ss->cache->radius * 1.5f * (1.0f + brush->pose_offset);
     SculptSearchSphereData data = {
         .ss = ss,
         .sd = sd,
index ff1f8c9a1c02f11922f9d7cbc4c5474bcf77306e..9d3689ce4ee07216b6e044fcde2dcdcb5d7cc565 100644 (file)
@@ -95,6 +95,7 @@
  \
     /* sculpting defaults to the draw tool for new brushes */ \
     .sculpt_tool = SCULPT_TOOL_DRAW, \
+    .pose_smooth_iterations = 4, \
  \
     /* A kernel radius of 1 has almost no effect (T63233). */ \
     .blur_kernel_radius = 2, \
index c55ab81a733324a1d7218813a4ae40eaa3cec215..a7e15ac9547c154ec899ad986dc644045c8270fb 100644 (file)
@@ -334,6 +334,9 @@ typedef struct Brush {
 
   /* pose */
   float pose_offset;
+  int pose_smooth_iterations;
+
+  char _pad2[4];
 
   /* multiplane scrape */
   float multiplane_scrape_angle;
index 86b1ed9234902ada94d73cb88e5ddba8f7af0cd9..321f381569157f317b8c6dc146fd8333a8c1047d 100644 (file)
@@ -1887,6 +1887,15 @@ static void rna_def_brush(BlenderRNA *brna)
   RNA_def_property_ui_text(prop, "Plane Angle", "Angle between the planes of the crease");
   RNA_def_property_update(prop, 0, "rna_Brush_update");
 
+  prop = RNA_def_property(srna, "pose_smooth_iterations", PROP_INT, PROP_UNSIGNED);
+  RNA_def_property_int_sdna(prop, NULL, "pose_smooth_iterations");
+  RNA_def_property_range(prop, 0, 100);
+  RNA_def_property_ui_text(
+      prop,
+      "Smooth Iterations",
+      "Smooth iterations applied after calculating the pose factor of each vertex");
+  RNA_def_property_update(prop, 0, "rna_Brush_update");
+
   prop = RNA_def_property(srna, "auto_smooth_factor", PROP_FLOAT, PROP_FACTOR);
   RNA_def_property_float_sdna(prop, NULL, "autosmooth_factor");
   RNA_def_property_float_default(prop, 0);