Recast: properly set traverse type fields in off-mesh connections for MSET 7 or higher

The structure was incorrect prior to this patch for MSET 7 or higher.
This commit is contained in:
Kawe Mazidjatari 2024-09-18 11:41:33 +02:00
parent 3259b03fdd
commit 1a0b6efae5
5 changed files with 76 additions and 14 deletions

View File

@ -76,7 +76,10 @@ void OffMeshConnectionTool::reset()
void OffMeshConnectionTool::handleMenu()
{
// On newer navmesh sets, off-mesh links are always bidirectional.
#if DT_NAVMESH_SET_VERSION < 7
ImGui::Checkbox("Bidirectional", &m_bidir);
#endif
ImGui::Checkbox("Invert Lookup Order", &m_invertVertexLookupOrder);
ImGui::PushItemWidth(140);

View File

@ -462,7 +462,12 @@ static void drawOffMeshLinks(duDebugDraw* dd, const dtNavMesh& mesh, const dtNav
// 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);
#if DT_NAVMESH_SET_VERSION >= 7
30.f,
#else
(con->flags & DT_OFFMESH_CON_BIDIR) ? 30.0f : 0.0f,
#endif
30.0f, col);
// Reference positions.
drawOffMeshConnectionRefPosition(dd, con);
@ -748,7 +753,12 @@ void duDebugDrawNavMeshPoly(duDebugDraw* dd, const dtNavMesh& mesh, dtPolyRef re
// 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, c);
#if DT_NAVMESH_SET_VERSION >= 7
30.f,
#else
(con->flags & DT_OFFMESH_CON_BIDIR) ? 30.0f : 0.0f,
#endif
30.0f, c);
// Reference positions.
drawOffMeshConnectionRefPosition(dd, con);

View File

@ -349,13 +349,41 @@ struct dtBVNode
/// An off-mesh connection is a user defined traversable connection made up to two vertices.
struct dtOffMeshConnection
{
unsigned char getTraverseType() { return traverseContext & 0xff; }
unsigned char getVertLookupOrder() { return (traverseContext >> 8) & 0xff; }
void setTraverseType(unsigned char type, unsigned char order) { traverseContext = type | (order << 8); }
unsigned char getTraverseType()
{
#if DT_NAVMESH_SET_VERSION >= 7
return traverseType & (DT_MAX_TRAVERSE_TYPES-1);
#else
return traverseContext & 0xff;
#endif
}
unsigned char getVertLookupOrder()
{
#if DT_NAVMESH_SET_VERSION >= 7
return traverseType & (1<<6);
#else
return (traverseContext >> 8) & 0xff;
#endif
}
void setTraverseType(unsigned char type, unsigned char order)
{
#if DT_NAVMESH_SET_VERSION >= 7
traverseType = type & (DT_MAX_TRAVERSE_TYPES-1);
if (order) // Inverted, mark it.
traverseType |= (1<<6);
#else
traverseContext = type | (order<<8);
#endif
}
#if DT_NAVMESH_SET_VERSION < 7
/// The hint index of the off-mesh connection. (Or #DT_NULL_HINT if there is no hint.)
unsigned short getHintIndex() { return traverseContext; };
void setHintIndex(unsigned short index) { traverseContext = index; };
#endif
/// The endpoints of the connection. [(ax, ay, az, bx, by, bz)]
float pos[6];
@ -366,18 +394,27 @@ struct dtOffMeshConnection
/// The polygon reference of the connection within the tile.
unsigned short poly;
/// Link flags.
/// @note These are not the connection's user defined flags. Those are assigned via the
#if DT_NAVMESH_SET_VERSION >= 7
/// End point side.
unsigned char side;
/// The traverse type.
unsigned char traverseType;
/// The hint index.
unsigned short hintIndex;
#else
/// Link flags.
/// @note These are not the connection's user defined flags. Those are assigned via the
/// connection's dtPoly definition. These are link flags used for internal purposes.
unsigned char flags;
/// End point side.
unsigned char side;
/// The traverse types or hint indices. (If the off-mesh connection is used for wall running,
/// it needs a corresponding probe which this field will reference. Otherwise this field will
/// contain the traverse type and lookup order.)
/// The traverse type and lookup order.
unsigned short traverseContext;
#endif
/// The id of the off-mesh connection. (User assigned when the navigation mesh is built.)
unsigned short userId;

View File

@ -616,6 +616,12 @@ dtStatus dtNavMesh::connectExtOffMeshLinks(const dtTileRef tileRef)
const unsigned char traverseType = con->getTraverseType();
const bool invertVertLookup = con->getVertLookupOrder();
#if DT_NAVMESH_SET_VERSION >= 7
// NOTE: need to remove the vert lookup inversion flag from here as the
// engine uses this value directly to index into the activity array.
con->setTraverseType(traverseType, 0);
#endif
for (int y = miny; y <= maxy; ++y)
{
for (int x = minx; x <= maxx; ++x)
@ -636,7 +642,9 @@ dtStatus dtNavMesh::connectExtOffMeshLinks(const dtTileRef tileRef)
return DT_FAILURE | DT_OUT_OF_MEMORY;
// Link target poly to off-mesh connection.
#if DT_NAVMESH_SET_VERSION < 7
if (con->flags & DT_OFFMESH_CON_BIDIR)
#endif
{
const unsigned int landPolyIdx = decodePolyIdPoly(landPolyRef);
dtPoly* landPoly = &neiTile->polys[landPolyIdx];

View File

@ -1125,18 +1125,22 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
if (offMeshConClass[i*2+0] == 0xff)
{
dtOffMeshConnection* con = &offMeshCons[n];
con->poly = (unsigned short)(offMeshPolyBase + n);
// Copy connection end-points.
const float* endPts = &params->offMeshConVerts[i*2*3];
const float* refPos = &params->offMeshConRefPos[i*3];
rdVcopy(&con->pos[0], &endPts[0]);
rdVcopy(&con->pos[3], &endPts[3]);
rdVcopy(&con->refPos[0], &refPos[0]);
con->rad = params->offMeshConRad[i];
con->refYaw = params->offMeshConRefYaw[i];
con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0;
con->poly = (unsigned short)(offMeshPolyBase + n);
con->side = offMeshConClass[i*2+1];
con->setTraverseType(params->offMeshConJumps[i], params->offMeshConOrders[i]);
#if DT_NAVMESH_SET_VERSION >= 7
con->hintIndex = DT_NULL_HINT;
#else
con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0;
#endif
rdVcopy(&con->refPos[0], &refPos[0]);
con->refYaw = params->offMeshConRefYaw[i];
n++;
}
}