[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [59330] trunk/blender/source/blender: fix [#36352] Inset individual, uncheck "select outer" selects zero faces

Campbell Barton ideasman42 at gmail.com
Tue Aug 20 18:59:04 CEST 2013


Revision: 59330
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=59330
Author:   campbellbarton
Date:     2013-08-20 16:59:04 +0000 (Tue, 20 Aug 2013)
Log Message:
-----------
fix [#36352] Inset individual, uncheck "select outer" selects zero faces

rewrite individual inset not to remove and re-create faces, makes re-selection simpler.

Modified Paths:
--------------
    trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c
    trunk/blender/source/blender/bmesh/operators/bmo_inset.c
    trunk/blender/source/blender/editors/mesh/editmesh_inset.c

Modified: trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c
===================================================================
--- trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c	2013-08-20 16:56:46 UTC (rev 59329)
+++ trunk/blender/source/blender/bmesh/intern/bmesh_opdefines.c	2013-08-20 16:59:04 UTC (rev 59330)
@@ -1624,7 +1624,7 @@
 	 {{'\0'}},
 	},
 	bmo_inset_individual_exec,
-	BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH,
+	BMO_OPTYPE_FLAG_NORMALS_CALC,  /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */
 };
 
 /*

Modified: trunk/blender/source/blender/bmesh/operators/bmo_inset.c
===================================================================
--- trunk/blender/source/blender/bmesh/operators/bmo_inset.c	2013-08-20 16:56:46 UTC (rev 59329)
+++ trunk/blender/source/blender/bmesh/operators/bmo_inset.c	2013-08-20 16:59:04 UTC (rev 59330)
@@ -32,6 +32,7 @@
 
 #include "BLI_math.h"
 #include "BLI_array.h"
+#include "BLI_alloca.h"
 #include "BLI_memarena.h"
 #include "BKE_customdata.h"
 
@@ -42,199 +43,249 @@
 #define ELE_NEW		1
 
 
-
 /* -------------------------------------------------------------------- */
-/* Inset Individual */
+/* Generic Interp Face (use for both types of inset) */
 
+/**
+ * Interpolation, this is more complex for regions since we're not creating new faces
+ * and throwing away old ones, so instead, store face data needed for interpolation.
+ *
+ * \note This uses CustomData functions in quite a low-level way which should be
+ * avoided, but in this case its hard to do without storing a duplicate mesh. */
 
-/* Holds Per-Face Inset Edge Data */
-typedef struct EdgeInsetInfo {
-	float no[3];
-	BMEdge *e_old;
-	BMEdge *e_new;
-} EdgeInsetInfo;
+/* just enough of a face to store interpolation data we can use once the inset is done */
+typedef struct InterpFace {
+	BMFace *f;
+	void **blocks_l;
+	void **blocks_v;
+	float (*cos_2d)[2];
+	float axis_mat[3][3];
+} InterpFace;
 
-/**
- * Individual Face Inset.
- * Find all tagged faces (f), duplicate edges around faces, inset verts of
- * created edges, create new faces between old and new edges, fill face
- * between connected new edges, kill old face (f).
- */
-void bmo_inset_individual_exec(BMesh *bm, BMOperator *op)
+/* basically a clone of #BM_vert_interp_from_face */
+static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena)
 {
-	BMEdge **f_edges = NULL;
-	BMVert **f_verts = NULL;
-	BMFace *f;
+	BMLoop *l_iter, *l_first;
+	void **blocks_l    = iface->blocks_l = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_l) * f->len);
+	void **blocks_v    = iface->blocks_v = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_v) * f->len);
+	float (*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena, sizeof(*iface->cos_2d) * f->len);
+	void *axis_mat     = iface->axis_mat;
+	int i;
 
-	BMOIter oiter;
-	EdgeInsetInfo *eiinfo_arr = NULL;
+	BLI_assert(BM_face_is_normal_valid(f));
 
-	BLI_array_declare(eiinfo_arr);
-	BLI_array_declare(f_edges);
-	BLI_array_declare(f_verts);
+	axis_dominant_v3_to_m3(axis_mat, f->no);
 
