Commit: d4a46809d05402fbef8639d10cede39fe0a724f8
Author: Luca Rood
Date:   Mon Jan 16 23:31:22 2017 -0200
Branches: cloth-improvements
https://developer.blender.org/rBd4a46809d05402fbef8639d10cede39fe0a724f8

Implement single sided collisions

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

M       release/scripts/startup/bl_ui/properties_physics_cloth.py
M       source/blender/blenkernel/BKE_cloth.h
M       source/blender/blenkernel/intern/collision.c
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 d7396d7889..f5f5ce36d7 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -243,9 +243,11 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, 
Panel):
         col.prop(cloth, "distance_min", slider=True, text="Distance")
         col.prop(cloth, "distance_repel", slider=True, text="Repel Distance")
 
-        sub = layout.column()
-        sub.active = cloth.use_collision
-        sub.prop(cloth, "group")
+        col = layout.column()
+        col.active = cloth.use_collision
+        col.prop(cloth, "group")
+
+        col.prop(cloth, "use_normal")
 
         layout.separator()
 
diff --git a/source/blender/blenkernel/BKE_cloth.h 
b/source/blender/blenkernel/BKE_cloth.h
index c505e5fcbd..9e2b98a7ae 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -180,6 +180,7 @@ typedef enum {
 typedef enum {
        CLOTH_COLLSETTINGS_FLAG_ENABLED = ( 1 << 1 ), /* enables cloth - object 
collisions */
        CLOTH_COLLSETTINGS_FLAG_SELF = ( 1 << 2 ), /* enables selfcollisions */
+       CLOTH_COLLSETTINGS_FLAG_USE_NORMAL = ( 1 << 3 ), /* enable collision 
side detection based on normal */
 } CLOTH_COLLISIONSETTINGS_FLAGS;
 
 /* Spring types as defined in the paper.*/
diff --git a/source/blender/blenkernel/intern/collision.c 
b/source/blender/blenkernel/intern/collision.c
index b79f69d413..46d82784e4 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -234,6 +234,8 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
        float v1[3], v2[3], relativeVelocity[3];
        float magrelVel;
        float epsilon2 = BLI_bvhtree_get_epsilon ( collmd->bvhtree );
+       float collider_norm[3];
+       bool backside;
 
        cloth1 = clmd->clothObject;
 
@@ -262,6 +264,16 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
                        collmd->current_x[collpair->bp3].co,
                        &u1, &u2, &u3 );
 
+               /* compute collision normal */
+               if (clmd->coll_parms->flags & 
CLOTH_COLLSETTINGS_FLAG_USE_NORMAL) {
+                       normal_tri_v3(collider_norm, 
collmd->current_x[collpair->bp1].co, collmd->current_x[collpair->bp2].co, 
collmd->current_x[collpair->bp3].co);
+                       backside = dot_v3v3(collider_norm, collpair->normal) < 
0.0f;
+               }
+               else {
+                       copy_v3_v3(collider_norm, collpair->normal);
+                       backside = false;
+               }
+
                /* Calculate relative "velocity". */
                collision_interpolateOnTriangle ( v1, 
cloth1->verts[collpair->ap1].tv, cloth1->verts[collpair->ap2].tv, 
cloth1->verts[collpair->ap3].tv, w1, w2, w3 );
 
@@ -270,7 +282,7 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
                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);
+               magrelVel = dot_v3v3(relativeVelocity, collider_norm);
 
                /* printf("magrelVel: %f\n", magrelVel); */
 
@@ -286,7 +298,7 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
                        float temp[3], spf;
 
                        /* calculate tangential velocity */
-                       copy_v3_v3 ( temp, collpair->normal );
+                       copy_v3_v3 ( temp, collider_norm );
                        mul_v3_fl(temp, magrelVel);
                        sub_v3_v3v3(vrel_t_pre, relativeVelocity, temp);
 
@@ -316,14 +328,38 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
                        /* Impulse shoud be uniform throughout polygon, the 
scaling used above was wrong */
                        impulse =  magrelVel / 1.5f;
 
