BMesh: shrink/fatten faces-normals in face mode
nice for solid-modeling, gives better results for partial selections.
This commit is contained in:
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
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue