diff options
Diffstat (limited to 'source/blender/editors/physics/particle_edit.c')
-rw-r--r-- | source/blender/editors/physics/particle_edit.c | 131 |
1 files changed, 71 insertions, 60 deletions
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 64ad3a100cc..deba3bbca32 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -659,7 +659,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected if (selected==0 || key->flag & PEK_SELECT) { if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { - psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat); + psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat); invert_m4_m4(imat, mat); } @@ -674,7 +674,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected if (selected==0 || key->flag & PEK_SELECT) { if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { - psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat); + psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat); invert_m4_m4(imat, mat); } @@ -761,7 +761,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) psmd= psys_get_modifier(ob, psys); totpart= psys->totpart; - if (!psmd->dm) + if (!psmd->dm_final) return; tree= BLI_kdtree_new(totpart); @@ -769,7 +769,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) /* insert particles into kd tree */ LOOP_PARTICLES { key = pa->hair; - psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat); copy_v3_v3(co, key->co); mul_m4_v3(mat, co); BLI_kdtree_insert(tree, p, co); @@ -783,7 +783,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) LOOP_PARTICLES { key = pa->hair; - psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); + psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat); copy_v3_v3(co, key->co); mul_m4_v3(mat, co); co[0] = -co[0]; @@ -898,7 +898,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys) edit= psys->edit; psmd= psys_get_modifier(ob, psys); - if (!psmd->dm) + if (!psmd->dm_final) return; if (!edit->mirror_cache) @@ -911,7 +911,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys) * to avoid doing mirror twice */ LOOP_POINTS { if (point->flag & PEP_EDIT_RECALC) { - PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL); + PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL); if (edit->mirror_cache[p] != -1) edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC; @@ -946,11 +946,11 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) psys = edit->psys; psmd = psys_get_modifier(ob, psys); - if (!psmd->dm) + if (!psmd->dm_final) return; LOOP_EDITED_POINTS { - psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles + p, hairmat); + psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat); LOOP_KEYS { mul_m4_v3(hairmat, key->co); @@ -1095,7 +1095,7 @@ void recalc_lengths(PTCacheEdit *edit) /* calculate a tree for finding nearest emitter's vertice */ void recalc_emitter_field(Object *ob, ParticleSystem *psys) { - DerivedMesh *dm=psys_get_modifier(ob, psys)->dm; + DerivedMesh *dm=psys_get_modifier(ob, psys)->dm_final; PTCacheEdit *edit= psys->edit; float *vec, *nor; int i, totface /*, totvert*/; @@ -1188,12 +1188,12 @@ void update_world_cos(Object *ob, PTCacheEdit *edit) POINT_P; KEY_K; float hairmat[4][4]; - if (psys==0 || psys->edit==0 || psmd->dm==NULL) + if (psys==0 || psys->edit==0 || psmd->dm_final==NULL) return; LOOP_POINTS { if (!(psys->flag & PSYS_GLOBAL_HAIR)) - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, hairmat); + psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, hairmat); LOOP_KEYS { copy_v3_v3(key->world_co, key->co); @@ -1839,7 +1839,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool LOOP_VISIBLE_POINTS { if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR)) - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + p, mat); + psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat); if (pset->selectmode==SCE_SELECT_POINT) { LOOP_KEYS { @@ -2273,7 +2273,7 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror) psmd= psys_get_modifier(ob, psys); LOOP_TAGGED_POINTS { - PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL); + PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL); } } @@ -2353,7 +2353,7 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys) LOOP_POINTS { LOOP_TAGGED_KEYS { - PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL); + PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL); break; } } @@ -2567,7 +2567,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->dm, psys->part->from, psys->particles+p, mat); + psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat); copy_v3_v3(co, point->keys->co); mul_m4_v3(mat, co); BLI_kdtree_insert(tree, p, co); @@ -2577,7 +2577,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->dm, psys->part->from, psys->particles+p, mat); + psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat); copy_v3_v3(co, point->keys->co); mul_m4_v3(mat, co); @@ -2808,13 +2808,17 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) return; psmd= psys_get_modifier(ob, psys); - if (!psmd->dm) + if (!psmd->dm_final) return; + const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly); + /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */ BKE_mesh_tessface_ensure(me); - mirrorfaces= mesh_get_x_mirror_faces(ob, NULL); + /* Note: In case psys uses DM tessface indices, we mirror final DM iteslef, not orig mesh. Avoids an (impossible) + * dm -> orig -> dm tessface indices conversion... */ + mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd->dm_final : NULL); if (!edit->mirror_cache) PE_update_mirror_cache(ob, psys); @@ -2823,11 +2827,12 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) newtotpart= psys->totpart; LOOP_VISIBLE_POINTS { pa = psys->particles + p; + if (!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->dm, psys, pa, NULL); + PE_mirror_particle(ob, psmd->dm_final, psys, pa, NULL); continue; } else @@ -2840,6 +2845,8 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) } if (newtotpart != psys->totpart) { + MFace *mtessface = use_dm_final_indices ? psmd->dm_final->getTessFaceArray(psmd->dm_final) : me->mface; + /* allocate new arrays and copy existing */ new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new"); new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint new"); @@ -2869,10 +2876,12 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) for (p=0, point=edit->points; p<totpart; p++, point++) { pa = psys->particles + p; + const int pa_num = pa->num; if (point->flag & PEP_HIDE) continue; - if (!(point->flag & PEP_TAG) || mirrorfaces[pa->num*2] == -1) + + if (!(point->flag & PEP_TAG) || mirrorfaces[pa_num * 2] == -1) continue; /* duplicate */ @@ -2882,27 +2891,31 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) if (point->keys) newpoint->keys= MEM_dupallocN(point->keys); /* rotate weights according to vertex index rotation */ - rotation= mirrorfaces[pa->num*2+1]; + rotation= mirrorfaces[pa_num * 2 + 1]; newpa->fuv[0] = pa->fuv[2]; newpa->fuv[1] = pa->fuv[1]; newpa->fuv[2] = pa->fuv[0]; newpa->fuv[3] = pa->fuv[3]; - while (rotation-- > 0) - if (me->mface[pa->num].v4) { + while (rotation--) { + if (mtessface[pa_num].v4) { SHIFT4(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2], newpa->fuv[3]); } else { SHIFT3(float, newpa->fuv[0], newpa->fuv[1], newpa->fuv[2]); } + } - /* assign face inddex */ - newpa->num= mirrorfaces[pa->num*2]; - newpa->num_dmcache= psys_particle_dm_face_lookup(ob, psmd->dm, newpa->num, newpa->fuv, NULL); + /* assign face index */ + /* NOTE: mesh_get_x_mirror_faces generates -1 for non-found mirror, same as DMCACHE_NOTFOUND... */ + newpa->num = mirrorfaces[pa_num * 2]; - if ((newpa->num_dmcache != DMCACHE_NOTFOUND) && psys->part->use_modifier_stack && !psmd->dm->deformedOnly) { - newpa->num = newpa->num_dmcache; + if (use_dm_final_indices) { newpa->num_dmcache = DMCACHE_ISCHILD; } + else { + newpa->num_dmcache = psys_particle_dm_face_lookup( + psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL); + } /* update edit key pointers */ key= newpoint->keys; @@ -2912,7 +2925,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->dm, psys, pa, newpa); + PE_mirror_particle(ob, psmd->dm_final, psys, pa, newpa); newpa++; newpoint++; @@ -3360,7 +3373,7 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, totface=dm->getNumTessFaces(dm); mface=dm->getTessFaceDataArray(dm, CD_MFACE); mvert=dm->getVertDataArray(dm, CD_MVERT); - + /* lets intersect the faces */ for (i=0; i<totface; i++, mface++) { if (vert_cos) { @@ -3452,6 +3465,7 @@ static int brush_add(PEData *data, short number) { Scene *scene= data->scene; Object *ob= data->ob; + DerivedMesh *dm; PTCacheEdit *edit = data->edit; ParticleSystem *psys= edit->psys; ParticleData *add_pars; @@ -3465,11 +3479,7 @@ static int brush_add(PEData *data, short number) float framestep, timestep; short size= pset->brush[PE_BRUSH_ADD].size; short size2= size*size; - DerivedMesh *dm=0; RNG *rng; - const int *index_mf_to_mpoly; - const int *index_mp_to_orig; - bool release_dm = false; invert_m4_m4(imat, ob->obmat); @@ -3487,15 +3497,13 @@ static int brush_add(PEData *data, short number) timestep= psys_get_timestep(&sim); - if (psmd->dm->deformedOnly || psys->part->use_modifier_stack) - dm = psmd->dm; + if (psys->part->use_modifier_stack || psmd->dm_final->deformedOnly) { + dm = psmd->dm_final; + } else { - dm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH | CD_MASK_MFACE); - release_dm = true; + dm = psmd->dm_deformed; } - - index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); + BLI_assert(dm); for (i=0; i<number; i++) { if (number>1) { @@ -3523,16 +3531,22 @@ static int brush_add(PEData *data, short number) /* warning, returns the derived mesh face */ if (particle_intersect_dm(scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) { - if (index_mf_to_mpoly && index_mp_to_orig) - add_pars[n].num = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, add_pars[n].num_dmcache); - else + if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) { + add_pars[n].num = add_pars[n].num_dmcache; + add_pars[n].num_dmcache = DMCACHE_ISCHILD; + } + else if (dm == psmd->dm_deformed) { + /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */ + add_pars[n].num = add_pars[n].num_dmcache; + add_pars[n].num_dmcache = psys_particle_dm_face_lookup( + psmd->dm_final, psmd->dm_deformed, + add_pars[n].num, add_pars[n].fuv, NULL); + } + else { add_pars[n].num = add_pars[n].num_dmcache; + } - if (psys_particle_dm_face_lookup(ob, psmd->dm, add_pars[n].num_dmcache, add_pars[n].fuv, NULL) != DMCACHE_NOTFOUND) { - if (psys->part->use_modifier_stack && !psmd->dm->deformedOnly) { - add_pars[n].num = add_pars[n].num_dmcache; - add_pars[n].num_dmcache = DMCACHE_ISCHILD; - } + if (add_pars[n].num != DMCACHE_NOTFOUND) { n++; } } @@ -3567,7 +3581,7 @@ static int brush_add(PEData *data, short number) tree=BLI_kdtree_new(psys->totpart); for (i=0, pa=psys->particles; i<totpart; i++, pa++) { - psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0, 0); + psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0, 0); BLI_kdtree_insert(tree, i, cur_co); } @@ -3611,7 +3625,7 @@ static int brush_add(PEData *data, short number) int w, maxw; float maxd, totw=0.0, weight[3]; - psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0); + psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0); maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3); maxd= ptn[maxw-1].dist; @@ -3676,7 +3690,7 @@ static int brush_add(PEData *data, short number) } } for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) { - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat); + psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat); invert_m4_m4(imat, hairmat); mul_m4_v3(imat, hkey->co); } @@ -3688,9 +3702,6 @@ static int brush_add(PEData *data, short number) MEM_freeN(add_pars); - if (release_dm) - dm->release(dm); - BLI_rng_free(rng); return n; @@ -3866,7 +3877,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) case PE_BRUSH_PUFF: { if (edit->psys) { - data.dm= psmd->dm; + data.dm= psmd->dm_final; data.mval= mval; data.rad= pe_brush_size_get(scene, brush); data.select= selected; @@ -3922,7 +3933,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) case PE_BRUSH_WEIGHT: { if (edit->psys) { - data.dm= psmd->dm; + data.dm= psmd->dm_final; data.mval= mval; data.rad= pe_brush_size_get(scene, brush); @@ -4545,7 +4556,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3]) LOOP_VISIBLE_POINTS { if (psys) - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, mat); + psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat); LOOP_SELECTED_KEYS { copy_v3_v3(co, key->co); @@ -4576,7 +4587,7 @@ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, Partic int totpoint; /* no psmd->dm happens in case particle system modifier is not enabled */ - if (!(psys && psmd && psmd->dm) && !cache) + if (!(psys && psmd && psmd->dm_final) && !cache) return; if (cache && cache->flag & PTCACHE_DISK_CACHE) |