[Bf-blender-cvs] [80ed76cb66] cloth-improvements: New self collision implementation (needs some cleanup)

Luca Rood noreply at git.blender.org
Fri Jan 20 05:38:37 CET 2017


Commit: 80ed76cb6674e2782c2c763ca7907eea00870aae
Author: Luca Rood
Date:   Thu Jan 19 02:13:01 2017 -0200
Branches: cloth-improvements
https://developer.blender.org/rB80ed76cb6674e2782c2c763ca7907eea00870aae

New self collision implementation (needs some cleanup)

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

M	source/blender/blenkernel/BKE_cloth.h
M	source/blender/blenkernel/intern/cloth.c
M	source/blender/blenkernel/intern/collision.c

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

diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 9e2b98a7ae..f7cca99be6 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -237,7 +237,7 @@ void clothModifier_do (struct ClothModifierData *clmd, struct Scene *scene, stru
 int cloth_uses_vgroup(struct ClothModifierData *clmd);
 
 // needed for collision.c
-void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
+void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving, bool self);
 void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving);
 
 // needed for button_object.c
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index f2d96f3588..2eef11376a 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -233,14 +233,21 @@ static BVHTree *bvhtree_build_from_cloth (ClothModifierData *clmd, float epsilon
 	return bvhtree;
 }
 
-void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving)
+void bvhtree_update_from_cloth(ClothModifierData *clmd, bool moving, bool self)
 {	
 	unsigned int i = 0;
 	Cloth *cloth = clmd->clothObject;
-	BVHTree *bvhtree = cloth->bvhtree;
+	BVHTree *bvhtree;
 	ClothVertex *verts = cloth->verts;
 	const MVertTri *vt;
-	
+
+	if (self) {
+		bvhtree = cloth->bvhselftree;
+	}
+	else {
+		bvhtree = cloth->bvhtree;
+	}
+
 	if (!bvhtree)
 		return;
 	
@@ -907,7 +914,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d
 		maxdist = MAX2(maxdist, clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len*2.0f));
 	}
 	
-	clmd->clothObject->bvhselftree = bvhselftree_build_from_cloth ( clmd, maxdist );
+	clmd->clothObject->bvhselftree = bvhtree_build_from_cloth ( clmd, clmd->coll_parms->epsilon );
 
 	return 1;
 }
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 3d612a0c74..6f4e635a7b 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -312,7 +312,7 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM
 
 				/*impulse = magtangent / ( 1.0f + w1*w1 + w2*w2 + w3*w3 );  2.0 * */
 
-				/* Impulse shoud be uniform throughout polygon, the scaling used above was wrong */
+				/* Impulse should be uniform throughout polygon, the scaling used above was wrong */
 				impulse = magtangent / 1.5;
 
 				VECADDMUL ( i1, vrel_t_pre, w1 * impulse );
@@ -325,7 +325,7 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM
 			 * no 2.0 * magrelVel normally, but looks nicer DG */
 			/*impulse =  magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );*/
 
