[Bf-blender-cvs] [8ef353fa506] master: Sculpt: Cloth Simulation Dynamic area mode

Pablo Dobarro noreply at git.blender.org
Thu Oct 1 19:12:14 CEST 2020


Commit: 8ef353fa5061f6c393ef3bc96e3e11ae74d8435f
Author: Pablo Dobarro
Date:   Thu Oct 1 18:50:52 2020 +0200
Branches: master
https://developer.blender.org/rB8ef353fa5061f6c393ef3bc96e3e11ae74d8435f

Sculpt: Cloth Simulation Dynamic area mode

This simulation area mode moves the active area with the brush. When
enabled, the cloth brush has no restrictions on stroke length, area or
mesh vertex count.

In order to work, this enables PBVH nodes dynamically for simulation as
the stroke location moves and builds the constraints for new nodes
during the stroke. When a node is not inside the simulated area, all the
constraints that were created for it and vertex collisions are not
computed. The simulation limits falloff areas and constraints tweaking
control how the simulated and no simulated nodes blend.

Reviewed By: sergey, zeddb

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

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

M	release/scripts/startup/bl_ui/properties_paint_common.py
M	source/blender/blenkernel/BKE_paint.h
M	source/blender/editors/sculpt_paint/paint_cursor.c
M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_cloth.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/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 135ba802655..c601dec87a9 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -660,9 +660,11 @@ def brush_settings(layout, context, brush, popover=False):
         elif sculpt_tool == 'CLOTH':
             layout.separator()
             layout.prop(brush, "cloth_simulation_area_type")
-            if brush.cloth_simulation_area_type == 'LOCAL':
+            if brush.cloth_simulation_area_type != 'GLOBAL':
                 layout.prop(brush, "cloth_sim_limit")
                 layout.prop(brush, "cloth_sim_falloff")
