Changed Detour header var names more to verbose. Pass params as a struct to dtCreateNavMeshData. Named Off-mesh links to Off-mesh connections. Cleaned up Off-mesh connection code and samples. Added connection radius and direction to Off-mesh connections. Agent dimensions passed store in navmesh header.

This commit is contained in:
Mikko Mononen 2010-01-19 14:22:48 +00:00
parent da9dec1eef
commit 3abbfe006d
24 changed files with 7358 additions and 3099 deletions

View File

@ -30,6 +30,8 @@ enum duDebugDrawPrimitives
// Abstrace debug draw interface.
struct duDebugDraw
{
virtual void depthMask(bool state) = 0;
// Begin drawing primitives.
// Params:
// prim - (in) primitive type to draw, one of rcDebugDrawPrimitives.
@ -79,7 +81,8 @@ void duDebugDrawBoxWire(struct duDebugDraw* dd, float minx, float miny, float mi
float maxx, float maxy, float maxz, unsigned int col, const float lineWidth);
void duDebugDrawArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
const float x1, const float y1, const float z1, const float h, unsigned int col, const float lineWidth);
const float x1, const float y1, const float z1, const float h,
const float as0, const float as1, unsigned int col, const float lineWidth);
void duDebugDrawCircle(struct duDebugDraw* dd, const float x, const float y, const float z,
const float r, unsigned int col, const float lineWidth);
@ -103,7 +106,8 @@ void duAppendBoxWire(struct duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz, unsigned int col);
void duAppendArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
const float x1, const float y1, const float z1, const float h, unsigned int col);
const float x1, const float y1, const float z1, const float h,
const float as0, const float as1, unsigned int col);
void duAppendCircle(struct duDebugDraw* dd, const float x, const float y, const float z,
const float r, unsigned int col);

View File

@ -21,7 +21,13 @@
#include "DetourNavMesh.h"
void duDebugDrawNavMesh(struct duDebugDraw* dd, const dtNavMesh* mesh, bool drawClosedList = false);
enum DrawNavMeshFlags
{
DU_DRAWNAVMESH_CLOSEDLIST = 0x01,
DU_DRAWNAVMESH_OFFMESHCONS = 0x02
};
void duDebugDrawNavMesh(struct duDebugDraw* dd, const dtNavMesh* mesh, unsigned char flags);
void duDebugDrawNavMeshBVTree(struct duDebugDraw* dd, const dtNavMesh* mesh);
void duDebugDrawNavMeshPoly(struct duDebugDraw* dd, const dtNavMesh* mesh, dtPolyRef ref, const unsigned int col);

View File

@ -79,10 +79,11 @@ void duDebugDrawBoxWire(struct duDebugDraw* dd, float minx, float miny, float mi
}
void duDebugDrawArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
const float x1, const float y1, const float z1, const float h, unsigned int col, const float lineWidth)
const float x1, const float y1, const float z1, const float h,
const float as0, const float as1, unsigned int col, const float lineWidth)
{
dd->begin(DU_DRAW_LINES, lineWidth);
duAppendArc(dd, x0,y0,z0, x1,y1,z1, h, col);
duAppendArc(dd, x0,y0,z0, x1,y1,z1, h, as0, as1, col);
dd->end();
}
@ -234,25 +235,98 @@ void duAppendBox(struct duDebugDraw* dd, float minx, float miny, float minz,
}
}
inline void evalArc(const float x0, const float y0, const float z0,
const float dx, const float dy, const float dz,
const float h, const float u, float* res)
{
res[0] = x0 + dx * u;
res[1] = y0 + dy * u + h * (1-(u*2-1)*(u*2-1));
res[2] = z0 + dz * u;
}
inline void vcross(float* dest, const float* v1, const float* v2)
{
dest[0] = v1[1]*v2[2] - v1[2]*v2[1];
dest[1] = v1[2]*v2[0] - v1[0]*v2[2];
dest[2] = v1[0]*v2[1] - v1[1]*v2[0];
}
inline void vnormalize(float* v)
{
float d = 1.0f / sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] *= d;
v[1] *= d;
v[2] *= d;
}
inline void vsub(float* dest, const float* v1, const float* v2)
{
dest[0] = v1[0]-v2[0];
dest[1] = v1[1]-v2[1];
dest[2] = v1[2]-v2[2];
}
void appendArrowHead(struct duDebugDraw* dd, const float* p, const float* q,
const float s, unsigned int col)
{
float ax[3], ay[3] = {0,1,0}, az[3];
vsub(az, q, p);
vnormalize(az);
vcross(ax, ay, az);
vcross(ay, az, ax);
vnormalize(ay);
dd->vertex(p, col);
// dd->vertex(p[0]+az[0]*s+ay[0]*s/2, p[1]+az[1]*s+ay[1]*s/2, p[2]+az[2]*s+ay[2]*s/2, col);
dd->vertex(p[0]+az[0]*s+ax[0]*s/3, p[1]+az[1]*s+ax[1]*s/3, p[2]+az[2]*s+ax[2]*s/3, col);
dd->vertex(p, col);
// dd->vertex(p[0]+az[0]*s-ay[0]*s/2, p[1]+az[1]*s-ay[1]*s/2, p[2]+az[2]*s-ay[2]*s/2, col);
dd->vertex(p[0]+az[0]*s-ax[0]*s/3, p[1]+az[1]*s-ax[1]*s/3, p[2]+az[2]*s-ax[2]*s/3, col);
}
void duAppendArc(struct duDebugDraw* dd, const float x0, const float y0, const float z0,
const float x1, const float y1, const float z1, const float h, unsigned int col)
const float x1, const float y1, const float z1, const float h,
const float as0, const float as1, unsigned int col)
{
static const int NUM_ARC_PTS = 8;
static const float ARC_PTS_SCALE = 1.0f / (float)NUM_ARC_PTS;
static const float PAD = 0.05f;
static const float ARC_PTS_SCALE = (1.0f-PAD*2) / (float)NUM_ARC_PTS;
const float dx = x1 - x0;
const float dy = y1 - y0;
const float dz = z1 - z0;
const float len = sqrtf(dx*dx + dy*dy + dz*dz);
float px = x0, py = y0, pz = z0;
float prev[3];
evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD, prev);
for (int i = 1; i <= NUM_ARC_PTS; ++i)
{
const float u = i * ARC_PTS_SCALE;
const float x = x0 + dx * u;
const float y = y0 + dy * u + (len*h) * (1-(u*2-1)*(u*2-1));
const float z = z0 + dz * u;
dd->vertex(px,py,pz, col);
dd->vertex(x,y,z, col);
px = x; py = y; pz = z;
const float u = PAD + i * ARC_PTS_SCALE;
float pt[3];
evalArc(x0,y0,z0, dx,dy,dz, len*h, u, pt);
dd->vertex(prev[0],prev[1],prev[2], col);
dd->vertex(pt[0],pt[1],pt[2], col);
prev[0] = pt[0]; prev[1] = pt[1]; prev[2] = pt[2];
}
// End arrows
if (as0 > 0.001f)
{
float p[3], q[3];
evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD, p);
evalArc(x0,y0,z0, dx,dy,dz, len*h, PAD+0.05f, q);
appendArrowHead(dd, p, q, as0, col);
}
if (as1 > 0.001f)
{
float p[3], q[3];
evalArc(x0,y0,z0, dx,dy,dz, len*h, 1-PAD, p);
evalArc(x0,y0,z0, dx,dy,dz, len*h, 1-(PAD+0.05f), q);
appendArrowHead(dd, p, q, as1, col);
}
}

View File

