[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [55303] trunk/blender/source/blender/ editors/mesh: knife projection feature,

Campbell Barton ideasman42 at gmail.com
Fri Mar 15 14:06:32 CET 2013


Revision: 55303
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=55303
Author:   campbellbarton
Date:     2013-03-15 13:06:31 +0000 (Fri, 15 Mar 2013)
Log Message:
-----------
knife projection feature,
apart of 3d printing tools - use to cookie-cut text into a mesh.

Modified Paths:
--------------
    trunk/blender/source/blender/editors/mesh/CMakeLists.txt
    trunk/blender/source/blender/editors/mesh/editmesh_knife.c
    trunk/blender/source/blender/editors/mesh/mesh_intern.h
    trunk/blender/source/blender/editors/mesh/mesh_ops.c

Added Paths:
-----------
    trunk/blender/source/blender/editors/mesh/editmesh_knife_project.c

Modified: trunk/blender/source/blender/editors/mesh/CMakeLists.txt
===================================================================
--- trunk/blender/source/blender/editors/mesh/CMakeLists.txt	2013-03-15 11:59:46 UTC (rev 55302)
+++ trunk/blender/source/blender/editors/mesh/CMakeLists.txt	2013-03-15 13:06:31 UTC (rev 55303)
@@ -43,6 +43,7 @@
 	editmesh_add.c
 	editmesh_bvh.c
 	editmesh_knife.c
+	editmesh_knife_project.c
 	editmesh_loopcut.c
 	editmesh_rip.c
 	editmesh_select.c

Modified: trunk/blender/source/blender/editors/mesh/editmesh_knife.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_knife.c	2013-03-15 11:59:46 UTC (rev 55302)
+++ trunk/blender/source/blender/editors/mesh/editmesh_knife.c	2013-03-15 13:06:31 UTC (rev 55303)
@@ -37,6 +37,7 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_array.h"
+#include "BLI_linklist.h"
 #include "BLI_math.h"
 #include "BLI_smallhash.h"
 #include "BLI_memarena.h"
@@ -3270,3 +3271,167 @@
 	RNA_def_boolean(ot->srna, "use_occlude_geometry", TRUE, "Occlude Geometry", "Only cut the front most geometry");
 	RNA_def_boolean(ot->srna, "only_selected", FALSE, "Only Selected", "Only cut selected geometry");
 }
+
+
+/* -------------------------------------------------------------------- */
+/* Knife tool as a utility function
+ * that can be used for internal slicing operations */
+
+static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, float projmat[4][4])
+{
+	float co[3];
+	float co_ss[2];
+
+	{
+		BMLoop *l;
+		float tangent[3];
+
+		l = BM_FACE_FIRST_LOOP(f);
+		BM_loop_calc_face_tangent(l, tangent);
+		/* get a point inside the face (tiny offset) - we could be more clever here */
+		mul_v3_fl(tangent, 0.02f);
+		add_v3_v3v3(co, l->v->co, tangent);
+	}
+
+	ED_view3d_project_float_v3_m4(ar, co, co_ss, projmat);
+
+	/* check */
+	{
+		LinkNode *p = polys;
+		int isect = 0;
+
+		while (p) {
+			const float (*mval_fl)[2] = p->link;
+			const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
+			isect += (int)isect_point_poly_v2(co_ss, mval_fl, mval_tot - 1);
+			p = p->next;
+		}
+
+		if (isect % 2) {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * \param use_tag  When set, tag all faces inside the polylines.
+ */
+void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag)
+{
+	KnifeTool_OpData *kcd;
+
+	view3d_operator_needs_opengl(C);
+
+	/* init */
+	{
+		const bool only_select = false;
+		const bool cut_through = false;
+
+		kcd = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
+
+		knifetool_init(C, kcd, only_select, cut_through);
+
+		kcd->ignore_edge_snapping = true;
+		kcd->ignore_vert_snapping = true;
+
+		if (use_tag) {
+			BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
+		}
+	}
+
+	/* execute */
+	{
+		LinkNode *p = polys;
+
+		knife_recalc_projmat(kcd);
+
+		while (p) {
+			const float (*mval_fl)[2] = p->link;
+			const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
+			int i;
+
+			for (i = 0; i < mval_tot; i++) {
+				knifetool_update_mval(kcd, mval_fl[i]);
+				if (i == 0) {
+					knife_start_cut(kcd);
+					kcd->mode = MODE_DRAGGING;
+				}
+				else {
+					knife_add_cut(kcd);
+				}
+			}
+			knife_finish_cut(kcd);
+			kcd->mode = MODE_IDLE;
+			p = p->next;
+		}
+	}
+
+	/* finish */
+	{
+		knifetool_finish_ex(kcd);
+
+		/* tag faces inside! */
+		if (use_tag) {
+			BMesh *bm = kcd->em->bm;
+			float projmat[4][4];
+
+			BMEdge *e;
+			BMIter iter;
+
+			bool keep_search;
+
+			ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, projmat);
+
+			BM_mesh_elem_hflag_disable_all(kcd->em->bm, BM_FACE, BM_ELEM_TAG, false);
+
+			BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+
+				/* check are we tagged?, then we are an original face */
+				if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
+					BMFace *f;
+					BMIter fiter;
+					BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
+
+						/* if we trusy b*/
+						if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) {
+							BM_elem_flag_enable(f, BM_ELEM_TAG);
+						}
+					}
+				}
+			}
+
+			do {
+				BMFace *f;
+				keep_search = false;
+				BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+					if (BM_elem_flag_test(f, BM_ELEM_TAG) == false) {
+						/* am I connected to a tagged face via a tagged edge (ie, not across a cut) */
+						BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
+						BMLoop *l_iter = l_first;
+						int found = false;
+
+						do {
+							if (BM_elem_flag_test(l_iter, BM_ELEM_TAG) != false) {
+								found = true;
+								break;
+							}
+						} while ((l_iter = l_iter->next) != l_first);
+
+						if (found) {
+							// if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat))
+							{
+								BM_elem_flag_enable(f, BM_ELEM_TAG);
+								keep_search = true;
+							}
+						}
+					}
+				}
+			} while (keep_search);
+		}
+
+		knifetool_exit_ex(C, kcd);
+		kcd = NULL;
+	}
+}

