[Bf-blender-cvs] [d7c762d2f75] master: Cleanup: Rearrange the functions in 'transform_convert_mesh.c'

Germano Cavalcante noreply at git.blender.org
Mon Apr 26 14:35:19 CEST 2021


Commit: d7c762d2f7533a6f77a912f82937e79fb046362e
Author: Germano Cavalcante
Date:   Mon Apr 26 09:35:03 2021 -0300
Branches: master
https://developer.blender.org/rBd7c762d2f7533a6f77a912f82937e79fb046362e

Cleanup: Rearrange the functions in 'transform_convert_mesh.c'

The creation of `TransCustomData` is best located at the beginning of the
file as it is a specific struct of the file and can be used a lot locally.

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

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 872f3e1385a..59f314f5301 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -48,1530 +48,1551 @@
 
 #include "transform_convert.h"
 
-#define USE_FACE_SUBSTITUTE
-
 /* -------------------------------------------------------------------- */
-/** \name Island Creation
+/** \name Container TransCustomData Creation
  * \{ */
 
-void transform_convert_mesh_islands_calc(struct BMEditMesh *em,
-                                         const bool calc_single_islands,
-                                         const bool calc_island_center,
-                                         const bool calc_island_axismtx,
-                                         struct TransIslandData *r_island_data)
-{
-  struct TransIslandData data = {NULL};
+struct TransCustomDataMergeGroup {
+  /** map {BMVert: TransCustomDataLayerVert} */
+  struct LinkNode **cd_loop_groups;
+};
 
-  BMesh *bm = em->bm;
-  char htype;
-  char itype;
-  int i;
+struct TransCustomDataLayer {
+  BMesh *bm;
+  struct MemArena *arena;
 
-  /* group vars */
-  int *groups_array = NULL;
-  int(*group_index)[2] = NULL;
+  struct GHash *origfaces;
+  struct BMesh *bm_origfaces;
 
-  bool has_only_single_islands = bm->totedgesel == 0 && bm->totfacesel == 0;
-  if (has_only_single_islands && !calc_single_islands) {
-    return;
+  /* Special handle for multi-resolution. */
+  int cd_loop_mdisp_offset;
+
+  /* Optionally merge custom-data groups (this keeps UVs connected for example). */
+  struct {
+    /** map {BMVert: TransDataBasic} */
+    struct GHash *origverts;
+    struct TransCustomDataMergeGroup *data;
+    int data_len;
+    /** Array size of 'layer_math_map_len'
+     * maps #TransCustomDataLayerVert.cd_group index to absolute #CustomData layer index */
+    int *customdatalayer_map;
+    /** Number of math BMLoop layers. */
+    int customdatalayer_map_len;
+  } merge_group;
+
+  bool use_merge_group;
+};
+
+static void tc_mesh_customdatacorrect_free_fn(struct TransInfo *UNUSED(t),
+                                              struct TransDataContainer *UNUSED(tc),
+                                              struct TransCustomData *custom_data)
+{
+  struct TransCustomDataLayer *tcld = custom_data->data;
+  bmesh_edit_end(tcld->bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES);
+
+  if (tcld->bm_origfaces) {
+    BM_mesh_free(tcld->bm_origfaces);
+  }
+  if (tcld->origfaces) {
+    BLI_ghash_free(tcld->origfaces, NULL, NULL);
+  }
+  if (tcld->merge_group.origverts) {
+    BLI_ghash_free(tcld->merge_group.origverts, NULL, NULL);
+  }
+  if (tcld->arena) {
+    BLI_memarena_free(tcld->arena);
+  }
+  if (tcld->merge_group.customdatalayer_map) {
+    MEM_freeN(tcld->merge_group.customdatalayer_map);
   }
 
-  data.island_vert_map = MEM_mallocN(sizeof(*data.island_vert_map) * bm->totvert, __func__);
-  /* we shouldn't need this, but with incorrect selection flushing
-   * its possible we have a selected vertex that's not in a face,
-   * for now best not crash in that case. */
-  copy_vn_i(data.island_vert_map, bm->totvert, -1);
+  MEM_freeN(tcld);
+  custom_data->data = NULL;
+}
 
-  if (!has_only_single_islands) {
-    if (em->selectmode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) {
-      groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totedgesel, __func__);
-      data.island_tot = BM_mesh_calc_edge_groups(
-          bm, groups_array, &group_index, NULL, NULL, BM_ELEM_SELECT);
+#define USE_FACE_SUBSTITUTE
+#ifdef USE_FACE_SUBSTITUTE
+#  define FACE_SUBSTITUTE_INDEX INT_MIN
 
-      htype = BM_EDGE;
-      itype = BM_VERTS_OF_EDGE;
+/**
+ * Search for a neighboring face with area and preferably without selected vertex.
+ * Used to replace area-less faces in custom-data correction.
+ */
+static BMFace *tc_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;
     }
-    else { /* (bm->selectmode & SCE_SELECT_FACE) */
-      groups_array = MEM_mallocN(sizeof(*groups_array) * bm->totfacesel, __func__);
-      data.island_tot = BM_mesh_calc_face_groups(
-          bm, groups_array, &group_index, NULL, NULL, NULL, BM_ELEM_SELECT, BM_VERT);
-
-      htype = BM_FACE;
-      itype = BM_VERTS_OF_FACE;
+    if (is_zero_v3(f_test->no)) {
+      continue;
     }
 
-    BLI_assert(data.island_tot);
-    if (calc_island_center) {
-      data.center = MEM_mallocN(sizeof(*data.center) * data.island_tot, __func__);
+    /* 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 (calc_island_axismtx) {
-      data.axismtx = MEM_mallocN(sizeof(*data.axismtx) * data.island_tot, __func__);
+    if (best_face == NULL) {
+      best_face = f_test;
     }
+  }
+  return best_face;
+}
 
-    BM_mesh_elem_table_ensure(bm, htype);
-
-    void **ele_array;
-    ele_array = (htype == BM_FACE) ? (void **)bm->ftable : (void **)bm->etable;
-
-    BM_mesh_elem_index_ensure(bm, BM_VERT);
-
-    /* may be an edge OR a face array */
-    for (i = 0; i < data.island_tot; i++) {
-      BMEditSelection ese = {NULL};
-
-      const int fg_sta = group_index[i][0];
-      const int fg_len = group_index[i][1];
-      float co[3], no[3], tangent[3];
-      int j;
+static void tc_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 = tc_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);
 
-      zero_v3(co);
-      zero_v3(no);
-      zero_v3(tangent);
+    /* 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);
 
-      ese.htype = htype;
+    /* 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;
+  }
+}
 
-      /* loop on each face or edge in this group:
-       * - assign r_vert_map
-       * - calculate (co, no)
-       */
-      for (j = 0; j < fg_len; j++) {
-        ese.ele = ele_array[groups_array[fg_sta + j]];
+static BMFace *tc_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]);
+}
 
-        if (data.center) {
-          float tmp_co[3];
-          BM_editselection_center(&ese, tmp_co);
-          add_v3_v3(co, tmp_co);
-        }
+#endif /* USE_FACE_SUBSTITUTE */
 
-        if (data.axismtx) {
-          float tmp_no[3], tmp_tangent[3];
-          BM_editselection_normal(&ese, tmp_no);
-          BM_editselection_plane(&ese, tmp_tangent);
-          add_v3_v3(no, tmp_no);
-          add_v3_v3(tangent, tmp_tangent);
-        }
+static void tc_mesh_customdatacorrect_init_vert(struct TransCustomDataLayer *tcld,
+                                                struct TransDataBasic *td,
+                                                const int index)
+{
+  BMesh *bm = tcld->bm;
+  BMVert *v = td->extra;
+  BMIter liter;
+  int j, l_num;
+  float *loop_weights;
 
-        {
-          /* setup vertex map */
-          BMIter iter;
-          BMVert *v;
+  // BM_ITER_ELEM (l, &liter, sv->v, BM_LOOPS_OF_VERT) {
+  BM_iter_init(&liter, bm, BM_LOOPS_OF_VERT, v);
+  l_num = liter.count;
+  loop_weights = tcld->use_merge_group ? BLI_array_alloca(loop_weights, l_num) : NULL;
+  for (j = 0; j < l_num; j++) {
+    BMLoop *l = BM_iter_step(&liter);
+    BMLoop *l_prev, *l_next;
 
-          /* connected edge-verts */
-          BM_ITER_ELEM (v, &iter, ese.ele, itype) {
-            data.island_vert_map[BM_elem_index_get(v)] = i;
-          }
-        }
+    /* Generic custom-data correction. Copy face data. */
+    void **val_p;
+    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)) {
+        tc_mesh_customdatacorrect_face_substitute_set(tcld, l->f, f_copy);
       }
+#endif
+    }
 
-      if (data.center) {
-        mul_v3_v3fl(data.center[i], co, 1.0f / (float)fg_len);
+    if (tcld->use_merge_group) {
+      if ((l_prev = BM_loop_find_prev_nodouble(l, l->next, FLT_EPSILON)) &&
+          (l_next = BM_loop_find_next_nodouble(l, l_prev, FLT_EPSILON))) {
+        loop_weights[j] = angle_v3v3v3(l_prev->v->co, l->v->co, l_next->v->co);
       }
-
-      if (data.axismtx) {
-        if (createSpaceNormalTangent(data.axismtx[i], no, tangent)) {
-          /* pass */
-        }
-        else {
-          if (normalize_v3(no) != 0.0f) {
-            axis_dominant_v3_to_m3(data.axismtx[i], no);
-            invert_m3(data.axismtx[i]);
-          }
-          else {
-            unit_m3(data.axismtx[i]);
-          }
-        }
+      else {
+        loop_weights[j] = 0.0f;
       }
     }
-
-    MEM_freeN(groups_array);
-    MEM_freeN(group_index);
   }
 
-  /* for PET we need islands of 1 so connected vert

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list