[Bf-blender-cvs] [666a9385c4] cloth-improvements: Implement collision impulse clamping (to prevent explosions)

Luca Rood noreply at git.blender.org
Sat Mar 18 23:47:07 CET 2017


Commit: 666a9385c4bf2b6cf1b8cd8719f3b22e7f77b764
Author: Luca Rood
Date:   Sat Mar 18 16:53:12 2017 -0300
Branches: cloth-improvements
https://developer.blender.org/rB666a9385c4bf2b6cf1b8cd8719f3b22e7f77b764

Implement collision impulse clamping (to prevent explosions)

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

M	release/scripts/startup/bl_ui/properties_physics_cloth.py
M	source/blender/blenkernel/intern/collision.c
M	source/blender/makesdna/DNA_cloth_types.h
M	source/blender/makesrna/intern/rna_cloth.c

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

diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index c4464a79cf..a141e7e643 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -260,6 +260,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
         sub = col.column()
         sub.active = cloth.use_collision
         sub.prop(cloth, "distance_min", slider=True, text="Distance")
+        sub.prop(cloth, "impulse_clamp")
         sub.prop(cloth, "group")
 
         layout.separator()
@@ -279,6 +280,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
         sub.active = cloth.use_self_collision
         sub.prop(cloth, "self_friction", text="Friction")
         sub.prop(cloth, "self_distance_min", slider=True, text="Distance")
+        sub.prop(cloth, "self_impulse_clamp")
         sub.prop_search(cloth, "vertex_group_self_collisions", ob, "vertex_groups", text="Vertex Group")
 
 
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index d7fad86355..d6df750682 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -444,7 +444,7 @@ static void free_impulse_clusters(ImpulseCluster *clusters)
 /* This allows inserting impulses one by one into the cluster array, and immediately computing the clustering,
  * but the clustering isn't exact, because of not knowing all impulses beforehand.
  * Seems to be good enough however, and is much faster than the true hclust below... */
-static void insert_impulse_in_cluster_array(ImpulseCluster **clusters, const float impulse[3], const float clustang)
+static void insert_impulse_in_cluster_array(ImpulseCluster **clusters, const float impulse[3], const float clustang, const float clamp)
 {
 	ImpulseCluster *imp;
 	ImpulseCluster *close = NULL;
@@ -455,7 +455,7 @@ static void insert_impulse_in_cluster_array(ImpulseCluster **clusters, const flo
 
 	mag = normalize_v3_v3(dir, impulse);
 
-	if (mag < FLT_EPSILON) {
+	if ((mag < FLT_EPSILON) || (mag > clamp)) {
 		return;
 	}
 
@@ -640,8 +640,8 @@ DO_INLINE void collision_interpolateOnTriangle (float to[3], float v1[3], float
 	VECADDMUL(to, v3, w3);
 }
 
-static int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd, Object *collob,
-                                           CollPair *collpair, CollPair *collision_end, ImpulseCluster **vert_imp_clusters)
+static int cloth_collision_response_static(ClothModifierData *clmd, CollisionModifierData *collmd, Object *collob, CollPair *collpair,
+                                           CollPair *collision_end, ImpulseCluster **vert_imp_clusters, const float dt)
 {
 	int result = 0;
 	Cloth *cloth1;
@@ -792,15 +792,15 @@ static int cloth_collision_response_static(ClothModifierData *clmd, CollisionMod
 
 		if (result) {
 			if (cloth1->verts[collpair->ap1].impulse_count > 0) {
-				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap1], i1, M_PI / 20);
+				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap1], i1, (M_PI / 20), (clmd->coll_parms->clamp * dt));
 			}
 
 			if (cloth1->verts[collpair->ap2].impulse_count > 0) {
-				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap2], i2, M_PI / 20);
+				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap2], i2, (M_PI / 20), (clmd->coll_parms->clamp * dt));
 			}
 
 			if (cloth1->verts[collpair->ap3].impulse_count > 0) {
-				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap3], i3, M_PI / 20);
+				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap3], i3, (M_PI / 20), (clmd->coll_parms->clamp * dt));
 			}
 		}
 	}
@@ -809,7 +809,7 @@ static int cloth_collision_response_static(ClothModifierData *clmd, CollisionMod
 }
 
 static int cloth_selfcollision_response_static(ClothModifierData *clmd, CollPair *collpair, CollPair *collision_end,
-                                               ImpulseCluster **vert_imp_clusters)
+                                               ImpulseCluster **vert_imp_clusters, const float dt)
 {
 	int result = 0;
 	Cloth *cloth1;
@@ -960,15 +960,15 @@ static int cloth_selfcollision_response_static(ClothModifierData *clmd, CollPair
 
 		if (result) {
 			if (cloth1->verts[collpair->ap1].impulse_count > 0) {
-				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap1], i1, M_PI / 20);
+				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap1], i1, (M_PI / 20), (clmd->coll_parms->self_clamp * dt));
 			}
 
 			if (cloth1->verts[collpair->ap2].impulse_count > 0) {
-				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap2], i2, M_PI / 20);
+				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap2], i2, (M_PI / 20), (clmd->coll_parms->self_clamp * dt));
 			}
 
 			if (cloth1->verts[collpair->ap3].impulse_count > 0) {
-				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap3], i3, M_PI / 20);
+				insert_impulse_in_cluster_array(&vert_imp_clusters[collpair->ap3], i3, (M_PI / 20), (clmd->coll_parms->self_clamp * dt));
 			}
 		}
 	}
