[Bf-blender-cvs] [fdea8ecb5b] cloth-improvements: Implement velocity based adaptive step size calculation

Luca Rood noreply at git.blender.org
Wed Feb 1 07:11:55 CET 2017


Commit: fdea8ecb5b42fb82590a1fc63f639ccbb5f65b3b
Author: Luca Rood
Date:   Wed Feb 1 00:55:23 2017 -0200
Branches: cloth-improvements
https://developer.blender.org/rBfdea8ecb5b42fb82590a1fc63f639ccbb5f65b3b

Implement velocity based adaptive step size calculation

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

M	release/scripts/startup/bl_ui/properties_physics_cloth.py
M	source/blender/blenkernel/BKE_cloth.h
M	source/blender/blenkernel/intern/cloth.c
M	source/blender/makesdna/DNA_cloth_types.h
M	source/blender/makesrna/intern/rna_cloth.c
M	source/blender/physics/intern/BPH_mass_spring.cpp

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

diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 17acca7823..5bfa378fda 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -313,6 +313,29 @@ class PHYSICS_PT_cloth_scaling(PhysicButtonsPanel, Panel):
         sub.prop(cloth, "shrinking_max", text="Max")
 
 
+class PHYSICS_PT_cloth_adaptive_subframes(PhysicButtonsPanel, Panel):
+    bl_label = "Cloth Adaptive Subframes"
+    bl_options = {'DEFAULT_CLOSED'}
+    COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+    def draw(self, context):
+        layout = self.layout
+
+        md = context.cloth
+        cloth = context.cloth.settings
+
+        layout.active = cloth_panel_enabled(md)
+
+        layout.prop(cloth, "use_adaptive_subframes")
+
+        col = layout.column()
+        col.active = cloth.use_adaptive_subframes
+
+        col.prop(cloth, "max_sub_steps")
+        col.prop(cloth, "max_velocity")
+        col.prop(cloth, "adjustment_factor")
+
+
 class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
     bl_label = "Cloth Field Weights"
     bl_options = {'DEFAULT_CLOSED'}
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index ac8838591c..cadacc6948 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -111,6 +111,7 @@ typedef struct ClothVertex {
 	float	tx[3];		/* temporary position */
 	float 	txold[3];	/* temporary old position */
 	float 	tv[3];		/* temporary "velocity", mostly used as tv = tx-txold */
+	float	tvold[3];
 	float 	mass;		/* mass / weight of the vertex		*/
 	float 	goal;		/* goal, from SB			*/
 	float	impulse[3];	/* used in collision.c */
@@ -167,6 +168,7 @@ typedef struct ClothSpring {
 /* SIMULATION FLAGS: goal flags,.. */
 /* These are the bits used in SimSettings.flags. */
 typedef enum {
+	CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES = (1 << 0), /* use velocity based adaptive subframes*/
 	CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ),// object is only collision object, no cloth simulation is done
 	CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled
 	CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12),	/* edit cache in editmode */
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 8611e5b98f..16936c1524 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -118,6 +118,11 @@ void cloth_init(ClothModifierData *clmd )
 	clmd->sim_parms->struct_yield_fact = 1.0f;
 	clmd->sim_parms->bend_plasticity = 0.0f;
 	clmd->sim_parms->bend_yield_fact = 0.0f;
+
+	/* Adaptive subframes */
+	clmd->sim_parms->max_subframes = 50;
+	clmd->sim_parms->max_vel = 0.04f;
+	clmd->sim_parms->adjustment_factor = 0.8f;
 	
 	clmd->coll_parms->self_friction = 5.0;
 	clmd->coll_parms->friction = 5.0;
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index b13ba036e8..14a06a450a 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -111,6 +111,12 @@ typedef struct ClothSimSettings {
 
 	char pad0[6];
 	struct EffectorWeights *effector_weights;
+
+	/* Adaptive subframe stuff */
+	int max_subframes;
+	float max_vel;
+	float adjustment_factor;
+	char pad1[4];
 } ClothSimSettings;
 
 
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 9c4b545494..fd626e3a1b 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -197,6 +197,28 @@ static void rna_ClothSettings_max_shrink_set(struct PointerRNA *ptr, float value
 	settings->max_shrink = value;
 }
 
+static void rna_ClothSettings_subframes_set(struct PointerRNA *ptr, float value)
+{
+	ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
+
+	settings->stepsPerFrame = value;
+
+	/* check for max clipping */
+	if (value > settings->max_subframes)
+		settings->max_subframes = value;
+}
+
+static void rna_ClothSettings_max_subframes_set(struct PointerRNA *ptr, int value)
+{
+	ClothSimSettings *settings = (ClothSimSettings *)ptr->data;
+
+	/* check for clipping */
+	if (value < settings->stepsPerFrame)
+		value = settings->stepsPerFrame;
+
+	settings->max_subframes = value;
+}
+
 static void rna_ClothSettings_mass_vgroup_get(PointerRNA *ptr, char *value)
 {
 	ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
@@ -545,6 +567,7 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
 	RNA_def_property_int_sdna(prop, NULL, "stepsPerFrame");
 	RNA_def_property_range(prop, 1, INT_MAX);
 	RNA_def_property_ui_range(prop, 1, 80, 1, -1);
+	RNA_def_property_int_funcs(prop, NULL, "rna_ClothSettings_subframes_set", NULL);
 	RNA_def_property_ui_text(prop, "Quality",
 	                         "Quality of the simulation in steps per frame (higher is better quality but slower)");
 	RNA_def_property_update(prop, 0, "rna_cloth_update");
@@ -583,6 +606,33 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Voxel Grid Cell Size", "Size of the voxel grid cells for interaction effects");
 	RNA_def_property_update(prop, 0, "rna_cloth_update");
 
+	/* Adaptive subframes */
+	prop = RNA_def_property(srna, "use_adaptive_subframes", PROP_BOOLEAN, PROP_NONE);
+	RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES);
+	RNA_def_property_ui_text(prop, "Use Adaptive Subframes", "Adapt subframes to the cloth velocity");
+	RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+	RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+	prop = RNA_def_property(srna, "max_sub_steps", PROP_INT, PROP_NONE);
+	RNA_def_property_int_sdna(prop, NULL, "max_subframes");
+	RNA_def_property_range(prop, 1, INT_MAX);
+	RNA_def_property_ui_range(prop, 1, 80, 1, -1);
+	RNA_def_property_int_funcs(prop, NULL, "rna_ClothSettings_max_subframes_set", NULL);
+	RNA_def_property_ui_text(prop, "Max Subframes", "Maximum number of subframes to use with adaptive subframes");
+	RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+	prop = RNA_def_property(srna, "max_velocity", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "max_vel");
+	RNA_def_property_range(prop, 0.001f, 1.0f);
+	RNA_def_property_ui_text(prop, "Maximum Velocity", "Maximum velocity before increasing subframes");
+	RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+	prop = RNA_def_property(srna, "adjustment_factor", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "adjustment_factor");
+	RNA_def_property_range(prop, 0.1f, 1.0f);
+	RNA_def_property_ui_text(prop, "Adjustment Factor", "Factor of the velocity to adjust subframes by (lower means more subframes)");
+	RNA_def_property_update(prop, 0, "rna_cloth_update");
+
 	/* springs */
 	
 	prop = RNA_def_property(srna, "tension_damping", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 53ca40158e..c05a8b9fd9 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -128,6 +128,7 @@ void BKE_cloth_solver_set_positions(ClothModifierData *clmd)
 			BPH_mass_spring_set_rest_transform(id, i, I3);
 		
 		BPH_mass_spring_set_motion_state(id, i, verts[i].x, verts[i].v);
+		copy_v3_v3(verts[i].tvold, verts[i].v);
 	}
 }
 
