Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-08-22 22:02:36 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-08-22 22:02:36 +0400
commitc4e1d40022167cb271374f05ebd90c4b215262ad (patch)
tree1f1576ae248e971a224ca5772a87231d08d13168 /source/blender
parente97f979f73ffb1872a7bb388efab883b47544e78 (diff)
replace symmetrize code with calls to bmesh operators.
calls: bisect, duplicate, scale, flip, weld. resolves report [#36475] Symmetrise does not keep uv/weight also fixes issues with faces that cross the axis more then once.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/bmesh/operators/bmo_symmetrize.c670
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c4
2 files changed, 52 insertions, 622 deletions
diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c
index f0402cc5da7..b1a9950610d 100644
--- a/source/blender/bmesh/operators/bmo_symmetrize.c
+++ b/source/blender/bmesh/operators/bmo_symmetrize.c
@@ -15,7 +15,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * Contributor(s): Nicholas Bishop
+ * Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -29,654 +29,80 @@
#include "MEM_guardedalloc.h"
-#include "BLI_array.h"
-#include "BLI_math.h"
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#include "bmesh.h"
#include "intern/bmesh_operators_private.h"
-enum {
- SYMM_OUTPUT_GEOM = (1 << 0)
-};
-
-/* Note: don't think there's much need to make these user-adjustable? */
-#define SYMM_AXIS_THRESHOLD 0.00002f
-#define SYMM_VERT_THRESHOLD 0.00002f
-
-typedef enum {
- /* Coordinate lies on the side being copied from */
- SYMM_SIDE_KEEP,
- /* Coordinate lies on the side being copied from and within the
- * axis threshold */
- SYMM_SIDE_AXIS,
- /* Coordinate lies on the side being copied to */
- SYMM_SIDE_KILL
-} SymmSide;
-
-typedef struct {
- BMesh *bm;
- BMOperator *op;
-
- int axis;
- BMO_SymmDirection direction;
-
- /* Maps from input vertices to their mirrors. If the vertex
- * doesn't have a mirror, it's not in this map. If the vertex is
- * within the axis threshold, it's mapped to itself. */
- GHash *vert_symm_map;
-
- /* Edges that cross the symmetry plane and are asymmetric get
- * split. This map goes from input edges to output vertices. If an
- * edge is not split, it's not in this map. */
- GHash *edge_split_map;
-} Symm;
-
-/* Return which side the coordinate lies on */
-static SymmSide symm_co_side(const Symm *symm,
- const float *co)
-{
- float comp = co[symm->axis];
- if (ELEM3(symm->direction,
- BMO_SYMMETRIZE_NEGATIVE_X,
- BMO_SYMMETRIZE_NEGATIVE_Y,
- BMO_SYMMETRIZE_NEGATIVE_Z))
- {
- comp = -comp;
- }
-
- if (comp >= 0) {
- if (comp < SYMM_AXIS_THRESHOLD)
- return SYMM_SIDE_AXIS;
- else
- return SYMM_SIDE_KEEP;
- }
- else
- return SYMM_SIDE_KILL;
-}
-
-/* Output vertices and the vert_map array */
-static void symm_verts_mirror(Symm *symm)
-{
- BMOIter oiter;
- BMVert *src_v, *dst_v;
-
- symm->vert_symm_map = BLI_ghash_ptr_new(__func__);
-
- BMO_ITER (src_v, &oiter, symm->op->slots_in, "input", BM_VERT) {
- SymmSide side = symm_co_side(symm, src_v->co);
- float co[3];
-
- switch (side) {
- case SYMM_SIDE_KEEP:
- /* The vertex is outside the axis area; output its mirror */
- copy_v3_v3(co, src_v->co);
- co[symm->axis] = -co[symm->axis];
-
- dst_v = BM_vert_create(symm->bm, co, src_v, BM_CREATE_NOP);
- BMO_elem_flag_enable(symm->bm, dst_v, SYMM_OUTPUT_GEOM);
- BLI_ghash_insert(symm->vert_symm_map, src_v, dst_v);
- break;
-
- case SYMM_SIDE_AXIS:
- /* The vertex is within the axis area, snap to center */
- src_v->co[symm->axis] = 0;
- /* Vertex isn't copied, map to itself */
- BLI_ghash_insert(symm->vert_symm_map, src_v, src_v);
- break;
-
- case SYMM_SIDE_KILL:
- /* The vertex does not lie in the half-space being
- * copied from, nothing to do */
- break;
- }
- }
-}
-
-static int symm_edge_crosses_axis(const Symm *symm, const BMEdge *e)
-{
- const int sides[2] = {symm_co_side(symm, e->v1->co),
- symm_co_side(symm, e->v2->co)};
-
- return ((sides[0] != SYMM_SIDE_AXIS) &&
- (sides[1] != SYMM_SIDE_AXIS) &&
- (sides[0] != sides[1]));
-}
-
-/* Output edge split vertices for asymmetric edges and the edge_splits
- * mapping array */
-static void symm_split_asymmetric_edges(Symm *symm)
-{
- BMOIter oiter;
- BMEdge *e;
-
- symm->edge_split_map = BLI_ghash_ptr_new(__func__);
-
- BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) {
- float flipped[3];
-
- copy_v3_v3(flipped, e->v1->co);
- flipped[symm->axis] = -flipped[symm->axis];
-
- if (symm_edge_crosses_axis(symm, e) &&
- (!compare_v3v3(e->v2->co, flipped, SYMM_VERT_THRESHOLD)))
- {
- /* Endpoints lie on opposite sides and are asymmetric */
-
- BMVert *v;
- float lambda = 0, edge_dir[3], co[3];
- float plane_co[3][3][3] = {
- /* axis == 0 */
- {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}},
- /* axis == 1 */
- {{0, 0, 0}, {1, 0, 0}, {0, 0, 1}},
- /* axis == 2 */
- {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}},
- };
- int r;
-
- /* Find intersection of edge with symmetry plane */
- sub_v3_v3v3(edge_dir, e->v2->co, e->v1->co);
- normalize_v3(edge_dir);
- r = isect_ray_plane_v3(e->v1->co,
- edge_dir,
- plane_co[symm->axis][0],
- plane_co[symm->axis][1],
- plane_co[symm->axis][2],
- &lambda, true);
- BLI_assert(r);
+#define ELE_OUT 1
- madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda);
- co[symm->axis] = 0;
-
- /* Edge is asymmetric, split it with a new vertex */
- v = BM_vert_create(symm->bm, co, e->v1, BM_CREATE_NOP);
- BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM);
- BLI_ghash_insert(symm->edge_split_map, e, v);
- }
- }
-}
-
-static void symm_mirror_edges(Symm *symm)
-{
- BMOIter oiter;
- BMEdge *e;
-
- BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) {
- BMVert *v1 = NULL, *v2 = NULL;
- BMEdge *e_new;
-
- v1 = BLI_ghash_lookup(symm->vert_symm_map, e->v1);
- v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2);
-
- if (v1 && v2) {
- e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
- }
- else if (v1 || v2) {
- BMVert *v_split = BLI_ghash_lookup(symm->edge_split_map, e);
- if (v_split) {
- /* Output the keep side of the split edge */
- if (!v1) {
- e_new = BM_edge_create(symm->bm, v_split, e->v2, e, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
- v1 = v_split;
- }
- else {
- e_new = BM_edge_create(symm->bm, e->v1, v_split, e, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
- v2 = v_split;
- }
-
- /* Output the kill side of the split edge */
- e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE);
- BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM);
- }
- }
- }
-}
-
-/****************************** SymmPoly ******************************/
-
-typedef struct {
- /* Indices into the source mvert array (or -1 if not in that array) */
- BMVert **src_verts;
- /* Indices into the destination mvert array, these are vertices
- * created by an edge split (-1 for vertices not created by edge
- * split) */
- BMVert **edge_verts;
-
- /* Number of vertices in the polygon */
- int len;
-
- /* True only if none of the polygon's edges were split */
- bool already_symmetric;
-
- BMFace *src_face;
-} SymmPoly;
-
-static void symm_poly_with_splits(const Symm *symm,
- BMFace *f,
- SymmPoly *out)
-{
- BMIter iter;
- BMLoop *l;
- int i;
-
- out->src_face = f;
-
- /* Count vertices and check for edge splits */
- out->len = f->len;
- out->already_symmetric = true;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- if (BLI_ghash_haskey(symm->edge_split_map, l->e)) {
- out->len++;
- out->already_symmetric = false;
- }
- }
-
- i = 0;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- BMVert *split = BLI_ghash_lookup(symm->edge_split_map, l->e);
-
- out->src_verts[i] = l->v;
- out->edge_verts[i] = NULL;
- i++;
-
- if (split) {
- out->src_verts[i] = NULL;
- out->edge_verts[i] = split;
- i++;
- }
- }
-}
-
-static const float *symm_poly_co(const SymmPoly *sp, int v)
-{
- if (sp->src_verts[v])
- return sp->src_verts[v]->co;
- else if (sp->edge_verts[v])
- return sp->edge_verts[v]->co;
- else
- return NULL;
-}
-
-static SymmSide symm_poly_co_side(const Symm *symm,
- const SymmPoly *sp,
- int v)
-{
- return symm_co_side(symm, symm_poly_co(sp, v));
-}
-
-/* Return the index of the vertex in the destination array at corner
- * 'v' of the polygon, or -1 if not in that array */
-static BMVert *symm_poly_dst(const SymmPoly *sp, int v)
-{
- if (sp->edge_verts[v])
- return sp->edge_verts[v];
- else if (sp->src_verts[v])
- return sp->src_verts[v];
- else
- return NULL;
-}
-
-/* Same as above, but returns the index of the mirror if available, or
- * the same index if on the axis, or -1 otherwise */
-static BMVert *symm_poly_mirror_dst(const Symm *symm,
- const SymmPoly *sp,
- int v)
-{
- if (sp->edge_verts[v])
- return sp->edge_verts[v];
- else if (sp->src_verts[v]) {
- BMVert *v_src = BLI_ghash_lookup(symm->vert_symm_map, sp->src_verts[v]);
- if (v_src)
- return v_src;
- else
- return sp->src_verts[v];
- }
- else
- return NULL;
-}
-
-static bool symm_poly_next_crossing(const Symm *symm,
- const SymmPoly *sp,
- int start,
- int *l1,
- int *l2)
-{
- int i;
-
- for (i = 0; i < sp->len; i++) {
- (*l1) = (start + i) % sp->len;
- (*l2) = ((*l1) + 1) % sp->len;
-
- if ((symm_poly_co_side(symm, sp, *l1) == SYMM_SIDE_KILL) ^
- (symm_poly_co_side(symm, sp, *l2) == SYMM_SIDE_KILL))
- {
- return true;
- }
- }
-
- BLI_assert(!"symm_poly_next_crossing failed");
- return false;
-}
-
-static BMFace *symm_face_create_v(BMesh *bm, BMFace *f_example,
- BMVert **fv, BMEdge **fe, int len)
-{
- BMFace *f_new;
- int i;
-
- /* TODO: calling symmetrize in dynamic-topology sculpt mode
- * frequently tries to create faces of length less than two,
- * should investigate further */
- if (len < 3)
- return NULL;
-
- for (i = 0; i < len; i++) {
- int j = (i + 1) % len;
- fe[i] = BM_edge_exists(fv[i], fv[j]);
- if (!fe[i]) {
- fe[i] = BM_edge_create(bm, fv[i], fv[j], NULL, BM_CREATE_NOP);
- BMO_elem_flag_enable(bm, fe[i], SYMM_OUTPUT_GEOM);
- }
- }
- f_new = BM_face_create(bm, fv, fe, len, f_example, BM_CREATE_NO_DOUBLE);
- BM_face_select_set(bm, f_new, true);
- BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM);
-
- return f_new;
-}
-
-static void symm_mesh_output_poly_zero_splits(Symm *symm,
- SymmPoly *sp,
- BMVert **fv,
- BMEdge **fe,
- int segment_len,
- int start)
-{
- int i, j;
-
- j = 0;
-
- /* Output the keep side of the input polygon */
- for (i = 0; i < segment_len; i++) {
- const int offset = (start + i) % sp->len;
- BLI_assert(sp->src_verts[offset]);
- fv[j++] = sp->src_verts[offset];
- }
-
- /* Output the kill side of the polygon */
- for (i = segment_len - 1; i >= 0; i--) {
- const int offset = (start + i) % sp->len;
-
- if (symm_poly_co_side(symm, sp, offset) == SYMM_SIDE_KEEP) {
- BLI_assert(sp->src_verts[offset]);
- fv[j++] = BLI_ghash_lookup(symm->vert_symm_map,
- sp->src_verts[offset]);
- }
- }
-
- symm_face_create_v(symm->bm, sp->src_face, fv, fe, j);
-}
-
-static void symm_mesh_output_poly_with_splits(Symm *symm,
- SymmPoly *sp,
- BMVert **fv,
- BMEdge **fe,
- int segment_len,
- int start)
-{
- int i;
-
- /* Output the keep side of the input polygon */
-
- for (i = 0; i < segment_len; i++) {
- const int offset = (start + i) % sp->len;
- BMVert *v = symm_poly_dst(sp, offset);
-
- BLI_assert(v);
-
- fv[i] = v;
- }
-
- symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len);
-
- /* Output the kill side of the input polygon */
-
- for (i = 0; i < segment_len; i++) {
- const int offset = (start + i) % sp->len;
- BMVert *v = symm_poly_mirror_dst(symm, sp, offset);
-
- fv[segment_len - i - 1] = v;
-
- }
-
- symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len);
-}
-
-static void symm_mirror_polygons(Symm *symm)
+void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
{
- BMOIter oiter;
- BMFace *f;
- BMVert **pv = NULL;
- BMVert **fv = NULL;
- BMEdge **fe = NULL;
- BLI_array_declare(pv);
- BLI_array_declare(fv);
- BLI_array_declare(fe);
-
- BMO_ITER (f, &oiter, symm->op->slots_in, "input", BM_FACE) {
- BMIter iter;
- BMLoop *l;
- bool mirror_all = true, ignore_all = true;
-
- /* Check if entire polygon can be mirrored or ignored */
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- const SymmSide side = symm_co_side(symm, l->v->co);
- if (side == SYMM_SIDE_KILL)
- mirror_all = false;
- else if (side == SYMM_SIDE_KEEP)
- ignore_all = false;
- }
-
- if (mirror_all) {
- int i;
-
- /* Make a mirrored copy of the polygon */
-
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, f->len);
- BLI_array_grow_items(fe, f->len);
-
- i = f->len;
- BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) {
- i--;
-
- if (symm_co_side(symm, l->v->co) == SYMM_SIDE_KEEP)
- fv[i] = BLI_ghash_lookup(symm->vert_symm_map, l->v);
- else
- fv[i] = l->v;
- }
-
- symm_face_create_v(symm->bm, f, fv, fe, f->len);
- }
- else if (ignore_all) {
- BM_face_kill(symm->bm, f);
- }
- else {
- SymmPoly sp;
- int l1, l2, l3, l4;
- int double_l2, double_l3;
- int segment_len;
+ const int direction = BMO_slot_int_get(op->slots_in, "direction");
+ const int axis = direction % 3;
- BLI_array_empty(pv);
- BLI_array_grow_items(pv, f->len * 4);
- sp.src_verts = pv;
- sp.edge_verts = pv + f->len * 2;
- symm_poly_with_splits(symm, f, &sp);
+ BMOperator op_bisect;
+ BMOperator op_dupe;
+ BMOperator op_weld;
- /* Find first loop edge crossing the axis */
- symm_poly_next_crossing(symm, &sp, 0, &l1, &l2);
+ BMOpSlot *slot_vertmap;
+ BMOpSlot *slot_targetmap;
- /* If crossing isn't kill to keep, find the next one */
- if (symm_poly_co_side(symm, &sp, l1) != SYMM_SIDE_KILL) {
- symm_poly_next_crossing(symm, &sp, l2, &l1, &l2);
- }
+ float plane_no[3];
+ float scale[3];
- /* Find next crossing (keep to kill) */
- symm_poly_next_crossing(symm, &sp, l2, &l3, &l4);
-
- if (l2 == l3)
- segment_len = 0;
- else if (l2 < l3)
- segment_len = l3 - l2 + 1;
- else
- segment_len = (sp.len - l2 + 1) + l3;
-
- double_l2 = symm_poly_co_side(symm, &sp, l2) == SYMM_SIDE_KEEP;
- double_l3 = symm_poly_co_side(symm, &sp, l3) == SYMM_SIDE_KEEP;
+ BMOIter siter;
+ BMVert *v;
- /* Calculate number of new polygons/loops */
- if (segment_len == 0) {
- }
- else if (sp.already_symmetric) {
- int new_loops;
+ copy_v3_fl(plane_no, 0.0f);
+ copy_v3_fl(scale, 1.0f);
- if (double_l2 && double_l3)
- new_loops = segment_len * 2;
- else if (!double_l2 && !double_l3)
- new_loops = segment_len * 2 - 2;
- else
- new_loops = segment_len * 2 - 1;
+ plane_no[axis] = direction > 2 ? 1.0f : -1.0f;
+ scale[axis] *= -1.0f;
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, new_loops);
- BLI_array_grow_items(fe, new_loops);
+ /* Cut in half */
+ BMO_op_initf(bm, &op_bisect, op->flag,
+ "bisect_plane geom=%s plane_no=%v dist=%f clear_outer=%b",
+ op, "input", plane_no, 0.00001f, true);
- symm_mesh_output_poly_zero_splits(symm, &sp,
- fv, fe,
- segment_len, l2);
- BM_face_kill(symm->bm, f);
- }
- else if (!double_l2 && !double_l3) {
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, segment_len);
- BLI_array_grow_items(fe, segment_len);
+ BMO_op_exec(bm, &op_bisect);
- symm_mesh_output_poly_with_splits(symm, &sp,
- fv, fe,
- segment_len,
- l2);
+ /* Duplicate */
+ BMO_op_initf(bm, &op_dupe, op->flag,
+ "duplicate geom=%S",
+ &op_bisect, "geom.out");
- BM_face_kill(symm->bm, f);
- }
- else {
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, segment_len);
- BLI_array_grow_items(fe, segment_len);
+ BMO_op_exec(bm, &op_dupe);
- symm_mesh_output_poly_with_splits(symm, &sp,
- fv, fe,
- segment_len,
- l2);
+ /* Flag for output (some will be merged) */
+ BMO_slot_buffer_flag_enable(bm, op_bisect.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
+ BMO_slot_buffer_flag_enable(bm, op_dupe.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
- BM_face_kill(symm->bm, f);
- /* Output bridge triangle */
+ BMO_op_callf(bm, op->flag, "scale verts=%S vec=%v", &op_dupe, "geom.out", scale);
+ BMO_op_callf(bm, op->flag, "reverse_faces faces=%S", &op_dupe, "geom.out");
- BLI_array_empty(fv);
- BLI_array_empty(fe);
- BLI_array_grow_items(fv, 3);
- BLI_array_grow_items(fe, 3);
- if (double_l2) {
- fv[0] = symm_poly_dst(&sp, l2);
- fv[1] = symm_poly_mirror_dst(symm, &sp, l2);
- fv[2] = symm_poly_dst(&sp, l3);
- }
- else if (double_l3) {
- fv[0] = symm_poly_dst(&sp, l3);
- fv[1] = symm_poly_mirror_dst(symm, &sp, l3);
- fv[2] = symm_poly_dst(&sp, l2);
- }
+ /* Weld verts */
+ BMO_op_init(bm, &op_weld, op->flag, "weld_verts");
- BLI_assert(fv[0] && fv[1] && fv[2]);
+ slot_vertmap = BMO_slot_get(op_dupe.slots_out, "vert_map.out");
+ slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
- symm_face_create_v(symm->bm, NULL, fv, fe, 3);
- }
- }
+ BMO_ITER (v, &siter, op_bisect.slots_out, "geom_cut.out", BM_VERT) {
+ BMVert *v_dupe = BMO_slot_map_elem_get(slot_vertmap, v);
+ BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_dupe, v);
}
- BLI_array_free(pv);
- BLI_array_free(fv);
- BLI_array_free(fe);
-}
-
-/* Remove unused edges and vertices from the side being copied to */
-static void symm_kill_unused(Symm *symm)
-{
- BMOIter oiter;
- BMEdge *e;
- BMVert *v;
-
- /* Kill unused edges */
- BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) {
- const int crosses = symm_edge_crosses_axis(symm, e);
- const int symmetric = (crosses &&
- (!BLI_ghash_haskey(symm->edge_split_map, e)));
-
- if (((symm_co_side(symm, e->v1->co) == SYMM_SIDE_KILL) ||
- (symm_co_side(symm, e->v2->co) == SYMM_SIDE_KILL)) &&
- !symmetric)
- {
- /* The edge might be used by a face outside the input set */
- if (BM_edge_is_wire(e))
- BM_edge_kill(symm->bm, e);
- }
- }
-
- /* Kill unused vertices */
- BMO_ITER (v, &oiter, symm->op->slots_in, "input", BM_VERT) {
- if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) {
- if (BM_vert_edge_count(v) == 0)
- BM_vert_kill(symm->bm, v);
- }
- }
-}
-
-void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
-{
- Symm symm;
- BMO_SymmDirection direction = BMO_slot_int_get(op->slots_in, "direction");
-
- symm.bm = bm;
- symm.op = op;
- symm.axis = (ELEM(direction,
- BMO_SYMMETRIZE_NEGATIVE_X,
- BMO_SYMMETRIZE_POSITIVE_X) ? 0 :
- ELEM(direction,
- BMO_SYMMETRIZE_NEGATIVE_Y,
- BMO_SYMMETRIZE_POSITIVE_Y) ? 1 :
- ELEM(direction,
- BMO_SYMMETRIZE_NEGATIVE_Z,
- BMO_SYMMETRIZE_POSITIVE_Z) ? 2 : 0);
- symm.direction = direction;
+ BMO_op_exec(bm, &op_weld);
- symm_verts_mirror(&symm);
- symm_split_asymmetric_edges(&symm);
- symm_mirror_edges(&symm);
- symm_mirror_polygons(&symm);
- symm_kill_unused(&symm);
+ /* Cleanup */
+ BMO_op_finish(bm, &op_weld);
- BLI_ghash_free(symm.vert_symm_map, NULL, NULL);
- BLI_ghash_free(symm.edge_split_map, NULL, NULL);
+ BMO_op_finish(bm, &op_dupe);
+ BMO_op_finish(bm, &op_bisect);
- BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out",
- BM_ALL_NOLOOP, SYMM_OUTPUT_GEOM);
+ /* Create output */
+ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 38ce56b4bc7..a0bb9839ca5 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -4445,6 +4445,10 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op)
BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"));
BMO_op_exec(em->bm, &bmop);
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true);
+
if (!EDBM_op_finish(em, &bmop, op, true)) {
return OPERATOR_CANCELLED;
}