mirror of
https://github.com/recastnavigation/recastnavigation.git
synced 2026-09-26 12:06:20 +00:00
Monster update which adds detail height meshes.
- Added detail height mesh generation (RecastDetailMesh.cpp) for single,tiled statmeshes as well as tilemesh. - Added feature to contour tracing which detects extra vertices along tile edges which should be removed later. - Changed the tiled stat mesh preprocess, so that it first generated polymeshes per tile and finally combines them. - Fixed bug in the GUI code where invisible buttons could be pressed.
This commit is contained in:
@@ -23,24 +23,47 @@
|
||||
|
||||
void dtDebugDrawStatNavMeshPoly(const dtStatNavMesh* mesh, dtStatPolyRef ref, const float* col)
|
||||
{
|
||||
const dtStatPoly* p = mesh->getPolyByRef(ref);
|
||||
if (!p)
|
||||
return;
|
||||
int idx = mesh->getPolyIndexByRef(ref);
|
||||
if (idx == -1) return;
|
||||
|
||||
glColor4f(col[0],col[1],col[2],0.25f);
|
||||
glBegin(GL_TRIANGLES);
|
||||
unsigned short vi[3];
|
||||
for (int j = 2; j < (int)p->nv; ++j)
|
||||
|
||||
if (mesh->getPolyDetailCount())
|
||||
{
|
||||
vi[0] = p->v[0];
|
||||
vi[1] = p->v[j-1];
|
||||
vi[2] = p->v[j];
|
||||
for (int k = 0; k < 3; ++k)
|
||||
const dtStatPoly* p = mesh->getPoly(idx);
|
||||
const dtStatPolyDetail* pd = mesh->getPolyDetail(idx);
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int j = 0; j < pd->ntris; ++j)
|
||||
{
|
||||
const float* v = mesh->getVertex(vi[k]);
|
||||
glVertex3f(v[0], v[1]+0.2f, v[2]);
|
||||
const unsigned char* t = mesh->getDetailTri(pd->tbase+j);
|
||||
for (int k = 0; k < 3; ++k)
|
||||
{
|
||||
if (t[k] < p->nv)
|
||||
glVertex3fv(mesh->getVertex(p->v[t[k]]));
|
||||
else
|
||||
glVertex3fv(mesh->getDetailVertex(pd->vbase+(t[k]-p->nv)));
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
const dtStatPoly* p = mesh->getPoly(idx);
|
||||
glBegin(GL_TRIANGLES);
|
||||
unsigned short vi[3];
|
||||
for (int j = 2; j < (int)p->nv; ++j)
|
||||
{
|
||||
vi[0] = p->v[0];
|
||||
vi[1] = p->v[j-1];
|
||||
vi[2] = p->v[j];
|
||||
for (int k = 0; k < 3; ++k)
|
||||
{
|
||||
const float* v = mesh->getVertex(vi[k]);
|
||||
glVertex3f(v[0], v[1]+0.2f, v[2]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void drawBoxWire(float minx, float miny, float minz, float maxx, float maxy, float maxz, const float* col)
|
||||
@@ -103,76 +126,113 @@ void dtDebugDrawStatNavMeshBVTree(const dtStatNavMesh* mesh)
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void dtDebugDrawStatNavMesh(const dtStatNavMesh* mesh, bool drawClosedList)
|
||||
|
||||
static float distancePtLine2d(const float* pt, const float* p, const float* q)
|
||||
{
|
||||
glBegin(GL_TRIANGLES);
|
||||
float pqx = q[0] - p[0];
|
||||
float pqz = q[2] - p[2];
|
||||
float dx = pt[0] - p[0];
|
||||
float dz = pt[2] - p[2];
|
||||
float d = pqx*pqx + pqz*pqz;
|
||||
float t = pqx*dx + pqz*dz;
|
||||
if (d != 0) t /= d;
|
||||
dx = p[0] + t*pqx - pt[0];
|
||||
dz = p[2] + t*pqz - pt[2];
|
||||
return dx*dx + dz*dz;
|
||||
}
|
||||
|
||||
static void drawStatMeshPolyBoundaries(const dtStatNavMesh* mesh, bool inner)
|
||||
{
|
||||
static const float thr = 0.01f*0.01f;
|
||||
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < mesh->getPolyCount(); ++i)
|
||||
{
|
||||
const dtStatPoly* p = mesh->getPoly(i);
|
||||
const dtStatPolyDetail* pd = mesh->getPolyDetail(i);
|
||||
|
||||
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
|
||||
{
|
||||
if (inner)
|
||||
{
|
||||
// Skip non-connected edges.
|
||||
if (p->n[j] == 0) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip connected edges.
|
||||
if (p->n[j] != 0) continue;
|
||||
}
|
||||
|
||||
const float* v0 = mesh->getVertex(p->v[j]);
|
||||
const float* v1 = mesh->getVertex(p->v[(j+1) % nj]);
|
||||
|
||||
// Draw detail mesh edges which align with the actual poly edge.
|
||||
// This is really slow.
|
||||
for (int k = 0; k < pd->ntris; ++k)
|
||||
{
|
||||
const unsigned char* t = mesh->getDetailTri(pd->tbase+k);
|
||||
const float* tv[3];
|
||||
for (int m = 0; m < 3; ++m)
|
||||
{
|
||||
if (t[m] < p->nv)
|
||||
tv[m] = mesh->getVertex(p->v[t[m]]);
|
||||
else
|
||||
tv[m] = mesh->getDetailVertex(pd->vbase+(t[m]-p->nv));
|
||||
}
|
||||
for (int m = 0, n = 2; m < 3; n=m++)
|
||||
{
|
||||
if (((t[3] >> (n*2)) & 0x3) == 0) continue; // Skip inner edges.
|
||||
if (distancePtLine2d(tv[n],v0,v1) < thr &&
|
||||
distancePtLine2d(tv[m],v0,v1) < thr)
|
||||
{
|
||||
glVertex3fv(tv[n]);
|
||||
glVertex3fv(tv[m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void dtDebugDrawStatNavMesh(const dtStatNavMesh* mesh, bool drawClosedList)
|
||||
{
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int i = 0; i < mesh->getPolyDetailCount(); ++i)
|
||||
{
|
||||
const dtStatPoly* p = mesh->getPoly(i);
|
||||
const dtStatPolyDetail* pd = mesh->getPolyDetail(i);
|
||||
|
||||
if (drawClosedList && mesh->isInClosedList(i+1))
|
||||
glColor4ub(255,196,0,64);
|
||||
else
|
||||
glColor4ub(0,196,255,64);
|
||||
|
||||
unsigned short vi[3];
|
||||
for (int j = 2; j < (int)p->nv; ++j)
|
||||
|
||||
for (int j = 0; j < pd->ntris; ++j)
|
||||
{
|
||||
vi[0] = p->v[0];
|
||||
vi[1] = p->v[j-1];
|
||||
vi[2] = p->v[j];
|
||||
const unsigned char* t = mesh->getDetailTri(pd->tbase+j);
|
||||
for (int k = 0; k < 3; ++k)
|
||||
{
|
||||
const float* v = mesh->getVertex(vi[k]);
|
||||
glVertex3f(v[0], v[1]+0.2f, v[2]);
|
||||
if (t[k] < p->nv)
|
||||
glVertex3fv(mesh->getVertex(p->v[t[k]]));
|
||||
else
|
||||
glVertex3fv(mesh->getDetailVertex(pd->vbase+(t[k]-p->nv)));
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// Draw tri boundaries
|
||||
// Draw inter poly boundaries
|
||||
glColor4ub(0,48,64,32);
|
||||
glLineWidth(1.5f);
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < mesh->getPolyCount(); ++i)
|
||||
{
|
||||
const dtStatPoly* p = mesh->getPoly(i);
|
||||
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
|
||||
{
|
||||
if (p->n[j] == 0) continue;
|
||||
int vi[2];
|
||||
vi[0] = p->v[j];
|
||||
vi[1] = p->v[(j+1) % nj];
|
||||
for (int k = 0; k < 2; ++k)
|
||||
{
|
||||
const float* v = mesh->getVertex(vi[k]);
|
||||
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
drawStatMeshPolyBoundaries(mesh, true);
|
||||
|
||||
// Draw boundaries
|
||||
// Draw outer poly boundaries
|
||||
glLineWidth(2.5f);
|
||||
glColor4ub(0,48,64,220);
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < mesh->getPolyCount(); ++i)
|
||||
{
|
||||
const dtStatPoly* p = mesh->getPoly(i);
|
||||
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
|
||||
{
|
||||
if (p->n[j] != 0) continue;
|
||||
int vi[2];
|
||||
vi[0] = p->v[j];
|
||||
vi[1] = p->v[(j+1) % nj];
|
||||
for (int k = 0; k < 2; ++k)
|
||||
{
|
||||
const float* v = mesh->getVertex(vi[k]);
|
||||
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
drawStatMeshPolyBoundaries(mesh, false);
|
||||
|
||||
glLineWidth(1.0f);
|
||||
|
||||
glPointSize(3.0f);
|
||||
@@ -181,116 +241,120 @@ void dtDebugDrawStatNavMesh(const dtStatNavMesh* mesh, bool drawClosedList)
|
||||
for (int i = 0; i < mesh->getVertexCount(); ++i)
|
||||
{
|
||||
const float* v = mesh->getVertex(i);
|
||||
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||
glVertex3f(v[0], v[1], v[2]);
|
||||
}
|
||||
glEnd();
|
||||
glPointSize(1.0f);
|
||||
}
|
||||
|
||||
|
||||
static void drawTilePolyBoundaries(const dtTileHeader* header, bool inner)
|
||||
{
|
||||
static const float thr = 0.01f*0.01f;
|
||||
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < header->npolys; ++i)
|
||||
{
|
||||
const dtTilePoly* p = &header->polys[i];
|
||||
const dtTilePolyDetail* pd = &header->dmeshes[i];
|
||||
|
||||
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
|
||||
{
|
||||
if (inner)
|
||||
{
|
||||
if (p->n[j] == 0) continue;
|
||||
if (p->n[j] & 0x8000)
|
||||
{
|
||||
bool con = false;
|
||||
for (int k = 0; k < p->nlinks; ++k)
|
||||
{
|
||||
if (header->links[p->links+k].e == j)
|
||||
{
|
||||
con = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (con)
|
||||
glColor4ub(255,255,255,128);
|
||||
else
|
||||
glColor4ub(0,0,0,128);
|
||||
}
|
||||
else
|
||||
glColor4ub(0,48,64,32);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->n[j] != 0) continue;
|
||||
}
|
||||
|
||||
const float* v0 = &header->verts[p->v[j]*3];
|
||||
const float* v1 = &header->verts[p->v[(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)
|
||||
{
|
||||
const unsigned char* t = &header->dtris[(pd->tbase+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];
|
||||
else
|
||||
tv[m] = &header->dverts[(pd->vbase+(t[m]-p->nv))*3];
|
||||
}
|
||||
for (int m = 0, n = 2; m < 3; n=m++)
|
||||
{
|
||||
if (((t[3] >> (n*2)) & 0x3) == 0) continue; // Skip inner detail edges.
|
||||
if (distancePtLine2d(tv[n],v0,v1) < thr &&
|
||||
distancePtLine2d(tv[m],v0,v1) < thr)
|
||||
{
|
||||
glVertex3fv(tv[n]);
|
||||
glVertex3fv(tv[m]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void drawTile(const dtTileHeader* header)
|
||||
{
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (int i = 0; i < header->npolys; ++i)
|
||||
{
|
||||
const dtTilePoly* p = &header->polys[i];
|
||||
const dtTilePolyDetail* pd = &header->dmeshes[i];
|
||||
|
||||
glColor4ub(0,196,255,64);
|
||||
|
||||
unsigned short vi[3];
|
||||
for (int j = 2; j < (int)p->nv; ++j)
|
||||
for (int j = 0; j < pd->ntris; ++j)
|
||||
{
|
||||
vi[0] = p->v[0];
|
||||
vi[1] = p->v[j-1];
|
||||
vi[2] = p->v[j];
|
||||
const unsigned char* t = &header->dtris[(pd->tbase+j)*4];
|
||||
for (int k = 0; k < 3; ++k)
|
||||
{
|
||||
const float* v = &header->verts[vi[k]*3];
|
||||
glVertex3f(v[0], v[1]+0.2f, v[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// Draw tri boundaries
|
||||
glLineWidth(1.5f);
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < header->npolys; ++i)
|
||||
{
|
||||
const dtTilePoly* p = &header->polys[i];
|
||||
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
|
||||
{
|
||||
if (p->n[j] == 0) continue;
|
||||
if (p->n[j] & 0x8000)
|
||||
{
|
||||
bool con = false;
|
||||
for (int k = 0; k < p->nlinks; ++k)
|
||||
{
|
||||
if (header->links[p->links+k].e == j)
|
||||
{
|
||||
con = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (con)
|
||||
glColor4ub(255,255,255,128);
|
||||
if (t[k] < p->nv)
|
||||
glVertex3fv(&header->verts[p->v[t[k]]*3]);
|
||||
else
|
||||
glColor4ub(0,0,0,128);
|
||||
}
|
||||
else
|
||||
glColor4ub(0,48,64,32);
|
||||
/*
|
||||
{
|
||||
// Portal
|
||||
int side = (p->n[j] >> 13) & 3;
|
||||
int i = p->n[j] & 0x1fff;
|
||||
if (!header->portals[side][i].ncon) continue;
|
||||
}*/
|
||||
|
||||
int vi[2];
|
||||
vi[0] = p->v[j];
|
||||
vi[1] = p->v[(j+1) % nj];
|
||||
for (int k = 0; k < 2; ++k)
|
||||
{
|
||||
const float* v = &header->verts[vi[k]*3];
|
||||
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||
glVertex3fv(&header->dverts[(pd->vbase+t[k]-p->nv)*3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
// Draw boundaries
|
||||
// Draw inter poly boundaries
|
||||
glColor4ub(0,48,64,32);
|
||||
glLineWidth(1.5f);
|
||||
|
||||
drawTilePolyBoundaries(header, true);
|
||||
|
||||
// Draw outer poly boundaries
|
||||
glLineWidth(2.5f);
|
||||
glColor4ub(0,48,64,220);
|
||||
glBegin(GL_LINES);
|
||||
for (int i = 0; i < header->npolys; ++i)
|
||||
{
|
||||
const dtTilePoly* p = &header->polys[i];
|
||||
for (int j = 0, nj = (int)p->nv; j < nj; ++j)
|
||||
{
|
||||
if (p->n[j] != 0)
|
||||
{
|
||||
/* if (p->n[j] & 0x8000)
|
||||
{
|
||||
// Portal
|
||||
int side = (p->n[j] >> 13) & 3;
|
||||
int i = p->n[j] & 0x1fff;
|
||||
if (header->portals[side][i].ncon) continue;
|
||||
}
|
||||
else*/
|
||||
continue;
|
||||
}
|
||||
int vi[2];
|
||||
vi[0] = p->v[j];
|
||||
vi[1] = p->v[(j+1) % nj];
|
||||
for (int k = 0; k < 2; ++k)
|
||||
{
|
||||
const float* v = &header->verts[vi[k]*3];
|
||||
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
drawTilePolyBoundaries(header, false);
|
||||
|
||||
glLineWidth(1.0f);
|
||||
|
||||
glPointSize(3.0f);
|
||||
@@ -299,10 +363,10 @@ static void drawTile(const dtTileHeader* header)
|
||||
for (int i = 0; i < header->nverts; ++i)
|
||||
{
|
||||
const float* v = &header->verts[i*3];
|
||||
glVertex3f(v[0], v[1]+0.21f, v[2]);
|
||||
glVertex3f(v[0], v[1], v[2]);
|
||||
}
|
||||
glEnd();
|
||||
glPointSize(1.0f);
|
||||
glPointSize(1.0f);
|
||||
|
||||
// Draw portals
|
||||
/* glBegin(GL_LINES);
|
||||
@@ -401,21 +465,30 @@ void dtDebugDrawTiledNavMesh(const dtTiledNavMesh* mesh)
|
||||
|
||||
void dtDebugDrawTiledNavMeshPoly(const dtTiledNavMesh* mesh, dtTilePolyRef ref, const float* col)
|
||||
{
|
||||
const dtTilePoly* p = mesh->getPolyByRef(ref);
|
||||
if (!p) return;
|
||||
const float* verts = mesh->getPolyVertsByRef(ref);
|
||||
unsigned int salt, it, ip;
|
||||
dtDecodeTileId(ref, salt, it, ip);
|
||||
if (it >= DT_MAX_TILES) return;
|
||||
const dtTile* tile = mesh->getTile(it);
|
||||
if (tile->salt != salt || tile->header == 0) return;
|
||||
const dtTileHeader* header = tile->header;
|
||||
|
||||
if (ip >= (unsigned int)header->npolys) return;
|
||||
|
||||
glColor4f(col[0],col[1],col[2],0.25f);
|
||||
|
||||
const dtTilePoly* p = &header->polys[ip];
|
||||
const dtTilePolyDetail* pd = &header->dmeshes[ip];
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
unsigned short vi[3];
|
||||
for (int j = 2; j < (int)p->nv; ++j)
|
||||
for (int i = 0; i < pd->ntris; ++i)
|
||||
{
|
||||
vi[0] = p->v[0];
|
||||
vi[1] = p->v[j-1];
|
||||
vi[2] = p->v[j];
|
||||
for (int k = 0; k < 3; ++k)
|
||||
const unsigned char* t = &header->dtris[(pd->tbase+i)*4];
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
const float* v = &verts[vi[k]*3];
|
||||
glVertex3f(v[0], v[1]+0.2f, v[2]);
|
||||
if (t[j] < p->nv)
|
||||
glVertex3fv(&header->verts[p->v[t[j]]*3]);
|
||||
else
|
||||
glVertex3fv(&header->dverts[(pd->vbase+t[j]-p->nv)*3]);
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
|
||||
Reference in New Issue
Block a user