aboutsummaryrefslogtreecommitdiff
path: root/dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp')
-rw-r--r--dep/recastnavigation/Detour/DetourNavMeshBuilder.cpp341
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 = &params->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 = &params->offMeshConVerts[(i*2+0)*3];
- const float* p1 = &params->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(&params->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax);
+ offMeshConClass[i*2+1] = classifyOffMeshPoint(&params->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 = &params->verts[p[j]*3];
+ const unsigned short* vb = &params->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 = &params->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 = &params->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 = &params->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], &params->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 = &params->verts[poly->verts[j]*3];
+ const unsigned short* vb = &params->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], &params->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;