Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Sat, 2 Jun 2018 11:09:12 +0000 (13:09 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 2 Jun 2018 11:09:12 +0000 (13:09 +0200)
1  2 
source/blender/blenkernel/intern/particle_system.c

index 2fccd8706721d98bae5989ff0ccb3aa23edb2cdb,47e0994bb83a561790057b661948263f92c1766d..88fc8c6a4401966ddf2270fa123f430eac29aced
  #include "BKE_collision.h"
  #include "BKE_colortools.h"
  #include "BKE_effect.h"
 +#include "BKE_global.h"
 +#include "BKE_library.h"
  #include "BKE_library_query.h"
  #include "BKE_main.h"
  #include "BKE_particle.h"
  
 +#include "BKE_collection.h"
  #include "BKE_DerivedMesh.h"
  #include "BKE_object.h"
  #include "BKE_material.h"
  #include "BKE_modifier.h"
  #include "BKE_scene.h"
  #include "BKE_bvhutils.h"
 -#include "BKE_depsgraph.h"
 +
 +#include "DEG_depsgraph.h"
 +#include "DEG_depsgraph_query.h"
  
  #include "PIL_time.h"
  
  #include "RE_shader_ext.h"
 -#include "DEG_depsgraph.h"
  
  /* fluid sim particle import */
  #ifdef WITH_MOD_FLUID
@@@ -125,11 -121,11 +125,11 @@@ static int particles_are_dynamic(Partic
                return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
  }
  
 -float psys_get_current_display_percentage(ParticleSystem *psys)
 +float psys_get_current_display_percentage(ParticleSystem *psys, const bool use_render_params)
  {
        ParticleSettings *part=psys->part;
  
 -      if ((psys->renderdata && !particles_are_dynamic(psys)) ||  /* non-dynamic particles can be rendered fully */
 +      if ((use_render_params && !particles_are_dynamic(psys)) ||  /* non-dynamic particles can be rendered fully */
            (part->child_nbr && part->childtype)  ||    /* display percentage applies to children */
            (psys->pointcache->flag & PTCACHE_BAKING))  /* baking is always done with full amount */
        {
@@@ -289,31 -285,31 +289,31 @@@ static void realloc_particles(ParticleS
        }
  }
  
 -int psys_get_child_number(Scene *scene, ParticleSystem *psys)
 +int psys_get_child_number(Scene *scene, ParticleSystem *psys, const bool use_render_params)
  {
        int nbr;
  
        if (!psys->part->childtype)
                return 0;
  
 -      if (psys->renderdata)
 +      if (use_render_params)
                nbr= psys->part->ren_child_nbr;
        else
                nbr= psys->part->child_nbr;
  
 -      return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL);
 +      return get_render_child_particle_number(&scene->r, nbr, use_render_params);
  }
  
 -int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
 +int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render_params)
  {
 -      return psys->totpart*psys_get_child_number(scene, psys);
 +      return psys->totpart*psys_get_child_number(scene, psys, use_render_params);
  }
  
  /************************************************/
  /*                    Distribution                                            */
  /************************************************/
  
 -void psys_calc_dmcache(Object *ob, DerivedMesh *dm_final, DerivedMesh *dm_deformed, ParticleSystem *psys)
 +void psys_calc_dmcache(Object *ob, Mesh *mesh_final, Mesh *mesh_original, ParticleSystem *psys)
  {
        /* use for building derived mesh mapping info:
         *
        PARTICLE_P;
        
        /* CACHE LOCATIONS */
 -      if (!dm_final->deformedOnly) {
 +      if (!mesh_final->runtime.deformed_only) {
                /* Will use later to speed up subsurf/derivedmesh */
                LinkNode *node, *nodedmelem, **nodearray;
                int totdmelem, totelem, i, *origindex, *origindex_poly = NULL;
  
                if (psys->part->from == PART_FROM_VERT) {
 -                      totdmelem= dm_final->getNumVerts(dm_final);
 +                      totdmelem = mesh_final->totvert;
  
                        if (use_modifier_stack) {
                                totelem= totdmelem;
                        }
                        else {
                                totelem= me->totvert;
 -                              origindex= dm_final->getVertDataArray(dm_final, CD_ORIGINDEX);
 +                              origindex = CustomData_get_layer(&mesh_final->vdata, CD_ORIGINDEX);
                        }
                }
                else { /* FROM_FACE/FROM_VOLUME */
 -                      totdmelem= dm_final->getNumTessFaces(dm_final);
 +                      totdmelem= mesh_final->totface;
  
                        if (use_modifier_stack) {
                                totelem= totdmelem;
                                origindex_poly= NULL;
                        }
                        else {
 -                              totelem = dm_deformed->getNumTessFaces(dm_deformed);
 -                              origindex = dm_final->getTessFaceDataArray(dm_final, CD_ORIGINDEX);
 +                              totelem = mesh_original->totface;
 +                              origindex = CustomData_get_layer(&mesh_final->fdata, CD_ORIGINDEX);
  
                                /* for face lookups we need the poly origindex too */
 -                              origindex_poly= dm_final->getPolyDataArray(dm_final, CD_ORIGINDEX);
 +                              origindex_poly = CustomData_get_layer(&mesh_final->pdata, CD_ORIGINDEX);
                                if (origindex_poly == NULL) {
                                        origindex= NULL;
                                }
                                                pa->num_dmcache = DMCACHE_NOTFOUND;
                                }
                                else { /* FROM_FACE/FROM_VOLUME */
 -                                      pa->num_dmcache = psys_particle_dm_face_lookup(dm_final, dm_deformed, pa->num, pa->fuv, nodearray);
 +                                      pa->num_dmcache = psys_particle_dm_face_lookup(mesh_final, mesh_original, pa->num, pa->fuv, nodearray);
                                }
                        }
                }
@@@ -440,7 -436,7 +440,7 @@@ void psys_thread_context_init(ParticleT
  {
        memset(ctx, 0, sizeof(ParticleThreadContext));
        ctx->sim = *sim;
 -      ctx->dm = ctx->sim.psmd->dm_final;
 +      ctx->mesh = ctx->sim.psmd->mesh_final;
        ctx->ma = give_current_material(sim->ob, sim->psys->part->omat);
  }
  
@@@ -515,6 -511,7 +515,6 @@@ void psys_thread_context_free(ParticleT
        if (ctx->jitoff) MEM_freeN(ctx->jitoff);
        if (ctx->weight) MEM_freeN(ctx->weight);
        if (ctx->index) MEM_freeN(ctx->index);
 -      if (ctx->skip) MEM_freeN(ctx->skip);
        if (ctx->seams) MEM_freeN(ctx->seams);
        //if (ctx->vertpart) MEM_freeN(ctx->vertpart);
        BLI_kdtree_free(ctx->tree);
@@@ -705,9 -702,9 +705,9 @@@ void psys_get_birth_coords(ParticleSimu
  
        /* get birth location from object               */
        if (use_tangents)
 -              psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0);
 +              psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0);
        else
 -              psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0);
 +              psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0);
                
        /* get possible textural influence */
        psys_get_texture(sim, pa, &ptex, PAMAP_IVEL, cfra);
  }
  
  /* recursively evaluate emitter parent anim at cfra */
 -static void evaluate_emitter_anim(Scene *scene, Object *ob, float cfra)
 +static void evaluate_emitter_anim(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float cfra)
  {
        if (ob->parent)
 -              evaluate_emitter_anim(scene, ob->parent, cfra);
 +              evaluate_emitter_anim(depsgraph, scene, ob->parent, cfra);
        
        /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
 -      BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, cfra, ADT_RECALC_ANIM);
 -      BKE_object_where_is_calc_time(scene, ob, cfra);
 +      BKE_animsys_evaluate_animdata(depsgraph, scene, &ob->id, ob->adt, cfra, ADT_RECALC_ANIM);
 +      BKE_object_where_is_calc_time(depsgraph, scene, ob, cfra);
  }
  
  /* sets particle to the emitter surface with initial velocity & rotation */
