diff options
Diffstat (limited to 'source/blender/modifiers/intern/MOD_particlesystem.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_particlesystem.c | 167 |
1 files changed, 99 insertions, 68 deletions
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 80b6c16b382..784e44f5758 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -42,33 +42,34 @@ #include "BKE_cdderivedmesh.h" -#include "BKE_global.h" +#include "BKE_editmesh.h" +#include "BKE_mesh.h" +#include "BKE_library.h" #include "BKE_modifier.h" #include "BKE_particle.h" -#include "MOD_util.h" +#include "DEG_depsgraph_query.h" +#include "MOD_util.h" static void initData(ModifierData *md) { ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; psmd->psys = NULL; - psmd->dm_final = NULL; - psmd->dm_deformed = NULL; + psmd->mesh_final = NULL; + psmd->mesh_original = NULL; psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; } static void freeData(ModifierData *md) { ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; - if (psmd->dm_final) { - psmd->dm_final->needsFree = true; - psmd->dm_final->release(psmd->dm_final); - psmd->dm_final = NULL; - if (psmd->dm_deformed) { - psmd->dm_deformed->needsFree = true; - psmd->dm_deformed->release(psmd->dm_deformed); - psmd->dm_deformed = NULL; + if (psmd->mesh_final) { + BKE_id_free(NULL, psmd->mesh_final); + psmd->mesh_final = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } } psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; @@ -88,8 +89,8 @@ static void copyData(const ModifierData *md, ModifierData *target) modifier_copyData_generic(md, target); - tpsmd->dm_final = NULL; - tpsmd->dm_deformed = NULL; + tpsmd->mesh_final = NULL; + tpsmd->mesh_original = NULL; tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0; } @@ -101,47 +102,42 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md) /* saves the current emitter state for a particle system and calculates particles */ static void deformVerts( - ModifierData *md, Object *ob, - DerivedMesh *derivedData, + ModifierData *md, const ModifierEvalContext *ctx, + Mesh *mesh, float (*vertexCos)[3], - int UNUSED(numVerts), - ModifierApplyFlag flag) + int UNUSED(numVerts)) { - DerivedMesh *dm = derivedData; + Mesh *mesh_src = mesh; ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md; ParticleSystem *psys = NULL; - bool needsFree = false; /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */ - if (ob->particlesystem.first) + if (ctx->object->particlesystem.first) psys = psmd->psys; else return; - if (!psys_check_enabled(ob, psys, (flag & MOD_APPLY_RENDER) != 0)) + if (!psys_check_enabled(ctx->object, psys, (ctx->flag & MOD_APPLY_RENDER) != 0)) return; - if (dm == NULL) { - dm = get_dm(ob, NULL, NULL, vertexCos, false, true); - - if (!dm) + if (mesh_src == NULL) { + mesh_src = get_mesh(ctx->object, NULL, NULL, vertexCos, false, true); + if (mesh_src == NULL) { return; - - needsFree = true; + } } /* clear old dm */ - if (psmd->dm_final) { - psmd->dm_final->needsFree = true; - psmd->dm_final->release(psmd->dm_final); - if (psmd->dm_deformed) { - psmd->dm_deformed->needsFree = 1; - psmd->dm_deformed->release(psmd->dm_deformed); - psmd->dm_deformed = NULL; + if (psmd->mesh_final) { + BKE_id_free(NULL, psmd->mesh_final); + psmd->mesh_final = NULL; + if (psmd->mesh_original) { + BKE_id_free(NULL, psmd->mesh_original); + psmd->mesh_original = NULL; } } else if (psmd->flag & eParticleSystemFlag_file_loaded) { - /* in file read dm just wasn't saved in file so no need to reset everything */ + /* in file read mesh just wasn't saved in file so no need to reset everything */ psmd->flag &= ~eParticleSystemFlag_file_loaded; } else { @@ -149,48 +145,75 @@ static void deformVerts( psys->recalc |= PSYS_RECALC_RESET; } - /* make new dm */ - psmd->dm_final = CDDM_copy(dm); - CDDM_apply_vert_coords(psmd->dm_final, vertexCos); - CDDM_calc_normals(psmd->dm_final); - - if (needsFree) { - dm->needsFree = true; - dm->release(dm); - } + /* make new mesh */ + BKE_id_copy_ex(NULL, &mesh_src->id, (ID **)&psmd->mesh_final, + 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_apply_vert_coords(psmd->mesh_final, vertexCos); + BKE_mesh_calc_normals(psmd->mesh_final); + + BKE_mesh_tessface_ensure(psmd->mesh_final); + + if (!psmd->mesh_final->runtime.deformed_only) { + /* 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 { + mesh_original = mesh_src; + } - /* protect dm */ - psmd->dm_final->needsFree = false; + 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); + } - DM_ensure_tessface(psmd->dm_final); + BKE_mesh_tessface_ensure(psmd->mesh_original); + } - if (!psmd->dm_final->deformedOnly) { - /* 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 (ob->derivedDeform) { - psmd->dm_deformed = CDDM_copy(ob->derivedDeform); - } - else { /* Can happen in some cases, e.g. when rendering from Edit mode... */ - psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data); - } - DM_ensure_tessface(psmd->dm_deformed); + if (mesh_src != psmd->mesh_final && mesh_src != mesh) { + BKE_id_free(NULL, mesh_src); } /* report change in mesh structure */ - if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert || - psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge || - psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface) + if (psmd->mesh_final->totvert != psmd->totdmvert || + psmd->mesh_final->totedge != psmd->totdmedge || + psmd->mesh_final->totface != psmd->totdmface) { psys->recalc |= PSYS_RECALC_RESET; - psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final); - psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final); - psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final); + psmd->totdmvert = psmd->mesh_final->totvert; + psmd->totdmedge = psmd->mesh_final->totedge; + psmd->totdmface = psmd->mesh_final->totface; } - if (!(ob->transflag & OB_NO_PSYS_UPDATE)) { + if (!(ctx->object->transflag & OB_NO_PSYS_UPDATE)) { + struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); psmd->flag &= ~eParticleSystemFlag_psys_updated; - particle_system_update(G.main, md->scene, ob, psys, (flag & MOD_APPLY_RENDER) != 0); + particle_system_update(ctx->depsgraph, scene, ctx->object, psys, (ctx->flag & MOD_APPLY_RENDER) != 0); psmd->flag |= eParticleSystemFlag_psys_updated; } } @@ -225,17 +248,25 @@ ModifierTypeInfo modifierType_ParticleSystem = { eModifierTypeFlag_EnableInEditmode */, /* copyData */ copyData, + + /* deformVerts_DM */ NULL, + /* deformVertsEM_DM */ NULL, + /* deformMatrices_DM */ NULL, + /* deformMatricesEM_DM*/NULL, + /* applyModifier_DM */ NULL, + /* applyModifierEM_DM */NULL, + /* deformVerts */ deformVerts, - /* deformVertsEM */ NULL, /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, /* applyModifier */ NULL, /* applyModifierEM */ NULL, + /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ freeData, /* isDisabled */ NULL, - /* updateDepgraph */ NULL, /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* dependsOnNormals */ NULL, |