[Bf-blender-cvs] [5e232d7a0ba] blender-v2.90-release: Fix bad 'Correct Face Attributes' behavior when extruding faces

Germano Cavalcante noreply at git.blender.org
Tue Jul 28 14:54:41 CEST 2020


Commit: 5e232d7a0ba2500a20d1920895c9ba1d3df88b29
Author: Germano Cavalcante
Date:   Tue Jul 28 09:49:59 2020 -0300
Branches: blender-v2.90-release
https://developer.blender.org/rB5e232d7a0ba2500a20d1920895c9ba1d3df88b29

Fix bad 'Correct Face Attributes' behavior when extruding faces

A face must have area in order to be possible calculate interpolation weights.
The same to the reference UVs.
But the new faces created with the extrude operator, have no area (before moving).

The solution was to get the loop data from some neighbor face.

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

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

M	source/blender/editors/transform/transform_convert_mesh.c

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

diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 289057b612e..451903f1857 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -51,6 +51,8 @@
 /* Own include. */
 #include "transform_convert.h"
 
+#define USE_FACE_SUBSTITUTE
+
 /* -------------------------------------------------------------------- */
 /** \name Island Creation
  *
@@ -1020,6 +1022,77 @@ static void mesh_customdatacorrect_free_cb(struct TransInfo *UNUSED(t),
   custom_data->data = NULL;
 }
 
+#ifdef USE_FACE_SUBSTITUTE
+
+#  define FACE_SUBSTITUTE_INDEX INT_MIN
+
+/* Search for a neighboring face with area and preferably without selected vertex.
+ * Used to replace arealess faces in customdata correction. */
+static BMFace *mesh_customdatacorrect_find_best_face_substitute(BMFace *f)
+{
+  BMFace *best_face = NULL;
+  BMLoop *l;
+  BMIter liter;
+  BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+    BMLoop *l_radial_next = l->radial_next;
+    BMFace *f_test = l_radial_next->f;
+    if (f_test == f) {
+      continue;
+    }
+    if (is_zero_v3(f_test->no)) {
+      continue;
+    }
+
+    /* Check the loops edge isn't selected. */
+    if (!BM_elem_flag_test(l_radial_next->v, BM_ELEM_SELECT) &&
+        !BM_elem_flag_test(l_radial_next->next->v, BM_ELEM_SELECT)) {
+      /* Prefer edges with unselected vertices.
+       * Useful for extrude. */
+      best_face = f_test;
+      break;
+    }
+    if (best_face == NULL) {
+      best_face = f_test;
+    }
+  }
+  return best_face;
+}
+
+static void mesh_customdatacorrect_face_substitute_set(struct TransCustomDataLayer *tcld,
+                                                       BMFace *f,
+                                                       BMFace *f_copy)
+{
+  BLI_assert(is_zero_v3(f->no));
+  BMesh *bm = tcld->bm;
+  /* It is impossible to calculate the loops weights of a face without area.
+   * Find a substitute. */
+  BMFace *f_substitute = mesh_customdatacorrect_find_best_face_substitute(f);
+  if (f_substitute) {
+    /* Copy the custom-data from the substitute face. */
+    BMLoop *l_iter, *l_first;
+    l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+    do {
+      BM_loop_interp_from_face(bm, l_iter, f_substitute, false, false);
+    } while ((l_iter = l_iter->next) != l_first);
+
+    /* Use the substitute face as the reference during the transformation. */
+    BMFace *f_substitute_copy = BM_face_copy(tcld->bm_origfaces, bm, f_substitute, true, true);
+
+    /* Hack: reference substitute face in `f_copy->no`.
+     * `tcld->origfaces` is already used to restore the initial value. */
+    BM_elem_index_set(f_copy, FACE_SUBSTITUTE_INDEX);
+    *((BMFace **)&f_copy->no[0]) = f_substitute_copy;
+  }
+}
+
+static BMFace *mesh_customdatacorrect_face_substitute_get(BMFace *f_copy)
+{
+  BLI_assert(BM_elem_index_get(f_copy) == FACE_SUBSTITUTE_INDEX);
+  return *((BMFace **)&f_copy->no[0]);
+}
+
+#endif /* USE_FACE_SUBSTITUTE */
+
 static void mesh_customdatacorrect_init_vert(struct TransCustomDataLayer *tcld,
                                              BMVert *v,
                                              const int index)
@@ -1042,6 +1115,11 @@ static void mesh_customdatacorrect_init_vert(struct TransCustomDataLayer *tcld,
     if (!BLI_ghash_ensure_p(tcld->origfaces, l->f, &val_p)) {
       BMFace *f_copy = BM_face_copy(tcld->bm_origfaces, bm, l->f, true, true);
       *val_p = f_copy;
+#ifdef USE_FACE_SUBSTITUTE
+      if (is_zero_v3(l->f->no)) {
+        mesh_customdatacorrect_face_substitute_set(tcld, l->f, f_copy);
+      }
+#endif
     }
 
     if (tcld->use_merge_group) {
@@ -1256,6 +1334,14 @@ static void mesh_customdatacorrect_apply_vert(struct TransCustomDataLayer *tcld,
 
     f_copy = BLI_ghash_lookup(tcld->origfaces, l->f);
 
+#ifdef USE_FACE_SUBSTITUTE
+    /* In some faces it is not possible to calculate interpolation,
+     * so we use a substitute. */
+    if (BM_elem_index_get(f_copy) == FACE_SUBSTITUTE_INDEX) {
+      f_copy = mesh_customdatacorrect_face_substitute_get(f_copy);
+    }
+#endif
+
     /* only loop data, no vertex data since that contains shape keys,
      * and we do not want to mess up other shape keys */
     BM_loop_interp_from_face(bm, l, f_copy, false, false);



More information about the Bf-blender-cvs mailing list