diff options
Diffstat (limited to 'dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp')
-rw-r--r-- | dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp | 341 |
1 files changed, 149 insertions, 192 deletions
diff --git a/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp b/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp index 9d8471b96a1..fcac215fff4 100644 --- a/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp +++ b/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp @@ -261,6 +261,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, return false; if (!params->polyCount || !params->polys) return false; + if (!params->detailMeshes || !params->detailVerts || !params->detailTris) + return false; const int nvp = params->nvp; @@ -276,50 +278,10 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, if (!offMeshConClass) return false; - // Find tight heigh bounds, used for culling out off-mesh start locations. - float hmin = FLT_MAX; - float hmax = -FLT_MAX; - - if (params->detailVerts && params->detailVertsCount) - { - for (int i = 0; i < params->detailVertsCount; ++i) - { - const float h = params->detailVerts[i*3+1]; - hmin = dtMin(hmin,h); - hmax = dtMax(hmax,h); - } - } - else - { - for (int i = 0; i < params->vertCount; ++i) - { - const unsigned short* iv = ¶ms->verts[i*3]; - const float h = params->bmin[1] + iv[1] * params->ch; - hmin = dtMin(hmin,h); - hmax = dtMax(hmax,h); - } - } - hmin -= params->walkableClimb; - hmax += params->walkableClimb; - float bmin[3], bmax[3]; - dtVcopy(bmin, params->bmin); - dtVcopy(bmax, params->bmax); - bmin[1] = hmin; - bmax[1] = hmax; - for (int i = 0; i < params->offMeshConCount; ++i) { - const float* p0 = ¶ms->offMeshConVerts[(i*2+0)*3]; - const float* p1 = ¶ms->offMeshConVerts[(i*2+1)*3]; - offMeshConClass[i*2+0] = classifyOffMeshPoint(p0, bmin, bmax); - offMeshConClass[i*2+1] = classifyOffMeshPoint(p1, bmin, bmax); - - // Zero out off-mesh start positions which are not even potentially touching the mesh. - if (offMeshConClass[i*2+0] == 0xff) - { - if (p0[1] < bmin[1] || p0[1] > bmax[1]) - offMeshConClass[i*2+0] = 0; - } + offMeshConClass[i*2+0] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax); + offMeshConClass[i*2+1] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax); // Cound how many links should be allocated for off-mesh connections. if (offMeshConClass[i*2+0] == 0xff) @@ -345,13 +307,23 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, for (int j = 0; j < nvp; ++j) { if (p[j] == MESH_NULL_IDX) break; + int nj = j+1; + if (nj >= nvp || p[nj] == MESH_NULL_IDX) nj = 0; + const unsigned short* va = ¶ms->verts[p[j]*3]; + const unsigned short* vb = ¶ms->verts[p[nj]*3]; + edgeCount++; - if (p[nvp+j] & 0x8000) + if (params->tileSize > 0) { - unsigned short dir = p[nvp+j] & 0xf; - if (dir != 0xf) - portalCount++; + if (va[0] == params->tileSize && vb[0] == params->tileSize) + portalCount++; // x+ + else if (va[2] == params->tileSize && vb[2] == params->tileSize) + portalCount++; // z+ + else if (va[0] == 0 && vb[0] == 0) + portalCount++; // x- + else if (va[2] == 0 && vb[2] == 0) + portalCount++; // z- } } } @@ -360,41 +332,18 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, // Find unique detail vertices. int uniqueDetailVertCount = 0; - int detailTriCount = 0; - if (params->detailMeshes) - { - // Has detail mesh, count unique detail vertex count and use input detail tri count. - detailTriCount = params->detailTriCount; - for (int i = 0; i < params->polyCount; ++i) - { - const unsigned short* p = ¶ms->polys[i*nvp*2]; - int ndv = params->detailMeshes[i*4+1]; - int nv = 0; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - nv++; - } - ndv -= nv; - uniqueDetailVertCount += ndv; - } - } - else + for (int i = 0; i < params->polyCount; ++i) { - // No input detail mesh, build detail mesh from nav polys. - uniqueDetailVertCount = 0; // No extra detail verts. - detailTriCount = 0; - for (int i = 0; i < params->polyCount; ++i) + const unsigned short* p = ¶ms->polys[i*nvp*2]; + int ndv = params->detailMeshes[i*4+1]; + int nv = 0; + for (int j = 0; j < nvp; ++j) { - const unsigned short* p = ¶ms->polys[i*nvp*2]; - int nv = 0; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - nv++; - } - detailTriCount += nv-2; + if (p[j] == MESH_NULL_IDX) break; + nv++; } + ndv -= nv; + uniqueDetailVertCount += ndv; } // Calculate data size @@ -404,8 +353,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, const int linksSize = dtAlign4(sizeof(dtLink)*maxLinkCount); const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount); const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount); - const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*detailTriCount); - const int bvTreeSize = params->buildBvTree ? dtAlign4(sizeof(dtBVNode)*params->polyCount*2) : 0; + const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*params->detailTriCount); + const int bvTreeSize = dtAlign4(sizeof(dtBVNode)*params->polyCount*2); const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount); const int dataSize = headerSize + vertsSize + polysSize + linksSize + @@ -437,7 +386,6 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, header->version = DT_NAVMESH_VERSION; header->x = params->tileX; header->y = params->tileY; - header->layer = params->tileLayer; header->userId = params->userId; header->polyCount = totPolyCount; header->vertCount = totVertCount; @@ -446,14 +394,14 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, dtVcopy(header->bmax, params->bmax); header->detailMeshCount = params->polyCount; header->detailVertCount = uniqueDetailVertCount; - header->detailTriCount = detailTriCount; + header->detailTriCount = params->detailTriCount; header->bvQuantFactor = 1.0f / params->cs; header->offMeshBase = params->polyCount; header->walkableHeight = params->walkableHeight; header->walkableRadius = params->walkableRadius; header->walkableClimb = params->walkableClimb; header->offMeshConCount = storedOffMeshConCount; - header->bvNodeCount = params->buildBvTree ? params->polyCount*2 : 0; + header->bvNodeCount = params->polyCount*2; const int offMeshVertsBase = params->vertCount; const int offMeshPolyBase = params->polyCount; @@ -497,27 +445,7 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, { if (src[j] == MESH_NULL_IDX) break; p->verts[j] = src[j]; - if (src[nvp+j] & 0x8000) - { - // Border or portal edge. - unsigned short dir = src[nvp+j] & 0xf; - if (dir == 0xf) // Border - p->neis[j] = 0; - else if (dir == 0) // Portal x- - p->neis[j] = DT_EXT_LINK | 4; - else if (dir == 1) // Portal z+ - p->neis[j] = DT_EXT_LINK | 2; - else if (dir == 2) // Portal x+ - p->neis[j] = DT_EXT_LINK | 0; - else if (dir == 3) // Portal z- - p->neis[j] = DT_EXT_LINK | 6; - } - else - { - // Normal connection - p->neis[j] = src[nvp+j]+1; - } - + p->neis[j] = (src[nvp+j]+1) & 0xffff; p->vertCount++; } src += nvp*2; @@ -539,68 +467,61 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, n++; } } - - // Store detail meshes and vertices. - // The nav polygon vertices are stored as the first vertices on each mesh. - // We compress the mesh data by skipping them and using the navmesh coordinates. - if (params->detailMeshes) + + // Store portal edges. + if (params->tileSize > 0) { - unsigned short vbase = 0; for (int i = 0; i < params->polyCount; ++i) { - dtPolyDetail& dtl = navDMeshes[i]; - const int vb = (int)params->detailMeshes[i*4+0]; - const int ndv = (int)params->detailMeshes[i*4+1]; - const int nv = navPolys[i].vertCount; - dtl.vertBase = (unsigned int)vbase; - dtl.vertCount = (unsigned char)(ndv-nv); - dtl.triBase = (unsigned int)params->detailMeshes[i*4+2]; - dtl.triCount = (unsigned char)params->detailMeshes[i*4+3]; - // Copy vertices except the first 'nv' verts which are equal to nav poly verts. - if (ndv-nv) + dtPoly* poly = &navPolys[i]; + for (int j = 0; j < poly->vertCount; ++j) { - memcpy(&navDVerts[vbase*3], ¶ms->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv)); - vbase += (unsigned short)(ndv-nv); + int nj = j+1; + if (nj >= poly->vertCount) nj = 0; + + const unsigned short* va = ¶ms->verts[poly->verts[j]*3]; + const unsigned short* vb = ¶ms->verts[poly->verts[nj]*3]; + + if (va[0] == params->tileSize && vb[0] == params->tileSize) // x+ + poly->neis[j] = DT_EXT_LINK | 0; + else if (va[2] == params->tileSize && vb[2] == params->tileSize) // z+ + poly->neis[j] = DT_EXT_LINK | 2; + else if (va[0] == 0 && vb[0] == 0) // x- + poly->neis[j] = DT_EXT_LINK | 4; + else if (va[2] == 0 && vb[2] == 0) // z- + poly->neis[j] = DT_EXT_LINK | 6; } } - // Store triangles. - memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount); } - else + + // Store detail meshes and vertices. + // The nav polygon vertices are stored as the first vertices on each mesh. + // We compress the mesh data by skipping them and using the navmesh coordinates. + unsigned short vbase = 0; + for (int i = 0; i < params->polyCount; ++i) { - // Create dummy detail mesh by triangulating polys. - int tbase = 0; - for (int i = 0; i < params->polyCount; ++i) + dtPolyDetail& dtl = navDMeshes[i]; + const int vb = (int)params->detailMeshes[i*4+0]; + const int ndv = (int)params->detailMeshes[i*4+1]; + const int nv = navPolys[i].vertCount; + dtl.vertBase = (unsigned int)vbase; + dtl.vertCount = (unsigned char)(ndv-nv); + dtl.triBase = (unsigned int)params->detailMeshes[i*4+2]; + dtl.triCount = (unsigned char)params->detailMeshes[i*4+3]; + // Copy vertices except the first 'nv' verts which are equal to nav poly verts. + if (ndv-nv) { - dtPolyDetail& dtl = navDMeshes[i]; - const int nv = navPolys[i].vertCount; - dtl.vertBase = 0; - dtl.vertCount = 0; - dtl.triBase = (unsigned int)tbase; - dtl.triCount = (unsigned char)(nv-2); - // Triangulate polygon (local indices). - for (int j = 2; j < nv; ++j) - { - unsigned char* t = &navDTris[tbase*4]; - t[0] = 0; - t[1] = (unsigned char)(j-1); - t[2] = (unsigned char)j; - // Bit for each edge that belongs to poly boundary. - t[3] = (1<<2); - if (j == 2) t[3] |= (1<<0); - if (j == nv-1) t[3] |= (1<<4); - tbase++; - } + memcpy(&navDVerts[vbase*3], ¶ms->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv)); + vbase += (unsigned short)(ndv-nv); } } + // Store triangles. + memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount); // Store and create BVtree. // TODO: take detail mesh into account! use byte per bbox extent? - if (params->buildBvTree) - { - createBVTree(params->verts, params->vertCount, params->polys, params->polyCount, - nvp, params->cs, params->ch, params->polyCount*2, navBvtree); - } + createBVTree(params->verts, params->vertCount, params->polys, params->polyCount, + nvp, params->cs, params->ch, params->polyCount*2, navBvtree); // Store Off-Mesh connections. n = 0; @@ -632,14 +553,51 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, return true; } +inline void swapByte(unsigned char* a, unsigned char* b) +{ + unsigned char tmp = *a; + *a = *b; + *b = tmp; +} + +inline void swapEndian(unsigned short* v) +{ + unsigned char* x = (unsigned char*)v; + swapByte(x+0, x+1); +} + +inline void swapEndian(short* v) +{ + unsigned char* x = (unsigned char*)v; + swapByte(x+0, x+1); +} + +inline void swapEndian(unsigned int* v) +{ + unsigned char* x = (unsigned char*)v; + swapByte(x+0, x+3); swapByte(x+1, x+2); +} + +inline void swapEndian(int* v) +{ + unsigned char* x = (unsigned char*)v; + swapByte(x+0, x+3); swapByte(x+1, x+2); +} + +inline void swapEndian(float* v) +{ + unsigned char* x = (unsigned char*)v; + swapByte(x+0, x+3); swapByte(x+1, x+2); +} + bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/) { dtMeshHeader* header = (dtMeshHeader*)data; int swappedMagic = DT_NAVMESH_MAGIC; int swappedVersion = DT_NAVMESH_VERSION; - dtSwapEndian(&swappedMagic); - dtSwapEndian(&swappedVersion); + swapEndian(&swappedMagic); + swapEndian(&swappedVersion); if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) && (header->magic != swappedMagic || header->version != swappedVersion)) @@ -647,31 +605,30 @@ bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/) return false; } - dtSwapEndian(&header->magic); - dtSwapEndian(&header->version); - dtSwapEndian(&header->x); - dtSwapEndian(&header->y); - dtSwapEndian(&header->layer); - dtSwapEndian(&header->userId); - dtSwapEndian(&header->polyCount); - dtSwapEndian(&header->vertCount); - dtSwapEndian(&header->maxLinkCount); - dtSwapEndian(&header->detailMeshCount); - dtSwapEndian(&header->detailVertCount); - dtSwapEndian(&header->detailTriCount); - dtSwapEndian(&header->bvNodeCount); - dtSwapEndian(&header->offMeshConCount); - dtSwapEndian(&header->offMeshBase); - dtSwapEndian(&header->walkableHeight); - dtSwapEndian(&header->walkableRadius); - dtSwapEndian(&header->walkableClimb); - dtSwapEndian(&header->bmin[0]); - dtSwapEndian(&header->bmin[1]); - dtSwapEndian(&header->bmin[2]); - dtSwapEndian(&header->bmax[0]); - dtSwapEndian(&header->bmax[1]); - dtSwapEndian(&header->bmax[2]); - dtSwapEndian(&header->bvQuantFactor); + swapEndian(&header->magic); + swapEndian(&header->version); + swapEndian(&header->x); + swapEndian(&header->y); + swapEndian(&header->userId); + swapEndian(&header->polyCount); + swapEndian(&header->vertCount); + swapEndian(&header->maxLinkCount); + swapEndian(&header->detailMeshCount); + swapEndian(&header->detailVertCount); + swapEndian(&header->detailTriCount); + swapEndian(&header->bvNodeCount); + swapEndian(&header->offMeshConCount); + swapEndian(&header->offMeshBase); + swapEndian(&header->walkableHeight); + swapEndian(&header->walkableRadius); + swapEndian(&header->walkableClimb); + swapEndian(&header->bmin[0]); + swapEndian(&header->bmin[1]); + swapEndian(&header->bmin[2]); + swapEndian(&header->bmax[0]); + swapEndian(&header->bmax[1]); + swapEndian(&header->bmax[2]); + swapEndian(&header->bvQuantFactor); // Freelist index and pointers are updated when tile is added, no need to swap. @@ -717,7 +674,7 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) // Vertices for (int i = 0; i < header->vertCount*3; ++i) { - dtSwapEndian(&verts[i]); + swapEndian(&verts[i]); } // Polys @@ -727,10 +684,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) // poly->firstLink is update when tile is added, no need to swap. for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j) { - dtSwapEndian(&p->verts[j]); - dtSwapEndian(&p->neis[j]); + swapEndian(&p->verts[j]); + swapEndian(&p->neis[j]); } - dtSwapEndian(&p->flags); + swapEndian(&p->flags); } // Links are rebuild when tile is added, no need to swap. @@ -739,14 +696,14 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) for (int i = 0; i < header->detailMeshCount; ++i) { dtPolyDetail* pd = &detailMeshes[i]; - dtSwapEndian(&pd->vertBase); - dtSwapEndian(&pd->triBase); + swapEndian(&pd->vertBase); + swapEndian(&pd->triBase); } // Detail verts for (int i = 0; i < header->detailVertCount*3; ++i) { - dtSwapEndian(&detailVerts[i]); + swapEndian(&detailVerts[i]); } // BV-tree @@ -755,10 +712,10 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) dtBVNode* node = &bvTree[i]; for (int j = 0; j < 3; ++j) { - dtSwapEndian(&node->bmin[j]); - dtSwapEndian(&node->bmax[j]); + swapEndian(&node->bmin[j]); + swapEndian(&node->bmax[j]); } - dtSwapEndian(&node->i); + swapEndian(&node->i); } // Off-mesh Connections. @@ -766,9 +723,9 @@ bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) { dtOffMeshConnection* con = &offMeshCons[i]; for (int j = 0; j < 6; ++j) - dtSwapEndian(&con->pos[j]); - dtSwapEndian(&con->rad); - dtSwapEndian(&con->poly); + swapEndian(&con->pos[j]); + swapEndian(&con->rad); + swapEndian(&con->poly); } return true; |