Changeset View
Changeset View
Standalone View
Standalone View
source/blender/modifiers/intern/MOD_particlesystem.c
| Show All 17 Lines | |||||
| */ | */ | ||||
| /** \file | /** \file | ||||
| * \ingroup modifiers | * \ingroup modifiers | ||||
| */ | */ | ||||
| #include <stddef.h> | #include <stddef.h> | ||||
| #include "MEM_guardedalloc.h" | |||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "DNA_material_types.h" | #include "DNA_material_types.h" | ||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| #include "BKE_editmesh.h" | #include "BKE_editmesh.h" | ||||
| #include "BKE_mesh.h" | #include "BKE_mesh.h" | ||||
| #include "BKE_library.h" | #include "BKE_library.h" | ||||
| #include "BKE_modifier.h" | #include "BKE_modifier.h" | ||||
| #include "BKE_particle.h" | #include "BKE_particle.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "MOD_util.h" | #include "MOD_util.h" | ||||
| static void initData(ModifierData *md) | static void initData(ModifierData *md) | ||||
| { | { | ||||
| ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; | ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; | ||||
| psmd->psys = NULL; | psmd->psys = 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->mesh_final) { | static void freeRuntimeData(void *runtime_data_v) | ||||
| BKE_id_free(NULL, psmd->mesh_final); | { | ||||
| psmd->mesh_final = NULL; | if (runtime_data_v == NULL) { | ||||
| if (psmd->mesh_original) { | return; | ||||
| BKE_id_free(NULL, psmd->mesh_original); | } | ||||
| psmd->mesh_original = NULL; | ParticleSystemModifierDataRuntime *runtime_data = runtime_data_v; | ||||
| if (runtime_data->mesh_final) { | |||||
| BKE_id_free(NULL, runtime_data->mesh_final); | |||||
| } | |||||
| if (runtime_data->mesh_original) { | |||||
| BKE_id_free(NULL, runtime_data->mesh_original); | |||||
| } | } | ||||
| MEM_freeN(runtime_data); | |||||
| } | } | ||||
| psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; | |||||
| static void freeData(ModifierData *md) | |||||
| { | |||||
| ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; | |||||
| freeRuntimeData(md->runtime); | |||||
| /* ED_object_modifier_remove may have freed this first before calling | /* ED_object_modifier_remove may have freed this first before calling | ||||
| * modifier_free (which calls this function) */ | * modifier_free (which calls this function) */ | ||||
| if (psmd->psys) { | if (psmd->psys) { | ||||
| psmd->psys->flag |= PSYS_DELETE; | psmd->psys->flag |= PSYS_DELETE; | ||||
| } | } | ||||
| } | } | ||||
| static void copyData(const ModifierData *md, ModifierData *target, const int flag) | |||||
| { | |||||
| #if 0 | |||||
| const ParticleSystemModifierData *psmd = (const ParticleSystemModifierData *)md; | |||||
| #endif | |||||
| ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *)target; | |||||
| modifier_copyData_generic(md, target, flag); | |||||
| tpsmd->mesh_final = NULL; | |||||
| tpsmd->mesh_original = NULL; | |||||
| tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0; | |||||
| } | |||||
| static void requiredDataMask(Object *UNUSED(ob), | static void requiredDataMask(Object *UNUSED(ob), | ||||
| ModifierData *md, | ModifierData *md, | ||||
| CustomData_MeshMasks *r_cddata_masks) | CustomData_MeshMasks *r_cddata_masks) | ||||
| { | { | ||||
| ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; | ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md; | ||||
| psys_emitter_customdata_mask(psmd->psys, r_cddata_masks); | psys_emitter_customdata_mask(psmd->psys, r_cddata_masks); | ||||
| } | } | ||||
| Show All 23 Lines | static void deformVerts(ModifierData *md, | ||||
| if (mesh_src == NULL) { | if (mesh_src == NULL) { | ||||
| mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, vertexCos, numVerts, false, true); | mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, NULL, vertexCos, numVerts, false, true); | ||||
| if (mesh_src == NULL) { | if (mesh_src == NULL) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| ParticleSystemModifierDataRuntime *runtime = BKE_particle_modifier_runtime_ensure(psmd); | |||||
| /* clear old dm */ | /* clear old dm */ | ||||
| bool had_mesh_final = (psmd->mesh_final != NULL); | bool had_mesh_final = (runtime->mesh_final != NULL); | ||||
| if (psmd->mesh_final) { | if (runtime->mesh_final) { | ||||
| BKE_id_free(NULL, psmd->mesh_final); | BKE_id_free(NULL, runtime->mesh_final); | ||||
| psmd->mesh_final = NULL; | runtime->mesh_final = NULL; | ||||
| if (psmd->mesh_original) { | if (runtime->mesh_original) { | ||||
| BKE_id_free(NULL, psmd->mesh_original); | BKE_id_free(NULL, runtime->mesh_original); | ||||
| psmd->mesh_original = NULL; | runtime->mesh_original = NULL; | ||||
| } | } | ||||
| } | } | ||||
| else if (psmd->flag & eParticleSystemFlag_file_loaded) { | else if (psmd->flag & eParticleSystemFlag_file_loaded) { | ||||
| /* in file read mesh 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; | psmd->flag &= ~eParticleSystemFlag_file_loaded; | ||||
| if (psys->particles == NULL) { | if (psys->particles == NULL) { | ||||
| psys->recalc |= ID_RECALC_PSYS_RESET; | psys->recalc |= ID_RECALC_PSYS_RESET; | ||||
| } | } | ||||
| /* TODO(sergey): This is not how particles were working prior to copy on | /* TODO(sergey): This is not how particles were working prior to copy on | ||||
| * write, but now evaluation is similar to case when one duplicates the | * write, but now evaluation is similar to case when one duplicates the | ||||
| * object. In that case particles were doing reset here. */ | * object. In that case particles were doing reset here. */ | ||||
| psys->recalc |= ID_RECALC_PSYS_RESET; | psys->recalc |= ID_RECALC_PSYS_RESET; | ||||
| } | } | ||||
| /* make new mesh */ | /* make new mesh */ | ||||
| psmd->mesh_final = BKE_mesh_copy_for_eval(mesh_src, false); | runtime->mesh_final = BKE_mesh_copy_for_eval(mesh_src, false); | ||||
| BKE_mesh_apply_vert_coords(psmd->mesh_final, vertexCos); | BKE_mesh_apply_vert_coords(runtime->mesh_final, vertexCos); | ||||
| BKE_mesh_calc_normals(psmd->mesh_final); | BKE_mesh_calc_normals(runtime->mesh_final); | ||||
| BKE_mesh_tessface_ensure(psmd->mesh_final); | BKE_mesh_tessface_ensure(runtime->mesh_final); | ||||
| if (!psmd->mesh_final->runtime.deformed_only) { | if (!runtime->mesh_final->runtime.deformed_only) { | ||||
| /* Get the original mesh from the object, this is what the particles | /* 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 | * are attached to so in case of non-deform modifiers we need to remap | ||||
| * them to the final mesh (typically subdivision surfaces). */ | * them to the final mesh (typically subdivision surfaces). */ | ||||
| Mesh *mesh_original = NULL; | Mesh *mesh_original = NULL; | ||||
| if (ctx->object->type == OB_MESH) { | if (ctx->object->type == OB_MESH) { | ||||
| BMEditMesh *em = BKE_editmesh_from_object(ctx->object); | BMEditMesh *em = BKE_editmesh_from_object(ctx->object); | ||||
| if (em) { | if (em) { | ||||
| /* In edit mode get directly from the edit mesh. */ | /* In edit mode get directly from the edit mesh. */ | ||||
| psmd->mesh_original = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL); | runtime->mesh_original = BKE_mesh_from_bmesh_for_eval_nomain(em->bm, NULL); | ||||
| } | } | ||||
| else { | else { | ||||
| /* Otherwise get regular mesh. */ | /* Otherwise get regular mesh. */ | ||||
| mesh_original = ctx->object->data; | mesh_original = ctx->object->data; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| mesh_original = mesh_src; | mesh_original = mesh_src; | ||||
| } | } | ||||
| if (mesh_original) { | if (mesh_original) { | ||||
| /* Make a persistent copy of the mesh. We don't actually need | /* Make a persistent copy of the mesh. We don't actually need | ||||
| * all this data, just some topology for remapping. Could be | * all this data, just some topology for remapping. Could be | ||||
| * optimized once. */ | * optimized once. */ | ||||
| psmd->mesh_original = BKE_mesh_copy_for_eval(mesh_original, false); | runtime->mesh_original = BKE_mesh_copy_for_eval(mesh_original, false); | ||||
| } | } | ||||
| BKE_mesh_tessface_ensure(psmd->mesh_original); | BKE_mesh_tessface_ensure(runtime->mesh_original); | ||||
| } | } | ||||
| if (mesh_src != psmd->mesh_final && mesh_src != mesh) { | if (mesh_src != runtime->mesh_final && mesh_src != mesh) { | ||||
| BKE_id_free(NULL, mesh_src); | BKE_id_free(NULL, mesh_src); | ||||
| } | } | ||||
| /* Report change in mesh structure. | /* Report change in mesh structure. | ||||
| * This is an unreliable check for the topology check, but allows some | * This is an unreliable check for the topology check, but allows some | ||||
| * handy configuration like emitting particles from inside particle | * handy configuration like emitting particles from inside particle | ||||
| * instance. */ | * instance. */ | ||||
| if (had_mesh_final && (psmd->mesh_final->totvert != psmd->totdmvert || | if (had_mesh_final && (runtime->mesh_final->totvert != runtime->totdmvert || | ||||
| psmd->mesh_final->totedge != psmd->totdmedge || | runtime->mesh_final->totedge != runtime->totdmedge || | ||||
| psmd->mesh_final->totface != psmd->totdmface)) { | runtime->mesh_final->totface != runtime->totdmface)) { | ||||
| psys->recalc |= ID_RECALC_PSYS_RESET; | psys->recalc |= ID_RECALC_PSYS_RESET; | ||||
| psmd->totdmvert = psmd->mesh_final->totvert; | runtime->totdmvert = runtime->mesh_final->totvert; | ||||
| psmd->totdmedge = psmd->mesh_final->totedge; | runtime->totdmedge = runtime->mesh_final->totedge; | ||||
| psmd->totdmface = psmd->mesh_final->totface; | runtime->totdmface = runtime->mesh_final->totface; | ||||
| } | } | ||||
| if (!(ctx->object->transflag & OB_NO_PSYS_UPDATE)) { | if (!(ctx->object->transflag & OB_NO_PSYS_UPDATE)) { | ||||
| struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); | struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); | ||||
| psmd->flag &= ~eParticleSystemFlag_psys_updated; | psmd->flag &= ~eParticleSystemFlag_psys_updated; | ||||
| particle_system_update( | particle_system_update( | ||||
| ctx->depsgraph, scene, ctx->object, psys, (ctx->flag & MOD_APPLY_RENDER) != 0); | ctx->depsgraph, scene, ctx->object, psys, (ctx->flag & MOD_APPLY_RENDER) != 0); | ||||
| psmd->flag |= eParticleSystemFlag_psys_updated; | psmd->flag |= eParticleSystemFlag_psys_updated; | ||||
| Show All 33 Lines | |||||
| #endif | #endif | ||||
| ModifierTypeInfo modifierType_ParticleSystem = { | ModifierTypeInfo modifierType_ParticleSystem = { | ||||
| /* name */ "ParticleSystem", | /* name */ "ParticleSystem", | ||||
| /* structName */ "ParticleSystemModifierData", | /* structName */ "ParticleSystemModifierData", | ||||
| /* structSize */ sizeof(ParticleSystemModifierData), | /* structSize */ sizeof(ParticleSystemModifierData), | ||||
| /* type */ eModifierTypeType_OnlyDeform, | /* type */ eModifierTypeType_OnlyDeform, | ||||
| /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | | /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | | ||||
| eModifierTypeFlag_UsesPointCache /* | | eModifierTypeFlag_UsesPointCache, /* | | ||||
| eModifierTypeFlag_SupportsEditmode | | eModifierTypeFlag_SupportsEditmode | | ||||
| eModifierTypeFlag_EnableInEditmode */ | eModifierTypeFlag_EnableInEditmode */ | ||||
| , | |||||
| /* copyData */ copyData, | /* copyData */ modifier_copyData_generic, | ||||
| /* deformVerts */ deformVerts, | /* deformVerts */ deformVerts, | ||||
| /* deformMatrices */ NULL, | /* deformMatrices */ NULL, | ||||
| /* deformVertsEM */ NULL, | /* deformVertsEM */ NULL, | ||||
| /* deformMatricesEM */ NULL, | /* deformMatricesEM */ NULL, | ||||
| /* applyModifier */ NULL, | /* applyModifier */ NULL, | ||||
| /* initData */ initData, | /* initData */ initData, | ||||
| /* requiredDataMask */ requiredDataMask, | /* requiredDataMask */ requiredDataMask, | ||||
| /* freeData */ freeData, | /* freeData */ freeData, | ||||
| /* isDisabled */ NULL, | /* isDisabled */ NULL, | ||||
| /* updateDepsgraph */ NULL, | /* updateDepsgraph */ NULL, | ||||
| /* dependsOnTime */ NULL, | /* dependsOnTime */ NULL, | ||||
| /* dependsOnNormals */ NULL, | /* dependsOnNormals */ NULL, | ||||
| /* foreachObjectLink */ NULL, | /* foreachObjectLink */ NULL, | ||||
| /* foreachIDLink */ NULL, | /* foreachIDLink */ NULL, | ||||
| /* foreachTexLink */ NULL, | /* foreachTexLink */ NULL, | ||||
| /* freeRuntimeData */ NULL, | /* freeRuntimeData */ freeRuntimeData, | ||||
| }; | }; | ||||