[Bf-blender-cvs] [1a5027449aa] master: Fix proportional connected not working with loose edges due to hidden geometry

Pablo Dobarro noreply at git.blender.org
Mon Feb 22 13:59:09 CET 2021


Commit: 1a5027449aafc55c571ad125fd2c81f22a3fc42a
Author: Pablo Dobarro
Date:   Mon Feb 22 12:24:22 2021 +0100
Branches: master
https://developer.blender.org/rB1a5027449aafc55c571ad125fd2c81f22a3fc42a

Fix proportional connected not working with loose edges due to hidden geometry

This was introduced in the new geodesic distances algorithm for proportional
editing. When all faces of an edge are hidden, that edge should be considered
as loose geometry.

Initial patch by Pablo with modifications by Brecht.

Differential Revision: https://developer.blender.org/D10488

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

M	source/blender/bmesh/bmesh_class.h
M	source/blender/editors/transform/transform_convert_mesh.c

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

diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h
index 65f3d8bbad3..7cbad1ed069 100644
--- a/source/blender/bmesh/bmesh_class.h
+++ b/source/blender/bmesh/bmesh_class.h
@@ -373,7 +373,8 @@ enum {
   BM_ELEM_DRAW = (1 << 5), /* edge display */
 
   /* spare tag, assumed dirty, use define in each function to name based on use */
-  // _BM_ELEM_TAG_ALT = (1 << 6),  // UNUSED
+  BM_ELEM_TAG_ALT = (1 << 6),
+
   /**
    * For low level internal API tagging,
    * since tools may want to tag verts and not have functions clobber them.
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 5e2eca13f90..7270763c4e4 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -306,6 +306,24 @@ static bool bmesh_test_dist_add(BMVert *v0,
   return false;
 }
 
+static bool bmesh_test_loose_edge(BMEdge *edge)
+{
+  /* Actual loose edge. */
+  if (edge->l == NULL) {
+    return true;
+  }
+
+  /* Loose edge due to hidden adjacent faces. */
+  BMIter iter;
+  BMFace *face;
+  BM_ITER_ELEM (face, &iter, edge, BM_FACES_OF_EDGE) {
+    if (BM_elem_flag_test(face, BM_ELEM_HIDDEN) == 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
 /**
  * \param mtx: Measure distance in this space.
  * \param dists: Store the closest connected distance to selected vertices.
@@ -319,6 +337,9 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
   BLI_LINKSTACK_DECLARE(queue, BMEdge *);
 
   /* any BM_ELEM_TAG'd edge is in 'queue_next', so we don't add in twice */
+  const int tag_queued = BM_ELEM_TAG;
+  const int tag_loose = BM_ELEM_TAG_ALT;
+
   BLI_LINKSTACK_DECLARE(queue_next, BMEdge *);
 
   BLI_LINKSTACK_INIT(queue);
@@ -366,7 +387,8 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
       if (dists[i1] != FLT_MAX || dists[i2] != FLT_MAX) {
         BLI_LINKSTACK_PUSH(queue, e);
       }
-      BM_elem_flag_disable(e, BM_ELEM_TAG);
+      BM_elem_flag_disable(e, tag_queued);
+      BM_elem_flag_set(e, tag_loose, bmesh_test_loose_edge(e));
     }
   }
 
@@ -379,7 +401,7 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
       int i1 = BM_elem_index_get(v1);
       int i2 = BM_elem_index_get(v2);
 
-      if (e->l == NULL || (dists[i1] == FLT_MAX || dists[i2] == FLT_MAX)) {
+      if (BM_elem_flag_test(e, tag_loose) || (dists[i1] == FLT_MAX || dists[i2] == FLT_MAX)) {
         /* Propagate along edge from vertex with smallest to largest distance. */
         if (dists[i1] > dists[i2]) {
           SWAP(int, i1, i2);
@@ -392,16 +414,16 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
           BMEdge *e_other;
           BMIter eiter;
           BM_ITER_ELEM (e_other, &eiter, v2, BM_EDGES_OF_VERT) {
-            if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 &&
-                (e->l == NULL || e_other->l == NULL)) {
-              BM_elem_flag_enable(e_other, BM_ELEM_TAG);
+            if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 &&
+                (BM_elem_flag_test(e, tag_loose) || BM_elem_flag_test(e_other, tag_loose))) {
+              BM_elem_flag_enable(e_other, tag_queued);
               BLI_LINKSTACK_PUSH(queue_next, e_other);
             }
           }
         }
       }
 
-      if (e->l != NULL) {
+      if (!BM_elem_flag_test(e, tag_loose)) {
         /* Propagate across edge to vertices in adjacent faces. */
         BMLoop *l;
         BMIter liter;
@@ -417,10 +439,10 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
               BMEdge *e_other;
               BMIter eiter;
               BM_ITER_ELEM (e_other, &eiter, v_other, BM_EDGES_OF_VERT) {
-                if (e_other != e && BM_elem_flag_test(e_other, BM_ELEM_TAG) == 0 &&
-                    (e_other->l == NULL ||
+                if (e_other != e && BM_elem_flag_test(e_other, tag_queued) == 0 &&
+                    (BM_elem_flag_test(e_other, tag_loose) ||
                      dists[BM_elem_index_get(BM_edge_other_vert(e_other, v_other))] != FLT_MAX)) {
-                  BM_elem_flag_enable(e_other, BM_ELEM_TAG);
+                  BM_elem_flag_enable(e_other, tag_queued);
                   BLI_LINKSTACK_PUSH(queue_next, e_other);
                 }
               }
@@ -434,13 +456,13 @@ void transform_convert_mesh_connectivity_distance(struct BMesh *bm,
     for (LinkNode *lnk = queue_next; lnk; lnk = lnk->next) {
       BMEdge *e_link = lnk->link;
 
-      BM_elem_flag_disable(e_link, BM_ELEM_TAG);
+      BM_elem_flag_disable(e_link, tag_queued);
     }
 
     BLI_LINKSTACK_SWAP(queue, queue_next);
 
     /* None should be tagged now since 'queue_next' is empty. */
-    BLI_assert(BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, BM_ELEM_TAG, true) == 0);
+    BLI_assert(BM_iter_mesh_count_flag(BM_EDGES_OF_MESH, bm, tag_queued, true) == 0);
   } while (BLI_LINKSTACK_SIZE(queue));
 
   BLI_LINKSTACK_FREE(queue);



More information about the Bf-blender-cvs mailing list