Recast: small debug draw refactor

Move all render logic to separate functions and add flag to disable/enable the rendering of the poly faces.
This commit is contained in:
Kawe Mazidjatari 2024-08-22 23:48:16 +02:00
parent 7a963c7fb3
commit 83ab1c87ff
3 changed files with 150 additions and 126 deletions

View File

@ -130,7 +130,7 @@ Editor::Editor() :
m_crowd(0),
m_navMeshDrawFlags(
DU_DRAWNAVMESH_OFFMESHCONS|DU_DRAWNAVMESH_WITH_CLOSED_LIST|
DU_DRAWNAVMESH_POLY_BOUNDS_OUTER|DU_DRAWNAVMESH_ALPHA),
DU_DRAWNAVMESH_POLY_FACES|DU_DRAWNAVMESH_POLY_BOUNDS_OUTER|DU_DRAWNAVMESH_ALPHA),
m_filterLowHangingObstacles(true),
m_filterLedgeSpans(true),
m_filterWalkableLowHeightSpans(true),
@ -1234,9 +1234,14 @@ void Editor::renderDetourDebugMenu()
toggleNavMeshDrawFlag(DU_DRAWNAVMESH_TILE_CELLS);
#endif
isEnabled = (getNavMeshDrawFlags() & DU_DRAWNAVMESH_POLY_FACES);
if (ImGui::Checkbox("Poly Faces", &isEnabled))
toggleNavMeshDrawFlag(DU_DRAWNAVMESH_POLY_FACES);
isEnabled = (getNavMeshDrawFlags() & DU_DRAWNAVMESH_POLY_VERTS);
if (ImGui::Checkbox("Vertex Points", &isEnabled))
if (ImGui::Checkbox("Poly Verts", &isEnabled))
toggleNavMeshDrawFlag(DU_DRAWNAVMESH_POLY_VERTS);
isEnabled = (getNavMeshDrawFlags() & DU_DRAWNAVMESH_POLY_BOUNDS_INNER);

View File

@ -34,14 +34,15 @@ enum DrawNavMeshFlags
DU_DRAWNAVMESH_TILE_BOUNDS = 1 << 6, // Render tile boundaries.
DU_DRAWNAVMESH_TILE_CELLS = 1 << 7, // Render tile cells.
DU_DRAWNAVMESH_POLY_VERTS = 1 << 8, // Render vertex points.
DU_DRAWNAVMESH_POLY_BOUNDS_INNER = 1 << 9, // Render inner poly boundaries.
DU_DRAWNAVMESH_POLY_BOUNDS_OUTER = 1 << 10, // Render outer poly boundaries.
DU_DRAWNAVMESH_POLY_CENTERS = 1 << 11, // Render poly centers.
DU_DRAWNAVMESH_POLY_GROUPS = 1 << 12, // Render poly group by color.
DU_DRAWNAVMESH_LEDGE_SPANS = 1 << 13, // Render ledge spans.
DU_DRAWNAVMESH_DEPTH_MASK = 1 << 14, // Use depth mask.
DU_DRAWNAVMESH_ALPHA = 1 << 15, // Use transparency.
DU_DRAWNAVMESH_TRAVERSE_LINKS = 1 << 16, // Render traverse links.
DU_DRAWNAVMESH_POLY_FACES = 1 << 9, // Render poly faces.
DU_DRAWNAVMESH_POLY_BOUNDS_INNER = 1 << 10, // Render inner poly boundaries.
DU_DRAWNAVMESH_POLY_BOUNDS_OUTER = 1 << 11, // Render outer poly boundaries.
DU_DRAWNAVMESH_POLY_CENTERS = 1 << 12, // Render poly centers.
DU_DRAWNAVMESH_POLY_GROUPS = 1 << 13, // Render poly group by color.
DU_DRAWNAVMESH_LEDGE_SPANS = 1 << 14, // Render ledge spans.
DU_DRAWNAVMESH_DEPTH_MASK = 1 << 15, // Use depth mask.
DU_DRAWNAVMESH_ALPHA = 1 << 16, // Use transparency.
DU_DRAWNAVMESH_TRAVERSE_LINKS = 1 << 17, // Render traverse links.
};
struct duDrawTraverseLinkParams

