From 36faf739a71624b6ca10cec7233779f9eeace0bd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 5 Jun 2019 12:39:40 +0200 Subject: 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 --- source/blender/editors/physics/particle_edit.c | 108 +++++++++++++---------- source/blender/editors/physics/particle_object.c | 23 +++-- 2 files changed, 74 insertions(+), 57 deletions(-) (limited to 'source/blender/editors/physics') diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index dc634865a0a..7506ad37908 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -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; } diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index b03ec56c7e4..d85bf72851d 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -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); -- cgit v1.2.3