mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Recast: editor improvements
- Separate disjoint set and traversal table building code - Use game types and data to determine what to build into the traversal tables (e.g., 5 traversal tables for _small and only 1 for the rest). - Automatically initialize the editor using the _small navmesh parameters instead of the broken defaults.
This commit is contained in:
parent
b456825016
commit
602fa7d1ec
@ -62,6 +62,8 @@ Editor::Editor() :
|
||||
m_filterLowHangingObstacles(true),
|
||||
m_filterLedgeSpans(true),
|
||||
m_filterWalkableLowHeightSpans(true),
|
||||
m_navMeshType(NAVMESH_SMALL),
|
||||
m_navmeshName(NavMesh_GetNameForType(NAVMESH_SMALL)),
|
||||
m_tool(0),
|
||||
m_ctx(0)
|
||||
{
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "NavEditor/Include/Editor.h"
|
||||
#include "NavEditor/Include/Editor_TileMesh.h"
|
||||
|
||||
#include "tier0/commonmacros.h"
|
||||
#include "game/server/ai_navmesh.h"
|
||||
#include "game/server/ai_hull.h"
|
||||
|
||||
@ -185,6 +184,8 @@ Editor_TileMesh::Editor_TileMesh() :
|
||||
m_tileTriCount(0)
|
||||
{
|
||||
resetCommonSettings();
|
||||
selectNavMeshType(NAVMESH_SMALL);
|
||||
|
||||
memset(m_lastBuiltTileBmin, 0, sizeof(m_lastBuiltTileBmin));
|
||||
memset(m_lastBuiltTileBmax, 0, sizeof(m_lastBuiltTileBmax));
|
||||
|
||||
@ -220,19 +221,32 @@ const hulldef hulls[NAVMESH_COUNT] = {
|
||||
{ g_navMeshNames[NAVMESH_LARGE] , NAI_Hull::Width(HULL_TITAN) , NAI_Hull::Height(HULL_TITAN) * NAI_Hull::Scale(HULL_TITAN) , 60, 64.0f },
|
||||
{ g_navMeshNames[NAVMESH_EXTRA_LARGE], NAI_Hull::Width(HULL_GOLIATH), NAI_Hull::Height(HULL_GOLIATH) * NAI_Hull::Scale(HULL_GOLIATH), 65, 64.0f },
|
||||
};
|
||||
|
||||
void Editor_TileMesh::selectNavMeshType(const NavMeshType_e navMeshType)
|
||||
{
|
||||
const hulldef& h = hulls[navMeshType];
|
||||
|
||||
m_agentRadius = h.radius;
|
||||
m_agentMaxClimb = h.climbHeight;
|
||||
m_agentHeight = h.height;
|
||||
m_navmeshName = h.name;
|
||||
m_tileSize = h.tileSize;
|
||||
|
||||
m_navMeshType = navMeshType;
|
||||
}
|
||||
|
||||
void Editor_TileMesh::handleSettings()
|
||||
{
|
||||
for (const hulldef& h : hulls)
|
||||
for (int i = 0; i < NAVMESH_COUNT; i++)
|
||||
{
|
||||
if (imguiButton(h.name))
|
||||
const NavMeshType_e navMeshType = NavMeshType_e(i);
|
||||
|
||||
if (imguiButton(NavMesh_GetNameForType(navMeshType)))
|
||||
{
|
||||
m_agentRadius = h.radius;
|
||||
m_agentMaxClimb = h.climbHeight;
|
||||
m_agentHeight = h.height;
|
||||
m_navmeshName = h.name;
|
||||
m_tileSize = h.tileSize;
|
||||
selectNavMeshType(navMeshType);
|
||||
}
|
||||
}
|
||||
|
||||
Editor::handleCommonSettings();
|
||||
|
||||
if (imguiCheck("Keep Intermediate Results", m_keepInterResults))
|
||||
@ -654,7 +668,7 @@ bool Editor_TileMesh::handleBuild()
|
||||
params.maxPolys = m_maxPolysPerTile;
|
||||
params.polyGroupCount = 0;
|
||||
params.traversalTableSize = 0;
|
||||
params.traversalTableCount = DT_NUM_TRAVERSAL_TABLES;
|
||||
params.traversalTableCount = NavMesh_GetTraversalTableCountForNavMeshType(m_navMeshType);
|
||||
params.magicDataCount = 0;
|
||||
|
||||
dtStatus status;
|
||||
@ -662,7 +676,7 @@ bool Editor_TileMesh::handleBuild()
|
||||
status = m_navMesh->init(¶ms);
|
||||
if (dtStatusFailed(status))
|
||||
{
|
||||
m_ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not init navmesh.");
|
||||
m_ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not init Detour navmesh.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -796,9 +810,19 @@ void Editor_TileMesh::buildAllTiles()
|
||||
}
|
||||
}
|
||||
|
||||
if (!dtCreateStaticPathingData(m_navMesh))
|
||||
// Reserve the first poly groups
|
||||
// 0 = technically usable for normal poly groups, but for possible internal usage we reserve it for now.
|
||||
// 1 = DT_STRAY_POLY_GROUP.
|
||||
dtDisjointSet data(DT_FIRST_USABLE_POLY_GROUP);
|
||||
|
||||
if (!dtCreateDisjointPolyGroups(m_navMesh, data))
|
||||
{
|
||||
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Failed to build static pathing data.");
|
||||
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Failed to build disjoint poly groups.");
|
||||
}
|
||||
|
||||
if (!dtCreateTraversalTableData(m_navMesh, data, NavMesh_GetTraversalTableCountForNavMeshType(m_navMeshType)))
|
||||
{
|
||||
m_ctx->log(RC_LOG_ERROR, "buildNavigation: Failed to build traversal table data.");
|
||||
}
|
||||
|
||||
// Start the build process.
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "Recast/Include/Recast.h"
|
||||
#include "NavEditor/Include/EditorInterfaces.h"
|
||||
|
||||
#include "game/server/ai_navmesh.h"
|
||||
|
||||
struct hulldef
|
||||
{
|
||||
const char* name;
|
||||
@ -132,7 +134,9 @@ protected:
|
||||
float m_detailSampleDist;
|
||||
float m_detailSampleMaxError;
|
||||
int m_partitionType;
|
||||
const char* m_navmeshName = "unnamed";
|
||||
|
||||
NavMeshType_e m_navMeshType;
|
||||
const char* m_navmeshName;
|
||||
|
||||
EditorTool* m_tool;
|
||||
EditorToolState* m_toolStates[MAX_TOOLS];
|
||||
|
@ -94,6 +94,8 @@ public:
|
||||
virtual void handleMeshChanged(class InputGeom* geom);
|
||||
virtual bool handleBuild();
|
||||
virtual void collectSettings(struct BuildSettings& settings);
|
||||
|
||||
void selectNavMeshType(const NavMeshType_e navMeshType);
|
||||
|
||||
void getTilePos(const float* pos, int& tx, int& ty);
|
||||
void getTileExtents(int tx, int ty, float* bmin, float* bmax);
|
||||
|
@ -68,6 +68,9 @@ static const int DT_VERTS_PER_POLYGON = 6;
|
||||
/// For reference, Titanfall 2 single player NavMeshes also marked everything unconnected as '1'.
|
||||
static const unsigned short DT_STRAY_POLY_GROUP = 1;
|
||||
|
||||
/// The first non-reserved poly group; DT_STRAY_POLY_GROUP and below are reserved.
|
||||
static const unsigned short DT_FIRST_USABLE_POLY_GROUP = 2;
|
||||
|
||||
/// The minimum required number of poly groups for static pathing logic to work.
|
||||
/// (E.g. if we have 2 poly groups, group id 1 (DT_STRAY_POLY_GROUP), and group
|
||||
/// id 2, then 1 is never reachable as its considered 'trash' by design, and 2
|
||||
@ -76,8 +79,8 @@ static const unsigned short DT_STRAY_POLY_GROUP = 1;
|
||||
/// on the same (or connected) poly island before trying to compute a path).
|
||||
static const int DT_MIN_POLY_GROUP_COUNT = 3;
|
||||
|
||||
/// The number of traversal tables that will be used for static pathing.
|
||||
static const int DT_NUM_TRAVERSAL_TABLES = 5;
|
||||
/// The maximum number of traversal tables per navmesh that will be used for static pathing.
|
||||
static const int DT_MAX_TRAVERSAL_TABLES = 5;
|
||||
|
||||
/// @{
|
||||
/// @name Tile Serialization Constants
|
||||
|
@ -168,11 +168,19 @@ private:
|
||||
rdIntArray parent;
|
||||
};
|
||||
|
||||
/// Builds navigation mesh static pathing data from the provided navmesh.
|
||||
/// Builds navigation mesh disjoint poly groups from the provided navmesh.
|
||||
/// @ingroup detour
|
||||
/// @param[in] nav The navigation mesh to use.
|
||||
/// @return True if the static pathing data was successfully created.
|
||||
bool dtCreateStaticPathingData(dtNavMesh* nav);
|
||||
/// @param[in] nav The navigation mesh to use.
|
||||
/// @param[Out] disjoint The disjoint set data.
|
||||
/// @return True if the disjoint set data was successfully created.
|
||||
bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint);
|
||||
|
||||
/// Builds navigation mesh static traversal table from the provided navmesh.
|
||||
/// @ingroup detour
|
||||
/// @param[in] nav The navigation mesh to use.
|
||||
/// @param[in] disjoint The disjoint set data.
|
||||
/// @return True if the static traversal table was successfully created.
|
||||
bool dtCreateTraversalTableData(dtNavMesh* nav, const dtDisjointSet& disjoint, const int tableCount);
|
||||
|
||||
/// Builds navigation mesh tile data from the provided tile creation data.
|
||||
/// @ingroup detour
|
||||
|
@ -263,6 +263,7 @@ dtStatus dtNavMesh::init(const dtNavMeshParams* params)
|
||||
const int traversalTableCount = params->traversalTableCount;
|
||||
if (traversalTableCount)
|
||||
{
|
||||
rdAssert(traversalTableCount > 0 && traversalTableCount <= DT_MAX_TRAVERSAL_TABLES);
|
||||
const int setTableBufSize = sizeof(int**)*traversalTableCount;
|
||||
|
||||
m_traversalTables = (int**)rdAlloc(setTableBufSize, RD_ALLOC_PERM);
|
||||
@ -308,7 +309,7 @@ dtStatus dtNavMesh::init(unsigned char* data, const int dataSize, const int flag
|
||||
params.maxPolys = header->polyCount;
|
||||
params.polyGroupCount = 0;
|
||||
params.traversalTableSize = 0;
|
||||
params.traversalTableCount = DT_NUM_TRAVERSAL_TABLES;
|
||||
params.traversalTableCount = 0;
|
||||
params.magicDataCount = 0;
|
||||
|
||||
dtStatus status = init(¶ms);
|
||||
|
@ -281,15 +281,10 @@ static void setPolyGroupsTraversalReachability(int* const tableData, const int n
|
||||
tableData[index] &= ~value;
|
||||
}
|
||||
|
||||
bool dtCreateStaticPathingData(dtNavMesh* nav)
|
||||
bool dtCreateDisjointPolyGroups(dtNavMesh* nav, dtDisjointSet& disjoint)
|
||||
{
|
||||
rdAssert(nav);
|
||||
|
||||
// Reserve the first 2 poly groups
|
||||
// 0 = technically usable for normal poly groups, but for simplicity we reserve it for now.
|
||||
// 1 = DT_STRAY_POLY_GROUP.
|
||||
dtDisjointSet data(2);
|
||||
|
||||
// Clear all labels.
|
||||
for (int i = 0; i < nav->getMaxTiles(); ++i)
|
||||
{
|
||||
@ -353,7 +348,7 @@ bool dtCreateStaticPathingData(dtNavMesh* nav)
|
||||
if (poly.firstLink == DT_NULL_LINK)
|
||||
poly.groupId = DT_STRAY_POLY_GROUP;
|
||||
else
|
||||
poly.groupId = (unsigned short)data.insertNew();
|
||||
poly.groupId = (unsigned short)disjoint.insertNew();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -361,7 +356,7 @@ bool dtCreateStaticPathingData(dtNavMesh* nav)
|
||||
poly.groupId = (unsigned short)l;
|
||||
|
||||
for (const int nl : nlabels)
|
||||
data.setUnion(l, nl);
|
||||
disjoint.setUnion(l, nl);
|
||||
}
|
||||
|
||||
if (!noLabels)
|
||||
@ -380,7 +375,7 @@ bool dtCreateStaticPathingData(dtNavMesh* nav)
|
||||
dtPoly& poly = tile->polys[j];
|
||||
if (poly.groupId != DT_STRAY_POLY_GROUP)
|
||||
{
|
||||
int id = data.find(poly.groupId);
|
||||
int id = disjoint.find(poly.groupId);
|
||||
poly.groupId = (unsigned short)id;
|
||||
}
|
||||
}
|
||||
@ -388,7 +383,7 @@ bool dtCreateStaticPathingData(dtNavMesh* nav)
|
||||
|
||||
// Gather all unique polygroups and map them to a contiguous range.
|
||||
std::map<unsigned short, unsigned short> groupMap;
|
||||
unsigned short numPolyGroups = DT_STRAY_POLY_GROUP+1; // Anything <= DT_STRAY_POLY_GROUP is reserved!
|
||||
unsigned short numPolyGroups = DT_FIRST_USABLE_POLY_GROUP; // Anything <= DT_STRAY_POLY_GROUP is reserved!
|
||||
for (int i = 0; i < nav->getMaxTiles(); ++i)
|
||||
{
|
||||
dtMeshTile* tile = nav->getTile(i);
|
||||
@ -417,8 +412,15 @@ bool dtCreateStaticPathingData(dtNavMesh* nav)
|
||||
}
|
||||
}
|
||||
|
||||
const int tableSize = calcTraversalTableSize(numPolyGroups);
|
||||
const int tableCount = DT_NUM_TRAVERSAL_TABLES;
|
||||
nav->m_params.polyGroupCount = numPolyGroups;
|
||||
return true;
|
||||
}
|
||||
|
||||
// todo(amos): remove param 'tableCount' and make struct 'dtTraversalTableCreateParams'
|
||||
bool dtCreateTraversalTableData(dtNavMesh* nav, const dtDisjointSet& disjoint, const int tableCount)
|
||||
{
|
||||
const int polyGroupCount = nav->m_params.polyGroupCount;
|
||||
const int tableSize = calcTraversalTableSize(polyGroupCount);
|
||||
|
||||
rdAssert(nav->m_traversalTables);
|
||||
|
||||
@ -449,18 +451,17 @@ bool dtCreateStaticPathingData(dtNavMesh* nav)
|
||||
nav->m_traversalTables[i] = traversalTable;
|
||||
memset(traversalTable, 0, sizeof(int)*tableSize);
|
||||
|
||||
for (unsigned short j = 0; j < numPolyGroups; j++)
|
||||
for (unsigned short j = 0; j < polyGroupCount; j++)
|
||||
{
|
||||
for (unsigned short k = 0; k < numPolyGroups; k++)
|
||||
for (unsigned short k = 0; k < polyGroupCount; k++)
|
||||
{
|
||||
// Only reachable if its the same polygroup or if they are linked!
|
||||
const bool isReachable = j == k || data.find(j) == data.find(k);
|
||||
setPolyGroupsTraversalReachability(traversalTable, numPolyGroups, j, k, isReachable);
|
||||
const bool isReachable = j == k || disjoint.find(j) == disjoint.find(k);
|
||||
setPolyGroupsTraversalReachability(traversalTable, polyGroupCount, j, k, isReachable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nav->m_params.polyGroupCount = numPolyGroups;
|
||||
nav->m_params.traversalTableSize = tableSize;
|
||||
nav->m_params.traversalTableCount = tableCount;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user