+                
+            if brush.cloth_simulation_area_type == 'LOCAL':
                 layout.prop(brush, "use_cloth_pin_simulation_boundary")
 
             layout.separator()
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 653c8a752d5..dc2a42e3988 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -256,6 +256,18 @@ typedef struct SculptPoseIKChain {
 
 /* Cloth Brush */
 
+/* Cloth Simulation. */
+typedef enum eSculptClothNodeSimState {
+  /* Constraints were not built for this node, so it can't be simulated. */
+  SCULPT_CLOTH_NODE_UNINITIALIZED,
+
+  /* There are constraints for the geometry in this node, but it should not be simulated. */
+  SCULPT_CLOTH_NODE_INACTIVE,
+
+  /* There are constraints for this node and they should be used by the solver. */
+  SCULPT_CLOTH_NODE_ACTIVE,
+} eSculptClothNodeSimState;
+
 typedef enum eSculptClothConstraintType {
   /* Constraint that creates the structure of the cloth. */
   SCULPT_CLOTH_CONSTRAINT_STRUCTURAL = 0,
@@ -282,6 +294,10 @@ typedef struct SculptClothLengthConstraint {
   float length;
   float strength;
 
+  /* Index in SculptClothSimulation.node_state of the node from where this constraint was created.
+   * This constraints will only be used by the solver if the state is active. */
+  int node;
+
   eSculptClothConstraintType type;
 } SculptClothLengthConstraint;
 
@@ -308,6 +324,11 @@ typedef struct SculptClothSimulation {
   float (*last_iteration_pos)[3];
 
   struct ListBase *collider_list;
+
+  int totnode;
+  /* PBVHNode pointer as a key, index in SculptClothSimulation.node_state as value. */
+  struct GHash *node_state_index;
+  eSculptClothNodeSimState *node_state;
 } SculptClothSimulation;
 
 typedef struct SculptPersistentBase {
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 2b6ecdcd640..2e24c2533c5 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1663,7 +1663,7 @@ static void paint_cursor_draw_3d_view_brush_cursor_inactive(PaintCursorContext *
 
   /* Cloth brush local simulation areas. */
   if (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
-      brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) {
+      brush->cloth_simulation_area_type != BRUSH_CLOTH_SIMULATION_AREA_GLOBAL) {
     const float white[3] = {1.0f, 1.0f, 1.0f};
     const float zero_v[3] = {0.0f};
     /* This functions sets its own drawing space in order to draw the simulation limits when the
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 70404f055e9..f9dbfaa5da9 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -5646,6 +5646,17 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
       };
       BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
     }
+    if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC) {
+      SculptSearchSphereData data = {
+          .ss = ss,
+          .sd = sd,
+          .radius_squared = square_f(ss->cache->initial_radius * (1.0 + brush->cloth_sim_limit)),
+          .original = false,
+          .ignore_fully_ineffective = false,
+          .center = ss->cache->location,
+      };
+      BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
+    }
     else {
       /* Gobal simulation, get all nodes. */
       BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
@@ -5724,10 +5735,10 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
       if (!ss->cache->cloth_sim) {
         ss->cache->cloth_sim = SCULPT_cloth_brush_simulation_create(ss, 1.0f, 0.0f, false, true);
         SCULPT_cloth_brush_simulation_init(ss, ss->cache->cloth_sim);
-        SCULPT_cloth_brush_build_nodes_constraints(
-            sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX);
       }
       SCULPT_cloth_brush_store_simulation_state(ss, ss->cache->cloth_sim);
+      SCULPT_cloth_brush_ensure_nodes_constraints(
+          sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, FLT_MAX);
     }
 
     bool invert = ss->cache->pen_flip || ss->cache->invert || brush->flag & BRUSH_DIR_IN;
@@ -5870,6 +5881,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
 
     if (brush->deform_target == BRUSH_DEFORM_TARGET_CLOTH_SIM) {
       if (SCULPT_stroke_is_main_symmetry_pass(ss->cache)) {
+        SCULPT_cloth_sim_activate_nodes(ss->cache->cloth_sim, nodes, totnode);
         SCULPT_cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
       }
     }
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 3d0e5791f0d..7b14f48c6a8 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -103,6 +103,22 @@
 #include <stdlib.h>
 #include <string.h>
 
+static void cloth_brush_simulation_location_get(SculptSession *ss,
+                                                const Brush *brush,
+                                                float r_location[3])
+{
+  if (!ss->cache || !brush) {
+    zero_v3(r_location);
+    return;
+  }
+
+  if (brush->cloth_simulation_area_type == BRUSH_CLOTH_SIMULATION_AREA_LOCAL) {
+    copy_v3_v3(r_location, ss->cache->initial_location);
+    return;
+  }
+  copy_v3_v3(r_location, ss->cache->location);
+}
+
 static float cloth_brush_simulation_falloff_get(const Brush *brush,
                                                 const float radius,
                                                 const float location[3],
@@ -162,6 +178,7 @@ static void cloth_brush_reallocate_constraints(SculptClothSimulation *cloth_sim)
 
 static void cloth_brush_add_length_constraint(SculptSession *ss,
                                               SculptClothSimulation *cloth_sim,
+                                              const int node_index,
                                               const int v1,
                                               const int v2,
                                               const bool use_persistent)
@@ -172,6 +189,8 @@ static void cloth_brush_add_length_constraint(SculptSession *ss,
   length_constraint->elem_index_a = v1;
   length_constraint->elem_index_b = v2;
 
+  length_constraint->node = node_index;
+
   length_constraint->elem_position_a = cloth_sim->pos[v1];
   length_constraint->elem_position_b = cloth_sim->pos[v2];
 
@@ -197,6 +216,7 @@ static void cloth_brush_add_length_constraint(SculptSession *ss,
 }
 
 static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim,
+                                                const int node_index,
                                                 const int v,
                                                 const float strength)
 {
@@ -206,6 +226,8 @@ static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim
   length_constraint->elem_index_a = v;
   length_constraint->elem_index_b = v;
 
+  length_constraint->node = node_index;
+
   length_constraint->elem_position_a = cloth_sim->pos[v];
   length_constraint->elem_position_b = cloth_sim->init_pos[v];
 
@@ -221,6 +243,7 @@ static void cloth_brush_add_softbody_constraint(SculptClothSimulation *cloth_sim
 }
 
 static void cloth_brush_add_deformation_constraint(SculptClothSimulation *cloth_sim,
+                                                   const int node_index,
                                                    const int v,
                                                    const float strength)
 {
@@ -230,6 +253,8 @@ static void cloth_brush_add_deformation_constraint(SculptClothSimulation *cloth_
   length_constraint->elem_index_a = v;
   length_constraint->elem_index_b = v;
 
+  length_constraint->node = node_index;
+
   length_constraint->type = SCULPT_CLOTH_CONSTRAINT_DEFORMATION;
 
   length_constraint->elem_position_a = cloth_sim->pos[v];
@@ -250,11 +275,20 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
   SculptThreadedTaskData *data = userdata;
   SculptSession *ss = data->ob->sculpt;
   const Brush *brush = data->brush;
+  PBVHNode *node = data->nodes[n];
+
+  const int node_index = (int)(BLI_ghash_lookup(data->cloth_sim->node_state_index, node));
+  if (data->cloth_sim->node_state[node_index] != SCULPT_CLOTH_NODE_UNINITIALIZED) {
+    /* The simulation already contains constraints for this node. */
+    return;
+  }
 
   PBVHVertexIter vd;
 
   const bool pin_simulation_boundary = ss->cache != NULL && brush != NULL &&
-                                       brush->flag2 & BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY;
+                                       brush->flag2 & BRUSH_CLOTH_PIN_SIMULATION_BOUNDARY &&
+                                       brush->cloth_simulation_area_type !=
+                                           BRUSH_CLOTH_SIMULATION_AREA_DYNAMIC;
 
   const bool use_persistent = brush != NULL && brush->flag & BRUSH_PERSISTENT;
 
@@ -273,7 +307,7 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
                                              data->cloth_sim_radius * data->

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list