[Bf-blender-cvs] [7ce0d9d7916] master: Cleanup: de-duplicate code for edge-split tagging

Campbell Barton noreply at git.blender.org
Fri Jul 23 08:41:41 CEST 2021


Commit: 7ce0d9d79166c281c161d124ee72dc448efd4325
Author: Campbell Barton
Date:   Fri Jul 23 16:10:06 2021 +1000
Branches: master
https://developer.blender.org/rB7ce0d9d79166c281c161d124ee72dc448efd4325

Cleanup: de-duplicate code for edge-split tagging

Share functionality for single and multi-threaded edge-split tagging.

Remove logic that ensured vert & loop indices in bm_mesh_edges_sharp_tag
(missing from fd9fc809b76d625a1ead6e1fbe5e486cc012f5f3).

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

M	source/blender/bmesh/intern/bmesh_mesh_normals.c

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

diff --git a/source/blender/bmesh/intern/bmesh_mesh_normals.c b/source/blender/bmesh/intern/bmesh_mesh_normals.c
index 08d29a5a819..6dfaa0ca688 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_normals.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_normals.c
@@ -43,10 +43,12 @@
 /* Smooth angle to use when tagging edges is disabled entirely. */
 #define EDGE_TAG_FROM_SPLIT_ANGLE_BYPASS -FLT_MAX
 
-static void bm_mesh_edges_sharp_tag(BMesh *bm,
-                                    const float (*fnos)[3],
-                                    const float split_angle,
-                                    const bool do_sharp_edges_tag);
+static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
+                                                  BMEdge *e,
+                                                  const float split_angle_cos);
+static void bm_edge_tag_from_smooth(const float (*fnos)[3],
+                                    BMEdge *e,
+                                    const float split_angle_cos);
 
 /* -------------------------------------------------------------------- */
 /** \name Update Vertex & Face Normals
@@ -413,49 +415,23 @@ static void bm_mesh_edges_sharp_tag(BMesh *bm,
   const bool check_angle = (split_angle < (float)M_PI);
   const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
 
-  {
-    char htype = BM_VERT | BM_LOOP;
-    if (fnos) {
-      htype |= BM_FACE;
-    }
-    BM_mesh_elem_index_ensure(bm, htype);
+  if (fnos) {
+    BM_mesh_elem_index_ensure(bm, BM_FACE);
   }
 
-  /* This first loop checks which edges are actually smooth,
-   * and pre-populate lnos with vnos (as if they were all smooth). */
-  BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
-    BMLoop *l_a, *l_b;
-
-    BM_elem_index_set(e, i);              /* set_inline */
-    BM_elem_flag_disable(e, BM_ELEM_TAG); /* Clear tag (means edge is sharp). */
-
-    /* An edge with only two loops, might be smooth... */
-    if (BM_edge_loop_pair(e, &l_a, &l_b)) {
-      bool is_angle_smooth = true;
-      if (check_angle) {
-        const float *no_a = fnos ? fnos[BM_elem_index_get(l_a->f)] : l_a->f->no;
-        const float *no_b = fnos ? fnos[BM_elem_index_get(l_b->f)] : l_b->f->no;
-        is_angle_smooth = (dot_v3v3(no_a, no_b) >= split_angle_cos);
+  if (do_sharp_edges_tag) {
+    BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
+      BM_elem_index_set(e, i); /* set_inline */
+      if (e->l != NULL) {
+        bm_edge_tag_from_smooth_and_set_sharp(fnos, e, split_angle_cos);
       }
-
-      /* We only tag edges that are *really* smooth:
-       * If the angle between both its polys' normals is below split_angle value,
-       * and it is tagged as such,
-       * and both its faces are smooth,
-       * and both its faces have compatible (non-flipped) normals,
-       * i.e. both loops on the same edge do not share the same vertex.
-       */
-      if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) &&
-          BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) && l_a->v != l_b->v) {
-        if (is_angle_smooth) {
-          BM_elem_flag_enable(e, BM_ELEM_TAG);
-        }
-        else if (do_sharp_edges_tag) {
-          /* Note that we do not care about the other sharp-edge cases
-           * (sharp poly, non-manifold edge, etc.),
-           * only tag edge as sharp when it is due to angle threshold. */
-          BM_elem_flag_disable(e, BM_ELEM_SMOOTH);
-        }
+    }
+  }
+  else {
+    BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) {
+      BM_elem_index_set(e, i); /* set_inline */
+      if (e->l != NULL) {
+        bm_edge_tag_from_smooth(fnos, e, split_angle_cos);
       }
     }
   }