@@@ -1012,7 -1009,7 +1012,7 @@@ void reset_particle(ParticleSimulationD
        
        /* get precise emitter matrix if particle is born */
        if (part->type != PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
 -              evaluate_emitter_anim(sim->scene, sim->ob, pa->time);
 +              evaluate_emitter_anim(sim->depsgraph, sim->scene, sim->ob, pa->time);
  
                psys->flag |= PSYS_OB_ANIM_RESTORE;
        }
@@@ -1146,8 -1143,7 +1146,8 @@@ static void set_keyed_keys(ParticleSimu
        int totpart = psys->totpart, k, totkeys = psys->totkeyed;
        int keyed_flag = 0;
  
 -      ksim.scene= sim->scene;
 +      ksim.depsgraph = sim->depsgraph;
 +      ksim.scene = sim->scene;
        
        /* no proper targets so let's clear and bail out */
        if (psys->totkeyed==0) {
@@@ -1308,7 -1304,7 +1308,7 @@@ void psys_update_particle_tree(Particle
  static void psys_update_effectors(ParticleSimulationData *sim)
  {
        pdEndEffectors(&sim->psys->effectors);
 -      sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys,
 +      sim->psys->effectors = pdInitEffectors(sim->depsgraph, sim->scene, sim->ob, sim->psys,
                                               sim->psys->part->effector_weights, true);
        precalc_guides(sim, sim->psys->effectors);
  }
@@@ -2129,7 -2125,7 +2129,7 @@@ static void basic_integrate(ParticleSim
        tkey.time=pa->state.time;
  
        if (part->type != PART_HAIR) {
 -              if (do_guides(sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
 +              if (do_guides(sim->depsgraph, sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
                        copy_v3_v3(pa->state.co,tkey.co);
                        /* guides don't produce valid velocity */
                        sub_v3_v3v3(pa->state.vel, tkey.co, pa->prev_state.co);
@@@ -2910,9 -2906,10 +2910,9 @@@ static void psys_update_path_cache(Part
        ParticleSystem *psys = sim->psys;
        ParticleSettings *part = psys->part;
        ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
 -      Base *base;
        int distr=0, alloc=0, skip=0;
  
 -      if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
 +      if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys, use_render_params)) || psys->recalc&PSYS_RECALC_RESET)
                alloc=1;
  
        if (alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT)))
                if (alloc)
                        realloc_particles(sim, sim->psys->totpart);
  
 -              if (psys_get_tot_child(sim->scene, psys)) {
 +              if (psys_get_tot_child(sim->scene, psys, use_render_params)) {
                        /* don't generate children while computing the hair keys */
                        if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
                                distribute_particles(sim, PART_FROM_CHILD);
                skip = 1; /* only hair, keyed and baked stuff can have paths */
        else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)))
                skip = 1; /* particle visualization must be set as path */
 -      else if (!psys->renderdata) {
 +      else {
                if (part->draw_as != PART_DRAW_REND)
                        skip = 1; /* draw visualization */
                else if (psys->pointcache->flag & PTCACHE_BAKING)
                        skip = 1; /* no need to cache paths while baking dynamics */
 -              else if (psys_in_edit_mode(sim->scene, psys)) {
 +
 +              else if (psys_in_edit_mode(sim->depsgraph, psys)) {
                        if ((pset->flag & PE_DRAW_PART)==0)
                                skip = 1;
                        else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0)
  
  
        /* particle instance modifier with "path" option need cached paths even if particle system doesn't */
 -      for (base = sim->scene->base.first; base; base= base->next) {
 -              ModifierData *md = modifiers_findByType(base->object, eModifierType_ParticleInstance);
 +      FOREACH_SCENE_OBJECT_BEGIN(sim->scene, ob)
 +      {
 +              ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleInstance);
                if (md) {
                        ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
                        if (pimd->flag & eParticleInstanceFlag_Path && pimd->ob == sim->ob && pimd->psys == (psys - (ParticleSystem*)sim->ob->particlesystem.first)) {
                        }
                }
        }
 +      FOREACH_SCENE_OBJECT_END;
  
        if (!skip) {
                psys_cache_paths(sim, cfra, use_render_params);
@@@ -3025,11 -3019,11 +3025,11 @@@ static MDeformVert *hair_set_pinning(MD
        return dvert;
  }
  
 -static void hair_create_input_dm(ParticleSimulationData *sim, int totpoint, int totedge, DerivedMesh **r_dm, ClothHairData **r_hairdata)
 +static void hair_create_input_mesh(ParticleSimulationData *sim, int totpoint, int totedge, Mesh **r_mesh, ClothHairData **r_hairdata)
  {
        ParticleSystem *psys = sim->psys;
        ParticleSettings *part = psys->part;
 -      DerivedMesh *dm;
 +      Mesh *mesh;
        ClothHairData *hairdata;
        MVert *mvert;
        MEdge *medge;
        float max_length;
        float hair_radius;
        
 -      dm = *r_dm;
 -      if (!dm) {
 -              *r_dm = dm = CDDM_new(totpoint, totedge, 0, 0, 0);
 -              DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL);
 -      }
 -      mvert = CDDM_get_verts(dm);
 -      medge = CDDM_get_edges(dm);
 -      dvert = DM_get_vert_data_layer(dm, CD_MDEFORMVERT);
 +      mesh = *r_mesh;
 +      if (!mesh) {
 +              *r_mesh = mesh = BKE_mesh_new_nomain(totpoint, totedge, 0, 0, 0);
 +              CustomData_add_layer(&mesh->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, mesh->totvert);
 +              BKE_mesh_update_customdata_pointers(mesh, false);
 +      }
 +      mvert = mesh->mvert;
 +      medge = mesh->medge;
 +      dvert = mesh->dvert;
        
        hairdata = *r_hairdata;
        if (!hairdata) {
                        pa->hair_index = hair_index;
                        use_hair = psys_hair_use_simulation(pa, max_length);
  
 -                      psys_mat_hair_to_object(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat);
 +                      psys_mat_hair_to_object(sim->ob, sim->psmd->mesh_final, psys->part->from, pa, hairmat);
                        mul_m4_m4m4(root_mat, sim->ob->obmat, hairmat);
                        normalize_m4(root_mat);
  
@@@ -3181,26 -3174,26 +3181,26 @@@ static void do_hair_dynamics(ParticleSi
        }
        
        realloc_roots = false; /* whether hair root info array has to be reallocated */
 -      if (psys->hair_in_dm) {
 -              DerivedMesh *dm = psys->hair_in_dm;
 -              if (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm)) {
 -                      dm->release(dm);
 -                      psys->hair_in_dm = NULL;
 +      if (psys->hair_in_mesh) {
 +              Mesh *mesh = psys->hair_in_mesh;
 +              if (totpoint != mesh->totvert || totedge != mesh->totedge) {
 +                      BKE_id_free(NULL, mesh);
 +                      psys->hair_in_mesh = NULL;
                        realloc_roots = true;
                }
        }
        
 -      if (!psys->hair_in_dm || !psys->clmd->hairdata || realloc_roots) {
 +      if (!psys->hair_in_mesh || !psys->clmd->hairdata || realloc_roots) {
                if (psys->clmd->hairdata) {
                        MEM_freeN(psys->clmd->hairdata);
                        psys->clmd->hairdata = NULL;
                }
        }
        
 -      hair_create_input_dm(sim, totpoint, totedge, &psys->hair_in_dm, &psys->clmd->hairdata);
 +      hair_create_input_mesh(sim, totpoint, totedge, &psys->hair_in_mesh, &psys->clmd->hairdata);
        
 -      if (psys->hair_out_dm)
 -              psys->hair_out_dm->release(psys->hair_out_dm);
 +      if (psys->hair_out_mesh)
 +              BKE_id_free(NULL, psys->hair_out_mesh);
        
        psys->clmd->point_cache = psys->pointcache;
        /* for hair sim we replace the internal cloth effector weights temporarily
        clmd_effweights = psys->clmd->sim_parms->effector_weights;
        psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
        
 -      deformedVerts = MEM_mallocN(sizeof(*deformedVerts) * psys->hair_in_dm->getNumVerts(psys->hair_in_dm), "do_hair_dynamics vertexCos");
 -      psys->hair_out_dm = CDDM_copy(psys->hair_in_dm);
 -      psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts);
 -      
 -      clothModifier_do(psys->clmd, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts);
 -      
 -      CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts);
 +      BKE_id_copy_ex(
 +                  NULL, &psys->hair_in_mesh->id, (ID **)&psys->hair_out_mesh,
 +                  LIB_ID_CREATE_NO_MAIN |
 +                  LIB_ID_CREATE_NO_USER_REFCOUNT |
 +                  LIB_ID_CREATE_NO_DEG_TAG |
 +                  LIB_ID_COPY_NO_PREVIEW,
 +                  false);
 +      deformedVerts = BKE_mesh_vertexCos_get(psys->hair_out_mesh, NULL);
 +      clothModifier_do(psys->clmd, sim->depsgraph, sim->scene, sim->ob, psys->hair_in_mesh, deformedVerts);
 +      BKE_mesh_apply_vert_coords(psys->hair_out_mesh, deformedVerts);
        
        MEM_freeN(deformedVerts);
        
@@@ -3230,7 -3220,7 +3230,7 @@@ static void hair_step(ParticleSimulatio
        ParticleSystem *psys = sim->psys;
        ParticleSettings *part = psys->part;
        PARTICLE_P;
 -      float disp = psys_get_current_display_percentage(psys);
 +      float disp = psys_get_current_display_percentage(psys, use_render_params);
  
        LOOP_PARTICLES {
                pa->size = part->size;
  
        if (psys->recalc & PSYS_RECALC_RESET) {
                /* need this for changing subsurf levels */
 -              psys_calc_dmcache(sim->ob, sim->psmd->dm_final, sim->psmd->dm_deformed, psys);
 +              psys_calc_dmcache(sim->ob, sim->psmd->mesh_final, sim->psmd->mesh_original, psys);
  
                if (psys->clmd)
                        cloth_free_modifier(psys->clmd);
@@@ -3292,7 -3282,7 +3292,7 @@@ static void save_hair(ParticleSimulatio
  
                if (pa->totkey) {
                        sub_v3_v3(key->co, root->co);
 -                      psys_vec_rot_to_face(sim->psmd->dm_final, pa, key->co);
 +                      psys_vec_rot_to_face(sim->psmd->mesh_final, pa, key->co);
                }
  
                key->time = pa->state.time;
@@@ -3746,13 -3736,13 +3746,13 @@@ static void dynamics_step(ParticleSimul
        free_collider_cache(&sim->colliders);
        BLI_rng_free(rng);
  }
 -static void update_children(ParticleSimulationData *sim)
 +static void update_children(ParticleSimulationData *sim, const bool use_render_params)
  {
        if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0)
        /* don't generate children while growing hair - waste of time */
                psys_free_children(sim->psys);
        else if (sim->psys->part->childtype) {
 -              if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys))
 +              if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys, use_render_params))
                        distribute_particles(sim, PART_FROM_CHILD);
                else {
                        /* Children are up to date, nothing to do. */
                psys_free_children(sim->psys);
  }
  /* updates cached particles' alive & other flags etc..*/
 -static void cached_step(ParticleSimulationData *sim, float cfra)
 +static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
  {
        ParticleSystem *psys = sim->psys;
        ParticleSettings *part = psys->part;
  
        psys_update_effectors(sim);
        
 -      disp= psys_get_current_display_percentage(psys);
 +      disp= psys_get_current_display_percentage(psys, use_render_params);
  
        LOOP_PARTICLES {
                psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
        }
  }
  
- static void particles_fluid_step(Main *bmain, ParticleSimulationData *sim, int UNUSED(cfra), const bool use_render_params)
- {     
+ static void particles_fluid_step(
+         Main *bmain, ParticleSimulationData *sim, int UNUSED(cfra), const bool use_render_params)
+ {
        ParticleSystem *psys = sim->psys;
        if (psys->particles) {
                MEM_freeN(psys->particles);
@@@ -3994,8 -3985,8 +3995,8 @@@ static void system_step(ParticleSimulat
                int cache_result = BKE_ptcache_read(pid, cache_cfra, true);
  
                if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
 -                      cached_step(sim, cfra);
 -                      update_children(sim);
 +                      cached_step(sim, cfra, use_render_params);
 +                      update_children(sim, use_render_params);
                        psys_update_path_cache(sim, cfra, use_render_params);
  
                        BKE_ptcache_validate(cache, (int)cache_cfra);
                }
                else if (cache_result == PTCACHE_READ_OLD) {
                        psys->cfra = (float)cache->simframe;
 -                      cached_step(sim, psys->cfra);
 +                      cached_step(sim, psys->cfra, use_render_params);
                }
  
                /* if on second frame, write cache for first frame */
  
  /* 3. do dynamics */
        /* set particles to be not calculated TODO: can't work with pointcache */
 -      disp= psys_get_current_display_percentage(psys);
 +      disp= psys_get_current_display_percentage(psys, use_render_params);
  
        LOOP_PARTICLES {
                if (psys_frand(psys, p) > disp)
                        BKE_ptcache_write(pid, (int)cache_cfra);
        }
  
 -      update_children(sim);
 +      update_children(sim, use_render_params);
  
  /* cleanup */
        if (psys->lattice_deform_data) {
@@@ -4216,7 -4207,7 +4217,7 @@@ static int hair_needs_recalc(ParticleSy
  
  /* main particle update call, checks that things are ok on the large scale and
   * then advances in to actual particle calculations depending on particle type */
 -void particle_system_update(Main *bmain, Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params)
 +void particle_system_update(struct Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params)
  {
        ParticleSimulationData sim= {0};
        ParticleSettings *part = psys->part;
        if (!psys_check_enabled(ob, psys, use_render_params))
                return;
  
 -      cfra= BKE_scene_frame_get(scene);
 +      cfra = DEG_get_ctime(depsgraph);
  
 -      sim.scene= scene;
 -      sim.ob= ob;
 -      sim.psys= psys;
 -      sim.psmd= psys_get_modifier(ob, psys);
 +      sim.depsgraph = depsgraph;
 +      sim.scene = scene;
 +      sim.ob = ob;
 +      sim.psys = psys;
 +      sim.psmd = psys_get_modifier(ob, psys);
  
        /* system was already updated from modifier stack */
        if (sim.psmd->flag & eParticleSystemFlag_psys_updated) {
                        return;
        }
  
 -      if (!sim.psmd->dm_final)
 +      if (!sim.psmd->mesh_final)
                return;
  
        if (part->from != PART_FROM_VERT) {
 -              DM_ensure_tessface(sim.psmd->dm_final);
 +              BKE_mesh_tessface_ensure(sim.psmd->mesh_final);
        }
  
        /* execute drivers only, as animation has already been done */
 -      BKE_animsys_evaluate_animdata(scene, &part->id, part->adt, cfra, ADT_RECALC_DRIVERS);
 +      BKE_animsys_evaluate_animdata(depsgraph, scene, &part->id, part->adt, cfra, ADT_RECALC_DRIVERS);
  
        /* to verify if we need to restore object afterwards */
        psys->flag &= ~PSYS_OB_ANIM_RESTORE;
  
 -      if (psys->recalc & PSYS_RECALC_TYPE)
 -              psys_changed_type(sim.ob, sim.psys);
 -
        if (psys->recalc & PSYS_RECALC_RESET)
                psys->totunexist = 0;
  
                                for (i=0; i<=part->hair_step; i++) {
                                        hcfra=100.0f*(float)i/(float)psys->part->hair_step;
                                        if ((part->flag & PART_HAIR_REGROW)==0)
 -                                              BKE_animsys_evaluate_animdata(scene, &part->id, part->adt, hcfra, ADT_RECALC_ANIM);
 +                                              BKE_animsys_evaluate_animdata(depsgraph, scene, &part->id, part->adt, hcfra, ADT_RECALC_ANIM);
                                        system_step(&sim, hcfra, use_render_params);
                                        psys->cfra = hcfra;
                                        psys->recalc = 0;
                }
                case PART_FLUID:
                {
 -                      particles_fluid_step(bmain, &sim, (int)cfra, use_render_params);
 +                      particles_fluid_step(G.main  /* Yuck :/ */, &sim, (int)cfra, use_render_params);
                        break;
                }
                default:
                                case PART_PHYS_KEYED:
                                {
                                        PARTICLE_P;
 -                                      float disp = psys_get_current_display_percentage(psys);
 +                                      float disp = psys_get_current_display_percentage(psys, use_render_params);
                                        bool free_unexisting = false;
  
                                        /* Particles without dynamics haven't been reset yet because they don't use pointcache */
  
        /* make sure emitter is left at correct time (particle emission can change this) */
        if (psys->flag & PSYS_OB_ANIM_RESTORE) {
 -              evaluate_emitter_anim(scene, ob, cfra);
 +              evaluate_emitter_anim(depsgraph, scene, ob, cfra);
                psys->flag &= ~PSYS_OB_ANIM_RESTORE;
        }
  
        psys->recalc = 0;
  
        /* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
 -      if (psys->renderdata==0)
 -              invert_m4_m4(psys->imat, ob->obmat);
 +      invert_m4_m4(psys->imat, ob->obmat);
 +
 +      BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
  }
  
  /* ID looper */
@@@ -4415,16 -4407,10 +4416,16 @@@ void BKE_particlesystem_id_loop(Particl
  
  /* **** Depsgraph evaluation **** */
  
 -void BKE_particle_system_eval_init(EvaluationContext *UNUSED(eval_ctx),
 +void BKE_particle_system_eval_init(struct Depsgraph *depsgraph,
                                     Scene *scene,
                                     Object *ob)
  {
 -      DEG_debug_print_eval(__func__, ob->id.name, ob);
 +      DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob);
 +      for (ParticleSystem *psys = ob->particlesystem.first;
 +           psys != NULL;
 +           psys = psys->next)
 +      {
 +              psys->recalc |= (psys->part->id.recalc & DEG_TAG_PSYS_ALL);
 +      }
        BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
  }