/** * $Id$ * * ***** 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) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** */ #include #include #include "Recast.h" extern "C"{ #include "BKE_navmesh_conversion.h" #include "DNA_meshdata_types.h" #include "BKE_cdderivedmesh.h" #include "BLI_math.h" } inline float area2(const float* a, const float* b, const float* c) { return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]); } inline bool left(const float* a, const float* b, const float* c) { return area2(a, b, c) < 0; } int polyNumVerts(const unsigned short* p, const int vertsPerPoly) { int nv = 0; for (int i=0; i 0) t /= d; if (t < 0) t = 0; else if (t > 1) t = 1; dx[0] = a[0] + t*abx[0] - point[0]; dx[2] = a[2] + t*abx[2] - point[2]; return dx[0]*dx[0] + dx[2]*dx[2]; } bool buildRawVertIndicesData(DerivedMesh* dm, int &nverts, float *&verts, int &ntris, unsigned short *&tris, int *&trisToFacesMap, int *&recastData) { nverts = dm->getNumVerts(dm); if (nverts>=0xffff) { printf("Converting navmesh: Error! Too many vertices. Max number of vertices %d\n", 0xffff); return false; } verts = new float[3*nverts]; dm->getVertCos(dm, (float(*)[3])verts); //flip coordinates for (int vi=0; vigetNumFaces(dm); MFace *faces = dm->getFaceArray(dm); ntris = nfaces; for (int fi=0; fiv4) ntris++; } //copy and transform to triangles (reorder on the run) trisToFacesMap = new int[ntris]; tris = new unsigned short[3*ntris]; unsigned short* tri = tris; int triIdx = 0; for (int fi=0; fiv1; tri[3*triIdx+1] = (unsigned short) face->v3; tri[3*triIdx+2] = (unsigned short) face->v2; trisToFacesMap[triIdx++]=fi; if (face->v4) { tri[3*triIdx+0] = (unsigned short) face->v1; tri[3*triIdx+1] = (unsigned short) face->v4; tri[3*triIdx+2] = (unsigned short) face->v3; trisToFacesMap[triIdx++]=fi; } } //carefully, recast data is just reference to data in derived mesh recastData = (int*)CustomData_get_layer(&dm->faceData, CD_RECAST); return true; } bool buildPolygonsByDetailedMeshes(const int vertsPerPoly, const int npolys, unsigned short* polys, const unsigned short* dmeshes, const float* verts, const unsigned short* dtris, const int* dtrisToPolysMap) { int capacity = vertsPerPoly; unsigned short* newPoly = new unsigned short[capacity]; memset(newPoly, 0xff, sizeof(unsigned short)*capacity); for (int polyidx=0; polyidxtolerance) adjustedPoly[adjustedNv++] = cur; } memcpy(newPoly, adjustedPoly, adjustedNv*sizeof(unsigned short)); delete adjustedPoly; nv = adjustedNv; bool allBorderTraversed = true; for (size_t i=0; i<(size_t)dtrisNum; i++) { if (traversedTris[i]==0) { //check whether it has border edges int curpolytri = dtrisBase+i; for (int k=0; k<3; k++) { unsigned short neighbortri = dtris[curpolytri*3*2+3+k]; if ( neighbortri==0xffff || dtrisToPolysMap[neighbortri]!=polyidx+1) { allBorderTraversed = false; break; } } } } if (nv<=vertsPerPoly && allBorderTraversed) { for (int i=0; irecastData[_qsort_context->trisToFacesMap[*(int*)a]] - _qsort_context->recastData[_qsort_context->trisToFacesMap[*(int*)b]] ); } bool buildNavMeshData(const int nverts, const float* verts, const int ntris, const unsigned short *tris, const int* recastData, const int* trisToFacesMap, int &ndtris, unsigned short *&dtris, int &npolys, unsigned short *&dmeshes, unsigned short *&polys, int &vertsPerPoly, int *&dtrisToPolysMap, int *&dtrisToTrisMap) { if (!recastData) { printf("Converting navmesh: Error! Can't find recast custom data\n"); return false; } //sort the triangles by polygon idx int* trisMapping = new int[ntris]; for (int i=0; i0) { validTriStart = i; break; } } if (validTriStart<0) { printf("Converting navmesh: Error! No valid polygons in mesh\n"); delete trisMapping; return false; } ndtris = ntris-validTriStart; //fill dtris to faces mapping dtrisToTrisMap = new int[ndtris]; memcpy(dtrisToTrisMap, &trisMapping[validTriStart], ndtris*sizeof(int)); delete trisMapping; trisMapping=NULL; //create detailed mesh triangles - copy only valid triangles //and reserve memory for adjacency info dtris = new unsigned short[3*2*ndtris]; memset(dtris, 0xffff, sizeof(unsigned short)*3*2*ndtris); for (int i=0; i