| 
									
										
										
										
											2011-10-25 16:17:26 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  |  * ***** 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 | 
					
						
							| 
									
										
										
										
											2012-02-11 04:16:17 +00:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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, | 
					
						
							| 
									
										
										
										
											2012-02-11 04:16:17 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2007 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *  | 
					
						
							| 
									
										
										
										
											2012-03-24 00:20:36 +00:00
										 |  |  |  * Contributor(s): Joseph Eagar, Joshua Leung, Howard Trickey, | 
					
						
							|  |  |  |  *                 Campbell Barton | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 00:20:36 +00:00
										 |  |  | /** \file blender/editors/mesh/editmesh_knife.c
 | 
					
						
							|  |  |  |  *  \ingroup edmesh | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-20 01:02:39 +00:00
										 |  |  | #ifdef _MSC_VER
 | 
					
						
							|  |  |  | #  define _USE_MATH_DEFINES
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							|  |  |  | #include "BLI_array.h"
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | #include "BLI_rand.h"
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | #include "BLI_smallhash.h"
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | #include "BLI_scanfill.h"
 | 
					
						
							| 
									
										
										
										
											2012-03-01 20:09:17 +00:00
										 |  |  | #include "BLI_memarena.h"
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BIF_gl.h"
 | 
					
						
							|  |  |  | #include "BIF_glutil.h" /* for paint cursor */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ED_screen.h"
 | 
					
						
							|  |  |  | #include "ED_space_api.h"
 | 
					
						
							|  |  |  | #include "ED_view3d.h"
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-11 08:46:56 +00:00
										 |  |  | #include "DNA_scene_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-19 22:17:30 +00:00
										 |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-11 08:46:56 +00:00
										 |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "BKE_tessmesh.h"
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:44:28 +00:00
										 |  |  | #include "UI_resources.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-11 08:46:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | #include "RNA_access.h"
 | 
					
						
							|  |  |  | #include "RNA_define.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | #include "mesh_intern.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* this code here is kindof messy. . .I might need to eventually rework it - joeedh */ | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | #define KMAXDIST    10  /* max mouse distance from edge before not detecting it */
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | #define KNIFE_FLT_EPS          0.00001f
 | 
					
						
							|  |  |  | #define KNIFE_FLT_EPS_SQUARED  (KNIFE_FLT_EPS * KNIFE_FLT_EPS)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | typedef struct KnifeColors { | 
					
						
							|  |  |  | 	unsigned char line[3]; | 
					
						
							|  |  |  | 	unsigned char edge[3]; | 
					
						
							|  |  |  | 	unsigned char curpoint[3]; | 
					
						
							|  |  |  | 	unsigned char curpoint_a[4]; | 
					
						
							|  |  |  | 	unsigned char point[3]; | 
					
						
							|  |  |  | 	unsigned char point_a[4]; | 
					
						
							|  |  |  | } KnifeColors; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | /* knifetool operator */ | 
					
						
							|  |  |  | typedef struct KnifeVert { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	BMVert *v; /* non-NULL if this is an original vert */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	ListBase edges; | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 	ListBase faces; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	float co[3], cageco[3], sco[3]; /* sco is screen coordinates for cageco */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	short flag, draw, isface, inspace; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } KnifeVert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct Ref { | 
					
						
							|  |  |  | 	struct Ref *next, *prev; | 
					
						
							|  |  |  | 	void *ref; | 
					
						
							|  |  |  | } Ref; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct KnifeEdge { | 
					
						
							|  |  |  | 	KnifeVert *v1, *v2; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	BMFace *basef; /* face to restrict face fill to */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	ListBase faces; | 
					
						
							|  |  |  | 	int draw; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	BMEdge *e, *oe; /* non-NULL if this is an original edge */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } KnifeEdge; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct BMEdgeHit { | 
					
						
							| 
									
										
										
										
											2010-10-03 21:10:59 +00:00
										 |  |  | 	KnifeEdge *kfe; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	float hit[3], cagehit[3]; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	float realhit[3]; /* used in midpoint mode */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	float schit[3]; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	float l; /* lambda along cut line */ | 
					
						
							|  |  |  | 	float perc; /* lambda along hit line */ | 
					
						
							|  |  |  | 	KnifeVert *v; /* set if snapped to a vert */ | 
					
						
							| 
									
										
										
										
											2010-10-03 21:10:59 +00:00
										 |  |  | 	BMFace *f; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } BMEdgeHit; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | typedef struct KnifePosData { | 
					
						
							|  |  |  | 	float co[3]; | 
					
						
							|  |  |  | 	float cage[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* At most one of vert, edge, or bmface should be non-NULL,
 | 
					
						
							|  |  |  | 	 * saying whether the point is snapped to a vertex, edge, or in a face. | 
					
						
							|  |  |  | 	 * If none are set, this point is in space and is_space should be true. */ | 
					
						
							|  |  |  | 	KnifeVert *vert; | 
					
						
							|  |  |  | 	KnifeEdge *edge; | 
					
						
							|  |  |  | 	BMFace *bmface; | 
					
						
							|  |  |  | 	int is_space; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	int mval[2]; /* mouse screen position */ | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | } KnifePosData; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | /* struct for properties used while drawing */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | typedef struct KnifeTool_OpData { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	ARegion *ar;        /* region that knifetool was activated in */ | 
					
						
							|  |  |  | 	void *draw_handle;  /* for drawing preview loop */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	ViewContext vc; | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	//bContext *C;
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	Object *ob; | 
					
						
							|  |  |  | 	BMEditMesh *em; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	MemArena *arena; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GHash *origvertmap; | 
					
						
							|  |  |  | 	GHash *origedgemap; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	GHash *kedgefacemap; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	BMBVHTree *bmbvh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_mempool *kverts; | 
					
						
							|  |  |  | 	BLI_mempool *kedges; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	float vthresh; | 
					
						
							|  |  |  | 	float ethresh; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* used for drag-cutting */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	BMEdgeHit *linehits; | 
					
						
							|  |  |  | 	int totlinehit; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	/* Data for mouse-position-derived data (cur) and previous click (prev) */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	KnifePosData curr, prev; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	int totkedge, totkvert; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	BLI_mempool *refs; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	float projmat[4][4]; | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 	KnifeColors colors; | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* operatpr options */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:26:16 +00:00
										 |  |  | 	char cut_through;    /* preference, can be modified at runtime (that feature may go) */ | 
					
						
							|  |  |  | 	char only_select;    /* set on initialization */ | 
					
						
							|  |  |  | 	char select_result;  /* set on initialization */ | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 	short is_ortho; | 
					
						
							| 
									
										
										
										
											2012-10-23 18:17:51 +00:00
										 |  |  | 	float ortho_extent; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	float clipsta, clipend; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	enum { | 
					
						
							|  |  |  | 		MODE_IDLE, | 
					
						
							|  |  |  | 		MODE_DRAGGING, | 
					
						
							|  |  |  | 		MODE_CONNECT, | 
					
						
							| 
									
										
										
										
											2011-11-16 19:06:38 +00:00
										 |  |  | 		MODE_PANNING | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} mode; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	int snap_midpoints, prevmode, extend; | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 	int ignore_edge_snapping, ignore_vert_snapping; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 	enum { | 
					
						
							|  |  |  | 		ANGLE_FREE, | 
					
						
							|  |  |  | 		ANGLE_0, | 
					
						
							|  |  |  | 		ANGLE_45, | 
					
						
							|  |  |  | 		ANGLE_90, | 
					
						
							|  |  |  | 		ANGLE_135 | 
					
						
							|  |  |  | 	} angle_snapping; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	float (*cagecos)[3]; | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | } KnifeTool_OpData; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  |                                  float r_origin[3], float r_ray[3]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-23 21:04:26 +00:00
										 |  |  | 	#define HEADER_LENGTH 190
 | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 	char header[HEADER_LENGTH]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-23 21:04:26 +00:00
										 |  |  | 	BLI_snprintf(header, HEADER_LENGTH, "LMB: define cut lines, Return/Spacebar: confirm, Esc or RMB: cancel, E: new cut, Ctrl: midpoint snap (%s), " | 
					
						
							| 
									
										
										
										
											2012-04-20 12:26:16 +00:00
										 |  |  | 	             "Shift: ignore snap (%s), C: angle constrain (%s), Z: cut through (%s)", | 
					
						
							|  |  |  | 	             kcd->snap_midpoints ? "On" : "Off", | 
					
						
							|  |  |  | 	             kcd->ignore_edge_snapping ?  "On" : "Off", | 
					
						
							|  |  |  | 	             kcd->angle_snapping ? "On" : "Off", | 
					
						
							|  |  |  | 	             kcd->cut_through ? "On" : "Off"); | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ED_area_headerprint(CTX_wm_area(C), header); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3]) | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-09-20 04:56:24 +00:00
										 |  |  | 	ED_view3d_project_float_v3_m4(kcd->ar, co, sco, kcd->projmat); | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | static void knife_pos_data_clear(KnifePosData *kpd) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	zero_v3(kpd->co); | 
					
						
							|  |  |  | 	zero_v3(kpd->cage); | 
					
						
							|  |  |  | 	kpd->vert = NULL; | 
					
						
							|  |  |  | 	kpd->edge = NULL; | 
					
						
							|  |  |  | 	kpd->bmface = NULL; | 
					
						
							|  |  |  | 	kpd->mval[0] = 0; | 
					
						
							|  |  |  | 	kpd->mval[1] = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static ListBase *knife_empty_list(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2012-02-25 16:49:59 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-13 14:45:17 +00:00
										 |  |  | 	ListBase *lst; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lst = BLI_memarena_alloc(kcd->arena, sizeof(ListBase)); | 
					
						
							|  |  |  | 	lst->first = lst->last = NULL; | 
					
						
							|  |  |  | 	return lst; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_append_list(KnifeTool_OpData *kcd, ListBase *lst, void *elem) | 
					
						
							| 
									
										
										
										
											2012-02-25 16:49:59 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-13 14:45:17 +00:00
										 |  |  | 	Ref *ref; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ref = BLI_mempool_calloc(kcd->refs); | 
					
						
							|  |  |  | 	ref->ref = elem; | 
					
						
							|  |  |  | 	BLI_addtail(lst, ref); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | static Ref *find_ref(ListBase *lb, void *ref) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Ref *ref1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (ref1 = lb->first; ref1; ref1 = ref1->next) { | 
					
						
							|  |  |  | 		if (ref1->ref == ref) | 
					
						
							|  |  |  | 			return ref1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static KnifeEdge *new_knife_edge(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	kcd->totkedge++; | 
					
						
							|  |  |  | 	return BLI_mempool_calloc(kcd->kedges); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_add_to_vert_edges(KnifeTool_OpData *kcd, KnifeEdge *kfe) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-13 14:45:17 +00:00
										 |  |  | 	knife_append_list(kcd, &kfe->v1->edges, kfe); | 
					
						
							|  |  |  | 	knife_append_list(kcd, &kfe->v2->edges, kfe); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | /* Add faces of an edge to a KnifeVert's faces list.  No checks for dups. */ | 
					
						
							|  |  |  | static void knife_add_edge_faces_to_vert(KnifeTool_OpData *kcd, KnifeVert *kfv, BMEdge *e) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BMIter bmiter; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BM_ITER_ELEM(f, &bmiter, e, BM_FACES_OF_EDGE) { | 
					
						
							|  |  |  | 		knife_append_list(kcd, &kfv->faces, f); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find a face in common in the two faces lists.
 | 
					
						
							| 
									
										
										
										
											2012-09-03 22:04:14 +00:00
										 |  |  |  * If more than one, return the first; if none, return NULL */ | 
					
						
							| 
									
										
										
										
											2012-07-29 00:20:28 +00:00
										 |  |  | static BMFace *knife_find_common_face(ListBase *faces1, ListBase *faces2) | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Ref *ref1, *ref2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (ref1 = faces1->first; ref1; ref1 = ref1->next) { | 
					
						
							|  |  |  | 		for (ref2 = faces2->first; ref2; ref2 = ref2->next) { | 
					
						
							|  |  |  | 			if (ref1->ref == ref2->ref) | 
					
						
							| 
									
										
										
										
											2012-07-29 00:20:28 +00:00
										 |  |  | 				return (BMFace *)(ref1->ref); | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-28 08:29:20 +00:00
										 |  |  | static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], float *cageco) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	kcd->totkvert++; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	copy_v3_v3(kfv->co, co); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	copy_v3_v3(kfv->cageco, cageco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	copy_v3_v3(kfv->sco, co); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | 	knife_project_v3(kcd, kfv->co, kfv->sco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return kfv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* get a KnifeVert wrapper for an existing BMVert */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (!kfv) { | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 		BMIter bmiter; | 
					
						
							|  |  |  | 		BMFace *f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 		kfv = new_knife_vert(kcd, v->co, kcd->cagecos[BM_elem_index_get(v)]); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		kfv->v = v; | 
					
						
							|  |  |  | 		BLI_ghash_insert(kcd->origvertmap, v, kfv); | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 		BM_ITER_ELEM(f, &bmiter, v, BM_FACES_OF_VERT) { | 
					
						
							|  |  |  | 			knife_append_list(kcd, &kfv->faces, f); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return kfv; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 12:54:32 +00:00
										 |  |  | /* get a KnifeEdge wrapper for an existing BMEdge */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static KnifeEdge *get_bm_knife_edge(KnifeTool_OpData *kcd, BMEdge *e) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	KnifeEdge *kfe = BLI_ghash_lookup(kcd->origedgemap, e); | 
					
						
							|  |  |  | 	if (!kfe) { | 
					
						
							| 
									
										
										
										
											2012-08-07 12:54:32 +00:00
										 |  |  | 		BMIter bmiter; | 
					
						
							|  |  |  | 		BMFace *f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		kfe = new_knife_edge(kcd); | 
					
						
							|  |  |  | 		kfe->e = e; | 
					
						
							|  |  |  | 		kfe->v1 = get_bm_knife_vert(kcd, e->v1); | 
					
						
							|  |  |  | 		kfe->v2 = get_bm_knife_vert(kcd, e->v2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 		knife_add_to_vert_edges(kcd, kfe); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		BLI_ghash_insert(kcd->origedgemap, e, kfe); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 12:54:32 +00:00
										 |  |  | 		BM_ITER_ELEM(f, &bmiter, e, BM_FACES_OF_EDGE) { | 
					
						
							|  |  |  | 			knife_append_list(kcd, &kfe->faces, f); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return kfe; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | /* User has just clicked for first time or first time after a restart (E key).
 | 
					
						
							|  |  |  |  * Copy the current position data into prev. */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_start_cut(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	kcd->prev = kcd->curr; | 
					
						
							|  |  |  | 	kcd->curr.is_space = 0; /*TODO: why do we do this? */ | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (kcd->prev.vert == NULL && kcd->prev.edge == NULL && is_zero_v3(kcd->prev.cage)) { | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 		/* Make prevcage a point on the view ray to mouse closest to a point on model: choose vertex 0 */ | 
					
						
							|  |  |  | 		float origin[3], ray[3], co[3]; | 
					
						
							|  |  |  | 		BMVert *v0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		knife_input_ray_cast(kcd, kcd->curr.mval, origin, ray); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 		add_v3_v3v3(co, origin, ray); | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 		v0 = BM_vert_at_index(kcd->em->bm, 0); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 		if (v0) { | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 			closest_to_line_v3(kcd->prev.cage, v0->co, co, origin); | 
					
						
							|  |  |  | 			copy_v3_v3(kcd->prev.co, kcd->prev.cage); /*TODO: do we need this? */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 			copy_v3_v3(kcd->curr.cage, kcd->prev.cage); | 
					
						
							|  |  |  | 			copy_v3_v3(kcd->curr.co, kcd->prev.co); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ListBase *lst = BLI_ghash_lookup(kcd->kedgefacemap, f); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (!lst) { | 
					
						
							| 
									
										
										
										
											2012-08-07 12:54:32 +00:00
										 |  |  | 		BMIter bmiter; | 
					
						
							|  |  |  | 		BMEdge *e; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-13 14:45:17 +00:00
										 |  |  | 		lst = knife_empty_list(kcd); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-07 12:54:32 +00:00
										 |  |  | 		BM_ITER_ELEM(e, &bmiter, f, BM_EDGES_OF_FACE) { | 
					
						
							|  |  |  | 			knife_append_list(kcd, lst, get_bm_knife_edge(kcd, e)); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		BLI_ghash_insert(kcd->kedgefacemap, f, lst); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return lst; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* finds the proper face to restrict face fill to */ | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | static void knife_find_basef(KnifeEdge *kfe) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 	kfe->basef = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_edge_append_face(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMFace *f) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-13 14:45:17 +00:00
										 |  |  | 	knife_append_list(kcd, knife_get_face_kedges(kcd, f), kfe); | 
					
						
							|  |  |  | 	knife_append_list(kcd, &kfe->faces, f); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float co[3], KnifeEdge **newkfe_out) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	KnifeEdge *newkfe = new_knife_edge(kcd); | 
					
						
							|  |  |  | 	Ref *ref; | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 	BMFace *f; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	float perc, cageco[3], l12; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	l12 = len_v3v3(kfe->v1->co, kfe->v2->co); | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 	if (l12 < KNIFE_FLT_EPS) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		copy_v3_v3(cageco, kfe->v1->cageco); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		perc = len_v3v3(co, kfe->v1->co) / l12; | 
					
						
							|  |  |  | 		interp_v3_v3v3(cageco, kfe->v1->cageco, kfe->v2->cageco, perc); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	newkfe->v1 = kfe->v1; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	newkfe->v2 = new_knife_vert(kcd, co, cageco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	newkfe->v2->draw = 1; | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 	if (kfe->e) { | 
					
						
							|  |  |  | 		knife_add_edge_faces_to_vert(kcd, newkfe->v2, kfe->e); | 
					
						
							| 
									
										
										
										
											2012-07-29 00:20:28 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 		/* kfe cuts across an existing face.
 | 
					
						
							| 
									
										
										
										
											2012-10-04 13:26:15 +00:00
										 |  |  | 		 * If v1 and v2 are in multiple faces together (e.g., if they | 
					
						
							|  |  |  | 		 * are in doubled polys) then this arbitrarily chooses one of them */ | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 		f = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces); | 
					
						
							|  |  |  | 		if (f) | 
					
						
							|  |  |  | 			knife_append_list(kcd, &newkfe->v2->faces, f); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	newkfe->basef = kfe->basef; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	ref = find_ref(&kfe->v1->edges, kfe); | 
					
						
							|  |  |  | 	BLI_remlink(&kfe->v1->edges, ref); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	kfe->v1 = newkfe->v2; | 
					
						
							|  |  |  | 	BLI_addtail(&kfe->v1->edges, ref); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	for (ref = kfe->faces.first; ref; ref = ref->next) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 		knife_edge_append_face(kcd, newkfe, ref->ref); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	knife_add_to_vert_edges(kcd, newkfe); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	newkfe->draw = kfe->draw; | 
					
						
							|  |  |  | 	newkfe->e = kfe->e; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	*newkfe_out = newkfe; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return newkfe->v2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | /* Make a single KnifeEdge for cut from kcd->prev to kcd->curr.
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  |  * and move cur data to prev. */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_add_single_cut(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	KnifeEdge *kfe = new_knife_edge(kcd), *kfe2 = NULL, *kfe3 = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (kcd->prev.vert && kcd->prev.vert == kcd->curr.vert) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	kfe->draw = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	if (kcd->prev.vert) { | 
					
						
							|  |  |  | 		kfe->v1 = kcd->prev.vert; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	else if (kcd->prev.edge) { | 
					
						
							|  |  |  | 		kfe->v1 = knife_split_edge(kcd, kcd->prev.edge, kcd->prev.co, &kfe2); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 		kfe->v1 = new_knife_vert(kcd, kcd->prev.co, kcd->prev.co); | 
					
						
							|  |  |  | 		kfe->v1->draw = kfe->draw = !kcd->prev.is_space; | 
					
						
							|  |  |  | 		kfe->v1->inspace = kcd->prev.is_space; | 
					
						
							|  |  |  | 		kfe->draw = !kcd->prev.is_space; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		kfe->v1->isface = 1; | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 		if (kfe->v1->draw && kcd->prev.bmface) | 
					
						
							|  |  |  | 			knife_append_list(kcd, &kfe->v1->faces, kcd->prev.bmface); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (kcd->curr.vert) { | 
					
						
							|  |  |  | 		kfe->v2 = kcd->curr.vert; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	else if (kcd->curr.edge) { | 
					
						
							|  |  |  | 		kfe->v2 = knife_split_edge(kcd, kcd->curr.edge, kcd->curr.co, &kfe3); | 
					
						
							|  |  |  | 		kcd->curr.vert = kfe->v2; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		kfe->v2 = new_knife_vert(kcd, kcd->curr.co, kcd->curr.co); | 
					
						
							|  |  |  | 		kfe->v2->draw = !kcd->curr.is_space; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		kfe->v2->isface = 1; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		kfe->v2->inspace = kcd->curr.is_space; | 
					
						
							|  |  |  | 		if (kfe->v2->draw && kcd->curr.bmface) | 
					
						
							|  |  |  | 			knife_append_list(kcd, &kfe->v2->faces, kcd->curr.bmface); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		if (kcd->curr.is_space) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			kfe->draw = 0; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		kcd->curr.vert = kfe->v2; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-27 20:12:29 +00:00
										 |  |  | 	knife_find_basef(kfe); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	knife_add_to_vert_edges(kcd, kfe); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (kfe->basef && !find_ref(&kfe->faces, kfe->basef)) | 
					
						
							|  |  |  | 		knife_edge_append_face(kcd, kfe, kfe->basef); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* sanity check to make sure we're in the right edge/face lists */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (kcd->curr.bmface) { | 
					
						
							|  |  |  | 		if (!find_ref(&kfe->faces, kcd->curr.bmface)) { | 
					
						
							|  |  |  | 			knife_edge_append_face(kcd, kfe, kcd->curr.bmface); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		if (kcd->prev.bmface && kcd->prev.bmface != kcd->curr.bmface) { | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 			if (!find_ref(&kfe->faces, kcd->prev.bmface)) { | 
					
						
							|  |  |  | 				knife_edge_append_face(kcd, kfe, kcd->prev.bmface); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* set up for next cut */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	kcd->prev = kcd->curr; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int verge_linehit(const void *vlh1, const void *vlh2) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	const BMEdgeHit *lh1 = vlh1, *lh2 = vlh2; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	if      (lh1->l < lh2->l) return -1; | 
					
						
							| 
									
										
										
										
											2012-04-20 12:26:16 +00:00
										 |  |  | 	else if (lh1->l > lh2->l) return 1; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	else return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | /* If there's a linehit connected (same face) as testi in range [firsti, lasti], return the first such, else -1.
 | 
					
						
							| 
									
										
										
										
											2012-09-04 18:47:08 +00:00
										 |  |  |  * If testi is out of range, look for connection to f instead, if f is non-NULL */ | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, int firsti, int lasti) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = firsti; i <= lasti; i++) { | 
					
						
							|  |  |  | 		if (testi >= 0 && testi < kcd->totlinehit) { | 
					
						
							|  |  |  | 			if (knife_find_common_face(&kcd->linehits[testi].kfe->faces, | 
					
						
							| 
									
										
										
										
											2012-09-04 18:47:08 +00:00
										 |  |  | 			                           &kcd->linehits[i].kfe->faces)) | 
					
						
							| 
									
										
										
										
											2012-09-26 20:26:31 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 				return i; | 
					
						
							| 
									
										
										
										
											2012-09-26 20:26:31 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-09-04 18:47:08 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else if (f) { | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 			if (find_ref(&kcd->linehits[i].kfe->faces, f)) | 
					
						
							|  |  |  | 				return i; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Sort in order of distance along cut line, but take care when distances are equal */ | 
					
						
							|  |  |  | static void knife_sort_linehits(KnifeTool_OpData *kcd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i, j, k, nexti, nsame; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* for ranges of equal "l", swap if neccesary to make predecessor and
 | 
					
						
							|  |  |  | 	 * successor faces connected to the linehits at either end of the range */ | 
					
						
							| 
									
										
										
										
											2012-09-04 18:47:08 +00:00
										 |  |  | 	for (i = 0; i < kcd->totlinehit - 1; i = nexti) { | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 		for (j = i + 1; j < kcd->totlinehit; j++) { | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 			if (fabsf(kcd->linehits[j].l - kcd->linehits[i].l) > KNIFE_FLT_EPS) | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		nexti = j; | 
					
						
							|  |  |  | 		j--; | 
					
						
							|  |  |  | 		nsame = j - i; | 
					
						
							|  |  |  | 		if (nsame > 0) { | 
					
						
							|  |  |  | 			/* find something connected to predecessor of equal range */ | 
					
						
							|  |  |  | 			k = find_connected_linehit(kcd, i - 1, kcd->prev.bmface, i, j); | 
					
						
							|  |  |  | 			if (k != -1) { | 
					
						
							|  |  |  | 				if (k != i) { | 
					
						
							|  |  |  | 					SWAP(BMEdgeHit, kcd->linehits[i], kcd->linehits[k]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				i++; | 
					
						
							|  |  |  | 				nsame--; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (nsame > 0) { | 
					
						
							|  |  |  | 				/* find something connected to successor of equal range */ | 
					
						
							|  |  |  | 				k = find_connected_linehit(kcd, j + 1, kcd->curr.bmface, i, j); | 
					
						
							|  |  |  | 				if (k != -1 && k != j) { | 
					
						
							|  |  |  | 					SWAP(BMEdgeHit, kcd->linehits[j], kcd->linehits[k]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			/* rest of same range doesn't matter because we won't connect them */ | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_add_single_cut_through(KnifeTool_OpData *kcd, KnifeVert *v1, KnifeVert *v2, BMFace *f) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	KnifeEdge *kfenew; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	kfenew = new_knife_edge(kcd); | 
					
						
							|  |  |  | 	kfenew->draw = 1; | 
					
						
							|  |  |  | 	kfenew->basef = f; | 
					
						
							|  |  |  | 	kfenew->v1 = v1; | 
					
						
							|  |  |  | 	kfenew->v2 = v2; | 
					
						
							|  |  |  | 	kfenew->draw = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	knife_add_to_vert_edges(kcd, kfenew); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!find_ref(&kfenew->faces, f)) | 
					
						
							|  |  |  | 		knife_edge_append_face(kcd, kfenew, f); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_get_vert_faces(KnifeTool_OpData *kcd, KnifeVert *kfv, BMFace *facef, ListBase *lst) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMIter bmiter; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (kfv->isface && facef) { | 
					
						
							| 
									
										
										
										
											2012-02-13 14:45:17 +00:00
										 |  |  | 		knife_append_list(kcd, lst, facef); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (kfv->v) { | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 		BM_ITER_ELEM (f, &bmiter, kfv->v, BM_FACES_OF_VERT) { | 
					
						
							| 
									
										
										
										
											2012-02-13 14:45:17 +00:00
										 |  |  | 			knife_append_list(kcd, lst, f); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_get_edge_faces(KnifeTool_OpData *kcd, KnifeEdge *kfe, ListBase *lst) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMIter bmiter; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (kfe->e) { | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 		BM_ITER_ELEM (f, &bmiter, kfe->e, BM_FACES_OF_EDGE) { | 
					
						
							| 
									
										
										
										
											2012-02-13 14:45:17 +00:00
										 |  |  | 			knife_append_list(kcd, lst, f); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* BMESH_TODO: add more functionality to cut-through:
 | 
					
						
							|  |  |  |  *    - cutting "in face" (e.g., holes) should cut in all faces, not just visible one | 
					
						
							|  |  |  |  *    - perhaps improve O(n^2) algorithm used here */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_cut_through(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMEdgeHit *lh, *lh2; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 	KnifeEdge *kfe, *kfe2, *kfe3; | 
					
						
							|  |  |  | 	KnifeVert *v1, *v2, *firstv = NULL, *lastv = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	ListBase firstfaces = {NULL, NULL}, lastfaces = {NULL, NULL}; | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	Ref *r, *r2; | 
					
						
							|  |  |  | 	KnifeEdge **splitkfe; | 
					
						
							|  |  |  | 	int i, j, found; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!kcd->totlinehit) { | 
					
						
							|  |  |  | 		/* if no linehits then no interesting back face stuff to do */ | 
					
						
							|  |  |  | 		knife_add_single_cut(kcd); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 	/* TODO: probably don't need to sort at all */ | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	splitkfe = MEM_callocN(kcd->totlinehit * sizeof(KnifeEdge *), "knife_cut_through"); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	if (kcd->prev.vert) { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		if (kcd->prev.vert == kcd->curr.vert) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 		firstv = kcd->prev.vert; | 
					
						
							|  |  |  | 		knife_get_vert_faces(kcd, firstv, kcd->prev.bmface, &firstfaces); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	else if (kcd->prev.edge) { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		if (kcd->prev.edge == kcd->curr.edge) | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 		firstv = knife_split_edge(kcd, kcd->prev.edge, kcd->prev.co, &kfe3); | 
					
						
							|  |  |  | 		knife_get_edge_faces(kcd, kcd->prev.edge, &firstfaces); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (kcd->curr.vert) { | 
					
						
							|  |  |  | 		lastv = kcd->curr.vert; | 
					
						
							|  |  |  | 		knife_get_vert_faces(kcd, lastv, kcd->curr.bmface, &lastfaces); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	else if (kcd->curr.edge) { | 
					
						
							|  |  |  | 		lastv = knife_split_edge(kcd, kcd->curr.edge, kcd->curr.co, &kfe3); | 
					
						
							|  |  |  | 		knife_get_edge_faces(kcd, kcd->curr.edge, &lastfaces); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (firstv) { | 
					
						
							|  |  |  | 		/* For each face incident to firstv,
 | 
					
						
							|  |  |  | 		 * find the first following linehit (if any) sharing that face and connect */ | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		for (r = firstfaces.first; r; r = r->next) { | 
					
						
							| 
									
										
										
										
											2012-02-25 16:04:03 +00:00
										 |  |  | 			f = r->ref; | 
					
						
							|  |  |  | 			found = 0; | 
					
						
							|  |  |  | 			for (j = 0, lh2 = kcd->linehits; j < kcd->totlinehit; j++, lh2++) { | 
					
						
							|  |  |  | 				kfe2 = lh2->kfe; | 
					
						
							|  |  |  | 				for (r2 = kfe2->faces.first; r2; r2 = r2->next) { | 
					
						
							|  |  |  | 					if (r2->ref == f) { | 
					
						
							|  |  |  | 						v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]); | 
					
						
							|  |  |  | 						knife_add_single_cut_through(kcd, firstv, v2, f); | 
					
						
							|  |  |  | 						found = 1; | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!found && lastv) { | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 				for (r2 = lastfaces.first; r2; r2 = r2->next) { | 
					
						
							|  |  |  | 					if (r2->ref == f) { | 
					
						
							|  |  |  | 						knife_add_single_cut_through(kcd, firstv, lastv, f); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-02-25 16:04:03 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0, lh = kcd->linehits; i < kcd->totlinehit; i++, lh++) { | 
					
						
							|  |  |  | 		kfe = lh->kfe; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* For each face attached to edge for this linehit,
 | 
					
						
							|  |  |  | 		 * find the first following linehit (if any) sharing that face and connect */ | 
					
						
							|  |  |  | 		for (r = kfe->faces.first; r; r = r->next) { | 
					
						
							|  |  |  | 			f = r->ref; | 
					
						
							|  |  |  | 			found = 0; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			for (j = i + 1, lh2 = lh + 1; j < kcd->totlinehit; j++, lh2++) { | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 				kfe2 = lh2->kfe; | 
					
						
							|  |  |  | 				for (r2 = kfe2->faces.first; r2; r2 = r2->next) { | 
					
						
							|  |  |  | 					if (r2->ref == f) { | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 						v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]); | 
					
						
							|  |  |  | 						v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 						knife_add_single_cut_through(kcd, v1, v2, f); | 
					
						
							|  |  |  | 						found = 1; | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (!found && lastv) { | 
					
						
							|  |  |  | 				for (r2 = lastfaces.first; r2; r2 = r2->next) { | 
					
						
							|  |  |  | 					if (r2->ref == f) { | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 						v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]); | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 						knife_add_single_cut_through(kcd, v1, lastv, f); | 
					
						
							|  |  |  | 						break; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN(splitkfe); | 
					
						
							|  |  |  | 	MEM_freeN(kcd->linehits); | 
					
						
							|  |  |  | 	kcd->linehits = NULL; | 
					
						
							|  |  |  | 	kcd->totlinehit = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* set up for next cut */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	kcd->prev = kcd->curr; | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | /* User has just left-clicked after the first time.
 | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  |  * Add all knife cuts implied by line from prev to curr. | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  |  * If that line crossed edges then kcd->linehits will be non-NULL. */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_add_cut(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	KnifePosData savcur = kcd->curr; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	if (kcd->cut_through) { | 
					
						
							|  |  |  | 		knife_cut_through(kcd); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (kcd->linehits) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		BMEdgeHit *lh, *lastlh, *firstlh; | 
					
						
							|  |  |  | 		int i; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 		knife_sort_linehits(kcd); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		lh = kcd->linehits; | 
					
						
							|  |  |  | 		lastlh = firstlh = NULL; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (i = 0; i < kcd->totlinehit; i++, (lastlh = lh), lh++) { | 
					
						
							| 
									
										
										
										
											2010-10-03 21:10:59 +00:00
										 |  |  | 			BMFace *f = lastlh ? lastlh->f : lh->f; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 			if (lastlh && len_squared_v3v3(lastlh->hit, lh->hit) == 0.0f) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				if (!firstlh) | 
					
						
							|  |  |  | 					firstlh = lastlh; | 
					
						
							|  |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else if (lastlh && firstlh) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				if (firstlh->v || lastlh->v) { | 
					
						
							| 
									
										
										
										
											2010-10-03 21:10:59 +00:00
										 |  |  | 					KnifeVert *kfv = firstlh->v ? firstlh->v : lastlh->v; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 					kcd->prev.vert = kfv; | 
					
						
							|  |  |  | 					copy_v3_v3(kcd->prev.co, firstlh->hit); | 
					
						
							|  |  |  | 					copy_v3_v3(kcd->prev.cage, firstlh->cagehit); | 
					
						
							|  |  |  | 					kcd->prev.edge = NULL; | 
					
						
							|  |  |  | 					kcd->prev.bmface = f; | 
					
						
							|  |  |  | 					/* TODO: should we set prev.in_space = 0 ? */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				lastlh = firstlh = NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 			if (len_squared_v3v3(kcd->prev.cage, lh->realhit) < KNIFE_FLT_EPS_SQUARED) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 			if (len_squared_v3v3(kcd->curr.cage, lh->realhit) < KNIFE_FLT_EPS_SQUARED) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 			/* first linehit may be down face parallel to view */ | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 			if (!lastlh && fabsf(lh->l) < KNIFE_FLT_EPS) | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 				continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 			if (kcd->prev.is_space) { | 
					
						
							|  |  |  | 				kcd->prev.is_space = 0; | 
					
						
							|  |  |  | 				copy_v3_v3(kcd->prev.co, lh->hit); | 
					
						
							|  |  |  | 				copy_v3_v3(kcd->prev.cage, lh->cagehit); | 
					
						
							|  |  |  | 				kcd->prev.vert = NULL; | 
					
						
							|  |  |  | 				kcd->prev.edge = lh->kfe; | 
					
						
							|  |  |  | 				kcd->prev.bmface = lh->f; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 			kcd->curr.is_space = 0; | 
					
						
							|  |  |  | 			kcd->curr.edge = lh->kfe; | 
					
						
							|  |  |  | 			kcd->curr.bmface = lh->f; | 
					
						
							|  |  |  | 			kcd->curr.vert = lh->v; | 
					
						
							|  |  |  | 			copy_v3_v3(kcd->curr.co, lh->hit); | 
					
						
							|  |  |  | 			copy_v3_v3(kcd->curr.cage, lh->cagehit); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 			/* don't draw edges down faces parallel to view */ | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 			if (lastlh && fabsf(lastlh->l - lh->l) < KNIFE_FLT_EPS) { | 
					
						
							| 
									
										
										
										
											2012-09-03 14:37:34 +00:00
										 |  |  | 				kcd->prev = kcd->curr; | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			knife_add_single_cut(kcd); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 		if (savcur.is_space) { | 
					
						
							|  |  |  | 			kcd->prev = savcur; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 			kcd->curr = savcur; | 
					
						
							| 
									
										
										
										
											2012-03-06 12:16:55 +00:00
										 |  |  | 			knife_add_single_cut(kcd); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		MEM_freeN(kcd->linehits); | 
					
						
							|  |  |  | 		kcd->linehits = NULL; | 
					
						
							|  |  |  | 		kcd->totlinehit = 0; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		knife_add_single_cut(kcd); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_finish_cut(KnifeTool_OpData *UNUSED(kcd)) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knifetool_draw_angle_snapping(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bglMats mats; | 
					
						
							|  |  |  | 	double u[3], u1[2], u2[2], v1[3], v2[3], dx, dy; | 
					
						
							|  |  |  | 	double wminx, wminy, wmaxx, wmaxy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* make u the window coords of prevcage */ | 
					
						
							|  |  |  | 	view3d_get_transformation(kcd->ar, kcd->vc.rv3d, kcd->ob, &mats); | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	gluProject(kcd->prev.cage[0], kcd->prev.cage[1], kcd->prev.cage[2], | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	           mats.modelview, mats.projection, mats.viewport, | 
					
						
							|  |  |  | 	           &u[0], &u[1], &u[2]); | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* make u1, u2 the points on window going through u at snap angle */ | 
					
						
							|  |  |  | 	wminx = kcd->ar->winrct.xmin; | 
					
						
							|  |  |  | 	wmaxx = kcd->ar->winrct.xmin + kcd->ar->winx; | 
					
						
							|  |  |  | 	wminy = kcd->ar->winrct.ymin; | 
					
						
							|  |  |  | 	wmaxy = kcd->ar->winrct.ymin + kcd->ar->winy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (kcd->angle_snapping) { | 
					
						
							|  |  |  | 		case ANGLE_0: | 
					
						
							|  |  |  | 			u1[0] = wminx; | 
					
						
							|  |  |  | 			u2[0] = wmaxx; | 
					
						
							|  |  |  | 			u1[1] = u2[1] = u[1]; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case ANGLE_90: | 
					
						
							|  |  |  | 			u1[0] = u2[0] = u[0]; | 
					
						
							|  |  |  | 			u1[1] = wminy; | 
					
						
							|  |  |  | 			u2[1] = wmaxy; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case ANGLE_45: | 
					
						
							|  |  |  | 			/* clip against left or bottom */ | 
					
						
							|  |  |  | 			dx = u[0] - wminx; | 
					
						
							|  |  |  | 			dy = u[1] - wminy; | 
					
						
							|  |  |  | 			if (dy > dx) { | 
					
						
							|  |  |  | 				u1[0] = wminx; | 
					
						
							|  |  |  | 				u1[1] = u[1] - dx; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 				u1[0] = u[0] - dy; | 
					
						
							|  |  |  | 				u1[1] = wminy; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			/* clip against right or top */ | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 			dx = wmaxx - u[0]; | 
					
						
							|  |  |  | 			dy = wmaxy - u[1]; | 
					
						
							|  |  |  | 			if (dy > dx) { | 
					
						
							|  |  |  | 				u2[0] = wmaxx; | 
					
						
							|  |  |  | 				u2[1] = u[1] + dx; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 				u2[0] = u[0] + dy; | 
					
						
							|  |  |  | 				u2[1] = wmaxy; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case ANGLE_135: | 
					
						
							|  |  |  | 			/* clip against right or bottom */ | 
					
						
							|  |  |  | 			dx = wmaxx - u[0]; | 
					
						
							|  |  |  | 			dy = u[1] - wminy; | 
					
						
							|  |  |  | 			if (dy > dx) { | 
					
						
							|  |  |  | 				u1[0] = wmaxx; | 
					
						
							|  |  |  | 				u1[1] = u[1] - dx; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 				u1[0] = u[0] + dy; | 
					
						
							|  |  |  | 				u1[1] = wminy; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			/* clip against left or top */ | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 			dx = u[0] - wminx; | 
					
						
							|  |  |  | 			dy = wmaxy - u[1]; | 
					
						
							|  |  |  | 			if (dy > dx) { | 
					
						
							|  |  |  | 				u2[0] = wminx; | 
					
						
							|  |  |  | 				u2[1] = u[1] + dx; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 				u2[0] = u[0] - dy; | 
					
						
							|  |  |  | 				u2[1] = wmaxy; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* unproject u1 and u2 back into object space */ | 
					
						
							|  |  |  | 	gluUnProject(u1[0], u1[1], 0.0, | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	             mats.modelview, mats.projection, mats.viewport, | 
					
						
							|  |  |  | 	             &v1[0], &v1[1], &v1[2]); | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 	gluUnProject(u2[0], u2[1], 0.0, | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	             mats.modelview, mats.projection, mats.viewport, | 
					
						
							|  |  |  | 	             &v2[0], &v2[1], &v2[2]); | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:44:28 +00:00
										 |  |  | 	UI_ThemeColor(TH_TRANSFORM); | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 	glLineWidth(2.0); | 
					
						
							|  |  |  | 	glBegin(GL_LINES); | 
					
						
							|  |  |  | 	glVertex3dv(v1); | 
					
						
							|  |  |  | 	glVertex3dv(v2); | 
					
						
							|  |  |  | 	glEnd(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | static void knife_init_colors(KnifeColors *colors) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* possible BMESH_TODO: add explicit themes or calculate these by
 | 
					
						
							| 
									
										
										
										
											2012-05-20 21:23:26 +00:00
										 |  |  | 	 * figuring out contrasting colors with grid / edges / verts | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 	 * a la UI_make_axis_color */ | 
					
						
							|  |  |  | 	UI_GetThemeColor3ubv(TH_NURB_VLINE, colors->line); | 
					
						
							|  |  |  | 	UI_GetThemeColor3ubv(TH_NURB_ULINE, colors->edge); | 
					
						
							|  |  |  | 	UI_GetThemeColor3ubv(TH_HANDLE_SEL_VECT, colors->curpoint); | 
					
						
							|  |  |  | 	UI_GetThemeColor3ubv(TH_HANDLE_SEL_VECT, colors->curpoint_a); | 
					
						
							| 
									
										
										
										
											2012-04-20 13:45:38 +00:00
										 |  |  | 	colors->curpoint_a[3] = 102; | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 	UI_GetThemeColor3ubv(TH_ACTIVE_SPLINE, colors->point); | 
					
						
							|  |  |  | 	UI_GetThemeColor3ubv(TH_ACTIVE_SPLINE, colors->point_a); | 
					
						
							| 
									
										
										
										
											2012-04-20 13:45:38 +00:00
										 |  |  | 	colors->point_a[3] = 102; | 
					
						
							| 
									
										
										
										
											2012-04-19 13:44:28 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | /* modal loop selection drawing callback */ | 
					
						
							| 
									
										
										
										
											2012-04-17 17:25:10 +00:00
										 |  |  | static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-17 17:25:10 +00:00
										 |  |  | 	View3D *v3d = CTX_wm_view3d(C); | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	KnifeTool_OpData *kcd = arg; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:26:16 +00:00
										 |  |  | 	if (v3d->zbuf) glDisable(GL_DEPTH_TEST); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	glPolygonOffset(1.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	glPushMatrix(); | 
					
						
							|  |  |  | 	glMultMatrixf(kcd->ob->obmat); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (kcd->mode == MODE_DRAGGING) { | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 		if (kcd->angle_snapping != ANGLE_FREE) | 
					
						
							|  |  |  | 			knifetool_draw_angle_snapping(kcd); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 		glColor3ubv(kcd->colors.line); | 
					
						
							| 
									
										
										
										
											2012-04-19 13:44:28 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glLineWidth(2.0); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glBegin(GL_LINES); | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 		glVertex3fv(kcd->prev.cage); | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		glVertex3fv(kcd->curr.cage); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glEnd(); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		glLineWidth(1.0); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (kcd->curr.edge) { | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 		glColor3ubv(kcd->colors.edge); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glLineWidth(2.0); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glBegin(GL_LINES); | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		glVertex3fv(kcd->curr.edge->v1->cageco); | 
					
						
							|  |  |  | 		glVertex3fv(kcd->curr.edge->v2->cageco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glEnd(); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glLineWidth(1.0); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	else if (kcd->curr.vert) { | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 		glColor3ubv(kcd->colors.point); | 
					
						
							| 
									
										
										
										
											2011-04-13 03:56:14 +00:00
										 |  |  | 		glPointSize(11); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glBegin(GL_POINTS); | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		glVertex3fv(kcd->curr.cage); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glEnd(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (kcd->curr.bmface) { | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 		glColor3ubv(kcd->colors.curpoint); | 
					
						
							| 
									
										
										
										
											2011-04-13 03:56:14 +00:00
										 |  |  | 		glPointSize(9); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glBegin(GL_POINTS); | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		glVertex3fv(kcd->curr.cage); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glEnd(); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (kcd->totlinehit > 0) { | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 		const float vthresh4 = kcd->vthresh / 4.0f; | 
					
						
							|  |  |  | 		const float vthresh4_squared = vthresh4 * vthresh4; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		BMEdgeHit *lh; | 
					
						
							|  |  |  | 		int i; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glEnable(GL_BLEND); | 
					
						
							|  |  |  | 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		/* draw any snapped verts first */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 		glColor4ubv(kcd->colors.point_a); | 
					
						
							| 
									
										
										
										
											2011-04-13 03:56:14 +00:00
										 |  |  | 		glPointSize(11); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glBegin(GL_POINTS); | 
					
						
							|  |  |  | 		lh = kcd->linehits; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (i = 0; i < kcd->totlinehit; i++, lh++) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			float sv1[3], sv2[3]; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 			knife_project_v3(kcd, lh->kfe->v1->cageco, sv1); | 
					
						
							|  |  |  | 			knife_project_v3(kcd, lh->kfe->v2->cageco, sv2); | 
					
						
							|  |  |  | 			knife_project_v3(kcd, lh->cagehit, lh->schit); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 			if (len_squared_v2v2(lh->schit, sv1) < vthresh4_squared) { | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 				copy_v3_v3(lh->cagehit, lh->kfe->v1->cageco); | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 				glVertex3fv(lh->cagehit); | 
					
						
							| 
									
										
										
										
											2010-10-03 21:10:59 +00:00
										 |  |  | 				lh->v = lh->kfe->v1; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 			else if (len_squared_v2v2(lh->schit, sv2) < vthresh4_squared) { | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 				copy_v3_v3(lh->cagehit, lh->kfe->v2->cageco); | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 				glVertex3fv(lh->cagehit); | 
					
						
							| 
									
										
										
										
											2010-10-03 21:10:59 +00:00
										 |  |  | 				lh->v = lh->kfe->v2; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		/* now draw the rest */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 		glColor4ubv(kcd->colors.curpoint_a); | 
					
						
							| 
									
										
										
										
											2011-04-13 03:56:14 +00:00
										 |  |  | 		glPointSize(7); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glBegin(GL_POINTS); | 
					
						
							|  |  |  | 		lh = kcd->linehits; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (i = 0; i < kcd->totlinehit; i++, lh++) { | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 			glVertex3fv(lh->cagehit); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glDisable(GL_BLEND); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (kcd->totkedge > 0) { | 
					
						
							|  |  |  | 		BLI_mempool_iter iter; | 
					
						
							|  |  |  | 		KnifeEdge *kfe; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glLineWidth(1.0); | 
					
						
							|  |  |  | 		glBegin(GL_LINES); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BLI_mempool_iternew(kcd->kedges, &iter); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			if (!kfe->draw) | 
					
						
							|  |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 			glColor3ubv(kcd->colors.line); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 			glVertex3fv(kfe->v1->cageco); | 
					
						
							|  |  |  | 			glVertex3fv(kfe->v2->cageco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		glEnd(); | 
					
						
							|  |  |  | 		glLineWidth(1.0); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (kcd->totkvert > 0) { | 
					
						
							|  |  |  | 		BLI_mempool_iter iter; | 
					
						
							|  |  |  | 		KnifeVert *kfv; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 03:56:14 +00:00
										 |  |  | 		glPointSize(5.0); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		glBegin(GL_POINTS); | 
					
						
							|  |  |  | 		BLI_mempool_iternew(kcd->kverts, &iter); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			if (!kfv->draw) | 
					
						
							|  |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 			glColor3ubv(kcd->colors.point); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 			glVertex3fv(kfv->cageco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		glEnd(); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	glPopMatrix(); | 
					
						
							| 
									
										
										
										
											2012-04-17 17:25:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:26:16 +00:00
										 |  |  | 	if (v3d->zbuf) glEnable(GL_DEPTH_TEST); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-02 20:45:20 +00:00
										 |  |  | static float len_v3_tri_side_max(const float v1[3], const float v2[3], const float v3[3]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 	const float s1 = len_squared_v3v3(v1, v2); | 
					
						
							|  |  |  | 	const float s2 = len_squared_v3v3(v2, v3); | 
					
						
							|  |  |  | 	const float s3 = len_squared_v3v3(v3, v1); | 
					
						
							| 
									
										
										
										
											2011-12-02 20:45:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 	return sqrtf(MAX3(s1, s2, s3)); | 
					
						
							| 
									
										
										
										
											2011-12-02 20:45:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, | 
					
						
							| 
									
										
										
										
											2011-12-02 20:45:20 +00:00
										 |  |  |                                        const float v1[3],  const float v2[3], const float v3[3], | 
					
						
							|  |  |  |                                        SmallHash *ehash, bglMats *mats, int *count) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	BVHTree *tree2 = BLI_bvhtree_new(3, FLT_EPSILON * 4, 8, 8), *tree = BMBVH_BVHTree(bmtree); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	BMEdgeHit *edges = NULL; | 
					
						
							|  |  |  | 	BLI_array_declare(edges); | 
					
						
							|  |  |  | 	BVHTreeOverlap *results, *result; | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | 	BMLoop **ls; | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 	float cos[9], lambda; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	unsigned int tot = 0; | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-02 20:45:20 +00:00
										 |  |  | 	/* for comparing distances, error of intersection depends on triangle scale.
 | 
					
						
							|  |  |  | 	 * need to scale down before squaring for accurate comparison */ | 
					
						
							| 
									
										
										
										
											2012-10-23 14:57:25 +00:00
										 |  |  | 	const float depsilon = (FLT_EPSILON / 2.0f) * len_v3_tri_side_max(v1, v2, v3); | 
					
						
							| 
									
										
										
										
											2011-12-02 20:45:20 +00:00
										 |  |  | 	const float depsilon_squared = depsilon * depsilon; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	copy_v3_v3(cos + 0, v1); | 
					
						
							|  |  |  | 	copy_v3_v3(cos + 3, v2); | 
					
						
							|  |  |  | 	copy_v3_v3(cos + 6, v3); | 
					
						
							| 
									
										
										
										
											2011-09-17 12:31:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	BLI_bvhtree_insert(tree2, 0, cos, 3); | 
					
						
							|  |  |  | 	BLI_bvhtree_balance(tree2); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	result = results = BLI_bvhtree_overlap(tree, tree2, &tot); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	for (i = 0; i < tot; i++, result++) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		float p[3]; | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 		BMLoop *l1; | 
					
						
							|  |  |  | 		BMFace *hitf; | 
					
						
							|  |  |  | 		ListBase *lst; | 
					
						
							|  |  |  | 		Ref *ref; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-25 20:58:03 +00:00
										 |  |  | 		ls = (BMLoop **)kcd->em->looptris[result->indexA]; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 		l1 = ls[0]; | 
					
						
							|  |  |  | 		lst = knife_get_face_kedges(kcd, l1->f); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 		for (ref = lst->first; ref; ref = ref->next) { | 
					
						
							|  |  |  | 			KnifeEdge *kfe = ref->ref; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 			if (BLI_smallhash_haskey(ehash, (intptr_t)kfe)) { | 
					
						
							| 
									
										
										
										
											2012-09-03 05:36:47 +00:00
										 |  |  | 				continue;  /* We already found a hit on this knife edge */ | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 			if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) { | 
					
						
							|  |  |  | 				float no[3], view[3], sp[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 				if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_squared) { | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_squared) { | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 				if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_squared || | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 				    len_squared_v3v3(kcd->curr.cage, p) < depsilon_squared) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				knife_project_v3(kcd, p, sp); | 
					
						
							| 
									
										
										
										
											2012-09-20 04:56:24 +00:00
										 |  |  | 				ED_view3d_unproject(mats, view, sp[0], sp[1], 0.0f); | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 				mul_m4_v3(kcd->ob->imat, view); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (kcd->cut_through) { | 
					
						
							|  |  |  | 					hitf = FALSE; | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					/* check if this point is visible in the viewport */ | 
					
						
							|  |  |  | 					float p1[3], lambda1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					/* if face isn't planer, p may be behind the current tesselated tri,
 | 
					
						
							| 
									
										
										
										
											2012-09-03 05:36:47 +00:00
										 |  |  | 					 * so move it onto that and then a little towards eye */ | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					if (isect_line_tri_v3(p, view, ls[0]->v->co, ls[1]->v->co, ls[2]->v->co, &lambda1, NULL)) { | 
					
						
							|  |  |  | 						interp_v3_v3v3(p1, p, view, lambda1); | 
					
						
							| 
									
										
										
										
											2012-09-03 05:36:47 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					else { | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 						copy_v3_v3(p1, p); | 
					
						
							| 
									
										
										
										
											2011-11-28 01:20:53 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					sub_v3_v3(view, p1); | 
					
						
							|  |  |  | 					normalize_v3(view); | 
					
						
							| 
									
										
										
										
											2011-11-28 01:20:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					copy_v3_v3(no, view); | 
					
						
							|  |  |  | 					mul_v3_fl(no, 0.003); | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					/* go towards view a bit */ | 
					
						
							|  |  |  | 					add_v3_v3(p1, no); | 
					
						
							|  |  |  | 						 | 
					
						
							|  |  |  | 					/* ray cast */ | 
					
						
							|  |  |  | 					hitf = BMBVH_RayCast(bmtree, p1, no, NULL, NULL); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 				/* ok, if visible add the new point */ | 
					
						
							|  |  |  | 				if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) { | 
					
						
							|  |  |  | 					BMEdgeHit hit; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 					if (len_squared_v3v3(p, kcd->curr.co) < depsilon_squared || | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					    len_squared_v3v3(p, kcd->prev.co) < depsilon_squared) | 
					
						
							| 
									
										
										
										
											2012-09-03 05:36:47 +00:00
										 |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 						continue; | 
					
						
							| 
									
										
										
										
											2012-09-03 05:36:47 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					hit.kfe = kfe; | 
					
						
							|  |  |  | 					hit.v = NULL; | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					knife_find_basef(kfe); | 
					
						
							|  |  |  | 					hit.f = kfe->basef; | 
					
						
							|  |  |  | 					hit.perc = len_v3v3(p, kfe->v1->cageco) / len_v3v3(kfe->v1->cageco, kfe->v2->cageco); | 
					
						
							|  |  |  | 					copy_v3_v3(hit.cagehit, p); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					interp_v3_v3v3(p, kfe->v1->co, kfe->v2->co, hit.perc); | 
					
						
							|  |  |  | 					copy_v3_v3(hit.realhit, p); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					/* BMESH_TODO: should also snap to vertices */ | 
					
						
							|  |  |  | 					if (kcd->snap_midpoints) { | 
					
						
							|  |  |  | 						float perc = hit.perc; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						/* select the closest from the edge endpoints or the midpoint */ | 
					
						
							|  |  |  | 						if (perc < 0.25f) { | 
					
						
							|  |  |  | 							perc = 0.0f; | 
					
						
							| 
									
										
										
										
											2012-09-03 05:36:47 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 						else if (perc < 0.75f) { | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 							perc = 0.5f; | 
					
						
							| 
									
										
										
										
											2012-09-03 05:36:47 +00:00
										 |  |  | 						} | 
					
						
							|  |  |  | 						else { | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 							perc = 1.0f; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 						interp_v3_v3v3(hit.hit, kfe->v1->co, kfe->v2->co, perc); | 
					
						
							|  |  |  | 						interp_v3_v3v3(hit.cagehit, kfe->v1->cageco, kfe->v2->cageco, perc); | 
					
						
							| 
									
										
										
										
											2012-09-03 05:36:47 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					else { | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 						copy_v3_v3(hit.hit, p); | 
					
						
							| 
									
										
										
										
											2010-10-03 21:10:59 +00:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2012-08-06 13:37:25 +00:00
										 |  |  | 					knife_project_v3(kcd, hit.cagehit, hit.schit); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					BLI_array_append(edges, hit); | 
					
						
							|  |  |  | 					BLI_smallhash_insert(ehash, (intptr_t)kfe, NULL); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (results) | 
					
						
							|  |  |  | 		MEM_freeN(results); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-12 18:46:21 +00:00
										 |  |  | 	BLI_bvhtree_free(tree2); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	*count = BLI_array_count(edges); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return edges; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_bgl_get_mats(KnifeTool_OpData *UNUSED(kcd), bglMats *mats) | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bgl_get_mats(mats); | 
					
						
							|  |  |  | 	//copy_m4_m4(mats->modelview, kcd->vc.rv3d->viewmat);
 | 
					
						
							|  |  |  | 	//copy_m4_m4(mats->projection, kcd->vc.rv3d->winmat);
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 18:17:51 +00:00
										 |  |  | /* Calculate maximum excursion (doubled) from (0,0,0) of mesh */ | 
					
						
							|  |  |  | static void calc_ortho_extent(KnifeTool_OpData *kcd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 	BMVert *v; | 
					
						
							|  |  |  | 	BMesh* bm = kcd->em->bm; | 
					
						
							|  |  |  | 	float max_xyz = 0.0f; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							|  |  |  | 		for (i = 0; i < 3; i++) | 
					
						
							|  |  |  | 			max_xyz = max_ff(max_xyz, fabs(v->co[i])); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	kcd->ortho_extent = 2 * max_xyz; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | /* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_find_line_hits(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bglMats mats; | 
					
						
							|  |  |  | 	BMEdgeHit *e1, *e2; | 
					
						
							| 
									
										
										
										
											2010-10-04 04:35:42 +00:00
										 |  |  | 	SmallHash hash, *ehash = &hash; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	float v1[3], v2[3], v3[3], v4[4], s1[3], s2[3]; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	int i, c1, c2; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	knife_bgl_get_mats(kcd, &mats); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (kcd->linehits) { | 
					
						
							|  |  |  | 		MEM_freeN(kcd->linehits); | 
					
						
							|  |  |  | 		kcd->linehits = NULL; | 
					
						
							|  |  |  | 		kcd->totlinehit = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	copy_v3_v3(v1, kcd->prev.cage); | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	copy_v3_v3(v2, kcd->curr.cage); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* project screen line's 3d coordinates back into 2d */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	knife_project_v3(kcd, v1, s1); | 
					
						
							|  |  |  | 	knife_project_v3(kcd, v2, s2); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (len_v2v2(s1, s2) < 1) | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* unproject screen line */ | 
					
						
							| 
									
										
										
										
											2011-05-20 16:52:10 +00:00
										 |  |  | 	ED_view3d_win_to_segment_clip(kcd->ar, kcd->vc.v3d, s1, v1, v3); | 
					
						
							|  |  |  | 	ED_view3d_win_to_segment_clip(kcd->ar, kcd->vc.v3d, s2, v2, v4); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	mul_m4_v3(kcd->ob->imat, v1); | 
					
						
							|  |  |  | 	mul_m4_v3(kcd->ob->imat, v2); | 
					
						
							|  |  |  | 	mul_m4_v3(kcd->ob->imat, v3); | 
					
						
							|  |  |  | 	mul_m4_v3(kcd->ob->imat, v4); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-13 01:11:08 +00:00
										 |  |  | 	/* numeric error, 'v1' -> 'v2', 'v2' -> 'v4' can end up being ~2000 units apart in otho mode
 | 
					
						
							|  |  |  | 	 * (from ED_view3d_win_to_segment_clip() above) | 
					
						
							|  |  |  | 	 * this gives precision error in 'knife_edge_tri_isect', rather then solving properly | 
					
						
							|  |  |  | 	 * (which may involve using doubles everywhere!), | 
					
						
							|  |  |  | 	 * limit the distance between these points */ | 
					
						
							|  |  |  | 	if (kcd->is_ortho) { | 
					
						
							| 
									
										
										
										
											2012-10-23 18:17:51 +00:00
										 |  |  | 		if (kcd->ortho_extent == 0.0f) | 
					
						
							|  |  |  | 			calc_ortho_extent(kcd); | 
					
						
							|  |  |  | 		limit_dist_v3(v1, v3, kcd->ortho_extent + 10.0f); | 
					
						
							|  |  |  | 		limit_dist_v3(v2, v4, kcd->ortho_extent + 10.0f); | 
					
						
							| 
									
										
										
										
											2012-03-13 01:11:08 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-04 04:35:42 +00:00
										 |  |  | 	BLI_smallhash_init(ehash); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* test two triangles of sceen line's plane */ | 
					
						
							| 
									
										
										
										
											2010-10-04 04:35:42 +00:00
										 |  |  | 	e1 = knife_edge_tri_isect(kcd, kcd->bmbvh, v1, v2, v3, ehash, &mats, &c1); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	e2 = knife_edge_tri_isect(kcd, kcd->bmbvh, v2, v3, v4, ehash, &mats, &c2); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (c1 && c2) { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		e1 = MEM_reallocN(e1, sizeof(BMEdgeHit) * (c1 + c2)); | 
					
						
							|  |  |  | 		memcpy(e1 + c1, e2, sizeof(BMEdgeHit) * c2); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		MEM_freeN(e2); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (c2) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		e1 = e2; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	kcd->linehits = e1; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	kcd->totlinehit = c1 + c2; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* find position along screen line, used for sorting */ | 
					
						
							|  |  |  | 	for (i = 0; i < kcd->totlinehit; i++) { | 
					
						
							|  |  |  | 		BMEdgeHit *lh = e1 + i; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		lh->l = len_v2v2(lh->schit, s1) / len_v2v2(s2, s1); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-04 04:35:42 +00:00
										 |  |  | 	BLI_smallhash_release(ehash); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_input_ray_cast(KnifeTool_OpData *kcd, const int mval_i[2], | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  |                                  float r_origin[3], float r_ray[3]) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bglMats mats; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	float mval[2], imat[3][3]; | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | 	knife_bgl_get_mats(kcd, &mats); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 	mval[0] = (float)mval_i[0]; | 
					
						
							|  |  |  | 	mval[1] = (float)mval_i[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* unproject to find view ray */ | 
					
						
							| 
									
										
										
										
											2012-09-20 04:56:24 +00:00
										 |  |  | 	ED_view3d_unproject(&mats, r_origin, mval[0], mval[1], 0.0f); | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	if (kcd->is_ortho) { | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 		negate_v3_v3(r_ray, kcd->vc.rv3d->viewinv[2]); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 		sub_v3_v3v3(r_ray, r_origin, kcd->vc.rv3d->viewinv[3]); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 	normalize_v3(r_ray); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* transform into object space */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); | 
					
						
							|  |  |  | 	copy_m3_m4(imat, kcd->ob->obmat); | 
					
						
							|  |  |  | 	invert_m3(imat); | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	mul_m4_v3(kcd->ob->imat, r_origin); | 
					
						
							|  |  |  | 	mul_m3_v3(imat, r_ray); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], int *is_space) | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							| 
									
										
										
										
											2012-10-10 01:22:19 +00:00
										 |  |  | 	float dist = KMAXDIST; | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 	float origin[3]; | 
					
						
							|  |  |  | 	float ray[3]; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* unproject to find view ray */ | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 	knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray); | 
					
						
							|  |  |  | 	add_v3_v3v3(co, origin, ray); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	if (is_space) | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		*is_space = !f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (!f) { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		/* try to use backbuffer selection method if ray casting failed */ | 
					
						
							| 
									
										
										
										
											2012-03-27 04:46:52 +00:00
										 |  |  | 		f = EDBM_face_find_nearest(&kcd->vc, &dist); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 		/* cheat for now; just put in the origin instead
 | 
					
						
							|  |  |  | 		 * of a true coordinate on the face. | 
					
						
							|  |  |  | 		 * This just puts a point 1.0f infront of the view. */ | 
					
						
							|  |  |  | 		add_v3_v3v3(co, origin, ray); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return f; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* find the 2d screen space density of vertices within a radius.  used to scale snapping
 | 
					
						
							|  |  |  |  * distance for picking edges/verts.*/ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	int is_space; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	float co[3], cageco[3], sco[3]; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	f = knife_find_closest_face(kcd, co, cageco, &is_space); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	if (f && !is_space) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		ListBase *lst; | 
					
						
							|  |  |  | 		Ref *ref; | 
					
						
							|  |  |  | 		float dis; | 
					
						
							|  |  |  | 		int c = 0; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 		knife_project_v3(kcd, cageco, sco); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		lst = knife_get_face_kedges(kcd, f); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (ref = lst->first; ref; ref = ref->next) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			KnifeEdge *kfe = ref->ref; | 
					
						
							|  |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			for (i = 0; i < 2; i++) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				KnifeVert *kfv = i ? kfe->v2 : kfe->v1; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 				knife_project_v3(kcd, kfv->cageco, kfv->sco); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				dis = len_v2v2(kfv->sco, sco); | 
					
						
							|  |  |  | 				if (dis < radius) { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 					if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 						float vec[3]; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 						copy_v3_v3(vec, kfv->cageco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 						mul_m4_v3(kcd->vc.obedit->obmat, vec); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-28 13:03:56 +00:00
										 |  |  | 						if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 							c++; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					else { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 						c++; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		return c; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* returns snapping distance for edges/verts, scaled by the density of the
 | 
					
						
							|  |  |  |  * surrounding mesh (in screen space)*/ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	float density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-06 22:48:28 +00:00
										 |  |  | 	if (density < 1.0f) | 
					
						
							|  |  |  | 		density = 1.0f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-23 13:28:22 +00:00
										 |  |  | 	return min_ff(maxsize / (density * 0.5f), maxsize); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* p is closest point on edge to the mouse cursor */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, int *is_space) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->ethresh); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 	if (kcd->ignore_vert_snapping) | 
					
						
							| 
									
										
										
										
											2012-05-03 21:35:04 +00:00
										 |  |  | 		maxdist *= 0.5f; | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	f = knife_find_closest_face(kcd, co, cageco, NULL); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	*is_space = !f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* set p to co, in case we don't find anything, means a face cut */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	copy_v3_v3(p, co); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	copy_v3_v3(cagep, cageco); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	kcd->curr.bmface = f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (f) { | 
					
						
							|  |  |  | 		KnifeEdge *cure = NULL; | 
					
						
							|  |  |  | 		ListBase *lst; | 
					
						
							|  |  |  | 		Ref *ref; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		float dis, curdis = FLT_MAX; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 		knife_project_v3(kcd, cageco, sco); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		/* look through all edges associated with this face */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		lst = knife_get_face_kedges(kcd, f); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (ref = lst->first; ref; ref = ref->next) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			KnifeEdge *kfe = ref->ref; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			/* project edge vertices into screen space */ | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 			knife_project_v3(kcd, kfe->v1->cageco, kfe->v1->sco); | 
					
						
							|  |  |  | 			knife_project_v3(kcd, kfe->v2->cageco, kfe->v2->sco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			dis = dist_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco); | 
					
						
							|  |  |  | 			if (dis < curdis && dis < maxdist) { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 				if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { | 
					
						
							|  |  |  | 					float labda = labda_PdistVL2Dfl(sco, kfe->v1->sco, kfe->v2->sco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 					float vec[3]; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 					vec[0] = kfe->v1->cageco[0] + labda * (kfe->v2->cageco[0] - kfe->v1->cageco[0]); | 
					
						
							|  |  |  | 					vec[1] = kfe->v1->cageco[1] + labda * (kfe->v2->cageco[1] - kfe->v1->cageco[1]); | 
					
						
							|  |  |  | 					vec[2] = kfe->v1->cageco[2] + labda * (kfe->v2->cageco[2] - kfe->v1->cageco[2]); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 					mul_m4_v3(kcd->vc.obedit->obmat, vec); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-28 13:03:56 +00:00
										 |  |  | 					if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 						cure = kfe; | 
					
						
							|  |  |  | 						curdis = dis; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 					cure = kfe; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 					curdis = dis; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		if (fptr) | 
					
						
							|  |  |  | 			*fptr = f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		if (cure && p) { | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 			if (!kcd->ignore_edge_snapping || !(cure->e)) { | 
					
						
							| 
									
										
										
										
											2012-06-21 08:58:17 +00:00
										 |  |  | 				KnifeVert *edgesnap = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 				if (kcd->snap_midpoints) { | 
					
						
							| 
									
										
										
										
											2011-11-16 06:17:56 +00:00
										 |  |  | 					mid_v3_v3v3(p, cure->v1->co, cure->v2->co); | 
					
						
							|  |  |  | 					mid_v3_v3v3(cagep, cure->v1->cageco, cure->v2->cageco); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 					float d; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 					closest_to_line_segment_v3(cagep, cageco, cure->v1->cageco, cure->v2->cageco); | 
					
						
							|  |  |  | 					d = len_v3v3(cagep, cure->v1->cageco) / len_v3v3(cure->v1->cageco, cure->v2->cageco); | 
					
						
							|  |  |  | 					interp_v3_v3v3(p, cure->v1->co, cure->v2->co, d); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-06-21 08:58:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* update mouse coordinates to the snapped-to edge's screen coordinates
 | 
					
						
							|  |  |  | 				 * this is important for angle snap, which uses the previous mouse position */ | 
					
						
							|  |  |  | 				edgesnap = new_knife_vert(kcd, p, cagep); | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 				kcd->curr.mval[0] = (int)edgesnap->sco[0]; | 
					
						
							|  |  |  | 				kcd->curr.mval[1] = (int)edgesnap->sco[1]; | 
					
						
							| 
									
										
										
										
											2012-06-21 08:58:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 				return NULL; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		return cure; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (fptr) | 
					
						
							|  |  |  | 		*fptr = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* find a vertex near the mouse cursor, if it exists */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  |                                           int *is_space) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->vthresh); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 	if (kcd->ignore_vert_snapping) | 
					
						
							| 
									
										
										
										
											2012-05-03 21:35:04 +00:00
										 |  |  | 		maxdist *= 0.5f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	f = knife_find_closest_face(kcd, co, cageco, is_space); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* set p to co, in case we don't find anything, means a face cut */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	copy_v3_v3(p, co); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	copy_v3_v3(cagep, p); | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	kcd->curr.bmface = f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (f) { | 
					
						
							|  |  |  | 		ListBase *lst; | 
					
						
							|  |  |  | 		Ref *ref; | 
					
						
							|  |  |  | 		KnifeVert *curv = NULL; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		float dis, curdis = FLT_MAX; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 		knife_project_v3(kcd, cageco, sco); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		lst = knife_get_face_kedges(kcd, f); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (ref = lst->first; ref; ref = ref->next) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 			KnifeEdge *kfe = ref->ref; | 
					
						
							|  |  |  | 			int i; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			for (i = 0; i < 2; i++) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				KnifeVert *kfv = i ? kfe->v2 : kfe->v1; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 				knife_project_v3(kcd, kfv->cageco, kfv->sco); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				dis = len_v2v2(kfv->sco, sco); | 
					
						
							|  |  |  | 				if (dis < curdis && dis < maxdist) { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 					if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 						float vec[3]; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 						copy_v3_v3(vec, kfv->cageco); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 						mul_m4_v3(kcd->vc.obedit->obmat, vec); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-28 13:03:56 +00:00
										 |  |  | 						if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 							curv = kfv; | 
					
						
							|  |  |  | 							curdis = dis; | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					else { | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 						curv = kfv; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 						curdis = dis; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 		if (!kcd->ignore_vert_snapping || !(curv && curv->v)) { | 
					
						
							|  |  |  | 			if (fptr) | 
					
						
							|  |  |  | 				*fptr = f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 			if (curv && p) { | 
					
						
							|  |  |  | 				copy_v3_v3(p, curv->co); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 				copy_v3_v3(cagep, curv->cageco); | 
					
						
							| 
									
										
										
										
											2012-06-21 08:58:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				/* update mouse coordinates to the snapped-to vertex's screen coordinates
 | 
					
						
							|  |  |  | 				 * this is important for angle snap, which uses the previous mouse position */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 				kcd->curr.mval[0] = (int)curv->sco[0]; | 
					
						
							|  |  |  | 				kcd->curr.mval[1] = (int)curv->sco[1]; | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 			return curv; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 			if (fptr) | 
					
						
							|  |  |  | 				*fptr = f; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-01 04:40:59 +00:00
										 |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (fptr) | 
					
						
							|  |  |  | 		*fptr = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_snap_angle(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int dx, dy; | 
					
						
							|  |  |  | 	float w, abs_tan; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	dx = kcd->vc.mval[0] - kcd->prev.mval[0]; | 
					
						
							|  |  |  | 	dy = kcd->vc.mval[1] - kcd->prev.mval[1]; | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 	if (dx == 0 || dy == 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	w = (float)dy / (float)dx; | 
					
						
							|  |  |  | 	abs_tan = fabsf(w); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	if (abs_tan <= 0.4142f) { /* tan(22.5 degrees) = 0.4142 */ | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 		kcd->angle_snapping = ANGLE_0; | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 		kcd->vc.mval[1] = kcd->prev.mval[1]; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (abs_tan < 2.4142f) { /* tan(67.5 degrees) = 2.4142 */ | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 		if (w > 0) { | 
					
						
							|  |  |  | 			kcd->angle_snapping = ANGLE_45; | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 			kcd->vc.mval[1] = kcd->prev.mval[1] + dx; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 			kcd->angle_snapping = ANGLE_135; | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 			kcd->vc.mval[1] = kcd->prev.mval[1] - dx; | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 		kcd->angle_snapping = ANGLE_90; | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 		kcd->vc.mval[0] = kcd->prev.mval[0]; | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* update active knife edge/vert pointers */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static int knife_update_active(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 	if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) | 
					
						
							|  |  |  | 		knife_snap_angle(kcd); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	knife_pos_data_clear(&kcd->curr); | 
					
						
							|  |  |  | 	kcd->curr.mval[0] = kcd->vc.mval[0]; | 
					
						
							|  |  |  | 	kcd->curr.mval[1] = kcd->vc.mval[1]; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-22 04:40:38 +00:00
										 |  |  | 	/* XXX knife_snap_angle updates the view coordinate mouse values to constrained angles,
 | 
					
						
							|  |  |  | 	 * which current mouse values are set to current mouse values are then used | 
					
						
							|  |  |  | 	 * for vertex and edge snap detection, without regard to the exact angle constraint */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	kcd->curr.vert = knife_find_closest_vert(kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space); | 
					
						
							| 
									
										
										
										
											2012-06-21 08:58:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (!kcd->curr.vert) { | 
					
						
							|  |  |  | 		kcd->curr.edge = knife_find_closest_edge(kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.bmface, &kcd->curr.is_space); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	/* if no hits are found this would normally default to (0, 0, 0) so instead
 | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 	 * get a point at the mouse ray closest to the previous point. | 
					
						
							|  |  |  | 	 * Note that drawing lines in `free-space` isn't properly supported | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	 * but theres no guarantee (0, 0, 0) has any geometry either - campbell */ | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	if (kcd->curr.vert == NULL && kcd->curr.edge == NULL) { | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		float origin[3], ray[3], co[3]; | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		knife_input_ray_cast(kcd, kcd->vc.mval, origin, ray); | 
					
						
							|  |  |  | 		add_v3_v3v3(co, origin, ray); | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 		closest_to_line_v3(kcd->curr.cage, kcd->prev.cage, co, origin); | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (kcd->mode == MODE_DRAGGING) { | 
					
						
							|  |  |  | 		knife_find_line_hits(kcd); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-20 01:02:39 +00:00
										 |  |  | #define SCANFILL_CUTS 0
 | 
					
						
							|  |  |  | #if SCANFILL_CUTS
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | #define MARK            4
 | 
					
						
							|  |  |  | #define DEL             8
 | 
					
						
							|  |  |  | #define VERT_ON_EDGE    16
 | 
					
						
							|  |  |  | #define VERT_ORIG       32
 | 
					
						
							|  |  |  | #define FACE_FLIP       64
 | 
					
						
							|  |  |  | #define BOUNDARY        128
 | 
					
						
							|  |  |  | #define FACE_NEW        256
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct facenet_entry { | 
					
						
							|  |  |  | 	struct facenet_entry *next, *prev; | 
					
						
							|  |  |  | 	KnifeEdge *kfe; | 
					
						
							|  |  |  | } facenet_entry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void rnd_offset_co(float co[3], float scale) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	for (i = 0; i < 3; i++) { | 
					
						
							| 
									
										
										
										
											2012-04-15 10:06:36 +00:00
										 |  |  | 		co[i] += (BLI_frand() - 0.5) * scale; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void remerge_faces(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMesh *bm = kcd->em->bm; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	SmallHash svisit, *visit = &svisit; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 	BMFace **stack = NULL; | 
					
						
							|  |  |  | 	BLI_array_declare(stack); | 
					
						
							|  |  |  | 	BMFace **faces = NULL; | 
					
						
							|  |  |  | 	BLI_array_declare(faces); | 
					
						
							| 
									
										
										
										
											2011-04-22 23:37:58 +00:00
										 |  |  | 	BMOperator bmop; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	int idx; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 	BMO_op_initf(bm, &bmop, "beautify_fill faces=%ff constrain_edges=%fe", FACE_NEW, BOUNDARY); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 	BMO_op_exec(bm, &bmop); | 
					
						
							| 
									
										
										
										
											2012-03-19 08:36:27 +00:00
										 |  |  | 	BMO_slot_buffer_flag_enable(bm, &bmop, "geomout", BM_FACE, FACE_NEW); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 	BMO_op_finish(bm, &bmop); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	BLI_smallhash_init(visit); | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 	BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		BMIter eiter; | 
					
						
							|  |  |  | 		BMEdge *e; | 
					
						
							|  |  |  | 		BMFace *f2; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 		if (!BMO_elem_flag_test(bm, f, FACE_NEW)) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 21:48:16 +00:00
										 |  |  | 		if (BLI_smallhash_haskey(visit, (intptr_t)f)) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		BLI_array_empty(stack); | 
					
						
							|  |  |  | 		BLI_array_empty(faces); | 
					
						
							|  |  |  | 		BLI_array_append(stack, f); | 
					
						
							| 
									
										
										
										
											2011-04-13 21:48:16 +00:00
										 |  |  | 		BLI_smallhash_insert(visit, (intptr_t)f, NULL); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		do { | 
					
						
							|  |  |  | 			f2 = BLI_array_pop(stack); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			BLI_array_append(faces, f2); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 			BM_ITER_ELEM (e, &eiter, f2, BM_EDGES_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 				BMIter fiter; | 
					
						
							|  |  |  | 				BMFace *f3; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 				if (BMO_elem_flag_test(bm, e, BOUNDARY)) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 				BM_ITER_ELEM (f3, &fiter, e, BM_FACES_OF_EDGE) { | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 					if (!BMO_elem_flag_test(bm, f3, FACE_NEW)) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 						continue; | 
					
						
							| 
									
										
										
										
											2011-04-13 21:48:16 +00:00
										 |  |  | 					if (BLI_smallhash_haskey(visit, (intptr_t)f3)) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 						continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 21:48:16 +00:00
										 |  |  | 					BLI_smallhash_insert(visit, (intptr_t)f3, NULL); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 					BLI_array_append(stack, f3); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		} while (BLI_array_count(stack) > 0); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		if (BLI_array_count(faces) > 0) { | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 			idx = BM_elem_index_get(faces[0]); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 15:09:13 +00:00
										 |  |  | 			f2 = BM_faces_join(bm, faces, BLI_array_count(faces), TRUE); | 
					
						
							| 
									
										
										
										
											2012-02-27 10:35:39 +00:00
										 |  |  | 			if (f2) { | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 				BMO_elem_flag_enable(bm, f2, FACE_NEW); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 				BM_elem_index_set(f2, idx); /* set_dirty! *//* BMESH_TODO, check if this is valid or not */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 	/* BMESH_TODO, check if the code above validates the indices */ | 
					
						
							| 
									
										
										
										
											2011-11-16 12:38:40 +00:00
										 |  |  | 	/* bm->elem_index_dirty &= ~BM_FACE; */ | 
					
						
							|  |  |  | 	bm->elem_index_dirty |= BM_FACE; | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-17 05:33:23 +00:00
										 |  |  | 	BLI_smallhash_release(visit); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-18 08:39:26 +00:00
										 |  |  | 	BLI_array_free(stack); | 
					
						
							|  |  |  | 	BLI_array_free(faces); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* use edgenet to fill faces.  this is a bit annoying and convoluted.*/ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knifenet_fill_faces(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-18 15:09:13 +00:00
										 |  |  | 	ScanFillContext sf_ctx; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	BMesh *bm = kcd->em->bm; | 
					
						
							|  |  |  | 	BMIter bmiter; | 
					
						
							|  |  |  | 	BLI_mempool_iter iter; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 	BMEdge *e; | 
					
						
							|  |  |  | 	KnifeVert *kfv; | 
					
						
							|  |  |  | 	KnifeEdge *kfe; | 
					
						
							|  |  |  | 	facenet_entry *entry; | 
					
						
							| 
									
										
										
										
											2012-02-26 22:38:49 +00:00
										 |  |  | 	ListBase *face_nets = MEM_callocN(sizeof(ListBase) * bm->totface, "face_nets"); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	BMFace **faces = MEM_callocN(sizeof(BMFace *) * bm->totface, "faces knife"); | 
					
						
							|  |  |  | 	MemArena *arena = BLI_memarena_new(1 << 16, "knifenet_fill_faces"); | 
					
						
							| 
									
										
										
										
											2012-02-17 02:06:30 +00:00
										 |  |  | 	SmallHash shash; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	int i, j, k = 0, totface = bm->totface; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	BMO_push(bm, NULL); | 
					
						
							| 
									
										
										
										
											2012-02-27 14:07:19 +00:00
										 |  |  | 	bmesh_edit_begin(bm, BMO_OP_FLAG_UNTAN_MULTIRES); | 
					
						
							| 
									
										
										
										
											2011-11-01 12:51:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* BMESH_TODO this should be valid now, leaving here until we can ensure this - campbell */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	i = 0; | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 	BM_ITER_MESH (f, &bmiter, bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 		BM_elem_index_set(f, i); /* set_inline */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		faces[i] = f; | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-11-16 12:38:40 +00:00
										 |  |  | 	bm->elem_index_dirty &= ~BM_FACE; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 	BM_ITER_MESH (e, &bmiter, bm, BM_EDGES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 		BMO_elem_flag_enable(bm, e, BOUNDARY); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 12:20:18 +00:00
										 |  |  | 	/* turn knife verts into real verts, as necessary */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	BLI_mempool_iternew(kcd->kverts, &iter); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) { | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		if (!kfv->v) { | 
					
						
							| 
									
										
										
										
											2011-09-12 05:24:45 +00:00
										 |  |  | 			/* shouldn't we be at least copying the normal? - if not some comment here should explain why - campbell */ | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 			kfv->v = BM_vert_create(bm, kfv->co, NULL); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			kfv->flag = 1; | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 			BMO_elem_flag_enable(bm, kfv->v, DEL); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			kfv->flag = 0; | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 			BMO_elem_flag_enable(bm, kfv->v, VERT_ORIG); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 		BMO_elem_flag_enable(bm, kfv->v, MARK); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* we want to only do changed faces.  first, go over new edges and add to
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	 * face net lists.*/ | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	i = j = k = 0; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	BLI_mempool_iternew(kcd->kedges, &iter); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) { | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		Ref *ref; | 
					
						
							|  |  |  | 		if (!kfe->v1 || !kfe->v2 || kfe->v1->inspace || kfe->v2->inspace) | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		i++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (kfe->e && kfe->v1->v == kfe->e->v1 && kfe->v2->v == kfe->e->v2) { | 
					
						
							|  |  |  | 			kfe->oe = kfe->e; | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 		j++; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		if (kfe->e) { | 
					
						
							|  |  |  | 			kfe->oe = kfe->e; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 			BMO_elem_flag_enable(bm, kfe->e, DEL); | 
					
						
							|  |  |  | 			BMO_elem_flag_disable(bm, kfe->e, BOUNDARY); | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 			kfe->e = NULL; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 		kfe->e = BM_edge_create(bm, kfe->v1->v, kfe->v2->v, NULL, TRUE); | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 		BMO_elem_flag_enable(bm, kfe->e, BOUNDARY); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (ref = kfe->faces.first; ref; ref = ref->next) { | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			f = ref->ref; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			entry = BLI_memarena_alloc(arena, sizeof(*entry)); | 
					
						
							|  |  |  | 			entry->kfe = kfe; | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 			BLI_addtail(face_nets + BM_elem_index_get(f), entry); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* go over original edges, and add to faces with new geometry */ | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 	BLI_mempool_iternew(kcd->kedges, &iter); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) { | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 		Ref *ref; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 		if (!kfe->v1 || !kfe->v2 || kfe->v1->inspace || kfe->v2->inspace) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		if (!(kfe->oe && kfe->v1->v == kfe->oe->v1 && kfe->v2->v == kfe->oe->v2)) | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 		k++; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 		BMO_elem_flag_enable(bm, kfe->e, BOUNDARY); | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 		kfe->oe = kfe->e; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (ref = kfe->faces.first; ref; ref = ref->next) { | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 			f = ref->ref; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 			if (face_nets[BM_elem_index_get(f)].first) { | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 				entry = BLI_memarena_alloc(arena, sizeof(*entry)); | 
					
						
							|  |  |  | 				entry->kfe = kfe; | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 				BLI_addtail(face_nets + BM_elem_index_get(f), entry); | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-15 10:06:36 +00:00
										 |  |  | 	BLI_srand(0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	for (i = 0; i < totface; i++) { | 
					
						
							| 
									
										
										
										
											2012-02-17 02:06:30 +00:00
										 |  |  | 		SmallHash *hash = &shash; | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 		ScanFillFace *sf_tri; | 
					
						
							|  |  |  | 		ScanFillVert *sf_vert, *sf_vert_last; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		int j; | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 		float rndscale = (KNIFE_FLT_EPS / 4.0f); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		f = faces[i]; | 
					
						
							|  |  |  | 		BLI_smallhash_init(hash); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		if (face_nets[i].first) | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 			BMO_elem_flag_enable(bm, f, DEL); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-05 00:23:55 +00:00
										 |  |  | 		BLI_scanfill_begin(&sf_ctx); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (entry = face_nets[i].first; entry; entry = entry->next) { | 
					
						
							| 
									
										
										
										
											2011-04-13 21:48:16 +00:00
										 |  |  | 			if (!BLI_smallhash_haskey(hash, (intptr_t)entry->kfe->v1)) { | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 				sf_vert = BLI_scanfill_vert_add(&sf_ctx, entry->kfe->v1->v->co); | 
					
						
							|  |  |  | 				sf_vert->poly_nr = 0; | 
					
						
							|  |  |  | 				rnd_offset_co(sf_vert->co, rndscale); | 
					
						
							|  |  |  | 				sf_vert->tmp.p = entry->kfe->v1->v; | 
					
						
							|  |  |  | 				BLI_smallhash_insert(hash, (intptr_t)entry->kfe->v1, sf_vert); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-13 21:48:16 +00:00
										 |  |  | 			if (!BLI_smallhash_haskey(hash, (intptr_t)entry->kfe->v2)) { | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 				sf_vert = BLI_scanfill_vert_add(&sf_ctx, entry->kfe->v2->v->co); | 
					
						
							|  |  |  | 				sf_vert->poly_nr = 0; | 
					
						
							|  |  |  | 				rnd_offset_co(sf_vert->co, rndscale); | 
					
						
							|  |  |  | 				sf_vert->tmp.p = entry->kfe->v2->v; | 
					
						
							|  |  |  | 				BLI_smallhash_insert(hash, (intptr_t)entry->kfe->v2, sf_vert); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (j = 0, entry = face_nets[i].first; entry; entry = entry->next, j++) { | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 			sf_vert_last = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v1); | 
					
						
							|  |  |  | 			sf_vert = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v2); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 			sf_vert->poly_nr++; | 
					
						
							|  |  |  | 			sf_vert_last->poly_nr++; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		for (j = 0, entry = face_nets[i].first; entry; entry = entry->next, j++) { | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 			sf_vert_last = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v1); | 
					
						
							|  |  |  | 			sf_vert = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v2); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 			if (sf_vert->poly_nr > 1 && sf_vert_last->poly_nr > 1) { | 
					
						
							|  |  |  | 				ScanFillEdge *sf_edge; | 
					
						
							|  |  |  | 				sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert); | 
					
						
							| 
									
										
										
										
											2011-11-29 11:49:53 +00:00
										 |  |  | 				if (entry->kfe->oe) | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 					sf_edge->f = SF_EDGE_BOUNDARY;  /* mark as original boundary edge */ | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 				BMO_elem_flag_disable(bm, entry->kfe->e->v1, DEL); | 
					
						
							|  |  |  | 				BMO_elem_flag_disable(bm, entry->kfe->e->v2, DEL); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 				if (sf_vert_last->poly_nr < 2) | 
					
						
							|  |  |  | 					BLI_remlink(&sf_ctx.fillvertbase, sf_vert_last); | 
					
						
							|  |  |  | 				if (sf_vert->poly_nr < 2) | 
					
						
							|  |  |  | 					BLI_remlink(&sf_ctx.fillvertbase, sf_vert); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-05 00:23:55 +00:00
										 |  |  | 		BLI_scanfill_calc(&sf_ctx, FALSE); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-13 14:47:53 +00:00
										 |  |  | 		for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { | 
					
						
							|  |  |  | 			BMVert *v1 = sf_tri->v3->tmp.p, *v2 = sf_tri->v2->tmp.p, *v3 = sf_tri->v1->tmp.p; | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			BMFace *f2; | 
					
						
							| 
									
										
										
										
											2012-02-16 09:44:22 +00:00
										 |  |  | 			BMLoop *l_iter; | 
					
						
							| 
									
										
										
										
											2011-04-13 03:56:14 +00:00
										 |  |  | 			BMVert *verts[3] = {v1, v2, v3}; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			if (v1 == v2 || v2 == v3 || v1 == v3) | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 			if (BM_face_exists(bm, verts, 3, &f2)) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 				continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 			f2 = BM_face_create_quad_tri(bm, | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 			                             v1, v2, v3, NULL, | 
					
						
							|  |  |  | 			                             NULL, FALSE); | 
					
						
							| 
									
										
										
										
											2012-02-07 17:42:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 			BMO_elem_flag_enable(bm, f2, FACE_NEW); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-16 09:44:22 +00:00
										 |  |  | 			l_iter = BM_FACE_FIRST_LOOP(f2); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			do { | 
					
						
							| 
									
										
										
										
											2012-02-16 09:44:22 +00:00
										 |  |  | 				BMO_elem_flag_disable(bm, l_iter->e, DEL); | 
					
						
							|  |  |  | 			} while ((l_iter = l_iter->next) != BM_FACE_FIRST_LOOP(f2)); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 18:43:59 +00:00
										 |  |  | 			BMO_elem_flag_disable(bm, f2, DEL); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 			BM_elem_index_set(f2, i); /* set_dirty! *//* note, not 100% sure this is dirty? need to check */ | 
					
						
							| 
									
										
										
										
											2011-11-16 12:38:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 14:38:09 +00:00
										 |  |  | 			BM_face_normal_update(f2); | 
					
						
							| 
									
										
										
										
											2011-11-16 12:38:40 +00:00
										 |  |  | 			if (dot_v3v3(f->no, f2->no) < 0.0f) { | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 				BM_face_normal_flip(bm, f2); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-05 00:23:55 +00:00
										 |  |  | 		BLI_scanfill_end(&sf_ctx); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		BLI_smallhash_release(hash); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-11-16 12:38:40 +00:00
										 |  |  | 	bm->elem_index_dirty |= BM_FACE; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	/* interpolate customdata */ | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 	BM_ITER_MESH (f, &bmiter, bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 		BMLoop *l1; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 		BMFace *f2; | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 		BMIter liter1; | 
					
						
							| 
									
										
										
										
											2011-11-16 12:38:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 		if (!BMO_elem_flag_test(bm, f, FACE_NEW)) | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 		f2 = faces[BM_elem_index_get(f)]; | 
					
						
							|  |  |  | 		if (BM_elem_index_get(f) < 0 || BM_elem_index_get(f) >= totface) { | 
					
						
							| 
									
										
										
										
											2011-09-24 12:13:13 +00:00
										 |  |  | 			fprintf(stderr, "%s: face index out of range! (bmesh internal error)\n", __func__); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-13 02:42:50 +00:00
										 |  |  | 		BM_elem_attrs_copy(bm, bm, f2, f); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 		BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2012-02-07 17:42:46 +00:00
										 |  |  | 			BM_loop_interp_from_face(bm, l1, f2, TRUE, TRUE); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-11-16 12:38:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* merge triangles back into faces */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	remerge_faces(kcd); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	/* delete left over faces */ | 
					
						
							| 
									
										
										
										
											2012-07-21 00:58:02 +00:00
										 |  |  | 	BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete geom=%ff context=%i", DEL, DEL_ONLYFACES); | 
					
						
							|  |  |  | 	BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete geom=%fe context=%i", DEL, DEL_EDGES); | 
					
						
							|  |  |  | 	BMO_op_callf(bm, BMO_FLAG_DEFAULTS, "delete geom=%fv context=%i", DEL, DEL_VERTS); | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (face_nets)  | 
					
						
							|  |  |  | 		MEM_freeN(face_nets); | 
					
						
							|  |  |  | 	if (faces) | 
					
						
							|  |  |  | 		MEM_freeN(faces); | 
					
						
							|  |  |  | 	BLI_memarena_free(arena); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 	BMO_error_clear(bm); /* remerge_faces sometimes raises errors, so make sure to clear them */ | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-27 14:07:19 +00:00
										 |  |  | 	bmesh_edit_end(bm, BMO_OP_FLAG_UNTAN_MULTIRES); | 
					
						
							| 
									
										
										
										
											2011-04-13 00:35:48 +00:00
										 |  |  | 	BMO_pop(bm); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | #else  /* use direct (non-scanfill) method for cuts */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* assuming v is on line ab, what fraction of the way is v from a to b? */ | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | static float frac_along(const float a[3], const float b[3], const float v[3]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	float lab; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lab = len_v3v3(a, b); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	if (lab == 0.0f) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		return 0.0f; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		return len_v3v3(a, v) / lab; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* sort list of kverts by fraction along edge e */ | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | static void sort_by_frac_along(ListBase *lst, BMEdge *e) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	KnifeVert *vcur, *vprev; | 
					
						
							|  |  |  | 	float *v1co, *v2co; | 
					
						
							|  |  |  | 	Ref *cur = NULL, *prev = NULL, *next = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (lst->first == lst->last) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	v1co = e->v1->co; | 
					
						
							|  |  |  | 	v2co = e->v2->co; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	for (cur = ((Ref *)lst->first)->next; cur; cur = next) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		next = cur->next; | 
					
						
							|  |  |  | 		prev = cur->prev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BLI_remlink(lst, cur); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		vcur = cur->ref; | 
					
						
							|  |  |  | 		while (prev) { | 
					
						
							|  |  |  | 			vprev = prev->ref; | 
					
						
							|  |  |  | 			if (frac_along(v1co, v2co, vprev->co) <= frac_along(v1co, v2co, vcur->co)) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			prev = prev->prev; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BLI_insertlinkafter(lst, prev, cur); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The chain so far goes from an instantiated vertex to kfv (some may be reversed).
 | 
					
						
							|  |  |  |  * If possible, complete the chain to another instantiated vertex and return 1, else return 0. | 
					
						
							|  |  |  |  * The visited hash says which KnifeVert's have already been tried, not including kfv. */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static int find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited, | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  |                              ListBase *chain) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	Ref *r; | 
					
						
							|  |  |  | 	KnifeEdge *kfe; | 
					
						
							|  |  |  | 	KnifeVert *kfv_other; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (kfv->v) | 
					
						
							|  |  |  | 		return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL); | 
					
						
							|  |  |  | 	/* Try all possible next edges. Could either go through fedges
 | 
					
						
							|  |  |  | 	 * (all the KnifeEdges for the face being cut) or could go through | 
					
						
							|  |  |  | 	 * kve->edges and restrict to cutting face and uninstantiated edges. | 
					
						
							|  |  |  | 	 * Not clear which is better. Let's do the first. */ | 
					
						
							|  |  |  | 	for (r = fedges->first; r; r = r->next) { | 
					
						
							|  |  |  | 		kfe = r->ref; | 
					
						
							|  |  |  | 		kfv_other = NULL; | 
					
						
							|  |  |  | 		if (kfe->v1 == kfv) | 
					
						
							|  |  |  | 			kfv_other = kfe->v2; | 
					
						
							|  |  |  | 		else if (kfe->v2 == kfv) | 
					
						
							|  |  |  | 			kfv_other = kfe->v1; | 
					
						
							|  |  |  | 		if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) { | 
					
						
							|  |  |  | 			knife_append_list(kcd, chain, kfe); | 
					
						
							|  |  |  | 			if (find_chain_search(kcd, kfv_other, fedges, visited, chain)) | 
					
						
							|  |  |  | 				return TRUE; | 
					
						
							|  |  |  | 			BLI_remlink(chain, chain->last); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static ListBase *find_chain_from_vertex(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMVert *v, ListBase *fedges) | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	SmallHash visited_, *visited = &visited_; | 
					
						
							|  |  |  | 	ListBase *ans; | 
					
						
							|  |  |  | 	int found; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ans = knife_empty_list(kcd); | 
					
						
							|  |  |  | 	knife_append_list(kcd, ans, kfe); | 
					
						
							|  |  |  | 	found = 0; | 
					
						
							|  |  |  | 	BLI_smallhash_init(visited); | 
					
						
							|  |  |  | 	if (kfe->v1->v == v) { | 
					
						
							|  |  |  | 		BLI_smallhash_insert(visited, (uintptr_t)(kfe->v1), NULL); | 
					
						
							|  |  |  | 		found = find_chain_search(kcd, kfe->v2, fedges, visited, ans); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		BLI_assert(kfe->v2->v == v); | 
					
						
							|  |  |  | 		BLI_smallhash_insert(visited, (uintptr_t)(kfe->v2), NULL); | 
					
						
							|  |  |  | 		found = find_chain_search(kcd, kfe->v1, fedges, visited, ans); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_smallhash_release(visited); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (found) | 
					
						
							|  |  |  | 		return ans; | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find a chain in fedges from one instantiated vertex to another.
 | 
					
						
							|  |  |  |  * Remove the edges in the chain from fedges and return a separate list of the chain. */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static ListBase *find_chain(KnifeTool_OpData *kcd, ListBase *fedges) | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	Ref *r, *ref; | 
					
						
							|  |  |  | 	KnifeEdge *kfe; | 
					
						
							|  |  |  | 	BMVert *v1, *v2; | 
					
						
							|  |  |  | 	ListBase *ans; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ans = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (r = fedges->first; r; r = r->next) { | 
					
						
							|  |  |  | 		kfe = r->ref; | 
					
						
							|  |  |  | 		v1 = kfe->v1->v; | 
					
						
							|  |  |  | 		v2 = kfe->v2->v; | 
					
						
							|  |  |  | 		if (v1 && v2) { | 
					
						
							|  |  |  | 			ans = knife_empty_list(kcd); | 
					
						
							|  |  |  | 			knife_append_list(kcd, ans, kfe); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (v1) | 
					
						
							|  |  |  | 			ans = find_chain_from_vertex(kcd, kfe, v1, fedges); | 
					
						
							|  |  |  | 		else if (v2) | 
					
						
							|  |  |  | 			ans = find_chain_from_vertex(kcd, kfe, v2, fedges); | 
					
						
							|  |  |  | 		if (ans) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (ans) { | 
					
						
							|  |  |  | 		BLI_assert(BLI_countlist(ans) > 0); | 
					
						
							|  |  |  | 		for (r = ans->first; r; r = r->next) { | 
					
						
							|  |  |  | 			ref = find_ref(fedges, r->ref); | 
					
						
							|  |  |  | 			BLI_assert(ref != NULL); | 
					
						
							|  |  |  | 			BLI_remlink(fedges, ref); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ans; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* The hole so far goes from kfvfirst to kfv (some may be reversed).
 | 
					
						
							|  |  |  |  * If possible, complete the hole back to kfvfirst and return 1, else return 0. | 
					
						
							|  |  |  |  * The visited hash says which KnifeVert's have already been tried, not including kfv or kfvfirst. */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static int find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges, | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  |                             SmallHash *visited, ListBase *hole) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	Ref *r; | 
					
						
							|  |  |  | 	KnifeEdge *kfe, *kfelast; | 
					
						
							|  |  |  | 	KnifeVert *kfv_other; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (kfv == kfvfirst) | 
					
						
							|  |  |  | 		return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	kfelast = ((Ref *)hole->last)->ref; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	for (r = fedges->first; r; r = r->next) { | 
					
						
							|  |  |  | 		kfe = r->ref; | 
					
						
							|  |  |  | 		if (kfe == kfelast) | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 		if (kfe->v1->v || kfe->v2->v) | 
					
						
							|  |  |  | 			continue; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		kfv_other = NULL; | 
					
						
							|  |  |  | 		if (kfe->v1 == kfv) | 
					
						
							|  |  |  | 			kfv_other = kfe->v2; | 
					
						
							|  |  |  | 		else if (kfe->v2 == kfv) | 
					
						
							|  |  |  | 			kfv_other = kfe->v1; | 
					
						
							|  |  |  | 		if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) { | 
					
						
							|  |  |  | 			knife_append_list(kcd, hole, kfe); | 
					
						
							|  |  |  | 			if (find_hole_search(kcd, kfvfirst, kfv_other, fedges, visited, hole)) | 
					
						
							|  |  |  | 				return TRUE; | 
					
						
							|  |  |  | 			BLI_remlink(hole, hole->last); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Find a hole (simple cycle with no instantiated vertices).
 | 
					
						
							|  |  |  |  * Remove the edges in the cycle from fedges and return a separate list of the cycle */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static ListBase *find_hole(KnifeTool_OpData *kcd, ListBase *fedges) | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	ListBase *ans; | 
					
						
							|  |  |  | 	Ref *r, *ref; | 
					
						
							|  |  |  | 	KnifeEdge *kfe; | 
					
						
							|  |  |  | 	SmallHash visited_, *visited = &visited_; | 
					
						
							|  |  |  | 	int found; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ans = NULL; | 
					
						
							|  |  |  | 	found = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (r = fedges->first; r && !found; r = r->next) { | 
					
						
							|  |  |  | 		kfe = r->ref; | 
					
						
							|  |  |  | 		if (kfe->v1->v || kfe->v2->v || kfe->v1 == kfe->v2) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BLI_smallhash_init(visited); | 
					
						
							|  |  |  | 		ans = knife_empty_list(kcd); | 
					
						
							|  |  |  | 		knife_append_list(kcd, ans, kfe); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		found = find_hole_search(kcd, kfe->v1, kfe->v2, fedges, visited, ans); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BLI_smallhash_release(visited); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (found) { | 
					
						
							|  |  |  | 		for (r = ans->first; r; r = r->next) { | 
					
						
							|  |  |  | 			kfe = r->ref; | 
					
						
							|  |  |  | 			ref = find_ref(fedges, r->ref); | 
					
						
							|  |  |  | 			if (ref) | 
					
						
							|  |  |  | 				BLI_remlink(fedges, ref); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return ans; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Try to find "nice" diagonals - short, and far apart from each other.
 | 
					
						
							|  |  |  |  * If found, return TRUE and make a 'main chain' going across f which uses | 
					
						
							|  |  |  |  * the two diagonals and one part of the hole, and a 'side chain' that | 
					
						
							|  |  |  |  * completes the hole. */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static int find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, ListBase **mainchain, | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  |                             ListBase **sidechain) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	float **fco, **hco; | 
					
						
							|  |  |  | 	BMVert **fv; | 
					
						
							|  |  |  | 	KnifeVert **hv; | 
					
						
							|  |  |  | 	KnifeEdge **he; | 
					
						
							|  |  |  | 	Ref *r; | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 	KnifeVert *kfv, *kfvother; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	KnifeEdge *kfe; | 
					
						
							|  |  |  | 	ListBase *chain; | 
					
						
							|  |  |  | 	BMVert *v; | 
					
						
							|  |  |  | 	BMIter iter; | 
					
						
							| 
									
										
										
										
											2012-06-07 18:21:07 +00:00
										 |  |  | 	int nh, nf, i, j, k, m, ax, ay, ok, sep = 0 /* Quite warnings */, bestsep; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	int besti[2], bestj[2]; | 
					
						
							|  |  |  | 	float d, bestd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	nh = BLI_countlist(hole); | 
					
						
							|  |  |  | 	nf = f->len; | 
					
						
							|  |  |  | 	if (nh < 2 || nf < 3) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Gather 2d projections of hole and face vertex coordinates.
 | 
					
						
							|  |  |  | 	 * Use best-axis projection - not completely accurate, maybe revisit */ | 
					
						
							|  |  |  | 	axis_dominant_v3(&ax, &ay, f->no); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	hco = BLI_memarena_alloc(kcd->arena, nh * sizeof(float *)); | 
					
						
							|  |  |  | 	fco = BLI_memarena_alloc(kcd->arena, nf * sizeof(float *)); | 
					
						
							|  |  |  | 	hv = BLI_memarena_alloc(kcd->arena, nh * sizeof(KnifeVert *)); | 
					
						
							|  |  |  | 	fv = BLI_memarena_alloc(kcd->arena, nf * sizeof(BMVert *)); | 
					
						
							|  |  |  | 	he = BLI_memarena_alloc(kcd->arena, nh * sizeof(KnifeEdge *)); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	i = 0; | 
					
						
							|  |  |  | 	kfv = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 	kfvother = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	for (r = hole->first; r; r = r->next) { | 
					
						
							|  |  |  | 		kfe = r->ref; | 
					
						
							|  |  |  | 		he[i] = kfe; | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 		if (kfvother == NULL) { | 
					
						
							|  |  |  | 			kfv = kfe->v1; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 			kfv = kfvother; | 
					
						
							|  |  |  | 			BLI_assert(kfv == kfe->v1 || kfv == kfe->v2); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		hco[i] = BLI_memarena_alloc(kcd->arena, 2 * sizeof(float)); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		hco[i][0] = kfv->co[ax]; | 
					
						
							|  |  |  | 		hco[i][1] = kfv->co[ay]; | 
					
						
							|  |  |  | 		hv[i] = kfv; | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 		kfvother = (kfe->v1 == kfv) ? kfe->v2 : kfe->v1; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		i++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	j = 0; | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 	BM_ITER_ELEM (v, &iter, f, BM_VERTS_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		fco[j] = BLI_memarena_alloc(kcd->arena, 2 * sizeof(float)); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		fco[j][0] = v->co[ax]; | 
					
						
							|  |  |  | 		fco[j][1] = v->co[ay]; | 
					
						
							|  |  |  | 		fv[j] = v; | 
					
						
							|  |  |  | 		j++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	/* For first diagonal  (m == 0), want shortest length.
 | 
					
						
							|  |  |  | 	 * For second diagonal (m == 1), want max separation of index of hole | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	 * vertex from the hole vertex used in the first diagonal, and from there | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 	 * want the one with shortest length not to the same vertex as the first diagonal. */ | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	for (m = 0; m < 2; m++) { | 
					
						
							|  |  |  | 		besti[m] = -1; | 
					
						
							|  |  |  | 		bestj[m] = -1; | 
					
						
							|  |  |  | 		bestd = FLT_MAX; | 
					
						
							|  |  |  | 		bestsep = 0; | 
					
						
							|  |  |  | 		for (i = 0; i < nh; i++) { | 
					
						
							|  |  |  | 			if (m == 1) { | 
					
						
							|  |  |  | 				if (i == besti[0]) | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				sep = (i + nh - besti[0]) % nh; | 
					
						
							|  |  |  | 				sep = MIN2(sep, nh - sep); | 
					
						
							|  |  |  | 				if (sep < bestsep) | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				bestd = FLT_MAX; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for (j = 0; j < nf; j++) { | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 				if (m == 1 && j == bestj[0]) | 
					
						
							|  |  |  | 					continue; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 				d = len_squared_v2v2(hco[i], fco[j]); | 
					
						
							|  |  |  | 				if (d > bestd) | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				ok = TRUE; | 
					
						
							|  |  |  | 				for (k = 0; k < nh && ok; k++) { | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 					if (k == i || (k + 1) % nh == i) | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 						continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 					if (isect_line_line_v2(hco[i], fco[j], hco[k], hco[(k + 1) % nh])) | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 						ok = FALSE; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (!ok) | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				for (k = 0; k < nf && ok; k++) { | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 					if (k == j || (k + 1) % nf == j) | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 						continue; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 					if (isect_line_line_v2(hco[i], fco[j], fco[k], fco[(k + 1) % nf])) | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 						ok = FALSE; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (ok) { | 
					
						
							|  |  |  | 					besti[m] = i; | 
					
						
							|  |  |  | 					bestj[m] = j; | 
					
						
							|  |  |  | 					if (m == 1) | 
					
						
							|  |  |  | 						bestsep = sep; | 
					
						
							|  |  |  | 					bestd = d; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (besti[0] != -1 && besti[1] != -1) { | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 		BLI_assert(besti[0] != besti[1] && bestj[0] != bestj[1]); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		kfe = new_knife_edge(kcd); | 
					
						
							|  |  |  | 		kfe->v1 = get_bm_knife_vert(kcd, fv[bestj[0]]); | 
					
						
							|  |  |  | 		kfe->v2 = hv[besti[0]]; | 
					
						
							|  |  |  | 		chain = knife_empty_list(kcd); | 
					
						
							|  |  |  | 		knife_append_list(kcd, chain, kfe); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		for (i = besti[0]; i != besti[1]; i = (i + 1) % nh) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 			knife_append_list(kcd, chain, he[i]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		kfe = new_knife_edge(kcd); | 
					
						
							|  |  |  | 		kfe->v1 = hv[besti[1]]; | 
					
						
							|  |  |  | 		kfe->v2 = get_bm_knife_vert(kcd, fv[bestj[1]]); | 
					
						
							|  |  |  | 		knife_append_list(kcd, chain, kfe); | 
					
						
							|  |  |  | 		*mainchain = chain; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		chain = knife_empty_list(kcd); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		for (i = besti[1]; i != besti[0]; i = (i + 1) % nh) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 			knife_append_list(kcd, chain, he[i]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*sidechain = chain; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return TRUE; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		return FALSE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static int knife_edge_in_face(KnifeTool_OpData *UNUSED(kcd), KnifeEdge *kfe, BMFace *f) | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-19 14:38:09 +00:00
										 |  |  | 	/* BMesh *bm = kcd->em->bm; */ /* UNUSED */ | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	BMVert *v1, *v2; | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 	BMLoop *l1, *l2, *l; | 
					
						
							|  |  |  | 	float mid[3]; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 	int v1inside, v2inside; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 	if (!f) | 
					
						
							|  |  |  | 		return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	v1 = kfe->v1->v; | 
					
						
							|  |  |  | 	v2 = kfe->v2->v; | 
					
						
							|  |  |  | 	l1 = NULL; | 
					
						
							|  |  |  | 	l2 = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* find out if v1 and v2, if set, are part of the face */ | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 	BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		if (v1 && l->v == v1) | 
					
						
							|  |  |  | 			l1 = l; | 
					
						
							|  |  |  | 		if (v2 && l->v == v2) | 
					
						
							|  |  |  | 			l2 = l; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* BM_face_point_inside_test uses best-axis projection so this isn't most accurate test... */ | 
					
						
							| 
									
										
										
										
											2012-04-19 14:38:09 +00:00
										 |  |  | 	v1inside = l1 ? 0 : BM_face_point_inside_test(f, kfe->v1->co); | 
					
						
							|  |  |  | 	v2inside = l2 ? 0 : BM_face_point_inside_test(f, kfe->v2->co); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	if ((l1 && v2inside) || (l2 && v1inside) || (v1inside && v2inside)) | 
					
						
							|  |  |  | 		return TRUE; | 
					
						
							|  |  |  | 	if (l1 && l2) { | 
					
						
							|  |  |  | 		/* Can have case where v1 and v2 are on shared chain between two faces.
 | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 		 * BM_face_legal_splits does visibility and self-intersection tests, | 
					
						
							|  |  |  | 		 * but it is expensive and maybe a bit buggy, so use a simple | 
					
						
							|  |  |  | 		 * "is the midpoint in the face" test */ | 
					
						
							|  |  |  | 		mid_v3_v3v3(mid, kfe->v1->co, kfe->v2->co); | 
					
						
							| 
									
										
										
										
											2012-04-19 14:38:09 +00:00
										 |  |  | 		return BM_face_point_inside_test(f, mid); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Split face f with KnifeEdges on chain.  f remains as one side, the face formed is put in *newface.
 | 
					
						
							|  |  |  |  * The new face will be on the left side of the chain as viewed from the normal-out side of f. */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *chain, BMFace **newface) | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	BMesh *bm = kcd->em->bm; | 
					
						
							|  |  |  | 	KnifeEdge *kfe, *kfelast; | 
					
						
							|  |  |  | 	BMVert *v1, *v2; | 
					
						
							|  |  |  | 	BMFace *fnew; | 
					
						
							|  |  |  | 	Ref *ref; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	KnifeVert *kfv, *kfvprev; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	BMLoop *lnew, *l_iter; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 	int nco = BLI_countlist(chain) - 1; | 
					
						
							|  |  |  | 	float (*cos)[3] = NULL; | 
					
						
							|  |  |  | 	KnifeVert **kverts; | 
					
						
							|  |  |  | 	BLI_array_fixedstack_declare(cos, BM_NGON_STACK_SIZE, nco, __func__); | 
					
						
							|  |  |  | 	BLI_array_fixedstack_declare(kverts, BM_NGON_STACK_SIZE, nco, __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	kfe = ((Ref *)chain->first)->ref; | 
					
						
							|  |  |  | 	v1 = kfe->v1->v ? kfe->v1->v : kfe->v2->v; | 
					
						
							|  |  |  | 	kfelast = ((Ref *)chain->last)->ref; | 
					
						
							|  |  |  | 	v2 = kfelast->v2->v ? kfelast->v2->v : kfelast->v1->v; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	BLI_assert(v1 != NULL && v2 != NULL); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	kfvprev = kfe->v1->v == v1 ? kfe->v1 : kfe->v2; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	for (ref = chain->first, i = 0; i < nco && ref != chain->last; ref = ref->next, i++) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		kfe = ref->ref; | 
					
						
							|  |  |  | 		BLI_assert(kfvprev == kfe->v1 || kfvprev == kfe->v2); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		kfv = kfe->v1 == kfvprev ? kfe->v2 : kfe->v1; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		copy_v3_v3(cos[i], kfv->co); | 
					
						
							|  |  |  | 		kverts[i] = kfv; | 
					
						
							|  |  |  | 		kfvprev = kfv; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	BLI_assert(i == nco); | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 	lnew = NULL; | 
					
						
							|  |  |  | 	if (nco == 0) { | 
					
						
							| 
									
										
										
										
											2012-04-09 12:50:43 +00:00
										 |  |  | 		/* Want to prevent creating two-sided polygons */ | 
					
						
							|  |  |  | 		if (BM_edge_exists(v1, v2)) { | 
					
						
							|  |  |  | 			*newface = NULL; | 
					
						
							| 
									
										
										
										
											2012-04-20 11:14:16 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2012-04-09 12:50:43 +00:00
										 |  |  | 			*newface = BM_face_split(bm, f, v1, v2, &lnew, NULL, TRUE); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 		fnew = BM_face_split_n(bm, f, v1, v2, cos, nco, &lnew, NULL); | 
					
						
							|  |  |  | 		*newface = fnew; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (fnew) { | 
					
						
							|  |  |  | 			/* Now go through lnew chain matching up chain kv's and assign real v's to them */ | 
					
						
							|  |  |  | 			for (l_iter = lnew->next, i = 0; i < nco; l_iter = l_iter->next, i++) { | 
					
						
							|  |  |  | 				BLI_assert(equals_v3v3(cos[i], l_iter->v->co)); | 
					
						
							| 
									
										
										
										
											2012-04-20 11:14:16 +00:00
										 |  |  | 				if (kcd->select_result) { | 
					
						
							|  |  |  | 					BM_edge_select_set(bm, l_iter->e, TRUE); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 				kverts[i]->v = l_iter->v; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 11:14:16 +00:00
										 |  |  | 	/* the select chain above doesnt account for the first loop */ | 
					
						
							|  |  |  | 	if (kcd->select_result) { | 
					
						
							|  |  |  | 		if (lnew) { | 
					
						
							|  |  |  | 			BM_edge_select_set(bm, lnew->e, TRUE); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	BLI_array_fixedstack_free(cos); | 
					
						
							|  |  |  | 	BLI_array_fixedstack_free(kverts); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_make_face_cuts(KnifeTool_OpData *kcd, BMFace *f, ListBase *kfedges) | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	BMesh *bm = kcd->em->bm; | 
					
						
							|  |  |  | 	KnifeEdge *kfe; | 
					
						
							|  |  |  | 	BMFace *fnew, *fnew2, *fhole; | 
					
						
							|  |  |  | 	ListBase *chain, *hole, *sidechain; | 
					
						
							|  |  |  | 	ListBase *fnew_kfedges, *fnew2_kfedges; | 
					
						
							|  |  |  | 	Ref *ref, *refnext; | 
					
						
							|  |  |  | 	int count, oldcount; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	oldcount = BLI_countlist(kfedges); | 
					
						
							|  |  |  | 	while ((chain = find_chain(kcd, kfedges)) != NULL) { | 
					
						
							|  |  |  | 		knife_make_chain_cut(kcd, f, chain, &fnew); | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 		if (!fnew) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* Move kfedges to fnew_kfedges if they are now in fnew.
 | 
					
						
							|  |  |  | 		 * The chain edges were removed already */ | 
					
						
							|  |  |  | 		fnew_kfedges = knife_empty_list(kcd); | 
					
						
							|  |  |  | 		for (ref = kfedges->first; ref; ref = refnext) { | 
					
						
							|  |  |  | 			kfe = ref->ref; | 
					
						
							|  |  |  | 			refnext = ref->next; | 
					
						
							|  |  |  | 			if (knife_edge_in_face(kcd, kfe, fnew)) { | 
					
						
							|  |  |  | 				BLI_remlink(kfedges, ref); | 
					
						
							|  |  |  | 				kfe->basef = fnew; | 
					
						
							|  |  |  | 				knife_append_list(kcd, fnew_kfedges, kfe); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (fnew_kfedges->first) | 
					
						
							|  |  |  | 			knife_make_face_cuts(kcd, fnew, fnew_kfedges); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* find_chain should always remove edges if it returns TRUE,
 | 
					
						
							|  |  |  | 		 * but guard against infinite loop anyway */ | 
					
						
							|  |  |  | 		count = BLI_countlist(kfedges); | 
					
						
							|  |  |  | 		if (count >= oldcount) { | 
					
						
							|  |  |  | 			BLI_assert(!"knife find_chain infinite loop"); | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		oldcount = count; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while ((hole = find_hole(kcd, kfedges)) != NULL) { | 
					
						
							|  |  |  | 		if (find_hole_chains(kcd, hole, f, &chain, &sidechain)) { | 
					
						
							|  |  |  | 			/* chain goes across f and sidechain comes back
 | 
					
						
							|  |  |  | 			 * from the second last vertex to the second vertex. | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 			knife_make_chain_cut(kcd, f, chain, &fnew); | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 			if (!fnew) { | 
					
						
							|  |  |  | 				BLI_assert(!"knife failed hole cut"); | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 			kfe = ((Ref *)sidechain->first)->ref; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 			if (knife_edge_in_face(kcd, kfe, f)) { | 
					
						
							|  |  |  | 				knife_make_chain_cut(kcd, f, sidechain, &fnew2); | 
					
						
							|  |  |  | 				fhole = f; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else if (knife_edge_in_face(kcd, kfe, fnew)) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 				knife_make_chain_cut(kcd, fnew, sidechain, &fnew2); | 
					
						
							|  |  |  | 				fhole = fnew2; | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-03-12 11:27:59 +00:00
										 |  |  | 				/* shouldn't happen except in funny edge cases */ | 
					
						
							|  |  |  | 				return; | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			BM_face_kill(bm, fhole); | 
					
						
							|  |  |  | 			/* Move kfedges to either fnew or fnew2 if appropriate.
 | 
					
						
							|  |  |  | 			 * The hole edges were removed already */ | 
					
						
							|  |  |  | 			fnew_kfedges = knife_empty_list(kcd); | 
					
						
							|  |  |  | 			fnew2_kfedges = knife_empty_list(kcd); | 
					
						
							|  |  |  | 			for (ref = kfedges->first; ref; ref = refnext) { | 
					
						
							|  |  |  | 				kfe = ref->ref; | 
					
						
							|  |  |  | 				refnext = ref->next; | 
					
						
							|  |  |  | 				if (knife_edge_in_face(kcd, kfe, fnew)) { | 
					
						
							|  |  |  | 					BLI_remlink(kfedges, ref); | 
					
						
							|  |  |  | 					kfe->basef = fnew; | 
					
						
							|  |  |  | 					knife_append_list(kcd, fnew_kfedges, kfe); | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else if (knife_edge_in_face(kcd, kfe, fnew2)) { | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 					BLI_remlink(kfedges, ref); | 
					
						
							|  |  |  | 					kfe->basef = fnew2; | 
					
						
							|  |  |  | 					knife_append_list(kcd, fnew2_kfedges, kfe); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			/* We'll skip knife edges that are in the newly formed hole.
 | 
					
						
							|  |  |  | 			 * (Maybe we shouldn't have made a hole in the first place?) */ | 
					
						
							|  |  |  | 			if (fnew != fhole && fnew_kfedges->first) | 
					
						
							|  |  |  | 				knife_make_face_cuts(kcd, fnew, fnew_kfedges); | 
					
						
							|  |  |  | 			if (fnew2 != fhole && fnew2_kfedges->first) | 
					
						
							|  |  |  | 				knife_make_face_cuts(kcd, fnew2, fnew2_kfedges); | 
					
						
							|  |  |  | 			if (f == fhole) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			/* find_hole should always remove edges if it returns TRUE,
 | 
					
						
							|  |  |  | 			 * but guard against infinite loop anyway */ | 
					
						
							|  |  |  | 			count = BLI_countlist(kfedges); | 
					
						
							|  |  |  | 			if (count >= oldcount) { | 
					
						
							|  |  |  | 				BLI_assert(!"knife find_hole infinite loop"); | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			oldcount = count; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Use the network of KnifeEdges and KnifeVerts accumulated to make real BMVerts and BMEdedges */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_make_cuts(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	BMesh *bm = kcd->em->bm; | 
					
						
							|  |  |  | 	KnifeEdge *kfe; | 
					
						
							|  |  |  | 	KnifeVert *kfv; | 
					
						
							|  |  |  | 	BMFace *f; | 
					
						
							|  |  |  | 	BMEdge *e, *enew; | 
					
						
							|  |  |  | 	ListBase *lst; | 
					
						
							|  |  |  | 	Ref *ref; | 
					
						
							|  |  |  | 	float pct; | 
					
						
							|  |  |  | 	SmallHashIter hiter; | 
					
						
							|  |  |  | 	BLI_mempool_iter iter; | 
					
						
							|  |  |  | 	SmallHash fhash_, *fhash = &fhash_; | 
					
						
							|  |  |  | 	SmallHash ehash_, *ehash = &ehash_; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_smallhash_init(fhash); | 
					
						
							|  |  |  | 	BLI_smallhash_init(ehash); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* put list of cutting edges for a face into fhash, keyed by face */ | 
					
						
							|  |  |  | 	BLI_mempool_iternew(kcd->kedges, &iter); | 
					
						
							|  |  |  | 	for (kfe = BLI_mempool_iterstep(&iter); kfe; kfe = BLI_mempool_iterstep(&iter)) { | 
					
						
							|  |  |  | 		f = kfe->basef; | 
					
						
							|  |  |  | 		if (!f || kfe->e) | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		lst = BLI_smallhash_lookup(fhash, (uintptr_t)f); | 
					
						
							|  |  |  | 		if (!lst) { | 
					
						
							|  |  |  | 			lst = knife_empty_list(kcd); | 
					
						
							|  |  |  | 			BLI_smallhash_insert(fhash, (uintptr_t)f, lst); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		knife_append_list(kcd, lst, kfe); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* put list of splitting vertices for an edge into ehash, keyed by edge */ | 
					
						
							|  |  |  | 	BLI_mempool_iternew(kcd->kverts, &iter); | 
					
						
							|  |  |  | 	for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) { | 
					
						
							|  |  |  | 		if (kfv->v) | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			continue;  /* already have a BMVert */ | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		for (ref = kfv->edges.first; ref; ref = ref->next) { | 
					
						
							|  |  |  | 			kfe = ref->ref; | 
					
						
							|  |  |  | 			e = kfe->e; | 
					
						
							|  |  |  | 			if (!e) | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			lst = BLI_smallhash_lookup(ehash, (uintptr_t)e); | 
					
						
							|  |  |  | 			if (!lst) { | 
					
						
							|  |  |  | 				lst = knife_empty_list(kcd); | 
					
						
							|  |  |  | 				BLI_smallhash_insert(ehash, (uintptr_t)e, lst); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			/* there can be more than one kfe in kfv's list with same e */ | 
					
						
							|  |  |  | 			if (!find_ref(lst, kfv)) | 
					
						
							|  |  |  | 				knife_append_list(kcd, lst, kfv); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* split bmesh edges where needed */ | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	for (lst = BLI_smallhash_iternew(ehash, &hiter, (uintptr_t *)&e); lst; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	     lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&e)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		sort_by_frac_along(lst, e); | 
					
						
							|  |  |  | 		for (ref = lst->first; ref; ref = ref->next) { | 
					
						
							|  |  |  | 			kfv = ref->ref; | 
					
						
							|  |  |  | 			pct = frac_along(e->v1->co, e->v2->co, kfv->co); | 
					
						
							|  |  |  | 			kfv->v = BM_edge_split(bm, e, e->v1, &enew, pct); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 	if (kcd->only_select) { | 
					
						
							| 
									
										
										
										
											2012-04-20 11:14:16 +00:00
										 |  |  | 		EDBM_flag_disable_all(kcd->em, BM_ELEM_SELECT); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 	/* do cuts for each face */ | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | 	for (lst = BLI_smallhash_iternew(fhash, &hiter, (uintptr_t *)&f); lst; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	     lst = BLI_smallhash_iternext(&hiter, (uintptr_t *)&f)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | 		knife_make_face_cuts(kcd, f, lst); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_smallhash_release(fhash); | 
					
						
							|  |  |  | 	BLI_smallhash_release(ehash); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* called on tool confirmation */ | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | static void knifetool_finish(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	KnifeTool_OpData *kcd = op->customdata; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | #if SCANFILL_CUTS
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	knifenet_fill_faces(kcd); | 
					
						
							| 
									
										
										
										
											2012-03-07 14:44:43 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 	knife_make_cuts(kcd); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-03 16:35:51 +00:00
										 |  |  | 	EDBM_mesh_normals_update(kcd->em); | 
					
						
							| 
									
										
										
										
											2012-03-27 00:01:35 +00:00
										 |  |  | 	EDBM_update_generic(C, kcd->em, TRUE); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | /* copied from paint_image.c */ | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | static int project_knife_view_clip(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	int orth = ED_view3d_clip_range_get(v3d, rv3d, clipsta, clipend); | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (orth) { /* only needed for ortho */ | 
					
						
							|  |  |  | 		float fac = 2.0f / ((*clipend) - (*clipsta)); | 
					
						
							|  |  |  | 		*clipsta *= fac; | 
					
						
							|  |  |  | 		*clipend *= fac; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return orth; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knife_recalc_projmat(KnifeTool_OpData *kcd) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	invert_m4_m4(kcd->ob->imat, kcd->ob->obmat); | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat); | 
					
						
							| 
									
										
										
										
											2011-12-16 23:50:55 +00:00
										 |  |  | 	//mult_m4_m4m4(kcd->projmat, kcd->vc.rv3d->winmat, kcd->vc.rv3d->viewmat);
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-18 21:38:02 +00:00
										 |  |  | 	kcd->is_ortho = project_knife_view_clip(kcd->vc.v3d, kcd->vc.rv3d,  | 
					
						
							|  |  |  | 	                                        &kcd->clipsta, &kcd->clipend); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called when modal loop selection is done... */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knifetool_exit(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	KnifeTool_OpData *kcd = op->customdata; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	if (!kcd) | 
					
						
							|  |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	WM_cursor_restore(CTX_wm_window(C)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* deactivate the extra drawing stuff in 3D-View */ | 
					
						
							|  |  |  | 	ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* free the custom data */ | 
					
						
							|  |  |  | 	BLI_mempool_destroy(kcd->refs); | 
					
						
							|  |  |  | 	BLI_mempool_destroy(kcd->kverts); | 
					
						
							|  |  |  | 	BLI_mempool_destroy(kcd->kedges); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BLI_ghash_free(kcd->origedgemap, NULL, NULL); | 
					
						
							|  |  |  | 	BLI_ghash_free(kcd->origvertmap, NULL, NULL); | 
					
						
							|  |  |  | 	BLI_ghash_free(kcd->kedgefacemap, NULL, NULL); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	BMBVH_FreeBVH(kcd->bmbvh); | 
					
						
							|  |  |  | 	BLI_memarena_free(kcd->arena); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* tag for redraw */ | 
					
						
							|  |  |  | 	ED_region_tag_redraw(kcd->ar); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-18 12:54:23 +00:00
										 |  |  | 	if (kcd->cagecos) | 
					
						
							|  |  |  | 		MEM_freeN(kcd->cagecos); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-26 04:41:27 +00:00
										 |  |  | 	if (kcd->linehits) | 
					
						
							|  |  |  | 		MEM_freeN(kcd->linehits); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* destroy kcd itself */ | 
					
						
							|  |  |  | 	MEM_freeN(kcd); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	op->customdata = NULL; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-09 07:06:06 +00:00
										 |  |  | static void cage_mapped_verts_callback(void *userData, int index, const float co[3], | 
					
						
							|  |  |  |                                        const float UNUSED(no_f[3]), const short UNUSED(no_s[3])) | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	void **data = userData; | 
					
						
							|  |  |  | 	BMEditMesh *em = data[0]; | 
					
						
							|  |  |  | 	float (*cagecos)[3] = data[1]; | 
					
						
							|  |  |  | 	SmallHash *hash = data[2]; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	if (index >= 0 && index < em->bm->totvert && !BLI_smallhash_haskey(hash, index)) { | 
					
						
							|  |  |  | 		BLI_smallhash_insert(hash, index, NULL); | 
					
						
							|  |  |  | 		copy_v3_v3(cagecos[index], co); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval[2]) | 
					
						
							| 
									
										
										
										
											2012-04-18 16:55:15 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	knife_recalc_projmat(kcd); | 
					
						
							|  |  |  | 	kcd->vc.mval[0] = mval[0]; | 
					
						
							|  |  |  | 	kcd->vc.mval[1] = mval[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (knife_update_active(kcd)) { | 
					
						
							|  |  |  | 		ED_region_tag_redraw(kcd->ar); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | /* called when modal loop selection gets set up... */ | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut)) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	KnifeTool_OpData *kcd; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 	Object *obedit = CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	DerivedMesh *cage, *final; | 
					
						
							|  |  |  | 	SmallHash shash; | 
					
						
							|  |  |  | 	void *data[3]; | 
					
						
							| 
									
										
										
										
											2012-05-06 12:13:45 +00:00
										 |  |  | 	const short only_select = RNA_boolean_get(op->ptr, "only_selected"); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* alloc new customdata */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), "knifetool Modal Op Data"); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* assign the drawing handle for drawing preview line... */ | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	kcd->ob = obedit; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	kcd->ar = CTX_wm_region(C); | 
					
						
							|  |  |  | 	kcd->draw_handle = ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	em_setup_viewcontext(C, &kcd->vc); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-02 12:09:49 +00:00
										 |  |  | 	kcd->em = BMEdit_FromObject(kcd->ob); | 
					
						
							| 
									
										
										
										
											2011-11-16 12:38:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-12 10:51:45 +00:00
										 |  |  | 	BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cage = editbmesh_get_derived_cage_and_final(scene, obedit, kcd->em, &final, CD_MASK_DERIVEDMESH); | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	kcd->cagecos = MEM_callocN(sizeof(float) * 3 * kcd->em->bm->totvert, "knife cagecos"); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	data[0] = kcd->em; | 
					
						
							|  |  |  | 	data[1] = kcd->cagecos; | 
					
						
							|  |  |  | 	data[2] = &shash; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 	BLI_smallhash_init(&shash); | 
					
						
							|  |  |  | 	cage->foreachMappedVert(cage, cage_mapped_verts_callback, data); | 
					
						
							|  |  |  | 	BLI_smallhash_release(&shash); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 	kcd->bmbvh = BMBVH_NewBVH(kcd->em, | 
					
						
							|  |  |  | 	                          (BMBVH_USE_CAGE | BMBVH_RETURN_ORIG) | | 
					
						
							|  |  |  | 	                          (only_select ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN), | 
					
						
							|  |  |  | 	                          scene, obedit); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	kcd->arena = BLI_memarena_new(1 << 15, "knife"); | 
					
						
							|  |  |  | 	kcd->vthresh = KMAXDIST - 1; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	kcd->ethresh = KMAXDIST; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 20:43:05 +00:00
										 |  |  | 	kcd->extend = 1; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	knife_recalc_projmat(kcd); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	ED_region_tag_redraw(kcd->ar); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-01 22:59:18 +00:00
										 |  |  | 	kcd->refs = BLI_mempool_create(sizeof(Ref), 1, 2048, 0); | 
					
						
							|  |  |  | 	kcd->kverts = BLI_mempool_create(sizeof(KnifeVert), 1, 512, BLI_MEMPOOL_ALLOW_ITER); | 
					
						
							|  |  |  | 	kcd->kedges = BLI_mempool_create(sizeof(KnifeEdge), 1, 512, BLI_MEMPOOL_ALLOW_ITER); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-16 00:51:36 +00:00
										 |  |  | 	kcd->origedgemap = BLI_ghash_ptr_new("knife origedgemap"); | 
					
						
							|  |  |  | 	kcd->origvertmap = BLI_ghash_ptr_new("knife origvertmap"); | 
					
						
							|  |  |  | 	kcd->kedgefacemap = BLI_ghash_ptr_new("knife origvertmap"); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 	/* cut all the way through the mesh if use_occlude_geometry button not pushed */ | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | 	kcd->cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry"); | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 	kcd->only_select = only_select; | 
					
						
							| 
									
										
										
										
											2011-12-29 13:43:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 11:14:16 +00:00
										 |  |  | 	/* can't usefully select resulting edges in face mode */ | 
					
						
							|  |  |  | 	kcd->select_result = (kcd->em->selectmode != SCE_SELECT_FACE); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-03 02:41:12 +00:00
										 |  |  | 	knife_pos_data_clear(&kcd->curr); | 
					
						
							| 
									
										
										
										
											2012-03-12 12:45:55 +00:00
										 |  |  | 	knife_pos_data_clear(&kcd->prev); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 12:05:08 +00:00
										 |  |  | 	knife_init_colors(&kcd->colors); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | static int knifetool_cancel(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* this is just a wrapper around exit() */ | 
					
						
							|  |  |  | 	knifetool_exit(C, op); | 
					
						
							|  |  |  | 	return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | static int knifetool_invoke(bContext *C, wmOperator *op, wmEvent *evt) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	KnifeTool_OpData *kcd; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	view3d_operator_needs_opengl(C); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!knifetool_init(C, op, 0)) | 
					
						
							|  |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* add a modal handler for this operator - handles loop selection */ | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	WM_cursor_modal(CTX_wm_window(C), BC_KNIFECURSOR); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	WM_event_add_modal_handler(C, op); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	kcd = op->customdata; | 
					
						
							| 
									
										
										
										
											2012-04-18 16:55:15 +00:00
										 |  |  | 	knifetool_update_mval(kcd, evt->mval); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 	knife_update_header(C, kcd); | 
					
						
							| 
									
										
										
										
											2012-03-23 14:52:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	return OPERATOR_RUNNING_MODAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | enum { | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	KNF_MODAL_CANCEL = 1, | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 	KNF_MODAL_CONFIRM, | 
					
						
							|  |  |  | 	KNF_MODAL_MIDPOINT_ON, | 
					
						
							|  |  |  | 	KNF_MODAL_MIDPOINT_OFF, | 
					
						
							|  |  |  | 	KNF_MODAL_NEW_CUT, | 
					
						
							|  |  |  | 	KNF_MODEL_IGNORE_SNAP_ON, | 
					
						
							|  |  |  | 	KNF_MODEL_IGNORE_SNAP_OFF, | 
					
						
							|  |  |  | 	KNF_MODAL_ADD_CUT, | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | 	KNF_MODAL_ANGLE_SNAP_TOGGLE, | 
					
						
							|  |  |  | 	KNF_MODAL_CUT_THROUGH_TOGGLE | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-07 15:10:21 +00:00
										 |  |  | wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf) | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	static EnumPropertyItem modal_items[] = { | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		{KNF_MODAL_CANCEL, "CANCEL", 0, "Cancel", ""}, | 
					
						
							|  |  |  | 		{KNF_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, | 
					
						
							|  |  |  | 		{KNF_MODAL_MIDPOINT_ON, "SNAP_MIDPOINTS_ON", 0, "Snap To Midpoints On", ""}, | 
					
						
							|  |  |  | 		{KNF_MODAL_MIDPOINT_OFF, "SNAP_MIDPOINTS_OFF", 0, "Snap To Midpoints Off", ""}, | 
					
						
							|  |  |  | 		{KNF_MODEL_IGNORE_SNAP_ON, "IGNORE_SNAP_ON", 0, "Ignore Snapping On", ""}, | 
					
						
							|  |  |  | 		{KNF_MODEL_IGNORE_SNAP_OFF, "IGNORE_SNAP_OFF", 0, "Ignore Snapping Off", ""}, | 
					
						
							|  |  |  | 		{KNF_MODAL_ANGLE_SNAP_TOGGLE, "ANGLE_SNAP_TOGGLE", 0, "Toggle Angle Snapping", ""}, | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | 		{KNF_MODAL_CUT_THROUGH_TOGGLE, "CUT_THROUGH_TOGGLE", 0, "Toggle Cut Through", ""}, | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		{KNF_MODAL_NEW_CUT, "NEW_CUT", 0, "End Current Cut", ""}, | 
					
						
							|  |  |  | 		{KNF_MODAL_ADD_CUT, "ADD_CUT", 0, "Add Cut", ""}, | 
					
						
							| 
									
										
										
										
											2012-07-29 00:20:28 +00:00
										 |  |  | 		{0, NULL, 0, NULL, NULL} | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "Knife Tool Modal Map"); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 	/* this function is called for each spacetype, only needs to add map once */ | 
					
						
							| 
									
										
										
										
											2012-04-17 15:40:04 +00:00
										 |  |  | 	if (keymap && keymap->modal_items) | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	keymap = WM_modalkeymap_add(keyconf, "Knife Tool Modal Map", modal_items); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 	/* items for modal map */ | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CANCEL); | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 	WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_ADD_CUT); | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | 	WM_modalkeymap_add_item(keymap, RIGHTMOUSE, KM_PRESS, KM_ANY, 0, KNF_MODAL_CANCEL); | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 	WM_modalkeymap_add_item(keymap, RETKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM); | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, PADENTER, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM); | 
					
						
							| 
									
										
										
										
											2012-04-23 11:19:39 +00:00
										 |  |  | 	WM_modalkeymap_add_item(keymap, SPACEKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_CONFIRM); | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 	WM_modalkeymap_add_item(keymap, EKEY, KM_PRESS, 0, 0, KNF_MODAL_NEW_CUT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_MIDPOINT_ON); | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, KNF_MODAL_MIDPOINT_OFF); | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_PRESS, KM_ANY, 0, KNF_MODAL_MIDPOINT_ON); | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, RIGHTCTRLKEY, KM_RELEASE, KM_ANY, 0, KNF_MODAL_MIDPOINT_OFF); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, KNF_MODEL_IGNORE_SNAP_ON); | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, KNF_MODEL_IGNORE_SNAP_OFF); | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_PRESS, KM_ANY, 0, KNF_MODEL_IGNORE_SNAP_ON); | 
					
						
							|  |  |  | 	WM_modalkeymap_add_item(keymap, RIGHTSHIFTKEY, KM_RELEASE, KM_ANY, 0, KNF_MODEL_IGNORE_SNAP_OFF); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 	WM_modalkeymap_add_item(keymap, CKEY, KM_PRESS, 0, 0, KNF_MODAL_ANGLE_SNAP_TOGGLE); | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | 	WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, 0, 0, KNF_MODAL_CUT_THROUGH_TOGGLE); | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 	WM_modalkeymap_assign(keymap, "MESH_OT_knife_tool"); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 	return keymap; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-10-05 04:43:46 +00:00
										 |  |  | 	Object *obedit = CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2012-04-20 12:19:09 +00:00
										 |  |  | 	KnifeTool_OpData *kcd = op->customdata; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-02 12:09:49 +00:00
										 |  |  | 	if (!obedit || obedit->type != OB_MESH || BMEdit_FromObject(obedit) != kcd->em) { | 
					
						
							| 
									
										
										
										
											2011-05-12 18:46:21 +00:00
										 |  |  | 		knifetool_exit(C, op); | 
					
						
							| 
									
										
										
										
											2012-03-23 14:52:00 +00:00
										 |  |  | 		ED_area_headerprint(CTX_wm_area(C), NULL); | 
					
						
							| 
									
										
										
										
											2011-02-23 08:12:27 +00:00
										 |  |  | 		return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2011-05-12 18:46:21 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-02-23 08:12:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	view3d_operator_needs_opengl(C); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	if (kcd->mode == MODE_PANNING) | 
					
						
							|  |  |  | 		kcd->mode = kcd->prevmode; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 	/* handle modal keymap */ | 
					
						
							|  |  |  | 	if (event->type == EVT_MODAL_MAP) { | 
					
						
							|  |  |  | 		switch (event->val) { | 
					
						
							|  |  |  | 			case KNF_MODAL_CANCEL: | 
					
						
							|  |  |  | 				/* finish */ | 
					
						
							|  |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				knifetool_exit(C, op); | 
					
						
							| 
									
										
										
										
											2012-03-23 14:52:00 +00:00
										 |  |  | 				ED_area_headerprint(CTX_wm_area(C), NULL); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 			case KNF_MODAL_CONFIRM: | 
					
						
							|  |  |  | 				/* finish */ | 
					
						
							|  |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				knifetool_finish(C, op); | 
					
						
							|  |  |  | 				knifetool_exit(C, op); | 
					
						
							| 
									
										
										
										
											2012-03-23 14:52:00 +00:00
										 |  |  | 				ED_area_headerprint(CTX_wm_area(C), NULL); | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				return OPERATOR_FINISHED; | 
					
						
							|  |  |  | 			case KNF_MODAL_MIDPOINT_ON: | 
					
						
							|  |  |  | 				kcd->snap_midpoints = 1; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				knife_recalc_projmat(kcd); | 
					
						
							|  |  |  | 				knife_update_active(kcd); | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 				knife_update_header(C, kcd); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 			case KNF_MODAL_MIDPOINT_OFF: | 
					
						
							|  |  |  | 				kcd->snap_midpoints = 0; | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				knife_recalc_projmat(kcd); | 
					
						
							|  |  |  | 				knife_update_active(kcd); | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 				knife_update_header(C, kcd); | 
					
						
							| 
									
										
										
										
											2011-08-30 01:59:33 +00:00
										 |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			case KNF_MODEL_IGNORE_SNAP_ON: | 
					
						
							|  |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							|  |  |  | 				kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 1; | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 				knife_update_header(C, kcd); | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			case KNF_MODEL_IGNORE_SNAP_OFF: | 
					
						
							|  |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							|  |  |  | 				kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 0; | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 				knife_update_header(C, kcd); | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 			case KNF_MODAL_ANGLE_SNAP_TOGGLE: | 
					
						
							|  |  |  | 				kcd->angle_snapping = !kcd->angle_snapping; | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 				knife_update_header(C, kcd); | 
					
						
							| 
									
										
										
										
											2012-01-04 13:43:40 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | 			case KNF_MODAL_CUT_THROUGH_TOGGLE: | 
					
						
							|  |  |  | 				kcd->cut_through = !kcd->cut_through; | 
					
						
							| 
									
										
										
										
											2012-10-06 03:34:52 +00:00
										 |  |  | 				knifetool_update_mval(kcd, event->mval);  /* refresh knife path */ | 
					
						
							| 
									
										
										
										
											2012-04-18 19:59:27 +00:00
										 |  |  | 				knife_update_header(C, kcd); | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 			case KNF_MODAL_NEW_CUT: | 
					
						
							|  |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							| 
									
										
										
										
											2011-05-09 20:43:05 +00:00
										 |  |  | 				knife_finish_cut(kcd); | 
					
						
							|  |  |  | 				kcd->mode = MODE_IDLE; | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			case KNF_MODAL_ADD_CUT: | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 				knife_recalc_projmat(kcd); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				if (kcd->mode == MODE_DRAGGING) { | 
					
						
							|  |  |  | 					knife_add_cut(kcd); | 
					
						
							|  |  |  | 					if (!kcd->extend) { | 
					
						
							|  |  |  | 						knife_finish_cut(kcd); | 
					
						
							|  |  |  | 						kcd->mode = MODE_IDLE; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else if (kcd->mode != MODE_PANNING) { | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 					knife_start_cut(kcd); | 
					
						
							|  |  |  | 					kcd->mode = MODE_DRAGGING; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { /* non-modal-mapped events */ | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 		switch (event->type) { | 
					
						
							|  |  |  | 			case WHEELUPMOUSE: | 
					
						
							|  |  |  | 			case WHEELDOWNMOUSE: | 
					
						
							|  |  |  | 				return OPERATOR_PASS_THROUGH; | 
					
						
							|  |  |  | 			case MIDDLEMOUSE: | 
					
						
							|  |  |  | 				if (event->val != KM_RELEASE) { | 
					
						
							|  |  |  | 					if (kcd->mode != MODE_PANNING) | 
					
						
							|  |  |  | 						kcd->prevmode = kcd->mode; | 
					
						
							|  |  |  | 					kcd->mode = MODE_PANNING; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				else { | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 					kcd->mode = kcd->prevmode; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				ED_region_tag_redraw(kcd->ar); | 
					
						
							|  |  |  | 				return OPERATOR_PASS_THROUGH; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			case MOUSEMOVE: /* mouse moved somewhere to select another loop */ | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				if (kcd->mode != MODE_PANNING) { | 
					
						
							| 
									
										
										
										
											2012-04-18 16:55:15 +00:00
										 |  |  | 					knifetool_update_mval(kcd, event->mval); | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-09 21:38:55 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* keep going until the user confirms */ | 
					
						
							| 
									
										
										
										
											2011-04-11 01:38:20 +00:00
										 |  |  | 	return OPERATOR_RUNNING_MODAL; | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | void MESH_OT_knife_tool(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* description */ | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	ot->name = "Knife Topology Tool"; | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 	ot->idname = "MESH_OT_knife_tool"; | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	ot->description = "Cut new topology"; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* callbacks */ | 
					
						
							| 
									
										
										
										
											2012-02-10 18:09:19 +00:00
										 |  |  | 	ot->invoke = knifetool_invoke; | 
					
						
							|  |  |  | 	ot->modal = knifetool_modal; | 
					
						
							|  |  |  | 	ot->cancel = knifetool_cancel; | 
					
						
							|  |  |  | 	ot->poll = ED_operator_editmesh_view3d; | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2012-03-12 23:56:11 +00:00
										 |  |  | 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; | 
					
						
							| 
									
										
										
										
											2012-04-18 18:20:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-20 10:52:13 +00:00
										 |  |  | 	RNA_def_boolean(ot->srna, "use_occlude_geometry", TRUE, "Occlude Geometry", "Only cut the front most geometry"); | 
					
						
							| 
									
										
										
										
											2012-05-06 12:13:45 +00:00
										 |  |  | 	RNA_def_boolean(ot->srna, "only_selected", FALSE, "Only Selected", "Only cut selected geometry"); | 
					
						
							| 
									
										
										
										
											2010-09-25 01:54:58 +00:00
										 |  |  | } |