From c9f7a3b32a39aec2c7826f2ffa9939fd705e7237 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 25 May 2018 21:44:33 +0200 Subject: Fix T55207, fix T55208: hair not positioned correctly after subsurf. The problem was that the particle system modifier was reading ob->derivedDeform during modifier stack evaluation. Due to the mesh -> DM conversion this was no longer set leading to wrong results. In fact we don't really need the deformed mesh, just the original mesh topology for face/poly index remapping. So the solution is to use that instead. --- source/blender/blenkernel/BKE_particle.h | 4 +- source/blender/blenkernel/intern/object.c | 6 +-- source/blender/blenkernel/intern/particle.c | 14 +++--- .../blenkernel/intern/particle_distribute.c | 4 +- source/blender/blenkernel/intern/particle_system.c | 8 ++-- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/editors/physics/particle_edit.c | 8 ++-- source/blender/editors/physics/particle_object.c | 2 +- source/blender/makesdna/DNA_modifier_types.h | 2 +- .../blender/modifiers/intern/MOD_particlesystem.c | 51 +++++++++++++++------- 10 files changed, 61 insertions(+), 40 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index b6a87ae333e..4820f0173bf 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -439,8 +439,8 @@ void psys_particle_on_dm(struct Mesh *mesh_final, int from, int index, int index /* particle_system.c */ void distribute_particles(struct ParticleSimulationData *sim, int from); void initialize_particle(struct ParticleSimulationData *sim, struct ParticleData *pa); -void psys_calc_dmcache(struct Object *ob, struct Mesh *mesh_final, struct Mesh *mesh_deformed, struct ParticleSystem *psys); -int psys_particle_dm_face_lookup(struct Mesh *mesh_final, struct Mesh *mesh_deformed, int findex, const float fw[4], struct LinkNode **poly_nodes); +void psys_calc_dmcache(struct Object *ob, struct Mesh *mesh_final, struct Mesh *mesh_original, struct ParticleSystem *psys); +int psys_particle_dm_face_lookup(struct Mesh *mesh_final, struct Mesh *mesh_original, int findex, const float fw[4], struct LinkNode **poly_nodes); void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 39e190631ff..b8764f2c29d 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -379,9 +379,9 @@ void BKE_object_free_caches(Object *object) if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } psmd->flag |= eParticleSystemFlag_file_loaded; update_flag |= OB_RECALC_DATA; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 26c822f5fef..a42826a1f89 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1295,7 +1295,7 @@ static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4 * \return the DM tessface index. */ int psys_particle_dm_face_lookup( - Mesh *mesh_final, Mesh *mesh_deformed, + Mesh *mesh_final, Mesh *mesh_original, int findex_orig, const float fw[4], struct LinkNode **poly_nodes) { MFace *mtessface_final; @@ -1308,7 +1308,7 @@ int psys_particle_dm_face_lookup( const int *index_mp_to_orig = NULL; const int totface_final = mesh_final->totface; - const int totface_deformed = mesh_deformed ? mesh_deformed->totface : totface_final; + const int totface_deformed = mesh_original ? mesh_original->totface : totface_final; if (ELEM(0, totface_final, totface_deformed)) { return DMCACHE_NOTFOUND; @@ -1318,8 +1318,8 @@ int psys_particle_dm_face_lookup( index_mp_to_orig = CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX); BLI_assert(index_mf_to_mpoly); - if (mesh_deformed) { - index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_deformed->fdata, CD_ORIGINDEX); + if (mesh_original) { + index_mf_to_mpoly_deformed = CustomData_get_layer(&mesh_original->fdata, CD_ORIGINDEX); } else { BLI_assert(mesh_final->runtime.deformed_only); @@ -1329,8 +1329,8 @@ int psys_particle_dm_face_lookup( pindex_orig = index_mf_to_mpoly_deformed[findex_orig]; - if (mesh_deformed == NULL) { - mesh_deformed = mesh_final; + if (mesh_original == NULL) { + mesh_original = mesh_final; } index_mf_to_mpoly_deformed = NULL; @@ -1349,7 +1349,7 @@ int psys_particle_dm_face_lookup( return DMCACHE_NOTFOUND; } } - else if (findex_orig >= mesh_deformed->totface) { + else if (findex_orig >= mesh_original->totface) { return DMCACHE_NOTFOUND; /* index not in the original mesh */ } diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index e85a3f15022..846afd48064 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -847,7 +847,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti /* Simple children */ if (part->childtype != PART_CHILD_FACES) { BLI_srandom(31415926 + psys->seed + psys->child_seed); - distribute_simple_children(scene, ob, final_mesh, sim->psmd->mesh_deformed, psys, use_render_params); + distribute_simple_children(scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params); return 0; } } @@ -1233,7 +1233,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) BLI_task_pool_free(task_pool); - psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_deformed, sim->psys); + psys_calc_dmcache(sim->ob, final_mesh, sim->psmd->mesh_original, sim->psys); if (ctx.mesh != final_mesh) BKE_id_free(NULL, ctx.mesh); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 6c454cfa0b1..cba0721ab3f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -311,7 +311,7 @@ int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render /* Distribution */ /************************************************/ -void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, ParticleSystem *psys) +void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, ParticleSystem *psys) { /* use for building derived mesh mapping info: * @@ -350,7 +350,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, Partic origindex_poly= NULL; } else { - totelem = mesh_deformed->totface; + totelem = mesh_original->totface; origindex = CustomData_get_layer(&mesh_final->fdata, CD_ORIGINDEX); /* for face lookups we need the poly origindex too */ @@ -414,7 +414,7 @@ void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_deformed, Partic pa->num_dmcache = DMCACHE_NOTFOUND; } else { /* FROM_FACE/FROM_VOLUME */ - pa->num_dmcache = psys_particle_dm_face_lookup(mesh_final, mesh_deformed, pa->num, pa->fuv, nodearray); + pa->num_dmcache = psys_particle_dm_face_lookup(mesh_final, mesh_original, pa->num, pa->fuv, nodearray); } } } @@ -3242,7 +3242,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re if (psys->recalc & PSYS_RECALC_RESET) { /* need this for changing subsurf levels */ - psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_deformed, psys); + psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_original, psys); if (psys->clmd) cloth_free_modifier(psys->clmd); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index e74f82dfb6d..bc4b8daf0d3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5230,7 +5230,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; psmd->mesh_final = NULL; - psmd->mesh_deformed = NULL; + psmd->mesh_original = NULL; psmd->psys= newdataadr(fd, psmd->psys); psmd->flag &= ~eParticleSystemFlag_psys_updated; psmd->flag |= eParticleSystemFlag_file_loaded; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 5210ff76491..b8a5c138a57 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -2963,7 +2963,7 @@ static void PE_mirror_x( } else { newpa->num_dmcache = psys_particle_dm_face_lookup( - psmd->mesh_final, psmd->mesh_deformed, newpa->num, newpa->fuv, NULL); + psmd->mesh_final, psmd->mesh_original, newpa->num, newpa->fuv, NULL); } /* update edit key pointers */ @@ -3557,7 +3557,7 @@ static int brush_add(const bContext *C, PEData *data, short number) mesh = psmd->mesh_final; } else { - mesh = psmd->mesh_deformed; + mesh = psmd->mesh_original; } BLI_assert(mesh); @@ -3591,11 +3591,11 @@ static int brush_add(const bContext *C, PEData *data, short number) add_pars[n].num = add_pars[n].num_dmcache; add_pars[n].num_dmcache = DMCACHE_ISCHILD; } - else if (mesh == psmd->mesh_deformed) { + else if (mesh == psmd->mesh_original) { /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */ add_pars[n].num = add_pars[n].num_dmcache; add_pars[n].num_dmcache = psys_particle_dm_face_lookup( - psmd->mesh_final, psmd->mesh_deformed, + psmd->mesh_final, psmd->mesh_original, add_pars[n].num, add_pars[n].fuv, NULL); } else { diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index cb7c90a6c3d..55f518a2a8c 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -680,7 +680,7 @@ static bool remap_hair_emitter( mesh = target_psmd->mesh_final; } else { - mesh = target_psmd->mesh_deformed; + mesh = target_psmd->mesh_original; } target_mesh = target_psmd->mesh_final; if (mesh == NULL) { diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 4371172f236..93ab7a035bc 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -739,7 +739,7 @@ typedef struct ParticleSystemModifierData { struct ParticleSystem *psys; struct Mesh *mesh_final; /* Final Mesh - its topology may differ from orig mesh. */ - struct Mesh *mesh_deformed; /* Deformed-only Mesh - its topology is same as orig mesh one. */ + struct Mesh *mesh_original; /* Original mesh that particles are attached to. */ int totdmvert, totdmedge, totdmface; short flag, pad; } ParticleSystemModifierData; diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index c2493e6d8f3..72bdcc779ea 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -42,6 +42,7 @@ #include "BKE_cdderivedmesh.h" +#include "BKE_editmesh.h" #include "BKE_mesh.h" #include "BKE_library.h" #include "BKE_modifier.h" @@ -55,7 +56,7 @@ static void initData(ModifierData *md) ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; psmd->psys = NULL; psmd->mesh_final = NULL; - psmd->mesh_deformed = NULL; + psmd->mesh_original = NULL; psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; } static void freeData(ModifierData *md) @@ -65,9 +66,9 @@ static void freeData(ModifierData *md) if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } } psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; @@ -88,7 +89,7 @@ static void copyData(const ModifierData *md, ModifierData *target) modifier_copyData_generic(md, target); tpsmd->mesh_final = NULL; - tpsmd->mesh_deformed = NULL; + tpsmd->mesh_original = NULL; tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0; } @@ -129,9 +130,9 @@ static void deformVerts( if (psmd->mesh_final) { BKE_id_free(NULL, psmd->mesh_final); psmd->mesh_final = NULL; - if (psmd->mesh_deformed) { - BKE_id_free(NULL, psmd->mesh_deformed); - psmd->mesh_deformed = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } } else if (psmd->flag & eParticleSystemFlag_file_loaded) { @@ -156,20 +157,40 @@ static void deformVerts( BKE_mesh_tessface_ensure(psmd->mesh_final); if (!psmd->mesh_final->runtime.deformed_only) { - /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set. - * This is awfully weak though. :| */ - if (ctx->object->derivedDeform) { - DM_to_mesh(ctx->object->derivedDeform, psmd->mesh_deformed, ctx->object, CD_MASK_EVERYTHING, false); + /* Get the original mesh from the object, this is what the particles + * are attached to so in case of non-deform modifiers we need to remap + * them to the final mesh (typically subdivision surfaces). */ + Mesh *mesh_original = NULL; + + if (ctx->object->type == OB_MESH) { + BMEditMesh *edit_btmesh = BKE_editmesh_from_object(ctx->object); + + if (edit_btmesh) { + /* In edit mode get directly from the edit mesh. */ + psmd->mesh_original = BKE_bmesh_to_mesh_nomain(edit_btmesh->bm, &(struct BMeshToMeshParams){0}); + } + else { + /* Otherwise get regular mesh. */ + mesh_original = ctx->object->data; + } } - else { /* Can happen in some cases, e.g. when rendering from Edit mode... */ - BKE_id_copy_ex(NULL, &mesh_src->id, (ID **)&psmd->mesh_deformed, + else { + mesh_original = mesh_src; + } + + if (mesh_original) { + /* Make a persistent copy of the mesh. We don't actually need + * all this data, just some topology for remapping. Could be + * optimized once. */ + BKE_id_copy_ex(NULL, &mesh_original->id, (ID **)&psmd->mesh_original, LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW, false); } - BKE_mesh_tessface_ensure(psmd->mesh_deformed); + + BKE_mesh_tessface_ensure(psmd->mesh_original); } if (mesh_src != psmd->mesh_final && mesh_src != mesh) { -- cgit v1.2.3