@@ -1027,10 +1028,12 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
 	Cloth *cloth = clmd->clothObject;
 	ClothVertex *verts = cloth->verts/*, *cv*/;
 	unsigned int mvert_num = cloth->mvert_num;
-	float dt = clmd->sim_parms->dt * clmd->sim_parms->timescale;
 	Implicit_Data *id = cloth->implicit;
 	ColliderContacts *contacts = NULL;
 	int totcolliders = 0;
+	float max_vel;
+	float vel;
+	float tmp_vec[3];
 	
 	BKE_sim_debug_data_clear_category("collision");
 	
@@ -1054,7 +1057,13 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
 
 	while (step < tf) {
 		ImplicitSolverResult result;
-		
+		float dt = clmd->sim_parms->dt * clmd->sim_parms->timescale;
+		max_vel = 0.0f;
+
+		if (step + dt > tf) {
+			dt = tf - step;
+		}
+
 		if (is_hair) {
 			/* determine contact points */
 			if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) {
@@ -1100,7 +1109,32 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
 		}
 		
 		BPH_mass_spring_solve_positions(id, dt);
-		
+
+		for (i = 0; i < mvert_num; i++) {
+			BPH_mass_spring_get_new_position(id, i, tmp_vec);
+			vel = len_v3v3(tmp_vec, verts[i].txold);
+			max_vel = max_ff(max_vel, vel);
+		}
+
+		/* Adaptive step calculation */
+		if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_ADAPTIVE_SUBFRAMES) {
+			clmd->sim_parms->dt *= clmd->sim_parms->max_vel / max_vel * clmd->sim_parms->adjustment_factor;
+			clmd->sim_parms->dt = min_ff(1.0f / clmd->sim_parms->stepsPerFrame, clmd->sim_parms->dt);
+
+			if ((clmd->sim_parms->max_subframes > 0) && ((1.0f / clmd->sim_parms->max_subframes) > clmd->sim_parms->dt)) {
+				clmd->sim_parms->dt = 1.0f / clmd->sim_parms->max_subframes;
+			}
+			else {
+				if (max_vel > clmd->sim_parms->max_vel) {
+					for (i = 0; i < mvert_num; i++) {
+						BPH_mass_spring_set_motion_state(id, i, verts[i].txold, verts[i].tvold);
+					}
+
+					continue;
+				}
+			}
+		}
+
 		BPH_mass_spring_apply_result(id);
 		
 		/* move pinned verts to correct position */
@@ -1113,15 +1147,15 @@ int BPH_cloth_solve(Object *ob, float frame, ClothModifierData *clmd, ListBase *
 					BPH_mass_spring_set_position(id, i, x);
 				}
 			}
-			
-			BPH_mass_spring_get_motion_state(id, i, verts[i].txold, NULL);
+
+			BPH_mass_spring_get_motion_state(id, i, verts[i].txold, verts[i].tvold);
 		}
 		
 		/* free contact points */
 		if (contacts) {
 			cloth_free_contacts(contacts, totcolliders);
 		}
-		
+
 		step += dt;
 	}




More information about the Bf-blender-cvs mailing list