[Bf-blender-cvs] [c3279be222b] master: Sculpt: Multiplane Scrape Brush

Pablo Dobarro noreply at git.blender.org
Thu Nov 21 18:14:06 CET 2019


Commit: c3279be222bdca1981a8c1a8582b19a7e693009b
Author: Pablo Dobarro
Date:   Wed Nov 6 19:39:34 2019 +0100
Branches: master
https://developer.blender.org/rBc3279be222bdca1981a8c1a8582b19a7e693009b

Sculpt: Multiplane Scrape Brush

The Multiplane Scrape brush creates sharp edges with a given fixed angle by trimming the mesh with two planes in local space at the same time.  When working with stylized or hard surface models, this brush produces way better results and is more predictable than any other crease/flatten brush based on curves and alphas.
It is also the first brush we have than can produce hard surface concave creases.
The Multiplane Scrape Brush also has a dynamic mode where it samples the surface to fit the angle and scrape planes during a stroke. With this mode enabled you can sculpt multiple times over the same edge without creating artifacts.
It can also create creases that change between concave and convex during the same stroke.

The behavior of this brush will improve after merging patches like D5993 and its behavior in concave creases can still be improved, so I will keep tweaking its parameters and default values once we have all brush properties available.

Reviewed By: jbakker

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

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

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenkernel/intern/brush.c
M	source/blender/blenloader/intern/versioning_defaults.c
M	source/blender/editors/sculpt_paint/paint_cursor.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/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index efd26c2daf8..63e5aa53077 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -430,6 +430,13 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
                 col.separator()
                 row = col.row()
                 row.prop(brush, "use_grab_active_vertex")
+            elif brush.sculpt_tool == 'MULTIPLANE_SCRAPE':
+                row = col.row()
+                row.prop(brush, "multiplane_scrape_angle")
+                row = col.row()
+                row.prop(brush, "use_multiplane_scrape_dynamic")
+                row = col.row()
+                row.prop(brush, "show_multiplane_scrape_planes_preview")
 
             # topology_rake_factor
             if (
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index eebed72103f..794876ec444 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -938,6 +938,14 @@ void BKE_brush_sculpt_reset(Brush *br)
       br->curve_preset = BRUSH_CURVE_SPHERE;
       br->spacing = 6;
       break;
+    case SCULPT_TOOL_MULTIPLANE_SCRAPE:
+      br->flag2 |= BRUSH_MULTIPLANE_SCRAPE_DYNAMIC | BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW;
+      br->alpha = 0.7f;
+      br->normal_radius_factor = 0.70f;
+      br->multiplane_scrape_angle = 60;
+      br->curve_preset = BRUSH_CURVE_SMOOTH;
+      br->spacing = 5;
+      break;
     case SCULPT_TOOL_CREASE:
       br->flag |= BRUSH_DIR_IN;
       br->alpha = 0.25;
@@ -1010,6 +1018,7 @@ void BKE_brush_sculpt_reset(Brush *br)
     case SCULPT_TOOL_FLATTEN:
     case SCULPT_TOOL_FILL:
     case SCULPT_TOOL_SCRAPE:
+    case SCULPT_TOOL_MULTIPLANE_SCRAPE:
       br->add_col[0] = 1.0f;
       br->add_col[1] = 0.39f;
       br->add_col[2] = 0.39f;
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 05758b446ad..45ec6eef813 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -509,6 +509,14 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
       brush->sculpt_tool = SCULPT_TOOL_POSE;
     }
 
+    brush_name = "Multiplane Scrape";
+    brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2);
+    if (!brush) {
+      brush = BKE_brush_add(bmain, brush_name, OB_MODE_SCULPT);
+      id_us_min(&brush->id);
+      brush->sculpt_tool = SCULPT_TOOL_MULTIPLANE_SCRAPE;
+    }
+
     brush_name = "Simplify";
     brush = BLI_findstring(&bmain->brushes, brush_name, offsetof(ID, name) + 2);
     if (!brush) {
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index b9af33e7ad6..ac738f326a3 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1214,6 +1214,70 @@ static void sculpt_geometry_preview_lines_draw(const uint gpuattr, SculptSession
   }
 }
 
