void recast_qsort(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
{
	char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
	int d, r, swaptype, swap_cnt;

loop:	
	SWAPINIT(a, es);
	swap_cnt = 0;
	if (n < 7) {
		for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
			for (pl = pm; 
				pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
				pl -= es)
				swap(pl, pl - es);
		return;
	}
	pm = (char *)a + (n / 2) * es;
	if (n > 7) {
		pl = (char *)a;
		pn = (char *)a + (n - 1) * es;
		if (n > 40) {
			d = (n / 8) * es;
			pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
			pm = med3(pm - d, pm, pm + d, cmp, thunk);
			pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
		}
		pm = med3(pl, pm, pn, cmp, thunk);
	}
	swap((char *)a, pm);
	pa = pb = (char *)a + es;

	pc = pd = (char *)a + (n - 1) * es;
	for (;;) {
		while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) {
			if (r == 0) {
				swap_cnt = 1;
				swap(pa, pb);
				pa += es;
			}
			pb += es;
		}
		while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) {
			if (r == 0) {
				swap_cnt = 1;
				swap(pc, pd);
				pd -= es;
			}
			pc -= es;
		}
		if (pb > pc)
			break;
		swap(pb, pc);
		swap_cnt = 1;
		pb += es;
		pc -= es;
	}
	if (swap_cnt == 0) {  /* Switch to insertion sort */
		for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
			for (pl = pm; 
				pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
				pl -= es)
				swap(pl, pl - es);
		return;
	}

	pn = (char *)a + n * es;
	r = min(pa - (char *)a, pb - pa);
	vecswap((char *)a, pb - r, r);
	r = min(pd - pc, pn - pd - es);
	vecswap(pb, pn - r, r);
	if ((r = pb - pa) > es)
		recast_qsort(a, r / es, es, thunk, cmp);
	if ((r = pd - pc) > es) {
		/* Iterate rather than recurse to save stack space */
		a = pn - r;
		n = r / es;
		goto loop;
	}
}
Example #2
0
int buildNavMeshData(const int nverts, const float* verts, 
							 const int ntris, const unsigned short *tris, 
							 const int* recastData, const int* trisToFacesMap,
							 int *ndtris_r, unsigned short **dtris_r,
							 int *npolys_r, unsigned short **dmeshes_r, unsigned short **polys_r,
							 int *vertsPerPoly_r, int **dtrisToPolysMap_r, int **dtrisToTrisMap_r)

{
	int *trisMapping = MEM_callocN(sizeof(int)*ntris, "buildNavMeshData trisMapping");
	int i;
	struct SortContext context;
	int validTriStart, prevPolyIdx, curPolyIdx, newPolyIdx, prevpolyidx;
	unsigned short *dmesh;

	int ndtris, npolys, vertsPerPoly;
	unsigned short *dtris, *dmeshes, *polys;
	int *dtrisToPolysMap, *dtrisToTrisMap;

	if (!recastData)
	{
		printf("Converting navmesh: Error! Can't find recast custom data\n");
		return 0;
	}

	//sort the triangles by polygon idx
	for (i=0; i<ntris; i++)
		trisMapping[i]=i;
	context.recastData = recastData;
	context.trisToFacesMap = trisToFacesMap;
	recast_qsort(trisMapping, ntris, sizeof(int), &context, compareByData);

	//search first valid triangle - triangle of convex polygon
	validTriStart = -1;
	for (i=0; i< ntris; i++)
	{
		if (recastData[trisToFacesMap[trisMapping[i]]]>0)
		{
			validTriStart = i;
			break;
		}
	}

	if (validTriStart<0)
	{
		printf("Converting navmesh: Error! No valid polygons in mesh\n");
		MEM_freeN(trisMapping);
		return 0;
	}

	ndtris = ntris-validTriStart;
	//fill dtris to faces mapping
	dtrisToTrisMap = MEM_callocN(sizeof(int)*ndtris, "buildNavMeshData dtrisToTrisMap");
	memcpy(dtrisToTrisMap, &trisMapping[validTriStart], ndtris*sizeof(int));
	MEM_freeN(trisMapping);

	//create detailed mesh triangles  - copy only valid triangles
	//and reserve memory for adjacency info
	dtris = MEM_callocN(sizeof(unsigned short)*3*2*ndtris, "buildNavMeshData dtris");
	memset(dtris, 0xffff, sizeof(unsigned short)*3*2*ndtris);
	for (i=0; i<ndtris; i++)
	{
		memcpy(dtris+3*2*i, tris+3*dtrisToTrisMap[i], sizeof(unsigned short)*3);
	}

	//create new recast data corresponded to dtris and renumber for continuous indices
	prevPolyIdx = -1;
	newPolyIdx = 0;
	dtrisToPolysMap = MEM_callocN(sizeof(int)*ndtris, "buildNavMeshData dtrisToPolysMap");
	for (i=0; i<ndtris; i++)
	{
		curPolyIdx = recastData[trisToFacesMap[dtrisToTrisMap[i]]];
		if (curPolyIdx!=prevPolyIdx)
		{
			newPolyIdx++;
			prevPolyIdx=curPolyIdx;
		}
		dtrisToPolysMap[i] = newPolyIdx;
	}


	//build adjacency info for detailed mesh triangles
	recast_buildMeshAdjacency(dtris, ndtris, nverts, 3);

	//create detailed mesh description for each navigation polygon
	npolys = dtrisToPolysMap[ndtris-1];
	dmeshes = MEM_callocN(sizeof(unsigned short)*npolys*4, "buildNavMeshData dmeshes");
	memset(dmeshes, 0, npolys*4*sizeof(unsigned short));
	dmesh = NULL;
	prevpolyidx = 0;
	for (i=0; i<ndtris; i++)
	{
		int curpolyidx = dtrisToPolysMap[i];
		if (curpolyidx!=prevpolyidx)
		{
			if (curpolyidx!=prevpolyidx+1)
			{
				printf("Converting navmesh: Error! Wrong order of detailed mesh faces\n");
				return 0;
			}
			dmesh = dmesh==NULL ? dmeshes : dmesh+4;
			dmesh[2] = (unsigned short)i;	//tbase
			dmesh[3] = 0;	//tnum
			prevpolyidx = curpolyidx;
		}
		dmesh[3]++;
	}

	//create navigation polygons
	vertsPerPoly = 6;
	polys = MEM_callocN(sizeof(unsigned short)*npolys*vertsPerPoly*2, "buildNavMeshData polys");
	memset(polys, 0xff, sizeof(unsigned short)*vertsPerPoly*2*npolys);

	buildPolygonsByDetailedMeshes(vertsPerPoly, npolys, polys, dmeshes, verts, dtris, dtrisToPolysMap);

	*ndtris_r = ndtris;
	*npolys_r = npolys;
	*vertsPerPoly_r = vertsPerPoly;
	*dtris_r = dtris;
	*dmeshes_r = dmeshes;
	*polys_r = polys;
	*dtrisToPolysMap_r = dtrisToPolysMap;
	*dtrisToTrisMap_r = dtrisToTrisMap;

	return 1;
}