[Bf-blender-cvs] [8c10e56331d] master: Sculpt: Cloth Brush Soft Body Influence property

Pablo Dobarro noreply at git.blender.org
Wed Jul 29 19:14:51 CEST 2020


Commit: 8c10e56331d0fb79d101c5edf214d7b327cc70c3
Author: Pablo Dobarro
Date:   Wed Jul 29 19:12:35 2020 +0200
Branches: master
https://developer.blender.org/rB8c10e56331d0fb79d101c5edf214d7b327cc70c3

Sculpt: Cloth Brush Soft Body Influence property

This property adds constraints to the simulation using the initial
location of the vertices, making it behave like a soft body. The
strength of these constraints can be modified with the brush parameter.
This makes some deformation modes more subtle and predictable, making it
possible to use the cloth brush to add surface detail in a more
controllable way without loosing completely the original shape of the
mesh.

Reviewed By: sergey

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

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

M	release/scripts/startup/bl_ui/properties_paint_common.py
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/editors/sculpt_paint/sculpt_cloth.c
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 6dde1e715bb..8cadad7e0d7 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -662,6 +662,7 @@ def brush_settings(layout, context, brush, popover=False):
             layout.separator()
             layout.prop(brush, "cloth_mass")
             layout.prop(brush, "cloth_damping")