-                       VECADDMUL ( i1, collpair->normal, w1 * impulse );
-                       cloth1->verts[collpair->ap1].impulse_count++;
+                       if (backside) {
+                               float pt_relvel[3];
+                               float pt_magvel;
+
+                               sub_v3_v3v3(pt_relvel, 
collmd->current_v[collpair->bp1].co, cloth1->verts[collpair->ap1].tv);
+                               pt_magvel = dot_v3v3(pt_relvel, collider_norm);
+
+                               VECADDMUL ( i1, collider_norm, pt_magvel * 
0.25f );
+                               cloth1->verts[collpair->ap1].impulse_count++;
+
+                               sub_v3_v3v3(pt_relvel, 
collmd->current_v[collpair->bp2].co, cloth1->verts[collpair->ap2].tv);
+                               pt_magvel = dot_v3v3(pt_relvel, collider_norm);
+
+                               VECADDMUL ( i2, collider_norm, pt_magvel * 
0.25f );
+                               cloth1->verts[collpair->ap2].impulse_count++;
+
+                               sub_v3_v3v3(pt_relvel, 
collmd->current_v[collpair->bp3].co, cloth1->verts[collpair->ap3].tv);
+                               pt_magvel = dot_v3v3(pt_relvel, collider_norm);
+
+                               VECADDMUL ( i3, collider_norm, pt_magvel * 
0.25f );
+                               cloth1->verts[collpair->ap3].impulse_count++;
+                       }
+                       else {
+                               VECADDMUL ( i1, collider_norm, w1 * impulse );
+                               cloth1->verts[collpair->ap1].impulse_count++;
 
-                       VECADDMUL ( i2, collpair->normal, w2 * impulse );
-                       cloth1->verts[collpair->ap2].impulse_count++;
+                               VECADDMUL ( i2, collider_norm, w2 * impulse );
+                               cloth1->verts[collpair->ap2].impulse_count++;
 
-                       VECADDMUL ( i3, collpair->normal, w3 * impulse );
-                       cloth1->verts[collpair->ap3].impulse_count++;
+                               VECADDMUL ( i3, collider_norm, 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))
@@ -333,7 +369,13 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
                         * 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 + 
epsilon2*8.0f/9.0f - collpair->distance;
+                       if (backside) {
+                               d = clmd->coll_parms->epsilon*8.0f/9.0f + 
epsilon2*8.0f/9.0f;
+                       }
+                       else {
+                               d = clmd->coll_parms->epsilon*8.0f/9.0f + 
epsilon2*8.0f/9.0f - collpair->distance;
+                       }
+
                        if ( ( magrelVel < 0.1f*d*spf ) && ( d > ALMOST_ZERO ) 
) {
                                repulse = MIN2 ( d*1.0f/spf, 0.1f*d*spf - 
magrelVel );
 
@@ -347,9 +389,9 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
                                /* Impulse shoud be uniform throughout polygon, 
the scaling used above was wrong */
                                impulse = repulse / 1.5f;
 
-                               VECADDMUL ( i1, collpair->normal,  impulse );
-                               VECADDMUL ( i2, collpair->normal,  impulse );
-                               VECADDMUL ( i3, collpair->normal,  impulse );
+                               VECADDMUL ( i1, collider_norm,  impulse );
+                               VECADDMUL ( i2, collider_norm,  impulse );
+                               VECADDMUL ( i3, collider_norm,  impulse );
                        }
 
                        result = 1;
@@ -361,8 +403,15 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
                         * v += impulse; x_new = x + v;
                         * We don't use dt!! */
                        float spf = (float)clmd->sim_parms->stepsPerFrame / 
clmd->sim_parms->timescale;
+                       float d;
+
+                       if (backside) {
+                               d = clmd->coll_parms->epsilon*8.0f/9.0f + 
epsilon2*8.0f/9.0f;
+                       }
+                       else {
+                               d = clmd->coll_parms->epsilon*8.0f/9.0f + 
epsilon2*8.0f/9.0f - (float)collpair->distance;
+                       }
 
-                       float d = clmd->coll_parms->epsilon*8.0f/9.0f + 
epsilon2*8.0f/9.0f - (float)collpair->distance;
                        if ( d > ALMOST_ZERO) {
                                /* stay on the safe side and clamp repulse */
                                float repulse = d*1.0f/spf;
@@ -372,9 +421,9 @@ static int cloth_collision_response_static ( 
ClothModifierData *clmd, CollisionM
                                /* Impulse shoud be uniform throughout polygon, 
the scaling used above was wrong */
                                float impulse = repulse / 4.5f;
 
-                               VECADDMUL ( i1, collpair->normal,  impulse );
-                               VECADDMUL ( i2, collpair->normal,  impulse );
-                               VECADDMUL ( i3, collpair->normal,  impulse );
+                               VECADDMUL ( i1, collider_norm,  impulse );
+                               VECADDMUL ( i2, collider_norm,  impulse );
+                               VECADDMUL ( i3, collider_norm,  impulse );
 
                                cloth1->verts[collpair->ap1].impulse_count++;
                                cloth1->verts[collpair->ap2].impulse_count++;
diff --git a/source/blender/makesrna/intern/rna_cloth.c 
b/source/blender/makesrna/intern/rna_cloth.c
index 13de955d52..095d90b182 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -842,6 +842,11 @@ static void rna_def_cloth_collision_settings(BlenderRNA 
*brna)
                                 "How many collision iterations should be done. 
(higher is better quality but slower)");
        RNA_def_property_update(prop, 0, "rna_cloth_update");
 
+       prop = RNA_def_property(srna, "use_normal", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flags", 
CLOTH_COLLSETTINGS_FLAG_USE_NORMAL);
+       RNA_def_property_ui_text(prop, "Single Sided", "Collision acts with 
respect to the collider normals (improves penetration recovery)");
+       RNA_def_property_update(prop, 0, "rna_cloth_update");
+
        /* self collision */
 
        prop = RNA_def_property(srna, "use_self_collision", PROP_BOOLEAN, 
PROP_NONE);

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to