/* * $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 ***** */ /** \file blender/blenkernel/intern/navmesh_conversion.c * \ingroup bke */ #include #include #include "MEM_guardedalloc.h" #include "DNA_meshdata_types.h" #include "BKE_navmesh_conversion.h" #include "BKE_cdderivedmesh.h" #include "BLI_utildefines.h" #include "BLI_math.h" #include "recast-capi.h" BM_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]); } BM_INLINE int 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 i, nv = 0; for (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]; } int buildRawVertIndicesData(DerivedMesh* dm, int *nverts_r, float **verts_r, int *ntris_r, unsigned short **tris_r, int **trisToFacesMap_r, int **recastData) { int vi, fi, triIdx; int nverts, ntris; int *trisToFacesMap; float *verts; unsigned short *tris, *tri; int nfaces; MFace *faces; nverts = dm->getNumVerts(dm); if (nverts>=0xffff) { printf("Converting navmesh: Error! Too many vertices. Max number of vertices %d\n", 0xffff); return 0; } verts = MEM_callocN(sizeof(float)*3*nverts, "buildRawVertIndicesData verts"); dm->getVertCos(dm, (float(*)[3])verts); //flip coordinates for (vi=0; vigetNumFaces(dm); faces = dm->getFaceArray(dm); ntris = nfaces; for (fi=0; fiv4) ntris++; } //copy and transform to triangles (reorder on the run) trisToFacesMap = MEM_callocN(sizeof(int)*ntris, "buildRawVertIndicesData trisToFacesMap"); tris = MEM_callocN(sizeof(unsigned short)*3*ntris, "buildRawVertIndicesData tris"); tri = tris; triIdx = 0; for (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); *nverts_r = nverts; *verts_r = verts; *ntris_r = ntris; *tris_r = tris; *trisToFacesMap_r = trisToFacesMap; return 1; } int 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 polyidx; int capacity = vertsPerPoly; unsigned short* newPoly = MEM_callocN(sizeof(unsigned short)*capacity, "buildPolygonsByDetailedMeshes newPoly"); memset(newPoly, 0xff, sizeof(unsigned short)*capacity); for (polyidx=0; polyidxtolerance) adjustedPoly[adjustedNv++] = cur; } memcpy(newPoly, adjustedPoly, adjustedNv*sizeof(unsigned short)); MEM_freeN(adjustedPoly); nv = adjustedNv; allBorderTraversed = 1; for (i=0; irecastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)a]] - ((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int*)b]] ); } 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; i0) { 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