+            layout.prop(brush, "cloth_constraint_softbody_strength")
             layout.separator()
 
         elif sculpt_tool == 'SCRAPE':
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 1c02aece06f..b9a8dbd762f 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -260,10 +260,20 @@ typedef struct SculptPoseIKChain {
 /* Cloth Brush */
 
 typedef struct SculptClothLengthConstraint {
-  int v1;
-  int v2;
+  /* Elements that are affected by the constraint. */
+  /* Element a should always be a mesh vertex with the index stored in elem_index_a as it is always
+   * deformed. Element b cound be another vertex of the same mesh or any other position (arbitrary
+   * point, position for a previous state). In that case, elem_index_a and elem_index_b should be
+   * the same to avoid affecting two different vertices when solving the constraints.
+   * *elem_position points to the position which is owned by the element. */
+  int elem_index_a;
+  float *elem_position_a;
+
+  int elem_index_b;
+  float *elem_position_b;
 
   float length;
+  float strength;
 } SculptClothLengthConstraint;
 
 typedef struct SculptClothSimulation {
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 4232be91034..91293b78dae 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -113,36 +113,71 @@ static bool cloth_brush_sim_has_length_constraint(SculptClothSimulation *cloth_s
   return BLI_edgeset_haskey(cloth_sim->created_length_constraints, v1, v2);
 }
 
+static void cloth_brush_reallocate_constraints(SculptClothSimulation *cloth_sim)
+{
+  if (cloth_sim->tot_length_constraints >= cloth_sim->capacity_length_constraints) {
+    cloth_sim->capacity_length_constraints += CLOTH_LENGTH_CONSTRAINTS_BLOCK;
+    cloth_sim->length_constraints = MEM_reallocN_id(cloth_sim->length_constraints,
+                                                    cloth_sim->capacity_length_constraints *
+                                                        sizeof(SculptClothLengthConstraint),
+                                                    "length constraints");
+  }
+}
+
 static void cloth_brush_add_length_constraint(SculptSession *ss,
                                               SculptClothSimulation *cloth_sim,
                                               const int v1,
                                               const int v2)
 {
-  cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v1 = v1;
-  cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v2 = v2;
-  cloth_sim->length_constraints[cloth_sim->tot_length_constraints].length = len_v3v3(
-      SCULPT_vertex_co_get(ss, v1), SCULPT_vertex_co_get(ss, v2));
+  SculptClothLengthConstraint *length_constraint =
+      &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
+
+  length_constraint->elem_index_a = v1;
+  length_constraint->elem_index_b = v2;
+
+  length_constraint->elem_position_a = cloth_sim->pos[v1];
+  length_constraint->elem_position_b = cloth_sim->pos[v2];
+
+  length_constraint->length = len_v3v3(SCULPT_vertex_co_get(ss, v1), SCULPT_vertex_co_get(ss, v2));
+  length_constraint->strength = 1.0f;
 
   cloth_sim->tot_length_constraints++;
 
   /* Reallocation if the array capacity is exceeded. */
-  if (cloth_sim->tot_length_constraints >= cloth_sim->capacity_length_constraints) {
-    cloth_sim->capacity_length_constraints += CLOTH_LENGTH_CONSTRAINTS_BLOCK;
-    cloth_sim->length_constraints = MEM_reallocN_id(cloth_sim->length_constraints,
-                                                    cloth_sim->capacity_length_constraints *
-                                                        sizeof(SculptClothLengthConstraint),
-                                                    "length constraints");
-  }
+  cloth_brush_reallocate_constraints(cloth_sim);
 
   /* Add the constraint to the GSet to avoid creating it again. */
   BLI_edgeset_add(cloth_sim->created_length_constraints, v1, v2);
 }
 
+static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim,
+                                                const int v,
+                                                const float strength)
+{
+  SculptClothLengthConstraint *length_constraint =
+      &cloth_sim->length_constraints[cloth_sim->tot_length_constraints];
+
+  length_constraint->elem_index_a = v;
+  length_constraint->elem_index_b = v;
+
+  length_constraint->elem_position_a = cloth_sim->pos[v];
+  length_constraint->elem_position_b = cloth_sim->init_pos[v];
+
+  length_constraint->length = 0.0f;
+  length_constraint->strength = strength;
+
+  cloth_sim->tot_length_constraints++;
+
+  /* Reallocation if the array capacity is exceeded. */
+  cloth_brush_reallocate_constraints(cloth_sim);
+}
+
 static void do_cloth_brush_build_constraints_task_cb_ex(
     void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
 {
   SculptThreadedTaskData *data = userdata;
   SculptSession *ss = data->ob->sculpt;
+  Brush *brush = data->brush;
 
   PBVHVertexIter vd;
 
@@ -162,6 +197,11 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
       }
       SCULPT_VERTEX_NEIGHBORS_ITER_END(ni);
 
+      if (brush->cloth_constraint_softbody_strength > 0.0f) {
+        cloth_brush_add_softbody_constraint(
+            data->cloth_sim, vd.index, brush->cloth_constraint_softbody_strength);
+      }
+
       /* As we don't know the order of the neighbor vertices, we create all possible combinations
        * between the neighbor and the original vertex as length constraints. */
       /* This results on a pattern that contains structural, shear and bending constraints for all
@@ -484,11 +524,11 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
     for (int i = 0; i < cloth_sim->tot_length_constraints; i++) {
 
       const SculptClothLengthConstraint *constraint = &cloth_sim->length_constraints[i];
-      const int v1 = constraint->v1;
-      const int v2 = constraint->v2;
+      const int v1 = constraint->elem_index_a;
+      const int v2 = constraint->elem_index_b;
 
       float v1_to_v2[3];
-      sub_v3_v3v3(v1_to_v2, cloth_sim->pos[v2], cloth_sim->pos[v1]);
+      sub_v3_v3v3(v1_to_v2, constraint->elem_position_b, constraint->elem_position_a);
       const float current_distance = len_v3(v1_to_v2);
       float correction_vector[3];
       float correction_vector_half[3];
@@ -524,8 +564,14 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
                                                   cloth_sim->init_pos[v2]) :
                                               1.0f;
 
-      madd_v3_v3fl(cloth_sim->pos[v1], correction_vector_half, 1.0f * mask_v1 * sim_factor_v1);
-      madd_v3_v3fl(cloth_sim->pos[v2], correction_vector_half, -1.0f * mask_v2 * sim_factor_v2);
+      madd_v3_v3fl(cloth_sim->pos[v1],
+                   correction_vector_half,
+                   1.0f * mask_v1 * sim_factor_v1 * constraint->strength);
+      if (v1 != v2) {
+        madd_v3_v3fl(cloth_sim->pos[v2],
+                     correction_vector_half,
+                     -1.0f * mask_v2 * sim_factor_v2 * constraint->strength);
+      }
     }
   }
 }
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index ac1a257a4c6..8b42f1a936d 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -508,7 +508,7 @@ typedef struct Brush {
   /** Source for fill tool color gradient application. */
   char gradient_fill_mode;
 
-  char _pad0[1];
+  char _pad0[5];
 
   /** Projection shape (sphere, circle). */
   char falloff_shape;
@@ -580,6 +580,8 @@ typedef struct Brush {
   float cloth_sim_limit;
   float cloth_sim_falloff;
 
+  float cloth_constraint_softbody_strength;
+
   /* smooth */
   int smooth_deform_type;
   float surface_smooth_shape_preservation;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 452564fbe48..b40e20569d6 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -2568,6 +2568,15 @@ static void rna_def_brush(BlenderRNA *brna)
                            "Area to apply deformation falloff to the effects of the simulation");
   RNA_def_property_update(prop, 0, "rna_Brush_update");
 
+  prop = RNA_def_property(srna, "cloth_constraint_softbody_strength", PROP_FLOAT, PROP_FACTOR);
+  RNA_def_property_float_sdna(prop, NULL, "cloth_constraint_softbody_strength");
+  RNA_def_property_range(prop, 0.0f, 1.0f);
+  RNA_def_property_ui_text(
+      prop,
+      "Soft Body Influence",
+      "How much the simulation preserves the original shape, acting as a soft body");
+  RNA_def_property_update(prop, 0, "rna_Brush_update");
+
   prop = RNA_def_property(srna, "hardness", PROP_FLOAT, PROP_FACTOR);
   RNA_def_property_float_sdna(prop, NULL, "hardness");
   RNA_def_property_range(prop, 0.0f, 1.0f);



More information about the Bf-blender-cvs mailing list