diff options
author | Campbell Barton <ideasman42@gmail.com> | 2018-11-21 02:01:04 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2018-11-21 02:01:04 +0300 |
commit | 19875439b5fb2b7c569bc95f384b5be548a5e45f (patch) | |
tree | 0133b5545724d2445a1497317d3a4f7aa78060b5 /source/blender/modifiers/intern/MOD_mirror.c | |
parent | 6aa7cea3c28d5c79867ba64e4bcef8c5c6ef871e (diff) |
Modifier: Mirror learns to bisect on plane
D3966 by @kioku w/ edits.
This adds bisect and flip options to mirror modifier.
Diffstat (limited to 'source/blender/modifiers/intern/MOD_mirror.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_mirror.c | 100 |
1 files changed, 94 insertions, 6 deletions
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; } |