diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-07-22 18:50:38 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-07-22 18:50:38 +0400 |
commit | 57ce6d1470907b283742f45d369b4fe6edcee361 (patch) | |
tree | f0a0cdf436b57dd09020a48cb9fe7a599d353499 /source/blender/editors/transform | |
parent | 9634f8f1151740609230c24761ac20fdfe1a9168 (diff) |
old todo, rotate around individual origins now supports connected face/edge islands.
previously this gave very odd/annoying results, see bug reports [#36134], [#35419]
Diffstat (limited to 'source/blender/editors/transform')
-rw-r--r-- | source/blender/editors/transform/transform.c | 4 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 203 |
2 files changed, 146 insertions, 61 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a565213f031..b15470c98c9 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -111,9 +111,7 @@ static bool transdata_check_local_center(TransInfo *t) { return ((t->around == V3D_LOCAL) && ( (t->flag & (T_OBJECT | T_POSE)) || - (t->obedit && t->obedit->type == OB_MESH && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) || - (t->obedit && t->obedit->type == OB_MBALL) || - (t->obedit && t->obedit->type == OB_ARMATURE) || + (t->obedit && ELEM3(t->obedit->type, OB_MESH, OB_MBALL, OB_ARMATURE)) || (t->spacetype == SPACE_IPO)) ); } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 93e01d84eaf..977a9b88fc8 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -124,6 +124,11 @@ #include "BLI_sys_types.h" // for intptr_t support +/* when transforming islands */ +struct TransIslandData { + float co[3]; + float axismtx[3][3]; +}; /* local function prototype - for Object/Bone Constraints */ static bool constraints_list_needinv(TransInfo *t, ListBase *list); @@ -1914,34 +1919,124 @@ static void editmesh_set_connectivity_distance(BMesh *bm, float mtx[3][3], float MEM_freeN(dists_prev); } -static BMElem *bm_vert_single_select_face(BMVert *eve) +static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, int *r_island_tot, int **r_island_vert_map) { - BMElem *ele; - BMIter iter; + BMesh *bm = em->bm; + struct TransIslandData *trans_islands; + char htype; + char itype; + int i; + + /* group vars */ + int *groups_array; + int (*group_index)[2]; + int group_tot; + void **ele_array; + + int *vert_map; + + if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) { + groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__); + group_tot = BM_mesh_calc_edge_groups(bm, groups_array, &group_index, + NULL, NULL, + BM_ELEM_SELECT); + + htype = BM_EDGE; + itype = BM_VERTS_OF_EDGE; - BM_ITER_ELEM (ele, &iter, eve, BM_FACES_OF_VERT) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - return ele; - } } - return NULL; -} -static BMElem *bm_vert_single_select_edge(BMVert *eve) -{ - BMElem *ele; - BMIter iter; + else { /* (bm->selectmode & SCE_SELECT_FACE) */ + groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__); + group_tot = BM_mesh_calc_face_groups(bm, groups_array, &group_index, + NULL, NULL, + BM_ELEM_SELECT, BM_VERT); + + htype = BM_FACE; + itype = BM_VERTS_OF_FACE; + } + + + trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__); - BM_ITER_ELEM (ele, &iter, eve, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { - return ele; + vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__); + /* we shouldn't need this, but with incorrect selection flushing + * its possible we have a selected vertex thats not in a face, for now best not crash in that case. */ + fill_vn_i(vert_map, bm->totvert, -1); + + EDBM_index_arrays_ensure(em, htype); + ele_array = (htype == BM_FACE) ? (void **)em->face_index : (void **)em->edge_index; + + BM_mesh_elem_index_ensure(bm, BM_VERT); + + /* may be an edge OR a face array */ + for (i = 0; i < group_tot; i++) { + BMEditSelection ese = {0}; + + const int fg_sta = group_index[i][0]; + const int fg_len = group_index[i][1]; + float co[3], no[3], tangent[3]; + int j; + + zero_v3(co); + zero_v3(no); + zero_v3(tangent); + + ese.htype = htype; + + /* loop on each face in this group: + * - assign r_vert_map + * - calculate (co, no) + */ + for (j = 0; j < fg_len; j++) { + float tmp_co[3], tmp_no[3], tmp_tangent[3]; + + ese.ele = ele_array[groups_array[fg_sta + j]]; + + BM_editselection_center(&ese, tmp_co); + BM_editselection_normal(&ese, tmp_no); + BM_editselection_plane(&ese, tmp_tangent); + + add_v3_v3(co, tmp_co); + add_v3_v3(no, tmp_no); + add_v3_v3(tangent, tmp_tangent); + + { + /* setup vertex map */ + BMIter iter; + BMVert *v; + + /* connected edge-verts */ + BM_ITER_ELEM (v, &iter, ese.ele, itype) { + vert_map[BM_elem_index_get(v)] = i; + } + } + } + + mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len); + + if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) { + /* pass */ + } + else { + normalize_v3(no); + axis_dominant_v3_to_m3(trans_islands[i].axismtx, no); + invert_m3(trans_islands[i].axismtx); } } - return NULL; + + MEM_freeN(groups_array); + MEM_freeN(group_index); + + *r_island_tot = group_tot; + *r_island_vert_map = vert_map; + + return trans_islands; } /* way to overwrite what data is edited with transform */ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx, - BMEditMesh *em, BMVert *eve, float *bweight) + BMEditMesh *em, BMVert *eve, float *bweight, + struct TransIslandData *v_island) { BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0); @@ -1951,40 +2046,20 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx //else td->loc = eve->co; copy_v3_v3(td->iloc, td->loc); - copy_v3_v3(td->center, td->loc); - if (t->around == V3D_LOCAL) { - BMElem *ele; - bool is_axismat_set = false; - - if (em->selectmode & (SCE_SELECT_FACE | SCE_SELECT_EDGE) && - (ele = ((em->selectmode & SCE_SELECT_FACE) ? - bm_vert_single_select_face(eve) : - bm_vert_single_select_edge(eve)))) - { - float normal[3], tangent[3]; - - BMEditSelection ese; - ese.next = ese.prev = NULL; - ese.ele = ele; - ese.htype = ele->head.htype; - - BM_editselection_center(&ese, td->center); - BM_editselection_normal(&ese, normal); - BM_editselection_plane(&ese, tangent); - - if (createSpaceNormalTangent(td->axismtx, normal, tangent)) { - is_axismat_set = true; - } - } + if (v_island) { + copy_v3_v3(td->center, v_island->co); + copy_m3_m3(td->axismtx, v_island->axismtx); + } + else if (t->around == V3D_LOCAL) { + copy_v3_v3(td->center, td->loc); - /* for verts or fallback when createSpaceNormalTangent fails */ - if (is_axismat_set == false) { - axis_dominant_v3_to_m3(td->axismtx, eve->no); - invert_m3(td->axismtx); - } + axis_dominant_v3_to_m3(td->axismtx, eve->no); + invert_m3(td->axismtx); } else { + copy_v3_v3(td->center, td->loc); + /* Setting normals */ copy_v3_v3(td->axismtx[2], eve->no); td->axismtx[0][0] = @@ -2021,7 +2096,6 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx static void createTransEditVerts(TransInfo *t) { - ToolSettings *ts = t->scene->toolsettings; TransData *tob = NULL; TransDataExtension *tx = NULL; BMEditMesh *em = BKE_editmesh_from_object(t->obedit); @@ -2036,12 +2110,12 @@ static void createTransEditVerts(TransInfo *t) int count = 0, countsel = 0, a, totleft; int propmode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; int mirror = 0; - short selectmode = ts->selectmode; int cd_vert_bweight_offset = -1; bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0; - /* BMESH_TODO, writing into the index values is BAD!, means we cant - * use the values for vertex mirror - campbell */ + struct TransIslandData *island_info = NULL; + int island_info_tot; + int *island_vert_map = NULL; if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_begin(em, 0, false, (t->flag & T_PROP_EDIT) == 0, use_topology); @@ -2050,17 +2124,17 @@ static void createTransEditVerts(TransInfo *t) /* quick check if we can transform */ /* note: in prop mode we need at least 1 selected */ - if (selectmode & SCE_SELECT_VERTEX) { + if (em->selectmode & SCE_SELECT_VERTEX) { if (bm->totvertsel == 0) { goto cleanup; } } - else if (selectmode & SCE_SELECT_EDGE) { + else if (em->selectmode & SCE_SELECT_EDGE) { if (bm->totvertsel == 0 || bm->totedgesel == 0) { goto cleanup; } } - else if (selectmode & SCE_SELECT_FACE) { + else if (em->selectmode & SCE_SELECT_FACE) { if (bm->totvertsel == 0 || bm->totfacesel == 0) { goto cleanup; } @@ -2112,6 +2186,13 @@ static void createTransEditVerts(TransInfo *t) editmesh_set_connectivity_distance(em->bm, mtx, dists); } + if (t->around == V3D_LOCAL) { + island_info = editmesh_islands_info_calc(em, &island_info_tot, &island_vert_map); + } + + /* BMESH_TODO, crazy-space writing into the index values is BAD!, means we cant + * use the values for vertex mirror - campbell */ + /* detect CrazySpace [tm] */ if (modifiers_getCageIndex(t->scene, t->obedit, NULL, 1) >= 0) { if (modifiers_isCorrectableDeformed(t->obedit)) { @@ -2151,9 +2232,11 @@ static void createTransEditVerts(TransInfo *t) BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, a) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { if (propmode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { + struct TransIslandData *v_island = (island_info && island_vert_map[a] != -1) ? + &island_info[island_vert_map[a]] : NULL; float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; - - VertsToTransData(t, tob, tx, em, eve, bweight); + + VertsToTransData(t, tob, tx, em, eve, bweight, v_island); if (tx) tx++; @@ -2213,6 +2296,11 @@ static void createTransEditVerts(TransInfo *t) } } + if (island_info) { + MEM_freeN(island_info); + MEM_freeN(island_vert_map); + } + if (mirror != 0) { tob = t->data; for (a = 0; a < t->total; a++, tob++) { @@ -2233,7 +2321,6 @@ cleanup: if (t->flag & T_MIRROR) { EDBM_verts_mirror_cache_end(em); - mirror = 1; } } |