diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-09-17 10:47:47 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-09-17 10:47:47 +0400 |
commit | 0002d3d85f4c4e6d3084e468fa844e717719ab4d (patch) | |
tree | cd4e26fc3bdd8bb58156caf9a7cc2422b7a05b43 /source/blender | |
parent | 59011071a442a6087708edeafd5058aabe61b4cb (diff) |
vertex group blend, support for blending multiple groups at once.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/include/ED_object.h | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_vgroup.c | 217 |
2 files changed, 114 insertions, 105 deletions
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index e1e65fee848..eae2141e527 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -208,6 +208,8 @@ void ED_object_select_linked_by_id(struct bContext *C, struct ID *id); bool *ED_vgroup_subset_from_select_type(struct Object *ob, enum eVGroupSelect subset_type, int *r_vgroup_tot, int *r_subset_count); +void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot, + int *r_vgroup_subset_map); struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper( const struct bContext *C, diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index ccabbed2a6d..14692a3051c 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -51,6 +51,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_linklist_stack.h" #include "BLF_translation.h" @@ -1418,6 +1419,20 @@ bool *ED_vgroup_subset_from_select_type(Object *ob, eVGroupSelect subset_type, i return vgroup_validmap; } +/** + * store indices from the vgroup_validmap (faster lookups in some cases) + */ +void ED_vgroup_subset_to_index_array(const bool *vgroup_validmap, const int vgroup_tot, + int *r_vgroup_subset_map) +{ + int i, j = 0; + for (i = 0; i < vgroup_tot; i++) { + if (vgroup_validmap[i]) { + r_vgroup_subset_map[j++] = i; + } + } +} + static void vgroup_normalize(Object *ob) { MDeformWeight *dw; @@ -2003,138 +2018,120 @@ static void vgroup_invert_subset(Object *ob, } } -static void vgroup_blend(Object *ob, const float fac) +static void vgroup_blend_subset(Object *ob, const bool *vgroup_validmap, const int vgroup_tot, + const int subset_count, + const float fac) { - MDeformVert *dv; - MDeformWeight *dw; + const float ifac = 1.0f - fac; + MDeformVert **dvert_array = NULL; int i, dvert_tot = 0; - const int def_nr = ob->actdef - 1; - - BLI_assert(fac >= 0.0f && fac <= 1.0f); + int *vgroup_subset_map = BLI_array_alloca(vgroup_subset_map, subset_count); + float *vgroup_subset_weights = BLI_array_alloca(vgroup_subset_weights, subset_count); - if (ob->type != OB_MESH) { - return; - } + BMEditMesh *em = BKE_editmesh_from_object(ob); + BMesh *bm = em ? em->bm : NULL; + Mesh *me = em ? NULL : ob->data; - if (BLI_findlink(&ob->defbase, def_nr)) { - const float ifac = 1.0f - fac; - - BMEditMesh *em = BKE_editmesh_from_object(ob); - BMesh *bm = em ? em->bm : NULL; - Mesh *me = em ? NULL : ob->data; - - /* bmesh only*/ - BMEdge *eed; - BMVert *eve; - BMIter iter; + MeshElemMap *emap ; + int *emap_mem; - /* mesh only */ - MDeformVert *dvert_array = NULL; + BLI_SMALLSTACK_DECLARE(dv_stack, MDeformVert *); + ED_vgroup_subset_to_index_array(vgroup_validmap, vgroup_tot, vgroup_subset_map); + ED_vgroup_parray_alloc(ob->data, &dvert_array, &dvert_tot, false); + memset(vgroup_subset_weights, 0, sizeof(*vgroup_subset_weights) * subset_count); - float *vg_weights; - float *vg_users; - int sel1, sel2; + if (bm) { + emap = NULL; + emap_mem = NULL; + } + else { + BKE_mesh_vert_edge_map_create(&emap, &emap_mem, + me->medge, me->totvert, me->totedge); + } - if (bm) { - BM_mesh_elem_index_ensure(bm, BM_VERT); - dvert_tot = bm->totvert; - } - else { - dvert_tot = me->totvert; - dvert_array = me->dvert; - } - vg_weights = MEM_callocN(sizeof(float) * dvert_tot, "vgroup_blend_f"); - vg_users = MEM_callocN(sizeof(int) * dvert_tot, "vgroup_blend_i"); + for (i = 0; i < dvert_tot; i++) { + MDeformVert *dv; + int dv_stack_tot = 0; + int j; + /* in case its not selected */ if (bm) { - const int cd_dvert_offset = CustomData_get_offset(&bm->vdata, CD_MDEFORMVERT); - - BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) { - sel1 = BM_elem_flag_test(eed->v1, BM_ELEM_SELECT); - sel2 = BM_elem_flag_test(eed->v2, BM_ELEM_SELECT); - - if (sel1 != sel2) { - int i1 /* , i2 */; - /* i1 is always the selected one */ - if (sel1) { - i1 = BM_elem_index_get(eed->v1); - /* i2 = BM_elem_index_get(eed->v2); */ /* UNUSED */ - eve = eed->v2; + BMVert *v = EDBM_vert_at_index(em, i); + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BMIter eiter; + BMEdge *e; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + BMVert *v_other = BM_edge_other_vert(e, v); + const int i_other = BM_elem_index_get(v_other); + + if (BM_elem_flag_test(v_other, BM_ELEM_SELECT) == 0) { + dv = dvert_array[i_other]; + BLI_SMALLSTACK_PUSH(dv_stack, dv); + dv_stack_tot++; } - else { - /* i2 = BM_elem_index_get(eed->v1); */ /* UNUSED */ - i1 = BM_elem_index_get(eed->v2); - eve = eed->v1; - } - - dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); - dw = defvert_find_index(dv, def_nr); - if (dw) { - vg_weights[i1] += dw->weight; - } - vg_users[i1]++; } } - - BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - if (BM_elem_flag_test(eve, BM_ELEM_SELECT) && vg_users[i] > 0) { - dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); - - dw = defvert_verify_index(dv, def_nr); - dw->weight = (fac * (vg_weights[i] / (float)vg_users[i])) + (ifac * dw->weight); - /* in case of division errors */ - CLAMP(dw->weight, 0.0f, 1.0f); + } + else { + MVert *v = &me->mvert[i]; + if (v->flag & SELECT) { + for (j = 0; j < emap[i].count; j++) { + MEdge *e = &me->medge[emap[i].indices[j]]; + const int i_other = (e->v1 == i ? e->v2 : e->v1); + MVert *v_other = &me->mvert[i_other]; + + if ((v_other->flag & SELECT) == 0) { + dv = dvert_array[i_other]; + BLI_SMALLSTACK_PUSH(dv_stack, dv); + dv_stack_tot++; + } } } } - else { - MEdge *ed = me->medge; - MVert *mv; - for (i = 0; i < me->totedge; i++, ed++) { - sel1 = me->mvert[ed->v1].flag & SELECT; - sel2 = me->mvert[ed->v2].flag & SELECT; + if (dv_stack_tot) { + const float dv_mul = 1.0f / (float)dv_stack_tot; - if (sel1 != sel2) { - int i1, i2; - /* i1 is always the selected one */ - if (sel1) { - i1 = ed->v1; - i2 = ed->v2; - } - else { - i2 = ed->v1; - i1 = ed->v2; - } - - dv = &dvert_array[i2]; - dw = defvert_find_index(dv, def_nr); - if (dw) { - vg_weights[i1] += dw->weight; - } - vg_users[i1]++; + /* vgroup_subset_weights is zero'd at this point */ + while ((dv = BLI_SMALLSTACK_POP(dv_stack))) { + for (j = 0; j < subset_count; j++) { + vgroup_subset_weights[j] += dv_mul * defvert_find_weight(dv, vgroup_subset_map[j]); } } - mv = me->mvert; - dv = dvert_array; - - for (i = 0; i < dvert_tot; i++, mv++, dv++) { - if ((mv->flag & SELECT) && (vg_users[i] > 0)) { - dw = defvert_verify_index(dv, def_nr); - dw->weight = (fac * (vg_weights[i] / (float)vg_users[i])) + (ifac * dw->weight); + dv = dvert_array[i]; + for (j = 0; j < subset_count; j++) { + MDeformWeight *dw; + if (vgroup_subset_weights[j] > 0.0f) { + dw = defvert_verify_index(dv, vgroup_subset_map[j]); + } + else { + dw = defvert_find_index(dv, vgroup_subset_map[j]); + } - /* in case of division errors */ + if (dw) { + dw->weight = (fac * vgroup_subset_weights[j]) + (ifac * dw->weight); CLAMP(dw->weight, 0.0f, 1.0f); } + + /* zero for next iteration */ + vgroup_subset_weights[j] = 0.0f; } } + } - MEM_freeN(vg_weights); - MEM_freeN(vg_users); + if (bm) { + /* pass */ } + else { + MEM_freeN(emap); + MEM_freeN(emap_mem); + } + + MEM_freeN(dvert_array); + BLI_SMALLSTACK_FREE(dv_stack); } static int inv_cmp_mdef_vert_weights(const void *a1, const void *a2) @@ -3506,8 +3503,13 @@ static int vertex_group_blend_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); float fac = RNA_float_get(op->ptr, "factor"); + eVGroupSelect subset_type = RNA_enum_get(op->ptr, "group_select_mode"); - vgroup_blend(ob, fac); + int subset_count, vgroup_tot; + + const bool *vgroup_validmap = ED_vgroup_subset_from_select_type(ob, subset_type, &vgroup_tot, &subset_count); + vgroup_blend_subset(ob, vgroup_validmap, vgroup_tot, subset_count, fac); + MEM_freeN((void *)vgroup_validmap); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -3525,10 +3527,14 @@ static int vertex_group_blend_poll(bContext *C) if (!(ob && !ob->id.lib && data && !data->lib)) return false; + if (ob->type != OB_MESH) { + return false; + } + if (BKE_object_is_in_editmode_vgroup(ob)) { return true; } - else if ((ob->type == OB_MESH) && (ob->mode & OB_MODE_WEIGHT_PAINT)) { + else if (ob->mode & OB_MODE_WEIGHT_PAINT) { if (ME_EDIT_PAINT_SEL_MODE(((Mesh *)data)) == SCE_SELECT_VERTEX) { return true; } @@ -3559,6 +3565,7 @@ void OBJECT_OT_vertex_group_blend(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + vgroup_operator_subset_select_props(ot, true); prop = RNA_def_property(ot->srna, "factor", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Factor", ""); RNA_def_property_range(prop, 0.0f, 1.0f); |