diff --git a/src/naveditor/Editor.cpp b/src/naveditor/Editor.cpp index 0dd59fce..cf26ddd7 100644 --- a/src/naveditor/Editor.cpp +++ b/src/naveditor/Editor.cpp @@ -435,11 +435,11 @@ void Editor::saveAll(std::string path, dtNavMesh* mesh) // TODO: this has to be done during navmesh init, not here!!! LinkTableData linkData; - buildLinkTable(mesh, linkData); + const int tableSize = buildLinkTable(mesh, linkData); header.params.disjointPolyGroupCount = linkData.setCount; header.params.reachabilityTableCount = m_reachabilityTableCount; - header.params.reachabilityTableSize = (linkData.setCount - 1) * ((linkData.setCount + 31) / 32) + (linkData.setCount - 1) / 32; + header.params.reachabilityTableSize = tableSize; fwrite(&header, sizeof(NavMeshSetHeader), 1, fp); @@ -458,7 +458,7 @@ void Editor::saveAll(std::string path, dtNavMesh* mesh) fwrite(tile->data, tile->dataSize, 1, fp); } - std::vector reachability(header.params.reachabilityTableSize, 0); + std::vector reachability(tableSize, 0); for (int i = 0; i < linkData.setCount; i++) setReachable(reachability, linkData.setCount, i, i, true); diff --git a/src/naveditor/GameUtils.cpp b/src/naveditor/GameUtils.cpp index 27283444..b7366bf3 100644 --- a/src/naveditor/GameUtils.cpp +++ b/src/naveditor/GameUtils.cpp @@ -98,8 +98,12 @@ void unpatchTileGame(dtMeshTile* t) } } -void buildLinkTable(dtNavMesh* mesh, LinkTableData& data) +int buildLinkTable(dtNavMesh* mesh, LinkTableData& data) { + // Reserve the first 2 poly groups + data.insert_new(); // 0 = technically usable for normal poly groups, but for simplicity we reserve it for now. + data.insert_new(); // 1 = DT_STRAY_POLY_GROUP. + //clear all labels for (int i = 0; i < mesh->getMaxTiles(); ++i) { @@ -118,7 +122,7 @@ void buildLinkTable(dtNavMesh* mesh, LinkTableData& data) { dtMeshTile* tile = mesh->getTile(i); if (!tile || !tile->header || !tile->dataSize) continue; - int pcount = tile->header->polyCount; + const int pcount = tile->header->polyCount; for (int j = 0; j < pcount; j++) { dtPoly& poly = tile->polys[j]; @@ -132,16 +136,21 @@ void buildLinkTable(dtNavMesh* mesh, LinkTableData& data) if (p->disjointSetId != (unsigned short)-1) nlabels.insert(p->disjointSetId); + plink = l.next; } if (nlabels.empty()) { - poly.disjointSetId = (unsigned short)data.insert_new(); + if (poly.firstLink == DT_NULL_LINK) + poly.disjointSetId = DT_STRAY_POLY_GROUP; + else + poly.disjointSetId = (unsigned short)data.insert_new(); } else { - auto l = *nlabels.begin(); + int l = *nlabels.begin(); poly.disjointSetId = (unsigned short)l; + for (const int nl : nlabels) data.set_union(l, nl); } @@ -149,11 +158,12 @@ void buildLinkTable(dtNavMesh* mesh, LinkTableData& data) } } //second pass + // TODO[ AMOS ]: is this necessary? for (int i = 0; i < mesh->getMaxTiles(); ++i) { dtMeshTile* tile = mesh->getTile(i); if (!tile || !tile->header || !tile->dataSize) continue; - int pcount = tile->header->polyCount; + const int pcount = tile->header->polyCount; for (int j = 0; j < pcount; j++) { dtPoly& poly = tile->polys[j]; @@ -161,6 +171,8 @@ void buildLinkTable(dtNavMesh* mesh, LinkTableData& data) poly.disjointSetId = (unsigned short)id; } } + + return (data.setCount-1) * ((data.setCount + 31) / 32) + (data.setCount-1) / 32; } void setReachable(std::vector& data, int count, int id1, int id2, bool value) { diff --git a/src/naveditor/include/GameUtils.h b/src/naveditor/include/GameUtils.h index 83b53738..eb172e71 100644 --- a/src/naveditor/include/GameUtils.h +++ b/src/naveditor/include/GameUtils.h @@ -14,7 +14,7 @@ void unpatchHeaderGame(NavMeshSetHeader& h); void patchTileGame(dtMeshTile* t); void unpatchTileGame(dtMeshTile* t); -void buildLinkTable(dtNavMesh* mesh, LinkTableData& data); +int buildLinkTable(dtNavMesh* mesh, LinkTableData& data); void setReachable(std::vector& data, int count, int id1, int id2, bool value); #endif // GAMEUTILS_H \ No newline at end of file diff --git a/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp b/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp index 2b3db83e..5458eb8d 100644 --- a/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp +++ b/src/thirdparty/recast/DebugUtils/Source/DetourDebugDraw.cpp @@ -22,18 +22,31 @@ #include "Detour/Include/DetourCommon.h" #include "Detour/Include/DetourNode.h" +static unsigned int getPolySurfaceColor(const dtPoly* poly, duDebugDraw* dd) +{ + return poly->disjointSetId == DT_STRAY_POLY_GROUP + ? duTransCol(duRGBA(240,20,10,255), 170) + : duTransCol(dd->areaToCol(poly->getArea()), 170); +} + +static unsigned int getPolyBoundaryColor(const dtPoly* poly, const bool inner) +{ + return poly->disjointSetId == DT_STRAY_POLY_GROUP + ? inner ? duRGBA(32,24,0,32) : duRGBA(32,24,0,220) + : inner ? duRGBA(0,48,64,32) : duRGBA(0,48,64,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)); + refPosDir[0], refPosDir[1], refPosDir[2], 0.f, 10.f, duRGBA(255,255,0,255)); } static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshTile* tile, - const unsigned int col, const float linew, - bool inner) + const float linew, bool inner) { static const float thr = 0.01f*0.01f; @@ -49,7 +62,7 @@ static void drawPolyBoundaries(duDebugDraw* dd, const dtMeshTile* tile, for (int j = 0, nj = (int)p->vertCount; j < nj; ++j) { - unsigned int c = col; + unsigned int c = getPolyBoundaryColor(p, inner); if (inner) { if (p->neis[j] == 0) continue; @@ -147,7 +160,7 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMesh if (flags & DU_DRAWNAVMESH_COLOR_TILES) col = tileColor; else - col = duTransCol(dd->areaToCol(p->getArea()), 170); + col = getPolySurfaceColor(p, dd); } for (int j = 0; j < pd->triCount; ++j) @@ -164,11 +177,11 @@ static void drawMeshTile(duDebugDraw* dd, const dtNavMesh& mesh, const dtNavMesh } dd->end(); - // Draw inter poly boundaries - drawPolyBoundaries(dd, tile, duRGBA(0,48,64,32), 1.5f, true); + // Draw inner poly boundaries + drawPolyBoundaries(dd, tile, 1.5f, true); // Draw outer poly boundaries - drawPolyBoundaries(dd, tile, duRGBA(0,48,64,220), 2.5f, false); + drawPolyBoundaries(dd, tile, 2.5f, false); // Draw poly centers drawPolyCenters(dd, tile, duRGBA(255, 255, 255, 100), 1.0f); diff --git a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h index 4b6147d1..0ee390df 100644 --- a/src/thirdparty/recast/Detour/Include/DetourNavMesh.h +++ b/src/thirdparty/recast/Detour/Include/DetourNavMesh.h @@ -63,6 +63,10 @@ typedef unsigned int dtTileRef; /// @ingroup detour static const int DT_VERTS_PER_POLYGON = 6; +/// A poly group that is unconnected and considered 'trash'; see [r5apex_ds + CA88B2]. +/// For reference, r2 single player NavMeshes also marked everything unconnected as '1'. +static const unsigned short DT_STRAY_POLY_GROUP = 1; + /// @{ /// @name Tile Serialization Constants /// These constants are used to detect whether a navigation tile's data