Added: trunk/blender/source/blender/editors/mesh/editmesh_knife_project.c
===================================================================
--- trunk/blender/source/blender/editors/mesh/editmesh_knife_project.c	                        (rev 0)
+++ trunk/blender/source/blender/editors/mesh/editmesh_knife_project.c	2013-03-15 13:06:31 UTC (rev 55303)
@@ -0,0 +1,163 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2007 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/mesh/editmesh_knife_project.c
+ *  \ingroup edmesh
+ */
+
+#include "DNA_curve_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_linklist.h"
+#include "BLI_listbase.h"
+
+#include "BKE_library.h"
+#include "BKE_mesh.h"
+#include "BKE_context.h"
+#include "BKE_curve.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_tessmesh.h"
+#include "BKE_report.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "mesh_intern.h"
+
+
+static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object *ob, LinkNode *polys)
+{
+	DerivedMesh *dm;
+	bool dm_needsFree;
+
+	if (ob->type == OB_MESH || ob->derivedFinal) {
+		dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH);
+		dm_needsFree = false;
+	}
+	else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+		dm = CDDM_from_curve(ob);
+		dm_needsFree = true;
+	}
+
+	if (dm) {
+		ListBase nurbslist = {NULL, NULL};
+		float projmat[4][4];
+
+		BKE_mesh_to_curve_nurblist(dm, &nurbslist, 0);  /* wire */
+		BKE_mesh_to_curve_nurblist(dm, &nurbslist, 1);  /* boundary */
+
+		ED_view3d_ob_project_mat_get(ar->regiondata, ob, projmat);
+
+		if (nurbslist.first) {
+			Nurb *nu;
+			for (nu = nurbslist.first; nu; nu = nu->next) {
+				if (nu->bp) {
+					int a;
+					BPoint *bp;
+					bool is_cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0;
+					float (*mval)[2] = MEM_mallocN(sizeof(*mval) * (nu->pntsu + is_cyclic), __func__);
+
+					for (bp = nu->bp, a = 0; a < nu->pntsu; a++, bp++) {
+						ED_view3d_project_float_v3_m4(ar, bp->vec, mval[a], projmat);
+					}
+					if (is_cyclic) {
+						copy_v2_v2(mval[a], mval[0]);
+					}
+
+					BLI_linklist_prepend(&polys, mval);
+				}
+			}
+		}
+
+		BKE_nurbList_free(&nurbslist);
+
+		if (dm_needsFree) {
+			dm->release(dm);
+		}
+	}
+
+
+	return polys;
+}
+
+static int knifeproject_exec(bContext *C, wmOperator *op)
+{
+	ARegion *ar = CTX_wm_region(C);
+	Scene *scene = CTX_data_scene(C);
+	Object *obedit = CTX_data_edit_object(C);
+	BMEditMesh *em = BMEdit_FromObject(obedit);
+
+	LinkNode *polys = NULL;
+
+	CTX_DATA_BEGIN (C, Object *, ob, selected_objects)
+	{
+		if (ob != obedit) {
+			polys = knifeproject_poly_from_object(ar, scene, ob, polys);
+		}
+	}
+	CTX_DATA_END;
+
+	if (polys) {
+		EDBM_mesh_knife(C, polys, true);
+
+		/* select only tagged faces */
+		BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
+		BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, BM_ELEM_TAG);
+
+		BLI_linklist_freeN(polys);
+
+		return OPERATOR_FINISHED;
+	}
+	else {
+		BKE_report(op->reports, RPT_ERROR, "No other selected objects found to use for projection");
+		return OPERATOR_CANCELLED;
+	}
+}
+
+void MESH_OT_knife_project(wmOperatorType *ot)
+{
+	/* description */
+	ot->name = "Knife Project";
+	ot->idname = "MESH_OT_knife_project";
+	ot->description = "Use other objects outlines & boundaries to project knife cuts";
+
+	/* callbacks */
+	ot->exec = knifeproject_exec;
+	ot->poll = ED_operator_editmesh_view3d;
+
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
+}
+


Property changes on: trunk/blender/source/blender/editors/mesh/editmesh_knife_project.c
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: trunk/blender/source/blender/editors/mesh/mesh_intern.h
===================================================================
--- trunk/blender/source/blender/editors/mesh/mesh_intern.h	2013-03-15 11:59:46 UTC (rev 55302)
+++ trunk/blender/source/blender/editors/mesh/mesh_intern.h	2013-03-15 13:06:31 UTC (rev 55303)
@@ -48,6 +48,7 @@
 struct wmKeyMap;
 struct wmOperator;
 struct wmOperatorType;
+struct LinkNode;
 
 /* ******************** editmesh_utils.c */
 
@@ -204,6 +205,8 @@
 void MESH_OT_loopcut(struct wmOperatorType *ot);
 
 void MESH_OT_knife_tool(struct wmOperatorType *ot);
+void MESH_OT_knife_project(wmOperatorType *ot);
+
 void MESH_OT_bevel(struct wmOperatorType *ot);
 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list