Particle system: Move runtime data to runtime field
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 5 Jun 2019 10:39:40 +0000 (12:39 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Thu, 13 Jun 2019 09:34:01 +0000 (11:34 +0200)
Allows it to be preserved during copy-on-write update when on-geometry
related update is needed.

This is a required part for T63537, where we need to preserve the entire
evaluation data when object is tagged for only RECALC_COPY_ON_WRITE.

Reviewers: brecht

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D5023

15 files changed:
source/blender/blenkernel/BKE_particle.h
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_distribute.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenloader/intern/readfile.c
source/blender/draw/intern/draw_cache_impl_particles.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/particle_object.c
source/blender/editors/transform/transform_conversions.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/intern/rna_particle.c
source/blender/modifiers/intern/MOD_explode.c
source/blender/modifiers/intern/MOD_particleinstance.c
source/blender/modifiers/intern/MOD_particlesystem.c

index 164dbbb..ca3a560 100644 (file)
@@ -38,6 +38,7 @@ struct ParticleKey;
 struct ParticleSettings;
 struct ParticleSystem;
 struct ParticleSystemModifierData;
+struct ParticleSystemModifierDataRuntime;
 
 struct BVHTreeRay;
 struct BVHTreeRayHit;
@@ -608,6 +609,13 @@ float psys_get_current_display_percentage(struct ParticleSystem *psys,
 #define DMCACHE_NOTFOUND -1
 #define DMCACHE_ISCHILD -2
 
+/* **** Particle system modifier helpers.  **** */
+
+struct Mesh *BKE_particle_modifier_mesh_final_get(struct ParticleSystemModifierData *psmd);
+struct Mesh *BKE_particle_modifier_mesh_original_get(struct ParticleSystemModifierData *psmd);
+struct ParticleSystemModifierDataRuntime *BKE_particle_modifier_runtime_ensure(
+    struct ParticleSystemModifierData *psmd);
+
 /* **** Depsgraph evaluation **** */
 
 struct Depsgraph;
index 2a66edc..e74b2b0 100644 (file)
@@ -497,12 +497,13 @@ void BKE_object_free_caches(Object *object)
   for (md = object->modifiers.first; md != NULL; md = md->next) {
     if (md->type == eModifierType_ParticleSystem) {
       ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
-      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;
+      ParticleSystemModifierDataRuntime *psmd_runtime = BKE_particle_modifier_runtime_ensure(psmd);
+      if (psmd_runtime->mesh_final) {
+        BKE_id_free(NULL, psmd_runtime->mesh_final);
+        psmd_runtime->mesh_final = NULL;
+        if (psmd_runtime->mesh_original) {
+          BKE_id_free(NULL, psmd_runtime->mesh_original);
+          psmd_runtime->mesh_original = NULL;
         }
         psmd->flag |= eParticleSystemFlag_file_loaded;
         update_flag |= ID_RECALC_GEOMETRY;
index 13649ea..61ee568 100644 (file)
@@ -1889,7 +1889,8 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd,
                               float vtan[3],
                               float orco[3])
 {
-  if (psmd && psmd->mesh_final) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+  if (psmd && mesh_final) {
     if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) {
       if (vec) {
         copy_v3_v3(vec, fuv);
@@ -1902,7 +1903,7 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd,
     }
     /* we cant use the num_dmcache */
     psys_particle_on_dm(
-        psmd->mesh_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco);
+        mesh_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco);
   }
   else {
     psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco);
@@ -2253,13 +2254,15 @@ void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params
 
   tree = BLI_kdtree_3d_new(totparent);
 
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(sim->psmd);
+
   for (p = 0, cpa = sim->psys->child; p < totparent; p++, cpa++) {
     psys_particle_on_emitter(
         sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco);
 
     /* Check if particle doesn't exist because of texture influence.
      * Insert only existing particles into kdtree. */
-    get_cpa_texture(sim->psmd->mesh_final,
+    get_cpa_texture(mesh_final,
                     psys,
                     part,
                     psys->particles + cpa->pa[0],
@@ -2427,6 +2430,8 @@ static void psys_thread_create_path(ParticleTask *task,
     return;
   }
 
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(ctx->sim.psmd);
+
   if (ctx->between) {
     ParticleData *pa = psys->particles + cpa->pa[0];
     int w, needupdate;
@@ -2531,7 +2536,7 @@ static void psys_thread_create_path(ParticleTask *task,
       sub_v3_v3v3(off1[w], co, key[w]->co);
     }
 
-    psys_mat_hair_to_global(ob, ctx->sim.psmd->mesh_final, psys->part->from, pa, hairmat);
+    psys_mat_hair_to_global(ob, mesh_final, psys->part->from, pa, hairmat);
   }
   else {
     ParticleData *pa = psys->particles + cpa->parent;
@@ -2562,7 +2567,7 @@ static void psys_thread_create_path(ParticleTask *task,
                                                                            pa->num_dmcache;
 
     /* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
-    if (cpa_num > ctx->sim.psmd->mesh_final->totface) {
+    if (cpa_num > mesh_final->totface) {
       cpa_num = 0;
     }
     cpa_fuv = pa->fuv;
@@ -2579,7 +2584,7 @@ static void psys_thread_create_path(ParticleTask *task,
                              0,
                              orco);
 
-    psys_mat_hair_to_global(ob, ctx->sim.psmd->mesh_final, psys->part->from, pa, hairmat);
+    psys_mat_hair_to_global(ob, mesh_final, psys->part->from, pa, hairmat);
   }
 
   child_keys->segments = ctx->segments;
@@ -2925,19 +2930,21 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
     copy_v3_v3(col, &ma->r);
   }
 
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+
   if ((psys->flag & PSYS_GLOBAL_HAIR) == 0) {
     if ((psys->part->flag & PART_CHILD_EFFECT) == 0) {
-      vg_effector = psys_cache_vgroup(psmd->mesh_final, psys, PSYS_VG_EFFECTOR);
+      vg_effector = psys_cache_vgroup(mesh_final, psys, PSYS_VG_EFFECTOR);
     }
 
     if (!psys->totchild) {
-      vg_length = psys_cache_vgroup(psmd->mesh_final, psys, PSYS_VG_LENGTH);
+      vg_length = psys_cache_vgroup(mesh_final, psys, PSYS_VG_LENGTH);
     }
   }
 
   /* ensure we have tessfaces to be used for mapping */
   if (part->from != PART_FROM_VERT) {
-    BKE_mesh_tessface_ensure(psmd->mesh_final);
+    BKE_mesh_tessface_ensure(mesh_final);
   }
 
   /*---first main loop: create all actual particles' paths---*/
@@ -2947,7 +2954,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
       psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
       pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p));
       if (vg_length) {
-        pa_length *= psys_particle_value_from_verts(psmd->mesh_final, part->from, pa, vg_length);
+        pa_length *= psys_particle_value_from_verts(mesh_final, part->from, pa, vg_length);
       }
     }
 
@@ -2965,7 +2972,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
     init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
 
     /* hairmat is needed for for non-hair particle too so we get proper rotations */
-    psys_mat_hair_to_global(sim->ob, psmd->mesh_final, psys->part->from, pa, hairmat);
+    psys_mat_hair_to_global(sim->ob, mesh_final, psys->part->from, pa, hairmat);
     copy_v3_v3(rotmat[0], hairmat[2]);
     copy_v3_v3(rotmat[1], hairmat[1]);
     copy_v3_v3(rotmat[2], hairmat[0]);
@@ -3023,7 +3030,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
         float effector = 1.0f;
         if (vg_effector) {
           effector *= psys_particle_value_from_verts(
-              psmd->mesh_final, psys->part->from, pa, vg_effector);
+              mesh_final, psys->part->from, pa, vg_effector);
         }
 
         sub_v3_v3v3(vec, (cache[p] + 1)->co, cache[p]->co);
@@ -3158,7 +3165,8 @@ static void psys_cache_edit_paths_iter(void *__restrict iter_data_v,
   init_particle_interpolation(ob, psys, pa, &pind);
 
   if (psys) {
-    psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
+    Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+    psys_mat_hair_to_global(ob, mesh_final, psys->part->from, pa, hairmat);
     copy_v3_v3(rotmat[0], hairmat[2]);
     copy_v3_v3(rotmat[1], hairmat[1]);
     copy_v3_v3(rotmat[2], hairmat[0]);
@@ -4038,8 +4046,9 @@ void psys_get_texture(
             mul_m4_v3(mtex->object->imat, texvec);
           }
           break;
-        case TEXCO_UV:
-          if (get_particle_uv(sim->psmd->mesh_final,
+        case TEXCO_UV: {
+          Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(sim->psmd);
+          if (get_particle_uv(mesh_final,
                               pa,
                               0,
                               pa->fuv,
@@ -4050,6 +4059,7 @@ void psys_get_texture(
           }
           /* no break, failed to get uv's, so let's try orco's */
           ATTR_FALLTHROUGH;
+        }
         case TEXCO_ORCO:
           psys_particle_on_emitter(sim->psmd,
                                    sim->psys->part->from,
@@ -4323,7 +4333,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
       }
       else if (!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
         if ((pa->flag & PARS_REKEY) == 0) {
-          psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, part->from, pa, hairmat);
+          Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(sim->psmd);
+          psys_mat_hair_to_global(sim->ob, mesh_final, part->from, pa, hairmat);
           mul_m4_v3(hairmat, state->co);
           mul_mat3_m4_v3(hairmat, state->vel);
 
@@ -4405,7 +4416,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
                                  0,
                                  par_orco);
         if (part->type == PART_HAIR) {
-          psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
+          Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+          psys_mat_hair_to_global(sim->ob, mesh_final, psys->part->from, pa, hairmat);
         }
         else {
           unit_m4(hairmat);
@@ -4437,9 +4449,10 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
                                  0,
                                  par_orco);
         if (part->type == PART_HAIR) {
+          Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
           psys_particle_on_emitter(
               psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco);
-          psys_mat_hair_to_global(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
+          psys_mat_hair_to_global(sim->ob, mesh_final, psys->part->from, pa, hairmat);
         }
         else {
           copy_v3_v3(orco, cpa->fuv);
@@ -4450,7 +4463,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
       /* get different child parameters from textures & vgroups */
       memset(&ctx, 0, sizeof(ParticleThreadContext));
       ctx.sim = *sim;
-      ctx.mesh = psmd->mesh_final;
+      ctx.mesh = BKE_particle_modifier_mesh_final_get(psmd);
       ctx.ma = ma;
       /* TODO: assign vertex groups */
       get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
@@ -4715,14 +4728,16 @@ void psys_get_dupli_texture(ParticleSystem *psys,
   /* Grid distribution doesn't support UV or emit from vertex mode */
   bool is_grid = (part->distr == PART_DISTR_GRID && part->from != PART_FROM_VERT);
 
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+
   if (cpa) {
-    if ((part->childtype == PART_CHILD_FACES) && (psmd->mesh_final != NULL)) {
-      CustomData *mtf_data = &psmd->mesh_final->fdata;
+    if ((part->childtype == PART_CHILD_FACES) && (mesh_final != NULL)) {
+      CustomData *mtf_data = &mesh_final->fdata;
       const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
       mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx);
 
       if (mtface && !is_grid) {
-        mface = CustomData_get(&psmd->mesh_final->fdata, cpa->num, CD_MFACE);
+        mface = CustomData_get(&mesh_final->fdata, cpa->num, CD_MFACE);
         mtface += cpa->num;
         psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
       }
@@ -4745,8 +4760,8 @@ void psys_get_dupli_texture(ParticleSystem *psys,
     }
   }
 
-  if ((part->from == PART_FROM_FACE) && (psmd->mesh_final != NULL) && !is_grid) {
-    CustomData *mtf_data = &psmd->mesh_final->fdata;
+  if ((part->from == PART_FROM_FACE) && (mesh_final != NULL) && !is_grid) {
+    CustomData *mtf_data = &mesh_final->fdata;
     const int uv_idx = CustomData_get_render_layer(mtf_data, CD_MTFACE);
     mtface = CustomData_get_layer_n(mtf_data, CD_MTFACE, uv_idx);
 
@@ -4756,14 +4771,14 @@ void psys_get_dupli_texture(ParticleSystem *psys,
       num = pa->num;
     }
 
-    if (num >= psmd->mesh_final->totface) {
+    if (num >= mesh_final->totface) {
       /* happens when simplify is enabled
        * gives invalid coords but would crash otherwise */
       num = DMCACHE_NOTFOUND;
     }
 
     if (mtface && !ELEM(num, DMCACHE_NOTFOUND, DMCACHE_ISCHILD)) {
-      mface = CustomData_get(&psmd->mesh_final->fdata, num, CD_MFACE);
+      mface = CustomData_get(&mesh_final->fdata, num, CD_MFACE);
       mtface += num;
       psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
     }
@@ -4884,8 +4899,10 @@ void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, Par
     int p, h;
     float hairmat[4][4], imat[4][4];
 
+    Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(sim.psmd);
+
     for (p = 0; p < psys->totpart; p++, pa++) {
-      psys_mat_hair_to_global(sim.ob, sim.psmd->mesh_final, psys->part->from, pa, hairmat);
+      psys_mat_hair_to_global(sim.ob, mesh_final, psys->part->from, pa, hairmat);
       invert_m4_m4(imat, hairmat);
 
       hkey = pa->hair;
@@ -4920,3 +4937,40 @@ void BKE_particle_batch_cache_free(ParticleSystem *psys)
     BKE_particle_batch_cache_free_cb(psys);
   }
 }
+
+/* **** Particle system modifier helpers.  **** */
+
+Mesh *BKE_particle_modifier_mesh_final_get(ParticleSystemModifierData *psmd)
+{
+  if (psmd == NULL) {
+    return NULL;
+  }
+  ParticleSystemModifierDataRuntime *runtime = psmd->modifier.runtime;
+  if (runtime == NULL) {
+    return NULL;
+  }
+  return runtime->mesh_final;
+}
+
+Mesh *BKE_particle_modifier_mesh_original_get(ParticleSystemModifierData *psmd)
+{
+  if (psmd == NULL) {
+    return NULL;
+  }
+  ParticleSystemModifierDataRuntime *runtime = psmd->modifier.runtime;
+  if (runtime == NULL) {
+    return NULL;
+  }
+  return runtime->mesh_original;
+}
+
+ParticleSystemModifierDataRuntime *BKE_particle_modifier_runtime_ensure(
+    ParticleSystemModifierData *psmd)
+{
+  BLI_assert(psmd != NULL);
+  if (psmd->modifier.runtime == NULL) {
+    psmd->modifier.runtime = MEM_callocN(sizeof(ParticleSystemModifierDataRuntime),
+                                         "psmd runtime");
+  }
+  return psmd->modifier.runtime;
+}
index 070c3c7..7bb2dae 100644 (file)
@@ -878,7 +878,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
                                                int from)
 {
   Scene *scene = sim->scene;
-  Mesh *final_mesh = sim->psmd->mesh_final;
+  Mesh *final_mesh = BKE_particle_modifier_mesh_final_get(sim->psmd);
   Object *ob = sim->ob;
   ParticleSystem *psys = sim->psys;
   ParticleData *pa = 0, *tpars = 0;
@@ -926,8 +926,8 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx,
   if (from == PART_FROM_CHILD) {
     /* Simple children */
     if (part->childtype != PART_CHILD_FACES) {
-      distribute_simple_children(
-          scene, ob, final_mesh, sim->psmd->mesh_original, psys, use_render_params);
+      Mesh *mesh_original = BKE_particle_modifier_mesh_original_get(sim->psmd);
+      distribute_simple_children(scene, ob, final_mesh, mesh_original, psys, use_render_params);
       return 0;
     }
   }
@@ -1318,7 +1318,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
   TaskPool *task_pool;
   ParticleThreadContext ctx;
   ParticleTask *tasks;
-  Mesh *final_mesh = sim->psmd->mesh_final;
+  Mesh *final_mesh = BKE_particle_modifier_mesh_final_get(sim->psmd);
   int i, totpart, numtasks;
 
   /* create a task pool for distribution tasks */
@@ -1346,7 +1346,8 @@ 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_original, sim->psys);
+  Mesh *mesh_original = BKE_particle_modifier_mesh_original_get(sim->psmd);
+  psys_calc_dmcache(sim->ob, final_mesh, mesh_original, sim->psys);
 
   if (ctx.mesh != final_mesh) {
     BKE_id_free(NULL, ctx.mesh);
@@ -1371,7 +1372,8 @@ void distribute_particles(ParticleSimulationData *sim, int from)
   int distr_error = 0;
 
   if (psmd) {
-    if (psmd->mesh_final) {
+    Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+    if (mesh_final) {
       distribute_particles_on_dm(sim, from);
     }
     else {
index 27722aa..1b0655c 100644 (file)
@@ -467,7 +467,7 @@ void psys_thread_context_init(ParticleThreadContext *ctx, ParticleSimulationData
 {
   memset(ctx, 0, sizeof(ParticleThreadContext));
   ctx->sim = *sim;
-  ctx->mesh = ctx->sim.psmd->mesh_final;
+  ctx->mesh = BKE_particle_modifier_mesh_final_get(ctx->sim.psmd);
   ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
 }
 
@@ -3348,6 +3348,7 @@ static void hair_create_input_mesh(ParticleSimulationData *sim,
 
   /* make vgroup for pin roots etc.. */
   hair_index = 1;
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(sim->psmd);
   LOOP_PARTICLES
   {
     if (!(pa->flag & PARS_UNEXIST)) {
@@ -3358,7 +3359,7 @@ static void hair_create_input_mesh(ParticleSimulationData *sim,
       pa->hair_index = hair_index;
       use_hair = psys_hair_use_simulation(pa, max_length);
 
-      psys_mat_hair_to_object(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
+      psys_mat_hair_to_object(sim->ob, mesh_final, psys->part->from, pa, hairmat);
       mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
       normalize_m4(root_mat);
 
@@ -3524,7 +3525,9 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re
 
   if (psys->recalc & ID_RECALC_PSYS_RESET) {
     /* need this for changing subsurf levels */
-    psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_original, psys);
+    Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(sim->psmd);
+    Mesh *mesh_original = BKE_particle_modifier_mesh_original_get(sim->psmd);
+    psys_calc_dmcache(sim->ob, mesh_final, mesh_original, psys);
 
     if (psys->clmd) {
       cloth_free_modifier(psys->clmd);
@@ -3576,7 +3579,8 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra))
 
     if (pa->totkey) {
       sub_v3_v3(key->co, root->co);
-      psys_vec_rot_to_face(sim->psmd->mesh_final, pa, key->co);
+      Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(sim->psmd);
+      psys_vec_rot_to_face(mesh_final, pa, key->co);
     }
 
     key->time = pa->state.time;
@@ -4610,12 +4614,13 @@ void particle_system_update(struct Depsgraph *depsgraph,
     }
   }
 
-  if (!sim.psmd->mesh_final) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(sim.psmd);
+  if (!mesh_final) {
     return;
   }
 
   if (part->from != PART_FROM_VERT) {
-    BKE_mesh_tessface_ensure(sim.psmd->mesh_final);
+    BKE_mesh_tessface_ensure(mesh_final);
   }
 
   /* to verify if we need to restore object afterwards */
index ec61690..5c2618f 100644 (file)
@@ -5663,8 +5663,6 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb)
     else if (md->type == eModifierType_ParticleSystem) {
       ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
 
-      psmd->mesh_final = NULL;
-      psmd->mesh_original = NULL;
       psmd->psys = newdataadr(fd, psmd->psys);
       psmd->flag &= ~eParticleSystemFlag_psys_updated;
       psmd->flag |= eParticleSystemFlag_file_loaded;
index 5b19164..2c66215 100644 (file)
@@ -301,14 +301,15 @@ static void particle_calculate_parent_uvs(ParticleSystem *psys,
     return;
   }
   ParticleData *particle = &psys->particles[parent_index];
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
   int num = particle->num_dmcache;
   if (num == DMCACHE_NOTFOUND || num == DMCACHE_ISCHILD) {
-    if (particle->num < psmd->mesh_final->totface) {
+    if (particle->num < mesh_final->totface) {
       num = particle->num;
     }
   }
   if (num != DMCACHE_NOTFOUND && num != DMCACHE_ISCHILD) {
-    MFace *mface = &psmd->mesh_final->mface[num];
+    MFace *mface = &mesh_final->mface[num];
     for (int j = 0; j < num_uv_layers; j++) {
       psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, r_uv[j]);
     }
@@ -330,14 +331,15 @@ static void particle_calculate_parent_mcol(ParticleSystem *psys,
     return;
   }
   ParticleData *particle = &psys->particles[parent_index];
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
   int num = particle->num_dmcache;
   if (num == DMCACHE_NOTFOUND || num == DMCACHE_ISCHILD) {
-    if (particle->num < psmd->mesh_final->totface) {
+    if (particle->num < mesh_final->totface) {
       num = particle->num;
     }
   }
   if (num != DMCACHE_NOTFOUND && num != DMCACHE_ISCHILD) {
-    MFace *mface = &psmd->mesh_final->mface[num];
+    MFace *mface = &mesh_final->mface[num];
     for (int j = 0; j < num_uv_layers; j++) {
       psys_interpolate_mcol(mcols[j] + num, mface->v4, particle->fuv, &r_mcol[j]);
     }
@@ -361,8 +363,9 @@ static void particle_interpolate_children_uvs(ParticleSystem *psys,
   }
   ChildParticle *particle = &psys->child[child_index];
   int num = particle->num;
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
   if (num != DMCACHE_NOTFOUND) {
-    MFace *mface = &psmd->mesh_final->mface[num];
+    MFace *mface = &mesh_final->mface[num];
     for (int j = 0; j < num_uv_layers; j++) {
       psys_interpolate_uvs(mtfaces[j] + num, mface->v4, particle->fuv, r_uv[j]);
     }
@@ -384,9 +387,10 @@ static void particle_interpolate_children_mcol(ParticleSystem *psys,
     return;
   }
   ChildParticle *particle = &psys->child[child_index];
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
   int num = particle->num;
   if (num != DMCACHE_NOTFOUND) {
-    MFace *mface = &psmd->mesh_final->mface[num];
+    MFace *mface = &mesh_final->mface[num];
     for (int j = 0; j < num_col_layers; j++) {
       psys_interpolate_mcol(mcols[j] + num, mface->v4, particle->fuv, &r_mcol[j]);
     }
@@ -838,15 +842,16 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
   int active_col = 0;
 
   ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
 
-  if (psmd != NULL && psmd->mesh_final != NULL) {
-    if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) {
-      cache->num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
-      active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
+  if (psmd != NULL && mesh_final != NULL) {
+    if (CustomData_has_layer(&mesh_final->ldata, CD_MLOOPUV)) {
+      cache->num_uv_layers = CustomData_number_of_layers(&mesh_final->ldata, CD_MLOOPUV);
+      active_uv = CustomData_get_active_layer(&mesh_final->ldata, CD_MLOOPUV);
     }
-    if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) {
-      cache->num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL);
-      active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
+    if (CustomData_has_layer(&mesh_final->ldata, CD_MLOOPCOL)) {
+      cache->num_col_layers = CustomData_number_of_layers(&mesh_final->ldata, CD_MLOOPCOL);
+      active_col = CustomData_get_active_layer(&mesh_final->ldata, CD_MLOOPCOL);
     }
   }
 
@@ -890,7 +895,7 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
     GPU_vertbuf_data_alloc(cache->proc_uv_buf[i], cache->strands_len);
     GPU_vertbuf_attr_get_raw_data(cache->proc_uv_buf[i], uv_id, &uv_step[i]);
 
-    const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
+    const char *name = CustomData_get_layer_name(&mesh_final->ldata, CD_MLOOPUV, i);
     uint hash = BLI_ghashutil_strhash_p(name);
     int n = 0;
     BLI_snprintf(cache->uv_layer_names[i][n++], MAX_LAYER_NAME_LEN, "u%u", hash);
@@ -906,13 +911,13 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
     GPU_vertbuf_data_alloc(cache->proc_col_buf[i], cache->strands_len);
     GPU_vertbuf_attr_get_raw_data(cache->proc_col_buf[i], col_id, &col_step[i]);
 
-    const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPCOL, i);
+    const char *name = CustomData_get_layer_name(&mesh_final->ldata, CD_MLOOPCOL, i);
     uint hash = BLI_ghashutil_strhash_p(name);
     int n = 0;
     BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "c%u", hash);
 
     /* We only do vcols auto name that are not overridden by uvs */
-    if (CustomData_get_named_layer_index(&psmd->mesh_final->ldata, CD_MLOOPUV, name) == -1) {
+    if (CustomData_get_named_layer_index(&mesh_final->ldata, CD_MLOOPUV, name) == -1) {
       BLI_snprintf(cache->col_layer_names[i][n++], MAX_LAYER_NAME_LEN, "a%u", hash);
     }
 
@@ -922,15 +927,15 @@ static void particle_batch_cache_ensure_procedural_strand_data(PTCacheEdit *edit
   }
 
   if (cache->num_uv_layers || cache->num_col_layers) {
-    BKE_mesh_tessface_ensure(psmd->mesh_final);
+    BKE_mesh_tessface_ensure(mesh_final);
     if (cache->num_uv_layers) {
       for (int j = 0; j < cache->num_uv_layers; j++) {
-        mtfaces[j] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, j);
+        mtfaces[j] = (MTFace *)CustomData_get_layer_n(&mesh_final->fdata, CD_MTFACE, j);
       }
     }
     if (cache->num_col_layers) {
       for (int j = 0; j < cache->num_col_layers; j++) {
-        mcols[j] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, j);
+        mcols[j] = (MCol *)CustomData_get_layer_n(&mesh_final->fdata, CD_MCOL, j);
       }
     }
   }
@@ -1143,14 +1148,16 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
   float(**parent_uvs)[2] = NULL;
   MCol **parent_mcol = NULL;
 
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+
   if (psmd != NULL) {
-    if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPUV)) {
-      num_uv_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPUV);
-      active_uv = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPUV);
+    if (CustomData_has_layer(&mesh_final->ldata, CD_MLOOPUV)) {
+      num_uv_layers = CustomData_number_of_layers(&mesh_final->ldata, CD_MLOOPUV);
+      active_uv = CustomData_get_active_layer(&mesh_final->ldata, CD_MLOOPUV);
     }
-    if (CustomData_has_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL)) {
-      num_col_layers = CustomData_number_of_layers(&psmd->mesh_final->ldata, CD_MLOOPCOL);
-      active_col = CustomData_get_active_layer(&psmd->mesh_final->ldata, CD_MLOOPCOL);
+    if (CustomData_has_layer(&mesh_final->ldata, CD_MLOOPCOL)) {
+      num_col_layers = CustomData_number_of_layers(&mesh_final->ldata, CD_MLOOPCOL);
+      active_col = CustomData_get_active_layer(&mesh_final->ldata, CD_MLOOPCOL);
     }
   }
 
@@ -1166,7 +1173,7 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
     col_id = MEM_mallocN(sizeof(*col_id) * num_col_layers, "Col attr format");
 
     for (int i = 0; i < num_uv_layers; i++) {
-      const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
+      const char *name = CustomData_get_layer_name(&mesh_final->ldata, CD_MLOOPUV, i);
       char uuid[32];
 
       BLI_snprintf(uuid, sizeof(uuid), "u%u", BLI_ghashutil_strhash_p(name));
@@ -1178,7 +1185,7 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
     }
 
     for (int i = 0; i < num_uv_layers; i++) {
-      const char *name = CustomData_get_layer_name(&psmd->mesh_final->ldata, CD_MLOOPUV, i);
+      const char *name = CustomData_get_layer_name(&mesh_final->ldata, CD_MLOOPUV, i);
       char uuid[32];
 
       BLI_snprintf(uuid, sizeof(uuid), "c%u", BLI_ghashutil_strhash_p(name));
@@ -1197,17 +1204,17 @@ static void particle_batch_cache_ensure_pos_and_seg(PTCacheEdit *edit,
   GPU_indexbuf_init_ex(&elb, GPU_PRIM_LINE_STRIP, hair_cache->elems_len, hair_cache->point_len);
 
   if (num_uv_layers || num_col_layers) {
-    BKE_mesh_tessface_ensure(psmd->mesh_final);
+    BKE_mesh_tessface_ensure(mesh_final);
     if (num_uv_layers) {
       mtfaces = MEM_mallocN(sizeof(*mtfaces) * num_uv_layers, "Faces UV layers");
       for (int i = 0; i < num_uv_layers; i++) {
-        mtfaces[i] = (MTFace *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MTFACE, i);
+        mtfaces[i] = (MTFace *)CustomData_get_layer_n(&mesh_final->fdata, CD_MTFACE, i);
       }
     }
     if (num_col_layers) {
       mcols = MEM_mallocN(sizeof(*mcols) * num_col_layers, "Color layers");
       for (int i = 0; i < num_col_layers; i++) {
-        mcols[i] = (MCol *)CustomData_get_layer_n(&psmd->mesh_final->fdata, CD_MCOL, i);
+        mcols[i] = (MCol *)CustomData_get_layer_n(&mesh_final->fdata, CD_MCOL, i);
       }
     }
   }
index dc63486..7506ad3 100644 (file)
@@ -778,6 +778,7 @@ static void foreach_mouse_hit_key_iter(void *__restrict iter_data_v,
   }
   ParticleSystem *psys = edit->psys;
   ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
   ParticleEditSettings *pset = PE_settings(data->scene);
   const int selected = iter_data->selected;
   float mat[4][4], imat[4][4];
@@ -793,7 +794,7 @@ static void foreach_mouse_hit_key_iter(void *__restrict iter_data_v,
         if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
           if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
             psys_mat_hair_to_global(
-                data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
+                data->ob, mesh_final, psys->part->from, psys->particles + iter, mat);
             invert_m4_m4(imat, mat);
           }
           iter_data->func(data, mat, imat, iter, point->totkey - 1, key, mouse_distance);
@@ -812,7 +813,7 @@ static void foreach_mouse_hit_key_iter(void *__restrict iter_data_v,
         if (key_inside_circle(data, data->rad, KEY_WCO, &mouse_distance)) {
           if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
             psys_mat_hair_to_global(
-                data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
+                data->ob, mesh_final, psys->part->from, psys->particles + iter, mat);
             invert_m4_m4(imat, mat);
           }
           iter_data->func(data, mat, imat, iter, k, key, mouse_distance);
@@ -927,7 +928,9 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
   psmd_eval = edit->psmd_eval;
   totpart = psys->totpart;
 
-  if (!psmd_eval->mesh_final) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+
+  if (!mesh_final) {
     return;
   }
 
@@ -937,7 +940,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
   LOOP_PARTICLES
   {
     key = pa->hair;
-    psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat);
+    psys_mat_hair_to_orco(ob, mesh_final, psys->part->from, pa, mat);
     copy_v3_v3(co, key->co);
     mul_m4_v3(mat, co);
     BLI_kdtree_3d_insert(tree, p, co);
@@ -953,7 +956,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
   LOOP_PARTICLES
   {
     key = pa->hair;
-    psys_mat_hair_to_orco(ob, psmd_eval->mesh_final, psys->part->from, pa, mat);
+    psys_mat_hair_to_orco(ob, mesh_final, psys->part->from, pa, mat);
     copy_v3_v3(co, key->co);
     mul_m4_v3(mat, co);
     co[0] = -co[0];
@@ -1084,8 +1087,9 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
 
   edit = psys->edit;
   psmd_eval = edit->psmd_eval;
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
 
-  if (!psmd_eval->mesh_final) {
+  if (!mesh_final) {
     return;
   }
 
@@ -1102,7 +1106,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
   LOOP_POINTS
   {
     if (point->flag & PEP_EDIT_RECALC) {
-      PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
+      PE_mirror_particle(ob, mesh_final, psys, psys->particles + p, NULL);
 
       if (edit->mirror_cache[p] != -1) {
         edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
@@ -1152,8 +1156,8 @@ static void deflect_emitter_iter(void *__restrict iter_data_v,
   float *vec, *nor, dvec[3], dot, dist_1st = 0.0f;
   const float dist = iter_data->dist;
   const float emitterdist = iter_data->emitterdist;
-  psys_mat_hair_to_object(
-      object, psmd_eval->mesh_final, psys->part->from, psys->particles + iter, hairmat);
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+  psys_mat_hair_to_object(object, mesh_final, psys->part->from, psys->particles + iter, hairmat);
 
   LOOP_KEYS
   {
@@ -1217,7 +1221,8 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
 
   psys = edit->psys;
 
-  if (!edit->psmd_eval->mesh_final) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(edit->psmd_eval);
+  if (!mesh_final) {
     return;
   }
 
@@ -1382,7 +1387,7 @@ void recalc_lengths(PTCacheEdit *edit)
 void recalc_emitter_field(Depsgraph *UNUSED(depsgraph), Object *UNUSED(ob), ParticleSystem *psys)
 {
   PTCacheEdit *edit = psys->edit;
-  Mesh *mesh = edit->psmd_eval->mesh_final;
+  Mesh *mesh = BKE_particle_modifier_mesh_final_get(edit->psmd_eval);
   float *vec, *nor;
   int i, totface /*, totvert*/;
 
@@ -1489,15 +1494,16 @@ void update_world_cos(Depsgraph *UNUSED(depsgraph), Object *ob, PTCacheEdit *edi
   KEY_K;
   float hairmat[4][4];
 
-  if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+
+  if (psys == 0 || psys->edit == 0 || mesh_final == NULL) {
     return;
   }
 
   LOOP_POINTS
   {
     if (!(psys->flag & PSYS_GLOBAL_HAIR)) {
-      psys_mat_hair_to_global(
-          ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, hairmat);
+      psys_mat_hair_to_global(ob, mesh_final, psys->part->from, psys->particles + p, hairmat);
     }
 
     LOOP_KEYS
@@ -2269,11 +2275,12 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const
     data.is_changed |= PE_deselect_all_visible_ex(edit);
   }
 
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+
   LOOP_VISIBLE_POINTS
   {
     if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
-      psys_mat_hair_to_global(
-          ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
+      psys_mat_hair_to_global(ob, mesh_final, psys->part->from, psys->particles + p, mat);
     }
 
     if (pset->selectmode == SCE_SELECT_POINT) {
@@ -2739,10 +2746,11 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
   if (mirror) {
     /* mirror tags */
     psmd_eval = edit->psmd_eval;
+    Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
 
     LOOP_TAGGED_POINTS
     {
-      PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
+      PE_mirror_particle(ob, mesh_final, psys, psys->particles + p, NULL);
     }
   }
 
@@ -2831,12 +2839,13 @@ static void remove_tagged_keys(Depsgraph *depsgraph, Object *ob, ParticleSystem
     ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
     ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *)modifier_get_evaluated(
         depsgraph, ob, &psmd->modifier);
+    Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
 
     LOOP_POINTS
     {
       LOOP_TAGGED_KEYS
       {
-        PE_mirror_particle(ob, psmd_eval->mesh_final, psys, psys->particles + p, NULL);
+        PE_mirror_particle(ob, mesh_final, psys, psys->particles + p, NULL);
         break;
       }
     }
@@ -3063,6 +3072,8 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
   psmd_eval = edit->psmd_eval;
   totremoved = 0;
 
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+
   do {
     removed = 0;
 
@@ -3071,8 +3082,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
     /* insert particles into kd tree */
     LOOP_SELECTED_POINTS
     {
-      psys_mat_hair_to_object(
-          ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
+      psys_mat_hair_to_object(ob, mesh_final, psys->part->from, psys->particles + p, mat);
       copy_v3_v3(co, point->keys->co);
       mul_m4_v3(mat, co);
       BLI_kdtree_3d_insert(tree, p, co);
@@ -3083,8 +3093,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
     /* tag particles to be removed */
     LOOP_SELECTED_POINTS
     {
-      psys_mat_hair_to_object(
-          ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
+      psys_mat_hair_to_object(ob, mesh_final, psys->part->from, psys->particles + p, mat);
       copy_v3_v3(co, point->keys->co);
       mul_m4_v3(mat, co);
 
@@ -3347,20 +3356,22 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
   }
 
   psmd_eval = edit->psmd_eval;
-  if (!psmd_eval->mesh_final) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+  Mesh *mesh_original = BKE_particle_modifier_mesh_original_get(psmd_eval);
+
+  if (!mesh_final) {
     return;
   }
 
   const bool use_dm_final_indices = (psys->part->use_modifier_stack &&
-                                     !psmd_eval->mesh_final->runtime.deformed_only);
+                                     !mesh_final->runtime.deformed_only);
 
   /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
   BKE_mesh_tessface_ensure(me);
 
   /* NOTE: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh.
    * Avoids an (impossible) mesh -> orig -> mesh tessface indices conversion. */
-  mirrorfaces = mesh_get_x_mirror_faces(
-      ob, NULL, use_dm_final_indices ? psmd_eval->mesh_final : NULL);
+  mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? mesh_final : NULL);
 
   if (!edit->mirror_cache) {
     PE_update_mirror_cache(ob, psys);
@@ -3376,7 +3387,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
       if (point_is_selected(point)) {
         if (edit->mirror_cache[p] != -1) {
           /* already has a mirror, don't need to duplicate */
-          PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, NULL);
+          PE_mirror_particle(ob, mesh_final, psys, pa, NULL);
           continue;
         }
         else {
@@ -3391,7 +3402,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
   }
 
   if (newtotpart != psys->totpart) {
-    MFace *mtessface = use_dm_final_indices ? psmd_eval->mesh_final->mface : me->mface;
+    MFace *mtessface = use_dm_final_indices ? mesh_final->mface : me->mface;
 
     /* allocate new arrays and copy existing */
     new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new");
@@ -3467,7 +3478,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
       }
       else {
         newpa->num_dmcache = psys_particle_dm_face_lookup(
-            psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL);
+            mesh_final, mesh_original, newpa->num, newpa->fuv, NULL);
       }
 
       /* update edit key pointers */
@@ -3478,7 +3489,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
       }
 
       /* map key positions as mirror over x axis */
-      PE_mirror_particle(ob, psmd_eval->mesh_final, psys, pa, newpa);
+      PE_mirror_particle(ob, mesh_final, psys, pa, newpa);
 
       newpa++;
       newpoint++;
@@ -4157,19 +4168,18 @@ static void brush_add_count_iter(void *__restrict iter_data_v,
                               0,
                               0,
                               0)) {
-    if (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only) {
+    Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+    Mesh *mesh_original = BKE_particle_modifier_mesh_original_get(psmd_eval);
+    if (psys->part->use_modifier_stack && !mesh_final->runtime.deformed_only) {
       add_pars[iter].num = add_pars[iter].num_dmcache;
       add_pars[iter].num_dmcache = DMCACHE_ISCHILD;
     }
-    else if (iter_data->mesh == psmd_eval->mesh_original) {
+    else if (iter_data->mesh == mesh_original) {
       /* Final DM is not same topology as orig mesh,
        * we have to map num_dmcache to real final dm. */
       add_pars[iter].num = add_pars[iter].num_dmcache;
-      add_pars[iter].num_dmcache = psys_particle_dm_face_lookup(psmd_eval->mesh_final,
-                                                                psmd_eval->mesh_original,
-                                                                add_pars[iter].num,
-                                                                add_pars[iter].fuv,
-                                                                NULL);
+      add_pars[iter].num_dmcache = psys_particle_dm_face_lookup(
+          mesh_final, mesh_original, add_pars[iter].num, add_pars[iter].fuv, NULL);
     }
     else {
       add_pars[iter].num = add_pars[iter].num_dmcache;
@@ -4227,11 +4237,12 @@ static int brush_add(const bContext *C, PEData *data, short number)
 
   timestep = psys_get_timestep(&sim);
 
-  if (psys->part->use_modifier_stack || psmd_eval->mesh_final->runtime.deformed_only) {
-    mesh = psmd_eval->mesh_final;
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+  if (psys->part->use_modifier_stack || mesh_final->runtime.deformed_only) {
+    mesh = mesh_final;
   }
   else {
-    mesh = psmd_eval->mesh_original;
+    mesh = BKE_particle_modifier_mesh_original_get(psmd_eval);
   }
   BLI_assert(mesh);
 
@@ -4315,7 +4326,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
       tree = BLI_kdtree_3d_new(psys->totpart);
 
       for (i = 0, pa = psys->particles; i < totpart; i++, pa++) {
-        psys_particle_on_dm(psmd_eval->mesh_final,
+        psys_particle_on_dm(mesh_final,
                             psys->part->from,
                             pa->num,
                             pa->num_dmcache,
@@ -4372,7 +4383,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
         int w, maxw;
         float maxd, totw = 0.0, weight[3];
 
-        psys_particle_on_dm(psmd_eval->mesh_final,
+        psys_particle_on_dm(mesh_final,
                             psys->part->from,
                             pa->num,
                             pa->num_dmcache,
@@ -4450,7 +4461,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
         }
       }
       for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) {
-        psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat);
+        psys_mat_hair_to_global(ob, mesh_final, psys->part->from, pa, hairmat);
         invert_m4_m4(imat, hairmat);
         mul_m4_v3(imat, hkey->co);
       }
@@ -4651,7 +4662,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
         }
         case PE_BRUSH_PUFF: {
           if (edit->psys) {
-            data.mesh = psmd_eval->mesh_final;
+            data.mesh = BKE_particle_modifier_mesh_final_get(psmd_eval);
             data.mval = mval;
             data.rad = pe_brush_size_get(scene, brush);
             data.select = selected;
@@ -4708,7 +4719,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
         }
         case PE_BRUSH_WEIGHT: {
           if (edit->psys) {
-            data.mesh = psmd_eval->mesh_final;
+            data.mesh = BKE_particle_modifier_mesh_final_get(psmd_eval);
             data.mval = mval;
             data.rad = pe_brush_size_get(scene, brush);
 
@@ -5082,8 +5093,8 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
   LOOP_VISIBLE_POINTS
   {
     if (psys) {
-      psys_mat_hair_to_global(
-          ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
+      Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+      psys_mat_hair_to_global(ob, mesh_final, psys->part->from, psys->particles + p, mat);
     }
 
     LOOP_SELECTED_KEYS
@@ -5124,7 +5135,8 @@ void PE_create_particle_edit(
   }
 
   /* no psmd->dm happens in case particle system modifier is not enabled */
-  if (!(psys && psmd && psmd_eval->mesh_final) && !cache) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+  if (!(psys && psmd && mesh_final) && !cache) {
     return;
   }
 
index b03ec56..d85bf72 100644 (file)
@@ -620,6 +620,7 @@ static void disconnect_hair(Depsgraph *depsgraph, Scene *scene, Object *ob, Part
 
   edit = psys->edit;
   point = edit ? edit->points : NULL;
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
 
   for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
     if (point) {
@@ -627,7 +628,7 @@ static void disconnect_hair(Depsgraph *depsgraph, Scene *scene, Object *ob, Part
       point++;
     }
 
-    psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, pa, hairmat);
+    psys_mat_hair_to_global(ob, mesh_final, psys->part->from, pa, hairmat);
 
     for (k = 0, key = pa->hair; k < pa->totkey; k++, key++) {
       mul_m4_v3(hairmat, key->co);
@@ -725,7 +726,8 @@ static bool remap_hair_emitter(Depsgraph *depsgraph,
   float from_ob_imat[4][4], to_ob_imat[4][4];
   float from_imat[4][4], to_imat[4][4];
 
-  if (!target_psmd->mesh_final) {
+  Mesh *target_mesh_final = BKE_particle_modifier_mesh_final_get(target_psmd);
+  if (!target_mesh_final) {
     return false;
   }
   if (!psys->part || psys->part->type != PART_HAIR) {
@@ -742,14 +744,14 @@ static bool remap_hair_emitter(Depsgraph *depsgraph,
   invert_m4_m4(from_imat, from_mat);
   invert_m4_m4(to_imat, to_mat);
 
-  if (target_psmd->mesh_final->runtime.deformed_only) {
+  if (target_mesh_final->runtime.deformed_only) {
     /* we don't want to mess up target_psmd->dm when converting to global coordinates below */
-    mesh = target_psmd->mesh_final;
+    mesh = target_mesh_final;
   }
   else {
-    mesh = target_psmd->mesh_original;
+    mesh = BKE_particle_modifier_mesh_original_get(target_psmd);
   }
-  target_mesh = target_psmd->mesh_final;
+  target_mesh = target_mesh_final;
   if (mesh == NULL) {
     return false;
   }
@@ -1155,10 +1157,13 @@ static bool copy_particle_systems_to_object(const bContext *C,
     modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
 
     psmd->psys = psys;
-    BKE_id_copy_ex(NULL, &final_mesh->id, (ID **)&psmd->mesh_final, LIB_ID_COPY_LOCALIZE);
 
-    BKE_mesh_calc_normals(psmd->mesh_final);
-    BKE_mesh_tessface_ensure(psmd->mesh_final);
+    /* TODO(sergey): This should probably be accessing evaluated psmd. */
+    ParticleSystemModifierDataRuntime *runtime = BKE_particle_modifier_runtime_ensure(psmd);
+    BKE_id_copy_ex(NULL, &final_mesh->id, (ID **)&runtime->mesh_final, LIB_ID_COPY_LOCALIZE);
+
+    BKE_mesh_calc_normals(runtime->mesh_final);
+    BKE_mesh_tessface_ensure(runtime->mesh_final);
 
     if (psys_from->edit) {
       copy_particle_edit(depsgraph, scene, ob_to, psys, psys_from);
index 2dad3ae..b90e890 100644 (file)
@@ -2414,8 +2414,8 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
 
       if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
         ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
-        psys_mat_hair_to_global(
-            ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
+        Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+        psys_mat_hair_to_global(ob, mesh_final, psys->part->from, psys->particles + i, mat);
       }
 
       for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
@@ -2506,8 +2506,8 @@ void flushTransParticles(TransInfo *t)
 
       if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
         ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
-        psys_mat_hair_to_global(
-            ob, psmd_eval->mesh_final, psys->part->from, psys->particles + i, mat);
+        Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd_eval);
+        psys_mat_hair_to_global(ob, mesh_final, psys->part->from, psys->particles + i, mat);
         invert_m4_m4(imat, mat);
 
         for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
index 6a524e0..37980fc 100644 (file)
@@ -882,17 +882,24 @@ enum {
   MOD_MDEF_SURFACE = 1,
 };
 
-typedef struct ParticleSystemModifierData {
-  ModifierData modifier;
-
-  struct ParticleSystem *psys;
+/* Is stored in ModifierData.runtime. */
+#
+#
+typedef struct ParticleSystemModifierDataRuntime {
   /** Final Mesh - its topology may differ from orig mesh. */
   struct Mesh *mesh_final;
   /** Original mesh that particles are attached to. */
   struct Mesh *mesh_original;
   int totdmvert, totdmedge, totdmface;
+} ParticleSystemModifierDataRuntime;
+
+typedef struct ParticleSystemModifierData {
+  ModifierData modifier;
+
+  struct ParticleSystem *psys;
+  void *_pad1;
   short flag;
-  char _pad[2];
+  char _pad[6];
 } ParticleSystemModifierData;
 
 typedef enum {
index c1822b3..8112231 100644 (file)
@@ -173,7 +173,8 @@ static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr,
   for (md = ob->modifiers.first; md; md = md->next) {
     if (md->type == eModifierType_ParticleSystem) {
       psmd = (ParticleSystemModifierData *)md;
-      if (psmd && psmd->mesh_final && psmd->psys) {
+      Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+      if (psmd && mesh_final && psmd->psys) {
         psys = psmd->psys;
         for (i = 0, pa = psys->particles; i < psys->totpart; i++, pa++) {
           /* hairkeys are stored sequentially in memory, so we can
@@ -208,7 +209,8 @@ static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *valu
     }
     else {
       float hairmat[4][4];
-      psys_mat_hair_to_object(ob, psmd->mesh_final, psmd->psys->part->from, pa, hairmat);
+      Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+      psys_mat_hair_to_object(ob, mesh_final, psmd->psys->part->from, pa, hairmat);
       copy_v3_v3(values, hkey->co);
       mul_m4_v3(hairmat, values);
     }
@@ -238,7 +240,8 @@ static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float
       float hairmat[4][4];
       float imat[4][4];
 
-      psys_mat_hair_to_object(ob, psmd->mesh_final, psmd->psys->part->from, pa, hairmat);
+      Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(psmd);
+      psys_mat_hair_to_object(ob, mesh_final, psmd->psys->part->from, pa, hairmat);
       invert_m4_m4(imat, hairmat);
       copy_v3_v3(hkey->co, values);
       mul_m4_v3(imat, hkey->co);
@@ -265,8 +268,8 @@ static void rna_ParticleHairKey_co_object(HairKey *hairkey,
     }
     else {
       float hairmat[4][4];
-      psys_mat_hair_to_object(
-          object, modifier->mesh_final, modifier->psys->part->from, particle, hairmat);
+      Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(modifier);
+      psys_mat_hair_to_object(object, mesh_final, modifier->psys->part->from, particle, hairmat);
       copy_v3_v3(n_co, hairkey->co);
       mul_m4_v3(hairmat, n_co);
     }
@@ -290,14 +293,15 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle,
   int num = particle->num_dmcache;
   int from = modifier->psys->part->from;
 
-  if (!CustomData_has_layer(&modifier->mesh_final->ldata, CD_MLOOPUV)) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(modifier);
+  if (!CustomData_has_layer(&mesh_final->ldata, CD_MLOOPUV)) {
     BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
     return;
   }
-  BKE_mesh_tessface_ensure(modifier->mesh_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+  BKE_mesh_tessface_ensure(mesh_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
 
   if (num == DMCACHE_NOTFOUND) {
-    if (particle->num < modifier->mesh_final->totface) {
+    if (particle->num < mesh_final->totface) {
       num = particle->num;
     }
   }
@@ -309,8 +313,8 @@ static void rna_Particle_uv_on_emitter(ParticleData *particle,
       MFace *mface;
       MTFace *mtface;
 
-      mface = modifier->mesh_final->mface;
-      mtface = modifier->mesh_final->mtface;
+      mface = mesh_final->mface;
+      mtface = mesh_final->mtface;
 
       if (mface && mtface) {
         mtface += num;
@@ -439,9 +443,10 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
   int totvert;
   int num = -1;
 
-  BKE_mesh_tessface_ensure(modifier->mesh_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
-  totface = modifier->mesh_final->totface;
-  totvert = modifier->mesh_final->totvert;
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(modifier);
+  BKE_mesh_tessface_ensure(mesh_final); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+  totface = mesh_final->totface;
+  totvert = mesh_final->totvert;
 
   /* 1. check that everything is ok & updated */
   if (!particlesystem || !totface) {
@@ -474,7 +479,7 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
     }
     else if (part->from == PART_FROM_VERT) {
       if (num != DMCACHE_NOTFOUND && num < totvert) {
-        MFace *mface = modifier->mesh_final->mface;
+        MFace *mface = mesh_final->mface;
 
         *r_fuv = &particle->fuv;
 
@@ -517,7 +522,7 @@ static int rna_ParticleSystem_tessfaceidx_on_emitter(ParticleSystem *particlesys
       }
       else if (part->from == PART_FROM_VERT) {
         if (num != DMCACHE_NOTFOUND && num < totvert) {
-          MFace *mface = modifier->mesh_final->mface;
+          MFace *mface = mesh_final->mface;
 
           *r_fuv = &parent->fuv;
 
@@ -545,12 +550,13 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem,
                                              int uv_no,
                                              float r_uv[2])
 {
-  if (modifier->mesh_final == NULL) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(modifier);
+  if (mesh_final == NULL) {
     BKE_report(reports, RPT_ERROR, "Object was not yet evaluated");
     zero_v2(r_uv);
     return;
   }
-  if (!CustomData_has_layer(&modifier->mesh_final->ldata, CD_MLOOPUV)) {
+  if (!CustomData_has_layer(&mesh_final->ldata, CD_MLOOPUV)) {
     BKE_report(reports, RPT_ERROR, "Mesh has no UV data");
     zero_v2(r_uv);
     return;
@@ -567,9 +573,8 @@ static void rna_ParticleSystem_uv_on_emitter(ParticleSystem *particlesystem,
       zero_v2(r_uv);
     }
     else {
-      MFace *mface = &modifier->mesh_final->mface[num];
-      MTFace *mtface = (MTFace *)CustomData_get_layer_n(
-          &modifier->mesh_final->fdata, CD_MTFACE, uv_no);
+      MFace *mface = &mesh_final->mface[num];
+      MTFace *mtface = (MTFace *)CustomData_get_layer_n(&mesh_final->fdata, CD_MTFACE, uv_no);
 
       psys_interpolate_uvs(&mtface[num], mface->v4, *fuv, r_uv);
     }
@@ -584,7 +589,8 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem,
                                                int vcol_no,
                                                float r_mcol[3])
 {
-  if (!CustomData_has_layer(&modifier->mesh_final->ldata, CD_MLOOPCOL)) {
+  Mesh *mesh_final = BKE_particle_modifier_mesh_final_get(modifier);
+  if (!CustomData_has_layer(&mesh_final->ldata, CD_MLOOPCOL)) {
     BKE_report(reports, RPT_ERROR, "Mesh has no VCol data");
     zero_v3(r_mcol);
     return;
@@ -601,8 +607,8 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem,
       zero_v3(r_mcol);
     }
     else {
-      MFace *mface = &modifier->mesh_final->mface[num];
-      MCol *mc = (MCol *)CustomData_get_layer_n(&modifier->mesh_final->fdata, CD_MCOL, vcol_no);
+      MFace *mface = &mesh_final->mface[num];
+      MCol *mc = (MCol *)CustomData_get_layer_n(&mesh_final->fdata, CD_MCOL, vcol_no);
       MCol mcol;
 
       psys_interpolate_mcol(&mc[num * 4], mface->v4, *fuv, &mcol);
index 4ed7878..9b1586f 100644 (file)
@@ -1125,7 +1125,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
     if (psys->part == NULL || psys->particles == NULL) {
       return mesh;
     }
-    if (psmd->mesh_final == NULL) {
+    if (BKE_particle_modifier_mesh_final_get(psmd) == NULL) {
       return mesh;
     }
 
index 7191337..651feb8 100644 (file)
@@ -415,7 +415,11 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
             ChildParticle *cpa = psys->child + (p - psys->totpart);
             pa = psys->particles + (between ? cpa->pa[0] : cpa->parent);
           }
-          psys_mat_hair_to_global(sim.ob, sim.psmd->mesh_final, sim.psys->part->from, pa, hairmat);
+          psys_mat_hair_to_global(sim.ob,
+                                  BKE_particle_modifier_mesh_final_get(sim.psmd),
+                                  sim.psys->part->from,
+                                  pa,
+                                  hairmat);
           copy_m3_m4(mat, hairmat);
           /* to quaternion */
           mat3_to_quat(frame, mat);
index 5d7b380..02d477b 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <stddef.h>
 
+#include "MEM_guardedalloc.h"
+
 #include "BLI_utildefines.h"
 
 #include "DNA_material_types.h"
@@ -42,24 +44,27 @@ static void initData(ModifierData *md)
 {
   ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
   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) {
-    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;
-    }
+static void freeRuntimeData(void *runtime_data_v)
+{
+  if (runtime_data_v == NULL) {
+    return;
+  }
+  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);
   }
-  psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
+  MEM_freeN(runtime_data);
+}
 
+static void freeData(ModifierData *md)
+{
+  ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
+  freeRuntimeData(md->runtime);
   /* ED_object_modifier_remove may have freed this first before calling
    * modifier_free (which calls this function) */
   if (psmd->psys) {
@@ -67,20 +72,6 @@ static void freeData(ModifierData *md)
   }
 }
 
-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),
                              ModifierData *md,
                              CustomData_MeshMasks *r_cddata_masks)
@@ -120,14 +111,16 @@ static void deformVerts(ModifierData *md,
     }
   }
 
+  ParticleSystemModifierDataRuntime *runtime = BKE_particle_modifier_runtime_ensure(psmd);
+
   /* clear old dm */
-  bool had_mesh_final = (psmd->mesh_final != 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;
+  bool had_mesh_final = (runtime->mesh_final != NULL);
+  if (runtime->mesh_final) {
+    BKE_id_free(NULL, runtime->mesh_final);
+    runtime->mesh_final = NULL;
+    if (runtime->mesh_original) {
+      BKE_id_free(NULL, runtime->mesh_original);
+      runtime->mesh_original = NULL;
     }
   }
   else if (psmd->flag & eParticleSystemFlag_file_loaded) {
@@ -143,13 +136,13 @@ static void deformVerts(ModifierData *md,
   }
 
   /* make new mesh */
-  psmd->mesh_final = BKE_mesh_copy_for_eval(mesh_src, false);
-  BKE_mesh_apply_vert_coords(psmd->mesh_final, vertexCos);
-  BKE_mesh_calc_normals(psmd->mesh_final);
+  runtime->mesh_final = BKE_mesh_copy_for_eval(mesh_src, false);
+  BKE_mesh_apply_vert_coords(runtime->mesh_final, vertexCos);
+  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
      * are attached to so in case of non-deform modifiers we need to remap
      * them to the final mesh (typically subdivision surfaces). */
@@ -160,7 +153,7 @@ static void deformVerts(ModifierData *md,
 
       if (em) {
         /* 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 {
         /* Otherwise get regular mesh. */
@@ -175,13 +168,13 @@ static void deformVerts(ModifierData *md,
       /* Make a persistent copy of the mesh. We don't actually need
        * all this data, just some topology for remapping. Could be
        * 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);
   }
 
@@ -189,13 +182,13 @@ static void deformVerts(ModifierData *md,
    * This is an unreliable check for the topology check, but allows some
    * handy configuration like emitting particles from inside particle
    * instance. */
-  if (had_mesh_final && (psmd->mesh_final->totvert != psmd->totdmvert ||
-                         psmd->mesh_final->totedge != psmd->totdmedge ||
-                         psmd->mesh_final->totface != psmd->totdmface)) {
+  if (had_mesh_final && (runtime->mesh_final->totvert != runtime->totdmvert ||
+                         runtime->mesh_final->totedge != runtime->totdmedge ||
+                         runtime->mesh_final->totface != runtime->totdmface)) {
     psys->recalc |= ID_RECALC_PSYS_RESET;
-    psmd->totdmvert = psmd->mesh_final->totvert;
-    psmd->totdmedge = psmd->mesh_final->totedge;
-    psmd->totdmface = psmd->mesh_final->totface;
+    runtime->totdmvert = runtime->mesh_final->totvert;
+    runtime->totdmedge = runtime->mesh_final->totedge;
+    runtime->totdmface = runtime->mesh_final->totface;
   }
 
   if (!(ctx->object->transflag & OB_NO_PSYS_UPDATE)) {
@@ -245,12 +238,11 @@ ModifierTypeInfo modifierType_ParticleSystem = {
     /* structSize */ sizeof(ParticleSystemModifierData),
     /* type */ eModifierTypeType_OnlyDeform,
     /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping |
-        eModifierTypeFlag_UsesPointCache /* |
+        eModifierTypeFlag_UsesPointCache, /* |
                           eModifierTypeFlag_SupportsEditmode |
                           eModifierTypeFlag_EnableInEditmode */
-    ,
 
-    /* copyData */ copyData,
+    /* copyData */ modifier_copyData_generic,
 
     /* deformVerts */ deformVerts,
     /* deformMatrices */ NULL,
@@ -268,5 +260,5 @@ ModifierTypeInfo modifierType_ParticleSystem = {
     /* foreachObjectLink */ NULL,
     /* foreachIDLink */ NULL,
     /* foreachTexLink */ NULL,
-    /* freeRuntimeData */ NULL,
+    /* freeRuntimeData */ freeRuntimeData,
 };