[Bf-blender-cvs] [f944cab9f3e] transform_mirror_axis: EditMesh support mirror on all axes

mano-wii noreply at git.blender.org
Tue Sep 10 21:12:51 CEST 2019


Commit: f944cab9f3eea738677d15c4d3a040e70c8d5fb5
Author: mano-wii
Date:   Mon Sep 9 00:08:01 2019 -0300
Branches: transform_mirror_axis
https://developer.blender.org/rBf944cab9f3eea738677d15c4d3a040e70c8d5fb5

EditMesh support mirror on all axes

Part of T68930

This patch adds two more mirror options that can be enabled simultaneously: Mirror Y and Z.

Since different transformation options use their own mirroring code (eg edge / vert slide and proportional editing), this patch proposes a generic solution that can be applied to any transformation.

The idea is to create a new array type that points to the location of each reference element with the mirror element location.

This reduces the amount of `TransData` that is already overkill.

Reviewers: campbellbarton

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

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

M	release/scripts/startup/bl_ui/space_view3d_toolbar.py
M	source/blender/editors/transform/transform.c
M	source/blender/editors/transform/transform.h
M	source/blender/editors/transform/transform_convert.c
M	source/blender/editors/transform/transform_convert_mesh.c
M	source/blender/editors/transform/transform_generics.c
M	source/blender/makesrna/intern/rna_mesh.c

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

diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index d96f8b04058..a6a1e8b1b11 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -144,11 +144,21 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
         ob = context.active_object
         mesh = ob.data
 
-        col = layout.column(align=True)
-        col.prop(mesh, "use_mirror_x")
+        split = layout.split()
+
+        col = split.column()
+        col.alignment = 'RIGHT'
+        col.label(text="Mirror")
+
+        col = split.column()
 
         row = col.row(align=True)
-        row.active = ob.data.use_mirror_x
+        row.prop(mesh, "use_mirror_x", text="X", toggle=True)
+        row.prop(mesh, "use_mirror_y", text="Y", toggle=True)
+        row.prop(mesh, "use_mirror_z", text="Z", toggle=True)
+
+        row = layout.row(align=True)
+        row.active = ob.data.use_mirror_x or ob.data.use_mirror_y or ob.data.use_mirror_z
         row.prop(mesh, "use_mirror_topology")
 
 
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 019db4f74fa..fd2fb757549 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -6503,37 +6503,6 @@ static void slide_origdata_create_data(TransDataContainer *tc,
     for (i = 0, sv = sv_array; i < v_num; i++, sv = POINTER_OFFSET(sv, v_stride)) {
       slide_origdata_create_data_vert(bm, sod, sv);
     }
-
-    if (tc->mirror.axis_flag) {
-      TransData *td = tc->data;
-      TransDataGenericSlideVert *sv_mirror;
-
-      sod->sv_mirror = MEM_callocN(sizeof(*sv_mirror) * tc->data_len, __func__);
-      sod->totsv_mirror = tc->data_len;
-
-      sv_mirror = sod->sv_mirror;
-
-      for (i = 0; i < tc->data_len; i++, td++) {
-        BMVert *eve = td->extra;
-        /* Check the vertex has been used since both sides
-         * of the mirror may be selected & sliding. */
-        if (eve && !BLI_ghash_haskey(sod->origverts, eve)) {
-          sv_mirror->v = eve;
-          copy_v3_v3(sv_mirror->co_orig_3d, eve->co);
-
-          slide_origdata_create_data_vert(bm, sod, sv_mirror);
-          sv_mirror++;
-        }
-        else {
-          sod->totsv_mirror--;
-        }
-      }
-
-      if (sod->totsv_mirror == 0) {
-        MEM_freeN(sod->sv_mirror);
-        sod->sv_mirror = NULL;
-      }
-    }
   }
 }
 
@@ -6693,15 +6662,6 @@ static void slide_origdata_interp_data(Object *obedit,
         slide_origdata_interp_data_vert(sod, bm, is_final, sv);
       }
     }