+static void sculpt_multiplane_scrape_preview_draw(const uint gpuattr,
+                                                  SculptSession *ss,
+                                                  float *outline_col,
+                                                  float outline_alpha)
+{
+  float local_mat_inv[4][4];
+  invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat);
+  GPU_matrix_mul(local_mat_inv);
+  float angle = ss->cache->multiplane_scrape_sampled_angle;
+  if (ss->cache->pen_flip || ss->cache->invert) {
+    angle = -angle;
+  }
+
+  float offset = ss->cache->radius * 0.25f;
+
+  float p[3] = {0.0f, 0.0f, ss->cache->radius};
+  float y_axis[3] = {0.0f, 1.0f, 0.0f};
+  float p_l[3];
+  float p_r[3];
+  float area_center[3] = {0.0f, 0.0f, 0.0f};
+  rotate_v3_v3v3fl(p_r, p, y_axis, DEG2RADF((angle + 180) * 0.5f));
+  rotate_v3_v3v3fl(p_l, p, y_axis, DEG2RADF(-(angle + 180) * 0.5f));
+
+  immBegin(GPU_PRIM_LINES, 14);
+  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
+  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
+
+  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
+  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
+
+  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+
+  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
+  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
+
+  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
+  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
+
+  immEnd();
+
+  immUniformColor3fvAlpha(outline_col, outline_alpha * 0.1f);
+  immBegin(GPU_PRIM_TRIS, 12);
+  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
+  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
+  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
+
+  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
+  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
+  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
+  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
+  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
+
+  immEnd();
+}
+
 static bool paint_use_2d_cursor(ePaintMode mode)
 {
   if (mode >= PAINT_MODE_TEXTURE_3D) {
@@ -1516,6 +1580,24 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
             }
           }
 
+          if (brush->sculpt_tool == SCULPT_TOOL_MULTIPLANE_SCRAPE &&
+              brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW && !ss->cache->first_time) {
+            GPU_matrix_push_projection();
+            ED_view3d_draw_setup_view(CTX_wm_window(C),
+                                      CTX_data_depsgraph_pointer(C),
+                                      CTX_data_scene(C),
+                                      ar,
+                                      CTX_wm_view3d(C),
+                                      NULL,
+                                      NULL,
+                                      NULL);
+            GPU_matrix_push();
+            GPU_matrix_mul(vc.obact->obmat);
+            sculpt_multiplane_scrape_preview_draw(pos, ss, outline_col, outline_alpha);
+            GPU_matrix_pop();
+            GPU_matrix_pop_projection();
+          }
+
           wmWindowViewport(win);
         }
       }
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index fcc2a7a08b3..6cda6ccac06 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -1771,6 +1771,10 @@ static float brush_strength(const Sculpt *sd,
         return 0.125f * alpha * flip * pressure * overlap * feather;
       }
 
+    case SCULPT_TOOL_MULTIPLANE_SCRAPE:
+      overlap = (1.0f + overlap) / 2.0f;
+      return alpha * flip * pressure * overlap * feather;
+
     case SCULPT_TOOL_FILL:
     case SCULPT_TOOL_SCRAPE:
     case SCULPT_TOOL_FLATTEN:
@@ -4843,6 +4847,341 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
   BKE_pbvh_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings);
 }
 
+/* -------------------------------------------------------------------- */
+
+/** \name Sculpt Multiplane Scrape Brush
+ * \{ */
+
+typedef struct MultiplaneScrapeSampleData {
+  float area_cos[2][3];
+  float area_nos[2][3];
+  int area_count[2];
+} MultiplaneScrapeSampleData;
+
+static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
+                                                   const int n,
+                                                   const TaskParallelTLS *__restrict tls)
+{
+  SculptThreadedTaskData *data = userdata;
+  SculptSession *ss = data->ob->sculpt;
+  const Brush *brush = data->brush;
+  MultiplaneScrapeSampleData *mssd = tls->userdata_chunk;
+  float(*mat)[4] = data->mat;
+
+  PBVHVertexIter vd;
+
+  SculptBrushTest test;
+  SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
+      ss, &test, brush->falloff_shape);
+
+  /* Apply the brush normal radius to the test before sampling */
+  float test_radius = sqrtf(test.radius_squared);
+  test_radius *= brush->normal_radius_factor;
+  test.radius_squared = test_radius * test_radius;
+
+  BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
+  {
+
+    if (sculpt_brush_test_sq_fn(&test, vd.co)) {
+      float local_co[3];
+      float normal[3];
+      if (vd.no) {
+        normal_short_to_float_v3(normal, vd.no);
+      }
+      else {
+        copy_v3_v3(normal, vd.fno);
+      }
+      mul_v3_m4v3(local_co, mat, vd.co);
+      /* Use the brush falloff to weight the sampled normals */
+      const float fade = tex_strength(ss,
+                                      brush,
+                                      vd.co,
+                                      sqrtf(test.dist),
+                                      vd.no,
+                                      vd.fno,
+                                      vd.mask ? *vd.mask : 0.0f,
+                                      vd.index,
+                                      tls->thread_id);
+
+      /* Sample the normal and area of the +X and -X axis individually */
+      if (local_co[0] > 0.0f) {
+        madd_v3_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list