[Bf-blender-cvs] [0b8221683fa] master: BMesh: add utility functions

Campbell Barton noreply at git.blender.org
Thu Jul 9 10:43:48 CEST 2020


Commit: 0b8221683fa9b4d228728dcf3c2e95389315a4a6
Author: Campbell Barton
Date:   Thu Jul 9 18:23:16 2020 +1000
Branches: master
https://developer.blender.org/rB0b8221683fa9b4d228728dcf3c2e95389315a4a6

BMesh: add utility functions

- BM_edge_uv_share_vert_check
- BM_face_uv_calc_center_median_weighted
- BM_loop_at_index_find

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

M	source/blender/bmesh/intern/bmesh_mesh.c
M	source/blender/bmesh/intern/bmesh_mesh.h
M	source/blender/bmesh/intern/bmesh_query_uv.c
M	source/blender/bmesh/intern/bmesh_query_uv.h
M	source/blender/editors/uvedit/uvedit_rip.c

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

diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c
index ffe84f93679..834371fefdf 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.c
+++ b/source/blender/bmesh/intern/bmesh_mesh.c
@@ -2377,6 +2377,26 @@ BMFace *BM_face_at_index_find(BMesh *bm, const int index)
   return BLI_mempool_findelem(bm->fpool, index);
 }
 
+BMLoop *BM_loop_at_index_find(BMesh *bm, const int index)
+{
+  BMIter iter;
+  BMFace *f;
+  int i = index;
+  BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+    if (i < f->len) {
+      BMLoop *l_first, *l_iter;
+      l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+      do {
+        if (i == 0) {
+          return l_iter;
+        }
+      } while ((l_iter = l_iter->next) != l_first);
+    }
+    i -= f->len;
+  }
+  return NULL;
+}
+
 /**
  * Use lookup table when available, else use slower find functions.
  *
diff --git a/source/blender/bmesh/intern/bmesh_mesh.h b/source/blender/bmesh/intern/bmesh_mesh.h
index 4ba0d948499..0d665f1d391 100644
--- a/source/blender/bmesh/intern/bmesh_mesh.h
+++ b/source/blender/bmesh/intern/bmesh_mesh.h
@@ -118,6 +118,7 @@ BLI_INLINE BMFace *BM_face_at_index(BMesh *bm, const int index)
 BMVert *BM_vert_at_index_find(BMesh *bm, const int index);
 BMEdge *BM_edge_at_index_find(BMesh *bm, const int index);
 BMFace *BM_face_at_index_find(BMesh *bm, const int index);
+BMLoop *BM_loop_at_index_find(BMesh *bm, const int index);
 
 BMVert *BM_vert_at_index_find_or_table(BMesh *bm, const int index);
 BMEdge *BM_edge_at_index_find_or_table(BMesh *bm, const int index);
diff --git a/source/blender/bmesh/intern/bmesh_query_uv.c b/source/blender/bmesh/intern/bmesh_query_uv.c
index 6c81bc21097..6d1a8dbbbd0 100644
--- a/source/blender/bmesh/intern/bmesh_query_uv.c
+++ b/source/blender/bmesh/intern/bmesh_query_uv.c
@@ -32,6 +32,69 @@
 #include "bmesh.h"
 #include "intern/bmesh_private.h"
 
+static void uv_aspect(const BMLoop *l,
+                      const float aspect[2],
+                      const int cd_loop_uv_offset,
+                      float r_uv[2])
+{
+  const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv;
+  r_uv[0] = uv[0] * aspect[0];
+  r_uv[1] = uv[1] * aspect[1];
+}
+
+/**
+ * Typically we avoid hiding arguments,
+ * make this an exception since it reads poorly with so many repeated arguments.
+ */
+#define UV_ASPECT(l, r_uv) uv_aspect(l, aspect, cd_loop_uv_offset, r_uv)
+
+/**
+ * Computes the UV center of a face, using the mean average weighted by edge length.
+ *
+ * See #BM_face_calc_center_median_weighted for matching spatial functionality.
+ *
+ * \param aspect: Calculate the center scaling by these values, and finally dividing.
+ * Since correct weighting depends on having the correct aspect.
+ */
+void BM_face_uv_calc_center_median_weighted(const BMFace *f,
+                                            const float aspect[2],
+                                            const int cd_loop_uv_offset,
+                                            float r_cent[2])
+{
+  const BMLoop *l_iter;
+  const BMLoop *l_first;
+  float totw = 0.0f;
+  float w_prev;
+
+  zero_v2(r_cent);
+
+  l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+  float uv_prev[2], uv_curr[2];
+  UV_ASPECT(l_iter->prev, uv_prev);
+  UV_ASPECT(l_iter, uv_curr);
+  w_prev = len_v2v2(uv_prev, uv_curr);
+  do {
+    float uv_next[2];
+    UV_ASPECT(l_iter->next, uv_next);
+    const float w_curr = len_v2v2(uv_curr, uv_next);
+    const float w = (w_curr + w_prev);
+    madd_v2_v2fl(r_cent, uv_curr, w);
+    totw += w;
+    w_prev = w_curr;
+    copy_v2_v2(uv_curr, uv_next);
+  } while ((l_iter = l_iter->next) != l_first);
+
+  if (totw != 0.0f) {
+    mul_v2_fl(r_cent, 1.0f / (float)totw);
+  }
+  /* Reverse aspect. */
+  r_cent[0] /= aspect[0];
+  r_cent[1] /= aspect[1];
+}
+
+#undef UV_ASPECT
+
 /**
  * Calculate the UV cross product (use the sign to check the winding).
  */
@@ -69,16 +132,25 @@ bool BM_loop_uv_share_edge_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_
 /**
  * Check if two loops that share a vertex also have the same UV coordinates.
  */
-bool BM_loop_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
+bool BM_loop_uv_share_vert_check(BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
 {
   BLI_assert(l_a->v == l_b->v);
-
-  {
     const MLoopUV *luv_a = BM_ELEM_CD_GET_VOID_P(l_a, cd_loop_uv_offset);
     const MLoopUV *luv_b = BM_ELEM_CD_GET_VOID_P(l_b, cd_loop_uv_offset);
     if (!equals_v2v2(luv_a->uv, luv_b->uv)) {
       return false;
     }
+  return true;
+}
+
+/**
+ * Check if two loops that share a vertex also have the same UV coordinates.
+ */
+bool BM_edge_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
+{
+  BLI_assert(l_a->v == l_b->v);
+  if (!BM_loop_uv_share_vert_check(l_a, l_b, cd_loop_uv_offset)) {
+    return false;
   }
 
   /* No need for NULL checks, these will always succeed. */
diff --git a/source/blender/bmesh/intern/bmesh_query_uv.h b/source/blender/bmesh/intern/bmesh_query_uv.h
index 9ed8671f8fe..115c51e2044 100644
--- a/source/blender/bmesh/intern/bmesh_query_uv.h
+++ b/source/blender/bmesh/intern/bmesh_query_uv.h
@@ -21,6 +21,18 @@
  * \ingroup bmesh
  */
 
+float BM_loop_uv_calc_edge_length_squared(const BMLoop *l,
+                                          const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
+    ATTR_NONNULL();
+float BM_loop_uv_calc_edge_length(const BMLoop *l,
+                                  const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
+    ATTR_NONNULL();
+
+void BM_face_uv_calc_center_median_weighted(const BMFace *f,
+                                            const float aspect[2],
+                                            const int cd_loop_uv_offset,
+                                            float r_cent[2]) ATTR_NONNULL();
+
 float BM_face_uv_calc_cross(const BMFace *f, const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL();
 
@@ -29,8 +41,10 @@ bool BM_loop_uv_share_edge_check(BMLoop *l_a,
                                     const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL();
 
-bool BM_loop_uv_share_vert_check(BMEdge *e,
-                                    BMLoop *l_a,
+bool BM_edge_uv_share_vert_check(BMEdge *e, BMLoop *l_a, BMLoop *l_b, const int cd_loop_uv_offset)
+    ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+
+bool BM_loop_uv_share_vert_check(BMLoop *l_a,
                                     BMLoop *l_b,
                                     const int cd_loop_uv_offset) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL();
diff --git a/source/blender/editors/uvedit/uvedit_rip.c b/source/blender/editors/uvedit/uvedit_rip.c
index 14f5ad3ab80..934c2e0457f 100644
--- a/source/blender/editors/uvedit/uvedit_rip.c
+++ b/source/blender/editors/uvedit/uvedit_rip.c
@@ -657,7 +657,7 @@ static UVRipPairs *uv_rip_pairs_from_loop(BMLoop *l_init,
             BMLoop *l_other = (l_radial_iter->v == l_step->v) ? l_radial_iter :
                                                                 l_radial_iter->next;
             BLI_assert(l_other->v == l_step->v);
-            if (BM_loop_uv_share_vert_check(e_radial, l_other, l_step, cd_loop_uv_offset)) {
+            if (BM_edge_uv_share_vert_check(e_radial, l_other, l_step, cd_loop_uv_offset)) {
               if (!UL(l_other)->in_rip_pairs && !UL(l_other)->in_stack) {
                 BLI_SMALLSTACK_PUSH(stack, l_other);
                 UL(l_other)->in_stack = true;



More information about the Bf-blender-cvs mailing list