@ -16,9 +16,11 @@
// 3. This notice may not be removed or altered from any source distribution.
//
#include <math.h>
#include "DebugDraw.h"
#include "DetourDebugDraw.h"
#include "DetourNavMesh.h"
#include "DetourCommon.h"
static float distancePtLine2d(const float* pt, const float* p, const float* q)
@ -43,26 +45,26 @@ static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshHeader* header,
dd->begin(DU_DRAW_LINES, linew);
for (int i = 0; i < header->npolys; ++i)
for (int i = 0; i < header->polyCount; ++i)
{
const dtPoly* p = &header->polys[i];
if (p->flags & DT_POLY_OFFMESH_LINK) continue;
if (p->flags & DT_POLY_OFFMESH_CONNECTION) continue;
const dtPolyDetail* pd = &header->dmeshes[i];
const dtPolyDetail* pd = &header->detailMeshes[i];
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
for (int j = 0, nj = (int)p->vertCount; j < nj; ++j)
{
unsigned int c = col;
if (inner)
{
if (p->n[j] == 0) continue;
if (p->n[j] & 0x8000)
if (p->neis[j] == 0) continue;
if (p->neis[j] & DT_EXT_LINK)
{
bool con = false;
for (int k = 0; k < p->nlinks; ++k)
for (int k = 0; k < p->linkCount; ++k)
{
if (header->links[p->links+k].e == j)
if (header->links[p->linkBase+k].edge == j)
{
con = true;
break;
@ -78,24 +80,24 @@ static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshHeader* header,
}
else
{
if (p->n[j] != 0) continue;
if (p->neis[j] != 0) continue;
}
const float* v0 = &header->verts[p->v[j]*3];
const float* v1 = &header->verts[p->v[(j+1)%nj]*3];
const float* v0 = &header->verts[p->verts[j]*3];
const float* v1 = &header->verts[p->verts[(j+1) % nj]*3];
// Draw detail mesh edges which align with the actual poly edge.
// This is really slow.
for (int k = 0; k < pd->ntris; ++k)
for (int k = 0; k < pd->triCount; ++k)
{
const unsigned char* t = &header->dtris[(pd->tbase+k)*4];
const unsigned char* t = &header->detailTris[(pd->triBase+k)*4];
const float* tv[3];
for (int m = 0; m < 3; ++m)
{
if (t[m] < p->nv)
tv[m] = &header->verts[p->v[t[m]]*3];
if (t[m] < p->vertCount)
tv[m] = &header->verts[p->verts[t[m]]*3];
else
tv[m] = &header->dverts[(pd->vbase+(t[m]-p->nv))*3];
tv[m] = &header->detailVerts[(pd->vertBase+(t[m]-p->vertCount))*3];
}
for (int m = 0, n = 2; m < 3; n=m++)
{
@ -113,59 +115,88 @@ static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshHeader* header,
dd->end();
}
static void drawMeshTile(duDebugDraw* dd, const dtNavMesh* mesh, const dtMeshTile* tile, bool drawClosedList)
static void drawMeshTile(duDebugDraw* dd, const dtNavMesh* mesh, const dtMeshTile* tile, unsigned char flags)
{
const dtMeshHeader* header = tile->header;
dtPolyRef base = mesh->getTileId(tile);
dd->depthMask(false);
dd->begin(DU_DRAW_TRIS);
for (int i = 0; i < header->npolys; ++i)
for (int i = 0; i < header->polyCount; ++i)
{
const dtPoly* p = &header->polys[i];
if (p->flags & DT_POLY_OFFMESH_LINK) // Skip off-mesh links.
if (p->flags & DT_POLY_OFFMESH_CONNECTION) // Skip off-mesh links.
continue;
const dtPolyDetail* pd = &header->dmeshes[i];
const dtPolyDetail* pd = &header->detailMeshes[i];
unsigned int col;
if (drawClosedList && mesh->isInClosedList(base | (dtPolyRef)i))
if ((flags & DU_DRAWNAVMESH_CLOSEDLIST) && mesh->isInClosedList(base | (dtPolyRef)i))
col = duRGBA(255,196,0,64);
else
col = duRGBA(0,196,255,64);
for (int j = 0; j < pd->ntris; ++j)
for (int j = 0; j < pd->triCount; ++j)
{
const unsigned char* t = &header->dtris[(pd->tbase+j)*4];
const unsigned char* t = &header->detailTris[(pd->triBase+j)*4];
for (int k = 0; k < 3; ++k)
{
if (t[k] < p->nv)
dd->vertex(&header->verts[p->v[t[k]]*3], col);
if (t[k] < p->vertCount)
dd->vertex(&header->verts[p->verts[t[k]]*3], col);
else
dd->vertex(&header->dverts[(pd->vbase+t[k]-p->nv)*3], col);
dd->vertex(&header->detailVerts[(pd->vertBase+t[k]-p->vertCount)*3], col);
}
}
}
dd->end();
if (flags & DU_DRAWNAVMESH_OFFMESHCONS)
{
dd->begin(DU_DRAW_LINES, 2.0f);
for (int i = 0; i < header->npolys; ++i)
for (int i = 0; i < header->polyCount; ++i)
{
const dtPoly* p = &header->polys[i];
if ((p->flags & DT_POLY_OFFMESH_LINK) == 0) // Skip regular polys.
if ((p->flags & DT_POLY_OFFMESH_CONNECTION) == 0) // Skip regular polys.
continue;
unsigned int col;
if (drawClosedList && mesh->isInClosedList(base | (dtPolyRef)i))
if ((flags & DU_DRAWNAVMESH_CLOSEDLIST) && mesh->isInClosedList(base | (dtPolyRef)i))
col = duRGBA(255,196,0,220);
else
col = duRGBA(0,196,255,220);
col = duRGBA(255,255,255,220);
const float* va = &header->verts[p->v[0]*3];
const float* vb = &header->verts[p->v[1]*3];
const dtOffMeshConnection* con = &header->offMeshCons[i - header->offMeshBase];
const float* va = &header->verts[p->verts[0]*3];
const float* vb = &header->verts[p->verts[1]*3];
duDebugDrawArc(dd, va[0],va[1]+0.1f,va[2], vb[0],vb[1]+0.1f,vb[2], 0.25f, col, 2.0f);
// End points and their on-mesh locations.
if (con->ref[0])
{
dd->vertex(va[0],va[1],va[2], col);
dd->vertex(con->pos[0],con->pos[1],con->pos[2], col);
duAppendCircle(dd, con->pos[0],con->pos[1]+0.1f,con->pos[2], con->rad, duRGBA(0,48,64,196));
}
if (con->ref[1])
{
dd->vertex(vb[0],vb[1],vb[2], col);
dd->vertex(con->pos[3],con->pos[4],con->pos[5], col);
duAppendCircle(dd, con->pos[3],con->pos[4]+0.1f,con->pos[5], con->rad, duRGBA(0,48,64,196));
}
// End point vertices.
dd->vertex(con->pos[0],con->pos[1],con->pos[2], duRGBA(0,48,64,196));
dd->vertex(con->pos[0],con->pos[1]+0.2f,con->pos[2], duRGBA(0,48,64,196));
dd->vertex(con->pos[3],con->pos[4],con->pos[5], duRGBA(0,48,64,196));
dd->vertex(con->pos[3],con->pos[4]+0.2f,con->pos[5], duRGBA(0,48,64,196));
// Connection arc.
duAppendArc(dd, con->pos[0],con->pos[1],con->pos[2], con->pos[3],con->pos[4],con->pos[5], 0.25f,
(con->flags & 1) ? 0.6f : 0, 0.6f, col);
}
dd->end();
}
// Draw inter poly boundaries
drawPolyBoundaries(dd, header, duRGBA(0,48,64,32), 1.5f, true);
@ -175,7 +206,7 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh* mesh, const dtMeshTil
const unsigned int vcol = duRGBA(0,0,0,196);
dd->begin(DU_DRAW_POINTS, 3.0f);
for (int i = 0; i < header->nverts; ++i)
for (int i = 0; i < header->vertCount; ++i)
{
const float* v = &header->verts[i*3];
dd->vertex(v[0], v[1], v[2], vcol);
@ -262,9 +293,12 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh* mesh, const dtMeshTil
glVertex3f(p->bmin[0], p->bmin[1], header->bmin[2]+0.1f);
}
glEnd();*/
dd->depthMask(true);
}
void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh* mesh, bool drawClosedList)
void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh* mesh, unsigned char flags)
{
if (!mesh) return;
@ -272,7 +306,7 @@ void duDebugDrawNavMesh(duDebugDraw* dd, const dtNavMesh* mesh, bool drawClosedL
{
const dtMeshTile* tile = mesh->getTile(i);
if (!tile->header) continue;
drawMeshTile(dd, mesh, tile, drawClosedList);
drawMeshTile(dd, mesh, tile, flags);
}
}
@ -282,11 +316,11 @@ static void drawMeshTileBVTree(duDebugDraw* dd, const dtNavMesh* mesh, const dtM
const dtMeshHeader* header = tile->header;
// Draw BV nodes.
const float cs = 1.0f / header->bvquant;
const float cs = 1.0f / header->bvQuantFactor;
dd->begin(DU_DRAW_LINES, 1.0f);
for (int i = 0; i < header->nbvtree; ++i)
for (int i = 0; i < header->bvNodeCount; ++i)
{
const dtBVNode* n = &header->bvtree[i];
const dtBVNode* n = &header->bvTree[i];
if (n->i < 0) // Leaf indices are positive.
continue;
duAppendBoxWire(dd, header->bmin[0] + n->bmin[0]*cs,
@ -402,31 +436,43 @@ void duDebugDrawNavMeshPoly(duDebugDraw* dd, const dtNavMesh* mesh, dtPolyRef re
const dtMeshHeader* header = tile->header;
const dtPoly* p = &header->polys[ip];
dd->depthMask(false);
const unsigned int c = (col & 0x00ffffff) | (64 << 24);
if (p->flags & DT_POLY_OFFMESH_LINK)
if (p->flags & DT_POLY_OFFMESH_CONNECTION)
{
const float* va = &header->verts[p->v[0]*3];
const float* vb = &header->verts[p->v[1]*3];
duDebugDrawArc(dd, va[0],va[1]+0.1f,va[2], vb[0],vb[1]+0.1f,vb[2], 0.25f, c, 2.0f);
dtOffMeshConnection* con = &header->offMeshCons[ip - header->offMeshBase];
dd->begin(DU_DRAW_LINES, 2.0f);
// Connection arc.
duAppendArc(dd, con->pos[0],con->pos[1],con->pos[2], con->pos[3],con->pos[4],con->pos[5], 0.25f,
(con->flags & 1) ? 0.6f : 0, 0.6f, c);
dd->end();
}
else
{
const dtPolyDetail* pd = &header->dmeshes[ip];
const dtPolyDetail* pd = &header->detailMeshes[ip];
dd->begin(DU_DRAW_TRIS);
for (int i = 0; i < pd->ntris; ++i)
for (int i = 0; i < pd->triCount; ++i)
{
const unsigned char* t = &header->dtris[(pd->tbase+i)*4];
const unsigned char* t = &header->detailTris[(pd->triBase+i)*4];
for (int j = 0; j < 3; ++j)
{
if (t[j] < p->nv)
dd->vertex(&header->verts[p->v[t[j]]*3], c);
if (t[j] < p->vertCount)
dd->vertex(&header->verts[p->verts[t[j]]*3], c);
else
dd->vertex(&header->dverts[(pd->vbase+t[j]-p->nv)*3], c);
dd->vertex(&header->detailVerts[(pd->vertBase+t[j]-p->vertCount)*3], c);
}
}
dd->end();
}
dd->depthMask(true);
}

View File

@ -72,148 +72,6 @@ void duDebugDrawTriMeshSlope(duDebugDraw* dd, const float* verts, int nverts,
dd->end();
}
/*
static void drawBoxWire(duDebugDraw* dd,
float minx, float miny, float minz,
float maxx, float maxy, float maxz,
const float* col)
{
// Submits 24 vertices.
unsigned int color = duRGBAf(col[0],col[1],col[2],col[3]);
// Top
dd->vertex(minx, miny, minz, color);
dd->vertex(maxx, miny, minz, color);
dd->vertex(maxx, miny, minz, color);
dd->vertex(maxx, miny, maxz, color);
dd->vertex(maxx, miny, maxz, color);
dd->vertex(minx, miny, maxz, color);
dd->vertex(minx, miny, maxz, color);
dd->vertex(minx, miny, minz, color);
// bottom
dd->vertex(minx, maxy, minz, color);
dd->vertex(maxx, maxy, minz, color);
dd->vertex(maxx, maxy, minz, color);
dd->vertex(maxx, maxy, maxz, color);
dd->vertex(maxx, maxy, maxz, color);
dd->vertex(minx, maxy, maxz, color);
dd->vertex(minx, maxy, maxz, color);
dd->vertex(minx, maxy, minz, color);
// Sides
dd->vertex(minx, miny, minz, color);
dd->vertex(minx, maxy, minz, color);
dd->vertex(maxx, miny, minz, color);
dd->vertex(maxx, maxy, minz, color);
dd->vertex(maxx, miny, maxz, color);
dd->vertex(maxx, maxy, maxz, color);
dd->vertex(minx, miny, maxz, color);
dd->vertex(minx, maxy, maxz, color);
}
*/
/*static void drawBox(duDebugDraw* dd,
float minx, float miny, float minz,
float maxx, float maxy, float maxz,
const float* col1, const float* col2)
{
// Submits 24 vertices.
const float verts[8*3] =
{
minx, miny, minz,
maxx, miny, minz,
maxx, miny, maxz,
minx, miny, maxz,
minx, maxy, minz,
maxx, maxy, minz,
maxx, maxy, maxz,
minx, maxy, maxz,
};
static const float dim[6] =
{
0.95f, 0.55f, 0.65f, 0.85f, 0.65f, 0.85f,
};
static const unsigned char inds[6*5] =
{
0, 7, 6, 5, 4,
1, 0, 1, 2, 3,
2, 1, 5, 6, 2,
3, 3, 7, 4, 0,
4, 2, 6, 7, 3,
5, 0, 4, 5, 1,
};
const unsigned char* in = inds;
for (int i = 0; i < 6; ++i)
{
float d = dim[*in]; in++;
unsigned int color;
if (i == 0)
color = duRGBAf(d*col2[0],d*col2[1],d*col2[2], col2[3]);
else
color = duRGBAf(d*col1[0],d*col1[1],d*col1[2], col1[3]);
dd->vertex(&verts[*in*3], color); in++;
dd->vertex(&verts[*in*3], color); in++;
dd->vertex(&verts[*in*3], color); in++;
dd->vertex(&verts[*in*3], color); in++;
}
}
void duDebugDrawCylinderWire(duDebugDraw* dd, float minx, float miny, float minz,
float maxx, float maxy, float maxz,
const float* col)
{
static const int NUM_SEG = 16;
float dir[NUM_SEG*2];
for (int i = 0; i < NUM_SEG; ++i)
{
const float a = (float)i/(float)NUM_SEG*(float)M_PI*2;
dir[i*2] = cosf(a);
dir[i*2+1] = sinf(a);
}
const float cx = (maxx + minx)/2;
const float cz = (maxz + minz)/2;
const float rx = (maxx - minx)/2;
const float rz = (maxz - minz)/2;
unsigned int color = duRGBAf(col[0],col[1],col[2],col[3]);
dd->begin(DU_DRAW_LINES);
for (int i = 0, j=NUM_SEG-1; i < NUM_SEG; j=i++)
{
dd->vertex(cx+dir[j*2+0]*rx, miny, cz+dir[j*2+1]*rz, color);
dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, color);
dd->vertex(cx+dir[j*2+0]*rx, maxy, cz+dir[j*2+1]*rz, color);
dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, color);
}
for (int i = 0; i < NUM_SEG; i += NUM_SEG/4)
{
dd->vertex(cx+dir[i*2+0]*rx, miny, cz+dir[i*2+1]*rz, color);
dd->vertex(cx+dir[i*2+0]*rx, maxy, cz+dir[i*2+1]*rz, color);
}
dd->end();
}
void duDebugDrawBoxWire(duDebugDraw* dd, float minx, float miny, float minz, float maxx, float maxy, float maxz, const float* col)
{
dd->begin(DU_DRAW_LINES, 1.0f);
drawBoxWire(dd, minx, miny, minz, maxx, maxy, maxz, col);
dd->end();
}
void duDebugDrawBox(duDebugDraw* dd, float minx, float miny, float minz, float maxx, float maxy, float maxz,
const float* col1, const float* col2)
{
dd->begin(DU_DRAW_QUADS,24);
drawBox(dd, minx, miny, minz, maxx, maxy, maxz, col1, col2);
dd->end();
}*/
static int getSpanCount(const rcHeightfield& hf)
{
const int w = hf.width;
@ -433,6 +291,7 @@ static const rcContour* findContourFromSet(const rcContourSet& cset, unsigned sh
return 0;
}
/*
static const int NUM_ADU_PTS = 8;
void drawArc(duDebugDraw* dd, const float* p0, const float* p1, unsigned int color)
@ -477,6 +336,7 @@ void duDebugDrawCross(struct duDebugDraw* dd, const float* p, const float s, con
dd->vertex(p[0],p[1]+dy,p[2]+s, color);
dd->end();
}
*/
void duDebugDrawRegionConnections(duDebugDraw* dd, const rcContourSet& cset, const float alpha)
{
@ -503,7 +363,7 @@ void duDebugDrawRegionConnections(duDebugDraw* dd, const rcContourSet& cset, con
if (cont2)
{
getContourCenter(cont2, orig, cs, ch, pos2);
drawArc(dd, pos, pos2, color);
duAppendArc(dd, pos[0],pos[1],pos[2], pos2[0],pos2[1],pos2[2], 0.25f, 0.6f, 0.6f, color);
}
}
}

View File

@ -171,6 +171,15 @@ inline bool checkOverlapBox(const unsigned short amin[3], const unsigned short a
return overlap;
}
inline bool overlapBounds(const float* amin, const float* amax, const float* bmin, const float* bmax)
{
bool overlap = true;
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap;
overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap;
return overlap;
}
void closestPtPointTriangle(float* closest, const float* p,
const float* a, const float* b, const float* c);

View File

@ -28,34 +28,36 @@ static const int DT_VERTS_PER_POLYGON = 6;
static const int DT_NAVMESH_MAGIC = 'DNAV';
static const int DT_NAVMESH_VERSION = 2;
static const unsigned char DT_POLY_OFFMESH_LINK = 1;
static const unsigned char DT_POLY_OFFMESH_CONNECTION = 1;
static const unsigned short DT_EXT_LINK = 0x8000;
// Structure describing the navigation polygon data.
struct dtPoly
{
unsigned short v[DT_VERTS_PER_POLYGON]; // Indices to vertices of the poly.
unsigned short n[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly.
unsigned short links; // Base index to header 'links' array.
unsigned char nlinks; // Number of links for
unsigned char nv; // Number of vertices.
unsigned short verts[DT_VERTS_PER_POLYGON]; // Indices to vertices of the poly.
unsigned short neis[DT_VERTS_PER_POLYGON]; // Refs to neighbours of the poly.
unsigned short linkBase; // Base index to header 'links' array.
unsigned char linkCount; // Number of links for
unsigned char vertCount; // Number of vertices.
unsigned char flags; // Flags.
};
// Stucture describing polygon detail triangles.
struct dtPolyDetail
{
unsigned short vbase; // Offset to detail vertex array.
unsigned short nverts; // Number of vertices in the detail mesh.
unsigned short tbase; // Offset to detail triangle array.
unsigned short ntris; // Number of triangles.
unsigned short vertBase; // Offset to detail vertex array.
unsigned short vertCount; // Number of vertices in the detail mesh.
unsigned short triBase; // Offset to detail triangle array.
unsigned short triCount; // Number of triangles.
};
// Stucture describing a link to another polygon.
struct dtLink
{
dtPolyRef ref; // Neighbour reference.
unsigned short p; // Index to polygon which owns this link.
unsigned char e; // Index to polygon edge which owns this link.
unsigned short poly; // Index to polygon which owns this link.
unsigned char edge; // Index to polygon edge which owns this link.
unsigned char side; // If boundary link, defines on which side the link is.
unsigned char bmin, bmax; // If boundary link, defines the sub edge area.
};
@ -66,37 +68,43 @@ struct dtBVNode
int i; // Index to item or if negative, escape index.
};
struct dtOffMeshLink
struct dtOffMeshConnection
{
dtPolyRef ref[2]; // Endpoint polys.
unsigned short p; // Poly Id
unsigned char side; // TODO
float pos[6]; // Both end point locations.
float rad; // Link connection radius.
dtPolyRef ref[2]; // End point polys.
unsigned short poly; // Poly Id
unsigned char flags; // Link flags
};
struct dtMeshHeader
{
int magic; // Magic number, used to identify the data.
int version; // Data version number.
int npolys; // Number of polygons in the tile.
int nverts; // Number of vertices in the tile.
int nlinks; // Number of links in the tile (will be updated when tile is added).
int maxlinks; // Number of allocated links.
int ndmeshes; // Number of detail meshes.
int ndverts; // Number of detail vertices.
int ndtris; // Number of detail triangles.
int nbvtree; // Number of BVtree nodes.
int nomlinks; // Number of Off-Mesh links.
int nombase; // Index to first polygon which is Off-Mesh link.
int polyCount; // Number of polygons in the tile.
int vertCount; // Number of vertices in the tile.
int linkCount; // Number of links in the tile (will be updated when tile is added).
int maxLinkCount; // Number of allocated links.
int detailMeshCount; // Number of detail meshes.
int detailVertCount; // Number of detail vertices.
int detailTriCount; // Number of detail triangles.
int bvNodeCount; // Number of BVtree nodes.
int offMeshConCount; // Number of Off-Mesh links.
int offMeshBase; // Index to first polygon which is Off-Mesh link.
float walkableHeight;
float walkableRadius;
float walkableClimb;
float bmin[3], bmax[3]; // Bounding box of the tile.
float bvquant; // BVtree quantization factor (world to bvnode coords)
float bvQuantFactor; // BVtree quantization factor (world to bvnode coords)
dtPoly* polys; // Pointer to the polygons (will be updated when tile is added).
float* verts; // Pointer to the vertices (will be updated when tile added).
dtLink* links; // Pointer to the links (will be updated when tile added).
dtPolyDetail* dmeshes; // Pointer to detail meshes (will be updated when tile added).
float* dverts; // Pointer to detail vertices (will be updated when tile added).
unsigned char* dtris; // Pointer to detail triangles (will be updated when tile added).
dtBVNode* bvtree; // Pointer to BVtree nodes (will be updated when tile added).
dtOffMeshLink* omlinks; // Pointer to Off-Mesh links. (will be updated when tile added).
dtPolyDetail* detailMeshes; // Pointer to detail meshes (will be updated when tile added).
float* detailVerts; // Pointer to detail vertices (will be updated when tile added).
unsigned char* detailTris; // Pointer to detail triangles (will be updated when tile added).
dtBVNode* bvTree; // Pointer to BVtree nodes (will be updated when tile added).
dtOffMeshConnection* offMeshCons; // Pointer to Off-Mesh links. (will be updated when tile added).
};
struct dtMeshTile
@ -115,7 +123,7 @@ enum dtStraightPathFlags
{
DT_STRAIGHTPATH_START = 0x01, // The vertex is the start position.
DT_STRAIGHTPATH_END = 0x02, // The vertex is the end position.
DT_STRAIGHTPATH_OFFMESH_LINK = 0x04, // The vertex is start of an off-mesh link.
DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, // The vertex is start of an off-mesh link.
};
class dtNavMesh
@ -129,13 +137,12 @@ public:
// orig - (in) origin of the nav mesh tile space.
// tileWidth - (in) width of each tile.
// tileHeight - (in) height of each tile.
// portalheight - (in) height of the portal region between tiles.
// maxTiles - (in) maximum number of tiles the navmesh can contain*.
// maxPolys - (in) maximum number of polygons each tile can contain*.
// maxNodes - (in) maximum number of A* nodes to use*.
// *) Will be rounded to next power of two.
// Returns: True if succeed, else false.
bool init(const float* orig, float tileWidth, float tileHeight, float portalHeight,
bool init(const float* orig, float tileWidth, float tileHeight,
int maxTiles, int maxPolys, int maxNodes);
// Initializes the nav mesh for single tile use.
@ -197,8 +204,9 @@ public:
// Params:
// center - (in) The center of the search box.
// extents - (in) The extents of the search box.
// nearestPt - (out, opt) The nearest point on found polygon, null if not needed.
// Returns: Reference identifier for the polygon, or 0 if no polygons found.
dtPolyRef findNearestPoly(const float* center, const float* extents);
dtPolyRef findNearestPoly(const float* center, const float* extents, float* nearestPt);
// Returns polygons which touch the query box.
// Params:
@ -312,7 +320,7 @@ public:
// startPos - (out) start point of the link.
// endPos - (out) end point of the link.
// Returns: true if link is found.
bool getOffMeshLinkPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
bool getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const;
// Returns height of the polygon at specified location.
// Params:
@ -379,7 +387,6 @@ private:
float m_orig[3]; // Origin of the tile (0,0)
float m_tileWidth, m_tileHeight; // Dimensions of each tile.
float m_portalHeight; // Extra height value used to connect portals.
int m_maxTiles; // Max number of tiles.
int m_tileLutSize; // Tile hash lookup size (must be pot).
int m_tileLutMask; // Tile hash lookup mask.

View File

@ -19,12 +19,36 @@
#ifndef DETOURNAVMESHBUILDER_H
#define DETOURNAVMESHBUILDER_H
bool dtCreateNavMeshData(const unsigned short* verts, const int nverts,
const unsigned short* polys, const int npolys, const int nvp,
const unsigned short* dmeshes, const float* dverts, const int ndverts,
const unsigned char* dtris, const int ndtris,
const float* omverts, const int nomlinks,
const float* bmin, const float* bmax, float cs, float ch, int tileSize, int walkableClimb,
unsigned char** outData, int* outDataSize);
struct dtNavMeshCreateParams
{
// Navmesh vertices.
const unsigned short* verts;
int vertCount;
// Navmesh polygons
const unsigned short* polys;
int polyCount;
int nvp;
// Navmesh Detail
const unsigned short* detailMeshes;
const float* detailVerts;
int detailVertsCount;
const unsigned char* detailTris;
int detailTriCount;
// Off-Mesh Connections.
const float* offMeshConVerts;
const float* offMeshConRad;
const unsigned char* offMeshConDir;
int offMeshConCount;
// Settings
float walkableHeight;
float walkableRadius;
float walkableClimb;
float bmin[3], bmax[3];
float cs;
float ch;
int tileSize;
};
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize);
#endif // DETOURNAVMESHBUILDER_H

View File

@ -25,8 +25,6 @@
#include "DetourCommon.h"
static const unsigned short EXT_LINK = 0x8000;
inline int opposite(int side) { return (side+2) & 0x3; }
inline bool overlapBoxes(const float* amin, const float* amax,
@ -82,7 +80,6 @@ inline int computeTileHash(int x, int y, const int mask)
dtNavMesh::dtNavMesh() :
m_tileWidth(0),
m_tileHeight(0),
m_portalHeight(0),
m_maxTiles(0),
m_tileLutSize(0),
m_tileLutMask(0),
@ -120,13 +117,12 @@ dtNavMesh::~dtNavMesh()
delete [] m_tiles;
}
bool dtNavMesh::init(const float* orig, float tileWidth, float tileHeight, float portalHeight,
bool dtNavMesh::init(const float* orig, float tileWidth, float tileHeight,
int maxTiles, int maxPolys, int maxNodes)
{
vcopy(m_orig, orig);
m_tileWidth = tileWidth;
m_tileHeight = tileHeight;
m_portalHeight = portalHeight;
// Init tiles
m_maxTiles = maxTiles;
@ -184,7 +180,7 @@ bool dtNavMesh::init(unsigned char* data, int dataSize, bool ownsData, int maxNo
const float w = header->bmax[0] - header->bmin[0];
const float h = header->bmax[2] - header->bmin[2];
if (!init(header->bmin, w, h, 0, 1, header->npolys, maxNodes))
if (!init(header->bmin, w, h, 1, header->polyCount, maxNodes))
return false;
return addTileAt(0,0, data, dataSize, ownsData);
@ -199,26 +195,27 @@ int dtNavMesh::findConnectingPolys(const float* va, const float* vb,
dtMeshHeader* h = tile->header;
float amin[2], amax[2];
calcRect(va,vb, amin,amax, side, 0.01f, m_portalHeight);
calcRect(va,vb, amin,amax, side, 0.01f, h->walkableClimb);
// Remove links pointing to 'side' and compact the links array.
float bmin[2], bmax[2];
unsigned short m = EXT_LINK | (unsigned short)side;
unsigned short m = DT_EXT_LINK | (unsigned short)side;
int n = 0;
dtPolyRef base = getTileId(tile);
for (int i = 0; i < h->npolys; ++i)
for (int i = 0; i < h->polyCount; ++i)
{
dtPoly* poly = &h->polys[i];
for (int j = 0; j < poly->nv; ++j)
const int nv = poly->vertCount;
for (int j = 0; j < nv; ++j)
{
// Skip edges which do not point to the right side.
if (poly->n[j] != m) continue;
if (poly->neis[j] != m) continue;
// Check if the segments touch.
const float* vc = &h->verts[poly->v[j]*3];
const float* vd = &h->verts[poly->v[(j+1) % (int)poly->nv]*3];
calcRect(vc,vd, bmin,bmax, side, 0.01f, m_portalHeight);
const float* vc = &h->verts[poly->verts[j]*3];
const float* vd = &h->verts[poly->verts[(j+1) % nv]*3];
calcRect(vc,vd, bmin,bmax, side, 0.01f, h->walkableClimb);
if (!overlapRects(amin,amax, bmin,bmax)) continue;
// Add return value.
if (n < maxcon)
@ -242,17 +239,17 @@ void dtNavMesh::removeExtLinks(dtMeshTile* tile, int side)
// Remove links pointing to 'side' and compact the links array.
dtLink* pool = m_tmpLinks;
int nlinks = 0;
for (int i = 0; i < h->npolys; ++i)
for (int i = 0; i < h->polyCount; ++i)
{
dtPoly* poly = &h->polys[i];
int plinks = nlinks;
int nplinks = 0;
for (int j = 0; j < poly->nlinks; ++j)
for (int j = 0; j < poly->linkCount; ++j)
{
dtLink* link = &h->links[poly->links+j];
dtLink* link = &h->links[poly->linkBase+j];
if ((int)link->side != side)
{
if (nlinks < h->maxlinks)
if (nlinks < h->maxLinkCount)
{
dtLink* dst = &pool[nlinks++];
memcpy(dst, link, sizeof(dtLink));
@ -260,11 +257,11 @@ void dtNavMesh::removeExtLinks(dtMeshTile* tile, int side)
}
}
}
poly->links = plinks;
poly->nlinks = nplinks;
poly->linkBase = plinks;
poly->linkCount = nplinks;
}
h->nlinks = nlinks;
if (h->nlinks)
h->linkCount = nlinks;
if (h->linkCount)
memcpy(h->links, m_tmpLinks, sizeof(dtLink)*nlinks);
}
@ -276,18 +273,18 @@ void dtNavMesh::buildExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
// Remove links pointing to 'side' and compact the links array.
dtLink* pool = m_tmpLinks;
int nlinks = 0;
for (int i = 0; i < h->npolys; ++i)
for (int i = 0; i < h->polyCount; ++i)
{
dtPoly* poly = &h->polys[i];
int plinks = nlinks;
int nplinks = 0;
// Copy internal and other external links.
for (int j = 0; j < poly->nlinks; ++j)
for (int j = 0; j < poly->linkCount; ++j)
{
dtLink* link = &h->links[poly->links+j];
dtLink* link = &h->links[poly->linkBase+j];
if ((int)link->side != side)
{
if (nlinks < h->maxlinks)
if (nlinks < h->maxLinkCount)
{
dtLink* dst = &pool[nlinks++];
memcpy(dst, link, sizeof(dtLink));
@ -296,26 +293,27 @@ void dtNavMesh::buildExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
}
}
// Create new links.
unsigned short m = EXT_LINK | (unsigned short)side;
for (int j = 0; j < poly->nv; ++j)
unsigned short m = DT_EXT_LINK | (unsigned short)side;
const int nv = poly->vertCount;
for (int j = 0; j < nv; ++j)
{
// Skip edges which do not point to the right side.
if (poly->n[j] != m) continue;
if (poly->neis[j] != m) continue;
// Create new links
const float* va = &h->verts[poly->v[j]*3];
const float* vb = &h->verts[poly->v[(j+1)%(int)poly->nv]*3];
const float* va = &h->verts[poly->verts[j]*3];
const float* vb = &h->verts[poly->verts[(j+1) % nv]*3];
dtPolyRef nei[4];
float neia[4*2];
int nnei = findConnectingPolys(va,vb, target, opposite(side), nei,neia,4);
for (int k = 0; k < nnei; ++k)
{
if (nlinks < h->maxlinks)
if (nlinks < h->maxLinkCount)
{
dtLink* link = &pool[nlinks++];
link->ref = nei[k];
link->p = (unsigned short)i;
link->e = (unsigned char)j;
link->poly = (unsigned short)i;
link->edge = (unsigned char)j;
link->side = (unsigned char)side;
// Compress portal limits to a byte value.
@ -338,11 +336,11 @@ void dtNavMesh::buildExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
}
}
poly->links = plinks;
poly->nlinks = nplinks;
poly->linkBase = plinks;
poly->linkCount = nplinks;
}
h->nlinks = nlinks;
if (h->nlinks)
h->linkCount = nlinks;
if (h->linkCount)
memcpy(h->links, m_tmpLinks, sizeof(dtLink)*nlinks);
}
@ -358,95 +356,103 @@ void dtNavMesh::buildIntLinks(dtMeshTile* tile)
unsigned int salt, it, ip, tileIdx;
dtDecodePolyId(base, salt, tileIdx, ip);
// Find Off-mesh link end points.
for (int i = 0; i < h->nomlinks; ++i)
// Find Off-mesh connection end points.
for (int i = 0; i < h->offMeshConCount; ++i)
{
dtOffMeshLink* link = &h->omlinks[i];
dtPoly* poly = &h->polys[link->p];
dtOffMeshConnection* con = &h->offMeshCons[i];
dtPoly* poly = &h->polys[con->poly];
link->ref[0] = 0;
link->ref[1] = 0;
con->ref[0] = 0;
con->ref[1] = 0;
const float ext[3] = { 0.1f, 0.3f, 0.1f }; //m_portalHeight }; // TODO: save agent size with mesh.
const float ext[3] = { con->rad, h->walkableClimb, con->rad };
for (int j = 0; j < 2; ++j)
{
const float* v = &h->verts[poly->v[j]*3];
dtPolyRef ref = findNearestPoly(v, ext);
// Make sure the location is on current mesh.
// Find polygon to connect to.
const float* p = &con->pos[j*3];
float nearestPt[3];
dtPolyRef ref = findNearestPoly(p, ext, nearestPt);
// findNearestPoly may return too optimistic results, further check to make sure.
if (sqr(nearestPt[0]-p[0])+sqr(nearestPt[2]-p[2]) > sqr(con->rad))
continue;
// TODO: Handle cross tile links.
dtDecodePolyId(ref, salt, it, ip);
if (it != tileIdx)
continue;
link->ref[j] = ref;
// Make sure the location is on current mesh.
float* v = &h->verts[poly->verts[j]*3];
vcopy(v, nearestPt);
con->ref[j] = ref;
}
}
for (int i = 0; i < h->npolys; ++i)
for (int i = 0; i < h->polyCount; ++i)
{
dtPoly* poly = &h->polys[i];
poly->links = nlinks;
poly->nlinks = 0;
poly->linkBase = nlinks;
poly->linkCount = 0;
if (poly->flags & DT_POLY_OFFMESH_LINK)
if (poly->flags & DT_POLY_OFFMESH_CONNECTION)
{
// Find Off-Mesh link and fill in information.
dtOffMeshLink& omlink = h->omlinks[i - h->nombase];
dtOffMeshConnection* con = &h->offMeshCons[i - h->offMeshBase];
// Connect both ends.
for (int j = 0; j < 2; ++j)
{
if (nlinks < h->maxlinks)
if (nlinks < h->maxLinkCount)
{
dtLink* link = &pool[nlinks++];
link->ref = omlink.ref[j];
link->p = (unsigned short)i;
link->e = (unsigned char)j;
link->ref = con->ref[j];
link->poly = (unsigned short)i;
link->edge = (unsigned char)j;
link->side = 0xff;
link->bmin = link->bmax = 0;
poly->nlinks++;
poly->linkCount++;
}
}
}
else
{
// Polygon edges.
for (int j = 0; j < poly->nv; ++j)
for (int j = 0; j < poly->vertCount; ++j)
{
// Skip hard and non-internal edges.
if (poly->n[j] == 0 || (poly->n[j] & EXT_LINK)) continue;
if (poly->neis[j] == 0 || (poly->neis[j] & DT_EXT_LINK)) continue;
if (nlinks < h->maxlinks)
if (nlinks < h->maxLinkCount)
{
dtLink* link = &pool[nlinks++];
link->ref = base | (unsigned int)(poly->n[j]-1);
link->p = (unsigned short)i;
link->e = (unsigned char)j;
link->ref = base | (unsigned int)(poly->neis[j]-1);
link->poly = (unsigned short)i;
link->edge = (unsigned char)j;
link->side = 0xff;
link->bmin = link->bmax = 0;
poly->nlinks++;
poly->linkCount++;
}
}
// Check this polygon is Off-Mesh link target and connect.
// TODO: Speed this up.
dtPolyRef curRef = base | (unsigned int)i;
for (int j = 0; j < h->nomlinks; ++j)
for (int j = 0; j < h->offMeshConCount; ++j)
{
const dtOffMeshLink* omlink = &h->omlinks[j];
const dtOffMeshConnection* con = &h->offMeshCons[j];
// Test both end points.
for (int k = 0; k < 2; ++k)
{
if (omlink->ref[k] == curRef)
if (con->ref[k] == curRef)
{
if (nlinks < h->maxlinks)
if (nlinks < h->maxLinkCount)
{
dtLink* link = &pool[nlinks++];
link->ref = base | (dtPolyRef)omlink->p;
link->p = (unsigned short)i;
link->e = 0;
link->ref = base | (dtPolyRef)con->poly;
link->poly = (unsigned short)i;
link->edge = 0;
link->side = 0xff;
link->bmin = link->bmax = 0;
poly->nlinks++;
poly->linkCount++;
}
}
}
@ -455,7 +461,7 @@ void dtNavMesh::buildIntLinks(dtMeshTile* tile)
}
}
h->nlinks = nlinks;
h->linkCount = nlinks;
}
bool dtNavMesh::addTileAt(int x, int y, unsigned char* data, int dataSize, bool ownsData)
@ -473,9 +479,9 @@ bool dtNavMesh::addTileAt(int x, int y, unsigned char* data, int dataSize, bool
return false;
// Make sure the tmp link array is large enough.
if (header->maxlinks > m_ntmpLinks)
if (header->maxLinkCount > m_ntmpLinks)
{
m_ntmpLinks = header->maxlinks;
m_ntmpLinks = header->maxLinkCount;
delete [] m_tmpLinks;
m_tmpLinks = 0;
m_tmpLinks = new dtLink[m_ntmpLinks];
@ -495,24 +501,24 @@ bool dtNavMesh::addTileAt(int x, int y, unsigned char* data, int dataSize, bool
// Patch header pointers.
const int headerSize = align4(sizeof(dtMeshHeader));
const int vertsSize = align4(sizeof(float)*3*header->nverts);
const int polysSize = align4(sizeof(dtPoly)*header->npolys);
const int linksSize = align4(sizeof(dtLink)*(header->maxlinks));
const int detailMeshesSize = align4(sizeof(dtPolyDetail)*header->ndmeshes);
const int detailVertsSize = align4(sizeof(float)*3*header->ndverts);
const int detailTrisSize = align4(sizeof(unsigned char)*4*header->ndtris);
const int bvtreeSize = header->nbvtree ? align4(sizeof(dtBVNode)*header->npolys*2) : 0;
const int offMeshLinksSize = align4(sizeof(dtOffMeshLink)*header->nomlinks);
const int vertsSize = align4(sizeof(float)*3*header->vertCount);
const int polysSize = align4(sizeof(dtPoly)*header->polyCount);
const int linksSize = align4(sizeof(dtLink)*(header->maxLinkCount));
const int detailMeshesSize = align4(sizeof(dtPolyDetail)*header->detailMeshCount);
const int detailVertsSize = align4(sizeof(float)*3*header->detailVertCount);
const int detailTrisSize = align4(sizeof(unsigned char)*4*header->detailTriCount);
const int bvtreeSize = header->bvNodeCount ? align4(sizeof(dtBVNode)*header->polyCount*2) : 0;
const int offMeshLinksSize = align4(sizeof(dtOffMeshConnection)*header->offMeshConCount);
unsigned char* d = data + headerSize;
header->verts = (float*)d; d += vertsSize;
header->polys = (dtPoly*)d; d += polysSize;
header->links = (dtLink*)d; d += linksSize;
header->dmeshes = (dtPolyDetail*)d; d += detailMeshesSize;
header->dverts = (float*)d; d += detailVertsSize;
header->dtris = (unsigned char*)d; d += detailTrisSize;
header->omlinks = (dtOffMeshLink*)d; d += offMeshLinksSize;
header->bvtree = header->nbvtree ? (dtBVNode*)d : 0; d += bvtreeSize;
header->detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize;
header->detailVerts = (float*)d; d += detailVertsSize;
header->detailTris = (unsigned char*)d; d += detailTrisSize;
header->offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize;
header->bvTree = header->bvNodeCount ? (dtBVNode*)d : 0; d += bvtreeSize;
// Init tile.
tile->header = header;
@ -573,7 +579,7 @@ const dtMeshTile* dtNavMesh::getTileByRef(dtPolyRef ref, int* polyIndex) const
dtDecodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return 0;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return 0;
if (ip >= (unsigned int)m_tiles[it].header->npolys) return 0;
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return 0;
if (polyIndex) *polyIndex = (int)ip;
return &m_tiles[it];
}
@ -663,22 +669,22 @@ bool dtNavMesh::closestPointOnPoly(dtPolyRef ref, const float* pos, float* close
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false;
const dtMeshHeader* header = m_tiles[it].header;
if (ip >= (unsigned int)header->npolys) return false;
if (ip >= (unsigned int)header->polyCount) return false;
const dtPoly* poly = &header->polys[ip];
float closestDistSqr = FLT_MAX;
const dtPolyDetail* pd = &header->dmeshes[ip];
const dtPolyDetail* pd = &header->detailMeshes[ip];
for (int j = 0; j < pd->ntris; ++j)
for (int j = 0; j < pd->triCount; ++j)
{
const unsigned char* t = &header->dtris[(pd->tbase+j)*4];
const unsigned char* t = &header->detailTris[(pd->triBase+j)*4];
const float* v[3];
for (int k = 0; k < 3; ++k)
{
if (t[k] < poly->nv)
v[k] = &header->verts[poly->v[t[k]]*3];
if (t[k] < poly->vertCount)
v[k] = &header->verts[poly->verts[t[k]]*3];
else
v[k] = &header->dverts[(pd->vbase+(t[k]-poly->nv))*3];
v[k] = &header->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3];
}
float pt[3];
closestPtPointTriangle(pt, pos, v[0], v[1], v[2]);
@ -701,7 +707,7 @@ bool dtNavMesh::closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, floa
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false;
const dtMeshHeader* header = m_tiles[it].header;
if (ip >= (unsigned int)header->npolys) return false;
if (ip >= (unsigned int)header->polyCount) return false;
const dtPoly* poly = &header->polys[ip];
// Collect vertices.
@ -709,9 +715,9 @@ bool dtNavMesh::closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, floa
float edged[DT_VERTS_PER_POLYGON];
float edget[DT_VERTS_PER_POLYGON];
int nv = 0;
for (int i = 0; i < (int)poly->nv; ++i)
for (int i = 0; i < (int)poly->vertCount; ++i)
{
vcopy(&verts[nv*3], &header->verts[poly->v[i]*3]);
vcopy(&verts[nv*3], &header->verts[poly->verts[i]*3]);
nv++;
}
@ -743,7 +749,7 @@ bool dtNavMesh::closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, floa
}
// Returns start and end location of an off-mesh link polygon.
bool dtNavMesh::getOffMeshLinkPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const
bool dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const
{
unsigned int salt, it, ip;
@ -752,7 +758,7 @@ bool dtNavMesh::getOffMeshLinkPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef
if (it >= (unsigned int)m_maxTiles) return false;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false;
const dtMeshHeader* prevHeader = m_tiles[it].header;
if (ip >= (unsigned int)prevHeader->npolys) return false;
if (ip >= (unsigned int)prevHeader->polyCount) return false;
const dtPoly* prevPoly = &prevHeader->polys[ip];
// Get current polygon
@ -760,23 +766,23 @@ bool dtNavMesh::getOffMeshLinkPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef
if (it >= (unsigned int)m_maxTiles) return false;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false;
const dtMeshHeader* header = m_tiles[it].header;
if (ip >= (unsigned int)header->npolys) return false;
if (ip >= (unsigned int)header->polyCount) return false;
const dtPoly* poly = &header->polys[ip];
// Make sure that the current poly is indeed off-mesh link.
if ((poly->flags & DT_POLY_OFFMESH_LINK) == 0)
if ((poly->flags & DT_POLY_OFFMESH_CONNECTION) == 0)
return false;
// Figure out which way to hand out the vertices.
int idx0 = 0, idx1 = 1;
for (int i = 0; i < prevPoly->nlinks; ++i)
for (int i = 0; i < prevPoly->linkCount; ++i)
{
const dtLink* link = &prevHeader->links[prevPoly->links+i];
const dtLink* link = &prevHeader->links[prevPoly->linkBase+i];
if (link->ref != polyRef)
continue;
// If first link does not point to the prev, then we need to reverse the order.
if (header->links[poly->links+0].ref != prevRef)
if (header->links[poly->linkBase+0].ref != prevRef)
{
idx0 = 1;
idx1 = 0;
@ -784,8 +790,8 @@ bool dtNavMesh::getOffMeshLinkPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef
}
}
vcopy(startPos, &header->verts[poly->v[idx0]*3]);
vcopy(endPos, &header->verts[poly->v[idx1]*3]);
vcopy(startPos, &header->verts[poly->verts[idx0]*3]);
vcopy(endPos, &header->verts[poly->verts[idx1]*3]);
return true;
}
@ -799,13 +805,13 @@ bool dtNavMesh::getPolyHeight(dtPolyRef ref, const float* pos, float* height) co
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false;
const dtMeshHeader* header = m_tiles[it].header;
if (ip >= (unsigned int)header->npolys) return false;
if (ip >= (unsigned int)header->polyCount) return false;
const dtPoly* poly = &header->polys[ip];
if (poly->flags & DT_POLY_OFFMESH_LINK)
if (poly->flags & DT_POLY_OFFMESH_CONNECTION)
{
const float* v0 = &header->verts[poly->v[0]*3];
const float* v1 = &header->verts[poly->v[1]*3];
const float* v0 = &header->verts[poly->verts[0]*3];
const float* v1 = &header->verts[poly->verts[1]*3];
const float d0 = vdist(pos, v0);
const float d1 = vdist(pos, v1);
const float u = d0 / (d0+d1);
@ -815,17 +821,17 @@ bool dtNavMesh::getPolyHeight(dtPolyRef ref, const float* pos, float* height) co
}
else
{
const dtPolyDetail* pd = &header->dmeshes[ip];
for (int j = 0; j < pd->ntris; ++j)
const dtPolyDetail* pd = &header->detailMeshes[ip];
for (int j = 0; j < pd->triCount; ++j)
{
const unsigned char* t = &header->dtris[(pd->tbase+j)*4];
const unsigned char* t = &header->detailTris[(pd->triBase+j)*4];
const float* v[3];
for (int k = 0; k < 3; ++k)
{
if (t[k] < poly->nv)
v[k] = &header->verts[poly->v[t[k]]*3];
if (t[k] < poly->vertCount)
v[k] = &header->verts[poly->verts[t[k]]*3];
else
v[k] = &header->dverts[(pd->vbase+(t[k]-poly->nv))*3];
v[k] = &header->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3];
}
float h;
if (closestHeightPointTriangle(pos, v[0], v[1], v[2], h))
@ -841,24 +847,26 @@ bool dtNavMesh::getPolyHeight(dtPolyRef ref, const float* pos, float* height) co
}
dtPolyRef dtNavMesh::findNearestPoly(const float* center, const float* extents)
dtPolyRef dtNavMesh::findNearestPoly(const float* center, const float* extents, float* nearestPt)
{
// Get nearby polygons from proximity grid.
dtPolyRef polys[128];
int npolys = queryPolygons(center, extents, polys, 128);
int polyCount = queryPolygons(center, extents, polys, 128);
// Find nearest polygon amongst the nearby polygons.
dtPolyRef nearest = 0;
float nearestDistanceSqr = FLT_MAX;
for (int i = 0; i < npolys; ++i)
for (int i = 0; i < polyCount; ++i)
{
dtPolyRef ref = polys[i];
float closest[3];
if (!closestPointOnPoly(ref, center, closest))
float closestPtPoly[3];
if (!closestPointOnPoly(ref, center, closestPtPoly))
continue;
float d = vdistSqr(center, closest);
float d = vdistSqr(center, closestPtPoly);
if (d < nearestDistanceSqr)
{
if (nearestPt)
vcopy(nearestPt, closestPtPoly);
nearestDistanceSqr = d;
nearest = ref;
}
@ -872,10 +880,10 @@ int dtNavMesh::queryTilePolygons(dtMeshTile* tile,
dtPolyRef* polys, const int maxPolys)
{
const dtMeshHeader* header = tile->header;
if (header->bvtree)
if (header->bvTree)
{
const dtBVNode* node = &header->bvtree[0];
const dtBVNode* end = &header->bvtree[header->nbvtree];
const dtBVNode* node = &header->bvTree[0];
const dtBVNode* end = &header->bvTree[header->bvNodeCount];
// Calculate quantized box
unsigned short bmin[3], bmax[3];
@ -887,12 +895,12 @@ int dtNavMesh::queryTilePolygons(dtMeshTile* tile,
float maxy = clamp(qmax[1], header->bmin[1], header->bmax[1]) - header->bmin[1];
float maxz = clamp(qmax[2], header->bmin[2], header->bmax[2]) - header->bmin[2];
// Quantize
bmin[0] = (unsigned short)(header->bvquant * minx) & 0xfffe;
bmin[1] = (unsigned short)(header->bvquant * miny) & 0xfffe;
bmin[2] = (unsigned short)(header->bvquant * minz) & 0xfffe;
bmax[0] = (unsigned short)(header->bvquant * maxx + 1) | 1;
bmax[1] = (unsigned short)(header->bvquant * maxy + 1) | 1;
bmax[2] = (unsigned short)(header->bvquant * maxz + 1) | 1;
bmin[0] = (unsigned short)(header->bvQuantFactor * minx) & 0xfffe;
bmin[1] = (unsigned short)(header->bvQuantFactor * miny) & 0xfffe;
bmin[2] = (unsigned short)(header->bvQuantFactor * minz) & 0xfffe;
bmax[0] = (unsigned short)(header->bvQuantFactor * maxx + 1) | 1;
bmax[1] = (unsigned short)(header->bvQuantFactor * maxy + 1) | 1;
bmax[2] = (unsigned short)(header->bvQuantFactor * maxz + 1) | 1;
// Traverse tree
dtPolyRef base = getTileId(tile);
@ -925,16 +933,16 @@ int dtNavMesh::queryTilePolygons(dtMeshTile* tile,
const dtMeshHeader* header = tile->header;
int n = 0;
dtPolyRef base = getTileId(tile);
for (int i = 0; i < header->npolys; ++i)
for (int i = 0; i < header->polyCount; ++i)
{
// Calc polygon bounds.
dtPoly* p = &header->polys[i];
const float* v = &header->verts[p->v[0]*3];
const float* v = &header->verts[p->verts[0]*3];
vcopy(bmin, v);
vcopy(bmax, v);
for (int j = 1; j < p->nv; ++j)
for (int j = 1; j < p->vertCount; ++j)
{
v = &header->verts[p->v[j]*3];
v = &header->verts[p->verts[j]*3];
vmin(bmin, v);
vmax(bmax, v);
}
@ -1036,9 +1044,9 @@ int dtNavMesh::findPath(dtPolyRef startRef, dtPolyRef endRef,
const dtMeshHeader* header = m_tiles[it].header;
const dtPoly* poly = &header->polys[ip];
for (int i = 0; i < poly->nlinks; ++i)
for (int i = 0; i < poly->linkCount; ++i)
{
dtPolyRef neighbour = header->links[poly->links+i].ref;
dtPolyRef neighbour = header->links[poly->linkBase+i].ref;
if (neighbour)
{
// Skip parent node.
@ -1228,7 +1236,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
vcopy(portalApex, portalLeft);
apexIndex = leftIndex;
unsigned char flags = (leftPolyFlags & DT_POLY_OFFMESH_LINK) ? DT_STRAIGHTPATH_OFFMESH_LINK : 0;
unsigned char flags = (leftPolyFlags & DT_POLY_OFFMESH_CONNECTION) ? DT_STRAIGHTPATH_OFFMESH_CONNECTION : 0;
dtPolyRef ref = leftPolyRef;
if (!vequal(&straightPath[(straightPathSize-1)*3], portalApex))
@ -1289,7 +1297,7 @@ int dtNavMesh::findStraightPath(const float* startPos, const float* endPos,
vcopy(portalApex, portalRight);
apexIndex = rightIndex;
unsigned char flags = (rightPolyFlags & DT_POLY_OFFMESH_LINK) ? DT_STRAIGHTPATH_OFFMESH_LINK : 0;
unsigned char flags = (rightPolyFlags & DT_POLY_OFFMESH_CONNECTION) ? DT_STRAIGHTPATH_OFFMESH_CONNECTION : 0;
dtPolyRef ref = rightPolyRef;
if (!vequal(&straightPath[(straightPathSize-1)*3], portalApex))
@ -1364,12 +1372,12 @@ int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos,
dtDecodePolyId(path[n], salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return n;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return n;
if (ip >= (unsigned int)m_tiles[it].header->npolys) return n;
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return n;
const dtMeshHeader* header = m_tiles[it].header;
const dtPoly* poly = &header->polys[ip];
// In case of Off-Mesh link, just snap to the end location and advance over it.
if (poly->flags & DT_POLY_OFFMESH_LINK)
if (poly->flags & DT_POLY_OFFMESH_CONNECTION)
{
if (n+1 < pathSize)
{
@ -1384,9 +1392,9 @@ int dtNavMesh::moveAlongPathCorridor(const float* startPos, const float* endPos,
// Collect vertices.
int nv = 0;
for (int i = 0; i < (int)poly->nv; ++i)
for (int i = 0; i < (int)poly->vertCount; ++i)
{
vcopy(&verts[nv*3], &header->verts[poly->v[i]*3]);
vcopy(&verts[nv*3], &header->verts[poly->verts[i]*3]);
nv++;
}
@ -1441,44 +1449,44 @@ bool dtNavMesh::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float
dtDecodePolyId(from, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return false;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false;
if (ip >= (unsigned int)m_tiles[it].header->npolys) return false;
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return false;
const dtMeshHeader* fromHeader = m_tiles[it].header;
const dtPoly* fromPoly = &fromHeader->polys[ip];
fromFlags = fromPoly->flags;
for (int i = 0; i < fromPoly->nlinks; ++i)
for (int i = 0; i < fromPoly->linkCount; ++i)
{
const dtLink* link = &fromHeader->links[fromPoly->links+i];
const dtLink* link = &fromHeader->links[fromPoly->linkBase+i];
if (link->ref != to)
continue;
dtDecodePolyId(to, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return false;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false;
if (ip >= (unsigned int)m_tiles[it].header->npolys) return false;
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return false;
const dtMeshHeader* toHeader = m_tiles[it].header;
const dtPoly* toPoly = &toHeader->polys[ip];
toFlags = toPoly->flags;
if (fromPoly->flags & DT_POLY_OFFMESH_LINK)
if (fromPoly->flags & DT_POLY_OFFMESH_CONNECTION)
{
const int v = fromHeader->links[fromPoly->links+0].ref == to ? 0 : 1;
vcopy(left, &fromHeader->verts[fromPoly->v[v]*3]);
vcopy(right, &fromHeader->verts[fromPoly->v[v]*3]);
const int v = fromHeader->links[fromPoly->linkBase+0].ref == to ? 0 : 1;
vcopy(left, &fromHeader->verts[fromPoly->verts[v]*3]);
vcopy(right, &fromHeader->verts[fromPoly->verts[v]*3]);
return true;
}
if (toPoly->flags & DT_POLY_OFFMESH_LINK)
if (toPoly->flags & DT_POLY_OFFMESH_CONNECTION)
{
const int v = toHeader->links[toPoly->links+0].ref == from ? 0 : 1;
vcopy(left, &toHeader->verts[toPoly->v[v]*3]);
vcopy(right, &toHeader->verts[toPoly->v[v]*3]);
const int v = toHeader->links[toPoly->linkBase+0].ref == from ? 0 : 1;
vcopy(left, &toHeader->verts[toPoly->verts[v]*3]);
vcopy(right, &toHeader->verts[toPoly->verts[v]*3]);
return true;
}
// Find portal vertices.
const int v0 = fromPoly->v[link->e];
const int v1 = fromPoly->v[(link->e+1) % fromPoly->nv];
const int v0 = fromPoly->verts[link->edge];
const int v1 = fromPoly->verts[(link->edge+1) % (int)fromPoly->vertCount];
vcopy(left, &fromHeader->verts[v0*3]);
vcopy(right, &fromHeader->verts[v1*3]);
// If the link is at tile boundary, clamp the vertices to
@ -1554,9 +1562,9 @@ int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float*
// Collect vertices.
int nv = 0;
for (int i = 0; i < (int)poly->nv; ++i)
for (int i = 0; i < (int)poly->vertCount; ++i)
{
vcopy(&verts[nv*3], &header->verts[poly->v[i]*3]);
vcopy(&verts[nv*3], &header->verts[poly->verts[i]*3]);
nv++;
}
@ -1576,10 +1584,10 @@ int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float*
// Follow neighbours.
dtPolyRef nextRef = 0;
for (int i = 0; i < poly->nlinks; ++i)
for (int i = 0; i < poly->linkCount; ++i)
{
const dtLink* link = &header->links[poly->links+i];
if ((int)link->e == segMax)
const dtLink* link = &header->links[poly->linkBase+i];
if ((int)link->edge == segMax)
{
// If the link is internal, just return the ref.
if (link->side == 0xff)
@ -1589,8 +1597,8 @@ int dtNavMesh::raycast(dtPolyRef centerRef, const float* startPos, const float*
}
// If the link is at tile boundary,
const int v0 = poly->v[link->e];
const int v1 = poly->v[(link->e+1) % poly->nv];
const int v0 = poly->verts[link->edge];
const int v1 = poly->verts[(link->edge+1) % poly->vertCount];
const float* left = &header->verts[v0*3];
const float* right = &header->verts[v1*3];
@ -1700,9 +1708,9 @@ int dtNavMesh::findPolysAround(dtPolyRef centerRef, const float* centerPos, floa
const dtMeshHeader* header = m_tiles[it].header;
const dtPoly* poly = &header->polys[ip];
for (int i = 0; i < poly->nlinks; ++i)
for (int i = 0; i < poly->linkCount; ++i)
{
const dtLink* link = &header->links[poly->links+i];
const dtLink* link = &header->links[poly->linkBase+i];
dtPolyRef neighbour = link->ref;
if (neighbour)
{
@ -1711,8 +1719,8 @@ int dtNavMesh::findPolysAround(dtPolyRef centerRef, const float* centerPos, floa
continue;
// Calc distance to the edge.
const float* va = &header->verts[poly->v[link->e]*3];
const float* vb = &header->verts[poly->v[(link->e+1)%poly->nv]*3];
const float* va = &header->verts[poly->verts[link->edge]*3];
const float* vb = &header->verts[poly->verts[(link->edge+1) % poly->vertCount]*3];
float tseg;
float distSqr = distancePtSegSqr2D(centerPos, va, vb, tseg);
@ -1804,17 +1812,17 @@ float dtNavMesh::findDistanceToWall(dtPolyRef centerRef, const float* centerPos,
const dtPoly* poly = &header->polys[ip];
// Hit test walls.
for (int i = 0, j = (int)poly->nv-1; i < (int)poly->nv; j = i++)
for (int i = 0, j = (int)poly->vertCount-1; i < (int)poly->vertCount; j = i++)
{
// Skip non-solid edges.
if (poly->n[j] & EXT_LINK)
if (poly->neis[j] & DT_EXT_LINK)
{
// Tile border.
bool solid = true;
for (int i = 0; i < poly->nlinks; ++i)
for (int i = 0; i < poly->linkCount; ++i)
{
const dtLink* link = &header->links[poly->links+i];
if (link->e == j && link->ref != 0)
const dtLink* link = &header->links[poly->linkBase+i];
if (link->edge == j && link->ref != 0)
{
solid = false;
break;
@ -1822,15 +1830,15 @@ float dtNavMesh::findDistanceToWall(dtPolyRef centerRef, const float* centerPos,
}
if (!solid) continue;
}
else if (poly->n[j])
else if (poly->neis[j])
{
// Internal edge
continue;
}
// Calc distance to the edge.
const float* vj = &header->verts[poly->v[j]*3];
const float* vi = &header->verts[poly->v[i]*3];
const float* vj = &header->verts[poly->verts[j]*3];
const float* vi = &header->verts[poly->verts[i]*3];
float tseg;
float distSqr = distancePtSegSqr2D(centerPos, vj, vi, tseg);
@ -1846,9 +1854,9 @@ float dtNavMesh::findDistanceToWall(dtPolyRef centerRef, const float* centerPos,
hitPos[2] = vj[2] + (vi[2] - vj[2])*tseg;
}
for (int i = 0; i < poly->nlinks; ++i)
for (int i = 0; i < poly->linkCount; ++i)
{
const dtLink* link = &header->links[poly->links+i];
const dtLink* link = &header->links[poly->linkBase+i];
dtPolyRef neighbour = link->ref;
if (neighbour)
{
@ -1857,8 +1865,8 @@ float dtNavMesh::findDistanceToWall(dtPolyRef centerRef, const float* centerPos,
continue;
// Calc distance to the edge.
const float* va = &header->verts[poly->v[link->e]*3];
const float* vb = &header->verts[poly->v[(link->e+1)%poly->nv]*3];
const float* va = &header->verts[poly->verts[link->edge]*3];
const float* vb = &header->verts[poly->verts[(link->edge+1) % poly->vertCount]*3];
float tseg;
float distSqr = distancePtSegSqr2D(centerPos, va, vb, tseg);
@ -1917,7 +1925,7 @@ const dtPoly* dtNavMesh::getPolyByRef(dtPolyRef ref) const
dtDecodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return 0;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return 0;
if (ip >= (unsigned int)m_tiles[it].header->npolys) return 0;
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return 0;
return &m_tiles[it].header->polys[ip];
}
@ -1927,7 +1935,7 @@ const float* dtNavMesh::getPolyVertsByRef(dtPolyRef ref) const
dtDecodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return 0;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return 0;
if (ip >= (unsigned int)m_tiles[it].header->npolys) return 0;
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return 0;
return m_tiles[it].header->verts;
}
@ -1937,7 +1945,7 @@ const dtLink* dtNavMesh::getPolyLinksByRef(dtPolyRef ref) const
dtDecodePolyId(ref, salt, it, ip);
if (it >= (unsigned int)m_maxTiles) return 0;
if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return 0;
if (ip >= (unsigned int)m_tiles[it].header->npolys) return 0;
if (ip >= (unsigned int)m_tiles[it].header->polyCount) return 0;
return m_tiles[it].header->links;
}

View File

@ -22,6 +22,7 @@
#include <string.h>
#include "DetourNavMesh.h"
#include "DetourCommon.h"
#include "DetourNavMeshBuilder.h"
@ -337,71 +338,64 @@ unsigned short findNearestPoly(dtMeshHeader* header, const float* center, const
}
*/
bool dtCreateNavMeshData(const unsigned short* verts, const int nverts,
const unsigned short* polys, const int npolys, const int nvp,
const unsigned short* dmeshes, const float* dverts, const int ndverts,
const unsigned char* dtris, const int ndtris,
const float* omverts, const int nomlinks,
const float* bmin, const float* bmax, float cs, float ch, int tileSize, int walkableClimb,
unsigned char** outData, int* outDataSize)
bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize)
{
if (nvp != DT_VERTS_PER_POLYGON)
if (params->nvp > DT_VERTS_PER_POLYGON)
return false;
if (nverts >= 0xffff)
if (params->vertCount >= 0xffff)
return false;
if (!params->vertCount || !params->verts)
return false;
if (!params->polyCount || !params->polys)
return false;
if (!params->detailMeshes || !params->detailVerts || !params->detailTris)
return false;
if (!nverts)
return false;
if (!npolys)
return false;
if (!dmeshes || !dverts || ! dtris)
return false;
const int nvp = params->nvp;
// Off-mesh links are stored as polygons, adjust values.
const int totpolys = npolys + nomlinks;
const int totverts = nverts + nomlinks*2;
// Off-mesh connectionss are stored as polygons, adjust values.
const int totPolyCount = params->polyCount + params->offMeshConCount;
const int totVertCount = params->vertCount + params->offMeshConCount*2;
// Find portal edges which are at tile borders.
int nedges = 0;
int nportals = 0;
for (int i = 0; i < npolys; ++i)
int edgeCount = 0;
int portalCount = 0;
for (int i = 0; i < params->polyCount; ++i)
{
const unsigned short* p = &polys[i*2*nvp];
const unsigned short* p = &params->polys[i*2*nvp];
for (int j = 0; j < nvp; ++j)
{
if (p[j] == 0xffff) break;
int nj = j+1;
if (nj >= nvp || p[nj] == 0xffff) nj = 0;
const unsigned short* va = &verts[p[j]*3];
const unsigned short* vb = &verts[p[nj]*3];
const unsigned short* va = &params->verts[p[j]*3];
const unsigned short* vb = &params->verts[p[nj]*3];
nedges++;
edgeCount++;
if (tileSize > 0)
if (params->tileSize > 0)
{
if (va[0] == tileSize && vb[0] == tileSize)
nportals++; // x+
else if (va[2] == tileSize && vb[2] == tileSize)
nportals++; // z+
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)
nportals++; // x-
portalCount++; // x-
else if (va[2] == 0 && vb[2] == 0)
nportals++; // z-
portalCount++; // z-
}
}
}
const int maxLinks = nedges + nportals*2 + nomlinks*4;
const int maxLinkCount = edgeCount + portalCount*2 + params->offMeshConCount*4;
// Find unique detail vertices.
int uniqueDetailVerts = 0;
if (dmeshes)
int uniqueDetailVertCount = 0;
for (int i = 0; i < params->polyCount; ++i)
{
for (int i = 0; i < npolys; ++i)
{
const unsigned short* p = &polys[i*nvp*2];
int ndv = dmeshes[i*4+1];
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)
{
@ -409,24 +403,23 @@ bool dtCreateNavMeshData(const unsigned short* verts, const int nverts,
nv++;
}
ndv -= nv;
uniqueDetailVerts += ndv;
}
uniqueDetailVertCount += ndv;
}
// Calculate data size
const int headerSize = align4(sizeof(dtMeshHeader));
const int vertsSize = align4(sizeof(float)*3*totverts);
const int polysSize = align4(sizeof(dtPoly)*totpolys);
const int linksSize = align4(sizeof(dtLink)*maxLinks);
const int detailMeshesSize = align4(sizeof(dtPolyDetail)*npolys);
const int detailVertsSize = align4(sizeof(float)*3*uniqueDetailVerts);
const int detailTrisSize = align4(sizeof(unsigned char)*4*ndtris);
const int bvtreeSize = align4(sizeof(dtBVNode)*npolys*2);
const int offMeshLinksSize = align4(sizeof(dtOffMeshLink)*nomlinks);
const int vertsSize = align4(sizeof(float)*3*totVertCount);
const int polysSize = align4(sizeof(dtPoly)*totPolyCount);
const int linksSize = align4(sizeof(dtLink)*maxLinkCount);
const int detailMeshesSize = align4(sizeof(dtPolyDetail)*params->polyCount);
const int detailVertsSize = align4(sizeof(float)*3*uniqueDetailVertCount);
const int detailTrisSize = align4(sizeof(unsigned char)*4*params->detailTriCount);
const int bvTreeSize = align4(sizeof(dtBVNode)*params->polyCount*2);
const int offMeshConsSize = align4(sizeof(dtOffMeshConnection)*params->offMeshConCount);
const int dataSize = headerSize + vertsSize + polysSize + linksSize +
detailMeshesSize + detailVertsSize + detailTrisSize +
bvtreeSize + offMeshLinksSize;
bvTreeSize + offMeshConsSize;
unsigned char* data = new unsigned char[dataSize];
if (!data)
@ -441,98 +434,99 @@ bool dtCreateNavMeshData(const unsigned short* verts, const int nverts,
dtPolyDetail* navDMeshes = (dtPolyDetail*)d; d += detailMeshesSize;
float* navDVerts = (float*)d; d += detailVertsSize;
unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize;
dtOffMeshLink* offMeshLinks = (dtOffMeshLink*)d; d += offMeshLinksSize;
dtBVNode* navBvtree = (dtBVNode*)d; d += bvtreeSize;
dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshConsSize;
dtBVNode* navBvtree = (dtBVNode*)d; d += bvTreeSize;
// Store header
header->magic = DT_NAVMESH_MAGIC;
header->version = DT_NAVMESH_VERSION;
header->npolys = totpolys;
header->nverts = totverts;
header->maxlinks = maxLinks;
header->bmin[0] = bmin[0];
header->bmin[1] = bmin[1];
header->bmin[2] = bmin[2];
header->bmax[0] = bmax[0];
header->bmax[1] = bmax[1];
header->bmax[2] = bmax[2];
header->ndmeshes = npolys;
header->ndverts = uniqueDetailVerts;
header->ndtris = ndtris;
header->bvquant = 1.0f/cs;
header->nombase = npolys;
header->nomlinks = nomlinks;
header->nbvtree = npolys*2;
header->polyCount = totPolyCount;
header->vertCount = totVertCount;
header->maxLinkCount = maxLinkCount;
vcopy(header->bmin, params->bmin);
vcopy(header->bmax, params->bmax);
header->detailMeshCount = params->polyCount;
header->detailVertCount = uniqueDetailVertCount;
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 = params->offMeshConCount;
header->bvNodeCount = params->polyCount*2;
const int offMeshVertsBase = params->vertCount;
const int offMeshPolyBase = params->polyCount;
// Store vertices
// Mesh vertices
for (int i = 0; i < nverts; ++i)
for (int i = 0; i < params->vertCount; ++i)
{
const unsigned short* iv = &verts[i*3];
const unsigned short* iv = &params->verts[i*3];
float* v = &navVerts[i*3];
v[0] = bmin[0] + iv[0] * cs;
v[1] = bmin[1] + iv[1] * ch;
v[2] = bmin[2] + iv[2] * cs;
v[0] = params->bmin[0] + iv[0] * params->cs;
v[1] = params->bmin[1] + iv[1] * params->ch;
v[2] = params->bmin[2] + iv[2] * params->cs;
}
// Off-mesh link vertices.
for (int i = 0; i < nomlinks; ++i)
for (int i = 0; i < params->offMeshConCount; ++i)
{
const float* linkv = &omverts[i*2*3];
float* v = &navVerts[(nverts+i*2)*3];
const float* linkv = &params->offMeshConVerts[i*2*3];
float* v = &navVerts[(offMeshVertsBase + i*2)*3];
vcopy(&v[0], &linkv[0]);
vcopy(&v[3], &linkv[3]);
}
// Store polygons
// Mesh polys
const unsigned short* src = polys;
for (int i = 0; i < npolys; ++i)
const unsigned short* src = params->polys;
for (int i = 0; i < params->polyCount; ++i)
{
dtPoly* p = &navPolys[i];
p->nv = 0;
p->vertCount = 0;
for (int j = 0; j < nvp; ++j)
{
if (src[j] == 0xffff) break;
p->v[j] = src[j];
p->n[j] = (src[nvp+j]+1) & 0xffff;
p->nv++;
p->verts[j] = src[j];
p->neis[j] = (src[nvp+j]+1) & 0xffff;
p->vertCount++;
}
src += nvp*2;
}
// Off-mesh link vertices.
const int omvbase = nverts; // first off-mesh link vertex.
for (int i = 0; i < nomlinks; ++i)
// Off-mesh connection vertices.
for (int i = 0; i < params->offMeshConCount; ++i)
{
dtPoly* p = &navPolys[npolys+i];
p->nv = 2;
p->v[0] = (unsigned short)(omvbase + i*2+0);
p->v[1] = (unsigned short)(omvbase + i*2+1);
p->flags = DT_POLY_OFFMESH_LINK; // Off-mesh link poly.
dtPoly* p = &navPolys[offMeshPolyBase+i];
p->vertCount = 2;
p->verts[0] = (unsigned short)(offMeshVertsBase + i*2+0);
p->verts[1] = (unsigned short)(offMeshVertsBase + i*2+1);
p->flags = DT_POLY_OFFMESH_CONNECTION; // Off-mesh link poly.
}
// Store portal edges.
if (tileSize > 0)
if (params->tileSize > 0)
{
for (int i = 0; i < npolys; ++i)
for (int i = 0; i < params->polyCount; ++i)
{
dtPoly* poly = &navPolys[i];
for (int j = 0; j < poly->nv; ++j)
for (int j = 0; j < poly->vertCount; ++j)
{
int nj = j+1;
if (nj >= poly->nv) nj = 0;
if (nj >= poly->vertCount) nj = 0;
const unsigned short* va = &verts[poly->v[j]*3];
const unsigned short* vb = &verts[poly->v[nj]*3];
const unsigned short* va = &params->verts[poly->verts[j]*3];
const unsigned short* vb = &params->verts[poly->verts[nj]*3];
if (va[0] == tileSize && vb[0] == tileSize) // x+
poly->n[j] = 0x8000 | 0;
else if (va[2] == tileSize && vb[2] == tileSize) // z+
poly->n[j] = 0x8000 | 1;
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 | 1;
else if (va[0] == 0 && vb[0] == 0) // x-
poly->n[j] = 0x8000 | 2;
poly->neis[j] = DT_EXT_LINK | 2;
else if (va[2] == 0 && vb[2] == 0) // z-
poly->n[j] = 0x8000 | 3;
poly->neis[j] = DT_EXT_LINK | 3;
}
}
}
@ -541,35 +535,42 @@ bool dtCreateNavMeshData(const unsigned short* verts, const int nverts,
// 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 < npolys; ++i)
for (int i = 0; i < params->polyCount; ++i)
{
dtPolyDetail& dtl = navDMeshes[i];
const int vb = dmeshes[i*4+0];
const int ndv = dmeshes[i*4+1];
const int nv = navPolys[i].nv;
dtl.vbase = vbase;
dtl.nverts = ndv-nv;
dtl.tbase = dmeshes[i*4+2];
dtl.ntris = dmeshes[i*4+3];
const int vb = params->detailMeshes[i*4+0];
const int ndv = params->detailMeshes[i*4+1];
const int nv = navPolys[i].vertCount;
dtl.vertBase = vbase;
dtl.vertCount = ndv-nv;
dtl.triBase = params->detailMeshes[i*4+2];
dtl.triCount = params->detailMeshes[i*4+3];
// Copy vertices except the first 'nv' verts which are equal to nav poly verts.
if (ndv-nv)
{
memcpy(&navDVerts[vbase*3], &dverts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
memcpy(&navDVerts[vbase*3], &params->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv));
vbase += ndv-nv;
}
}
// Store triangles.
memcpy(navDTris, dtris, sizeof(unsigned char)*4*ndtris);
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?
createBVTree(verts, nverts, polys, npolys, nvp, cs, ch, npolys*2, navBvtree);
createBVTree(params->verts, params->vertCount, params->polys, params->polyCount,
nvp, params->cs, params->ch, params->polyCount*2, navBvtree);
// Store Off-Mesh links.
for (int i = 0; i < nomlinks; ++i)
// Store Off-Mesh connections.
for (int i = 0; i < params->offMeshConCount; ++i)
{
dtOffMeshLink* link = &offMeshLinks[i];
link->p = npolys + i;
dtOffMeshConnection* con = &offMeshCons[i];
con->poly = offMeshPolyBase + i;
// Copy connection end-points.
const float* endPts = &params->offMeshConVerts[i*2*3];
vcopy(&con->pos[0], &endPts[0]);
vcopy(&con->pos[3], &endPts[3]);
con->rad = params->offMeshConRad[i];
con->flags = params->offMeshConDir[i];
}
*outData = data;

File diff suppressed because it is too large Load Diff

View File

@ -281,14 +281,13 @@
<key>PBXSmartGroupTreeModuleOutlineStateSelectionKey</key>
<array>
<array>
<integer>14</integer>
<integer>12</integer>
<integer>60</integer>
<integer>1</integer>
<integer>0</integer>
</array>
</array>
<key>PBXSmartGroupTreeModuleOutlineStateVisibleRectKey</key>
<string>{{0, 98}, {282, 643}}</string>
<string>{{0, 584}, {282, 643}}</string>
</dict>
<key>PBXTopSmartGroupGIDs</key>
<array/>
@ -323,7 +322,7 @@
<key>PBXProjectModuleGUID</key>
<string>6B8632A30F78115100E2684A</string>
<key>PBXProjectModuleLabel</key>
<string>DetourNavMesh.cpp</string>
<string>InputGeom.cpp</string>
<key>PBXSplitModuleInNavigatorKey</key>
<dict>
<key>Split0</key>
@ -331,15 +330,14 @@
<key>PBXProjectModuleGUID</key>
<string>6B8632A40F78115100E2684A</string>
<key>PBXProjectModuleLabel</key>
<string>DetourNavMesh.cpp</string>
<string>InputGeom.cpp</string>
<key>_historyCapacity</key>
<integer>0</integer>
<key>bookmark</key>
<string>6BE7322310FE72B300C1B074</string>
<string>6BCF348D1105F58E009445BF</string>
<key>history</key>
<array>
<string>6B57D358108C66B200DDD053</string>
<string>6B7FB74D1091EBDE001BA51A</string>
<string>6B8DE70D10B01BBF00DF20FB</string>
<string>6B8DE76D10B0243500DF20FB</string>
<string>6B8DE84910B0584400DF20FB</string>
@ -357,35 +355,38 @@
<string>6BB7FDC110F37703006DA0A6</string>
<string>6BB7FE1010F37CF7006DA0A6</string>
<string>6BB7FE3B10F3817A006DA0A6</string>
<string>6BB7FEA910F4B5E1006DA0A6</string>
<string>6BB7FEAD10F4B5E1006DA0A6</string>
<string>6BB7FEDE10F4B779006DA0A6</string>
<string>6BB7FF0310F4D699006DA0A6</string>
<string>6BB7FF6D10F4E8E2006DA0A6</string>
<string>6BB7FF6E10F4E8E2006DA0A6</string>
<string>6BB7FF7310F4E8E2006DA0A6</string>
<string>6BB7FFBE10F4E9A8006DA0A6</string>
<string>6BB7FFD610F4EC73006DA0A6</string>
<string>6BB7000610F4F03D006DA0A6</string>
<string>6BB7002C10F4F257006DA0A6</string>
<string>6BB7003710F4F39B006DA0A6</string>
<string>6BB7003810F4F39B006DA0A6</string>
<string>6BB7007210FA2B13006DA0A6</string>
<string>6BB700BF10FA3AB1006DA0A6</string>
<string>6BB35FED10FBD09300A9B4B8</string>
<string>6BB3601610FE561F00A9B4B8</string>
<string>6BB3601710FE561F00A9B4B8</string>
<string>6BB3603D10FE59E200A9B4B8</string>
<string>6BB3605210FE5CBD00A9B4B8</string>
<string>6BB3605310FE5CBD00A9B4B8</string>
<string>6BB3605410FE5CBD00A9B4B8</string>
<string>6BB3606210FE5E8F00A9B4B8</string>
<string>6BE7320210FE6CEF00C1B074</string>
<string>6BE7320C10FE6EBE00C1B074</string>
<string>6BE7321210FE70FE00C1B074</string>
<string>6BE7321D10FE72B300C1B074</string>
<string>6BE7321E10FE72B300C1B074</string>
<string>6BE7321F10FE72B300C1B074</string>
<string>6B69736710FFBDCA00984788</string>
<string>6B69736810FFBDCA00984788</string>
<string>6B69739F10FFCA4500984788</string>
<string>6BCF325E1104CFE7009445BF</string>
<string>6BCF325F1104CFE7009445BF</string>
<string>6BCF331811059E23009445BF</string>
<string>6BCF331911059E23009445BF</string>
<string>6BCF331A11059E23009445BF</string>
<string>6BCF332411059EA9009445BF</string>
<string>6BCF33351105B2B5009445BF</string>
<string>6BCF33651105BBA2009445BF</string>
<string>6BCF33671105BBA2009445BF</string>
<string>6BCF336A1105BBA2009445BF</string>
<string>6BCF33AF1105BE51009445BF</string>
<string>6BCF33E21105E5BB009445BF</string>
<string>6BCF34031105E98C009445BF</string>
<string>6BCF34041105E98C009445BF</string>
<string>6BCF341A1105EC43009445BF</string>
<string>6BCF34211105EC43009445BF</string>
<string>6BCF343A1105ECAB009445BF</string>
<string>6BCF343B1105ECAB009445BF</string>
<string>6BCF34441105ECEB009445BF</string>
<string>6BCF34691105EF2D009445BF</string>
<string>6BCF34731105F503009445BF</string>
<string>6BCF347A1105F519009445BF</string>
<string>6BCF347B1105F519009445BF</string>
<string>6BCF34821105F555009445BF</string>
<string>6BCF34831105F555009445BF</string>
<string>6BCF34841105F555009445BF</string>
</array>
<key>prevStack</key>
<array>
@ -407,29 +408,193 @@
<string>6BB7FE2210F37CF7006DA0A6</string>
<string>6BB7FE2310F37CF7006DA0A6</string>
<string>6BB7FE5410F3817A006DA0A6</string>
<string>6BB7FE7810F38224006DA0A6</string>
<string>6BB7FEB810F4B5E1006DA0A6</string>
<string>6BB7FEB910F4B5E1006DA0A6</string>
<string>6BB7FECF10F4B5E1006DA0A6</string>
<string>6BB7FF1210F4D699006DA0A6</string>
<string>6BB7FF2410F4D699006DA0A6</string>
<string>6BB7FF7910F4E8E2006DA0A6</string>
<string>6BB7FF8910F4E8E2006DA0A6</string>
<string>6BB7FF9610F4E8E2006DA0A6</string>
<string>6BB7FF9710F4E8E2006DA0A6</string>
<string>6BB7007510FA2B13006DA0A6</string>
<string>6BB7008C10FA3475006DA0A6</string>
<string>6BB7008E10FA3475006DA0A6</string>
<string>6BB700C310FA3AB1006DA0A6</string>
<string>6BE7320010FE6BDC00C1B074</string>
<string>6BE7320610FE6CEF00C1B074</string>
<string>6BE7320E10FE6EBE00C1B074</string>
<string>6BE7320F10FE6EBE00C1B074</string>
<string>6BE7321410FE70FE00C1B074</string>
<string>6BE7321810FE712A00C1B074</string>
<string>6BE7322010FE72B300C1B074</string>
<string>6BE7322110FE72B300C1B074</string>
<string>6BE7322210FE72B300C1B074</string>
<string>6B69737210FFBDCA00984788</string>
<string>6B69739810FFC43600984788</string>
<string>6B6973A210FFCA4500984788</string>
<string>6BCF31FD1104C9F0009445BF</string>
<string>6BCF31FE1104C9F0009445BF</string>
<string>6BCF31FF1104C9F0009445BF</string>
<string>6BCF32001104C9F0009445BF</string>
<string>6BCF32011104C9F0009445BF</string>
<string>6BCF32021104C9F0009445BF</string>
<string>6BCF32031104C9F0009445BF</string>
<string>6BCF32041104C9F0009445BF</string>
<string>6BCF32051104C9F0009445BF</string>
<string>6BCF32061104C9F0009445BF</string>
<string>6BCF32071104C9F0009445BF</string>
<string>6BCF32081104C9F0009445BF</string>
<string>6BCF32091104C9F0009445BF</string>
<string>6BCF320A1104C9F0009445BF</string>
<string>6BCF320B1104C9F0009445BF</string>
<string>6BCF320C1104C9F0009445BF</string>
<string>6BCF320D1104C9F0009445BF</string>
<string>6BCF320E1104C9F0009445BF</string>
<string>6BCF32111104C9F0009445BF</string>
<string>6BCF32121104C9F0009445BF</string>
<string>6BCF32151104C9F0009445BF</string>
<string>6BCF322E1104CA22009445BF</string>
<string>6BCF322F1104CA22009445BF</string>
<string>6BCF32441104CDB5009445BF</string>
<string>6BCF32451104CDB5009445BF</string>
<string>6BCF32461104CDB5009445BF</string>
<string>6BCF32471104CDB5009445BF</string>
<string>6BCF32481104CDB5009445BF</string>
<string>6BCF32491104CDB5009445BF</string>
<string>6BCF324A1104CDB5009445BF</string>
<string>6BCF324C1104CDB5009445BF</string>
<string>6BCF324E1104CDB5009445BF</string>
<string>6BCF324F1104CDB5009445BF</string>
<string>6BCF32501104CDB5009445BF</string>
<string>6BCF32511104CDB5009445BF</string>
<string>6BCF32521104CDB5009445BF</string>
<string>6BCF32681104CFE7009445BF</string>
<string>6BCF32691104CFE7009445BF</string>
<string>6BCF326A1104CFE7009445BF</string>
<string>6BCF326B1104CFE7009445BF</string>
<string>6BCF326C1104CFE7009445BF</string>
<string>6BCF326D1104CFE7009445BF</string>
<string>6BCF326E1104CFE7009445BF</string>
<string>6BCF326F1104CFE7009445BF</string>
<string>6BCF32701104CFE7009445BF</string>
<string>6BCF32711104CFE7009445BF</string>
<string>6BCF32721104CFE7009445BF</string>
<string>6BCF32731104CFE7009445BF</string>
<string>6BCF32741104CFE7009445BF</string>
<string>6BCF32751104CFE7009445BF</string>
<string>6BCF32761104CFE7009445BF</string>
<string>6BCF32771104CFE7009445BF</string>
<string>6BCF32781104CFE7009445BF</string>
<string>6BCF32791104CFE7009445BF</string>
<string>6BCF327A1104CFE7009445BF</string>
<string>6BCF32861104D114009445BF</string>
<string>6BCF32871104D114009445BF</string>
<string>6BCF32881104D114009445BF</string>
<string>6BCF32891104D114009445BF</string>
<string>6BCF32A31104D31E009445BF</string>
<string>6BCF32A51104D31E009445BF</string>
<string>6BCF32A61104D31E009445BF</string>
<string>6BCF32B41104D3E5009445BF</string>
<string>6BCF32C51104D678009445BF</string>
<string>6BCF32ED1104D7F5009445BF</string>
<string>6BCF32EE1104D7F5009445BF</string>
<string>6BCF32F51104D815009445BF</string>
<string>6BCF33021104D891009445BF</string>
<string>6BCF33041104D891009445BF</string>
<string>6BCF33061104D891009445BF</string>
<string>6BCF331611059D39009445BF</string>
<string>6BCF331C11059E23009445BF</string>
<string>6BCF331D11059E23009445BF</string>
<string>6BCF331E11059E23009445BF</string>
<string>6BCF331F11059E23009445BF</string>
<string>6BCF332611059EA9009445BF</string>
<string>6BCF332C1105A59B009445BF</string>
<string>6BCF33381105B2B5009445BF</string>
<string>6BCF33541105B986009445BF</string>
<string>6BCF33551105B986009445BF</string>
<string>6BCF33561105B986009445BF</string>
<string>6BCF33571105B986009445BF</string>
<string>6BCF33581105B986009445BF</string>
<string>6BCF33591105B986009445BF</string>
<string>6BCF335A1105B986009445BF</string>
<string>6BCF336E1105BBA2009445BF</string>
<string>6BCF336F1105BBA2009445BF</string>
<string>6BCF33701105BBA2009445BF</string>
<string>6BCF33711105BBA2009445BF</string>
<string>6BCF33721105BBA2009445BF</string>
<string>6BCF33731105BBA2009445BF</string>
<string>6BCF33741105BBA2009445BF</string>
<string>6BCF33751105BBA2009445BF</string>
<string>6BCF33761105BBA2009445BF</string>
<string>6BCF33781105BBA2009445BF</string>
<string>6BCF337A1105BBA2009445BF</string>
<string>6BCF337C1105BBA2009445BF</string>
<string>6BCF337D1105BBA2009445BF</string>
<string>6BCF337E1105BBA2009445BF</string>
<string>6BCF337F1105BBA2009445BF</string>
<string>6BCF33801105BBA2009445BF</string>
<string>6BCF33811105BBA2009445BF</string>
<string>6BCF33881105BBC8009445BF</string>
<string>6BCF338E1105BCB7009445BF</string>
<string>6BCF338F1105BCB7009445BF</string>
<string>6BCF339A1105BD0E009445BF</string>
<string>6BCF339B1105BD0E009445BF</string>
<string>6BCF339C1105BD0E009445BF</string>
<string>6BCF339D1105BD0E009445BF</string>
<string>6BCF339E1105BD0E009445BF</string>
<string>6BCF339F1105BD0E009445BF</string>
<string>6BCF33A41105BD41009445BF</string>
<string>6BCF33A91105BDAD009445BF</string>
<string>6BCF33B21105BE51009445BF</string>
<string>6BCF33B31105BE51009445BF</string>
<string>6BCF33B41105BE51009445BF</string>
<string>6BCF33B51105BE51009445BF</string>
<string>6BCF33B61105BE51009445BF</string>
<string>6BCF33BD1105BEE9009445BF</string>
<string>6BCF33CA1105C466009445BF</string>
<string>6BCF33D31105C5EF009445BF</string>
<string>6BCF33E41105E5BB009445BF</string>
<string>6BCF33E51105E5BB009445BF</string>
<string>6BCF33E61105E5BB009445BF</string>
<string>6BCF33E71105E5BB009445BF</string>
<string>6BCF33E81105E5BB009445BF</string>
<string>6BCF33E91105E5BB009445BF</string>
<string>6BCF33EA1105E5BB009445BF</string>
<string>6BCF33EB1105E5BB009445BF</string>
<string>6BCF33EC1105E5BB009445BF</string>
<string>6BCF33ED1105E5BB009445BF</string>
<string>6BCF33F21105E621009445BF</string>
<string>6BCF33F91105E71B009445BF</string>
<string>6BCF33FA1105E71B009445BF</string>
<string>6BCF340B1105E98C009445BF</string>
<string>6BCF340C1105E98C009445BF</string>
<string>6BCF340D1105E98C009445BF</string>
<string>6BCF340E1105E98C009445BF</string>
<string>6BCF340F1105E98C009445BF</string>
<string>6BCF34101105E98C009445BF</string>
<string>6BCF34111105E98C009445BF</string>
<string>6BCF34121105E98C009445BF</string>
<string>6BCF34131105E98C009445BF</string>
<string>6BCF34141105E98C009445BF</string>
<string>6BCF34231105EC43009445BF</string>
<string>6BCF34241105EC43009445BF</string>
<string>6BCF34251105EC43009445BF</string>
<string>6BCF34261105EC43009445BF</string>
<string>6BCF34271105EC43009445BF</string>
<string>6BCF34281105EC43009445BF</string>
<string>6BCF34291105EC43009445BF</string>
<string>6BCF342A1105EC43009445BF</string>
<string>6BCF342B1105EC43009445BF</string>
<string>6BCF342C1105EC43009445BF</string>
<string>6BCF342D1105EC43009445BF</string>
<string>6BCF342E1105EC43009445BF</string>
<string>6BCF342F1105EC43009445BF</string>
<string>6BCF34301105EC43009445BF</string>
<string>6BCF34311105EC43009445BF</string>
<string>6BCF34321105EC43009445BF</string>
<string>6BCF34331105EC43009445BF</string>
<string>6BCF34341105EC43009445BF</string>
<string>6BCF343D1105ECAB009445BF</string>
<string>6BCF343E1105ECAB009445BF</string>
<string>6BCF343F1105ECAB009445BF</string>
<string>6BCF34401105ECAB009445BF</string>
<string>6BCF34461105ECEB009445BF</string>
<string>6BCF344A1105ED03009445BF</string>
<string>6BCF34591105EE81009445BF</string>
<string>6BCF345F1105EEA7009445BF</string>
<string>6BCF346C1105EF2D009445BF</string>
<string>6BCF34751105F503009445BF</string>
<string>6BCF34761105F503009445BF</string>
<string>6BCF34771105F503009445BF</string>
<string>6BCF347D1105F519009445BF</string>
<string>6BCF347E1105F519009445BF</string>
<string>6BCF34851105F555009445BF</string>
<string>6BCF34861105F555009445BF</string>
</array>
</dict>
<key>SplitCount</key>
@ -443,18 +608,18 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{0, 0}, {952, 572}}</string>
<string>{{0, 0}, {952, 501}}</string>
<key>RubberWindowFrame</key>
<string>11 76 1256 702 0 0 1280 778 </string>
</dict>
<key>Module</key>
<string>PBXNavigatorGroup</string>
<key>Proportion</key>
<string>572pt</string>
<string>501pt</string>
</dict>
<dict>
<key>Proportion</key>
<string>84pt</string>
<string>155pt</string>
<key>Tabs</key>
<array>
<dict>
@ -468,7 +633,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {952, 57}}</string>
<string>{{10, 27}, {952, 90}}</string>
</dict>
<key>Module</key>
<string>XCDetailModule</string>
@ -484,7 +649,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {952, 63}}</string>
<string>{{10, 27}, {952, 212}}</string>
</dict>
<key>Module</key>
<string>PBXProjectFindModule</string>
@ -522,7 +687,7 @@
<key>GeometryConfiguration</key>
<dict>
<key>Frame</key>
<string>{{10, 27}, {952, 57}}</string>
<string>{{10, 27}, {952, 128}}</string>
<key>RubberWindowFrame</key>
<string>11 76 1256 702 0 0 1280 778 </string>
</dict>
@ -552,11 +717,11 @@
</array>
<key>TableOfContents</key>
<array>
<string>6BE731E710FE67F500C1B074</string>
<string>6BCF32211104C9F0009445BF</string>
<string>1CA23ED40692098700951B8B</string>
<string>6BE731E810FE67F500C1B074</string>
<string>6BCF32221104C9F0009445BF</string>
<string>6B8632A30F78115100E2684A</string>
<string>6BE731E910FE67F500C1B074</string>
<string>6BCF32231104C9F0009445BF</string>
<string>1CA23EDF0692099D00951B8B</string>
<string>1CA23EE00692099D00951B8B</string>
<string>1CA23EE10692099D00951B8B</string>
@ -705,14 +870,14 @@
</array>
<key>TableOfContents</key>
<array>
<string>6BE731EA10FE67F500C1B074</string>
<string>6BCF32241104C9F0009445BF</string>
<string>1CCC7628064C1048000F2A68</string>
<string>1CCC7629064C1048000F2A68</string>
<string>6BE731EB10FE67F500C1B074</string>
<string>6BE731EC10FE67F500C1B074</string>
<string>6BE731ED10FE67F500C1B074</string>
<string>6BE731EE10FE67F500C1B074</string>
<string>6BE731EF10FE67F500C1B074</string>
<string>6BCF32251104C9F0009445BF</string>
<string>6BCF32261104C9F0009445BF</string>
<string>6BCF32271104C9F0009445BF</string>
<string>6BCF32281104C9F0009445BF</string>
<string>6BCF32291104C9F0009445BF</string>
</array>
<key>ToolbarConfigUserDefaultsMinorVersion</key>
<string>2</string>
@ -744,6 +909,8 @@
<integer>5</integer>
<key>WindowOrderList</key>
<array>
<string>6BCF32991104D1B2009445BF</string>
<string>6BCF329A1104D1B2009445BF</string>
<string>/Users/memon/Code/recastnavigation/RecastDemo/Build/Xcode/Recast.xcodeproj</string>
</array>
<key>WindowString</key>

View File

@ -36,11 +36,11 @@
6BB788170FC0472B003C24DB /* ChunkyTriMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB788160FC0472B003C24DB /* ChunkyTriMesh.cpp */; };
6BB7FC0B10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */; };
6BB7FDA510F36F0E006DA0A6 /* InputGeom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB7FDA410F36F0E006DA0A6 /* InputGeom.cpp */; };
6BB7FE9110F4A192006DA0A6 /* OffMeshLinkTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB7FE9010F4A192006DA0A6 /* OffMeshLinkTool.cpp */; };
6BB93C7D10CFE1D500F74F2B /* DebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7A10CFE1D500F74F2B /* DebugDraw.cpp */; };
6BB93C7E10CFE1D500F74F2B /* DetourDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7B10CFE1D500F74F2B /* DetourDebugDraw.cpp */; };
6BB93C7F10CFE1D500F74F2B /* RecastDebugDraw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93C7C10CFE1D500F74F2B /* RecastDebugDraw.cpp */; };
6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */; };
6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */; };
8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
/* End PBXBuildFile section */
@ -100,8 +100,6 @@
6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NavMeshTesterTool.cpp; path = ../../Source/NavMeshTesterTool.cpp; sourceTree = SOURCE_ROOT; };
6BB7FDA310F36EFC006DA0A6 /* InputGeom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InputGeom.h; path = ../../Include/InputGeom.h; sourceTree = SOURCE_ROOT; };
6BB7FDA410F36F0E006DA0A6 /* InputGeom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InputGeom.cpp; path = ../../Source/InputGeom.cpp; sourceTree = SOURCE_ROOT; };
6BB7FE8F10F4A192006DA0A6 /* OffMeshLinkTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OffMeshLinkTool.h; path = ../../Include/OffMeshLinkTool.h; sourceTree = SOURCE_ROOT; };
6BB7FE9010F4A192006DA0A6 /* OffMeshLinkTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OffMeshLinkTool.cpp; path = ../../Source/OffMeshLinkTool.cpp; sourceTree = SOURCE_ROOT; };
6BB93C7710CFE1D500F74F2B /* DebugDraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DebugDraw.h; path = ../../../DebugUtils/Include/DebugDraw.h; sourceTree = SOURCE_ROOT; };
6BB93C7810CFE1D500F74F2B /* DetourDebugDraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DetourDebugDraw.h; path = ../../../DebugUtils/Include/DetourDebugDraw.h; sourceTree = SOURCE_ROOT; };
6BB93C7910CFE1D500F74F2B /* RecastDebugDraw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecastDebugDraw.h; path = ../../../DebugUtils/Include/RecastDebugDraw.h; sourceTree = SOURCE_ROOT; };
@ -110,6 +108,8 @@
6BB93C7C10CFE1D500F74F2B /* RecastDebugDraw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastDebugDraw.cpp; path = ../../../DebugUtils/Source/RecastDebugDraw.cpp; sourceTree = SOURCE_ROOT; };
6BB93CF410CFEC4500F74F2B /* RecastDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecastDump.h; path = ../../../DebugUtils/Include/RecastDump.h; sourceTree = SOURCE_ROOT; };
6BB93CF510CFEC4500F74F2B /* RecastDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RecastDump.cpp; path = ../../../DebugUtils/Source/RecastDump.cpp; sourceTree = SOURCE_ROOT; };
6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OffMeshConnectionTool.h; path = ../../Include/OffMeshConnectionTool.h; sourceTree = SOURCE_ROOT; };
6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OffMeshConnectionTool.cpp; path = ../../Source/OffMeshConnectionTool.cpp; sourceTree = SOURCE_ROOT; };
8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8D1107320486CEB800E47090 /* Recast.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Recast.app; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@ -259,8 +259,8 @@
6BB7FE8E10F4A175006DA0A6 /* Tools */ = {
isa = PBXGroup;
children = (
6BB7FE8F10F4A192006DA0A6 /* OffMeshLinkTool.h */,
6BB7FE9010F4A192006DA0A6 /* OffMeshLinkTool.cpp */,
6BCF32341104CD05009445BF /* OffMeshConnectionTool.h */,
6BCF32351104CD05009445BF /* OffMeshConnectionTool.cpp */,
6BB7FC0910EBB6AA006DA0A6 /* NavMeshTesterTool.h */,
6BB7FC0A10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp */,
);
@ -382,7 +382,7 @@
6BB93CF610CFEC4500F74F2B /* RecastDump.cpp in Sources */,
6BB7FC0B10EBB6AA006DA0A6 /* NavMeshTesterTool.cpp in Sources */,
6BB7FDA510F36F0E006DA0A6 /* InputGeom.cpp in Sources */,
6BB7FE9110F4A192006DA0A6 /* OffMeshLinkTool.cpp in Sources */,
6BCF32361104CD05009445BF /* OffMeshConnectionTool.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -28,10 +28,12 @@ class InputGeom
rcMeshLoaderObj* m_mesh;
float m_meshBMin[3], m_meshBMax[3];
static const int MAX_LINKS = 256;
static const int MAX_OFFMESH_CONNECTIONS = 256;
float m_linkVerts[MAX_LINKS*3*2];
int m_nlinks;
float m_offMeshConVerts[MAX_OFFMESH_CONNECTIONS*3*2];
float m_offMeshConRads[MAX_OFFMESH_CONNECTIONS];
unsigned char m_offMeshConDirs[MAX_OFFMESH_CONNECTIONS];
int m_offMeshConCount;
public:
InputGeom();
@ -47,11 +49,13 @@ public:
bool raycastMesh(float* src, float* dst, float& tmin);
// Extra links
int getOffMeshLinkCount() const { return m_nlinks; }
const float* getOffMeshLinkVertices() const { return m_linkVerts; }
void addOffMeshLink(const float* spos, const float* epos);
void deleteOffMeshLink(int i);
void drawLinks(struct duDebugDraw* dd, const float s);
int getOffMeshConnectionCount() const { return m_offMeshConCount; }
const float* getOffMeshConnectionVerts() const { return m_offMeshConVerts; }
const float* getOffMeshConnectionRads() const { return m_offMeshConRads; }
const unsigned char* getOffMeshConnectionDirs() const { return m_offMeshConDirs; }
void addOffMeshConnection(const float* spos, const float* epos, const float rad, unsigned char bidir);
void deleteOffMeshConnection(int i);
void drawOffMeshConnections(struct duDebugDraw* dd, bool hilight = false);
};
#endif // INPUTGEOM_H

View File

@ -29,6 +29,7 @@ class NavMeshTesterTool : public SampleTool
dtNavMesh* m_navMesh;
float m_agentRadius;
float m_agentHeight;
float m_agentClimb;
enum ToolMode
{

View File

@ -16,24 +16,25 @@
// 3. This notice may not be removed or altered from any source distribution.
//
#ifndef OFFMESHLINKTOOL_H
#define OFFMESHLINKTOOL_H
#ifndef OFFMESHCONNECTIONTOOL_H
#define OFFMESHCONNECTIONTOOL_H
#include "Sample.h"
// Tool to create extra links for InputGeom
class OffMeshLinkTool : public SampleTool
class OffMeshConnectionTool : public SampleTool
{
Sample* m_sample;
float m_hitPos[3];
bool m_hitPosSet;
bool m_bidir;
public:
OffMeshLinkTool();
~OffMeshLinkTool();
OffMeshConnectionTool();
~OffMeshConnectionTool();
virtual int type() { return TOOL_OFFMESH_LINK; }
virtual int type() { return TOOL_OFFMESH_CONNECTION; }
virtual void init(Sample* sample);
virtual void reset();
virtual void handleMenu();
@ -42,4 +43,4 @@ public:
virtual void handleRenderOverlay(double* proj, double* model, int* view);
};
#endif // OFFMESHLINKTOOL_H
#endif // OFFMESHCONNECTIONTOOL_H

View File

@ -24,6 +24,7 @@
struct DebugDrawGL : public duDebugDraw
{
virtual void depthMask(bool state);
virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f);
virtual void vertex(const float* pos, unsigned int color);
virtual void vertex(const float x, const float y, const float z, unsigned int color);
@ -35,7 +36,7 @@ enum SampleToolType
TOOL_NONE = 0,
TOOL_TILE_EDIT,
TOOL_NAVMESH_TESTER,
TOOL_OFFMESH_LINK,
TOOL_OFFMESH_CONNECTION,
};
struct SampleTool
@ -56,6 +57,7 @@ class Sample
protected:
class InputGeom* m_geom;
dtNavMesh* m_navMesh;
unsigned char m_navMeshDrawFlags;
float m_cellSize;
float m_cellHeight;
@ -92,6 +94,10 @@ public:
virtual class dtNavMesh* getNavMesh() { return m_navMesh; }
virtual float getAgentRadius() { return m_agentRadius; }
virtual float getAgentHeight() { return m_agentHeight; }
virtual float getAgentClimb() { return m_agentMaxClimb; }
inline unsigned char getNavMeshDrawFlags() const { return m_navMeshDrawFlags; }
inline void setNavMeshDrawFlags(unsigned char flags) { m_navMeshDrawFlags = flags; }
void resetCommonSettings();
void handleCommonSettings();

View File

@ -25,7 +25,7 @@
#include "MeshLoaderObj.h"
#include "DebugDraw.h"
#include "RecastDebugDraw.h"
#include "DetourNavMesh.h"
static bool intersectSegmentTriangle(const float* sp, const float* sq,
const float* a, const float* b, const float* c,
@ -72,7 +72,7 @@ static bool intersectSegmentTriangle(const float* sp, const float* sq,
InputGeom::InputGeom() :
m_chunkyMesh(0),
m_mesh(0),
m_nlinks(0)
m_offMeshConCount(0)
{
}
@ -90,8 +90,8 @@ bool InputGeom::loadMesh(const char* filepath)
m_chunkyMesh = 0;
delete m_mesh;
m_mesh = 0;
m_nlinks = 0;
}
m_offMeshConCount = 0;
m_mesh = new rcMeshLoaderObj;
if (!m_mesh)
@ -159,31 +159,52 @@ bool InputGeom::raycastMesh(float* src, float* dst, float& tmin)
return hit;
}
void InputGeom::addOffMeshLink(const float* spos, const float* epos)
void InputGeom::addOffMeshConnection(const float* spos, const float* epos, const float rad, unsigned char bidir)
{
if (m_nlinks >= MAX_LINKS) return;
float* v = &m_linkVerts[m_nlinks*3*2];
m_nlinks++;
if (m_offMeshConCount >= MAX_OFFMESH_CONNECTIONS) return;
float* v = &m_offMeshConVerts[m_offMeshConCount*3*2];
m_offMeshConRads[m_offMeshConCount] = rad;
m_offMeshConDirs[m_offMeshConCount] = bidir;
vcopy(&v[0], spos);
vcopy(&v[3], epos);
m_offMeshConCount++;
}
void InputGeom::deleteOffMeshLink(int i)
void InputGeom::deleteOffMeshConnection(int i)
{
m_nlinks--;
float* src = &m_linkVerts[(m_nlinks-1)*3*2];
float* dst = &m_linkVerts[i*3*2];
m_offMeshConCount--;
float* src = &m_offMeshConVerts[m_offMeshConCount*3*2];
float* dst = &m_offMeshConVerts[i*3*2];
vcopy(&dst[0], &src[0]);
vcopy(&dst[3], &src[3]);
m_offMeshConRads[i] = m_offMeshConRads[m_offMeshConCount];
m_offMeshConDirs[i] = m_offMeshConDirs[m_offMeshConCount];
}
void InputGeom::drawLinks(duDebugDraw* dd, const float s)
void InputGeom::drawOffMeshConnections(duDebugDraw* dd, bool hilight)
{
for (int i = 0; i < m_nlinks; ++i)
unsigned int conColor = duRGBA(192,192,192,hilight?192:64);
unsigned int baseColor = duRGBA(0,0,0,hilight?192:64);
dd->depthMask(false);
dd->begin(DU_DRAW_LINES, 2.0f);
for (int i = 0; i < m_offMeshConCount; ++i)
{
float* v = &m_linkVerts[i*3*2];
duDebugDrawArc(dd, v[0],v[1],v[2], v[3],v[4],v[5], 0.25f, duRGBA(255,255,255,192), 1.0f);
duDebugDrawCross(dd, v[0],v[1]+0.1f,v[2], s, duRGBA(0,0,0,255), 2.0f);
duDebugDrawCross(dd, v[3],v[4]+0.1f,v[5], s, duRGBA(0,0,0,255), 2.0f);
float* v = &m_offMeshConVerts[i*3*2];
dd->vertex(v[0],v[1],v[2], baseColor);
dd->vertex(v[0],v[1]+0.2f,v[2], baseColor);
dd->vertex(v[3],v[4],v[5], baseColor);
dd->vertex(v[3],v[4]+0.2f,v[5], baseColor);
duAppendCircle(dd, v[0],v[1]+0.1f,v[2], m_offMeshConRads[i], baseColor);
duAppendCircle(dd, v[3],v[4]+0.1f,v[5], m_offMeshConRads[i], baseColor);
duAppendArc(dd, v[0],v[1],v[2], v[3],v[4],v[5], 0.25f,
(m_offMeshConDirs[i]&1) ? 0.6f : 0.0f, 0.6f, conColor);
}
dd->end();
dd->depthMask(true);
}

View File

@ -66,6 +66,13 @@ NavMeshTesterTool::NavMeshTesterTool() :
NavMeshTesterTool::~NavMeshTesterTool()
{
if (m_sample)
{
unsigned char flags = DU_DRAWNAVMESH_CLOSEDLIST;
if (m_navMesh)
flags |= DU_DRAWNAVMESH_OFFMESHCONS;
m_sample->setNavMeshDrawFlags(flags);
}
}
void NavMeshTesterTool::init(Sample* sample)
@ -73,8 +80,18 @@ void NavMeshTesterTool::init(Sample* sample)
m_sample = sample;
m_agentRadius = sample->getAgentRadius();
m_agentHeight = sample->getAgentHeight();
m_agentClimb = sample->getAgentClimb();
m_navMesh = sample->getNavMesh();
recalc();
if (m_toolMode == TOOLMODE_PATHFIND)
{
unsigned char flags = DU_DRAWNAVMESH_CLOSEDLIST;
if (m_navMesh)
flags |= DU_DRAWNAVMESH_OFFMESHCONS;
m_sample->setNavMeshDrawFlags(flags);
}
}
void NavMeshTesterTool::handleMenu()
@ -99,6 +116,21 @@ void NavMeshTesterTool::handleMenu()
m_toolMode = TOOLMODE_FIND_POLYS_AROUND;
recalc();
}
if (m_toolMode == TOOLMODE_PATHFIND)
{
unsigned char flags = DU_DRAWNAVMESH_CLOSEDLIST;
if (m_navMesh)
flags |= DU_DRAWNAVMESH_OFFMESHCONS;
m_sample->setNavMeshDrawFlags(flags);
}
else
{
unsigned char flags = 0;
if (m_navMesh)
flags |= DU_DRAWNAVMESH_OFFMESHCONS;
m_sample->setNavMeshDrawFlags(flags);
}
}
void NavMeshTesterTool::handleClick(const float* p, bool shift)
@ -148,7 +180,7 @@ static bool getSteerTarget(dtNavMesh* navMesh, const float* startPos, const floa
while (ns < nsteerPath)
{
// Stop at Off-Mesh link or when point is further than slop away.
if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_LINK) ||
if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ||
!inRange(&steerPath[ns*3], startPos, minTargetDist, 1000.0f))
break;
ns++;
@ -171,12 +203,12 @@ void NavMeshTesterTool::recalc()
return;
if (m_sposSet)
m_startRef = m_navMesh->findNearestPoly(m_spos, m_polyPickExt);
m_startRef = m_navMesh->findNearestPoly(m_spos, m_polyPickExt, 0);
else
m_startRef = 0;
if (m_eposSet)
m_endRef = m_navMesh->findNearestPoly(m_epos, m_polyPickExt);
m_endRef = m_navMesh->findNearestPoly(m_epos, m_polyPickExt, 0);
else
m_endRef = 0;
@ -225,14 +257,14 @@ void NavMeshTesterTool::recalc()
break;
bool endOfPath = steerPosFlag & DT_STRAIGHTPATH_END;
bool offMeshLink = steerPosFlag & DT_STRAIGHTPATH_OFFMESH_LINK;
bool offMeshConnection = steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION;
// Find movement delta.
float delta[3], len;
vsub(delta, steerPos, iterPos);
len = sqrtf(vdot(delta,delta));
// If the steer target is end of path or off-mesh link, do not move past the location.
if ((endOfPath || offMeshLink) && len < STEP_SIZE)
if ((endOfPath || offMeshConnection) && len < STEP_SIZE)
len = 1;
else
len = STEP_SIZE / len;
@ -266,12 +298,12 @@ void NavMeshTesterTool::recalc()
}
break;
}
else if (offMeshLink && inRange(iterPos, steerPos, SLOP, 1.0f))
else if (offMeshConnection && inRange(iterPos, steerPos, SLOP, 1.0f))
{
// Reached off-mesh link.
// Reached off-mesh connection.
float startPos[3], endPos[3];
// Advance the path up to and over the off-mesh link.
// Advance the path up to and over the off-mesh connection.
dtPolyRef prevRef = 0, polyRef = polys[0];
while (npolys && polyRef != steerPosRef)
{
@ -281,16 +313,25 @@ void NavMeshTesterTool::recalc()
npolys--;
}
// Handle the link.
if (m_navMesh->getOffMeshLinkPolyEndPoints(prevRef, polyRef, startPos, endPos))
// Handle the connection.
if (m_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))
{
if (m_nsmoothPath < MAX_SMOOTH)
{
vcopy(&m_smoothPath[m_nsmoothPath*3], startPos);
m_nsmoothPath++;
// Hack to make the dotted path not visible during off-mesh connection.
if (m_nsmoothPath & 1)
{
vcopy(&m_smoothPath[m_nsmoothPath*3], startPos);
m_nsmoothPath++;
}
}
// Move position at the other side of the off-mesh link.
vcopy(iterPos, endPos);
float h;
m_navMesh->getPolyHeight(polys[0], iterPos, &h);
iterPos[1] = h;
}
}
@ -359,14 +400,14 @@ static void getPolyCenter(dtNavMesh* navMesh, dtPolyRef ref, float* center)
center[0] = 0;
center[1] = 0;
center[2] = 0;
for (int i = 0; i < (int)p->nv; ++i)
for (int i = 0; i < (int)p->vertCount; ++i)
{
const float* v = &verts[p->v[i]*3];
const float* v = &verts[p->verts[i]*3];
center[0] += v[0];
center[1] += v[1];
center[2] += v[2];
}
const float s = 1.0f / p->nv;
const float s = 1.0f / p->vertCount;
center[0] *= s;
center[1] *= s;
center[2] *= s;
@ -390,14 +431,6 @@ void NavMeshTesterTool::handleRender()
if (m_eposSet)
drawAgent(m_epos, m_agentRadius, m_agentHeight, 0/*m_agentMaxClimb*/, endCol);
/* if (flags & NAVMESH_POLYS)
duDebugDrawNavMesh(&dd, m_navMesh, m_toolMode == TOOLMODE_PATHFIND);
if (flags & NAVMESH_BVTREE)
duDebugDrawNavMeshBVTree(&dd, m_navMesh);
if (flags & NAVMESH_TOOLS)*/
{
if (m_toolMode == TOOLMODE_PATHFIND)
{
duDebugDrawNavMeshPoly(&dd, m_navMesh, m_startRef, startCol);
@ -417,7 +450,7 @@ void NavMeshTesterTool::handleRender()
for (int i = 0; i < m_nstraightPath-1; ++i)
{
unsigned int col = 0;
if (m_straightPathFlags[i] & DT_STRAIGHTPATH_OFFMESH_LINK)
if (m_straightPathFlags[i] & DT_STRAIGHTPATH_OFFMESH_CONNECTION)
col = offMeshCol;
else
col = pathCol;
@ -434,7 +467,7 @@ void NavMeshTesterTool::handleRender()
col = startCol;
else if (m_straightPathFlags[i] & DT_STRAIGHTPATH_START)
col = endCol;
else if (m_straightPathFlags[i] & DT_STRAIGHTPATH_OFFMESH_LINK)
else if (m_straightPathFlags[i] & DT_STRAIGHTPATH_OFFMESH_CONNECTION)
col = offMeshCol;
else
col = pathCol;
@ -504,16 +537,22 @@ void NavMeshTesterTool::handleRender()
if (m_parent[i])
{
float p0[3], p1[3];
getPolyCenter(m_navMesh, m_polys[i], p0);
getPolyCenter(m_navMesh, m_parent[i], p1);
duDebugDrawArc(&dd, p0[0],p0[1],p0[2], p1[0],p1[1],p1[2], 0.25f, duRGBA(0,0,0,128), 2.0f);
dd.depthMask(false);
getPolyCenter(m_navMesh, m_parent[i], p0);
getPolyCenter(m_navMesh, m_polys[i], p1);
duDebugDrawArc(&dd, p0[0],p0[1],p0[2], p1[0],p1[1],p1[2], 0.25f, 0.0f, 0.4f, duRGBA(0,0,0,128), 2.0f);
dd.depthMask(true);
}
}
if (m_sposSet && m_eposSet)
{
dd.depthMask(false);
const float dx = m_epos[0] - m_spos[0];
const float dz = m_epos[2] - m_spos[2];
const float dist = sqrtf(dx*dx + dz*dz);
duDebugDrawCircle(&dd, m_spos[0], m_spos[1]+m_agentHeight/2, m_spos[2], dist, duRGBA(64,16,0,220), 2.0f);
dd.depthMask(true);
}
}

View File

@ -24,7 +24,7 @@
#include "SDL.h"
#include "SDL_opengl.h"
#include "imgui.h"
#include "OffMeshLinkTool.h"
#include "OffMeshConnectionTool.h"
#include "InputGeom.h"
#include "Sample.h"
#include "Recast.h"
@ -35,39 +35,47 @@
# define snprintf _snprintf
#endif
OffMeshLinkTool::OffMeshLinkTool() :
OffMeshConnectionTool::OffMeshConnectionTool() :
m_sample(0),
m_hitPosSet(0)
m_hitPosSet(0),
m_bidir(true)
{
}
OffMeshLinkTool::~OffMeshLinkTool()
OffMeshConnectionTool::~OffMeshConnectionTool()
{
}
void OffMeshLinkTool::init(Sample* sample)
void OffMeshConnectionTool::init(Sample* sample)
{
m_sample = sample;
if (m_sample)
m_sample->setNavMeshDrawFlags(0);
}
void OffMeshLinkTool::reset()
void OffMeshConnectionTool::reset()
{
m_hitPosSet = false;
}
void OffMeshLinkTool::handleMenu()
void OffMeshConnectionTool::handleMenu()
{
if (m_hitPosSet)
if (imguiCheck("One Way", !m_bidir))
m_bidir = false;
if (imguiCheck("Bidirectional", m_bidir))
m_bidir = true;
if (!m_hitPosSet)
{
imguiValue("Click to set link start.");
imguiValue("Click to set connection start.");
}
else
{
imguiValue("Click to set link end.");
imguiValue("Click to set connection end.");
}
}
void OffMeshLinkTool::handleClick(const float* p, bool shift)
void OffMeshConnectionTool::handleClick(const float* p, bool shift)
{
if (!m_sample) return;
InputGeom* geom = m_sample->getInputGeom();
@ -79,8 +87,8 @@ void OffMeshLinkTool::handleClick(const float* p, bool shift)
// Find nearest link end-point
float nearestDist = FLT_MAX;
int nearestIndex = -1;
const float* verts = geom->getOffMeshLinkVertices();
for (int i = 0; i < geom->getOffMeshLinkCount()*2; ++i)
const float* verts = geom->getOffMeshConnectionVerts();
for (int i = 0; i < geom->getOffMeshConnectionCount()*2; ++i)
{
const float* v = &verts[i*3];
float d = vdistSqr(p, v);
@ -94,7 +102,7 @@ void OffMeshLinkTool::handleClick(const float* p, bool shift)
if (nearestIndex != -1 &&
sqrtf(nearestDist) < m_sample->getAgentRadius())
{
geom->deleteOffMeshLink(nearestIndex);
geom->deleteOffMeshConnection(nearestIndex);
}
}
else
@ -107,14 +115,14 @@ void OffMeshLinkTool::handleClick(const float* p, bool shift)
}
else
{
geom->addOffMeshLink(m_hitPos, p);
geom->addOffMeshConnection(m_hitPos, p, m_sample->getAgentRadius(), m_bidir ? 1 : 0);
m_hitPosSet = false;
}
}
}
void OffMeshLinkTool::handleRender()
void OffMeshConnectionTool::handleRender()
{
DebugDrawGL dd;
const float s = m_sample->getAgentRadius();
@ -124,10 +132,10 @@ void OffMeshLinkTool::handleRender()
InputGeom* geom = m_sample->getInputGeom();
if (geom)
geom->drawLinks(&dd, s);
geom->drawOffMeshConnections(&dd, true);
}
void OffMeshLinkTool::handleRenderOverlay(double* proj, double* model, int* view)
void OffMeshConnectionTool::handleRenderOverlay(double* proj, double* model, int* view)
{
GLdouble x, y, z;

View File

@ -23,6 +23,7 @@
#include "InputGeom.h"
#include "Recast.h"
#include "RecastDebugDraw.h"
#include "DetourDebugDraw.h"
#include "imgui.h"
#include "SDL.h"
#include "SDL_opengl.h"
@ -32,6 +33,11 @@
#endif
void DebugDrawGL::depthMask(bool state)
{
glDepthMask(state ? GL_TRUE : GL_FALSE);
}
void DebugDrawGL::begin(duDebugDrawPrimitives prim, float size)
{
switch (prim)
@ -76,6 +82,7 @@ void DebugDrawGL::end()
Sample::Sample() :
m_geom(0),
m_navMesh(0),
m_navMeshDrawFlags(DU_DRAWNAVMESH_CLOSEDLIST),
m_tool(0)
{
resetCommonSettings();

View File

@ -34,7 +34,7 @@
#include "DetourNavMeshBuilder.h"
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "OffMeshLinkTool.h"
#include "OffMeshConnectionTool.h"
#ifdef WIN32
# define snprintf _snprintf
@ -95,9 +95,9 @@ void Sample_SoloMeshSimple::handleTools()
{
setTool(new NavMeshTesterTool);
}
if (imguiCheck("Create Off-Mesh Links", type == TOOL_OFFMESH_LINK))
if (imguiCheck("Create Off-Mesh Connections", type == TOOL_OFFMESH_CONNECTION))
{
setTool(new OffMeshLinkTool);
setTool(new OffMeshConnectionTool);
}
imguiSeparator();
@ -197,14 +197,16 @@ void Sample_SoloMeshSimple::handleRender()
duDebugDrawTriMeshSlope(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(),
m_agentMaxSlope);
m_geom->drawLinks(&dd, m_agentRadius);
if ((m_navMeshDrawFlags & DU_DRAWNAVMESH_OFFMESHCONS) == 0)
m_geom->drawOffMeshConnections(&dd);
}
else if (m_drawMode != DRAWMODE_NAVMESH_TRANS)
{
// Draw mesh
duDebugDrawTriMesh(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(), 0);
m_geom->drawLinks(&dd, m_agentRadius);
if ((m_navMeshDrawFlags & DU_DRAWNAVMESH_OFFMESHCONS) == 0)
m_geom->drawOffMeshConnections(&dd);
}
glDisable(GL_FOG);
@ -222,7 +224,7 @@ void Sample_SoloMeshSimple::handleRender()
m_drawMode == DRAWMODE_NAVMESH_INVIS))
{
if (m_drawMode != DRAWMODE_NAVMESH_INVIS)
duDebugDrawNavMesh(&dd, m_navMesh); //, m_toolMode == TOOLMODE_PATHFIND);
duDebugDrawNavMesh(&dd, m_navMesh, m_navMeshDrawFlags);
if (m_drawMode == DRAWMODE_NAVMESH_BVTREE)
duDebugDrawNavMeshBVTree(&dd, m_navMesh);
}
@ -550,13 +552,32 @@ bool Sample_SoloMeshSimple::handleBuild()
{
unsigned char* navData = 0;
int navDataSize = 0;
if (!dtCreateNavMeshData(m_pmesh->verts, m_pmesh->nverts,
m_pmesh->polys, m_pmesh->npolys, m_pmesh->nvp,
m_dmesh->meshes, m_dmesh->verts, m_dmesh->nverts,
m_dmesh->tris, m_dmesh->ntris,
m_geom->getOffMeshLinkVertices(), m_geom->getOffMeshLinkCount(),
m_pmesh->bmin, m_pmesh->bmax, m_cfg.cs, m_cfg.ch, 0, m_cfg.walkableClimb,
&navData, &navDataSize))
dtNavMeshCreateParams params;
memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys;
params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp;
params.detailMeshes = m_dmesh->meshes;
params.detailVerts = m_dmesh->verts;
params.detailVertsCount = m_dmesh->nverts;
params.detailTris = m_dmesh->tris;
params.detailTriCount = m_dmesh->ntris;
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConCount = m_geom->getOffMeshConnectionCount();
params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius;
params.walkableClimb = m_agentMaxClimb;
vcopy(params.bmin, m_pmesh->bmin);
vcopy(params.bmax, m_pmesh->bmax);
params.cs = m_cfg.cs;
params.ch = m_cfg.ch;
if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
@ -618,6 +639,8 @@ bool Sample_SoloMeshSimple::handleBuild()
rcGetLog()->log(RC_LOG_PROGRESS, "TOTAL: %.1fms", rcGetDeltaTimeUsec(totStartTime, totEndTime)/1000.0f);
}
setNavMeshDrawFlags(DU_DRAWNAVMESH_OFFMESHCONS);
if (m_tool)
m_tool->init(this);

View File

@ -33,7 +33,7 @@
#include "DetourNavMeshBuilder.h"
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "OffMeshLinkTool.h"
#include "OffMeshConnectionTool.h"
#ifdef WIN32
# define snprintf _snprintf
@ -110,9 +110,9 @@ void Sample_SoloMeshTiled::handleTools()
{
setTool(new NavMeshTesterTool);
}
if (imguiCheck("Create Off-Mesh Links", type == TOOL_OFFMESH_LINK))
if (imguiCheck("Create Off-Mesh Links", type == TOOL_OFFMESH_CONNECTION))
{
setTool(new OffMeshLinkTool);
setTool(new OffMeshConnectionTool);
}
imguiSeparator();
@ -231,14 +231,16 @@ void Sample_SoloMeshTiled::handleRender()
duDebugDrawTriMeshSlope(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(),
m_agentMaxSlope);
m_geom->drawLinks(&dd, m_agentRadius);
if ((m_navMeshDrawFlags & DU_DRAWNAVMESH_OFFMESHCONS) == 0)
m_geom->drawOffMeshConnections(&dd);
}
else if (m_drawMode != DRAWMODE_NAVMESH_TRANS)
{
// Draw mesh
duDebugDrawTriMesh(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(), 0);
m_geom->drawLinks(&dd, m_agentRadius);
if ((m_navMeshDrawFlags & DU_DRAWNAVMESH_OFFMESHCONS) == 0)
m_geom->drawOffMeshConnections(&dd);
}
glDisable(GL_FOG);
@ -264,7 +266,7 @@ void Sample_SoloMeshTiled::handleRender()
m_drawMode == DRAWMODE_NAVMESH_INVIS))
{
if (m_drawMode != DRAWMODE_NAVMESH_INVIS)
duDebugDrawNavMesh(&dd, m_navMesh); //, m_toolMode == TOOLMODE_PATHFIND);
duDebugDrawNavMesh(&dd, m_navMesh, m_navMeshDrawFlags);
if (m_drawMode == DRAWMODE_NAVMESH_BVTREE)
duDebugDrawNavMeshBVTree(&dd, m_navMesh);
}
@ -922,13 +924,32 @@ bool Sample_SoloMeshTiled::handleBuild()
{
unsigned char* navData = 0;
int navDataSize = 0;
if (!dtCreateNavMeshData(m_pmesh->verts, m_pmesh->nverts,
m_pmesh->polys, m_pmesh->npolys, m_pmesh->nvp,
m_dmesh->meshes, m_dmesh->verts, m_dmesh->nverts,
m_dmesh->tris, m_dmesh->ntris,
0, 0,
m_pmesh->bmin, m_pmesh->bmax, m_cfg.cs, m_cfg.ch, 0, m_cfg.walkableClimb,
&navData, &navDataSize))
dtNavMeshCreateParams params;
memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys;
params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp;
params.detailMeshes = m_dmesh->meshes;
params.detailVerts = m_dmesh->verts;
params.detailVertsCount = m_dmesh->nverts;
params.detailTris = m_dmesh->tris;
params.detailTriCount = m_dmesh->ntris;
params.offMeshConVerts = 0;
params.offMeshConRad = 0;
params.offMeshConDir = 0;
params.offMeshConCount = 0;
params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius;
params.walkableClimb = m_agentMaxClimb;
vcopy(params.bmin, m_pmesh->bmin);
vcopy(params.bmax, m_pmesh->bmax);
params.cs = m_cfg.cs;
params.ch = m_cfg.ch;
if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "Could not build Detour navmesh.");
@ -992,6 +1013,8 @@ bool Sample_SoloMeshTiled::handleBuild()
rcGetLog()->log(RC_LOG_PROGRESS, "TOTAL: %.1fms", rcGetDeltaTimeUsec(totStartTime, totEndTime)/1000.0f);
}
setNavMeshDrawFlags(DU_DRAWNAVMESH_OFFMESHCONS);
if (m_tool)
m_tool->init(this);

View File

@ -33,7 +33,7 @@
#include "DetourNavMeshBuilder.h"
#include "DetourDebugDraw.h"
#include "NavMeshTesterTool.h"
#include "OffMeshLinkTool.h"
#include "OffMeshConnectionTool.h"
#ifdef WIN32
# define snprintf _snprintf
@ -253,9 +253,9 @@ void Sample_TileMesh::handleTools()
{
setTool(new NavMeshTileTool);
}
if (imguiCheck("Create Off-Mesh Links", type == TOOL_OFFMESH_LINK))
if (imguiCheck("Create Off-Mesh Links", type == TOOL_OFFMESH_CONNECTION))
{
setTool(new OffMeshLinkTool);
setTool(new OffMeshConnectionTool);
}
imguiSeparator();
@ -288,14 +288,14 @@ static void getPolyCenter(dtNavMesh* navMesh, dtPolyRef ref, float* center)
center[0] = 0;
center[1] = 0;
center[2] = 0;
for (int i = 0; i < (int)p->nv; ++i)
for (int i = 0; i < (int)p->vertCount; ++i)
{
const float* v = &verts[p->v[i]*3];
const float* v = &verts[p->verts[i]*3];
center[0] += v[0];
center[1] += v[1];
center[2] += v[2];
}
const float s = 1.0f / p->nv;
const float s = 1.0f / p->vertCount;
center[0] *= s;
center[1] *= s;
center[2] *= s;
@ -311,7 +311,8 @@ void Sample_TileMesh::handleRender()
// Draw mesh
duDebugDrawTriMesh(&dd, m_geom->getMesh()->getVerts(), m_geom->getMesh()->getVertCount(),
m_geom->getMesh()->getTris(), m_geom->getMesh()->getNormals(), m_geom->getMesh()->getTriCount(), 0);
m_geom->drawLinks(&dd, m_agentRadius);
if ((m_navMeshDrawFlags & DU_DRAWNAVMESH_OFFMESHCONS) == 0)
m_geom->drawOffMeshConnections(&dd);
glDepthMask(GL_FALSE);
@ -332,7 +333,7 @@ void Sample_TileMesh::handleRender()
duDebugDrawBoxWire(&dd, m_tileBmin[0],m_tileBmin[1],m_tileBmin[2], m_tileBmax[0],m_tileBmax[1],m_tileBmax[2], m_tileCol, 2.0f);
if (m_navMesh)
duDebugDrawNavMesh(&dd, m_navMesh);
duDebugDrawNavMesh(&dd, m_navMesh, m_navMeshDrawFlags);
if (m_tool)
m_tool->handleRender();
@ -392,9 +393,8 @@ bool Sample_TileMesh::handleBuild()
const float* bmin = m_geom->getMeshBoundsMin();
const float tileWorldWidth = m_tileSize*m_cellSize;
const float tileWorldHeight = m_tileSize*m_cellSize;
const float portalHeight = m_agentMaxClimb*m_cellHeight;
if (!m_navMesh->init(bmin, tileWorldWidth, tileWorldHeight, portalHeight, m_maxTiles, m_maxPolysPerTile, 2048))
if (!m_navMesh->init(bmin, tileWorldWidth, tileWorldHeight, m_maxTiles, m_maxPolysPerTile, 2048))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "buildTiledNavigation: Could not init navmesh.");
@ -404,6 +404,8 @@ bool Sample_TileMesh::handleBuild()
if (m_buildAll)
buildAllTiles();
setNavMeshDrawFlags(DU_DRAWNAVMESH_OFFMESHCONS);
if (m_tool)
m_tool->init(this);
@ -782,12 +784,32 @@ unsigned char* Sample_TileMesh::buildTileMesh(const float* bmin, const float* bm
return false;
}*/
if (!dtCreateNavMeshData(m_pmesh->verts, m_pmesh->nverts,
m_pmesh->polys, m_pmesh->npolys, m_pmesh->nvp,
m_dmesh->meshes, m_dmesh->verts, m_dmesh->nverts, m_dmesh->tris, m_dmesh->ntris,
0, 0,
bmin, bmax, m_cfg.cs, m_cfg.ch, m_cfg.tileSize, m_cfg.walkableClimb,
&navData, &navDataSize))
dtNavMeshCreateParams params;
memset(&params, 0, sizeof(params));
params.verts = m_pmesh->verts;
params.vertCount = m_pmesh->nverts;
params.polys = m_pmesh->polys;
params.polyCount = m_pmesh->npolys;
params.nvp = m_pmesh->nvp;
params.detailMeshes = m_dmesh->meshes;
params.detailVerts = m_dmesh->verts;
params.detailVertsCount = m_dmesh->nverts;
params.detailTris = m_dmesh->tris;
params.detailTriCount = m_dmesh->ntris;
params.offMeshConVerts = 0;
params.offMeshConRad = 0;
params.offMeshConDir = 0;
params.offMeshConCount = 0;
params.walkableHeight = m_agentHeight;
params.walkableRadius = m_agentRadius;
params.walkableClimb = m_agentMaxClimb;
vcopy(params.bmin, bmin);
vcopy(params.bmax, bmax);
params.cs = m_cfg.cs;
params.ch = m_cfg.ch;
params.tileSize = m_cfg.tileSize;
if (!dtCreateNavMeshData(&params, &navData, &navDataSize))
{
if (rcGetLog())
rcGetLog()->log(RC_LOG_ERROR, "Could not build Detour navmesh.");