diff options
Diffstat (limited to 'source/blender/blenkernel/intern/cloth.c')
-rw-r--r-- | source/blender/blenkernel/intern/cloth.c | 620 |
1 files changed, 428 insertions, 192 deletions
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 22fdcb9ea1f..08e638e7cb1 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -33,6 +33,7 @@ #include "DNA_cloth_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "BLI_utildefines.h" @@ -40,10 +41,14 @@ #include "BLI_edgehash.h" #include "BLI_linklist.h" -#include "BKE_cdderivedmesh.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "BKE_bvhutils.h" #include "BKE_cloth.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_mesh_runtime.h" #include "BKE_modifier.h" #include "BKE_pointcache.h" @@ -55,13 +60,19 @@ /* Prototypes for internal functions. */ static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3]); -static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ); -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); +static void cloth_from_mesh ( ClothModifierData *clmd, Mesh *mesh ); +static int cloth_from_object(Object *ob, ClothModifierData *clmd, Mesh *mesh, float framenr, int first); static void cloth_update_springs( ClothModifierData *clmd ); -static void cloth_update_verts( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); -static void cloth_update_spring_lengths( ClothModifierData *clmd, DerivedMesh *dm ); -static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); -static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ); +static void cloth_update_verts( Object *ob, ClothModifierData *clmd, Mesh *mesh ); +static void cloth_update_spring_lengths( ClothModifierData *clmd, Mesh *mesh ); +static int cloth_build_springs ( ClothModifierData *clmd, Mesh *mesh ); +static void cloth_apply_vgroup ( ClothModifierData *clmd, Mesh *mesh ); + +typedef struct BendSpringRef { + int index; + int polys; + ClothSpring *spring; +} BendSpringRef; /****************************************************************************** * @@ -80,13 +91,18 @@ void cloth_init(ClothModifierData *clmd ) clmd->sim_parms->gravity[0] = 0.0; clmd->sim_parms->gravity[1] = 0.0; clmd->sim_parms->gravity[2] = -9.81; - clmd->sim_parms->structural = 15.0; - clmd->sim_parms->max_struct = 15.0; - clmd->sim_parms->shear = 15.0; + clmd->sim_parms->tension = 15.0; + clmd->sim_parms->max_tension = 15.0; + clmd->sim_parms->compression = 15.0; + clmd->sim_parms->max_compression = 15.0; + clmd->sim_parms->shear = 5.0; + clmd->sim_parms->max_shear = 5.0; clmd->sim_parms->bending = 0.5; clmd->sim_parms->max_bend = 0.5; + clmd->sim_parms->tension_damp = 5.0; + clmd->sim_parms->compression_damp = 5.0; + clmd->sim_parms->shear_damp = 5.0; clmd->sim_parms->bending_damping = 0.5; - clmd->sim_parms->Cdis = 5.0; clmd->sim_parms->Cvi = 1.0; clmd->sim_parms->mass = 0.3f; clmd->sim_parms->stepsPerFrame = 5; @@ -101,7 +117,6 @@ void cloth_init(ClothModifierData *clmd ) clmd->sim_parms->timescale = 1.0f; /* speed factor, describes how fast cloth moves */ clmd->sim_parms->time_scale = 1.0f; /* multiplies cloth speed */ clmd->sim_parms->reset = 0; - clmd->sim_parms->vel_damping = 1.0f; /* 1.0 = no damping, 0.0 = fully dampened */ clmd->coll_parms->self_friction = 5.0; clmd->coll_parms->friction = 5.0; @@ -129,6 +144,8 @@ void cloth_init(ClothModifierData *clmd ) clmd->sim_parms->voxel_cell_size = 0.1f; + clmd->sim_parms->bending_model = CLOTH_BENDING_ANGULAR; + if (!clmd->sim_parms->effector_weights) clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL); @@ -317,7 +334,7 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr); } -static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr) +static int do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int framenr) { PointCache *cache; @@ -345,7 +362,7 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul return 1; } -static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr) +static int do_step_cloth(Depsgraph *depsgraph, Object *ob, ClothModifierData *clmd, Mesh *result, int framenr) { ClothVertex *verts = NULL; Cloth *cloth; @@ -357,7 +374,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul /* simulate 1 frame forward */ cloth = clmd->clothObject; verts = cloth->verts; - mvert = result->getVertArray(result); + mvert = result->mvert; /* force any pinned verts to their constrained location. */ for (i = 0; i < clmd->clothObject->mvert_num; i++, verts++) { @@ -370,7 +387,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul mul_m4_v3(ob->obmat, verts->xconst); } - effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true); + effectors = BKE_effectors_create(depsgraph, ob, NULL, clmd->sim_parms->effector_weights); if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH ) cloth_update_verts ( ob, clmd, result ); @@ -378,19 +395,22 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul /* Support for dynamic vertex groups, changing from frame to frame */ cloth_apply_vgroup ( clmd, result ); - if ( clmd->sim_parms->flags & (CLOTH_SIMSETTINGS_FLAG_SEW | CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH) ) + if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH) || + (clmd->sim_parms->vgroup_shrink > 0) || (clmd->sim_parms->shrink_min > 0.0f)) + { cloth_update_spring_lengths ( clmd, result ); + } cloth_update_springs( clmd ); // TIMEIT_START(cloth_step) /* call the solver. */ - ret = BPH_cloth_solve(ob, framenr, clmd, effectors); + ret = BPH_cloth_solve(depsgraph, ob, framenr, clmd, effectors); // TIMEIT_END(cloth_step) - pdEndEffectors(&effectors); + BKE_effectors_free(effectors); // printf ( "%f\n", ( float ) tval() ); @@ -400,7 +420,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul /************************************************ * clothModifier_do - main simulation function ************************************************/ -void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3]) +void clothModifier_do(ClothModifierData *clmd, Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *mesh, float (*vertexCos)[3]) { PointCache *cache; PTCacheID pid; @@ -408,15 +428,14 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived int framenr, startframe, endframe; int cache_result; - clmd->scene= scene; /* nice to pass on later :) */ - framenr= (int)scene->r.cfra; + framenr = DEG_get_ctime(depsgraph); cache= clmd->point_cache; BKE_ptcache_id_from_cloth(&pid, ob, clmd); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); clmd->sim_parms->timescale= timescale * clmd->sim_parms->time_scale; - if (clmd->sim_parms->reset || (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->mvert_num)) { + if (clmd->sim_parms->reset || (clmd->clothObject && mesh->totvert != clmd->clothObject->mvert_num)) { clmd->sim_parms->reset = 0; cache->flag |= PTCACHE_OUTDATED; BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); @@ -438,12 +457,12 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived } /* initialize simulation data if it didn't exist already */ - if (!do_init_cloth(ob, clmd, dm, framenr)) + if (!do_init_cloth(ob, clmd, mesh, framenr)) return; if (framenr == startframe) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - do_init_cloth(ob, clmd, dm, framenr); + do_init_cloth(ob, clmd, mesh, framenr); BKE_ptcache_validate(cache, framenr); cache->flag &= ~PTCACHE_REDO_NEEDED; clmd->clothObject->last_frame= framenr; @@ -479,9 +498,6 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived return; } - if (!can_simulate) - return; - /* if on second frame, write cache for first frame */ if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) BKE_ptcache_write(&pid, startframe); @@ -491,7 +507,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived /* do simulation */ BKE_ptcache_validate(cache, framenr); - if (!do_step_cloth(ob, clmd, dm, framenr)) { + if (!do_step_cloth(depsgraph, ob, clmd, mesh, framenr)) { BKE_ptcache_invalidate(cache); } else @@ -528,6 +544,9 @@ void cloth_free_modifier(ClothModifierData *clmd ) while (search) { ClothSpring *spring = search->link; + MEM_SAFE_FREE(spring->pa); + MEM_SAFE_FREE(spring->pb); + MEM_freeN ( spring ); search = search->next; } @@ -594,6 +613,9 @@ void cloth_free_modifier_extern(ClothModifierData *clmd ) while (search) { ClothSpring *spring = search->link; + MEM_SAFE_FREE(spring->pa); + MEM_SAFE_FREE(spring->pb); + MEM_freeN ( spring ); search = search->next; } @@ -659,15 +681,11 @@ static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*verte int cloth_uses_vgroup(ClothModifierData *clmd) { - return (((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) || - (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) || - (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW) || - (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF)) && - ((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))); + return (((clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) && (clmd->coll_parms->vgroup_selfcol > 0)) || + (clmd->sim_parms->vgroup_struct > 0) || + (clmd->sim_parms->vgroup_bend > 0) || + (clmd->sim_parms->vgroup_shrink > 0) || + (clmd->sim_parms->vgroup_mass > 0)); } /** @@ -675,7 +693,7 @@ int cloth_uses_vgroup(ClothModifierData *clmd) * **/ /* can be optimized to do all groups in one loop */ -static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) +static void cloth_apply_vgroup ( ClothModifierData *clmd, Mesh *mesh ) { int i = 0; int j = 0; @@ -685,11 +703,11 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) /* float goalfac = 0; */ /* UNUSED */ ClothVertex *verts = NULL; - if (!clmd || !dm) return; + if (!clmd || !mesh) return; clothObj = clmd->clothObject; - mvert_num = dm->getNumVerts(dm); + mvert_num = mesh->totvert; verts = clothObj->verts; @@ -697,7 +715,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) for (i = 0; i < mvert_num; i++, verts++) { /* Reset Goal values to standard */ - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + if (clmd->sim_parms->vgroup_mass > 0) verts->goal= clmd->sim_parms->defgoal; else verts->goal= 0.0f; @@ -709,10 +727,10 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) verts->flags &= ~CLOTH_VERT_FLAG_PINNED; verts->flags &= ~CLOTH_VERT_FLAG_NOSELFCOLL; - dvert = dm->getVertData ( dm, i, CD_MDEFORMVERT ); + dvert = CustomData_get(&mesh->vdata, i, CD_MDEFORMVERT); if ( dvert ) { for ( j = 0; j < dvert->totweight; j++ ) { - if (( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass-1)) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL )) { + if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_mass - 1)) { verts->goal = dvert->dw [j].weight; /* goalfac= 1.0f; */ /* UNUSED */ @@ -725,15 +743,16 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) verts->flags |= CLOTH_VERT_FLAG_PINNED; } - if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) { - if ( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_struct-1)) { - verts->struct_stiff = dvert->dw [j].weight; - verts->shear_stiff = dvert->dw [j].weight; - } + if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_struct - 1)) { + verts->struct_stiff = dvert->dw[j].weight; + } - if ( dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_bend-1)) { - verts->bend_stiff = dvert->dw [j].weight; - } + if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shear - 1)) { + verts->shear_stiff = dvert->dw[j].weight; + } + + if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_bend - 1)) { + verts->bend_stiff = dvert->dw[j].weight; } if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF ) { @@ -743,12 +762,10 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) } } } - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW ) { - if (clmd->sim_parms->vgroup_shrink > 0) { - if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shrink - 1)) { - /* used for linear interpolation between min and max shrink factor based on weight */ - verts->shrink_factor = dvert->dw[j].weight; - } + if (clmd->sim_parms->vgroup_shrink > 0) { + if (dvert->dw[j].def_nr == (clmd->sim_parms->vgroup_shrink - 1)) { + /* Used for linear interpolation between min and max shrink factor based on weight. */ + verts->shrink_factor = dvert->dw[j].weight; } } } @@ -759,23 +776,19 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) static float cloth_shrink_factor(ClothModifierData *clmd, ClothVertex *verts, int i1, int i2) { - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SEW ) { - /* linear interpolation between min and max shrink factor based on weight */ - float base = 1.0f - clmd->sim_parms->shrink_min; - float delta = clmd->sim_parms->shrink_min - clmd->sim_parms->shrink_max; + /* Linear interpolation between min and max shrink factor based on weight. */ + float base = 1.0f - clmd->sim_parms->shrink_min; + float delta = clmd->sim_parms->shrink_min - clmd->sim_parms->shrink_max; - float k1 = base + delta * verts[i1].shrink_factor; - float k2 = base + delta * verts[i2].shrink_factor; + float k1 = base + delta * verts[i1].shrink_factor; + float k2 = base + delta * verts[i2].shrink_factor; - /* Use geometrical mean to average two factors since it behaves better - for diagonals when a rectangle transforms into a trapezoid. */ - return sqrtf(k1 * k2); - } - else - return 1.0f; + /* Use geometrical mean to average two factors since it behaves better + for diagonals when a rectangle transforms into a trapezoid. */ + return sqrtf(k1 * k2); } -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float UNUSED(framenr), int first) +static int cloth_from_object(Object *ob, ClothModifierData *clmd, Mesh *mesh, float UNUSED(framenr), int first) { int i = 0; MVert *mvert = NULL; @@ -805,25 +818,25 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d return 0; } - // mesh input objects need DerivedMesh - if ( !dm ) + // mesh input objects need Mesh + if ( !mesh ) return 0; - cloth_from_mesh ( clmd, dm ); + cloth_from_mesh ( clmd, mesh ); // create springs clmd->clothObject->springs = NULL; clmd->clothObject->numsprings = -1; if ( clmd->sim_parms->shapekey_rest && !(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH ) ) - shapekey_rest = dm->getVertDataArray ( dm, CD_CLOTH_ORCO ); + shapekey_rest = CustomData_get_layer(&mesh->vdata, CD_CLOTH_ORCO); - mvert = dm->getVertArray (dm); + mvert = mesh->mvert; verts = clmd->clothObject->verts; // set initial values - for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) { + for ( i = 0; i < mesh->totvert; i++, verts++ ) { if (first) { copy_v3_v3(verts->x, mvert[i].co); @@ -841,7 +854,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d verts->mass = clmd->sim_parms->mass; verts->impulse_count = 0; - if ( clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL ) + if (clmd->sim_parms->vgroup_mass > 0) verts->goal= clmd->sim_parms->defgoal; else verts->goal= 0.0f; @@ -861,9 +874,9 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d // apply / set vertex groups // has to be happen before springs are build! - cloth_apply_vgroup (clmd, dm); + cloth_apply_vgroup (clmd, mesh); - if ( !cloth_build_springs ( clmd, dm ) ) { + if ( !cloth_build_springs ( clmd, mesh ) ) { cloth_free_modifier ( clmd ); modifier_setError(&(clmd->modifier), "Cannot build springs"); printf("cloth_free_modifier cloth_build_springs\n"); @@ -878,7 +891,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d clmd->clothObject->bvhtree = bvhtree_build_from_cloth ( clmd, MAX2(clmd->coll_parms->epsilon, clmd->coll_parms->distance_repel) ); - for (i = 0; i < dm->getNumVerts(dm); i++) { + for (i = 0; i < mesh->totvert; i++) { maxdist = MAX2(maxdist, clmd->coll_parms->selfepsilon* ( cloth->verts[i].avg_spring_len*2.0f)); } @@ -887,12 +900,12 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d return 1; } -static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) +static void cloth_from_mesh ( ClothModifierData *clmd, Mesh *mesh ) { - const MLoop *mloop = dm->getLoopArray(dm); - const MLoopTri *looptri = dm->getLoopTriArray(dm); - const unsigned int mvert_num = dm->getNumVerts(dm); - const unsigned int looptri_num = dm->getNumLoopTri(dm); + const MLoop *mloop = mesh->mloop; + const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh); + const unsigned int mvert_num = mesh->totvert; + const unsigned int looptri_num = mesh->runtime.looptris.len; /* Allocate our vertices. */ clmd->clothObject->mvert_num = mvert_num; @@ -913,7 +926,7 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) printf("cloth_free_modifier clmd->clothObject->looptri\n"); return; } - DM_verttri_from_looptri(clmd->clothObject->tri, mloop, looptri, looptri_num); + BKE_mesh_runtime_verttri_from_looptri(clmd->clothObject->tri, mloop, looptri, looptri_num); /* Free the springs since they can't be correct if the vertices * changed. @@ -924,7 +937,7 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) } /*************************************************************************************** - * SPRING NETWORK BUILDING IMPLEMENTATION BEGIN + * SPRING NETWORK GPU_BATCH_BUILDING IMPLEMENTATION BEGIN ***************************************************************************************/ BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1) @@ -951,13 +964,16 @@ static void cloth_free_edgelist(LinkNodePair *edgelist, unsigned int mvert_num) } } -static void cloth_free_errorsprings(Cloth *cloth, LinkNodePair *edgelist) +static void cloth_free_errorsprings(Cloth *cloth, LinkNodePair *edgelist, BendSpringRef *spring_ref) { if ( cloth->springs != NULL ) { LinkNode *search = cloth->springs; while (search) { ClothSpring *spring = search->link; + MEM_SAFE_FREE(spring->pa); + MEM_SAFE_FREE(spring->pb); + MEM_freeN ( spring ); search = search->next; } @@ -968,12 +984,49 @@ static void cloth_free_errorsprings(Cloth *cloth, LinkNodePair *edgelist) cloth_free_edgelist(edgelist, cloth->mvert_num); + MEM_SAFE_FREE(spring_ref); + if (cloth->edgeset) { BLI_edgeset_free(cloth->edgeset); cloth->edgeset = NULL; } } +BLI_INLINE void cloth_bend_poly_dir(ClothVertex *verts, int i, int j, int *inds, int len, float r_dir[3]) +{ + float cent[3] = {0}; + float fact = 1.0f / len; + + for (int x = 0; x < len; x++) { + madd_v3_v3fl(cent, verts[inds[x]].xrest, fact); + } + + normal_tri_v3(r_dir, verts[i].xrest, verts[j].xrest, cent); +} + +static float cloth_spring_angle(ClothVertex *verts, int i, int j, int *i_a, int *i_b, int len_a, int len_b) +{ + float dir_a[3], dir_b[3]; + float tmp[3], vec_e[3]; + float sin, cos; + + /* Poly vectors. */ + cloth_bend_poly_dir(verts, j, i, i_a, len_a, dir_a); + cloth_bend_poly_dir(verts, i, j, i_b, len_b, dir_b); + + /* Edge vector. */ + sub_v3_v3v3(vec_e, verts[i].xrest, verts[j].xrest); + normalize_v3(vec_e); + + /* Compute angle. */ + cos = dot_v3v3(dir_a, dir_b); + + cross_v3_v3v3(tmp, dir_a, dir_b); + sin = dot_v3v3(tmp, vec_e); + + return atan2f(sin, cos); +} + static void cloth_hair_update_bending_targets(ClothModifierData *clmd) { Cloth *cloth = clmd->clothObject; @@ -998,7 +1051,7 @@ static void cloth_hair_update_bending_targets(ClothModifierData *clmd) ClothHairData *hair_ij, *hair_kl; bool is_root = spring->kl != prev_mn; - if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) { + if (spring->type != CLOTH_SPRING_TYPE_BENDING_HAIR) { continue; } @@ -1073,7 +1126,7 @@ static void cloth_hair_update_bending_rest_targets(ClothModifierData *clmd) ClothHairData *hair_ij, *hair_kl; bool is_root = spring->kl != prev_mn; - if (spring->type != CLOTH_SPRING_TYPE_BENDING_ANG) { + if (spring->type != CLOTH_SPRING_TYPE_BENDING_HAIR) { continue; } @@ -1113,18 +1166,24 @@ static void cloth_update_springs( ClothModifierData *clmd ) while (search) { ClothSpring *spring = search->link; - spring->stiffness = 0.0f; + spring->lin_stiffness = 0.0f; - if (spring->type == CLOTH_SPRING_TYPE_STRUCTURAL) { - spring->stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0f; + if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { + if (spring->type & CLOTH_SPRING_TYPE_BENDING) { + spring->ang_stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; + } + } + + if (spring->type & CLOTH_SPRING_TYPE_STRUCTURAL) { + spring->lin_stiffness = (cloth->verts[spring->kl].struct_stiff + cloth->verts[spring->ij].struct_stiff) / 2.0f; } - else if (spring->type == CLOTH_SPRING_TYPE_SHEAR) { - spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; + else if (spring->type & CLOTH_SPRING_TYPE_SHEAR) { + spring->lin_stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; } else if (spring->type == CLOTH_SPRING_TYPE_BENDING) { - spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; + spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; } - else if (spring->type == CLOTH_SPRING_TYPE_BENDING_ANG) { + else if (spring->type == CLOTH_SPRING_TYPE_BENDING_HAIR) { ClothVertex *v1 = &cloth->verts[spring->ij]; ClothVertex *v2 = &cloth->verts[spring->kl]; if (clmd->hairdata) { @@ -1132,7 +1191,7 @@ static void cloth_update_springs( ClothModifierData *clmd ) v1->bend_stiff = clmd->hairdata[spring->ij].bending_stiffness; v2->bend_stiff = clmd->hairdata[spring->kl].bending_stiffness; } - spring->stiffness = (v1->bend_stiff + v2->bend_stiff) / 2.0f; + spring->lin_stiffness = (v1->bend_stiff + v2->bend_stiff) / 2.0f; } else if (spring->type == CLOTH_SPRING_TYPE_GOAL) { /* Warning: Appending NEW goal springs does not work because implicit solver would need reset! */ @@ -1155,27 +1214,27 @@ static void cloth_update_springs( ClothModifierData *clmd ) } /* Update rest verts, for dynamically deformable cloth */ -static void cloth_update_verts( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ) +static void cloth_update_verts( Object *ob, ClothModifierData *clmd, Mesh *mesh ) { unsigned int i = 0; - MVert *mvert = dm->getVertArray (dm); + MVert *mvert = mesh->mvert; ClothVertex *verts = clmd->clothObject->verts; /* vertex count is already ensured to match */ - for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) { + for ( i = 0; i < mesh->totvert; i++, verts++ ) { copy_v3_v3(verts->xrest, mvert[i].co); mul_m4_v3(ob->obmat, verts->xrest); } } /* Update spring rest lenght, for dynamically deformable cloth */ -static void cloth_update_spring_lengths( ClothModifierData *clmd, DerivedMesh *dm ) +static void cloth_update_spring_lengths( ClothModifierData *clmd, Mesh *mesh ) { Cloth *cloth = clmd->clothObject; LinkNode *search = cloth->springs; unsigned int struct_springs = 0; unsigned int i = 0; - unsigned int mvert_num = (unsigned int)dm->getNumVerts(dm); + unsigned int mvert_num = (unsigned int)mesh->totvert; float shrink_factor; clmd->sim_parms->avg_spring_len = 0.0f; @@ -1187,16 +1246,23 @@ static void cloth_update_spring_lengths( ClothModifierData *clmd, DerivedMesh *d while (search) { ClothSpring *spring = search->link; - if ( spring->type != CLOTH_SPRING_TYPE_SEWING ) { - if ( spring->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR | CLOTH_SPRING_TYPE_BENDING) ) + if (spring->type != CLOTH_SPRING_TYPE_SEWING) { + if (spring->type & (CLOTH_SPRING_TYPE_STRUCTURAL | CLOTH_SPRING_TYPE_SHEAR | CLOTH_SPRING_TYPE_BENDING)) { shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); - else + } + else { shrink_factor = 1.0f; + } spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; + + if (spring->type & CLOTH_SPRING_TYPE_BENDING) { + spring->restang = cloth_spring_angle(cloth->verts, spring->ij, spring->kl, + spring->pa, spring->pb, spring->la, spring->lb); + } } - if ( spring->type == CLOTH_SPRING_TYPE_STRUCTURAL ) { + if (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; @@ -1206,12 +1272,14 @@ static void cloth_update_spring_lengths( ClothModifierData *clmd, DerivedMesh *d search = search->next; } - if (struct_springs > 0) + if (struct_springs > 0) { clmd->sim_parms->avg_spring_len /= struct_springs; + } for (i = 0; i < mvert_num; i++) { - if (cloth->verts[i].spring_count > 0) + if (cloth->verts[i].spring_count > 0) { cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f / ((float)cloth->verts[i].spring_count); + } } } @@ -1250,23 +1318,115 @@ void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3] mul_m3_m3m3(mat, rot, mat); } -static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) +/* Add a shear and a bend spring between two verts within a poly. */ +static bool cloth_add_shear_bend_spring(ClothModifierData *clmd, LinkNodePair *edgelist, + const MLoop *mloop, const MPoly *mpoly, int i, int j, int k) +{ + Cloth *cloth = clmd->clothObject; + ClothSpring *spring; + const MLoop *tmp_loop; + float shrink_factor; + int x, y; + + /* Combined shear/bend properties. */ + spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); + + if (!spring) { + return false; + } + + spring_verts_ordered_set(spring, + mloop[mpoly[i].loopstart + j].v, + mloop[mpoly[i].loopstart + k].v); + + shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); + spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; + spring->type |= CLOTH_SPRING_TYPE_SHEAR; + spring->lin_stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; + + if (edgelist) { + BLI_linklist_append(&edgelist[spring->ij], spring); + BLI_linklist_append(&edgelist[spring->kl], spring); + } + + /* Bending specific properties. */ + if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { + spring->type |= CLOTH_SPRING_TYPE_BENDING; + + spring->la = k - j + 1; + spring->lb = mpoly[i].totloop - k + j + 1; + + spring->pa = MEM_mallocN(sizeof(*spring->pa) * spring->la, "spring poly"); + if (!spring->pa) { + return false; + } + + spring->pb = MEM_mallocN(sizeof(*spring->pb) * spring->lb, "spring poly"); + if (!spring->pb) { + return false; + } + + tmp_loop = mloop + mpoly[i].loopstart; + + for (x = 0; x < spring->la; x++) { + spring->pa[x] = tmp_loop[j + x].v; + } + + for (x = 0; x <= j; x++) { + spring->pb[x] = tmp_loop[x].v; + } + + for (y = k; y < mpoly[i].totloop; x++, y++) { + spring->pb[x] = tmp_loop[y].v; + } + + spring->mn = -1; + + spring->restang = cloth_spring_angle(cloth->verts, spring->ij, spring->kl, + spring->pa, spring->pb, spring->la, spring->lb); + + spring->ang_stiffness = (cloth->verts[spring->ij].bend_stiff + cloth->verts[spring->kl].bend_stiff) / 2.0f; + } + + BLI_linklist_prepend(&cloth->springs, spring); + + return true; +} + +BLI_INLINE bool cloth_bend_set_poly_vert_array(int **poly, int len, const MLoop *mloop) +{ + int *p = MEM_mallocN(sizeof(int) * len, "spring poly"); + + if (!p) { + return false; + } + + for (int i = 0; i < len; i++, mloop++) { + p[i] = mloop->v; + } + + *poly = p; + + return true; +} + +static int cloth_build_springs ( ClothModifierData *clmd, Mesh *mesh ) { Cloth *cloth = clmd->clothObject; ClothSpring *spring = NULL, *tspring = NULL, *tspring2 = NULL; unsigned int struct_springs = 0, shear_springs=0, bend_springs = 0, struct_springs_real = 0; - unsigned int i = 0; - unsigned int mvert_num = (unsigned int)dm->getNumVerts(dm); - unsigned int numedges = (unsigned int)dm->getNumEdges (dm); - unsigned int numpolys = (unsigned int)dm->getNumPolys(dm); + unsigned int mvert_num = (unsigned int)mesh->totvert; + unsigned int numedges = (unsigned int)mesh->totedge; + unsigned int numpolys = (unsigned int)mesh->totpoly; float shrink_factor; - const MEdge *medge = dm->getEdgeArray(dm); - const MPoly *mpoly = dm->getPolyArray(dm); - const MLoop *mloop = dm->getLoopArray(dm); + const MEdge *medge = mesh->medge; + const MPoly *mpoly = mesh->mpoly; + const MLoop *mloop = mesh->mloop; int index2 = 0; // our second vertex index - LinkNodePair *edgelist; + LinkNodePair *edgelist = NULL; EdgeSet *edgeset = NULL; LinkNode *search = NULL, *search2 = NULL; + BendSpringRef *spring_ref = NULL; // error handling if ( numedges==0 ) @@ -1280,13 +1440,23 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) cloth->springs = NULL; cloth->edgeset = NULL; - edgelist = MEM_callocN(sizeof(*edgelist) * mvert_num, "cloth_edgelist_alloc" ); + if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { + spring_ref = MEM_callocN(sizeof(*spring_ref) * numedges, "temp bend spring reference"); - if (!edgelist) - return 0; + if (!spring_ref) { + return 0; + } + } + else { + edgelist = MEM_callocN(sizeof(*edgelist) * mvert_num, "cloth_edgelist_alloc" ); - // structural springs - for ( i = 0; i < numedges; i++ ) { + if (!edgelist) { + return 0; + } + } + + /* Structural springs. */ + for (int i = 0; i < numedges; i++) { spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if ( spring ) { @@ -1294,13 +1464,13 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) 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->lin_stiffness = 1.0f; spring->type = CLOTH_SPRING_TYPE_SEWING; } else { shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); 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->lin_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; @@ -1315,9 +1485,13 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) struct_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); + + if (spring_ref) { + spring_ref[i].spring = spring; + } } else { - cloth_free_errorsprings(cloth, edgelist); + cloth_free_errorsprings(cloth, edgelist, spring_ref); return 0; } } @@ -1325,86 +1499,147 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) if (struct_springs_real > 0) clmd->sim_parms->avg_spring_len /= struct_springs_real; - for (i = 0; i < mvert_num; i++) { + for (int i = 0; i < mvert_num; i++) { if (cloth->verts[i].spring_count > 0) cloth->verts[i].avg_spring_len = cloth->verts[i].avg_spring_len * 0.49f / ((float)cloth->verts[i].spring_count); } - // shear springs - for (i = 0; i < numpolys; i++) { - /* triangle faces already have shear springs due to structural geometry */ - if (mpoly[i].totloop == 4) { - int j; + edgeset = BLI_edgeset_new_ex(__func__, numedges); + cloth->edgeset = edgeset; - for (j = 0; j != 2; j++) { - spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); + if (numpolys) { + for (int i = 0; i < numpolys; i++) { + /* Shear springs. */ + /* Triangle faces already have shear springs due to structural geometry. */ + if (mpoly[i].totloop > 3) { + for (int j = 1; j < mpoly[i].totloop - 1; j++) { + if (j > 1) { + if (cloth_add_shear_bend_spring(clmd, edgelist, mloop, mpoly, i, 0, j)) { + shear_springs++; + + if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { + bend_springs++; + } + } + else { + cloth_free_errorsprings(cloth, edgelist, spring_ref); + return 0; + } + } + + for (int k = j + 2; k < mpoly[i].totloop; k++) { + if (cloth_add_shear_bend_spring(clmd, edgelist, mloop, mpoly, i, j, k)) { + shear_springs++; - if (!spring) { - cloth_free_errorsprings(cloth, edgelist); - return 0; + if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { + bend_springs++; + } + } + else { + cloth_free_errorsprings(cloth, edgelist, spring_ref); + return 0; + } + } } + } - spring_verts_ordered_set( - spring, - mloop[mpoly[i].loopstart + (j + 0)].v, - mloop[mpoly[i].loopstart + (j + 2)].v); + /* Angular bending springs along struct springs. */ + if (clmd->sim_parms->bending_model == CLOTH_BENDING_ANGULAR) { + const MLoop *ml = mloop + mpoly[i].loopstart; - shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); - 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; + for (int j = 0; j < mpoly[i].totloop; j++, ml++) { + BendSpringRef *curr_ref = &spring_ref[ml->e]; + curr_ref->polys++; + + /* First poly found for this edge, store poly index. */ + if (curr_ref->polys == 1) { + curr_ref->index = i; + } + /* Second poly found for this egde, add bending data. */ + else if (curr_ref->polys == 2) { + spring = curr_ref->spring; + + spring->type |= CLOTH_SPRING_TYPE_BENDING; + + spring->la = mpoly[curr_ref->index].totloop; + spring->lb = mpoly[i].totloop; - BLI_linklist_append(&edgelist[spring->ij], spring); - BLI_linklist_append(&edgelist[spring->kl], spring); + if (!cloth_bend_set_poly_vert_array(&spring->pa, spring->la, &mloop[mpoly[curr_ref->index].loopstart]) || + !cloth_bend_set_poly_vert_array(&spring->pb, spring->lb, &mloop[mpoly[i].loopstart])) + { + cloth_free_errorsprings(cloth, edgelist, spring_ref); + return 0; + } + + spring->mn = ml->e; + + spring->restang = cloth_spring_angle(cloth->verts, spring->ij, spring->kl, + spring->pa, spring->pb, spring->la, spring->lb); - shear_springs++; + spring->ang_stiffness = (cloth->verts[spring->ij].bend_stiff + cloth->verts[spring->kl].bend_stiff) / 2.0f; + + bend_springs++; + } + /* Third poly found for this egde, remove bending data. */ + else if (curr_ref->polys == 3) { + spring = curr_ref->spring; - BLI_linklist_prepend(&cloth->springs, spring); + spring->type &= ~CLOTH_SPRING_TYPE_BENDING; + MEM_freeN(spring->pa); + MEM_freeN(spring->pb); + spring->pa = NULL; + spring->pb = NULL; + + bend_springs--; + } + } } } - } - edgeset = BLI_edgeset_new_ex(__func__, numedges); - cloth->edgeset = edgeset; + /* Linear bending springs. */ + if (clmd->sim_parms->bending_model == CLOTH_BENDING_LINEAR) { + search2 = cloth->springs; - if (numpolys) { - // bending springs - search2 = cloth->springs; - for ( i = struct_springs; i < struct_springs+shear_springs; i++ ) { - if ( !search2 ) - break; + for (int i = struct_springs; i < struct_springs+shear_springs; i++) { + if (!search2) { + break; + } - tspring2 = search2->link; - search = edgelist[tspring2->kl].list; - while ( search ) { - tspring = search->link; - index2 = ( ( tspring->ij==tspring2->kl ) ? ( tspring->kl ) : ( tspring->ij ) ); + tspring2 = search2->link; + search = edgelist[tspring2->kl].list; + + while (search) { + tspring = search->link; + index2 = ((tspring->ij == tspring2->kl) ? (tspring->kl) : (tspring->ij)); + + /* Check for existing spring. */ + /* Check also if startpoint is equal to endpoint. */ + if ((index2 != tspring2->ij) && + !BLI_edgeset_haskey(edgeset, tspring2->ij, index2)) + { + spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); + + if (!spring) { + cloth_free_errorsprings(cloth, edgelist, spring_ref); + return 0; + } - // check for existing spring - // check also if startpoint is equal to endpoint - if ((index2 != tspring2->ij) && - !BLI_edgeset_haskey(edgeset, tspring2->ij, index2)) - { - spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); + spring_verts_ordered_set(spring, tspring2->ij, index2); + shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); + spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; + spring->type = CLOTH_SPRING_TYPE_BENDING; + spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; + BLI_edgeset_insert(edgeset, spring->ij, spring->kl); + bend_springs++; - if (!spring) { - cloth_free_errorsprings(cloth, edgelist); - return 0; + BLI_linklist_prepend(&cloth->springs, spring); } - spring_verts_ordered_set(spring, tspring2->ij, index2); - shrink_factor = cloth_shrink_factor(clmd, cloth->verts, spring->ij, spring->kl); - spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest) * shrink_factor; - spring->type = CLOTH_SPRING_TYPE_BENDING; - spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; - BLI_edgeset_insert(edgeset, spring->ij, spring->kl); - bend_springs++; - - BLI_linklist_prepend ( &cloth->springs, spring ); + search = search->next; } - search = search->next; + + search2 = search2->next; } - search2 = search2->next; } } else if (struct_springs > 2) { @@ -1419,7 +1654,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if (!spring) { - cloth_free_errorsprings(cloth, edgelist); + cloth_free_errorsprings(cloth, edgelist, spring_ref); return 0; } @@ -1427,8 +1662,8 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring->kl = tspring->ij; spring->mn = tspring->kl; spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); - spring->type = CLOTH_SPRING_TYPE_BENDING_ANG; - spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; + spring->type = CLOTH_SPRING_TYPE_BENDING_HAIR; + spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; bend_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); @@ -1456,7 +1691,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if (!spring) { - cloth_free_errorsprings(cloth, edgelist); + cloth_free_errorsprings(cloth, edgelist, spring_ref); return 0; } @@ -1464,7 +1699,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring->kl = tspring->kl; spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_BENDING; - spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; + spring->lin_stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; bend_springs++; BLI_linklist_prepend ( &cloth->springs, spring ); @@ -1481,17 +1716,18 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) /* note: the edges may already exist so run reinsert */ /* insert other near springs in edgeset AFTER bending springs are calculated (for selfcolls) */ - for (i = 0; i < numedges; i++) { /* struct springs */ + for (int i = 0; i < numedges; i++) { /* struct springs */ BLI_edgeset_add(edgeset, medge[i].v1, medge[i].v2); } - for (i = 0; i < numpolys; i++) { /* edge springs */ + for (int i = 0; i < numpolys; i++) { /* edge springs */ if (mpoly[i].totloop == 4) { BLI_edgeset_add(edgeset, mloop[mpoly[i].loopstart + 0].v, mloop[mpoly[i].loopstart + 2].v); BLI_edgeset_add(edgeset, mloop[mpoly[i].loopstart + 1].v, mloop[mpoly[i].loopstart + 3].v); } } + MEM_SAFE_FREE(spring_ref); cloth->numsprings = struct_springs + shear_springs + bend_springs; @@ -1506,5 +1742,5 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) } /* cloth_build_springs */ /*************************************************************************************** - * SPRING NETWORK BUILDING IMPLEMENTATION END + * SPRING NETWORK GPU_BATCH_BUILDING IMPLEMENTATION END ***************************************************************************************/ |