[Bf-blender-cvs] [c56526d8b68] blender-v2.82-release: Fix T71329: Bevel: Don't drop offsets to 'in plane' faces

Hans Goudey noreply at git.blender.org
Mon Jan 13 18:14:39 CET 2020


Commit: c56526d8b68abdd4feb0367c716e713966b8de0f
Author: Hans Goudey
Date:   Mon Jan 13 12:12:12 2020 -0500
Branches: blender-v2.82-release
https://developer.blender.org/rBc56526d8b68abdd4feb0367c716e713966b8de0f

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

===================================================================

M	source/blender/bmesh/tools/bmesh_bevel.c

===================================================================

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,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list