-	const float thickness = BMO_slot_float_get(op->slots_in, "thickness");
-	const float depth = BMO_slot_float_get(op->slots_in, "depth");
-	const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset");
-	const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset");
-	const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate");
+	iface->f = f;
 
-	/* Only tag faces in slot */
-	BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
+	i = 0;
+	l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+	do {
+		mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co);
+		blocks_l[i] = NULL;
+		CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]);
+		/* if we were not modifying the loops later we would do... */
+		// blocks[i] = l_iter->head.data;
 
-	BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false);
+		blocks_v[i] = NULL;
+		CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]);
 
-	BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) {
-		BMFace *f_new_inner;
-		BMLoop *l_iter, *l_first;
-		BMLoop *l_iter_inner = NULL;
-		int i;
+		/* use later for index lookups */
+		BM_elem_index_set(l_iter, i); /* set_ok */
+	} while (i++, (l_iter = l_iter->next) != l_first);
+}
+static void bm_interp_face_free(InterpFace *iface, BMesh *bm)
+{
+	void **blocks_l = iface->blocks_l;
+	void **blocks_v = iface->blocks_v;
+	int i;
 
-		BLI_array_empty(f_verts);
-		BLI_array_empty(f_edges);
-		BLI_array_empty(eiinfo_arr);
-		BLI_array_grow_items(f_verts, f->len);
-		BLI_array_grow_items(f_edges, f->len);
-		BLI_array_grow_items(eiinfo_arr, f->len);
+	for (i = 0; i < iface->f->len; i++) {
+		CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]);
+		CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]);
+	}
+}
 
-		/* create verts */
-		i = 0;
-		l_iter = l_first = BM_FACE_FIRST_LOOP(f);
-		do {
-			f_verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0);
-			i++;
-		} while ((l_iter = l_iter->next) != l_first);
 
-		/* make edges */
-		i = 0;
-		l_iter = l_first;
-		do {
-			f_edges[i] = BM_edge_create(bm, f_verts[i], f_verts[(i + 1) % f->len], l_iter->e, 0);
+/* -------------------------------------------------------------------- */
+/* Inset Individual */
 
-			eiinfo_arr[i].e_new = f_edges[i];
-			eiinfo_arr[i].e_old = l_iter->e;
-			BM_edge_calc_face_tangent(l_iter->e, l_iter, eiinfo_arr[i].no);
+static void bmo_face_inset_individual(
+        BMesh *bm, BMFace *f, MemArena *interp_arena,
+        const float thickness, const float depth,
+        const bool use_even_offset, const bool use_relative_offset, const bool use_interpolate)
+{
+	InterpFace *iface = NULL;
 
-			/* Tagging (old elements) required when iterating over edges
-			 * connected to verts for translation vector calculation */
-			BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG);
-			BM_elem_index_set(l_iter->e, i);  /* set_dirty! */
-			i++;
-		} while ((l_iter = l_iter->next) != l_first);
-		/* done with edges */
+	/* stores verts split away from the face (aligned with face verts) */
+	BMVert **verts = BLI_array_alloca(verts, f->len);
+	/* store edge normals (aligned with face-loop-edges) */
+	float (*edge_nors)[3] = BLI_array_alloca(edge_nors, f->len);
+	float (*coords)[3] = BLI_array_alloca(coords, f->len);
 
-		bm->elem_index_dirty |= BM_EDGE;
+	BMLoop *l_iter, *l_first;
+	BMLoop *l_other;
+	unsigned int i;
 
-		/* Calculate translation vector for new  */
-		l_iter = l_first;
-		do {
-			EdgeInsetInfo *ei_prev = &eiinfo_arr[BM_elem_index_get(l_iter->prev->e)];
-			EdgeInsetInfo *ei_next = &eiinfo_arr[BM_elem_index_get(l_iter->e)];
-			float tvec[3];
-			float v_new_co[3];
-			int index = 0;
+	l_first = BM_FACE_FIRST_LOOP(f);
 
-			add_v3_v3v3(tvec, ei_prev->no, ei_next->no);
-			normalize_v3(tvec);
+	/* split off all loops */
+	l_iter = l_first;
+	i = 0;
+	do {
+		BMVert *v_other = l_iter->v;
+		BMVert *v_sep = BM_face_loop_separate(bm, l_iter);
+		if (v_sep == v_other) {
+			v_other = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0);
+		}
+		verts[i] = v_other;
 
-			/* l->e is traversed in order */
-			index = BM_elem_index_get(l_iter->e);
+		/* unrelated to splitting, but calc here */
+		BM_edge_calc_face_tangent(l_iter->e, l_iter, edge_nors[i]);
+	} while (i++, ((l_iter = l_iter->next) != l_first));
 
