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