[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