-			copy_v3_v3(v_new_co, eiinfo_arr[index].e_new->v1->co);
 
-			if (use_even_offset) {
-				mul_v3_fl(tvec, shell_angle_to_dist(angle_normalized_v3v3(ei_prev->no,  ei_next->no) / 2.0f));
-			}
+	/* build rim faces */
+	l_iter = l_first;
+	i = 0;
+	do {
+		BMFace *f_new_outer;
+		BMVert *v_other = verts[i];
+		BMVert *v_other_next = verts[(i + 1) % f->len];
 
-			/* Modify vertices and their normals */
-			if (use_relative_offset) {
-				mul_v3_fl(tvec, (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f);
-			}
+		BMEdge *e_other = BM_edge_create(bm, v_other, v_other_next, l_iter->e, BM_CREATE_NO_DOUBLE);
+		(void)e_other;
 
-			madd_v3_v3fl(v_new_co, tvec, thickness);
+		f_new_outer = BM_face_create_quad_tri(bm,
+		                                      v_other,
+		                                      v_other_next,
+		                                      l_iter->next->v,
+		                                      l_iter->v,
+		                                      f, false);
+		BMO_elem_flag_enable(bm, f_new_outer, ELE_NEW);
 
-			/* Set normal, add depth and write new vertex position*/
-			copy_v3_v3(eiinfo_arr[index].e_new->v1->no, f->no);
+		/* copy loop data */
+		l_other = l_iter->radial_next;
+		BM_elem_attrs_copy(bm, bm, l_iter->next, l_other->prev);
+		BM_elem_attrs_copy(bm, bm, l_iter, l_other->next->next);
 
-			madd_v3_v3fl(v_new_co, f->no, depth);
+		if (use_interpolate == false) {
+			BM_elem_attrs_copy(bm, bm, l_iter->next, l_other);
+			BM_elem_attrs_copy(bm, bm, l_iter, l_other->next);
+		}
+	} while (i++, ((l_iter = l_iter->next) != l_first));
 
-			copy_v3_v3(eiinfo_arr[index].e_new->v1->co, v_new_co);
-		} while ((l_iter = l_iter->next) != l_first);
+	/* hold interpolation values */
+	if (use_interpolate) {
+		iface = BLI_memarena_alloc(interp_arena, sizeof(*iface));
+		bm_interp_face_store(iface, bm, f, interp_arena);
+	}
 
+	/* Calculate translation vector for new */
+	l_iter = l_first;
+	i = 0;
+	do {
+		const float *eno_prev = edge_nors[(i ? i : f->len) - 1];
+		const float *eno_next = edge_nors[i];
+		float tvec[3];
+		float v_new_co[3];
 
-		/* Create New Inset Faces */
-		f_new_inner = BM_face_create(bm, f_verts, f_edges, f->len, 0);
-		BLI_assert(f_new_inner != NULL);  /* no reason it should fail */
+		add_v3_v3v3(tvec, eno_prev, eno_next);
+		normalize_v3(tvec);
 
+		copy_v3_v3(v_new_co, l_iter->v->co);
 
-		// Don't tag, gives more useful inner/outer select option
-		// BMO_elem_flag_enable(bm, f_new_inner, ELE_NEW);
+		if (use_even_offset) {
+			mul_v3_fl(tvec, shell_angle_to_dist(angle_normalized_v3v3(eno_prev,  eno_next) / 2.0f));
+		}
 
-
-		/* Copy Face Data */
-		/* interpolate loop data or just stretch */
-		if (use_interpolate) {
-			BM_face_interp_from_face(bm, f_new_inner, f, true);
+		/* Modify vertices and their normals */
+		if (use_relative_offset) {
+			mul_v3_fl(tvec, (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f);
 		}
-		else {

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list