[Bf-blender-cvs] [4a373afa5fb] master: Sculpt: Cloth brush

Pablo Dobarro noreply at git.blender.org
Fri Feb 28 16:59:47 CET 2020


Commit: 4a373afa5fb8f9eab92314fac1b140b7803f30fe
Author: Pablo Dobarro
Date:   Fri Feb 28 14:40:40 2020 +0100
Branches: master
https://developer.blender.org/rB4a373afa5fb8f9eab92314fac1b140b7803f30fe

Sculpt: Cloth brush

This brush has a simple physics solver that helps when sculpting cloth.

- The mass and the damping properties of the simulation are properties of the brush.
- It has two additional radius control to limit the influence and falloff of the simulation.
- Masked vertices are pinned in the simulation, and it applies the sculpt gravity directly in the solver.
- The Cloth Brush has 7 deformation modes with 2 falloff types (radial and plane).

The brush can create the constraints only on the required PBVH nodes, so the simulation is isolated on high poly meshes. As long
as the brush size is not too big it should be possible to keep it real time.

Known issues:
- The way constraints are created is extremely basic and it creates repeated constraints. Maybe there is another way to create fewer constraints while keeping the simulation quality decent. This part can also be multithreaded. (As it is it works ok, but it could be better)

Reviewed By: jbakker

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

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

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/editors/sculpt_paint/CMakeLists.txt
M	source/blender/editors/sculpt_paint/paint_cursor.c
M	source/blender/editors/sculpt_paint/paint_stroke.c
M	source/blender/editors/sculpt_paint/sculpt.c
A	source/blender/editors/sculpt_paint/sculpt_cloth.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/gpu/GPU_immediate_util.h
M	source/blender/gpu/intern/gpu_immediate_util.c
M	source/blender/makesdna/DNA_brush_defaults.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 24016061194..704af1ae307 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -626,6 +626,18 @@ def brush_settings(layout, context, brush, popover=False):
             layout.prop(brush, "pose_ik_segments")
             layout.prop(brush, "use_pose_ik_anchored")
             layout.separator()
+
+        if brush.sculpt_tool == 'CLOTH':
+            layout.separator()
+            layout.prop(brush, "cloth_sim_limit")
+            layout.prop(brush, "cloth_sim_falloff")
+            layout.separator()
+            layout.prop(brush, "cloth_deform_type")
+            layout.prop(brush, "cloth_force_falloff_type")
+            layout.separator()
+            layout.prop(brush, "cloth_mass")
+            layout.prop(brush, "cloth_damping")
+            layout.separator()
         
         if brush.sculpt_tool == 'SCRAPE':
             row = layout.row()
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 28e564f0fe2..4c274804a07 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -245,6 +245,31 @@ typedef struct SculptPoseIKChain {
   int tot_segments;
 } SculptPoseIKChain;
 
+/* Cloth Brush */
+
+typedef struct SculptClothLengthConstraint {
+  int v1;
+  int v2;
+
+  float length;
+} SculptClothLengthConstraint;
+
+typedef struct SculptClothSimulation {
+  SculptClothLengthConstraint *length_constraints;
+  int tot_length_constraints;
+  int capacity_length_constraints;
+  float *length_constraint_tweak;
+
+  float mass;
+  float damping;
+
+  float (*acceleration)[3];
+  float (*pos)[3];
+  float (*init_pos)[3];
+  float (*prev_pos)[3];
+
+} SculptClothSimulation;
+
 /* Session data (mode-specific) */
 
 typedef struct SculptSession {
@@ -298,6 +323,7 @@ typedef struct SculptSession {
   float cursor_radius;
   float cursor_location[3];
   float cursor_normal[3];
+  float cursor_sampled_normal[3];
   float cursor_view_normal[3];
 
   /* TODO(jbakker): Replace rv3d adn v3d with ViewContext */
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 15ef6479007..09b3ad89e73 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -1014,6 +1014,14 @@ void BKE_brush_sculpt_reset(Brush *br)
       br->flag &= ~BRUSH_SPACE;
       br->flag &= ~BRUSH_SPACE_ATTEN;
       break;
+    case SCULPT_TOOL_CLOTH:
+      br->cloth_mass = 1.0f;
+      br->cloth_damping = 0.01f;
+      br->cloth_sim_limit = 2.5f;
+      br->cloth_sim_falloff = 0.75f;
+      br->cloth_deform_type = BRUSH_CLOTH_DEFORM_DRAG;
+      br->flag &= ~(BRUSH_ALPHA_PRESSURE | BRUSH_SIZE_PRESSURE);
+      break;
     default:
       break;
   }
@@ -1081,6 +1089,15 @@ void BKE_brush_sculpt_reset(Brush *br)
       br->sub_col[1] = 0.750000;
       br->sub_col[2] = 0.750000;
       break;
+
+    case SCULPT_TOOL_CLOTH:
+      br->add_col[0] = 1.0f;
+      br->add_col[1] = 0.5f;
+      br->add_col[2] = 0.1f;
+      br->sub_col[0] = 1.0f;
+      br->sub_col[1] = 0.5f;
+      br->sub_col[2] = 0.1f;
+      break;
     default:
       break;
   }
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index a5cc262ddcd..2522bc0f5cc 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -59,6 +59,7 @@ set(SRC
   paint_vertex_weight_ops.c
   paint_vertex_weight_utils.c
   sculpt.c
+  sculpt_cloth.c
   sculpt_undo.c
   sculpt_uv.c
 
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index d5bb552b470..cabf17e8534 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1526,11 +1526,21 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
           immUniformColor3fvAlpha(outline_col, outline_alpha);
           GPU_line_width(2.0f);
           imm_draw_circle_wire_3d(pos, 0, 0, rds, 80);
+
           GPU_line_width(1.0f);
           immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
           imm_draw_circle_wire_3d(pos, 0, 0, rds * clamp_f(brush->alpha, 0.0f, 1.0f), 80);
           GPU_matrix_pop();
 
+          /* Cloth brush simulation areas. */
+          if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
+            GPU_matrix_push();
+            const float white[3] = {1.0f, 1.0f, 1.0f};
+            SCULPT_cloth_simulation_limits_draw(
+                pos, brush, vc.obact->obmat, gi.location, gi.normal, rds, 1.0f, white, 0.25f);
+            GPU_matrix_pop();
+          }
+
           /* Update and draw dynamic mesh preview lines. */
           GPU_matrix_push();
           GPU_matrix_mul(vc.obact->obmat);
