diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_data_modifier.py | 71 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 22 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_modifier.c | 30 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_mirror.c | 100 |
4 files changed, 196 insertions, 27 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 172fe07eab3..1dd3c545b79 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -569,7 +569,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): layout.operator("object.meshdeform_bind", text="Bind") def MIRROR(self, layout, ob, md): - split = layout.split(factor=0.25) + split = layout.split(factor=0.33) col = split.column() col.label(text="Axis:") @@ -578,15 +578,66 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "use_z") col = split.column() - col.label(text="Options:") - col.prop(md, "use_mirror_merge", text="Merge") - col.prop(md, "use_clip", text="Clipping") - col.prop(md, "use_mirror_vertex_groups", text="Vertex Groups") + col.label(text="Bisect:") + + col_x = col.column() + col_x.prop(md, "use_bisect_x") + col_x.active = md.use_x + + col_y = col.column() + col_y.prop(md, "use_bisect_y") + col_y.active = md.use_y + + col_z = col.column() + col_z.prop(md, "use_bisect_z") + col_z.active = md.use_z col = split.column() + col.label(text="Flip:") + + col_fx = col.column() + col_fx.prop(md, "flip_x") + col_fx.active = md.use_bisect_x and md.use_x + + col_fy = col.column() + col_fy.prop(md, "flip_y") + col_fy.active = md.use_bisect_y and md.use_y + + col_fz = col.column() + col_fz.prop(md, "flip_z") + col_fz.active = md.use_bisect_z and md.use_z + + layout.separator() + + col = layout.column() + col.label(text="Mirror Object:") + col.prop(md, "mirror_object", text="") + + layout.separator() + + col = layout.column() + col.label(text="Options:") + + row = layout.row() + row.prop(md, "use_mirror_vertex_groups", text="Vertex Groups") + row.prop(md, "use_clip", text="Clipping") + row = layout.row() + row.prop(md, "use_mirror_merge", text="Merge") + + col = layout.column() + if md.use_mirror_merge is True: + col.prop(md, "merge_threshold") + + layout.separator() + col = layout.column() + + + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) + col.label(text="Textures:") - col.prop(md, "use_mirror_u", text="Flip U") - col.prop(md, "use_mirror_v", text="Flip V") + row = layout.row() + row.prop(md, "use_mirror_u", text="Flip U") + row.prop(md, "use_mirror_v", text="Flip V") col = layout.column(align=True) @@ -600,12 +651,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "offset_u") col.prop(md, "offset_v") - col = layout.column() - - if md.use_mirror_merge is True: - col.prop(md, "merge_threshold") - col.label(text="Mirror Object:") - col.prop(md, "mirror_object", text="") def MULTIRES(self, layout, ob, md): layout.row().prop(md, "subdivision_type", expand=True) diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 4eb9f890be0..e2f963b7a1b 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -313,14 +313,20 @@ typedef struct MirrorModifierData { /* MirrorModifierData->flag */ enum { - MOD_MIR_CLIPPING = (1 << 0), - MOD_MIR_MIRROR_U = (1 << 1), - MOD_MIR_MIRROR_V = (1 << 2), - MOD_MIR_AXIS_X = (1 << 3), - MOD_MIR_AXIS_Y = (1 << 4), - MOD_MIR_AXIS_Z = (1 << 5), - MOD_MIR_VGROUP = (1 << 6), - MOD_MIR_NO_MERGE = (1 << 7), + MOD_MIR_CLIPPING = (1 << 0), + MOD_MIR_MIRROR_U = (1 << 1), + MOD_MIR_MIRROR_V = (1 << 2), + MOD_MIR_AXIS_X = (1 << 3), + MOD_MIR_AXIS_Y = (1 << 4), + MOD_MIR_AXIS_Z = (1 << 5), + MOD_MIR_VGROUP = (1 << 6), + MOD_MIR_NO_MERGE = (1 << 7), + MOD_MIR_BISECT_AXIS_X = (1 << 8), + MOD_MIR_BISECT_AXIS_Y = (1 << 9), + MOD_MIR_BISECT_AXIS_Z = (1 << 10), + MOD_MIR_FLIP_AXIS_X = (1 << 11), + MOD_MIR_FLIP_AXIS_Y = (1 << 12), + MOD_MIR_FLIP_AXIS_Z = (1 << 13), }; typedef struct EdgeSplitModifierData { diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index b633dd907ae..c2fa89891b0 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1561,6 +1561,36 @@ static void rna_def_modifier_mirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Clip", "Prevent vertices from going through the mirror during transform"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_bisect_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_BISECT_AXIS_X); + RNA_def_property_ui_text(prop, "X", "Cuts the mesh across the mirrorplane"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_bisect_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_BISECT_AXIS_Y); + RNA_def_property_ui_text(prop, "Y", "Cuts the mesh across the mirrorplane"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "use_bisect_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_BISECT_AXIS_Z); + RNA_def_property_ui_text(prop, "Z", "Cuts the mesh across the mirrorplane"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "flip_x", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_FLIP_AXIS_X); + RNA_def_property_ui_text(prop, "X", "Flips the direction of the slice"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "flip_y", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_FLIP_AXIS_Y); + RNA_def_property_ui_text(prop, "Y", "Flips the direction of the slice"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop = RNA_def_property(srna, "flip_z", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_FLIP_AXIS_Z); + RNA_def_property_ui_text(prop, "Z", "Flips the direction of the slice"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_mirror_vertex_groups", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_VGROUP); RNA_def_property_ui_text(prop, "Mirror Vertex Groups", "Mirror vertex groups (e.g. .R->.L)"); diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index d4e02a437d7..df08122aebf 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -45,6 +45,9 @@ #include "BKE_modifier.h" #include "BKE_deform.h" +#include "bmesh.h" +#include "bmesh_tools.h" + #include "MEM_guardedalloc.h" #include "DEG_depsgraph_build.h" @@ -78,21 +81,90 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Mirror Modifier"); } -static Mesh *doMirrorOnAxis( +static Mesh *doBiscetOnMirrorPlane( MirrorModifierData *mmd, Object *ob, const Mesh *mesh, - int axis) + int axis, + float mirrormat[4][4]) +{ + bool do_flip_axis = ( + (axis == 0 && mmd->flag & MOD_MIR_FLIP_AXIS_X) || + (axis == 1 && mmd->flag & MOD_MIR_FLIP_AXIS_Y) || + (axis == 2 && mmd->flag & MOD_MIR_FLIP_AXIS_Z)); + + const float bisect_distance = 0.001; + + Mesh *result; + BMesh *bm; + BMIter viter; + BMVert *v, *v_next; + + bm = BKE_mesh_to_bmesh_ex( + mesh, + &(struct BMeshCreateParams){0}, + &(struct BMeshFromMeshParams){ + .calc_face_normal = true, + .cd_mask_extra = CD_MASK_ORIGINDEX, + }); + + /* prepare data for bisecting */ + float plane[4]; + float plane_co[3] = {0, 0, 0}; + float plane_no[3]; + copy_v3_v3(plane_no, mirrormat[axis]); + + if (mmd->mirror_ob) { + float tmp[4][4]; + invert_m4_m4(tmp, ob->obmat); + mul_m4_m4m4(tmp, tmp, mmd->mirror_ob->obmat); + + copy_v3_v3(plane_no, tmp[axis]); + copy_v3_v3(plane_co, tmp[3]); + } + + plane_from_point_normal_v3(plane, plane_co, plane_no); + + BM_mesh_bisect_plane(bm, plane, false, false, 0, 0, bisect_distance); + + /* Plane definitions for vert killing. */ + float plane_offset[4]; + copy_v3_v3(plane_offset, plane); + plane_offset[3] = plane[3] - bisect_distance; + + if (do_flip_axis) { + negate_v3(plane_offset); + } + + /* Delete verts across the mirror plane. */ + BM_ITER_MESH_MUTABLE(v, v_next, &viter, bm, BM_VERTS_OF_MESH) { + if (plane_point_side_v3(plane_offset, v->co) > 0.0f) { + BM_vert_kill(bm, v); + } + } + + result = BKE_mesh_from_bmesh_for_eval_nomain(bm, 0); + BM_mesh_free(bm); + + return result; +} + +static Mesh *doMirrorOnAxis( + MirrorModifierData *mmd, + Object *ob, + const Mesh *mesh, + int axis) { const float tolerance_sq = mmd->tolerance * mmd->tolerance; const bool do_vtargetmap = (mmd->flag & MOD_MIR_NO_MERGE) == 0; int tot_vtargetmap = 0; /* total merge vertices */ + const bool do_bisect = ( + (axis == 0 && mmd->flag & MOD_MIR_BISECT_AXIS_X) || + (axis == 1 && mmd->flag & MOD_MIR_BISECT_AXIS_Y) || + (axis == 2 && mmd->flag & MOD_MIR_BISECT_AXIS_Z)); + Mesh *result; - const int maxVerts = mesh->totvert; - const int maxEdges = mesh->totedge; - const int maxLoops = mesh->totloop; - const int maxPolys = mesh->totpoly; MVert *mv, *mv_prev; MEdge *me; MLoop *ml; @@ -125,6 +197,18 @@ static Mesh *doMirrorOnAxis( mul_m4_m4m4(mtx, itmp, mtx); } + + Mesh *mesh_bisect = NULL; + if (do_bisect) { + mesh_bisect = doBiscetOnMirrorPlane(mmd, ob, mesh, axis, mtx); + mesh = mesh_bisect; + } + + const int maxVerts = mesh->totvert; + const int maxEdges = mesh->totedge; + const int maxLoops = mesh->totloop; + const int maxPolys = mesh->totpoly; + result = BKE_mesh_new_nomain_from_template( mesh, maxVerts * 2, maxEdges * 2, 0, maxLoops * 2, maxPolys * 2); @@ -290,6 +374,10 @@ static Mesh *doMirrorOnAxis( MEM_freeN(vtargetmap); } + if (mesh_bisect != NULL) { + BKE_id_free(NULL, mesh_bisect); + } + return result; } |