[Bf-blender-cvs] [a3e7440cfdd] master: Sculpt: Grab Active Vertex and Dynamic Mesh Preview

Pablo Dobarro noreply at git.blender.org
Tue Sep 10 16:27:11 CEST 2019


Commit: a3e7440cfdd2f307e5c57922fd22e8770f0b8390
Author: Pablo Dobarro
Date:   Mon Sep 9 22:23:54 2019 +0200
Branches: master
https://developer.blender.org/rBa3e7440cfdd2f307e5c57922fd22e8770f0b8390

Sculpt: Grab Active Vertex and Dynamic Mesh Preview

Grab active vertex snaps the maximum strength of the grab brush to the highlighted active vertex, making it easier to manipulate low poly models or meshes with subdivision surfaces.
Dynamic Mesh Preview generates a list of connected vertices from the active vertex and draws them from the cursor code. This helps to visualize the real geometry the user is manipulating from sculpt mode when there are active modifiers.

Reviewed By: brecht

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

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

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/blenkernel/intern/paint.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 c39f2ea051d..d96f8b04058 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -380,6 +380,11 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
             row = col.row()
             row.prop(brush, "use_automasking_topology")
 
+            if brush.sculpt_tool == 'GRAB':
+                col.separator()
+                row = col.row()
+                row.prop(brush, "grab_active_vertex")
+
             # topology_rake_factor
             if (
                     capabilities.has_topology_rake and
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 10c3f42bba7..ed4bcee3541 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -269,6 +269,10 @@ typedef struct SculptSession {
 
   float pivot_pos[3];
 
+  /* Dynamic mesh preview */
+  int *preview_vert_index_list;
+  int preview_vert_index_count;
+
   union {
     struct {
       struct SculptVertexPaintGeomMap gmap;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index b386a0d4483..5980aa456e2 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1060,6 +1060,10 @@ void BKE_sculptsession_free(Object *ob)
       MEM_freeN(ss->deform_imats);
     }
 
+    if (ss->preview_vert_index_list) {
+      MEM_freeN(ss->preview_vert_index_list);
+    }
+
     BKE_sculptsession_free_vwpaint_data(ob->sculpt);
 
     MEM_freeN(ss);
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index a000da57383..62e44bf04c5 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1180,6 +1180,20 @@ static void cursor_draw_point_with_symmetry(const uint gpuattr,
   }
 }
 
+static void sculpt_geometry_preview_lines_draw(const uint gpuattr, SculptSession *ss)
+{
+  immUniformColor4f(1.0f, 1.0f, 1.0f, 0.6f);
+  GPU_depth_test(true);
+  GPU_line_width(1.0f);
+  if (ss->preview_vert_index_count > 0) {
+    immBegin(GPU_PRIM_LINES, ss->preview_vert_index_count);
+    for (int i = 0; i < ss->preview_vert_index_count; i++) {
+      immVertex3fv(gpuattr, sculpt_vertex_co_get(ss, ss->preview_vert_index_list[i]));
+    }
+    immEnd();
+  }
+}
+
 static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
 {
   Scene *scene = CTX_data_scene(C);
@@ -1348,6 +1362,17 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
         imm_draw_circle_wire_3d(pos, 0, 0, rds, 40);
         GPU_matrix_pop();
 
+        /* Update and draw dynamic mesh preview lines */
+        GPU_matrix_push();
+        GPU_matrix_mul(vc.obact->obmat);
+        if (brush->sculpt_tool == SCULPT_TOOL_GRAB && brush->flag2 & BRUSH_GRAB_ACTIVE_VERTEX) {
+          if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->modifiers_active) {
+            sculpt_geometry_preview_lines_update(C, ss, rds);
+            sculpt_geometry_preview_lines_draw(pos, ss);
+          }
+        }
+        GPU_matrix_pop();
+
         GPU_matrix_pop_projection();
 
         wmWindowViewport(win);
@@ -1370,6 +1395,27 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
           add_v3_v3(cursor_location, ss->cache->grab_delta);
         }
         cursor_draw_point_with_symmetry(pos, ar, cursor_location, sd, vc.obact, ss->cache->radius);
+
+        /* Draw cached dynamic mesh preview lines */
+        if (brush->sculpt_tool == SCULPT_TOOL_GRAB && brush->flag2 & BRUSH_GRAB_ACTIVE_VERTEX) {
+          if (BKE_pbvh_type(ss->pbvh) == PBVH_FACES && ss->modifiers_active) {
+            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_geometry_preview_lines_draw(pos, ss);
+            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 792a75746d3..688adc56ef5 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -31,6 +31,7 @@
 #include "BLI_gsqueue.h"
 #include "BLI_stack.h"
 #include "BLI_task.h"
+#include "BLI_stack.h"
 #include "BLI_utildefines.h"
 #include "BLI_ghash.h"
 
@@ -99,7 +100,7 @@
 
 /* Do not use these functions while working with PBVH_GRIDS data in SculptSession */
 
-static float *sculpt_vertex_co_get(SculptSession *ss, int index)
+float *sculpt_vertex_co_get(SculptSession *ss, int index)
 {
   switch (BKE_pbvh_type(ss->pbvh)) {
     case PBVH_FACES:
@@ -5902,7 +5903,13 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
     float grab_location[3], imat[4][4], delta[3], loc[3];
 
     if (cache->first_time) {
-      copy_v3_v3(cache->orig_grab_location, cache->true_location);
+      if (tool == SCULPT_TOOL_GRAB && brush->flag2 & BRUSH_GRAB_ACTIVE_VERTEX) {
+        copy_v3_v3(cache->orig_grab_location,
+                   sculpt_vertex_co_get(ss, sculpt_active_vertex_get(ss)));
+      }
+      else {
+        copy_v3_v3(cache->orig_grab_location, cache->true_location);
+      }
     }
     else if (tool == SCULPT_TOOL_SNAKE_HOOK) {
       add_v3_v3(cache->true_location, cache->grab_delta);
@@ -5955,7 +5962,12 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
     copy_v3_v3(cache->old_grab_location, grab_location);
 
     if (tool == SCULPT_TOOL_GRAB) {
-      copy_v3_v3(cache->anchored_location, cache->true_location);
+      if (brush->flag2 & BRUSH_GRAB_ACTIVE_VERTEX) {
+        copy_v3_v3(cache->anchored_location, cache->orig_grab_location);
+      }
+      else {
+        copy_v3_v3(cache->anchored_location, cache->true_location);
+      }
     }
     else if (tool == SCULPT_TOOL_ELASTIC_DEFORM) {
       copy_v3_v3(cache->anchored_location, cache->true_location);
@@ -8995,6 +9007,72 @@ static void SCULPT_OT_mask_expand(wmOperatorType *ot)
                          2000);
 }
 
+void sculpt_geometry_preview_lines_update(bContext *C, SculptSession *ss, float radius)
+{
+  Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+  Object *ob = CTX_data_active_object(C);
+
+  ss->preview_vert_index_count = 0;
+  int totpoints = 0;
+
+  /* This function is called from the cursor drawing code, so the PBVH may not be build yet */
+  if (!ss->pbvh) {
+    return;
+  }
+
+  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+  if (!ss->pmap) {
+    return;
+  }
+
+  float brush_co[3];
+  copy_v3_v3(brush_co, sculpt_vertex_co_get(ss, sculpt_active_vertex_get(ss)));
+
+  char *visited_vertices = MEM_callocN(sculpt_vertex_count_get(ss) * sizeof(char),
+                                       "visited vertices");
+
+  if (ss->preview_vert_index_list == NULL) {
+    ss->preview_vert_index_list = MEM_callocN(4 * sizeof(int) * sculpt_vertex_count_get(ss),
+                                              "preview lines");
+  }
+
+  BLI_Stack *not_visited_vertices = BLI_stack_new(sizeof(VertexTopologyIterator),
+                                                  "Not visited vertices stack");
+  VertexTopologyIterator mevit;
+  mevit.v = sculpt_active_vertex_get(ss);
+  BLI_stack_push(not_visited_vertices, &mevit);
+
+  while (!BLI_stack_is_empty(not_visited_vertices)) {
+    VertexTopologyIterator c_mevit;
+    BLI_stack_pop(not_visited_vertices, &c_mevit);
+    SculptVertexNeighborIter ni;
+    sculpt_vertex_neighbors_iter_begin(ss, c_mevit.v, ni)
+    {
+      VertexTopologyIterator new_entry;
+      new_entry.v = ni.index;
+      new_entry.it = c_mevit.it + 1;
+      ss->preview_vert_index_list[totpoints] = c_mevit.v;
+      totpoints++;
+      ss->preview_vert_index_list[totpoints] = new_entry.v;
+      totpoints++;
+      if (visited_vertices[(int)ni.index] == 0) {
+        visited_vertices[(int)ni.index] = 1;
+        if (len_squared_v3v3(brush_co, sculpt_vertex_co_get(ss, new_entry.v)) < radius * radius) {
+          BLI_stack_push(not_visited_vertices, &new_entry);
+        }
+      }
+    }
+    sculpt_vertex_neighbors_iter_end(ni)
+  }
+
+  BLI_stack_free(not_visited_vertices);
+
+  MEM_freeN(visited_vertices);
+
+  ss->preview_vert_index_count = totpoints;
+}
+
 void ED_operatortypes_sculpt(void)
 {
   WM_operatortype_append(SCULPT_OT_brush_stroke);
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 3be8e0f7bb7..5995eadea59 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -57,6 +57,10 @@ bool sculpt_cursor_geometry_info_update(bContext *C,
                                         SculptCursorGeometryInfo *out,
                                         const float mouse[2],
                                         bool use_sampled_normal);
+void sculpt_geometry_preview_lines_update(bContext *C, struct SculptSession *ss, float radius);
+
+/* Sculpt PBVH abstraction API */
+float *sculpt_vertex_co_get(struct SculptSession *ss, int index);
 
 /* Dynamic topology */
 void sculpt_pbvh_clear(Object *ob);
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 56e255b132a..5901163c3a9 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -244,6 +244,8 @@ typedef struct Brush {
   int size;
   /** General purpose flag. */
   int

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list