BMesh: shrink/fatten faces-normals in face mode

nice for solid-modeling, gives better results for partial selections.
This commit is contained in:
Campbell Barton 2014-11-13 16:37:32 +01:00
parent 96ca64629d
commit 1ddfe6676d
Notes: blender-bot 2023-02-14 09:49:37 +01:00
Referenced by issue #42583, Shrink/Fatten Bug | Modeling, Edit Mode, Polygons
5 changed files with 58 additions and 7 deletions

View File

@ -422,6 +422,43 @@ void BM_edge_normals_update(BMEdge *e)
BM_vert_normal_update(e->v2);
}
bool BM_vert_normal_update_ex(BMVert *v, const char hflag, float r_no[3])
{
/* TODO, we can normalize each edge only once, then compare with previous edge */
BMIter liter;
BMLoop *l;
int len = 0;
zero_v3(r_no);
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
if (BM_elem_flag_test(l->f, hflag)) {
float vec1[3], vec2[3], fac;
/* Same calculation used in BM_mesh_normals_update */
sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
sub_v3_v3v3(vec2, l->next->v->co, l->v->co);
normalize_v3(vec1);
normalize_v3(vec2);
fac = saacos(-dot_v3v3(vec1, vec2));
madd_v3_v3fl(r_no, l->f->no, fac);
len++;
}
}
if (len) {
normalize_v3(r_no);
return true;
}
else {
return false;
}
}
/**
* update a vert normal (but not the faces incident on it)
*/
@ -431,12 +468,13 @@ void BM_vert_normal_update(BMVert *v)
BMIter liter;
BMLoop *l;
float vec1[3], vec2[3], fac;
int len = 0;
zero_v3(v->no);
BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
float vec1[3], vec2[3], fac;
/* Same calculation used in BM_mesh_normals_update */
sub_v3_v3v3(vec1, l->v->co, l->prev->v->co);
sub_v3_v3v3(vec2, l->next->v->co, l->v->co);

View File

@ -49,6 +49,7 @@ void BM_face_normal_update(BMFace *f) ATTR_NONNULL();
void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL();
bool BM_vert_normal_update_ex(BMVert *v, const char hflag, float r_no[3]);
void BM_vert_normal_update(BMVert *v) ATTR_NONNULL();
void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL();

View File

@ -1373,7 +1373,7 @@ float BM_vert_calc_shell_factor(BMVert *v)
}
/* alternate version of #BM_vert_calc_shell_factor which only
* uses 'hflag' faces, but falls back to all if none found. */
float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag)
float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hflag)
{
BMIter iter;
BMLoop *l;
@ -1384,7 +1384,7 @@ float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag)
BM_ITER_ELEM (l, &iter, v, BM_LOOPS_OF_VERT) {
if (BM_elem_flag_test(l->f, hflag)) { /* <-- main difference to BM_vert_calc_shell_factor! */
const float face_angle = BM_loop_calc_face_angle(l);
accum_shell += shell_v3v3_normalized_to_dist(v->no, l->f->no) * face_angle;
accum_shell += shell_v3v3_normalized_to_dist(no, l->f->no) * face_angle;
accum_angle += face_angle;
tot_sel++;
}

View File

@ -97,7 +97,7 @@ void BM_edge_calc_face_tangent(const BMEdge *e, const BMLoop *e_loop, float r
float BM_vert_calc_edge_angle(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_vert_calc_shell_factor(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_vert_calc_shell_factor_ex(BMVert *v, const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_vert_calc_shell_factor_ex(BMVert *v, const float no[3], const char hflag) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
float BM_vert_calc_mean_tagged_edge_length(BMVert *v) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
BMLoop *BM_face_find_shortest_loop(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();

View File

@ -2167,6 +2167,7 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
BMEditMesh *em, BMVert *eve, float *bweight,
struct TransIslandData *v_island)
{
float *no, _no[3];
BLI_assert(BM_elem_flag_test(eve, BM_ELEM_HIDDEN) == 0);
td->flag = 0;
@ -2176,19 +2177,30 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
td->loc = eve->co;
copy_v3_v3(td->iloc, td->loc);
if ((t->mode == TFM_SHRINKFATTEN) &&
(em->selectmode & SCE_SELECT_FACE) &&
BM_elem_flag_test(eve, BM_ELEM_SELECT) &&
(BM_vert_normal_update_ex(eve, BM_ELEM_SELECT, _no)))
{
no = _no;
}
else {
no = eve->no;
}
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);
createSpaceNormal(td->axismtx, eve->no);
createSpaceNormal(td->axismtx, no);
}
else {
copy_v3_v3(td->center, td->loc);
/* Setting normals */
copy_v3_v3(td->axismtx[2], eve->no);
copy_v3_v3(td->axismtx[2], no);
td->axismtx[0][0] =
td->axismtx[0][1] =
td->axismtx[0][2] =
@ -2217,7 +2229,7 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx
}
else if (t->mode == TFM_SHRINKFATTEN) {
td->ext = tx;
tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, BM_ELEM_SELECT);
tx->isize[0] = BM_vert_calc_shell_factor_ex(eve, no, BM_ELEM_SELECT);
}
}