From 0666de06f3119ff1640f1eb66833cd4feb669209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20T=C3=B6nne?= Date: Thu, 15 Jan 2015 18:15:52 +0100 Subject: Fix for particle system copy: This has to make sure the ORIGSPACE data layer is available. Otherwise particle mapping to the new mesh cannot work with subdivided and constructively-modified meshes. --- source/blender/blenkernel/BKE_particle.h | 3 ++ source/blender/blenkernel/intern/particle.c | 36 +++++++++++++++ source/blender/editors/physics/particle_object.c | 54 ++++++++++++++-------- .../blender/modifiers/intern/MOD_particlesystem.c | 32 +------------ 4 files changed, 74 insertions(+), 51 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index bdf3a36370e..a5f12bb9a3c 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -39,6 +39,8 @@ #include "DNA_particle_types.h" #include "DNA_object_types.h" +#include "BKE_customdata.h" + struct ParticleSystemModifierData; struct ParticleSystem; struct ParticleKey; @@ -312,6 +314,7 @@ void psys_interpolate_mcol(const struct MCol *mcol, int quad, const float w[4], void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int time); +CustomDataMask psys_emitter_customdata_mask(struct ParticleSystem *psys); void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3], float ornor[3]); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 72cb69aa183..b146a40db63 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1646,6 +1646,42 @@ static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), /************************************************/ /* Particles on emitter */ /************************************************/ + +CustomDataMask psys_emitter_customdata_mask(ParticleSystem *psys) +{ + CustomDataMask dataMask = 0; + MTex *mtex; + int i; + + if (!psys->part) + return 0; + + for (i = 0; i < MAX_MTEX; i++) { + mtex = psys->part->mtex[i]; + if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV)) + dataMask |= CD_MASK_MTFACE; + } + + if (psys->part->tanfac != 0.0f) + dataMask |= CD_MASK_MTFACE; + + /* ask for vertexgroups if we need them */ + for (i = 0; i < PSYS_TOT_VG; i++) { + if (psys->vgroup[i]) { + dataMask |= CD_MASK_MDEFORMVERT; + break; + } + } + + /* particles only need this if they are after a non deform modifier, and + * the modifier stack will only create them in that case. */ + dataMask |= CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORIGINDEX; + + dataMask |= CD_MASK_ORCO; + + return dataMask; +} + void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3], float ornor[3]) diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index 33bf2b815f9..c7794d3092e 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -651,9 +651,10 @@ void PARTICLE_OT_disconnect_hair(wmOperatorType *ot) } static bool remap_hair_emitter(Scene *scene, Object *UNUSED(ob), ParticleSystem *psys, - Object *target_ob, DerivedMesh *target_dm, ParticleSystem *target_psys, PTCacheEdit *target_edit, + Object *target_ob, ParticleSystem *target_psys, PTCacheEdit *target_edit, bool from_world_space, bool to_world_space) { + ParticleSystemModifierData *target_psmd = psys_get_modifier(target_ob, target_psys); ParticleData *pa, *tpa; PTCacheEditPoint *edit_point; PTCacheEditKey *ekey; @@ -661,22 +662,28 @@ static bool remap_hair_emitter(Scene *scene, Object *UNUSED(ob), ParticleSystem MFace *mface = NULL, *mf; MEdge *medge = NULL, *me; MVert *mvert; - DerivedMesh *dm; + DerivedMesh *dm, *target_dm; int numverts; int i, k; - if (!psys->part || psys->part->type != PART_HAIR || !target_psys->part || target_psys->part->type != PART_HAIR) + if (!target_psmd->dm) + return false; + if (!psys->part || psys->part->type != PART_HAIR) + return false; + if (!target_psys->part || target_psys->part->type != PART_HAIR) return false; edit_point = target_edit ? target_edit->points : NULL; - if (target_dm->deformedOnly) { - /* we don't want to mess up target_dm when converting to global coordinates below */ - dm = target_dm; + if (target_psmd->dm->deformedOnly) { + /* we don't want to mess up target_psmd->dm when converting to global coordinates below */ + dm = target_psmd->dm; } else { + /* warning: this rebuilds target_psmd->dm! */ dm = mesh_get_derived_deform(scene, target_ob, CD_MASK_BAREMESH); } + target_dm = target_psmd->dm; /* don't modify the original vertices */ dm = CDDM_copy(dm); @@ -738,7 +745,7 @@ static bool remap_hair_emitter(Scene *scene, Object *UNUSED(ob), ParticleSystem tpa->foffset = 0.0f; tpa->num = nearest.index; - tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, dm, tpa->num, tpa->fuv, NULL); + tpa->num_dmcache = psys_particle_dm_face_lookup(target_ob, target_dm, tpa->num, tpa->fuv, NULL); } else { me = &medge[nearest.index]; @@ -812,19 +819,14 @@ static bool remap_hair_emitter(Scene *scene, Object *UNUSED(ob), ParticleSystem static bool connect_hair(Scene *scene, Object *ob, ParticleSystem *psys) { - ParticleSystemModifierData *psmd; const bool from_global = psys->flag & PSYS_GLOBAL_HAIR; const bool to_global = false; if (!psys) return false; - psmd = psys_get_modifier(ob, psys); - if (!psmd->dm) - return false; - psys->flag &= ~PSYS_GLOBAL_HAIR; - return remap_hair_emitter(scene, ob, psys, ob, psmd->dm, psys, psys->edit, from_global, to_global); + return remap_hair_emitter(scene, ob, psys, ob, psys, psys->edit, from_global, to_global); } static int connect_hair_exec(bContext *C, wmOperator *op) @@ -937,6 +939,7 @@ static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Objec ModifierData *md, *md_next; ParticleSystem *psys, *psys_from; DerivedMesh *final_dm; + CustomDataMask cdmask; int i; if (ob_to->type != OB_MESH) @@ -960,16 +963,18 @@ static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Objec } BKE_object_free_particlesystems(ob_to); + BKE_object_copy_particlesystems(ob_to, ob_from); + /* For remapping we need a valid DM. * Because the modifier is appended at the end it's safe to use * the final DM of the object without particles */ - if (ob_to->derivedFinal) - final_dm = ob_to->derivedFinal; - else - final_dm = mesh_get_derived_final(scene, ob_to, CD_MASK_BAREMESH); + cdmask = 0; + for (psys = ob_to->particlesystem.first; psys; psys = psys->next, ++i) { + cdmask |= psys_emitter_customdata_mask(psys); + } + final_dm = mesh_get_derived_final(scene, ob_to, cdmask); - BKE_object_copy_particlesystems(ob_to, ob_from); for (psys = ob_to->particlesystem.first, psys_from = ob_from->particlesystem.first, i = 0; psys; psys = psys->next, psys_from = psys_from->next, ++i) { @@ -988,14 +993,23 @@ static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Objec psmd->psys = psys; psmd->dm = CDDM_copy(final_dm); CDDM_calc_normals(psmd->dm); + DM_ensure_tessface(psmd->dm); if (psys_from->edit) copy_particle_edit(scene, ob_to, psys, psys_from); + } + + /* note: do this after creating DM copies for all the particle system modifiers, + * the remapping otherwise makes final_dm invalid! + */ + for (psys = ob_to->particlesystem.first, psys_from = ob_from->particlesystem.first, i = 0; + psys; + psys = psys->next, psys_from = psys_from->next, ++i) { - remap_hair_emitter(scene, ob_from, psys_from, ob_to, psmd->dm, psys, psys->edit, false, false); + remap_hair_emitter(scene, ob_from, psys_from, ob_to, psys, psys->edit, false, false); /* tag for recalc */ - psys->recalc |= PSYS_RECALC_RESET; +// psys->recalc |= PSYS_RECALC_RESET; } DAG_id_tag_update(&ob_to->id, OB_RECALC_DATA); diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index a41fbb03462..9860daeda4c 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -85,37 +85,7 @@ static void copyData(ModifierData *md, ModifierData *target) static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) { ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; - CustomDataMask dataMask = 0; - MTex *mtex; - int i; - - if (!psmd->psys->part) - return 0; - - for (i = 0; i < MAX_MTEX; i++) { - mtex = psmd->psys->part->mtex[i]; - if (mtex && mtex->mapto && (mtex->texco & TEXCO_UV)) - dataMask |= CD_MASK_MTFACE; - } - - if (psmd->psys->part->tanfac != 0.0f) - dataMask |= CD_MASK_MTFACE; - - /* ask for vertexgroups if we need them */ - for (i = 0; i < PSYS_TOT_VG; i++) { - if (psmd->psys->vgroup[i]) { - dataMask |= CD_MASK_MDEFORMVERT; - break; - } - } - - /* particles only need this if they are after a non deform modifier, and - * the modifier stack will only create them in that case. */ - dataMask |= CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORIGINDEX; - - dataMask |= CD_MASK_ORCO; - - return dataMask; + return psys_emitter_customdata_mask(psmd->psys); } /* saves the current emitter state for a particle system and calculates particles */ -- cgit v1.2.3