@@ -1252,7 +1252,7 @@ static void cloth_bvh_selfcollisions_nearcheck(ClothModifierData * clmd, CollPai
 }
 
 static int cloth_bvh_objcollisions_resolve (ClothModifierData * clmd, Object **collobjs, CollPair **collisions,
-                                            CollPair **collisions_index, const unsigned int numcollobj)
+                                            CollPair **collisions_index, const unsigned int numcollobj, const float dt)
 {
 	Cloth *cloth = clmd->clothObject;
 	int i = 0, j = 0, mvert_num = 0;
@@ -1278,7 +1278,7 @@ static int cloth_bvh_objcollisions_resolve (ClothModifierData * clmd, Object **c
 			CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType(collob, eModifierType_Collision);
 
 			if ( collmd->bvhtree ) {
-				result += cloth_collision_response_static(clmd, collmd, collob, collisions[i], collisions_index[i], vert_imp_clusters);
+				result += cloth_collision_response_static(clmd, collmd, collob, collisions[i], collisions_index[i], vert_imp_clusters, dt);
 			}
 		}
 
@@ -1310,7 +1310,7 @@ static int cloth_bvh_objcollisions_resolve (ClothModifierData * clmd, Object **c
 	return ret;
 }
 
-static int cloth_bvh_selfcollisions_resolve(ClothModifierData * clmd, CollPair *collisions, CollPair *collisions_index)
+static int cloth_bvh_selfcollisions_resolve(ClothModifierData * clmd, CollPair *collisions, CollPair *collisions_index, const float dt)
 {
 	Cloth *cloth = clmd->clothObject;
 	int i = 0, j = 0, mvert_num = 0;
@@ -1329,7 +1329,7 @@ static int cloth_bvh_selfcollisions_resolve(ClothModifierData * clmd, CollPair *
 	for (j = 0; j < iter; j++) { /* 5 is just a value that ensures convergence */
 		result = 0;
 
-		result += cloth_selfcollision_response_static (clmd, collisions, collisions_index, vert_imp_clusters);
+		result += cloth_selfcollision_response_static (clmd, collisions, collisions_index, vert_imp_clusters, dt);
 
 		// apply impulses in parallel
 		if (result) {
@@ -1439,7 +1439,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
 				MEM_SAFE_FREE(overlap);
 			}
 
-			ret += cloth_bvh_objcollisions_resolve(clmd, collobjs, collisions,  collisions_index, numcollobj);
+			ret += cloth_bvh_objcollisions_resolve(clmd, collobjs, collisions,  collisions_index, numcollobj, dt);
 			ret2 += ret;
 
 			for (i = 0; i < numcollobj; i++) {
@@ -1474,7 +1474,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa
 				if (result && overlap) {
 					cloth_bvh_selfcollisions_nearcheck (clmd, &collisions, &collisions_index, result, overlap);
 
-					ret += cloth_bvh_selfcollisions_resolve ( clmd, collisions,  collisions_index);
+					ret += cloth_bvh_selfcollisions_resolve ( clmd, collisions,  collisions_index, dt);
 					ret2 += ret;
 				}
 
diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h
index 42a3f76cd5..d814763ac1 100644
--- a/source/blender/makesdna/DNA_cloth_types.h
+++ b/source/blender/makesdna/DNA_cloth_types.h
@@ -132,6 +132,8 @@ typedef struct ClothCollSettings {
 	float	friction;		/* Friction/damping applied on contact with other object.*/
 	float	damping;	/* Collision restitution on contact with other object.*/
 	float 	selfepsilon; 		/* for selfcollision */
+	float	clamp;		/* Impulse clamp for object collisions */
+	float	self_clamp;	/* Impulse clamp for self collisions */
 	int	flags;			/* collision flags defined in BKE_cloth.h */
 	short	loop_count;		/* How many iterations for the collision loop.		*/
 	short pad[3];
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 85fc5627a2..85995c2d40 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -996,6 +996,12 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
 	                         "How many object collision response iterations should be done. (higher is smoother but slower)");
 	RNA_def_property_update(prop, 0, "rna_cloth_update");
 
+	prop = RNA_def_property(srna, "impulse_clamp", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "clamp");
+	RNA_def_property_range(prop, 0.0f, 100.0f);
+	RNA_def_property_ui_text(prop, "Impulse Clamping", "Don't use collision impulses above this magnitude (0.0 to disable clamping)");
+	RNA_def_property_update(prop, 0, "rna_cloth_update");
+
 	/* self collision */
 
 	prop = RNA_def_property(srna, "use_self_collision", PROP_BOOLEAN, PROP_NONE);
@@ -1033,6 +1039,12 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
 	RNA_def_property_ui_text(prop, "Response Quality",
 	                         "How many self collision response iterations should be done. (higher is better quality but slower)");
 	RNA_def_property_update(prop, 0, "rna_cloth_update");
+
+	prop = RNA_def_property(srna, "self_impulse_clamp", PROP_FLOAT, PROP_NONE);
+	RNA_def_property_float_sdna(prop, NULL, "self_clamp");
+	RNA_def_pro

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list