From 28936a415076dbded4ec55cf94c49e8d0abe4035 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 6 Feb 2014 18:44:05 +0100 Subject: Patch T31269: Add sewing seams to cloth simulation Description: -------------------------- Use loose edges marked as seams as sewing springs. Usage: ------------------------- All this patch does is set the rest length to 0 and the stiffness to 1 for springs for loose edges marked as seams so that during the cloth simulation they will be brought together. Example Video: ------------------------- http://www.youtube.com/watch?v=-Y_bC0gjoM0 Original Patch by thesleepless (+ git patch by codemanx) Thank you! --- source/blender/blenkernel/BKE_cloth.h | 7 +++- source/blender/blenkernel/intern/cloth.c | 46 +++++++++++++++++++--- source/blender/blenkernel/intern/implicit.c | 13 ++++++- source/blender/makesdna/DNA_cloth_types.h | 6 ++- source/blender/makesrna/intern/rna_cloth.c | 59 +++++++++++++++++++++++++++++ 5 files changed, 121 insertions(+), 10 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 1b61d0a5443..1e7ac2815b0 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -106,6 +106,7 @@ typedef struct ClothVertex { float bend_stiff; float shear_stiff; int spring_count; /* how many springs attached? */ + float shrink_factor; /* how much to shrink this cloth */ } ClothVertex; @@ -149,7 +150,8 @@ typedef enum { CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */ CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12), /* edit cache in editmode */ - CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS = (1 << 13) /* don't allow spring compression */ + CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS = (1 << 13), /* don't allow spring compression */ + CLOTH_SIMSETTINGS_FLAG_SEW = (1 << 14), /* pull ends of loose edges together */ } CLOTH_SIMSETTINGS_FLAGS; /* COLLISION FLAGS */ @@ -163,7 +165,8 @@ typedef enum { CLOTH_SPRING_TYPE_STRUCTURAL = (1 << 1), CLOTH_SPRING_TYPE_SHEAR = (1 << 2), CLOTH_SPRING_TYPE_BENDING = (1 << 3), - CLOTH_SPRING_TYPE_GOAL = (1 << 4) + CLOTH_SPRING_TYPE_GOAL = (1 << 4), + CLOTH_SPRING_TYPE_SEWING = (1 << 5) } CLOTH_SPRING_TYPES; /* SPRING FLAGS */ diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index cab4adf46bf..0f6d4144b46 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -99,6 +99,8 @@ void cloth_init(ClothModifierData *clmd ) clmd->sim_parms->preroll = 0; clmd->sim_parms->maxspringlen = 10; clmd->sim_parms->vgroup_mass = 0; + clmd->sim_parms->vgroup_shrink = 0; + clmd->sim_parms->shrink_min = 0.0f; /* min amount the fabric will shrink by 0.0 = no shrinking, 1.0 = shrink to nothing*/ clmd->sim_parms->avg_spring_len = 0.0; clmd->sim_parms->presets = 2; /* cotton as start setting */ clmd->sim_parms->timescale = 1.0f; /* speed factor, describes how fast cloth moves */ @@ -737,6 +739,7 @@ int cloth_uses_vgroup(ClothModifierData *clmd) ((clmd->sim_parms->vgroup_mass>0) || (clmd->sim_parms->vgroup_struct>0)|| (clmd->sim_parms->vgroup_bend>0) || + (clmd->sim_parms->vgroup_shrink>0) || (clmd->coll_parms->vgroup_selfcol>0))); } @@ -809,6 +812,18 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) verts->flags |= CLOTH_VERT_FLAG_NOSELFCOLL; } } + + if (clmd->sim_parms->vgroup_shrink > 0 ) + { + if ( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shrink-1)) + { + verts->shrink_factor = clmd->sim_parms->shrink_min*(1.0f-dvert->dw[j].weight)+clmd->sim_parms->shrink_max*dvert->dw [j].weight; // linear interpolation between min and max shrink factor based on weight + } + } + else { + verts->shrink_factor = clmd->sim_parms->shrink_min; + } + } } } @@ -816,6 +831,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) } } + static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float UNUSED(framenr), int first) { int i = 0; @@ -1103,6 +1119,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) unsigned int numverts = (unsigned int)dm->getNumVerts (dm); unsigned int numedges = (unsigned int)dm->getNumEdges (dm); unsigned int numfaces = (unsigned int)dm->getNumTessFaces (dm); + float shrink_factor; MEdge *medge = dm->getEdgeArray (dm); MFace *mface = dm->getTessFaceArray (dm); int index2 = 0; // our second vertex index @@ -1133,15 +1150,26 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) if ( spring ) { spring_verts_ordered_set(spring, medge[i].v1, medge[i].v2); - spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); + if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW && medge[i].flag & ME_LOOSEEDGE) { + // handle sewing (loose edges will be pulled together) + spring->restlen = 0.0f; + spring->stiffness = 1.0f; + spring->type = CLOTH_SPRING_TYPE_SEWING; + } else { + if(clmd->sim_parms->vgroup_shrink > 0) + shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f); + else + shrink_factor = 1.0f - clmd->sim_parms->shrink_min; + spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; + spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0f; + spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; + } clmd->sim_parms->avg_spring_len += spring->restlen; cloth->verts[spring->ij].avg_spring_len += spring->restlen; cloth->verts[spring->kl].avg_spring_len += spring->restlen; cloth->verts[spring->ij].spring_count++; cloth->verts[spring->kl].spring_count++; - spring->type = CLOTH_SPRING_TYPE_STRUCTURAL; spring->flags = 0; - spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0f; struct_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); @@ -1173,7 +1201,11 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) } spring_verts_ordered_set(spring, mface[i].v1, mface[i].v3); - spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); + if(clmd->sim_parms->vgroup_shrink > 0) + shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f); + else + shrink_factor = 1.0f - clmd->sim_parms->shrink_min; + spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; @@ -1193,7 +1225,11 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) } spring_verts_ordered_set(spring, mface[i].v2, mface[i].v4); - spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); + if(clmd->sim_parms->vgroup_shrink > 0) + shrink_factor = 1.0f - ((cloth->verts[spring->ij].shrink_factor + cloth->verts[spring->kl].shrink_factor) / 2.0f); + else + shrink_factor = 1.0f - clmd->sim_parms->shrink_min; + spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index af057b6698d..d328c90aab3 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1260,7 +1260,7 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, } // calculate force of structural + shear springs - if ((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR)) { + if ((s->type & CLOTH_SPRING_TYPE_STRUCTURAL) || (s->type & CLOTH_SPRING_TYPE_SHEAR) || (s->type & CLOTH_SPRING_TYPE_SEWING) ) { if (length > L || no_compress) { s->flags |= CLOTH_SPRING_FLAG_NEEDED; @@ -1271,7 +1271,16 @@ DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, k = scaling / (clmd->sim_parms->avg_spring_len + FLT_EPSILON); // TODO: verify, half verified (couldn't see error) - mul_fvector_S(stretch_force, dir, k*(length-L)); + if(s->type & CLOTH_SPRING_TYPE_SEWING) { + // sewing springs usually have a large distance at first so clamp the force so we don't get tunnelling through colission objects + float force = k*(length-L); + if(force > clmd->sim_parms->max_sewing) { + force = clmd->sim_parms->max_sewing; + } + mul_fvector_S(stretch_force, dir, force); + } else { + mul_fvector_S(stretch_force, dir, k*(length-L)); + } VECADD(s->f, s->f, stretch_force); diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index df1cba6a44d..6c7d500e4e2 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -58,6 +58,7 @@ typedef struct ClothSimSettings { float max_bend; /* max bending scaling value, min is "bending" */ float max_struct; /* max structural scaling value, min is "structural" */ float max_shear; /* max shear scaling value, UNUSED */ + float max_sewing; /* max sewing force */ float avg_spring_len; /* used for normalized springs */ float timescale; /* parameter how fast cloth runs */ float maxgoal; /* see SB */ @@ -70,6 +71,8 @@ typedef struct ClothSimSettings { float velocity_smooth; /* smoothing of velocities for hair */ float collider_friction; /* friction with colliders */ float vel_damping; /* damp the velocity to speed up getting to the resting position */ + float shrink_min; /* min amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */ + float shrink_max; /* max amount to shrink cloth by 0.0f (no shrink) - 1.0f (shrink to nothing) */ int stepsPerFrame; /* Number of time steps per frame. */ int flags; /* flags, see CSIMSETT_FLAGS enum above. */ @@ -79,10 +82,11 @@ typedef struct ClothSimSettings { short vgroup_bend; /* vertex group for scaling bending stiffness */ short vgroup_mass; /* optional vertexgroup name for assigning weight.*/ short vgroup_struct; /* vertex group for scaling structural stiffness */ + short vgroup_shrink; /* vertex group for shrinking cloth */ short shapekey_rest; /* vertex group for scaling structural stiffness */ short presets; /* used for presets on GUI */ short reset; - short pad; + char pad[4]; struct EffectorWeights *effector_weights; } ClothSimSettings; diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index d5c63800aea..683f09aeed6 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -100,6 +100,17 @@ static void rna_ClothSettings_max_struct_set(struct PointerRNA *ptr, float value settings->max_struct = value; } +static void rna_ClothSettings_max_sewing_set(struct PointerRNA *ptr, float value) +{ + ClothSimSettings *settings = (ClothSimSettings*)ptr->data; + + /* check for clipping */ + if (value < 0.0f) + value = 0.0f; + + settings->max_sewing = value; +} + static void rna_ClothSettings_mass_vgroup_get(PointerRNA *ptr, char *value) { ClothSimSettings *sim = (ClothSimSettings *)ptr->data; @@ -118,6 +129,24 @@ static void rna_ClothSettings_mass_vgroup_set(PointerRNA *ptr, const char *value rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_mass); } +static void rna_ClothSettings_shrink_vgroup_get(PointerRNA *ptr, char *value) +{ + ClothSimSettings *sim = (ClothSimSettings*)ptr->data; + rna_object_vgroup_name_index_get(ptr, value, sim->vgroup_shrink); +} + +static int rna_ClothSettings_shrink_vgroup_length(PointerRNA *ptr) +{ + ClothSimSettings *sim = (ClothSimSettings*)ptr->data; + return rna_object_vgroup_name_index_length(ptr, sim->vgroup_shrink); +} + +static void rna_ClothSettings_shrink_vgroup_set(PointerRNA *ptr, const char *value) +{ + ClothSimSettings *sim = (ClothSimSettings*)ptr->data; + rna_object_vgroup_name_index_set(ptr, value, &sim->vgroup_shrink); +} + static void rna_ClothSettings_struct_vgroup_get(PointerRNA *ptr, char *value) { ClothSimSettings *sim = (ClothSimSettings *)ptr->data; @@ -351,6 +380,24 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) "Quality of the simulation in steps per frame (higher is better quality but slower)"); RNA_def_property_update(prop, 0, "rna_cloth_update"); + prop = RNA_def_property(srna, "vertex_group_shrink", PROP_STRING, PROP_NONE); + RNA_def_property_string_funcs(prop, "rna_ClothSettings_shrink_vgroup_get", "rna_ClothSettings_shrink_vgroup_length", + "rna_ClothSettings_shrink_vgroup_set"); + RNA_def_property_ui_text(prop, "Shrink Vertex Group", "Vertex Group for shrinking cloth"); + RNA_def_property_update(prop, 0, "rna_cloth_update"); + + prop = RNA_def_property(srna, "shrink_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "shrink_min"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Shrink Factor Min", "min amount to shrink cloth by"); + RNA_def_property_update(prop, 0, "rna_cloth_update"); + + prop = RNA_def_property(srna, "shrink_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "shrink_max"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Shrink Factor Max", "max amount to shrink cloth by"); + RNA_def_property_update(prop, 0, "rna_cloth_update"); + /* springs */ prop = RNA_def_property(srna, "use_stiffness_scale", PROP_BOOLEAN, PROP_NONE); @@ -380,6 +427,13 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Structural Stiffness Maximum", "Maximum structural stiffness value"); RNA_def_property_update(prop, 0, "rna_cloth_update"); + prop = RNA_def_property(srna, "sewing_force_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "max_sewing"); + RNA_def_property_range(prop, 0.0f, 10000.0f); + RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_sewing_set", NULL); + RNA_def_property_ui_text(prop, "Sewing Force Maximum", "Maximum sewing force"); + RNA_def_property_update(prop, 0, "rna_cloth_update"); + prop = RNA_def_property(srna, "vertex_group_structural_stiffness", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_ClothSettings_struct_vgroup_get", "rna_ClothSettings_struct_vgroup_length", @@ -402,6 +456,11 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Bending Stiffness Maximum", "Maximum bending stiffness value"); RNA_def_property_update(prop, 0, "rna_cloth_update"); + prop = RNA_def_property(srna, "use_sewing_springs", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_SEW); + RNA_def_property_ui_text(prop, "Sew Cloth", "Pulls loose edges together"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + prop = RNA_def_property(srna, "vertex_group_bending", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs(prop, "rna_ClothSettings_bend_vgroup_get", "rna_ClothSettings_bend_vgroup_length", "rna_ClothSettings_bend_vgroup_set"); -- cgit v1.2.3