-			/* Impulse shoud be uniform throughout polygon, the scaling used above was wrong */
+			/* Impulse should be uniform throughout polygon, the scaling used above was wrong */
 			impulse =  magrelVel / 1.5f;
 
 			if (backside) {
@@ -385,7 +385,7 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM
 
 				/*impulse = repulse / ( 1.0f + w1*w1 + w2*w2 + w3*w3 ); original 2.0 / 0.25 */
 
-				/* Impulse shoud be uniform throughout polygon, the scaling used above was wrong */
+				/* Impulse should be uniform throughout polygon, the scaling used above was wrong */
 				impulse = repulse / 1.5f;
 
 				VECADDMUL ( i1, collider_norm,  impulse );
@@ -417,7 +417,7 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM
 
 				/*float impulse = repulse / ( 3.0f * ( 1.0f + w1*w1 + w2*w2 + w3*w3 )); original 2.0 / 0.25 */
 
-				/* Impulse shoud be uniform throughout polygon, the scaling used above was wrong */
+				/* Impulse should be uniform throughout polygon, the scaling used above was wrong */
 				float impulse = repulse / 4.5f;
 
 				if (backside) {
@@ -457,6 +457,184 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM
 	return result;
 }
 
+static int cloth_selfcollision_response_static (ClothModifierData *clmd, CollPair *collpair, CollPair *collision_end)
+{
+	int result = 0;
+	Cloth *cloth1;
+	float w1, w2, w3, u1, u2, u3;
+	float v1[3], v2[3], relativeVelocity[3];
+	float magrelVel;
+
+	cloth1 = clmd->clothObject;
+
+	for ( ; collpair != collision_end; collpair++ ) {
+		float i1[3], i2[3], i3[3], j1[3], j2[3], j3[3]; /* i are impulses for ap and j are impulses for bp */
+
+		zero_v3(i1);
+		zero_v3(i2);
+		zero_v3(i3);
+
+		/* only handle static collisions here */
+		if ( collpair->flag & COLLISION_IN_FUTURE )
+			continue;
+
+		/* compute barycentric coordinates for both collision points */
+		collision_compute_barycentric ( collpair->pa,
+			cloth1->verts[collpair->ap1].tx,
+			cloth1->verts[collpair->ap2].tx,
+			cloth1->verts[collpair->ap3].tx,
+			&w1, &w2, &w3 );
+
+		/* was: txold */
+		collision_compute_barycentric ( collpair->pb,
+			cloth1->verts[collpair->bp1].tx,
+			cloth1->verts[collpair->bp2].tx,
+			cloth1->verts[collpair->bp3].tx,
+			&u1, &u2, &u3 );
+
+		/* Calculate relative "velocity". */
+		collision_interpolateOnTriangle ( v1, cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
+
+		collision_interpolateOnTriangle ( v2, cloth1->verts[collpair->bp1].tv, cloth1->verts[collpair->bp2].tv, cloth1->verts[collpair->bp3].tv, u1, u2, u3 );
+
+		sub_v3_v3v3(relativeVelocity, v2, v1);
+
+		/* Calculate the normal component of the relative velocity (actually only the magnitude - the direction is stored in 'normal'). */
+		magrelVel = dot_v3v3(relativeVelocity, collpair->normal);
+
+		/* printf("magrelVel: %f\n", magrelVel); */
+
+		/* TODO: Impulses should be weighed by mass as this is self col,
+		 * this has to be done after voronoi mass distribution is implemented */
+
+		/* If v_n_mag < 0 the edges are approaching each other. */
+		if ( magrelVel > ALMOST_ZERO ) {
+			/* Calculate Impulse magnitude to stop all motion in normal direction. */
+			float magtangent = 0, repulse = 0, d = 0;
+			double impulse = 0.0;
+			float vrel_t_pre[3];
+			float temp[3], spf;
+
+			/* calculate tangential velocity */
+			copy_v3_v3 ( temp, collpair->normal );
+			mul_v3_fl(temp, magrelVel);
+			sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp);
+
+			/* Decrease in magnitude of relative tangential velocity due to coulomb friction
+			 * in original formula "magrelVel" should be the "change of relative velocity in normal direction" */
+			magtangent = min_ff(clmd->coll_parms->friction * 0.01f * magrelVel, len_v3(vrel_t_pre));
+
+			/* Apply friction impulse. */
+			if ( magtangent > ALMOST_ZERO ) {
+				normalize_v3(vrel_t_pre);
+
+				/*impulse = magtangent / ( 1.0f + w1*w1 + w2*w2 + w3*w3 );  2.0 * */
+
+				/* Impulse should be uniform throughout polygon, the scaling used above was wrong */
+				impulse = magtangent / 1.5;
+
+				VECADDMUL ( i1, vrel_t_pre, w1 * impulse );
+				VECADDMUL ( i2, vrel_t_pre, w2 * impulse );
+				VECADDMUL ( i3, vrel_t_pre, w3 * impulse );
+			}
+
+			/* Apply velocity stopping impulse
+			 * I_c = m * v_N / 2.0
+			 * no 2.0 * magrelVel normally, but looks nicer DG */
+			/*impulse =  magrelVel / ( 1.0 + w1*w1 + w2*w2 + w3*w3 );*/
+
+			/* Impulse should be uniform throughout polygon, the scaling used above was wrong */
+			impulse =  magrelVel / 1.5f / 2.0f;
+
+			VECADDMUL ( i1, collpair->normal, w1 * impulse );
+			cloth1->verts[collpair->ap1].impulse_count++;
+
+			VECADDMUL ( i2, collpair->normal, w2 * impulse );
+			cloth1->verts[collpair->ap2].impulse_count++;
+
+			VECADDMUL ( i3, collpair->normal, w3 * impulse );
+			cloth1->verts[collpair->ap3].impulse_count++;
+
+			/* Apply repulse impulse if distance too short
+			 * I_r = -min(dt*kd, m(0, 1d/dt - v_n))
+			 * DG: this formula ineeds to be changed for this code since we apply impulses/repulses like this:
+			 * v += impulse; x_new = x + v;
+			 * We don't use dt!!
+			 * DG TODO: Fix usage of dt here! */
+			spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale;
+
+			d = clmd->coll_parms->epsilon*8.0f/9.0f * 2.0f - collpair->distance;
+
+			if ( ( magrelVel < 0.1f*d*spf ) && ( d > ALMOST_ZERO ) ) {
+				repulse = MIN2 ( d*1.0f/spf, 0.1f*d*spf - magrelVel );
+
+				/* stay on the safe side and clamp repulse */
+				/*if ( impulse > ALMOST_ZERO )
+					repulse = min_ff( repulse, 2.0*impulse );*/
+				repulse = min_ff(impulse, repulse);
+
+				/*impulse = repulse / ( 1.0f + w1*w1 + w2*w2 + w3*w3 ); original 2.0 / 0.25 */
+
+				/* Impulse should be uniform throughout polygon, the scaling used above was wrong */
+				impulse = repulse; /* TODO: This might have to be divided by two for self col (to be evaluated) */
+
+				VECADDMUL ( i1, collpair->normal, w1 * impulse );
+				VECADDMUL ( i2, collpair->normal, w2 * impulse );
+				VECADDMUL ( i3, collpair->normal, w3 * impulse );
+			}
+
+			result = 1;
+		}
+		else {
+			/* Apply repulse impulse if distance too short
+			 * I_r = -min(dt*kd, max(0, 1d/dt - v_n))
+			 * DG: this formula ineeds to be changed for this code since we apply impulses/repulses like this:
+			 * v += impulse; x_new = x + v;
+			 * We don't use dt!! */
+			float spf = (float)clmd->sim_parms->stepsPerFrame / clmd->sim_parms->timescale;
+			float d;
+
+			d = clmd->coll_parms->epsilon*8.0f/9.0f * 2.0f - (float)collpair->distance;
+
+			if ( d > ALMOST_ZERO) {
+				/* stay on the safe side and clamp repulse */
+				float repulse = d*1.0f/spf;
+
+				/*float impulse = repulse / ( 3.0f * ( 1.0f + w1*w1 + w2*w2 + w3*w3 )); original 2.0 / 0.25 */
+
+				/* Impulse should be uniform throughout polygon, the scaling used above was wrong */
+				float impulse = repulse / 4.5f / 2.0f; /* TODO: This might have to be divided by two for self col (to be evaluated) */
+
+				VECADDMUL ( i1, collpair->normal, w1 * impulse );
+				VECADDMUL ( i2, collpair->normal, w2 * impulse );
+				VECADDMUL ( i3, collpair->normal, w3 * impulse );
+
+				cloth1->verts[collpair->ap1].impulse_count++;
+				cloth1->verts[collpair->ap2].impulse_count++;
+				cloth1->verts[collpair->ap3].impulse_count++;
+
+				result = 1;
+			}
+		}
+
+		if (re

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list