From 19875439b5fb2b7c569bc95f384b5be548a5e45f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 21 Nov 2018 10:01:04 +1100 Subject: Modifier: Mirror learns to bisect on plane D3966 by @kioku w/ edits. This adds bisect and flip options to mirror modifier. --- source/blender/modifiers/intern/MOD_mirror.c | 100 +++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 6 deletions(-) (limited to 'source/blender/modifiers/intern/MOD_mirror.c') 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; } -- cgit v1.2.3