@@ -1620,6 +1630,48 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
             GPU_matrix_pop_projection();
           }
 
+          if (brush->sculpt_tool == SCULPT_TOOL_CLOTH && !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);
+
+            /* Plane falloff preview */
+            if (brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_PLANE) {
+              GPU_matrix_push();
+              GPU_matrix_mul(vc.obact->obmat);
+              SCULPT_cloth_plane_falloff_preview_draw(pos, ss, outline_col, outline_alpha);
+              GPU_matrix_pop();
+            }
+
+            /* Display the simulation limits if sculpting outside them. */
+            /* This does not makes much sense of plane fallof as the fallof is infinte. */
+            else if (brush->cloth_force_falloff_type == BRUSH_CLOTH_FORCE_FALLOFF_RADIAL) {
+              if (len_v3v3(ss->cache->true_location, ss->cache->true_initial_location) >
+                  ss->cache->radius * (1.0f + brush->cloth_sim_limit)) {
+                const float red[3] = {1.0f, 0.2f, 0.2f};
+                GPU_matrix_push();
+                SCULPT_cloth_simulation_limits_draw(pos,
+                                                    brush,
+                                                    vc.obact->obmat,
+                                                    ss->cache->true_initial_location,
+                                                    ss->cache->true_initial_normal,
+                                                    ss->cache->radius,
+                                                    2.0f,
+                                                    red,
+                                                    0.8f);
+                GPU_matrix_pop();
+              }
+            }
+
+            GPU_matrix_pop_projection();
+          }
+
           wmWindowViewport(win);
         }
       }
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 372ea954630..4abeb937758 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -228,6 +228,10 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
                SCULPT_TOOL_THUMB)) {
         return false;
       }
+      else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
+               brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
+        return false;
+      }
       else {
         return true;
       }
@@ -259,6 +263,7 @@ static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode m
                SCULPT_TOOL_THUMB,
                SCULPT_TOOL_SNAKE_HOOK,
                SCULPT_TOOL_ELASTIC_DEFORM,
+               SCULPT_TOOL_CLOTH,
                SCULPT_TOOL_POSE)) {
         return false;
       }
@@ -999,6 +1004,10 @@ bool paint_space_stroke_enabled(Brush *br, ePaintMode mode)
 
 static bool sculpt_is_grab_tool(Brush *br)
 {
+
+  if (br->sculpt_tool == SCULPT_TOOL_CLOTH && br->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
+    return true;
+  }
   return ELEM(br->sculpt_tool,
               SCULPT_TOOL_GRAB,
               SCULPT_TOOL_ELASTIC_DEFORM,
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 55ddc82c3f8..9a01be9d7b3 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -112,7 +112,7 @@ static void sculpt_vertex_random_access_init(SculptSession *ss)
   }
 }
 
-static int sculpt_vertex_count_get(SculptSession *ss)
+int sculpt_vertex_count_get(SculptSession *ss)
 {
   switch (BKE_pbvh_type(ss->pbvh)) {
     case PBVH_FACES:
@@ -171,7 +171,7 @@ static void sculpt_vertex_normal_get(SculptSession *ss, int index, float no[3])
   }
 }
 
-static float sculpt_vertex_mask_get(SculptSession *ss, int index)
+float sculpt_vertex_mask_get(SculptSession *ss, int index)
 {
   BMVert *v;
   float *mask;
@@ -220,22 +220,6 @@ static void sculpt_active_vertex_normal_get(SculptSession *ss, float normal[3])
 
 #define SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY 256
 
-typedef struct SculptVertexNeighborIter {
-  /* Storage */
-  int *neighbors;
-  int size;
-  int capacity;
-  int neighbors_fixed[SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY];
-
-  /* Internal iterator. */
-  int num_duplicates;
-  int i;
-
-  /* Public */
-  int index;
-  bool is_duplicate;
-} SculptVertexNeighborIter;
-
 static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter, int neighbor_index)
 {
   for (int i = 0; i < iter->size; i++) {
@@ -342,10 +326,10 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
   }
 }
 
-static void sculpt

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list