diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index df118276809..10a336a075a 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -59,6 +59,11 @@ struct PartDeflect; #define CLOTH_VERT_FLAG_PINNED 1 #define CLOTH_VERT_FLAG_NOSELFCOLL 2 /* vertex NOT used for self collisions */ +typedef struct ClothHairRoot { + float loc[3]; + float rot[3][3]; +} ClothHairRoot; + /** * This structure describes a cloth object against which the * simulation can run. diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 71656240369..14082af4cbd 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -4010,12 +4010,19 @@ static void do_hair_dynamics(ParticleSimulationData *sim) if (dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) { dm->release(dm); dm = psys->hair_in_dm = NULL; + + MEM_freeN(psys->clmd->roots); + psys->clmd->roots = NULL; } if (!dm) { dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0, 0, 0); DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL); } + + if (!psys->clmd->roots) { + psys->clmd->roots = MEM_mallocN(sizeof(ClothHairRoot) * totpoint, "hair roots"); + } mvert = CDDM_get_verts(dm); medge = CDDM_get_edges(dm); @@ -4032,6 +4039,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); for (k=0, key=pa->hair; ktotkey; k++,key++) { + ClothHairRoot *root = &psys->clmd->roots[pa->hair_index + k - 1]; /* create fake root before actual root to resist bending */ if (k==0) { @@ -4057,6 +4065,10 @@ static void do_hair_dynamics(ParticleSimulationData *sim) } } + /* store root transform in cloth data */ + copy_v3_v3(root->loc, hairmat[3]); + copy_m3_m4(root->rot, hairmat); + copy_v3_v3(mvert->co, key->co); mul_m4_v3(hairmat, mvert->co); mvert++; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 902f2a41800..53ceaa00703 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3934,6 +3934,7 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) if (psys->clmd) { psys->clmd = newdataadr(fd, psys->clmd); psys->clmd->clothObject = NULL; + psys->clmd->roots = NULL; psys->clmd->sim_parms= newdataadr(fd, psys->clmd->sim_parms); psys->clmd->coll_parms= newdataadr(fd, psys->clmd->coll_parms); @@ -4662,6 +4663,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) ClothModifierData *clmd = (ClothModifierData *)md; clmd->clothObject = NULL; + clmd->roots = NULL; clmd->sim_parms= newdataadr(fd, clmd->sim_parms); clmd->coll_parms= newdataadr(fd, clmd->coll_parms); diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 812e7d20e2a..3dd9ebb5f37 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -564,6 +564,8 @@ typedef struct ClothModifierData { struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */ struct PointCache *point_cache; /* definition is in DNA_object_force.h */ struct ListBase ptcaches; + /* XXX nasty hack, remove once hair can be separated from cloth modifier data */ + struct ClothHairRoot *roots; struct SimDebugData *debug_data; /* debug info */ } ClothModifierData; diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 15a73c0a34d..5c5e38f3444 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -178,6 +178,7 @@ static void copyData(ModifierData *md, ModifierData *target) tclmd->point_cache = BKE_ptcache_add(&tclmd->ptcaches); tclmd->point_cache->step = 1; tclmd->clothObject = NULL; + tclmd->roots = NULL; tclmd->debug_data = NULL; } @@ -207,6 +208,9 @@ static void freeData(ModifierData *md) BKE_ptcache_free_list(&clmd->ptcaches); clmd->point_cache = NULL; + if (clmd->roots) + MEM_freeN(clmd->roots); + BKE_sim_debug_data_free(clmd->debug_data); } }