From 8c2b5ffb118d065af4d34ff84f1493d914d948db Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Thu, 12 Jun 2014 10:22:10 -0400 Subject: Fix Bevel bug T39746, small scale gives flat profile. With very small meshes or very small bevel amounts, the bevel profile would be flat even if a round one was requested. Problem was that the code was checking the length of a cross product for closeness to zero to test coplanarity. Needed to normalize things before making that test to account for scale. --- source/blender/bmesh/tools/bmesh_bevel.c | 34 ++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'source') diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 9f9b3de6756..45ebe144b5e 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -52,6 +52,7 @@ #define BEVEL_EPSILON_D 1e-6 #define BEVEL_EPSILON 1e-6f #define BEVEL_EPSILON_SQ 1e-12f +#define BEVEL_EPSILON_BIG 1e-4 /* happens far too often, uncomment for development */ // #define BEVEL_ASSERT_PROJECT @@ -585,7 +586,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); ang = angle_v3v3(dir1, dir2); - if (ang < 100.0f * BEVEL_EPSILON) { + if (ang < BEVEL_EPSILON_BIG) { /* 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: @@ -606,7 +607,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, float e2->offset_l = d; copy_v3_v3(meetco, off1a); } - else if (fabsf(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) { + else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_BIG) { /* 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. */ @@ -811,11 +812,11 @@ static void offset_in_two_planes(BevelParams *bp, EdgeHalf *e1, EdgeHalf *e2, Ed add_v3_v3v3(off2b, off2a, dir2); ang = angle_v3v3(dir1, dir2); - if (ang < 100.0f * BEVEL_EPSILON) { + if (ang < BEVEL_EPSILON_BIG) { /* lines are parallel; put intersection on emid */ offset_on_edge_between(bp, e1, e2, emid, v, meetco); } - else if (fabsf(ang - (float)M_PI) < 100.0f * BEVEL_EPSILON) { + else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_BIG) { slide_dist(e2, v, e2->offset_l, meetco); d = dist_to_line_v3(meetco, v->co, BM_edge_other_vert(e1->e, v)->co); if (fabsf(d - e1->offset_r) > BEVEL_EPSILON) @@ -892,7 +893,7 @@ static void set_profile_params(BevelParams *bp, BoundVert *bndv) { EdgeHalf *e; Profile *pro; - float co1[3], co2[3], co3[3], d1[3], d2[3]; + float co1[3], co2[3], co3[3], d1[3], d2[3], d3[3], l; bool do_linear_interp; copy_v3_v3(co1, bndv->nv.co); @@ -905,6 +906,7 @@ static void set_profile_params(BevelParams *bp, BoundVert *bndv) pro->super_r = bp->pro_super_r; /* projection direction is direction of the edge */ sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co); + normalize_v3(pro->proj_dir); project_to_edge(e->e, co1, co2, pro->midco); /* put arc endpoints on plane with normal proj_dir, containing midco */ add_v3_v3v3(co3, co1, pro->proj_dir); @@ -920,12 +922,18 @@ static void set_profile_params(BevelParams *bp, BoundVert *bndv) /* default plane to project onto is the one with triangle co1 - midco - co2 in it */ sub_v3_v3v3(d1, pro->midco, co1); sub_v3_v3v3(d2, pro->midco, co2); + normalize_v3(d1); + normalize_v3(d2); cross_v3_v3v3(pro->plane_no, d1, d2); - if (normalize_v3(pro->plane_no) < BEVEL_EPSILON) { - /* co1 - midco -co2 are collinear - project onto that plane */ - cross_v3_v3v3(co3, d1, pro->proj_dir); - cross_v3_v3v3(pro->plane_no, d1, co3); - if (normalize_v3(pro->plane_no) < BEVEL_EPSILON) { + l = normalize_v3(pro->plane_no); + if (l <= BEVEL_EPSILON_BIG) { + /* co1 - midco -co2 are collinear - project plane that contains that line + * and is perpendicular to the plane containing it and the beveled edge */ + cross_v3_v3v3(d3, d1, pro->proj_dir); + normalize_v3(d3); + cross_v3_v3v3(pro->plane_no, d1, d3); + l = normalize_v3(pro->plane_no); + if (l <= BEVEL_EPSILON_BIG) { /* whole profile is collinear with edge: just interpolate */ do_linear_interp = true; } @@ -958,9 +966,9 @@ static void move_profile_plane(BoundVert *bndv, EdgeHalf *e1, EdgeHalf *e2) sub_v3_v3v3(d2, e2->e->v1->co, e2->e->v2->co); cross_v3_v3v3(no, d1, d2); cross_v3_v3v3(no2, d1, bndv->profile.proj_dir); - if (normalize_v3(no) > BEVEL_EPSILON && normalize_v3(no2) > BEVEL_EPSILON) { + if (normalize_v3(no) > BEVEL_EPSILON_BIG && normalize_v3(no2) > BEVEL_EPSILON_BIG) { dot = fabsf(dot_v3v3(no, no2)); - if (fabsf(dot - 1.0f) > BEVEL_EPSILON) + if (fabsf(dot - 1.0f) > BEVEL_EPSILON_BIG) copy_v3_v3(bndv->profile.plane_no, no); } } @@ -1700,7 +1708,7 @@ static BoundVert *pipe_test(BevVert *bv) sub_v3_v3v3(dir3, BM_edge_other_vert(v3->ebev->e, bv->v)->co, bv->v->co); normalize_v3(dir1); normalize_v3(dir3); - if (angle_v3v3(dir1, dir3) < 100.0f * BEVEL_EPSILON) { + if (angle_v3v3(dir1, dir3) < BEVEL_EPSILON_BIG) { epipe = v1->ebev; break; } -- cgit v1.2.3