From 2145005e5e3d9618982b25047bf803a3433fe0a3 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Tue, 21 Jun 2011 11:15:37 +0000 Subject: Fix for [#26939] Hair Combing intersects emitter when combed fast * Hair combing now uses substeps to apply the combing when the mouse movement exceeds 0.2 of the brush radius. * This could make combing a bit slower on fast mouse movements, but the increase in combing quality is definitely worth it. --- source/blender/editors/physics/particle_edit.c | 236 +++++++++++++------------ 1 file changed, 124 insertions(+), 112 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 6155929243b..9124bdaf41c 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3461,7 +3461,8 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) ARegion *ar= CTX_wm_region(C); float vec[3], mousef[2]; int mval[2]; - int flip, mouse[2], dx, dy, removed= 0, added=0, selected= 0; + int flip, mouse[2], removed= 0, added=0, selected= 0, tot_steps= 1, step= 1; + float dx, dy, dmax; int lock_root = pset->flag & PE_LOCK_FIRST; if(!PE_start_edit(edit)) @@ -3496,152 +3497,163 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) view3d_operator_needs_opengl(C); selected= (short)count_selected_keys(scene, edit); - switch(pset->brushtype) { - case PE_BRUSH_COMB: - { - float mval_f[2]; - data.mval= mval; - data.rad= (float)brush->size; + dmax = MAX2(fabs(dx), fabs(dy)); + tot_steps = dmax/(0.2f * brush->size) + 1; - data.combfac= (brush->strength - 0.5f) * 2.0f; - if(data.combfac < 0.0f) - data.combfac= 1.0f - 9.0f * data.combfac; - else - data.combfac= 1.0f - data.combfac; - - invert_m4_m4(ob->imat, ob->obmat); + dx /= (float)tot_steps; + dy /= (float)tot_steps; - mval_f[0]= dx; - mval_f[1]= dy; - ED_view3d_win_to_delta(ar, mval_f, vec); - data.dvec= vec; + for(step = 1; step<=tot_steps; step++) { + mval[0] = bedit->lastmouse[0] + step*dx; + mval[1] = bedit->lastmouse[1] + step*dy; - foreach_mouse_hit_key(&data, brush_comb, selected); - break; - } - case PE_BRUSH_CUT: - { - if(edit->psys && edit->pathcache) { + switch(pset->brushtype) { + case PE_BRUSH_COMB: + { + float mval_f[2]; data.mval= mval; data.rad= (float)brush->size; - data.cutfac= brush->strength; - if(selected) - foreach_selected_point(&data, brush_cut); + data.combfac= (brush->strength - 0.5f) * 2.0f; + if(data.combfac < 0.0f) + data.combfac= 1.0f - 9.0f * data.combfac; else - foreach_point(&data, brush_cut); + data.combfac= 1.0f - data.combfac; - removed= remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob)); - if(pset->flag & PE_KEEP_LENGTHS) - recalc_lengths(edit); - } - else - removed= 0; - - break; - } - case PE_BRUSH_LENGTH: - { - data.mval= mval; - - data.rad= (float)brush->size; - data.growfac= brush->strength / 50.0f; + invert_m4_m4(ob->imat, ob->obmat); - if(brush->invert ^ flip) - data.growfac= 1.0f - data.growfac; - else - data.growfac= 1.0f + data.growfac; + mval_f[0]= dx; + mval_f[1]= dy; + ED_view3d_win_to_delta(ar, mval_f, vec); + data.dvec= vec; - foreach_mouse_hit_point(&data, brush_length, selected); + foreach_mouse_hit_key(&data, brush_comb, selected); + break; + } + case PE_BRUSH_CUT: + { + if(edit->psys && edit->pathcache) { + data.mval= mval; + data.rad= (float)brush->size; + data.cutfac= brush->strength; + + if(selected) + foreach_selected_point(&data, brush_cut); + else + foreach_point(&data, brush_cut); + + removed= remove_tagged_particles(ob, edit->psys, pe_x_mirror(ob)); + if(pset->flag & PE_KEEP_LENGTHS) + recalc_lengths(edit); + } + else + removed= 0; - if(pset->flag & PE_KEEP_LENGTHS) - recalc_lengths(edit); - break; - } - case PE_BRUSH_PUFF: - { - if(edit->psys) { - data.dm= psmd->dm; + break; + } + case PE_BRUSH_LENGTH: + { data.mval= mval; + data.rad= (float)brush->size; - data.select= selected; + data.growfac= brush->strength / 50.0f; - data.pufffac= (brush->strength - 0.5f) * 2.0f; - if(data.pufffac < 0.0f) - data.pufffac= 1.0f - 9.0f * data.pufffac; + if(brush->invert ^ flip) + data.growfac= 1.0f - data.growfac; else - data.pufffac= 1.0f - data.pufffac; + data.growfac= 1.0f + data.growfac; - data.invert= (brush->invert ^ flip); - invert_m4_m4(ob->imat, ob->obmat); + foreach_mouse_hit_point(&data, brush_length, selected); - foreach_mouse_hit_point(&data, brush_puff, selected); + if(pset->flag & PE_KEEP_LENGTHS) + recalc_lengths(edit); + break; } - break; - } - case PE_BRUSH_ADD: - { - if(edit->psys && edit->psys->part->from==PART_FROM_FACE) { - data.mval= mval; + case PE_BRUSH_PUFF: + { + if(edit->psys) { + data.dm= psmd->dm; + data.mval= mval; + data.rad= (float)brush->size; + data.select= selected; + + data.pufffac= (brush->strength - 0.5f) * 2.0f; + if(data.pufffac < 0.0f) + data.pufffac= 1.0f - 9.0f * data.pufffac; + else + data.pufffac= 1.0f - data.pufffac; + + data.invert= (brush->invert ^ flip); + invert_m4_m4(ob->imat, ob->obmat); + + foreach_mouse_hit_point(&data, brush_puff, selected); + } + break; + } + case PE_BRUSH_ADD: + { + if(edit->psys && edit->psys->part->from==PART_FROM_FACE) { + data.mval= mval; - added= brush_add(&data, brush->count); + added= brush_add(&data, brush->count); - if(pset->flag & PE_KEEP_LENGTHS) - recalc_lengths(edit); + if(pset->flag & PE_KEEP_LENGTHS) + recalc_lengths(edit); + } + else + added= 0; + break; } - else - added= 0; - break; - } - case PE_BRUSH_SMOOTH: - { - data.mval= mval; - data.rad= (float)brush->size; + case PE_BRUSH_SMOOTH: + { + data.mval= mval; + data.rad= (float)brush->size; + + data.vec[0]= data.vec[1]= data.vec[2]= 0.0f; + data.tot= 0; - data.vec[0]= data.vec[1]= data.vec[2]= 0.0f; - data.tot= 0; + data.smoothfac= brush->strength; - data.smoothfac= brush->strength; + invert_m4_m4(ob->imat, ob->obmat); - invert_m4_m4(ob->imat, ob->obmat); + foreach_mouse_hit_key(&data, brush_smooth_get, selected); - foreach_mouse_hit_key(&data, brush_smooth_get, selected); + if(data.tot) { + mul_v3_fl(data.vec, 1.0f / (float)data.tot); + foreach_mouse_hit_key(&data, brush_smooth_do, selected); + } - if(data.tot) { - mul_v3_fl(data.vec, 1.0f / (float)data.tot); - foreach_mouse_hit_key(&data, brush_smooth_do, selected); + break; } + case PE_BRUSH_WEIGHT: + { + if(edit->psys) { + data.dm= psmd->dm; + data.mval= mval; + data.rad= (float)brush->size; - break; - } - case PE_BRUSH_WEIGHT: - { - if(edit->psys) { - data.dm= psmd->dm; - data.mval= mval; - data.rad= (float)brush->size; + data.weightfac = brush->strength; /* note that this will never be zero */ - data.weightfac = brush->strength; /* note that this will never be zero */ + foreach_mouse_hit_key(&data, brush_weight, selected); + } - foreach_mouse_hit_key(&data, brush_weight, selected); + break; } - - break; } - } - if((pset->flag & PE_KEEP_LENGTHS)==0) - recalc_lengths(edit); + if((pset->flag & PE_KEEP_LENGTHS)==0) + recalc_lengths(edit); - if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) { - if(pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob)) - PE_mirror_x(scene, ob, 1); + if(ELEM(pset->brushtype, PE_BRUSH_ADD, PE_BRUSH_CUT) && (added || removed)) { + if(pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob)) + PE_mirror_x(scene, ob, 1); - update_world_cos(ob,edit); - psys_free_path_cache(NULL, edit); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + update_world_cos(ob,edit); + psys_free_path_cache(NULL, edit); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + } + else + PE_update_object(scene, ob, 1); } - else - PE_update_object(scene, ob, 1); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob); -- cgit v1.2.3