[Bf-blender-cvs] [41564a4] master: BMesh: flatten faces operator

Campbell Barton noreply at git.blender.org
Thu Jun 11 13:54:37 CEST 2015


Commit: 41564a402ebc317304b8f063d7729d12bad76978
Author: Campbell Barton
Date:   Thu Jun 11 21:46:51 2015 +1000
Branches: master
https://developer.blender.org/rB41564a402ebc317304b8f063d7729d12bad76978

BMesh: flatten faces operator

===================================================================

M	release/scripts/startup/bl_ui/space_view3d.py
M	source/blender/bmesh/CMakeLists.txt
M	source/blender/bmesh/intern/bmesh_opdefines.c
M	source/blender/bmesh/intern/bmesh_operators_private.h
A	source/blender/bmesh/operators/bmo_planar_faces.c
M	source/blender/editors/mesh/editmesh_tools.c
M	source/blender/editors/mesh/mesh_intern.h
M	source/blender/editors/mesh/mesh_ops.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 4bbd3cc..eb681b7 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2439,6 +2439,7 @@ class VIEW3D_MT_edit_mesh_clean(Menu):
 
         layout.operator("mesh.dissolve_degenerate")
         layout.operator("mesh.dissolve_limited")
+        layout.operator("mesh.face_make_planar")
         layout.operator("mesh.vert_connect_nonplanar")
         layout.operator("mesh.vert_connect_concave")
         layout.operator("mesh.fill_holes")
diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt
index 80adb59..2946e1b 100644
--- a/source/blender/bmesh/CMakeLists.txt
+++ b/source/blender/bmesh/CMakeLists.txt
@@ -61,6 +61,7 @@ set(SRC
 	operators/bmo_mesh_conv.c
 	operators/bmo_mirror.c
 	operators/bmo_normals.c
+	operators/bmo_planar_faces.c
 	operators/bmo_poke.c
 	operators/bmo_primitive.c
 	operators/bmo_removedoubles.c
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index ce988c6..096c307 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -160,6 +160,28 @@ static BMOpDefine bmo_recalc_face_normals_def = {
 };
 
 /*
+ * Planar Faces.
+ *
+ * Iteratively flatten faces.
+ */
+static BMOpDefine bmo_planar_faces_def = {
+	"planar_faces",
+	/* slots_in */
+	{{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}},    /* input geometry. */
+	 {"iterations", BMO_OP_SLOT_INT},
+	 {"factor", BMO_OP_SLOT_FLT},           /* planar factor */
+	 {{'\0'}},
+	},
+	/* slots_out */
+	{{"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* output slot, computed boundary geometry. */
+	 {{'\0'}},
+	},
+	bmo_planar_faces_exec,
+	(BMO_OPTYPE_FLAG_SELECT_FLUSH |
+	 BMO_OPTYPE_FLAG_SELECT_VALIDATE),
+};
+
+/*
  * Region Extend.
  *
  * used to implement the select more/less tools.
@@ -2018,6 +2040,7 @@ const BMOpDefine *bmo_opdefines[] = {
 	&bmo_pointmerge_facedata_def,
 	&bmo_poke_def,
 	&bmo_recalc_face_normals_def,
+	&bmo_planar_faces_def,
 	&bmo_region_extend_def,
 	&bmo_remove_doubles_def,
 	&bmo_reverse_colors_def,
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
index 979f7d2..25340ee 100644
--- a/source/blender/bmesh/intern/bmesh_operators_private.h
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -82,6 +82,7 @@ void bmo_pointmerge_exec(BMesh *bm, BMOperator *op);
 void bmo_pointmerge_facedata_exec(BMesh *bm, BMOperator *op);
 void bmo_recalc_face_normals_exec(BMesh *bm, BMOperator *op);
 void bmo_poke_exec(BMesh *bm, BMOperator *op);
+void bmo_planar_faces_exec(BMesh *bm, BMOperator *op);
 void bmo_region_extend_exec(BMesh *bm, BMOperator *op);
 void bmo_remove_doubles_exec(BMesh *bm, BMOperator *op);
 void bmo_reverse_colors_exec(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/operators/bmo_planar_faces.c b/source/blender/bmesh/operators/bmo_planar_faces.c
new file mode 100644
index 0000000..4e3ac58
--- /dev/null
+++ b/source/blender/bmesh/operators/bmo_planar_faces.c
@@ -0,0 +1,158 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/bmesh/operators/bmo_planar_faces.c
+ *  \ingroup bmesh
+ *
+ * Iternatively flatten 4+ sided faces.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_ghash.h"
+
+#include "bmesh.h"
+
+#include "intern/bmesh_operators_private.h" /* own include */
+
+#define ELE_VERT_ADJUST (1 << 0)
+#define ELE_FACE_ADJUST (1 << 1)
+
+struct VertAccum {
+	float co[3];
+	int co_tot;
+};
+
+void bmo_planar_faces_exec(BMesh *bm, BMOperator *op)
+{
+	const float fac = BMO_slot_float_get(op->slots_in, "factor");
+	const int iterations = BMO_slot_int_get(op->slots_in, "iterations");
+	const int faces_num = BMO_slot_buffer_count(op->slots_in, "faces");
+
+	const float eps = 0.00001f;
+	const float eps_sq = SQUARE(eps);
+
+	BMOIter oiter;
+	BMFace *f;
+	BLI_mempool *vert_accum_pool;
+	GHash *vaccum_map;
+	float (*faces_center)[3];
+	int i, iter_step, shared_vert_num;
+
+	faces_center = MEM_mallocN(sizeof(*faces_center) * faces_num, __func__);
+
+	shared_vert_num = 0;
+	BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
+		BMLoop *l_iter, *l_first;
+
+		if (f->len == 3) {
+			continue;
+		}
+
+		BM_face_calc_center_mean_weighted(f, faces_center[i]);
+
+		l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+		do {
+			if (!BMO_elem_flag_test(bm, l_iter->v, ELE_VERT_ADJUST)) {
+				BMO_elem_flag_enable(bm, l_iter->v, ELE_VERT_ADJUST);
+				shared_vert_num += 1;
+			}
+		} while ((l_iter = l_iter->next) != l_first);
+
+		BMO_elem_flag_enable(bm, f, ELE_FACE_ADJUST);
+	}
+
+	vert_accum_pool = BLI_mempool_create(sizeof(struct VertAccum), 0, 512, BLI_MEMPOOL_NOP);
+	vaccum_map = BLI_ghash_ptr_new_ex(__func__, shared_vert_num);
+
+	for (iter_step = 0; iter_step < iterations; iter_step++) {
+		GHashIterator gh_iter;
+		bool changed = false;
+
+		BMO_ITER_INDEX (f, &oiter, op->slots_in, "faces", BM_FACE, i) {
+			BMLoop *l_iter, *l_first;
+			float plane[4];
+
+			if (!BMO_elem_flag_test(bm, f, ELE_FACE_ADJUST)) {
+				continue;
+			}
+			BMO_elem_flag_disable(bm, f, ELE_FACE_ADJUST);
+
+			BLI_assert(f->len != 3);
+
+			/* keep original face data (else we 'move' the face) */
+#if 0
+			BM_face_normal_update(f);
+			BM_face_calc_center_mean_weighted(f, f_center);
+#endif
+
+			plane_from_point_normal_v3(plane, faces_center[i], f->no);
+
+			l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+			do {
+				struct VertAccum *va;
+				void **va_p;
+				float co[3];
+
+				if (!BLI_ghash_ensure_p(vaccum_map, l_iter->v, &va_p)) {
+					*va_p = BLI_mempool_calloc(vert_accum_pool);
+				}
+				va = *va_p;
+
+				closest_to_plane_v3(co, plane, l_iter->v->co);
+				va->co_tot += 1;
+
+				interp_v3_v3v3(va->co, va->co, co, 1.0f / (float)va->co_tot);
+			} while ((l_iter = l_iter->next) != l_first);
+		}
+
+		GHASH_ITER (gh_iter, vaccum_map) {
+			BMVert *v = BLI_ghashIterator_getKey(&gh_iter);
+			struct VertAccum *va = BLI_ghashIterator_getValue(&gh_iter);
+			BMIter iter;
+
+			if (len_squared_v3v3(v->co, va->co) > eps_sq) {
+				BMO_elem_flag_enable(bm, v, ELE_VERT_ADJUST);
+				interp_v3_v3v3(v->co, v->co, va->co, fac);
+				changed = true;
+			}
+
+			/* tag for re-calculation */
+			BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) {
+				if (f->len != 3) {
+					BMO_elem_flag_enable(bm, f, ELE_FACE_ADJUST);
+				}
+			}
+		}
+
+		/* if nothing changed, break out early */
+		if (changed == false) {
+			break;
+		}
+
+		BLI_ghash_clear(vaccum_map, NULL, NULL);
+		BLI_mempool_clear(vert_accum_pool);
+	}
+
+	MEM_freeN(faces_center);
+	BLI_ghash_free(vaccum_map, NULL, NULL);
+	BLI_mempool_destroy(vert_accum_pool);
+}
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 50419cb..62aec78 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -1309,6 +1309,44 @@ void MESH_OT_vert_connect_nonplanar(wmOperatorType *ot)
 	RNA_def_property_float_default(prop, DEG2RADF(5.0f));
 }
 
