diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-06-05 13:39:40 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-06-13 12:34:01 +0300 |
commit | 36faf739a71624b6ca10cec7233779f9eeace0bd (patch) | |
tree | ad57fbc75b6bce4bdc590384a3fdf4eeb5fdbaf0 /source/blender/blenkernel | |
parent | 27537daee1b62aab0fb0d01b89b7d2c044e796cd (diff) |
Particle system: Move runtime data to runtime field
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
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 13 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 108 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_distribute.c | 14 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 17 |
5 files changed, 115 insertions, 45 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 164dbbbf482..ca3a560286f 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -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; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 2a66edc8d42..e74b2b0f671 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -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; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 13649eaf096..61ee5685451 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -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; +} diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 070c3c7a566..7bb2daeab23 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -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 { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 27722aab2d9..1b0655c6734 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -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 */ |