@@ -832,26 +808,46 @@ static int bm_loop_index_cmp(const void *a, const void *b)
   return 1;
 }
 
+/**
+ * We only tag edges that are *really* smooth when the following conditions are met:
+ * - The angle between both its polygons normals is below split_angle value.
+ * - The edge is tagged as smooth.
+ * - The faces of the edge are tagged as smooth.
+ * - The faces of the edge have compatible (non-flipped) topological normal (winding),
+ *   i.e. both loops on the same edge do not share the same vertex.
+ */
+BLI_INLINE bool bm_edge_is_smooth_no_angle_test(const BMEdge *e,
+                                                const BMLoop *l_a,
+                                                const BMLoop *l_b)
+{
+  return (
+      /* The face is manifold. */
+      (l_a->radial_next == l_b) &&
+      /* Faces have winding that faces the same way. */
+      (l_a->v != l_b->v) &&
+      /* The edge is smooth. */
+      BM_elem_flag_test(e, BM_ELEM_SMOOTH) &&
+      /* Both faces are smooth. */
+      BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH));
+}
+
 static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const float split_angle_cos)
 {
   BLI_assert(e->l != NULL);
   BMLoop *l_a = e->l, *l_b = l_a->radial_next;
   bool is_smooth = false;
-  if (l_a->radial_next == l_b) {
-    if (BM_elem_flag_test(e, BM_ELEM_SMOOTH) && BM_elem_flag_test(l_a->f, BM_ELEM_SMOOTH) &&
-        BM_elem_flag_test(l_b->f, BM_ELEM_SMOOTH) && l_a->v != l_b->v) {
-      if (split_angle_cos != -1.0f) {
-        const float dot = (fnos == NULL) ? dot_v3v3(l_a->f->no, l_b->f->no) :
-                                           dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
-                                                    fnos[BM_elem_index_get(l_b->f)]);
-        if (dot >= split_angle_cos) {
-          is_smooth = true;
-        }
-      }
-      else {
+  if (bm_edge_is_smooth_no_angle_test(e, l_a, l_b)) {
+    if (split_angle_cos != -1.0f) {
+      const float dot = (fnos == NULL) ? dot_v3v3(l_a->f->no, l_b->f->no) :
+                                         dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
+                                                  fnos[BM_elem_index_get(l_b->f)]);
+      if (dot >= split_angle_cos) {
         is_smooth = true;
       }
     }
+    else {
+      is_smooth = true;
+    }
   }
 
   /* Perform `BM_elem_flag_set(e, BM_ELEM_TAG, is_smooth)`
@@ -867,6 +863,43 @@ static void bm_edge_tag_from_smooth(const float (*fnos)[3], BMEdge *e, const flo
   }
 }
 
+/**
+ * A version of #bm_edge_tag_from_smooth that sets sharp edges
+ * when they would be considered smooth but exceed the split angle .
+ *
+ * \note This doesn't have the same atomic requirement as #bm_edge_tag_from_smooth
+ * since it isn't run from multiple threads at once.
+ */
+static void bm_edge_tag_from_smooth_and_set_sharp(const float (*fnos)[3],
+                                                  BMEdge *e,
+                                                  const float split_angle_cos)
+{
+  BLI_assert(e->l != NULL);
+  BMLoop *l_a = e->l, *l_b = l_a->radial_next;
+  bool is_smooth = false;
+  if (bm_edge_is_smooth_no_angle_test(e, l_a, l_b)) {
+    if (split_angle_cos != -1.0f) {
+      const float dot = (fnos == NULL) ? dot_v3v3(l_a->f->no, l_b->f->no) :
+                                         dot_v3v3(fnos[BM_elem_index_get(l_a->f)],
+                                                  fnos[BM_elem_index_get(l_b->f)]);
+      if (dot >= split_angle_cos) {
+        is_smooth = true;
+      }
+      else {
+        /* Note that we do not care about the other sharp-edge cases
+         * (sharp poly, non-manifold edge, etc.),
+         * only tag edge as sharp when it is due to angle threshold. */
+        BM_elem_flag_disable(e, BM_ELEM_SMOOTH);
+      }
+    }
+    else {
+      is_smooth = true;
+    }
+  }
+
+  BM_elem_flag_set(e, BM_ELEM_TAG, is_smooth);
+}
+
 /**
  * Operate on all vertices loops.
  * operating on vertices this is needed for multi-threading



More information about the Bf-blender-cvs mailing list