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
This commit is contained in:
Germano Cavalcante 2020-04-03 11:07:58 -03:00
parent d8b0b8d3db
commit 49289f31ff
Notes: blender-bot 2023-02-14 10:18:56 +01:00
Referenced by issue #74495, Shrink/Fatten gives strange results when Transform Pivot is Individual Origins
1 changed files with 79 additions and 56 deletions

View File

@ -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: