[Bf-blender-cvs] [c15635bd8d5] master: BMesh: support laplacian smooth for n-gons

Campbell Barton noreply at git.blender.org
Thu Aug 5 17:43:24 CEST 2021


Commit: c15635bd8d5483a56107b5c31d8dc0b6a691a767
Author: Campbell Barton
Date:   Fri Aug 6 01:42:02 2021 +1000
Branches: master
https://developer.blender.org/rBc15635bd8d5483a56107b5c31d8dc0b6a691a767

BMesh: support laplacian smooth for n-gons

Follow the same logic already used by the modifier.

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

M	source/blender/bmesh/operators/bmo_smooth_laplacian.c
M	source/blender/editors/mesh/editmesh_tools.c

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

diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
index eb25923d1d1..94856701e72 100644
--- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c
+++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c
@@ -37,12 +37,12 @@
 
 struct BLaplacianSystem {
   float *eweights;      /* Length weights per Edge. */
-  float (*fweights)[3]; /* Cotangent weights per face. */
+  float (*fweights)[3]; /* Cotangent weights per loop. */
   float *ring_areas;    /* Total area per ring. */
   float *vlengths;      /* Total sum of lengths(edges) per vertex. */
   float *vweights;      /* Total sum of weights per vertex. */
   int numEdges;         /* Number of edges. */
-  int numFaces;         /* Number of faces. */
+  int numLoops;         /* Number of loops. */
   int numVerts;         /* Number of verts. */
   bool *zerola;         /* Is zero area or length. */
 
@@ -57,7 +57,7 @@ struct BLaplacianSystem {
 typedef struct BLaplacianSystem LaplacianSystem;
 
 static bool vert_is_boundary(BMVert *v);
-static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts);
+static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts);
 static void init_laplacian_matrix(LaplacianSystem *sys);
 static void delete_laplacian_system(LaplacianSystem *sys);
 static void delete_void_pointer(void *data);
@@ -94,19 +94,19 @@ static void delete_laplacian_system(LaplacianSystem *sys)
 static void memset_laplacian_system(LaplacianSystem *sys, int val)
 {
   memset(sys->eweights, val, sizeof(float) * sys->numEdges);
-  memset(sys->fweights, val, sizeof(float) * sys->numFaces * 3);
+  memset(sys->fweights, val, sizeof(float[3]) * sys->numLoops);
   memset(sys->ring_areas, val, sizeof(float) * sys->numVerts);
   memset(sys->vlengths, val, sizeof(float) * sys->numVerts);
   memset(sys->vweights, val, sizeof(float) * sys->numVerts);
   memset(sys->zerola, val, sizeof(bool) * sys->numVerts);
 }
 
-static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts)
+static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numLoops, int a_numVerts)
 {
   LaplacianSystem *sys;
   sys = MEM_callocN(sizeof(LaplacianSystem), "ModLaplSmoothSystem");
   sys->numEdges = a_numEdges;
-  sys->numFaces = a_numFaces;
+  sys->numLoops = a_numLoops;
   sys->numVerts = a_numVerts;
 
   sys->eweights = MEM_callocN(sizeof(float) * sys->numEdges, "ModLaplSmoothEWeight");
@@ -115,7 +115,7 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
     return NULL;
   }
 
-  sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numFaces, "ModLaplSmoothFWeight");
+  sys->fweights = MEM_callocN(sizeof(float[3]) * sys->numLoops, "ModLaplSmoothFWeight");
   if (!sys->fweights) {
     delete_laplacian_system(sys);
     return NULL;
@@ -166,31 +166,23 @@ static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, in
 
 static void init_laplacian_matrix(LaplacianSystem *sys)
 {
-  float areaf;
-  float *v1, *v2, *v3, *v4;
-  float w1, w2, w3, w4;
-  int i, j;
-  bool has_4_vert;
-  uint idv1, idv2, idv3, idv4, idv[4];
   BMEdge *e;
   BMFace *f;
   BMIter eiter;
   BMIter fiter;
-  BMIter vi;
-  BMVert *vn;
-  BMVert *vf[4];
+  uint i;
 
   BM_ITER_MESH_INDEX (e, &eiter, sys->bm, BM_EDGES_OF_MESH, i) {
     if (BM_elem_flag_test(e, BM_ELEM_SELECT) || !BM_edge_is_boundary(e)) {
       continue;
     }
 
-    v1 = e->v1->co;
-    v2 = e->v2->co;
-    idv1 = BM_elem_index_get(e->v1);
-    idv2 = BM_elem_index_get(e->v2);
+    const float *v1 = e->v1->co;
+    const float *v2 = e->v2->co;
+    const int idv1 = BM_elem_index_get(e->v1);
+    const int idv2 = BM_elem_index_get(e->v2);
 
-    w1 = len_v3v3(v1, v2);
+    float w1 = len_v3v3(v1, v2);
     if (w1 > sys->min_area) {
       w1 = 1.0f / w1;
       sys->eweights[i] = w1;
@@ -203,176 +195,126 @@ static void init_laplacian_matrix(LaplacianSystem *sys)
     }
   }
 
-  BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) {
+  uint l_curr_index = 0;
+
+  BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) {
     if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+      l_curr_index += f->len;
       continue;
     }
 
-    BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) {
-      vf[j] = vn;
-    }
-    has_4_vert = (j == 4) ? 1 : 0;
-    idv1 = BM_elem_index_get(vf[0]);
-    idv2 = BM_elem_index_get(vf[1]);
-    idv3 = BM_elem_index_get(vf[2]);
-    idv4 = has_4_vert ? BM_elem_index_get(vf[3]) : 0;
-
-    v1 = vf[0]->co;
-    v2 = vf[1]->co;
-    v3 = vf[2]->co;
-    v4 = has_4_vert ? vf[3]->co : NULL;
-
-    if (has_4_vert) {
-      areaf = area_quad_v3(v1, v2, v3, v4);
-    }
-    else {
-      areaf = area_tri_v3(v1, v2, v3);
-    }
+    BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+    BMLoop *l_iter;
 
-    if (areaf < sys->min_area) {
-      sys->zerola[idv1] = true;
-      sys->zerola[idv2] = true;
-      sys->zerola[idv3] = true;
-      if (has_4_vert) {
-        sys->zerola[idv4] = true;
-      }
-    }
+    l_iter = l_first;
+    do {
+      const int vi_prev = BM_elem_index_get(l_iter->prev->v);
+      const int vi_curr = BM_elem_index_get(l_iter->v);
+      const int vi_next = BM_elem_index_get(l_iter->next->v);
 
-    sys->ring_areas[idv1] += areaf;
-    sys->ring_areas[idv2] += areaf;
-    sys->ring_areas[idv3] += areaf;
-    if (has_4_vert) {
-      sys->ring_areas[idv4] += areaf;
-    }
-
-    if (has_4_vert) {
-
-      idv[0] = idv1;
-      idv[1] = idv2;
-      idv[2] = idv3;
-      idv[3] = idv4;
+      const float *co_prev = l_iter->prev->v->co;
+      const float *co_curr = l_iter->v->co;
+      const float *co_next = l_iter->next->v->co;
 
-      for (j = 0; j < 4; j++) {
-        idv1 = idv[j];
-        idv2 = idv[(j + 1) % 4];
-        idv3 = idv[(j + 2) % 4];
-        idv4 = idv[(j + 3) % 4];
+      const float areaf = area_tri_v3(co_prev, co_curr, co_next);
 
-        v1 = vf[j]->co;
-        v2 = vf[(j + 1) % 4]->co;
-        v3 = vf[(j + 2) % 4]->co;
-        v4 = vf[(j + 3) % 4]->co;
+      if (areaf < sys->min_area) {
+        sys->zerola[vi_curr] = true;
+      }
 
-        w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
-        w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
-        w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
+      sys->ring_areas[vi_prev] += areaf;
+      sys->ring_areas[vi_curr] += areaf;
+      sys->ring_areas[vi_next] += areaf;
 
-        sys->vweights[idv1] += (w2 + w3 + w4) / 4.0f;
-      }
-    }
-    else {
-      w1 = cotangent_tri_weight_v3(v1, v2, v3);
-      w2 = cotangent_tri_weight_v3(v2, v3, v1);
-      w3 = cotangent_tri_weight_v3(v3, v1, v2);
+      const float w1 = cotangent_tri_weight_v3(co_curr, co_next, co_prev) / 2.0f;
+      const float w2 = cotangent_tri_weight_v3(co_next, co_prev, co_curr) / 2.0f;
+      const float w3 = cotangent_tri_weight_v3(co_prev, co_curr, co_next) / 2.0f;
 
-      sys->fweights[i][0] += w1;
-      sys->fweights[i][1] += w2;
-      sys->fweights[i][2] += w3;
+      sys->fweights[l_curr_index][0] += w1;
+      sys->fweights[l_curr_index][1] += w2;
+      sys->fweights[l_curr_index][2] += w3;
 
-      sys->vweights[idv1] += w2 + w3;
-      sys->vweights[idv2] += w1 + w3;
-      sys->vweights[idv3] += w1 + w2;
-    }
+      sys->vweights[vi_prev] += w1 + w2;
+      sys->vweights[vi_curr] += w2 + w3;
+      sys->vweights[vi_next] += w1 + w3;
+    } while (((void)(l_curr_index += 1), (l_iter = l_iter->next) != l_first));
   }
 }
 
 static void fill_laplacian_matrix(LaplacianSystem *sys)
 {
-  float *v1, *v2, *v3, *v4;
-  float w2, w3, w4;
-  int i, j;
-  bool has_4_vert;
-  uint idv1, idv2, idv3, idv4, idv[4];
-
   BMEdge *e;
   BMFace *f;
   BMIter eiter;
   BMIter fiter;
-  BMIter vi;
-  BMVert *vn;
-  BMVert *vf[4];
+  int i;
 
-  BM_ITER_MESH_INDEX (f, &fiter, sys->bm, BM_FACES_OF_MESH, i) {
+  uint l_curr_index = 0;
+
+  BM_ITER_MESH (f, &fiter, sys->bm, BM_FACES_OF_MESH) {
     if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+      l_curr_index += f->len;
       continue;
     }
 
-    BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, j) {
-      vf[j] = vn;
-    }
-    has_4_vert = (j == 4) ? 1 : 0;
-    if (has_4_vert) {
-      idv[0] = BM_elem_index_get(vf[0]);
-      idv[1] = BM_elem_index_get(vf[1]);
-      idv[2] = BM_elem_index_get(vf[2]);
-      idv[3] = BM_elem_index_get(vf[3]);
-      for (j = 0; j < 4; j++) {
-        idv1 = idv[j];
-        idv2 = idv[(j + 1) % 4];
-        idv3 = idv[(j + 2) % 4];
-        idv4 = idv[(j + 3) % 4];
-
-        v1 = vf[j]->co;
-        v2 = vf[(j + 1) % 4]->co;
-        v3 = vf[(j + 2) % 4]->co;
-        v4 = vf[(j + 3) % 4]->co;
-
-        w2 = cotangent_tri_weight_v3(v4, v1, v2) + cotangent_tri_weight_v3(v3, v1, v2);
-        w3 = cotangent_tri_weight_v3(v2, v3, v1) + cotangent_tri_weight_v3(v4, v1, v3);
-        w4 = cotangent_tri_weight_v3(v2, v4, v1) + cotangent_tri_weight_v3(v3, v4, v1);
-
-        w2 = w2 / 4.0f;
-        w3 = w3 / 4.0f;
-        w4 = w4 / 4.0f;
-
-        if (!vert_is_boundary(vf[j]) && sys->zerola[idv1] == false) {
-          EIG_linear_solver_matrix_add(sys->context, idv1, idv2, w2 * sys->vweights[idv1]);
-          EIG_linear_solver_matrix_add(sys->context, idv1, idv3, w3 * sys->vweights[idv1]);
-          EIG_linear_solver_matrix_add(sys->context, idv1, idv4, w4 * sys->vweights[idv1]);
-        }
+    BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+    BMLoop *l_iter = l_first;
+
+    int vi_prev = BM_elem_index_get(l_iter->prev->v);
+    int vi_curr = BM_elem_index_get(l_iter->v);
+
+    bool ok_prev = (sys->zerola[vi_prev] == false) && !vert_is_boundary(l_iter->prev->v);
+    bool ok_curr = (sys->zerola[vi_curr] == false) && !vert_is_boundary(l_iter->v);
+
+    do {
+      const int vi_next = BM_elem_index_get(l_iter->next->v);
+      const bool ok_next = (sys->zerola[vi_next] == false) && !vert_is_boundary(l_iter->next->v);
+
+      if (ok_prev) {
+        EIG_linear_solver_matrix_add(sys->context,
+                                     vi_prev,
+                                     vi_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list