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:
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;