Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGermano Cavalcante <germano.costa@ig.com.br>2020-07-28 15:49:59 +0300
committerGermano Cavalcante <germano.costa@ig.com.br>2020-07-28 15:53:44 +0300
commit5e232d7a0ba2500a20d1920895c9ba1d3df88b29 (patch)
tree5f75a658f392a51a4ab121986beb80f00d65fc6b
parent6a689b5047b23bccd5e36ae9cbd74cc64f4427b3 (diff)
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
-rw-r--r--source/blender/editors/transform/transform_convert_mesh.c86
1 files changed, 86 insertions, 0 deletions
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);