From 49289f31ffd2087b0ecc71f7100c8cb5cff413b5 Mon Sep 17 00:00:00 2001 From: Germano Cavalcante Date: Fri, 3 Apr 2020 11:07:58 -0300 Subject: Fix T74495: Shrink/Fatten gives strange results with Individual Origins The island `axismtx` is only necessary in some transform modes. In the case of `Shrink/Fatten`, the calculated `axismtx` brings an undesirable result. This commit rearrange the struct `TransIslandData` in order to calculate and reference only the arrays that will be used for each transform mode. Differential Revision: https://developer.blender.org/D7305 --- .../editors/transform/transform_convert_mesh.c | 135 ++++++++++++--------- 1 file changed, 79 insertions(+), 56 deletions(-) (limited to 'source') diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 22bba9544cd..7528f791130 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -61,8 +61,10 @@ /* when transforming islands */ struct TransIslandData { - float co[3]; - float axismtx[3][3]; + float (*center)[3]; + float (*axismtx)[3][3]; + int island_tot; + int *island_vert_map; }; /* -------------------------------------------------------------------- */ @@ -247,18 +249,19 @@ static void editmesh_set_connectivity_distance(BMesh *bm, } } -static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, - int *r_island_tot, - int **r_island_vert_map, - bool calc_single_islands) +static void editmesh_islands_info_calc(BMEditMesh *em, + const bool calc_single_islands, + const bool calc_island_axismtx, + struct TransIslandData *r_island_data) { BMesh *bm = em->bm; - struct TransIslandData *trans_islands; char htype; char itype; int i; /* group vars */ + float(*center)[3]; + float(*axismtx)[3][3] = NULL; int *groups_array; int(*group_index)[2]; int group_tot; @@ -283,7 +286,11 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, itype = BM_VERTS_OF_FACE; } - trans_islands = MEM_mallocN(sizeof(*trans_islands) * group_tot, __func__); + center = MEM_mallocN(sizeof(*center) * group_tot, __func__); + + if (calc_island_axismtx) { + axismtx = MEM_mallocN(sizeof(*axismtx) * group_tot, __func__); + } vert_map = MEM_mallocN(sizeof(*vert_map) * bm->totvert, __func__); /* we shouldn't need this, but with incorrect selection flushing @@ -311,7 +318,7 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, ese.htype = htype; - /* loop on each face in this group: + /* loop on each face or edge in this group: * - assign r_vert_map * - calculate (co, no) */ @@ -321,12 +328,14 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, 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); + + if (axismtx) { + BM_editselection_normal(&ese, tmp_no); + BM_editselection_plane(&ese, tmp_tangent); + add_v3_v3(no, tmp_no); + add_v3_v3(tangent, tmp_tangent); + } { /* setup vertex map */ @@ -340,18 +349,20 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, } } - mul_v3_v3fl(trans_islands[i].co, co, 1.0f / (float)fg_len); + mul_v3_v3fl(center[i], co, 1.0f / (float)fg_len); - if (createSpaceNormalTangent(trans_islands[i].axismtx, no, tangent)) { - /* pass */ - } - else { - if (normalize_v3(no) != 0.0f) { - axis_dominant_v3_to_m3(trans_islands[i].axismtx, no); - invert_m3(trans_islands[i].axismtx); + if (axismtx) { + if (createSpaceNormalTangent(axismtx[i], no, tangent)) { + /* pass */ } else { - unit_m3(trans_islands[i].axismtx); + if (normalize_v3(no) != 0.0f) { + axis_dominant_v3_to_m3(axismtx[i], no); + invert_m3(axismtx[i]); + } + else { + unit_m3(axismtx[i]); + } } } } @@ -372,22 +383,24 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, } if (group_tot_single != 0) { - trans_islands = MEM_reallocN(trans_islands, - sizeof(*trans_islands) * (group_tot + group_tot_single)); + center = MEM_reallocN(center, sizeof(*center) * (group_tot + group_tot_single)); + if (axismtx) { + axismtx = MEM_reallocN(axismtx, sizeof(*axismtx) * (group_tot + group_tot_single)); + } BM_ITER_MESH_INDEX (v, &viter, bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(v, BM_ELEM_SELECT) && (vert_map[i] == -1)) { - struct TransIslandData *v_island = &trans_islands[group_tot]; vert_map[i] = group_tot; + copy_v3_v3(center[group_tot], v->co); - copy_v3_v3(v_island->co, v->co); - - if (is_zero_v3(v->no) != 0.0f) { - axis_dominant_v3_to_m3(v_island->axismtx, v->no); - invert_m3(v_island->axismtx); - } - else { - unit_m3(v_island->axismtx); + if (axismtx) { + if (is_zero_v3(v->no) != 0.0f) { + axis_dominant_v3_to_m3(axismtx[group_tot], v->no); + invert_m3(axismtx[group_tot]); + } + else { + unit_m3(axismtx[group_tot]); + } } group_tot += 1; @@ -396,10 +409,10 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em, } } - *r_island_tot = group_tot; - *r_island_vert_map = vert_map; - - return trans_islands; + r_island_data->axismtx = axismtx; + r_island_data->center = center; + r_island_data->island_tot = group_tot; + r_island_data->island_vert_map = vert_map; } static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const float epsilon) @@ -567,7 +580,8 @@ static void VertsToTransData(TransInfo *t, BMEditMesh *em, BMVert *eve, float *bweight, - struct TransIslandData *v_island, + const struct TransIslandData *island_data, + const int island_index, const bool no_island_center) { float *no, _no[3]; @@ -589,14 +603,17 @@ static void VertsToTransData(TransInfo *t, no = eve->no; } - if (v_island) { + if (island_index != -1) { if (no_island_center) { copy_v3_v3(td->center, td->loc); } else { - copy_v3_v3(td->center, v_island->co); + copy_v3_v3(td->center, island_data->center[island_index]); } - copy_m3_m3(td->axismtx, v_island->axismtx); + } + + if ((island_index != -1) && island_data->axismtx) { + copy_m3_m3(td->axismtx, island_data->axismtx[island_index]); } else if (t->around == V3D_AROUND_LOCAL_ORIGINS) { copy_v3_v3(td->center, td->loc); @@ -654,9 +671,7 @@ void createTransEditVerts(TransInfo *t) const int prop_mode = (t->flag & T_PROP_EDIT) ? (t->flag & T_PROP_EDIT_ALL) : 0; int cd_vert_bweight_offset = -1; - struct TransIslandData *island_info = NULL; - int island_info_tot; - int *island_vert_map = NULL; + struct TransIslandData island_data = {NULL}; /* Snap rotation along normal needs a common axis for whole islands, * otherwise one get random crazy results, see T59104. @@ -758,8 +773,11 @@ void createTransEditVerts(TransInfo *t) (t->around == V3D_AROUND_LOCAL_ORIGINS) && (em->selectmode & SCE_SELECT_VERTEX)); - island_info = editmesh_islands_info_calc( - em, &island_info_tot, &island_vert_map, calc_single_islands); + /* The island axismtx is only necessary in some modes. + * TODO(Germano): Extend the list to exclude other modes. */ + const bool calc_island_axismtx = !ELEM(t->mode, TFM_SHRINKFATTEN); + + editmesh_islands_info_calc(em, calc_single_islands, calc_island_axismtx, &island_data); } /* detect CrazySpace [tm] */ @@ -809,21 +827,19 @@ void createTransEditVerts(TransInfo *t) continue; } if (prop_mode || BM_elem_flag_test(eve, BM_ELEM_SELECT)) { - struct TransIslandData *v_island = NULL; float *bweight = (cd_vert_bweight_offset != -1) ? BM_ELEM_CD_GET_VOID_P(eve, cd_vert_bweight_offset) : NULL; - if (island_info) { + int island_index = -1; + if (island_data.island_vert_map) { const int connected_index = (dists_index && dists_index[a] != -1) ? dists_index[a] : a; - v_island = (island_vert_map[connected_index] != -1) ? - &island_info[island_vert_map[connected_index]] : - NULL; + island_index = island_data.island_vert_map[connected_index]; } /* Do not use the island center in case we are using islands * only to get axis for snap/rotate to normal... */ - VertsToTransData(t, tob, tx, em, eve, bweight, v_island, is_snap_rotate); + VertsToTransData(t, tob, tx, em, eve, bweight, &island_data, island_index, is_snap_rotate); if (tx) { tx++; } @@ -889,9 +905,16 @@ void createTransEditVerts(TransInfo *t) } } - if (island_info) { - MEM_freeN(island_info); - MEM_freeN(island_vert_map); + if (island_data.center) { + MEM_freeN(island_data.center); + } + + if (island_data.axismtx) { + MEM_freeN(island_data.axismtx); + } + + if (island_data.island_vert_map) { + MEM_freeN(island_data.island_vert_map); } cleanup: -- cgit v1.2.3