diff options
author | Howard Trickey <howard.trickey@gmail.com> | 2013-05-24 17:13:05 +0400 |
---|---|---|
committer | Howard Trickey <howard.trickey@gmail.com> | 2013-05-24 17:13:05 +0400 |
commit | 834c6ca316a2f3a0da214952e09adc1c2335e47b (patch) | |
tree | a14d60130f1c73455e83e80691a00683cec6267a /source | |
parent | 1140051e5692a4f8bf52b754d26ff2779bbce3ec (diff) |
Fix bug #35450, bevel make large spikes sometimes.
Needed special case for when beveled edge is
antiparallel to an adjacent edge.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/bmesh/tools/bmesh_bevel.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index a0fbaaed810..cac63b831b8 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -310,6 +310,19 @@ static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3 return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep); } +/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */ +static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) +{ + float dir[3], len; + + sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co); + len = normalize_v3(dir); + if (d > len) + d = len - (float)(50.0 * BEVEL_EPSILON_D); + copy_v3_v3(slideco, v->co); + madd_v3_v3fl(slideco, dir, -d); +} + /* * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco. * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of @@ -324,13 +337,14 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, int on_right, float meetco[3]) { float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3], - off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], ang; /* get direction vectors for two offset lines */ sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); - if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) { + ang = angle_v3v3(dir1, dir2); + if (ang < 100.0f * BEVEL_EPSILON) { /* special case: e1 and e2 are parallel; put offset point perp to both, from v. * need to find a suitable plane. * if offsets are different, we're out of luck: just use e1->offset */ @@ -344,6 +358,12 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, madd_v3_v3fl(off1a, norm_perp1, e1->offset); copy_v3_v3(meetco, off1a); } + else if (fabs(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) { + /* special case e1 and e2 are antiparallel, so bevel is into + * a zero-area face. Just make the offset point on the + * common line, at offset distance from v. */ + slide_dist(e2, v, e2->offset, meetco); + } else { /* get normal to plane where meet point should be */ cross_v3_v3v3(norm_v, dir2, dir1); @@ -391,7 +411,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, { float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], co[3], - f1no[3], f2no[3]; + f1no[3], f2no[3], ang; int iret; /* get direction vectors for two offset lines */ @@ -416,10 +436,14 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, madd_v3_v3fl(off2a, norm_perp2, e2->offset); add_v3_v3v3(off2b, off2a, dir2); - if (angle_v3v3(dir1, dir2) < 100.0f * BEVEL_EPSILON) { + ang = angle_v3v3(dir1, dir2); + if (ang < 100.0f * BEVEL_EPSILON) { /* lines are parallel; off1a is a good meet point */ copy_v3_v3(meetco, off1a); } + else if (fabs(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) { + slide_dist(e2, v, e2->offset, meetco); + } else { iret = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2); if (iret == 0) { @@ -469,19 +493,6 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], int left, floa madd_v3_v3fl(r, fdir, e->offset); } -/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */ -static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) -{ - float dir[3], len; - - sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co); - len = normalize_v3(dir); - if (d > len) - d = len - (float)(50.0 * BEVEL_EPSILON_D); - copy_v3_v3(slideco, v->co); - madd_v3_v3fl(slideco, dir, -d); -} - /* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */ static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3], float projco[3]) { |