View File

@ -22,6 +22,20 @@
#include "Detour/Include/DetourNode.h"
#include "Shared/Include/SharedCommon.h"
static void drawPolyVerts(duDebugDraw* dd, const dtMeshTile* tile, const float* offset)
{
const dtMeshHeader* header = tile->header;
const unsigned int vcol = duRGBA(0, 0, 0, 220);
dd->begin(DU_DRAW_POINTS, 4.0f, offset);
for (int i = 0; i < header->vertCount; ++i)
{
const float* v = &tile->verts[i * 3];
dd->vertex(v[0], v[1], v[2], vcol);
}
dd->end();
}
static unsigned int getPolySurfaceColor(const dtPoly* poly, duDebugDraw* dd, const unsigned int alpha)
{
return poly->groupId == DT_UNLINKED_POLY_GROUP
@ -29,6 +43,51 @@ static unsigned int getPolySurfaceColor(const dtPoly* poly, duDebugDraw* dd, con
: duTransCol(dd->areaToCol(poly->getArea()), alpha);
}
static void drawPolyFaces(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query, const dtMeshTile* tile, const float* offset, unsigned int flags)
{
const dtMeshHeader* header = tile->header;
const dtPolyRef base = mesh.getPolyRefBase(tile);
// If the "Alpha" flag isn't set, force the colour to be opaque instead of semi-transparent.
const int tileAlpha = flags & DU_DRAWNAVMESH_ALPHA ? 170 : 255;
dd->begin(DU_DRAW_TRIS, 1.0f, offset);
for (int i = 0; i < header->polyCount; ++i)
{
const dtPoly* p = &tile->polys[i];
if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) // Skip off-mesh links.
continue;
const dtPolyDetail* pd = &tile->detailMeshes[i];
unsigned int col;
if (query && query->isInClosedList(base | (dtPolyRef)i))
col = duRGBA(255,196,0,64);
else
{
if (flags & DU_DRAWNAVMESH_TILE_COLORS)
col = duIntToCol(mesh.decodePolyIdTile(base), tileAlpha);
else if (flags & DU_DRAWNAVMESH_POLY_GROUPS)
col = duIntToCol(p->groupId, tileAlpha);
else
col = getPolySurfaceColor(p, dd, tileAlpha);
}
for (int j = 0; j < pd->triCount; ++j)
{
const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
for (int k = 0; k < 3; ++k)
{
if (t[k] < p->vertCount)
dd->vertex(&tile->verts[p->verts[t[k]]*3], col);
else
dd->vertex(&tile->detailVerts[(pd->vertBase+t[k]-p->vertCount)*3], col);
}
}
}
dd->end();
}
static unsigned int getPolyBoundaryColor(const dtPoly* poly, const bool inner)
{
return poly->groupId == DT_UNLINKED_POLY_GROUP
@ -36,15 +95,6 @@ static unsigned int getPolyBoundaryColor(const dtPoly* poly, const bool inner)
: inner ? duRGBA(0,24,32,32) : duRGBA(0,24,32,220);
}
static void drawOffMeshConnectionRefPosition(duDebugDraw* dd, const dtOffMeshConnection* con)
{
float refPosDir[3];
dtCalcOffMeshRefPos(con->refPos, con->refYaw, DT_OFFMESH_CON_REFPOS_OFFSET, refPosDir);
duAppendArrow(dd, con->refPos[0], con->refPos[1], con->refPos[2],
refPosDir[0], refPosDir[1], refPosDir[2], 0.f, 10.f, duRGBA(255,255,0,255));
}
static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshTile* tile,
const float linew, const float* offset, const int flags, bool inner)
{
@ -200,8 +250,7 @@ static void drawTraverseLinks(duDebugDraw* dd, const dtNavMesh& mesh, const dtNa
const dtPoly* endPoly;
const dtMeshTile* endTile;
if (dtStatusFailed(mesh.getTileAndPolyByRef(link->ref, &endTile, &endPoly)))
continue;
mesh.getTileAndPolyByRefUnsafe(link->ref, &endTile, &endPoly);
if (endPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) // Skip off-mesh links.
continue;
@ -292,54 +341,97 @@ static void drawTileBounds(duDebugDraw* dd, const dtMeshTile* tile, const float*
duDebugDrawBoxWire(dd, bmin[0],bmin[1],bmin[2], bmax[0],bmax[1],bmax[2], duRGBA(255,255,255,128), 1.0f,offset);
}
static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query,
const dtMeshTile* tile, const float* offset, unsigned int flags, const duDrawTraverseLinkParams& traverseLinkParams)
static void drawOffMeshConnectionRefPosition(duDebugDraw* dd, const dtOffMeshConnection* con)
{
// If the "Alpha" flag isn't set, force the colour to be opaque instead of semi-transparent.
const int tileAlpha = flags & DU_DRAWNAVMESH_ALPHA ? 170 : 255;
const bool depthTest = flags & DU_DRAWNAVMESH_DEPTH_MASK;
float refPosDir[3];
dtCalcOffMeshRefPos(con->refPos, con->refYaw, DT_OFFMESH_CON_REFPOS_OFFSET, refPosDir);
dtPolyRef base = mesh.getPolyRefBase(tile);
duAppendArrow(dd, con->refPos[0], con->refPos[1], con->refPos[2],
refPosDir[0], refPosDir[1], refPosDir[2], 0.f, 10.f, duRGBA(255,255,0,255));
}
static void drawOffMeshLinks(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query,
const dtMeshTile* tile, const float* offset)
{
const dtMeshHeader* header = tile->header;
const dtPolyRef base = mesh.getPolyRefBase(tile);
dd->depthMask(depthTest);
dd->begin(DU_DRAW_TRIS, 1.0f, offset);
dd->begin(DU_DRAW_LINES, 2.0f, offset);
for (int i = 0; i < header->polyCount; ++i)
{
const dtPoly* p = &tile->polys[i];
if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) // Skip off-mesh links.
if (p->getType() != DT_POLYTYPE_OFFMESH_CONNECTION) // Skip regular polys.
continue;
const dtPolyDetail* pd = &tile->detailMeshes[i];
const dtOffMeshConnection* con = &tile->offMeshCons[i - header->offMeshBase];
unsigned int col;
if (query && query->isInClosedList(base | (dtPolyRef)i))
col = duRGBA(255,196,0,64);
col = duRGBA(255,196,0,220);
else
col = duDarkenCol(duTransCol(dd->areaToCol(p->getArea()), 220));
const float* va = &tile->verts[p->verts[0]*3];
const float* vb = &tile->verts[p->verts[1]*3];
// Check to see if start and end end-points have links.
bool startSet = false;
bool endSet = false;
for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
{
if (flags & DU_DRAWNAVMESH_TILE_COLORS)
col = duIntToCol(mesh.decodePolyIdTile(base), tileAlpha);
else if (flags & DU_DRAWNAVMESH_POLY_GROUPS)
col = duIntToCol(p->groupId, tileAlpha);
else
col = getPolySurfaceColor(p, dd, tileAlpha);
const dtLink& link = tile->links[k];
if (link.edge == 0)
startSet = true;
if (link.edge == 1)
endSet = true;
}
for (int j = 0; j < pd->triCount; ++j)
{
const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4];
for (int k = 0; k < 3; ++k)
{
if (t[k] < p->vertCount)
dd->vertex(&tile->verts[p->verts[t[k]]*3], col);
else
dd->vertex(&tile->detailVerts[(pd->vertBase+t[k]-p->vertCount)*3], col);
}
}
// End points and their on-mesh locations.
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],con->pos[2]+5.0f, con->rad, duRGBA(220,32,16,196));
if (startSet)
duAppendCross(dd, con->pos[0],con->pos[1],con->pos[2]+5.0f, con->rad, duRGBA(220,220,16,196));
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],con->pos[5]+5.0f, con->rad, duRGBA(32,220,16,196));
if (endSet)
duAppendCross(dd, con->pos[3],con->pos[4],con->pos[5]+5.0f, con->rad, duRGBA(220,220,16,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],con->pos[2]+10.0f, 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],con->pos[5]+10.0f, 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 & DT_OFFMESH_CON_BIDIR) ? 30.0f : 0.0f, 30.0f, col);
// Reference positions.
drawOffMeshConnectionRefPosition(dd, con);
}
dd->end();
}
static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMeshQuery* query,
const dtMeshTile* tile, const float* offset, unsigned int flags, const duDrawTraverseLinkParams& traverseLinkParams)
{
const bool depthTest = flags & DU_DRAWNAVMESH_DEPTH_MASK;
dd->depthMask(depthTest);
if (flags & DU_DRAWNAVMESH_POLY_VERTS)
drawPolyVerts(dd, tile, offset);
if (flags & DU_DRAWNAVMESH_POLY_FACES)
drawPolyFaces(dd, mesh, query, tile, offset, flags);
// Draw inner poly boundaries
if (flags & DU_DRAWNAVMESH_POLY_BOUNDS_INNER)
drawPolyBoundaries(dd, tile, 1.5f, offset, flags, true);
@ -362,81 +454,7 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMesh
drawTileBounds(dd, tile, offset);
if (flags & DU_DRAWNAVMESH_OFFMESHCONS)
{
dd->begin(DU_DRAW_LINES, 2.0f, offset);
for (int i = 0; i < header->polyCount; ++i)
{
const dtPoly* p = &tile->polys[i];
if (p->getType() != DT_POLYTYPE_OFFMESH_CONNECTION) // Skip regular polys.
continue;
const dtOffMeshConnection* con = &tile->offMeshCons[i - header->offMeshBase];
unsigned int col;
if (query && query->isInClosedList(base | (dtPolyRef)i))
col = duRGBA(255, 196, 0, 220);
else
col = duDarkenCol(duTransCol(dd->areaToCol(p->getArea()), 220));
const float* va = &tile->verts[p->verts[0]*3];
const float* vb = &tile->verts[p->verts[1]*3];
// Check to see if start and end end-points have links.
bool startSet = false;
bool endSet = false;
for (unsigned int k = p->firstLink; k != DT_NULL_LINK; k = tile->links[k].next)
{
const dtLink& link = tile->links[k];
if (link.edge == 0)
startSet = true;
if (link.edge == 1)
endSet = true;
}
// End points and their on-mesh locations.
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],con->pos[2]+5.0f, con->rad, duRGBA(220,32,16,196));
if (startSet)
duAppendCross(dd, con->pos[0],con->pos[1],con->pos[2]+5.0f, con->rad, duRGBA(220,220,16,196));
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],con->pos[5]+5.0f, con->rad, duRGBA(32,220,16,196));
if (endSet)
duAppendCross(dd, con->pos[3],con->pos[4],con->pos[5]+5.0f, con->rad, duRGBA(220,220,16,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],con->pos[2]+10.0f, 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],con->pos[5]+10.0f, 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 & DT_OFFMESH_CON_BIDIR) ? 30.0f : 0.0f, 30.0f, col);
// Reference positions.
drawOffMeshConnectionRefPosition(dd, con);
}
dd->end();
}
if (flags & DU_DRAWNAVMESH_POLY_VERTS)
{
const unsigned int vcol = duRGBA(0,0,0,220);
dd->begin(DU_DRAW_POINTS, 4.0f, offset);
for (int i = 0; i < header->vertCount; ++i)
{
const float* v = &tile->verts[i*3];
dd->vertex(v[0], v[1], v[2], vcol);
}
dd->end();
}
drawOffMeshLinks(dd, mesh, query, tile, offset);
if (!depthTest)
dd->depthMask(true);