int polyIsConvex(const unsigned short *p, const int vertsPerPoly, const float *verts) { int j, nv = polyNumVerts(p, vertsPerPoly); if (nv < 3) return 0; for (j = 0; j < nv; j++) { const float *v = &verts[3 * p[j]]; const float *v_next = &verts[3 * p[(j + 1) % nv]]; const float *v_prev = &verts[3 * p[(nv + j - 1) % nv]]; if (!left(v_prev, v, v_next)) return 0; } return 1; }
bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts, unsigned short* &polys, int& npolys, unsigned short *&dmeshes, float *&dvertices, int &ndvertsuniq, unsigned short *&dtris, int& ndtris, int &vertsPerPoly) { DerivedMesh* dm = mesh_create_derived_no_virtual(GetScene()->GetBlenderScene(), GetBlenderObject(), NULL, CD_MASK_MESH); CustomData *pdata = dm->getPolyDataLayout(dm); int* recastData = (int*) CustomData_get_layer(pdata, CD_RECAST); if (recastData) { int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL; int nAllVerts = 0; float *allVerts = NULL; buildNavMeshDataByDerivedMesh(dm, &vertsPerPoly, &nAllVerts, &allVerts, &ndtris, &dtris, &npolys, &dmeshes, &polys, &dtrisToPolysMap, &dtrisToTrisMap, &trisToFacesMap); MEM_SAFE_FREE(dtrisToPolysMap); MEM_SAFE_FREE(dtrisToTrisMap); MEM_SAFE_FREE(trisToFacesMap); unsigned short *verticesMap = (unsigned short *)MEM_mallocN(sizeof(*verticesMap) * nAllVerts, __func__); memset(verticesMap, 0xff, sizeof(*verticesMap) * nAllVerts); int curIdx = 0; //vertices - mesh verts //iterate over all polys and create map for their vertices first... for (int polyidx=0; polyidx<npolys; polyidx++) { unsigned short* poly = &polys[polyidx*vertsPerPoly*2]; for (int i=0; i<vertsPerPoly; i++) { unsigned short idx = poly[i]; if (idx==0xffff) break; if (verticesMap[idx]==0xffff) { verticesMap[idx] = curIdx++; } poly[i] = verticesMap[idx]; } } nverts = curIdx; //...then iterate over detailed meshes //transform indices to local ones (for each navigation polygon) for (int polyidx=0; polyidx<npolys; polyidx++) { unsigned short *poly = &polys[polyidx*vertsPerPoly*2]; int nv = polyNumVerts(poly, vertsPerPoly); unsigned short *dmesh = &dmeshes[4*polyidx]; unsigned short tribase = dmesh[2]; unsigned short trinum = dmesh[3]; unsigned short vbase = curIdx; for (int j=0; j<trinum; j++) { unsigned short* dtri = &dtris[(tribase+j)*3*2]; for (int k=0; k<3; k++) { int newVertexIdx = verticesMap[dtri[k]]; if (newVertexIdx==0xffff) { newVertexIdx = curIdx++; verticesMap[dtri[k]] = newVertexIdx; } if (newVertexIdx<nverts) { //it's polygon vertex ("shared") int idxInPoly = polyFindVertex(poly, vertsPerPoly, newVertexIdx); if (idxInPoly==-1) { printf("Building NavMeshObject: Error! Can't find vertex in polygon\n"); return false; } dtri[k] = idxInPoly; } else { dtri[k] = newVertexIdx - vbase + nv; } } } dmesh[0] = vbase-nverts; //verts base dmesh[1] = curIdx-vbase; //verts num } vertices = new float[nverts*3]; ndvertsuniq = curIdx - nverts; if (ndvertsuniq>0) { dvertices = new float[ndvertsuniq*3]; } for (int vi=0; vi<nAllVerts; vi++) { int newIdx = verticesMap[vi]; if (newIdx!=0xffff) { if (newIdx<nverts) { //navigation mesh vertex memcpy(vertices+3*newIdx, allVerts+3*vi, 3*sizeof(float)); } else { //detailed mesh vertex memcpy(dvertices+3*(newIdx-nverts), allVerts+3*vi, 3*sizeof(float)); } } } MEM_SAFE_FREE(allVerts); MEM_freeN(verticesMap); } else { //create from RAS_MeshObject (detailed mesh is fake) RAS_MeshObject* meshobj = GetMesh(0); vertsPerPoly = 3; nverts = meshobj->m_sharedvertex_map.size(); if (nverts >= 0xffff) return false; //calculate count of tris int nmeshpolys = meshobj->NumPolygons(); npolys = nmeshpolys; for (int p=0; p<nmeshpolys; p++) { int vertcount = meshobj->GetPolygon(p)->VertexCount(); npolys+=vertcount-3; } //create verts vertices = new float[nverts*3]; float* vert = vertices; for (int vi=0; vi<nverts; vi++) { const float* pos = !meshobj->m_sharedvertex_map[vi].empty() ? meshobj->GetVertexLocation(vi) : NULL; if (pos) copy_v3_v3(vert, pos); else { memset(vert, 0, 3*sizeof(float)); //vertex isn't in any poly, set dummy zero coordinates } vert+=3; } //create tris polys = (unsigned short *)MEM_callocN(sizeof(unsigned short)*3*2*npolys, "BuildVertIndArrays polys"); memset(polys, 0xff, sizeof(unsigned short)*3*2*npolys); unsigned short *poly = polys; RAS_Polygon* raspoly; for (int p=0; p<nmeshpolys; p++) { raspoly = meshobj->GetPolygon(p); for (int v=0; v<raspoly->VertexCount()-2; v++) { poly[0] = raspoly->GetVertex(0)->getOrigIndex(); for (size_t i=1; i<3; i++) { poly[i] = raspoly->GetVertex(v+i)->getOrigIndex(); } poly += 6; } } dmeshes = NULL; dvertices = NULL; ndvertsuniq = 0; dtris = NULL; ndtris = npolys; } dm->release(dm); return true; }