Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2020-01-13 20:12:12 +0300
committerHans Goudey <h.goudey@me.com>2020-01-13 20:12:12 +0300
commitc56526d8b68abdd4feb0367c716e713966b8de0f (patch)
treee7f95f0fb2198142f45d00d8be340259c0646ddb /source/blender/bmesh
parent60c6a74ce1d3664130848d7b278d0fd1a45037be (diff)
Fix T71329: Bevel: Don't drop offsets to 'in plane' faces
offset_meet creates offset lines that can't be directly intersected, so the average of the points on each offset line is 'dropped' onto the faces around the beveled vertex, which can depend on where the loop starts. This fix skips faces with the same normals as the "in plane" faces from build_boundary. Reviewed By: howardt Differential Revision: https://developer.blender.org/D6521
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c270
1 files changed, 141 insertions, 129 deletions
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 9cc645f7a3a..07e159b3241 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -994,23 +994,31 @@ static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1,
return (ang11 - ang1co > -BEVEL_EPSILON_ANG);
}
-/*
+/**
* 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
* the bevel vertex, e1 precedes e2 in CCW order.
- * Except: if edges_between is true, there are edges between e1 and e2 in CCW order so they
- * don't share a common face. We want the meeting point to be on an existing face so it
- * should be dropped onto one of the intermediate faces, if possible.
* Offset edge is on right of both edges, where e1 enters v and e2 leave it.
* When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2),
- * but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may
- * lead to different offsets) then meeting point can be found be intersecting offset lines.
+ * but if the offsets are not equal (we allow for because the bevel modifier has edge weights that
+ * may lead to different offsets) then the meeting point can be found by intersecting offset lines.
* If making the meeting point significantly changes the left or right offset from the user spec,
* record the change in offset_l (or offset_r); later we can tell that a change has happened
* because the offset will differ from its original value in offset_l_spec (or offset_r_spec).
+ *
+ * \param edges_between If this is true, there are edges between e1 and e2 in CCW order so they
+ * don't share a common face. We want the meeting point to be on an existing face so it
+ * should be dropped onto one of the intermediate faces, if possible.
+ * \param e_in_plane If we need to drop from the calculated offset lines to one of the faces,
+ * we don't want to drop onto the 'in plane' face, so if this is not null skip this edge's faces.
*/
-static void offset_meet(
- EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, bool edges_between, float meetco[3])
+static void offset_meet(EdgeHalf *e1,
+ EdgeHalf *e2,
+ BMVert *v,
+ BMFace *f,
+ bool edges_between,
+ float meetco[3],
+ const EdgeHalf *e_in_plane)
{
float dir1[3], dir2[3], dir1n[3], dir2p[3], norm_v[3], norm_v1[3], norm_v2[3];
float norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3];
@@ -1018,10 +1026,10 @@ static void offset_meet(
float ang, d;
BMVert *closer_v;
EdgeHalf *e, *e1next, *e2prev;
- BMFace *ff;
+ BMFace *fnext;
int isect_kind;
- /* get direction vectors for two offset lines */
+ /* 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);
@@ -1032,20 +1040,20 @@ static void offset_meet(
sub_v3_v3v3(dir2p, v->co, BM_edge_other_vert(e2prev->e, v)->co);
}
else {
- /* shup up 'maybe unused' warnings */
+ /* Shut up 'maybe unused' warnings. */
zero_v3(dir1n);
zero_v3(dir2p);
}
ang = angle_v3v3(dir1, dir2);
if (ang < BEVEL_EPSILON_ANG) {
- /* special case: e1 and e2 are parallel; put offset point perp to both, from v.
+ /* Special case: e1 and e2 are parallel; put offset point perp to both, from v.
* need to find a suitable plane.
- * this code used to just use offset and dir1, but that makes for visible errors
+ * This code used to just use offset and dir1, but that makes for visible errors
* on a circle with > 200 sides, which trips this "nearly perp" code (see T61214).
* so use the average of the two, and the offset formula for angle bisector.
- * if offsets are different, we're out of luck:
- * use the max of the two (so get consistent looking results if the same situation
+ * If offsets are different, we're out of luck:
+ * Use the max of the two (so get consistent looking results if the same situation
* arises elsewhere in the object but with opposite roles for e1 and e2 */
if (f) {
copy_v3_v3(norm_v, f->no);
@@ -1063,23 +1071,21 @@ static void offset_meet(
copy_v3_v3(meetco, off1a);
}
else if (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG) {
- /* 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. */
+ /* 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. */
d = max_ff(e1->offset_r, e2->offset_l);
slide_dist(e2, v, d, meetco);
}
else {
- /* Get normal to plane where meet point should be,
- * using cross product instead of f->no in case f is non-planar.
- * Except: sometimes locally there can be a small angle
- * between dir1 and dir2 that leads to a normal that is actually almost
- * perpendicular to the face normal; in this case it looks wrong to use
- * the local (cross-product) normal, so use the face normal if the angle
- * between dir1 and dir2 is smallish.
+ /* Get normal to plane where meet point should be, using cross product instead of f->no
+ * in case f is non-planar.
+ * Except: sometimes locally there can be a small angle between dir1 and dir2 that leads
+ * to a normal that is actually almost perpendicular to the face normal;
+ * in this case it looks wrong to use the local (cross-product) normal,
+ * so use the face normal if the angle between dir1 and dir2 is smallish.
* If e1-v-e2 is a reflex angle (viewed from vertex normal side), need to flip.
- * Use f->no to figure out which side to look at angle from, as even if
- * f is non-planar, will be more accurate than vertex normal */
+ * Use f->no to figure out which side to look at angle from, as even if f is non-planar,
+ * will be more accurate than vertex normal. */
if (f && ang < BEVEL_SMALL_ANG) {
copy_v3_v3(norm_v1, f->no);
copy_v3_v3(norm_v2, f->no);
@@ -1093,7 +1099,7 @@ static void offset_meet(
copy_v3_v3(norm_v2, norm_v1);
}
else {
- /* separate faces; get face norms at corners for each separately */
+ /* Separate faces; get face norms at corners for each separately. */
cross_v3_v3v3(norm_v1, dir1n, dir1);
normalize_v3(norm_v1);
f = e1->fnext;
@@ -1108,13 +1114,13 @@ static void offset_meet(
}
}
- /* get vectors perp to each edge, perp to norm_v, and pointing into face */
+ /* Get vectors perp to each edge, perp to norm_v, and pointing into face. */
cross_v3_v3v3(norm_perp1, dir1, norm_v1);
cross_v3_v3v3(norm_perp2, dir2, norm_v2);
normalize_v3(norm_perp1);
normalize_v3(norm_perp2);
- /* get points that are offset distances from each line, then another point on each line */
+ /* Get points that are offset distances from each line, then another point on each line. */
copy_v3_v3(off1a, v->co);
madd_v3_v3fl(off1a, norm_perp1, e1->offset_r);
add_v3_v3v3(off1b, off1a, dir1);
@@ -1122,18 +1128,17 @@ static void offset_meet(
madd_v3_v3fl(off2a, norm_perp2, e2->offset_l);
add_v3_v3v3(off2b, off2a, dir2);
- /* intersect the lines */
+ /* Intersect the offset lines. */
isect_kind = isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2);
if (isect_kind == 0) {
- /* lines are collinear: we already tested for this, but this used a different epsilon */
- copy_v3_v3(meetco, off1a); /* just to do something */
+ /* Lines are collinear: we already tested for this, but this used a different epsilon. */
+ copy_v3_v3(meetco, off1a); /* Just to do something. */
}
else {
/* The lines intersect, but is it at a reasonable place?
- * One problem to check: if one of the offsets is 0, then don't
- * want an intersection that is outside that edge itself.
- * This can happen if angle between them is > 180 degrees,
- * or if the offset amount is > the edge length*/
+ * One problem to check: if one of the offsets is 0, then don't want an intersection
+ * that is outside that edge itself. This can happen if angle between them is > 180 degrees,
+ * or if the offset amount is > the edge length. */
if (e1->offset_r == 0.0f && is_outside_edge(e1, meetco, &closer_v)) {
copy_v3_v3(meetco, closer_v->co);
}
@@ -1141,19 +1146,26 @@ static void offset_meet(
copy_v3_v3(meetco, closer_v->co);
}
if (edges_between && e1->offset_r > 0.0f && e2->offset_l > 0.0f) {
- /* Try to drop meetco to a face between e1 and e2 */
+ /* Try to drop meetco to a face between e1 and e2. */
if (isect_kind == 2) {
- /* lines didn't meet in 3d: get average of meetco and isect2 */
+ /* Lines didn't meet in 3d: get average of meetco and isect2. */
mid_v3_v3v3(meetco, meetco, isect2);
}
for (e = e1; e != e2; e = e->next) {
- ff = e->fnext;
- if (!ff) {
+ fnext = e->fnext;
+ if (!fnext) {
continue;
}
- plane_from_point_normal_v3(plane, v->co, ff->no);
+ plane_from_point_normal_v3(plane, v->co, fnext->no);
closest_to_plane_normalized_v3(dropco, plane, meetco);
- if (point_between_edges(dropco, v, ff, e, e->next)) {
+ /* Don't drop to the faces next to the in plane edge. */
+ if (e_in_plane) {
+ ang = angle_v3v3(fnext->no, e_in_plane->fnext->no);
+ if ((fabsf(ang) < BEVEL_SMALL_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_SMALL_ANG)) {
+ continue;
+ }
+ }
+ if (point_between_edges(dropco, v, fnext, e, e->next)) {
copy_v3_v3(meetco, dropco);
break;
}
@@ -1163,8 +1175,7 @@ static void offset_meet(
}
}
-/* Chosen so that 1/sin(BEVEL_GOOD_ANGLE) is about 4,
- * giving that expansion factor to bevel width. */
+/* Chosen so 1/sin(BEVEL_GOOD_ANGLE) is about 4, giving that expansion factor to bevel width. */
#define BEVEL_GOOD_ANGLE 0.25f
/* Calculate the meeting point between e1 and e2 (one of which should have zero offsets),
@@ -1182,7 +1193,7 @@ static bool offset_meet_edge(
normalize_v3(dir1);
normalize_v3(dir2);
- /* find angle from dir1 to dir2 as viewed from vertex normal side */
+ /* Find angle from dir1 to dir2 as viewed from vertex normal side. */
ang = angle_normalized_v3v3(dir1, dir2);
if (fabsf(ang) < BEVEL_GOOD_ANGLE) {
if (r_angle) {
@@ -1192,7 +1203,7 @@ static bool offset_meet_edge(
}
cross_v3_v3v3(fno, dir1, dir2);
if (dot_v3v3(fno, v->no) < 0.0f) {
- ang = 2.0f * (float)M_PI - ang; /* angle is reflex */
+ ang = 2.0f * (float)M_PI - ang; /* Angle is reflex. */
if (r_angle) {
*r_angle = ang;
}
@@ -1219,7 +1230,7 @@ static bool offset_meet_edge(
}
/* Return true if it will look good to put the meeting point where offset_on_edge_between
- * would put it. This means that neither side sees a reflex angle */
+ * would put it. This means that neither side sees a reflex angle. */
static bool good_offset_on_edge_between(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, BMVert *v)
{
float ang;
@@ -1248,7 +1259,7 @@ static bool offset_on_edge_between(
if (ok1 && ok2) {
mid_v3_v3v3(meetco, meet1, meet2);
if (r_sinratio) {
- /* ang1 should not be 0, but be paranoid */
+ /* ang1 should not be 0, but be paranoid. */
*r_sinratio = (ang1 == 0.0f) ? 1.0f : sinf(ang2) / sinf(ang1);
}
retval = true;
@@ -1261,7 +1272,7 @@ static bool offset_on_edge_between(
}
else {
/* Neither offset line met emid.
- * This should only happen if all three lines are on top of each other */
+ * This should only happen if all three lines are on top of each other. */
slide_dist(emid, v, e1->offset_r, meetco);
}
@@ -1269,8 +1280,7 @@ static bool offset_on_edge_between(
}
/* Offset by e->offset in plane with normal plane_no, on left if left==true,
- * else on right. If no is NULL, choose an arbitrary plane different
- * from eh's direction. */
+ * else on right. If no is NULL, choose an arbitrary plane different from eh's direction. */
static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, float r[3])
{
float dir[3], no[3], fdir[3];
@@ -1303,7 +1313,7 @@ static void offset_in_plane(EdgeHalf *e, const float plane_no[3], bool left, flo
madd_v3_v3fl(r, fdir, left ? e->offset_l : e->offset_r);
}
-/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */
+/* 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])
{
float otherco[3];
@@ -1317,56 +1327,55 @@ static void project_to_edge(BMEdge *e, const float co_a[3], const float co_b[3],
}
/* If there is a bndv->ebev edge, find the mid control point if necessary.
- * It is the closest point on the beveled edge to the line segment between
- * bndv and bndv->next. */
+ * It is the closest point on the beveled edge to the line segment between bndv and bndv->next. */
static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
{
EdgeHalf *e;
Profile *pro;
- float co1[3], co2[3], co3[3], d1[3], d2[3];
+ float start[3], end[3], co3[3], d1[3], d2[3];
bool do_linear_interp;
- copy_v3_v3(co1, bndv->nv.co);
- copy_v3_v3(co2, bndv->next->nv.co);
+ copy_v3_v3(start, bndv->nv.co);
+ copy_v3_v3(end, bndv->next->nv.co);
pro = &bndv->profile;
e = bndv->ebev;
do_linear_interp = true;
if (e) {
do_linear_interp = false;
pro->super_r = bp->pro_super_r;
- /* projection direction is direction of the edge */
+ /* projection direction is direction of the edge. */
sub_v3_v3v3(pro->proj_dir, e->e->v1->co, e->e->v2->co);
if (e->is_rev) {
negate_v3(pro->proj_dir);
}
normalize_v3(pro->proj_dir);
- project_to_edge(e->e, co1, co2, pro->middle);
+ project_to_edge(e->e, start, end, pro->middle);
if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
- /* put arc endpoints on plane with normal proj_dir, containing middle */
- add_v3_v3v3(co3, co1, pro->proj_dir);
- if (!isect_line_plane_v3(pro->start, co1, co3, pro->middle, pro->proj_dir)) {
- /* shouldn't happen */
- copy_v3_v3(pro->start, co1);
+ /* Put arc endpoints on plane with normal proj_dir, containing middle. */
+ add_v3_v3v3(co3, start, pro->proj_dir);
+ if (!isect_line_plane_v3(pro->start, start, co3, pro->middle, pro->proj_dir)) {
+ /* Shouldn't happen. */
+ copy_v3_v3(pro->start, start);
}
- add_v3_v3v3(co3, co2, pro->proj_dir);
- if (!isect_line_plane_v3(pro->end, co2, co3, pro->middle, pro->proj_dir)) {
- /* shouldn't happen */
- copy_v3_v3(pro->end, co2);
+ add_v3_v3v3(co3, end, pro->proj_dir);
+ if (!isect_line_plane_v3(pro->end, end, co3, pro->middle, pro->proj_dir)) {
+ /* Shouldn't happen. */
+ copy_v3_v3(pro->end, end);
}
}
else {
- copy_v3_v3(pro->start, co1);
- copy_v3_v3(pro->end, co2);
+ copy_v3_v3(pro->start, start);
+ copy_v3_v3(pro->end, end);
}
- /* default plane to project onto is the one with triangle co1 - middle - co2 in it */
- sub_v3_v3v3(d1, pro->middle, co1);
- sub_v3_v3v3(d2, pro->middle, co2);
+ /* Default plane to project onto is the one with triangle start - middle - end in it. */
+ sub_v3_v3v3(d1, pro->middle, start);
+ sub_v3_v3v3(d2, pro->middle, end);
normalize_v3(d1);
normalize_v3(d2);
cross_v3_v3v3(pro->plane_no, d1, d2);
normalize_v3(pro->plane_no);
if (nearly_parallel(d1, d2)) {
- /* co1 - middle -co2 are collinear.
+ /* Start - middle - end are collinear.
* Should be case that beveled edge is coplanar with two boundary verts.
* We want to move the profile to that common plane, if possible.
* That makes the multi-segment bevels curve nicely in that plane, as users expect.
@@ -1380,8 +1389,8 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
}
else {
if (DEBUG_OLD_PROJ_TO_PERP_PLANE) {
- copy_v3_v3(pro->start, co1);
- copy_v3_v3(pro->end, co2);
+ copy_v3_v3(pro->start, start);
+ copy_v3_v3(pro->end, end);
}
if (DEBUG_OLD_FLAT_MID) {
copy_v3_v3(pro->middle, bv->v->co);
@@ -1389,7 +1398,7 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
else {
copy_v3_v3(pro->middle, bv->v->co);
if (e->prev->is_bev && e->next->is_bev && bv->selcount >= 3) {
- /* want mid at the meet point of next and prev offset edges */
+ /* Want mid at the meet point of next and prev offset edges. */
float d3[3], d4[3], co4[3], meetco[3], isect2[3];
int isect_kind;
@@ -1398,34 +1407,34 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
normalize_v3(d3);
normalize_v3(d4);
if (nearly_parallel(d3, d4)) {
- /* offset lines are collinear - want linear interpolation */
- mid_v3_v3v3(pro->middle, co1, co2);
+ /* Offset lines are collinear - want linear interpolation. */
+ mid_v3_v3v3(pro->middle, start, end);
do_linear_interp = true;
}
else {
- add_v3_v3v3(co3, co1, d3);
- add_v3_v3v3(co4, co2, d4);
- isect_kind = isect_line_line_v3(co1, co3, co2, co4, meetco, isect2);
+ add_v3_v3v3(co3, start, d3);
+ add_v3_v3v3(co4, end, d4);
+ isect_kind = isect_line_line_v3(start, co3, end, co4, meetco, isect2);
if (isect_kind != 0) {
copy_v3_v3(pro->middle, meetco);
}
else {
- /* offset lines don't intersect - want linear interpolation */
- mid_v3_v3v3(pro->middle, co1, co2);
+ /* Offset lines don't intersect - want linear interpolation. */
+ mid_v3_v3v3(pro->middle, start, end);
do_linear_interp = true;
}
}
}
}
- copy_v3_v3(pro->end, co2);
- sub_v3_v3v3(d1, pro->middle, co1);
+ copy_v3_v3(pro->end, end);
+ sub_v3_v3v3(d1, pro->middle, start);
normalize_v3(d1);
- sub_v3_v3v3(d2, pro->middle, co2);
+ sub_v3_v3v3(d2, pro->middle, end);
normalize_v3(d2);
cross_v3_v3v3(pro->plane_no, d1, d2);
normalize_v3(pro->plane_no);
if (nearly_parallel(d1, d2)) {
- /* whole profile is collinear with edge: just interpolate */
+ /* Whole profile is collinear with edge: just interpolate. */
do_linear_interp = true;
}
else {
@@ -1434,12 +1443,12 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
}
}
}
- copy_v3_v3(pro->plane_co, co1);
+ copy_v3_v3(pro->plane_co, start);
}
else if (bndv->is_arc_start) {
- /* assume pro->middle was alredy set */
- copy_v3_v3(pro->start, co1);
- copy_v3_v3(pro->end, co2);
+ /* Assume pro->middle was alredy set. */
+ copy_v3_v3(pro->start, start);
+ copy_v3_v3(pro->end, end);
pro->super_r = PRO_CIRCLE_R;
zero_v3(pro->plane_co);
zero_v3(pro->plane_no);
@@ -1448,10 +1457,10 @@ static void set_profile_params(BevelParams *bp, BevVert *bv, BoundVert *bndv)
}
if (do_linear_interp) {
pro->super_r = PRO_LINE_R;
- copy_v3_v3(pro->start, co1);
- copy_v3_v3(pro->end, co2);
- mid_v3_v3v3(pro->middle, co1, co2);
- /* won't use projection for this line profile */
+ copy_v3_v3(pro->start, start);
+ copy_v3_v3(pro->end, end);
+ mid_v3_v3v3(pro->middle, start, end);
+ /* Won't use projection for this line profile. */
zero_v3(pro->plane_co);
zero_v3(pro->plane_no);
zero_v3(pro->proj_dir);
@@ -2295,14 +2304,14 @@ static int count_bound_vert_seams(BevVert *bv)
return ans;
}
-/* Is e between two planes where angle between is 180? */
+/* Is e between two faces with a 180 degree angle between their normals? */
static bool eh_on_plane(EdgeHalf *e)
{
float dot;
if (e->fprev && e->fnext) {
dot = dot_v3v3(e->fprev->no, e->fnext->no);
- if (fabsf(dot) <= BEVEL_EPSILON_BIG || fabsf(dot - 1.0f) <= BEVEL_EPSILON_BIG) {
+ if (fabsf(dot + 1.0f) <= BEVEL_EPSILON_BIG || fabsf(dot - 1.0f) <= BEVEL_EPSILON_BIG) {
return true;
}
}
@@ -2422,7 +2431,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
* and join with the beveled edge to make a poly or adj mesh,
* Because e->prev has offset 0, offset_meet will put co on that edge. */
/* TODO: should do something else if angle between e and e->prev > 180 */
- offset_meet(e->prev, e, bv->v, e->fprev, false, co);
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
if (construct) {
bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = e->prev;
@@ -2434,7 +2443,7 @@ static void build_boundary_terminal_edge(BevelParams *bp,
adjust_bound_vert(e->leftv, co);
}
e = e->next;
- offset_meet(e->prev, e, bv->v, e->fprev, false, co);
+ offset_meet(e->prev, e, bv->v, e->fprev, false, co, NULL);
if (construct) {
bndv = add_new_bound_vert(mem_arena, vm, co);
bndv->efirst = e->prev;
@@ -2592,18 +2601,20 @@ static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *em
} while (v != vstart);
}
-/* Make a circular list of BoundVerts for bv, each of which has the coordinates
- * of a vertex on the boundary of the beveled vertex bv->v.
- * This may adjust some EdgeHalf widths, and there might have to be
- * a subsequent pass to make the widths as consistent as possible.
- * The first time through, construct will be true and we are making the BoundVerts
- * and setting up the BoundVert and EdgeHalf pointers appropriately.
- * For a width consistency path, we just recalculate the coordinates of the
- * BoundVerts. If the other ends have been (re)built already, then we
- * copy the offsets from there to match, else we use the ideal (user-specified)
- * widths.
- * Also, if construct, decide on the mesh pattern that will be used inside the boundary.
- * Doesn't make the actual BMVerts */
+/**
+ * Make a circular list of BoundVerts for bv, each of which has the coordinates of a vertex on the
+ * boundary of the beveled vertex bv->v. This may adjust some EdgeHalf widths, and there might have
+ * to be a subsequent pass to make the widths as consistent as possible.
+ * Doesn't make the actual BMVerts.
+ *
+ * For a width consistency pass, we just recalculate the coordinates of the BoundVerts. If the
+ * other ends have been (re)built already, then we copy the offsets from there to match, else we
+ * use the ideal (user-specified) widths.
+ *
+ * \param construct The first time through, construct will be true and we are making the BoundVerts
+ * and setting up the BoundVert and EdgeHalf pointers appropriately. Also, if construct, decide on
+ * the mesh pattern that will be used inside the boundary.
+ */
static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
{
MemArena *mem_arena = bp->mem_arena;
@@ -2614,7 +2625,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
int in_plane, not_in_plane, miter_outer, miter_inner;
int ang_kind;
- /* Current bevel does nothing if only one edge into a vertex */
+ /* Current bevel does nothing if only one edge into a vertex. */
if (bv->edgecount <= 1) {
return;
}
@@ -2626,21 +2637,21 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
vm = bv->vmesh;
- /* Find a beveled edge to be efirst */
+ /* Find a beveled edge to be efirst. */
e = efirst = next_bev(bv, NULL);
BLI_assert(e->is_bev);
if (bv->selcount == 1) {
- /* Special case: only one beveled edge in */
+ /* Special case: only one beveled edge in. */
build_boundary_terminal_edge(bp, bv, efirst, construct);
return;
}
- /* Special miters outside only for 3 or more beveled edges */
+ /* Special miters outside only for 3 or more beveled edges. */
miter_outer = (bv->selcount >= 3) ? bp->miter_outer : BEVEL_MITER_SHARP;
miter_inner = bp->miter_inner;
- /* keep track of the first beveled edge of an outside miter (there can be at most 1 per bv */
+ /* Keep track of the first beveled edge of an outside miter (there can be at most 1 per bv). */
emiter = NULL;
/* There is more than one beveled edge.
@@ -2650,14 +2661,13 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
do {
BLI_assert(e->is_bev);
eon = NULL;
- /* Make the BoundVert for the right side of e; other side will be made
- * when the beveled edge to the left of e is handled.
- * Analyze edges until next beveled edge.
- * They are either "in plane" (preceding and subsequent faces are coplanar) or not.
- * The "non-in-plane" edges affect the silhouette and we prefer to slide along one of those if
- * possible. */
- in_plane = not_in_plane = 0; /* Counts of in-plane / not-in-plane */
- enip = eip = NULL; /* representatives of each */
+ /* Make the BoundVert for the right side of e; the other side will be made when the beveled
+ * edge to the left of e is handled.
+ * Analyze edges until next beveled edge: They are either "in plane" (preceding and subsequent
+ * faces are coplanar) or not. The "non-in-plane" edges affect the silhouette and we prefer to
+ * slide along one of those if possible. */
+ in_plane = not_in_plane = 0; /* Counts of in-plane / not-in-plane. */
+ enip = eip = NULL; /* Representatives of each type. */
for (e2 = e->next; !e2->is_bev; e2 = e2->next) {
if (eh_on_plane(e2)) {
in_plane++;
@@ -2668,8 +2678,9 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
enip = e2;
}
}
+
if (in_plane == 0 && not_in_plane == 0) {
- offset_meet(e, e2, bv->v, e->fnext, false, co);
+ offset_meet(e, e2, bv->v, e->fnext, false, co, NULL);
}
else if (not_in_plane > 0) {
if (bp->loop_slide && not_in_plane == 1 && good_offset_on_edge_between(e, e2, enip, bv->v)) {
@@ -2678,7 +2689,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
else {
- offset_meet(e, e2, bv->v, NULL, true, co);
+ offset_meet(e, e2, bv->v, NULL, true, co, eip);
}
}
else {
@@ -2689,9 +2700,10 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
else {
- offset_meet(e, e2, bv->v, e->fnext, true, co);
+ offset_meet(e, e2, bv->v, e->fnext, true, co, eip);
}
}
+
if (construct) {
v = add_new_bound_vert(mem_arena, vm, co);
v->efirst = e;