| 
									
										
										
										
											2011-10-23 17:52:20 +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 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2011 by Blender Foundation | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): Benoit Bolsee, | 
					
						
							|  |  |  |  *                 Nick Samarin | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2011-02-16 17:07:18 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-12 03:02:50 +00:00
										 |  |  | /** \file blender/editors/mesh/mesh_navmesh.c
 | 
					
						
							|  |  |  |  *  \ingroup edmesh | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-19 23:36:10 +00:00
										 |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | #include "BLI_listbase.h"
 | 
					
						
							|  |  |  | #include "BLI_math_vector.h"
 | 
					
						
							|  |  |  | #include "BLI_linklist.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-14 13:20:13 +00:00
										 |  |  | #include "BKE_library.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | #include "BKE_depsgraph.h"
 | 
					
						
							|  |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-29 14:06:48 +00:00
										 |  |  | #include "BKE_scene.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | #include "BKE_DerivedMesh.h"
 | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | #include "BKE_report.h"
 | 
					
						
							| 
									
										
										
										
											2013-04-13 20:31:52 +00:00
										 |  |  | #include "BKE_editmesh.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "ED_object.h"
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:52 +00:00
										 |  |  | #include "ED_screen.h"
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "recast-capi.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-01 10:18:01 +00:00
										 |  |  | #include "mesh_intern.h"  /* own include */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-19 04:49:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-28 06:34:13 +00:00
										 |  |  | static void createVertsTrisData(bContext *C, LinkNode *obs, | 
					
						
							|  |  |  |                                 int *nverts_r, float **verts_r, int *ntris_r, int **tris_r, unsigned int *r_lay) | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	MVert *mvert; | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	int nfaces = 0, *tri, i, curnverts, basenverts, curnfaces; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	MFace *mface; | 
					
						
							|  |  |  | 	float co[3], wco[3]; | 
					
						
							|  |  |  | 	Object *ob; | 
					
						
							|  |  |  | 	LinkNode *oblink, *dmlink; | 
					
						
							|  |  |  | 	DerivedMesh *dm; | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 	LinkNode *dms = NULL; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	int nverts, ntris, *tris; | 
					
						
							|  |  |  | 	float *verts; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	nverts = 0; | 
					
						
							|  |  |  | 	ntris = 0; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* calculate number of verts and tris */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (oblink = obs; oblink; oblink = oblink->next) { | 
					
						
							|  |  |  | 		ob = (Object *) oblink->link; | 
					
						
							|  |  |  | 		dm = mesh_create_derived_no_virtual(scene, ob, NULL, CD_MASK_MESH); | 
					
						
							|  |  |  | 		BLI_linklist_append(&dms, (void *)dm); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		nverts += dm->getNumVerts(dm); | 
					
						
							|  |  |  | 		nfaces = dm->getNumTessFaces(dm); | 
					
						
							|  |  |  | 		ntris += nfaces; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 		/* resolve quad faces */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		mface = dm->getTessFaceArray(dm); | 
					
						
							|  |  |  | 		for (i = 0; i < nfaces; i++) { | 
					
						
							|  |  |  | 			MFace *mf = &mface[i]; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (mf->v4) | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				ntris += 1; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-01-28 06:34:13 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		*r_lay |= ob->lay; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* create data */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	verts = MEM_mallocN(sizeof(float) * 3 * nverts, "createVertsTrisData verts"); | 
					
						
							|  |  |  | 	tris = MEM_mallocN(sizeof(int) * 3 * ntris, "createVertsTrisData faces"); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	basenverts = 0; | 
					
						
							|  |  |  | 	tri = tris; | 
					
						
							|  |  |  | 	for (oblink = obs, dmlink = dms; oblink && dmlink; | 
					
						
							|  |  |  | 	     oblink = oblink->next, dmlink = dmlink->next) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ob = (Object *) oblink->link; | 
					
						
							|  |  |  | 		dm = (DerivedMesh *) dmlink->link; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		curnverts = dm->getNumVerts(dm); | 
					
						
							|  |  |  | 		mvert = dm->getVertArray(dm); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* copy verts */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		for (i = 0; i < curnverts; i++) { | 
					
						
							|  |  |  | 			MVert *v = &mvert[i]; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 			copy_v3_v3(co, v->co); | 
					
						
							|  |  |  | 			mul_v3_m4v3(wco, ob->obmat, co); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			verts[3 * (basenverts + i) + 0] = wco[0]; | 
					
						
							|  |  |  | 			verts[3 * (basenverts + i) + 1] = wco[2]; | 
					
						
							|  |  |  | 			verts[3 * (basenverts + i) + 2] = wco[1]; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 		/* create tris */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		curnfaces = dm->getNumTessFaces(dm); | 
					
						
							|  |  |  | 		mface = dm->getTessFaceArray(dm); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		for (i = 0; i < curnfaces; i++) { | 
					
						
							|  |  |  | 			MFace *mf = &mface[i]; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			tri[0] = basenverts + mf->v1; | 
					
						
							|  |  |  | 			tri[1] = basenverts + mf->v3; | 
					
						
							|  |  |  | 			tri[2] = basenverts + mf->v2; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 			tri += 3; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (mf->v4) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				tri[0] = basenverts + mf->v1; | 
					
						
							|  |  |  | 				tri[1] = basenverts + mf->v4; | 
					
						
							|  |  |  | 				tri[2] = basenverts + mf->v3; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 				tri += 3; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		basenverts += curnverts; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* release derived mesh */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (dmlink = dms; dmlink; dmlink = dmlink->next) { | 
					
						
							|  |  |  | 		dm = (DerivedMesh *) dmlink->link; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 		dm->release(dm); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	BLI_linklist_free(dms, NULL); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	*nverts_r = nverts; | 
					
						
							|  |  |  | 	*verts_r = verts; | 
					
						
							|  |  |  | 	*ntris_r = ntris; | 
					
						
							|  |  |  | 	*tris_r = tris; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | static bool buildNavMesh(const RecastData *recastParams, int nverts, float *verts, int ntris, int *tris, | 
					
						
							|  |  |  |                          struct recast_polyMesh **pmesh, struct recast_polyMeshDetail **dmesh, | 
					
						
							|  |  |  |                          ReportList *reports) | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float bmin[3], bmax[3]; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	struct recast_heightfield *solid; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	unsigned char *triflags; | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	struct recast_compactHeightfield *chf; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	struct recast_contourSet *cset; | 
					
						
							|  |  |  | 	int width, height, walkableHeight, walkableClimb, walkableRadius; | 
					
						
							| 
									
										
										
										
											2011-09-29 21:38:57 +00:00
										 |  |  | 	int minRegionArea, mergeRegionArea, maxEdgeLen; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	float detailSampleDist, detailSampleMaxError; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	recast_calcBounds(verts, nverts, bmin, bmax); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* ** Step 1. Initialize build config ** */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	walkableHeight = (int)ceilf(recastParams->agentheight / recastParams->cellheight); | 
					
						
							|  |  |  | 	walkableClimb = (int)floorf(recastParams->agentmaxclimb / recastParams->cellheight); | 
					
						
							|  |  |  | 	walkableRadius = (int)ceilf(recastParams->agentradius / recastParams->cellsize); | 
					
						
							|  |  |  | 	minRegionArea = (int)(recastParams->regionminsize * recastParams->regionminsize); | 
					
						
							|  |  |  | 	mergeRegionArea = (int)(recastParams->regionmergesize * recastParams->regionmergesize); | 
					
						
							|  |  |  | 	maxEdgeLen = (int)(recastParams->edgemaxlen / recastParams->cellsize); | 
					
						
							|  |  |  | 	detailSampleDist = recastParams->detailsampledist < 0.9f ? 0 : | 
					
						
							|  |  |  | 	                   recastParams->cellsize * recastParams->detailsampledist; | 
					
						
							|  |  |  | 	detailSampleMaxError = recastParams->cellheight * recastParams->detailsamplemaxerror; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* Set the area where the navigation will be build. */ | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	recast_calcGridSize(bmin, bmax, recastParams->cellsize, &width, &height); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 	/* zero dimensions cause zero alloc later on [#33758] */ | 
					
						
							|  |  |  | 	if (width <= 0 || height <= 0) { | 
					
						
							| 
									
										
										
										
											2013-01-04 07:57:33 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Object has a width or height of zero"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* ** Step 2: Rasterize input polygon soup ** */ | 
					
						
							|  |  |  | 	/* Allocate voxel heightfield where we rasterize our input data to */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	solid = recast_newHeightfield(); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (!recast_createHeightfield(solid, width, height, bmin, bmax, recastParams->cellsize, recastParams->cellheight)) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 		recast_destroyHeightfield(solid); | 
					
						
							| 
									
										
										
										
											2013-01-05 11:50:36 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Failed to create height field"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* Allocate array that can hold triangle flags */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	triflags = MEM_callocN(sizeof(unsigned char) * ntris, "buildNavMesh triflags"); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* Find triangles which are walkable based on their slope and rasterize them */ | 
					
						
							| 
									
										
										
										
											2012-11-04 07:18:29 +00:00
										 |  |  | 	recast_markWalkableTriangles(RAD2DEGF(recastParams->agentmaxslope), verts, nverts, tris, ntris, triflags); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	recast_rasterizeTriangles(verts, nverts, tris, triflags, ntris, solid); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	MEM_freeN(triflags); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* ** Step 3: Filter walkables surfaces ** */ | 
					
						
							| 
									
										
										
										
											2011-09-29 21:38:57 +00:00
										 |  |  | 	recast_filterLowHangingWalkableObstacles(walkableClimb, solid); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	recast_filterLedgeSpans(walkableHeight, walkableClimb, solid); | 
					
						
							|  |  |  | 	recast_filterWalkableLowHeightSpans(walkableHeight, solid); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* ** Step 4: Partition walkable surface to simple regions ** */ | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	chf = recast_newCompactHeightfield(); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (!recast_buildCompactHeightfield(walkableHeight, walkableClimb, solid, chf)) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 		recast_destroyHeightfield(solid); | 
					
						
							|  |  |  | 		recast_destroyCompactHeightfield(chf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-05 11:50:36 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Failed to create compact height field"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	recast_destroyHeightfield(solid); | 
					
						
							| 
									
										
										
										
											2011-09-29 21:38:57 +00:00
										 |  |  | 	solid = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!recast_erodeWalkableArea(walkableRadius, chf)) { | 
					
						
							|  |  |  | 		recast_destroyCompactHeightfield(chf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-05 11:50:36 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Failed to erode walkable area"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2011-09-29 21:38:57 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* Prepare for region partitioning, by calculating distance field along the walkable surface */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (!recast_buildDistanceField(chf)) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 		recast_destroyCompactHeightfield(chf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-05 11:50:36 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Failed to build distance field"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* Partition the walkable surface into simple regions without holes */ | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (!recast_buildRegions(chf, 0, minRegionArea, mergeRegionArea)) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 		recast_destroyCompactHeightfield(chf); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-05 11:50:36 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Failed to build regions"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* ** Step 5: Trace and simplify region contours ** */ | 
					
						
							|  |  |  | 	/* Create contours */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	cset = recast_newContourSet(); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (!recast_buildContours(chf, recastParams->edgemaxerror, maxEdgeLen, cset)) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 		recast_destroyCompactHeightfield(chf); | 
					
						
							|  |  |  | 		recast_destroyContourSet(cset); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-05 11:50:36 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Failed to build contours"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* ** Step 6: Build polygons mesh from contours ** */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	*pmesh = recast_newPolyMesh(); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (!recast_buildPolyMesh(cset, recastParams->vertsperpoly, *pmesh)) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 		recast_destroyCompactHeightfield(chf); | 
					
						
							|  |  |  | 		recast_destroyContourSet(cset); | 
					
						
							|  |  |  | 		recast_destroyPolyMesh(*pmesh); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-05 11:50:36 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Failed to build poly mesh"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* ** Step 7: Create detail mesh which allows to access approximate height on each polygon ** */ | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	*dmesh = recast_newPolyMeshDetail(); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (!recast_buildPolyMeshDetail(*pmesh, chf, detailSampleDist, detailSampleMaxError, *dmesh)) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 		recast_destroyCompactHeightfield(chf); | 
					
						
							|  |  |  | 		recast_destroyContourSet(cset); | 
					
						
							|  |  |  | 		recast_destroyPolyMesh(*pmesh); | 
					
						
							|  |  |  | 		recast_destroyPolyMeshDetail(*dmesh); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-05 11:50:36 +00:00
										 |  |  | 		BKE_report(reports, RPT_ERROR, "Failed to build poly mesh detail"); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return false; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	recast_destroyCompactHeightfield(chf); | 
					
						
							|  |  |  | 	recast_destroyContourSet(cset); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 	return true; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-28 06:34:13 +00:00
										 |  |  | static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, struct recast_polyMeshDetail *dmesh, | 
					
						
							|  |  |  |                                   Base *base, unsigned int lay) | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	float co[3], rot[3]; | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 	BMEditMesh *em; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	int i, j, k; | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	unsigned short *v; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	int face[3]; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	Object *obedit; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	int createob = base == NULL; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	int nverts, nmeshes, nvp; | 
					
						
							| 
									
										
										
										
											2011-09-29 21:38:57 +00:00
										 |  |  | 	unsigned short *verts, *polys; | 
					
						
							|  |  |  | 	unsigned int *meshes; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	float bmin[3], cs, ch, *dverts; | 
					
						
							|  |  |  | 	unsigned char *tris; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	zero_v3(co); | 
					
						
							|  |  |  | 	zero_v3(rot); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (createob) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 		/* create new object */ | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 		obedit = ED_object_add_type(C, OB_MESH, co, rot, false, lay); | 
					
						
							| 
									
										
										
										
											2010-07-29 14:06:48 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		obedit = base->object; | 
					
						
							| 
									
										
										
										
											2012-05-05 14:33:36 +00:00
										 |  |  | 		BKE_scene_base_deselect_all(scene); | 
					
						
							|  |  |  | 		BKE_scene_base_select(scene, base); | 
					
						
							| 
									
										
										
										
											2010-07-29 14:06:48 +00:00
										 |  |  | 		copy_v3_v3(obedit->loc, co); | 
					
						
							|  |  |  | 		copy_v3_v3(obedit->rot, rot); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-21 14:18:17 +00:00
										 |  |  | 	ED_object_editmode_enter(C, EM_DO_UNDO | EM_IGNORE_LAYER); | 
					
						
							| 
									
										
										
										
											2013-04-16 05:59:48 +00:00
										 |  |  | 	em = BKE_editmesh_from_object(obedit); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (!createob) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 		/* clear */ | 
					
						
							| 
									
										
										
										
											2012-03-27 04:46:52 +00:00
										 |  |  | 		EDBM_mesh_clear(em); | 
					
						
							| 
									
										
										
										
											2010-07-29 14:06:48 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* create verts for polygon mesh */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	verts = recast_polyMeshGetVerts(pmesh, &nverts); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	recast_polyMeshGetBoundbox(pmesh, bmin, NULL); | 
					
						
							|  |  |  | 	recast_polyMeshGetCell(pmesh, &cs, &ch); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (i = 0; i < nverts; i++) { | 
					
						
							|  |  |  | 		v = &verts[3 * i]; | 
					
						
							|  |  |  | 		co[0] = bmin[0] + v[0] * cs; | 
					
						
							|  |  |  | 		co[1] = bmin[1] + v[1] * ch; | 
					
						
							|  |  |  | 		co[2] = bmin[2] + v[2] * cs; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 		SWAP(float, co[1], co[2]); | 
					
						
							| 
									
										
										
										
											2013-08-21 05:39:46 +00:00
										 |  |  | 		BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* create custom data layer to save polygon idx */ | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 	CustomData_add_layer_named(&em->bm->pdata, CD_RECAST, CD_CALLOC, NULL, 0, "createRepresentation recastData"); | 
					
						
							| 
									
										
										
										
											2012-04-16 13:53:30 +00:00
										 |  |  | 	CustomData_bmesh_init_pool(&em->bm->pdata, 0, BM_FACE); | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* create verts and faces for detailed mesh */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	meshes = recast_polyMeshDetailGetMeshes(dmesh, &nmeshes); | 
					
						
							|  |  |  | 	polys = recast_polyMeshGetPolys(pmesh, NULL, &nvp); | 
					
						
							|  |  |  | 	dverts = recast_polyMeshDetailGetVerts(dmesh, NULL); | 
					
						
							|  |  |  | 	tris = recast_polyMeshDetailGetTris(dmesh, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (i = 0; i < nmeshes; i++) { | 
					
						
							|  |  |  | 		int uniquevbase = em->bm->totvert; | 
					
						
							|  |  |  | 		unsigned int vbase = meshes[4 * i + 0]; | 
					
						
							|  |  |  | 		unsigned short ndv = meshes[4 * i + 1]; | 
					
						
							|  |  |  | 		unsigned short tribase = meshes[4 * i + 2]; | 
					
						
							|  |  |  | 		unsigned short trinum = meshes[4 * i + 3]; | 
					
						
							|  |  |  | 		const unsigned short *p = &polys[i * nvp * 2]; | 
					
						
							|  |  |  | 		int nv = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (j = 0; j < nvp; ++j) { | 
					
						
							|  |  |  | 			if (p[j] == 0xffff) break; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 			nv++; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* create unique verts  */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		for (j = nv; j < ndv; j++) { | 
					
						
							|  |  |  | 			copy_v3_v3(co, &dverts[3 * (vbase + j)]); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 			SWAP(float, co[1], co[2]); | 
					
						
							| 
									
										
										
										
											2013-08-21 05:39:46 +00:00
										 |  |  | 			BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-28 14:15:14 +00:00
										 |  |  | 		/* need to rebuild entirely because array size changes */ | 
					
						
							| 
									
										
										
										
											2013-10-28 02:05:33 +00:00
										 |  |  | 		BM_mesh_elem_table_init(em->bm, BM_VERT); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* create faces */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		for (j = 0; j < trinum; j++) { | 
					
						
							|  |  |  | 			unsigned char *tri = &tris[4 * (tribase + j)]; | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 			BMFace *newFace; | 
					
						
							|  |  |  | 			int *polygonIdx; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			for (k = 0; k < 3; k++) { | 
					
						
							|  |  |  | 				if (tri[k] < nv) | 
					
						
							|  |  |  | 					face[k] = p[tri[k]];  /* shared vertex */ | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 				else | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 					face[k] = uniquevbase + tri[k] - nv;  /* unique vertex */ | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			newFace = BM_face_create_quad_tri(em->bm, | 
					
						
							| 
									
										
										
										
											2013-10-28 02:05:33 +00:00
										 |  |  | 			                                  BM_vert_at_index(em->bm, face[0]), | 
					
						
							|  |  |  | 			                                  BM_vert_at_index(em->bm, face[2]), | 
					
						
							|  |  |  | 			                                  BM_vert_at_index(em->bm, face[1]), NULL, | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 			                                  NULL, false); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 			/* set navigation polygon idx to the custom layer */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			polygonIdx = (int *)CustomData_bmesh_get(&em->bm->pdata, newFace->head.data, CD_RECAST); | 
					
						
							|  |  |  | 			*polygonIdx = i + 1; /* add 1 to avoid zero idx */ | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 	recast_destroyPolyMesh(pmesh); | 
					
						
							|  |  |  | 	recast_destroyPolyMeshDetail(dmesh); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-21 14:18:17 +00:00
										 |  |  | 	ED_object_editmode_exit(C, EM_FREEDATA);  | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, obedit); | 
					
						
							| 
									
										
										
										
											2010-07-14 13:20:13 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (createob) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		obedit->gameflag &= ~OB_COLLISION; | 
					
						
							|  |  |  | 		obedit->gameflag |= OB_NAVMESH; | 
					
						
							|  |  |  | 		obedit->body_type = OB_BODY_TYPE_NAVMESH; | 
					
						
							| 
									
										
										
										
											2010-07-29 14:06:48 +00:00
										 |  |  | 		rename_id((ID *)obedit, "Navmesh"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-09 21:11:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BKE_mesh_ensure_navmesh(obedit->data); | 
					
						
							| 
									
										
										
										
											2010-07-21 19:44:59 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	return obedit; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-23 21:25:07 +00:00
										 |  |  | static int navmesh_create_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 	LinkNode *obs = NULL; | 
					
						
							|  |  |  | 	Base *navmeshBase = NULL; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-30 16:22:40 +00:00
										 |  |  | 	CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 		if (base->object->type == OB_MESH) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			if (base->object->body_type == OB_BODY_TYPE_NAVMESH) { | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 				if (!navmeshBase || base == scene->basact) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 					navmeshBase = base; | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 				BLI_linklist_append(&obs, (void *)base->object); | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-07-29 14:06:48 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-02-16 17:07:18 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 	CTX_DATA_END; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 	if (obs) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		struct recast_polyMesh *pmesh = NULL; | 
					
						
							|  |  |  | 		struct recast_polyMeshDetail *dmesh = NULL; | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		bool ok; | 
					
						
							| 
									
										
										
										
											2013-01-28 06:34:13 +00:00
										 |  |  | 		unsigned int lay = 0; | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		int nverts = 0, ntris = 0; | 
					
						
							| 
									
										
										
										
											2013-08-07 03:55:21 +00:00
										 |  |  | 		int *tris = NULL; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		float *verts = NULL; | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-28 06:34:13 +00:00
										 |  |  | 		createVertsTrisData(C, obs, &nverts, &verts, &ntris, &tris, &lay); | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 		BLI_linklist_free(obs, NULL); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		if ((ok = buildNavMesh(&scene->gm.recastData, nverts, verts, ntris, tris, &pmesh, &dmesh, op->reports))) { | 
					
						
							| 
									
										
										
										
											2013-01-28 06:34:13 +00:00
										 |  |  | 			createRepresentation(C, pmesh, dmesh, navmeshBase, lay); | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 		MEM_freeN(verts); | 
					
						
							|  |  |  | 		MEM_freeN(tris); | 
					
						
							| 
									
										
										
										
											2011-10-11 04:09:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-04 05:43:26 +00:00
										 |  |  | 		return ok ? OPERATOR_FINISHED : OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2011-10-10 22:06:07 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		BKE_report(op->reports, RPT_ERROR, "No mesh objects found"); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-11 04:09:11 +00:00
										 |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | void MESH_OT_navmesh_make(wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2013-01-27 07:23:58 +00:00
										 |  |  | 	ot->name = "Create Navigation Mesh"; | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->description = "Create navigation mesh for selected objects"; | 
					
						
							|  |  |  | 	ot->idname = "MESH_OT_navmesh_make"; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2012-03-23 21:25:07 +00:00
										 |  |  | 	ot->exec = navmesh_create_exec; | 
					
						
							| 
									
										
										
										
											2010-07-14 20:09:04 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2010-07-09 22:16:52 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | static int navmesh_face_copy_exec(bContext *C, wmOperator *op) | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-02 12:09:49 +00:00
										 |  |  | 	Object *obedit = CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2013-04-16 05:59:48 +00:00
										 |  |  | 	BMEditMesh *em = BKE_editmesh_from_object(obedit); | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* do work here */ | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 	BMFace *efa_act = BM_mesh_active_face_get(em->bm, false, false); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (efa_act) { | 
					
						
							|  |  |  | 		if (CustomData_has_layer(&em->bm->pdata, CD_RECAST)) { | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 			BMFace *efa; | 
					
						
							|  |  |  | 			BMIter iter; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 			int targetPolyIdx = *(int *)CustomData_bmesh_get(&em->bm->pdata, efa_act->head.data, CD_RECAST); | 
					
						
							|  |  |  | 			targetPolyIdx = targetPolyIdx >= 0 ? targetPolyIdx : -targetPolyIdx; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 			if (targetPolyIdx > 0) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 				/* set target poly idx to other selected faces */ | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 				BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 					if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && efa != efa_act) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 						int *recastDataBlock = (int *)CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_RECAST); | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 						*recastDataBlock = targetPolyIdx; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 			else { | 
					
						
							|  |  |  | 				BKE_report(op->reports, RPT_ERROR, "Active face has no index set"); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | void MESH_OT_navmesh_face_copy(struct wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->name = "NavMesh Copy Face Index"; | 
					
						
							|  |  |  | 	ot->description = "Copy the index from the active face"; | 
					
						
							|  |  |  | 	ot->idname = "MESH_OT_navmesh_face_copy"; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->poll = ED_operator_editmesh; | 
					
						
							|  |  |  | 	ot->exec = navmesh_face_copy_exec; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | static int compare(const void *a, const void *b) | 
					
						
							| 
									
										
										
										
											2011-12-17 00:52:36 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	return (*(int *)a - *(int *)b); | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | static int findFreeNavPolyIndex(BMEditMesh *em) | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* construct vector of indices */ | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	int numfaces = em->bm->totface; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	int *indices = MEM_callocN(sizeof(int) * numfaces, "findFreeNavPolyIndex(indices)"); | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	BMFace *ef; | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 	BMIter iter; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	int i, idx = em->bm->totface - 1, freeIdx = 1; | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 	/*XXX this originally went last to first, but that isn't possible anymore*/ | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 	BM_ITER_MESH (ef, &iter, em->bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		int polyIdx = *(int *)CustomData_bmesh_get(&em->bm->pdata, ef->head.data, CD_RECAST); | 
					
						
							|  |  |  | 		indices[idx] = polyIdx; | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 		idx--; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 	qsort(indices, numfaces, sizeof(int), compare); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	/* search first free index */ | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	freeIdx = 1; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	for (i = 0; i < numfaces; i++) { | 
					
						
							|  |  |  | 		if (indices[i] == freeIdx) | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 			freeIdx++; | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		else if (indices[i] > freeIdx) | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	MEM_freeN(indices); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 	return freeIdx; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | static int navmesh_face_add_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-03-02 12:09:49 +00:00
										 |  |  | 	Object *obedit = CTX_data_edit_object(C); | 
					
						
							| 
									
										
										
										
											2013-04-16 05:59:48 +00:00
										 |  |  | 	BMEditMesh *em = BKE_editmesh_from_object(obedit); | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 	BMFace *ef; | 
					
						
							|  |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 	if (CustomData_has_layer(&em->bm->pdata, CD_RECAST)) { | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 		int targetPolyIdx = findFreeNavPolyIndex(em); | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 		if (targetPolyIdx > 0) { | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 			/* set target poly idx to selected faces */ | 
					
						
							| 
									
										
										
										
											2011-11-08 00:20:50 +00:00
										 |  |  | 			/*XXX this originally went last to first, but that isn't possible anymore*/ | 
					
						
							|  |  |  | 			 | 
					
						
							| 
									
										
										
										
											2012-04-19 13:47:58 +00:00
										 |  |  | 			BM_ITER_MESH (ef, &iter, em->bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2012-03-24 06:38:07 +00:00
										 |  |  | 				if (BM_elem_flag_test(ef, BM_ELEM_SELECT)) { | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 					int *recastDataBlock = (int *)CustomData_bmesh_get(&em->bm->pdata, ef->head.data, CD_RECAST); | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 					*recastDataBlock = targetPolyIdx; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-09-27 09:09:55 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	DAG_id_tag_update((ID *)obedit->data, OB_RECALC_DATA); | 
					
						
							|  |  |  | 	WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | void MESH_OT_navmesh_face_add(struct wmOperatorType *ot) | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->name = "NavMesh New Face Index"; | 
					
						
							|  |  |  | 	ot->description = "Add a new index and assign it to selected faces"; | 
					
						
							|  |  |  | 	ot->idname = "MESH_OT_navmesh_face_add"; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->poll = ED_operator_editmesh; | 
					
						
							|  |  |  | 	ot->exec = navmesh_face_add_exec; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int navmesh_obmode_data_poll(bContext *C) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *ob = ED_object_active_context(C); | 
					
						
							|  |  |  | 	if (ob && (ob->mode == OB_MODE_OBJECT) && (ob->type == OB_MESH)) { | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 		Mesh *me = ob->data; | 
					
						
							| 
									
										
										
										
											2012-02-13 04:52:41 +00:00
										 |  |  | 		return CustomData_has_layer(&me->pdata, CD_RECAST); | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int navmesh_obmode_poll(bContext *C) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *ob = ED_object_active_context(C); | 
					
						
							|  |  |  | 	if (ob && (ob->mode == OB_MODE_OBJECT) && (ob->type == OB_MESH)) { | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int navmesh_reset_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *ob = ED_object_active_context(C); | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	Mesh *me = ob->data; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-13 04:52:41 +00:00
										 |  |  | 	CustomData_free_layers(&me->pdata, CD_RECAST, me->totpoly); | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BKE_mesh_ensure_navmesh(me); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	DAG_id_tag_update(&me->id, OB_RECALC_DATA); | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_GEOM | ND_DATA, &me->id); | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_navmesh_reset(struct wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->name = "NavMesh Reset Index Values"; | 
					
						
							|  |  |  | 	ot->description = "Assign a new index to every face"; | 
					
						
							|  |  |  | 	ot->idname = "MESH_OT_navmesh_reset"; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->poll = navmesh_obmode_poll; | 
					
						
							|  |  |  | 	ot->exec = navmesh_reset_exec; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int navmesh_clear_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Object *ob = ED_object_active_context(C); | 
					
						
							| 
									
										
										
										
											2012-03-24 02:51:46 +00:00
										 |  |  | 	Mesh *me = ob->data; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-13 04:52:41 +00:00
										 |  |  | 	CustomData_free_layers(&me->pdata, CD_RECAST, me->totpoly); | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	DAG_id_tag_update(&me->id, OB_RECALC_DATA); | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	WM_event_add_notifier(C, NC_GEOM | ND_DATA, &me->id); | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_navmesh_clear(struct wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->name = "NavMesh Clear Data"; | 
					
						
							|  |  |  | 	ot->description = "Remove navmesh data from this mesh"; | 
					
						
							|  |  |  | 	ot->idname = "MESH_OT_navmesh_clear"; | 
					
						
							| 
									
										
										
										
											2011-10-10 07:21:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							| 
									
										
										
										
											2012-03-22 07:26:09 +00:00
										 |  |  | 	ot->poll = navmesh_obmode_data_poll; | 
					
						
							|  |  |  | 	ot->exec = navmesh_clear_exec; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							| 
									
										
										
										
											2012-03-26 02:56:48 +00:00
										 |  |  | 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2010-07-27 21:01:00 +00:00
										 |  |  | } |