+static int edbm_face_make_planar_exec(bContext *C, wmOperator *op)
+{
+	Object *obedit = CTX_data_edit_object(C);
+	BMEditMesh *em = BKE_editmesh_from_object(obedit);
+	const int repeat = RNA_int_get(op->ptr, "repeat");
+	const float fac = RNA_float_get(op->ptr, "factor");
+
+	if (!EDBM_op_callf(
+	        em, op, "planar_faces faces=%hf iterations=%i factor=%f",
+	        BM_ELEM_SELECT, repeat, fac))
+	{
+		return OPERATOR_CANCELLED;
+	}
+
+	EDBM_update_generic(em, true, true);
+	return OPERATOR_FINISHED;
+}
+
+void MESH_OT_face_make_planar(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Make Planar Faces";
+	ot->idname = "MESH_OT_face_make_planar";
+	ot->description = "Flatten selected faces";
+
+	/* api callbacks */
+	ot->exec = edbm_face_make_planar_exec;
+	ot->poll = ED_operator_editmesh;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+	/* props */
+	RNA_def_float(ot->srna, "factor", 0.5f, -10.0f, 10.0f, "Factor", "", 0.0f, 1.0f);
+	RNA_def_int(ot->srna, "repeat", 1, 1, 200,
+	            "Number of iterations to flatten faces", "", 1, 200);
+}
+
 
 static int edbm_edge_split_exec(bContext *C, wmOperator *op)
 {
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 9226146..8c44d5a 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -173,6 +173,7 @@ void MESH_OT_vert_connect(struct wmOperatorType *ot);
 void MESH_OT_vert_connect_path(struct wmOperatorType *ot);
 void MESH_OT_vert_connect_concave(struct wmOperatorType *ot);
 void MESH_OT_vert_connect_nonplanar(struct wmOperatorType *ot);
+void MESH_OT_face_make_planar(struct wmOperatorType *ot);
 void MESH_OT_edge_split(struct wmOperatorType *ot);
 void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot);
 void MESH_OT_wireframe(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index 197df48..20f222b 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -167,6 +167,7 @@ void ED_operatortypes_mesh(void)
 	WM_operatortype_append(MESH_OT_vert_connect_path);
 	WM_operator

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list