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. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to