[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59387] trunk/blender/source/blender: replace symmetrize code with calls to bmesh operators.

Campbell Barton ideasman42 at gmail.com
Thu Aug 22 20:02:36 CEST 2013


Revision: 59387
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59387
Author:   campbellbarton
Date:     2013-08-22 18:02:36 +0000 (Thu, 22 Aug 2013)
Log Message:
-----------
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.

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/operators/bmo_symmetrize.c
    trunk/blender/source/blender/editors/mesh/editmesh_tools.c

Modified: trunk/blender/source/blender/bmesh/operators/bmo_symmetrize.c
===================================================================
--- trunk/blender/source/blender/bmesh/operators/bmo_symmetrize.c	2013-08-22 17:56:08 UTC (rev 59386)
+++ trunk/blender/source/blender/bmesh/operators/bmo_symmetrize.c	2013-08-22 18:02:36 UTC (rev 59387)
@@ -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)
-};
+#define ELE_OUT 1
 
-/* 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)
+void bmo_symmetrize_exec(BMesh *bm, BMOperator *op)
 {
-	float comp = co[symm->axis];
-	if (ELEM3(symm->direction,
-	          BMO_SYMMETRIZE_NEGATIVE_X,
-	          BMO_SYMMETRIZE_NEGATIVE_Y,
-	          BMO_SYMMETRIZE_NEGATIVE_Z))
-	{
-		comp = -comp;
-	}
+	const int direction = BMO_slot_int_get(op->slots_in, "direction");
+	const int axis = direction % 3;
 
-	if (comp >= 0) {
-		if (comp < SYMM_AXIS_THRESHOLD)
-			return SYMM_SIDE_AXIS;
-		else
-			return SYMM_SIDE_KEEP;
-	}
-	else
-		return SYMM_SIDE_KILL;
-}
+	BMOperator op_bisect;
+	BMOperator op_dupe;
+	BMOperator op_weld;
 
-/* Output vertices and the vert_map array */
-static void symm_verts_mirror(Symm *symm)
-{
-	BMOIter oiter;
-	BMVert *src_v, *dst_v;
+	BMOpSlot *slot_vertmap;
+	BMOpSlot *slot_targetmap;
 
-	symm->vert_symm_map = BLI_ghash_ptr_new(__func__);
+	float plane_no[3];
+	float scale[3];
 
-	BMO_ITER (src_v, &oiter, symm->op->slots_in, "input", BM_VERT) {
-		SymmSide side = symm_co_side(symm, src_v->co);
-		float co[3];
+	BMOIter siter;
+	BMVert *v;
 
-		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];
+	copy_v3_fl(plane_no, 0.0f);
+	copy_v3_fl(scale, 1.0f);
 
-				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;
+	plane_no[axis] = direction > 2 ? 1.0f : -1.0f;
+	scale[axis] *= -1.0f;
 
-			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;
+	/* 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);
 
-			case SYMM_SIDE_KILL:
-				/* The vertex does not lie in the half-space being
-				 * copied from, nothing to do */
-				break;
-		}
-	}
-}
+	BMO_op_exec(bm, &op_bisect);
 
-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)};
+	/* Duplicate */
+	BMO_op_initf(bm, &op_dupe, op->flag,
+	             "duplicate geom=%S",
+	             &op_bisect, "geom.out");
 
-	return ((sides[0] != SYMM_SIDE_AXIS) &&
-	        (sides[1] != SYMM_SIDE_AXIS) &&
-	        (sides[0] != sides[1]));
-}
+	BMO_op_exec(bm, &op_dupe);
 
-/* 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;
+	/* 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);
 
-	symm->edge_split_map = BLI_ghash_ptr_new(__func__);
 
-	BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) {
-		float flipped[3];
+	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");
 
-		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 */
+	/* Weld verts */
+	BMO_op_init(bm, &op_weld, op->flag, "weld_verts");
 
-			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;
+	slot_vertmap = BMO_slot_get(op_dupe.slots_out, "vert_map.out");
+	slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap");
 
-			/* 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);
-
-			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);
-		}
+	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);
 	}
-}
 
-static void symm_mirror_edges(Symm *symm)
-{
-	BMOIter oiter;
-	BMEdge *e;
+	BMO_op_exec(bm, &op_weld);
 
-	BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) {
-		BMVert *v1 = NULL, *v2 = NULL;
-		BMEdge *e_new;
+	/* Cleanup */
+	BMO_op_finish(bm, &op_weld);
 
-		v1 = BLI_ghash_lookup(symm->vert_symm_map, e->v1);
-		v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2);
+	BMO_op_finish(bm, &op_dupe);
+	BMO_op_finish(bm, &op_bisect);
 
-		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);
-			}
-		}
-	}
+	/* Create output */
+	BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT);
 }
-
-/****************************** 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;
-}
-

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list