-
-    if (sod->sv_mirror) {
-      sv = sod->sv_mirror;
-      for (i = 0; i < v_num; i++, sv++) {
-        if (sv->cd_loop_groups || has_mdisps) {
-          slide_origdata_interp_data_vert(sod, bm, is_final, sv);
-        }
-      }
-    }
   }
 }
 
@@ -6729,8 +6689,6 @@ static void slide_origdata_free_date(SlideOrigData *sod)
     }
 
     MEM_SAFE_FREE(sod->layer_math_map);
-
-    MEM_SAFE_FREE(sod->sv_mirror);
   }
 }
 
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 92db32fa836..52c17b09aff 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -311,10 +311,6 @@ typedef struct SlideOrigData {
   /** Array size of 'layer_math_map_num'
    * maps TransDataVertSlideVert.cd_group index to absolute CustomData layer index */
   int *layer_math_map;
-
-  /** Array of slide vert data especially for mirror verts. */
-  TransDataGenericSlideVert *sv_mirror;
-  int totsv_mirror;
 } SlideOrigData;
 
 typedef struct EdgeSlideData {
@@ -449,6 +445,15 @@ typedef struct TransData {
   short protectflag;
 } TransData;
 
+typedef struct TransDataMirror {
+  /** location of mirrored reference data. */
+  float *loc_ref;
+  /** Location of the data to transform. */
+  float *loc;
+  short sign[3];
+  void *extra;
+} TransDataMirror;
+
 typedef struct MouseInput {
   void (*apply)(struct TransInfo *t, struct MouseInput *mi, const double mval[2], float output[3]);
   void (*post)(struct TransInfo *t, float values[3]);
@@ -549,10 +554,18 @@ typedef struct TransDataContainer {
    * Mirror option
    */
   struct {
-    /* Currently for mesh X mirror only. */
-    int axis_flag;
-    /** Set to -1.0f or 1.0 when use_mirror is set. */
-    float sign;
+    union {
+      struct {
+        /* For easy access. */
+        uint axis_x : 1;
+        uint axis_y : 1;
+        uint axis_z : 1;
+      };
+      short axis_flag;
+    };
+    /** Mirror data array. */
+    TransDataMirror *data;
+    int data_len;
   } mirror;
 
   TransCustomDataContainer custom;
@@ -860,16 +873,18 @@ enum {
   /** For Graph Editor - curves that can only have int-values
    * need their keyframes tagged with this. */
   TD_INTVALUES = 1 << 15,
-  /** For editmode mirror, clamp to x = 0 */
-  TD_MIRROR_EDGE = 1 << 16,
+  /** For editmode mirror, clamp axis to 0 */
+  TD_MIRROR_EDGE_X = 1 << 16,
+  TD_MIRROR_EDGE_Y = 1 << 17,
+  TD_MIRROR_EDGE_Z = 1 << 18,
   /** For fcurve handles, move them along with their keyframes */
-  TD_MOVEHANDLE1 = 1 << 17,
-  TD_MOVEHANDLE2 = 1 << 18,
+  TD_MOVEHANDLE1 = 1 << 19,
+  TD_MOVEHANDLE2 = 1 << 20,
   /** Exceptional case with pose bone rotating when a parent bone has 'Local Location'
    * option enabled and rotating also transforms it. */
-  TD_PBONE_LOCAL_MTX_P = 1 << 19,
+  TD_PBONE_LOCAL_MTX_P = 1 << 21,
   /** Same as above but for a child bone. */
-  TD_PBONE_LOCAL_MTX_C = 1 << 20,
+  TD_PBONE_LOCAL_MTX_C = 1 << 22,
 };
 
 /** #TransSnap.status */
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 6da03d917a6..12655ff48be 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1779,17 +1779,15 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
       bool has_face_sel = (bm->totfacesel != 0);
 
       if (tc->mirror.axis_flag) {
-        TransData *td;
+        TransDataMirror *tdm;
         int i;
 
         /* Rather then adjusting the selection (which the user would notice)
          * tag all mirrored verts, then auto-merge those. */
         BM_mesh_elem_hflag_disable_all(bm, BM_VERT, BM_ELEM_TAG, false);
 
-        for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
-          if (td->extra) {
-            BM_elem_flag_enable((BMVert *)td->extra, BM_ELEM_TAG);
-          }
+        for (i = tc->mirror.data_len, tdm = tc->mirror.data; i--; tdm++) {
+          BM_elem_flag_enable((BMVert *)tdm->extra, BM_ELEM_TAG);
         }
 
         hflag = BM_ELEM_SELECT | BM_ELEM_TAG;
diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c
index 98ae15ed2dc..cb7c0583c8c 100644
--- a/source/blender/editors/transform/transform_convert_mesh.c
+++ b/source/blender/editors/transform/transform_convert_mesh.c
@@ -52,6 +52,9 @@
 #include "transform_convert.h"
 #include "bmesh.h"
 
+/* Used for both mirror epsilon and TD_MIRROR_EDGE_ */
+#define TRANSFORM_MAXDIST_MIRROR 0.00002f
+
 /* when transforming islands */
 struct TransIslandData {
   float co[3];
@@ -395,6 +398,164 @@ static struct TransIslandData *editmesh_islands_info_calc(BMEditMesh *em,
   return trans_islands;
 }
 
+static bool is_in_quadrant_v3(const float co[3], const int quadrant[3], const float epsilon)
+{
+  if (quadrant[0] && ((co[0] * quadrant[0]) < -epsilon)) {
+    return false;
+  }
+  if (quadrant[1] && ((co[1] * quadrant[1]) < -epsilon)) {
+    return false;
+  }
+  if (quadrant[2] && ((co[2] * quadrant[2]) < -epsilon)) {
+    return false;
+  }
+  return true;
+}
+
+static TransDataMirror *editmesh_mirror_data_calc(BMEditMesh *em,
+                                                  bool use_select,
+                                                  const bool use_topology,
+                                                  const bool mirror_axis[3],
+                                                  int *r_mirror_data_len,
+                                                  BLI_bitmap **r_mirror_bitmap)
+{
+  BMesh *bm = em->bm;
+  int *index[3] = {NULL};
+  int i;
+
+  bool test_selected_only = use_select && (mirror_axis[0] + mirror_axis[1] + mirror_axis[2]) == 1;
+  for (i = 0; i < 3; i++) {
+    if (mirror_axis[i]) {
+      index[i] = MEM_mallocN(bm->totvert * sizeof(int), __func__);
+      EDBM_verts_mirror_cache_begin_ex(
+          em, i, false, test_selected_only, use_topology, TRANSFORM_MAXDIST_MIRROR, index[i]);
+    }
+  }
+
+  BMVert *eve;
+  BMIter iter;
+
+  int quadrant[3];
+  {
+    float mirror_sum[3] = {0};
+    BM_ITER_MESH (eve, &iter, bm, BM_VERTS_OF_MESH) {
+      if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+        continue;
+      }
+      if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+        add_v3_v3(mirror_sum, eve->co);
+      }
+    }
+
+    for (i = 0; i < 3; i++) {
+      if (mirror_axis[i]) {
+        quadrant[i] = mirror_sum[i] >= 0.0f ? 1 : -1;
+      }
+      else {
+        quadrant[i] = 0;
+      }
+    }
+  }
+
+  /* Tag only elements that will be transformed within the quadrant. */
+  BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+    if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+      continue;
+    }
+    if ((!use_select || BM_elem_flag_test(eve, BM_ELEM_SELECT)) &&
+        is_in_quadrant_v3(eve->co, quadrant, TRANSFORM_MAXDIST_MIRROR)) {
+      BM_elem_flag_enable(eve, BM_ELEM_TAG);
+      BM_elem_index_set(eve, i);
+    }
+    else {
+      BM_elem_flag_disable(eve, BM_ELEM_TAG);
+      BM_elem_index_set(eve, -1);
+    }
+  }
+
+  for (int a = 0; a < 3; a++) {
+    int *index_iter = index[a];
+    if (index_iter == NULL) {
+      continue;
+    }
+    BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
+      if (BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
+        continue;
+      }
+      if (test_selected_only && !BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
+        continue;
+      }
+      int elem_index = BM_elem_i

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list