Recast: setup off-mesh connections properly (WIP)

Titanfall navmeshes have the dtOffMeshConnection::userId field changed from unsigned into to unsigned short, and the lower half seems to be used for the jump types and (possibly) some flag. Work in progress implementation of the jump system on off-mesh links.
This commit is contained in:
Kawe Mazidjatari 2024-07-18 17:00:31 +02:00
parent 193ec6aec7
commit 740c593197
11 changed files with 50 additions and 27 deletions

View File

@ -482,6 +482,7 @@ bool Editor_SoloMesh::handleBuild()
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConJumps = m_geom->getOffMeshConnectionJumps();
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params.offMeshConUserID = m_geom->getOffMeshConnectionId();

View File

@ -200,10 +200,11 @@ struct MeshProcess : public dtTileCacheMeshProcess
params->offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params->offMeshConRad = m_geom->getOffMeshConnectionRads();
params->offMeshConDir = m_geom->getOffMeshConnectionDirs();
params->offMeshConJumps = m_geom->getOffMeshConnectionJumps();
params->offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params->offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params->offMeshConUserID = m_geom->getOffMeshConnectionId();
params->offMeshConCount = m_geom->getOffMeshConnectionCount();
params->offMeshConCount = m_geom->getOffMeshConnectionCount();
}
}
};

View File

@ -1005,6 +1005,7 @@ unsigned char* Editor_TileMesh::buildTileMesh(const int tx, const int ty, const
params.offMeshConVerts = m_geom->getOffMeshConnectionVerts();
params.offMeshConRad = m_geom->getOffMeshConnectionRads();
params.offMeshConDir = m_geom->getOffMeshConnectionDirs();
params.offMeshConJumps = m_geom->getOffMeshConnectionJumps();
params.offMeshConAreas = m_geom->getOffMeshConnectionAreas();
params.offMeshConFlags = m_geom->getOffMeshConnectionFlags();
params.offMeshConUserID = m_geom->getOffMeshConnectionId();

View File

@ -284,16 +284,17 @@ bool InputGeom::loadGeomSet(rcContext* ctx, const std::string& filepath)
float* refs = &m_offMeshConRefPos[m_offMeshConCount*3];
float rad;
float yaw;
int bidir, area = 0, flags = 0;
sscanf(row+1, "%f %f %f %f %f %f %f %d %d %d %f %f %f %f",
int bidir, area = 0, jump = 0, flags = 0;
sscanf(row+1, "%f %f %f %f %f %f %f %d %d %d %d %f %f %f %f",
&verts[0], &verts[1], &verts[2],
&verts[3], &verts[4], &verts[5],
&rad,
&bidir, &area, &flags,
&bidir, &jump, &area, &flags,
&refs[0], &refs[1], &refs[2],
&yaw);
m_offMeshConRads[m_offMeshConCount] = rad;
m_offMeshConDirs[m_offMeshConCount] = (unsigned char)bidir;
m_offMeshConJumps[m_offMeshConCount] = (unsigned char)jump;
m_offMeshConAreas[m_offMeshConCount] = (unsigned char)area;
m_offMeshConFlags[m_offMeshConCount] = (unsigned short)flags;
m_offMeshConRefYaws[m_offMeshConCount] = yaw;
@ -428,13 +429,14 @@ bool InputGeom::saveGeomSet(const BuildSettings* settings)
const float rad = m_offMeshConRads[i];
const float yaw = m_offMeshConRefYaws[i];
const int bidir = m_offMeshConDirs[i];
const int jump = m_offMeshConJumps[i];
const int area = m_offMeshConAreas[i];
const int flags = m_offMeshConFlags[i];
fprintf(fp, "c %f %f %f %f %f %f %f %d %d %d %f %f %f %f\n",
fprintf(fp, "c %f %f %f %f %f %f %f %d %d %d %d %f %f %f %f\n",
verts[0], verts[1], verts[2],
verts[3], verts[4], verts[5],
rad,
bidir, area, flags,
bidir, jump, area, flags,
refs[0], refs[1], refs[2],
yaw);
}
@ -535,7 +537,7 @@ bool InputGeom::raycastMesh(float* src, float* dst, float& tmin)
}
void InputGeom::addOffMeshConnection(const float* spos, const float* epos, const float rad,
unsigned char bidir, unsigned char area, unsigned short flags)
unsigned char bidir, unsigned char jump, unsigned char area, unsigned short flags)
{
if (m_offMeshConCount >= MAX_OFFMESH_CONNECTIONS) return;
float* refs = &m_offMeshConRefPos[m_offMeshConCount*3];
@ -547,6 +549,7 @@ void InputGeom::addOffMeshConnection(const float* spos, const float* epos, const
m_offMeshConRads[m_offMeshConCount] = rad;
m_offMeshConRefYaws[m_offMeshConCount] = yaw;
m_offMeshConDirs[m_offMeshConCount] = bidir;
m_offMeshConJumps[m_offMeshConCount] = jump;
m_offMeshConAreas[m_offMeshConCount] = area;
m_offMeshConFlags[m_offMeshConCount] = flags;
m_offMeshConId[m_offMeshConCount] = 1000 + m_offMeshConCount;
@ -568,6 +571,7 @@ void InputGeom::deleteOffMeshConnection(int i)
m_offMeshConRads[i] = m_offMeshConRads[m_offMeshConCount];
m_offMeshConRefYaws[i] = m_offMeshConRefYaws[m_offMeshConCount];
m_offMeshConDirs[i] = m_offMeshConDirs[m_offMeshConCount];
m_offMeshConJumps[i] = m_offMeshConJumps[m_offMeshConCount];
m_offMeshConAreas[i] = m_offMeshConAreas[m_offMeshConCount];
m_offMeshConFlags[i] = m_offMeshConFlags[m_offMeshConCount];
}

View File

@ -31,6 +31,7 @@ OffMeshConnectionTool::OffMeshConnectionTool() :
m_editor(0),
m_hitPosSet(0),
m_bidir(true),
m_jumpType(0),
m_oldFlags(0)
{
}
@ -69,6 +70,10 @@ void OffMeshConnectionTool::handleMenu()
if (ImGui::Checkbox("Bidirectional", &isBiDirectional))
m_bidir = true;
ImGui::PushItemWidth(140);
ImGui::SliderInt("Jump Type", &m_jumpType, 0, 31);
ImGui::PopItemWidth();
}
void OffMeshConnectionTool::handleClick(const float* /*s*/, const float* p, bool shift)
@ -113,7 +118,7 @@ void OffMeshConnectionTool::handleClick(const float* /*s*/, const float* p, bool
{
const unsigned char area = EDITOR_POLYAREA_JUMP;
const unsigned short flags = EDITOR_POLYFLAGS_WALK;
geom->addOffMeshConnection(m_hitPos, p, m_editor->getAgentRadius(), m_bidir ? 1 : 0, area, flags);
geom->addOffMeshConnection(m_hitPos, p, m_editor->getAgentRadius(), m_bidir ? 1 : 0, (unsigned char)m_jumpType, area, flags);
m_hitPosSet = false;
}
}

View File

@ -87,12 +87,13 @@ class InputGeom
float m_offMeshConVerts[MAX_OFFMESH_CONNECTIONS*3*2];
float m_offMeshConRads[MAX_OFFMESH_CONNECTIONS];
unsigned char m_offMeshConDirs[MAX_OFFMESH_CONNECTIONS];
unsigned char m_offMeshConJumps[MAX_OFFMESH_CONNECTIONS];
unsigned char m_offMeshConAreas[MAX_OFFMESH_CONNECTIONS];
unsigned short m_offMeshConFlags[MAX_OFFMESH_CONNECTIONS];
unsigned int m_offMeshConId[MAX_OFFMESH_CONNECTIONS];
unsigned short m_offMeshConId[MAX_OFFMESH_CONNECTIONS];
float m_offMeshConRefPos[MAX_OFFMESH_CONNECTIONS*3];
float m_offMeshConRefYaws[MAX_OFFMESH_CONNECTIONS];
int m_offMeshConCount;
short m_offMeshConCount;
///@}
/// @name Convex Volumes.
@ -137,13 +138,14 @@ public:
const float* getOffMeshConnectionVerts() const { return m_offMeshConVerts; }
const float* getOffMeshConnectionRads() const { return m_offMeshConRads; }
const unsigned char* getOffMeshConnectionDirs() const { return m_offMeshConDirs; }
const unsigned char* getOffMeshConnectionJumps() const { return m_offMeshConJumps; }
const unsigned char* getOffMeshConnectionAreas() const { return m_offMeshConAreas; }
const unsigned short* getOffMeshConnectionFlags() const { return m_offMeshConFlags; }
const unsigned int* getOffMeshConnectionId() const { return m_offMeshConId; }
const unsigned short* getOffMeshConnectionId() const { return m_offMeshConId; }
const float* getOffMeshConnectionRefPos() const { return m_offMeshConRefPos; }
const float* getOffMeshConnectionRefYaws() const { return m_offMeshConRefYaws; }
void addOffMeshConnection(const float* spos, const float* epos, const float rad,
unsigned char bidir, unsigned char area, unsigned short flags);
unsigned char bidir, unsigned char jump, unsigned char area, unsigned short flags);
void deleteOffMeshConnection(int i);
void drawOffMeshConnections(struct duDebugDraw* dd, const float* offset, bool hilight = false);
///@}

View File

@ -29,6 +29,7 @@ class OffMeshConnectionTool : public EditorTool
float m_hitPos[3];
bool m_hitPosSet;
bool m_bidir;
int m_jumpType;
unsigned int m_oldFlags;
public:

View File

@ -305,8 +305,12 @@ struct dtOffMeshConnection
/// End point side.
unsigned char side;
/// The id of the offmesh connection. (User assigned when the navigation mesh is built.)
unsigned int userId;
unsigned char jumpType;
unsigned char unk1;
/// The id of the off-mesh connection. (User assigned when the navigation mesh is built.)
unsigned short userId;
/// The reference position set to the start of the off-mesh connection with an offset of DT_OFFMESH_CON_REFPOS_OFFSET
float refPos[3]; // See [r5apex_ds + F114CF], [r5apex_ds + F11B42], [r5apex_ds + F12447].

View File

@ -70,8 +70,10 @@ struct dtNavMeshCreateParams
/// 0 = Travel only from endpoint A to endpoint B.<br/>
/// #DT_OFFMESH_CON_BIDIR = Bidirectional travel.
const unsigned char* offMeshConDir;
/// The user defined jump type of the off-mesh connection. [Size: #offMeshConCount]
const unsigned char* offMeshConJumps;
/// The user defined ids of the off-mesh connection. [Size: #offMeshConCount]
const unsigned int* offMeshConUserID;
const unsigned short* offMeshConUserID;
/// Off-mesh connection reference positions. [(x, y, z) * #offMeshConCount] [Unit: wu]
const float* offMeshConRefPos;
/// Off-mesh connection reference yaw. [Size: #offMeshConCount] [Unit: wu]

View File

@ -464,8 +464,8 @@ void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side)
link->next = poly->firstLink;
poly->firstLink = idx;
link->jumpType = DT_NULL_TRAVERSE_TYPE;
link->jumpDist = 0;
link->traverseType = DT_NULL_TRAVERSE_TYPE;
link->traverseDist = 0;
link->reverseLink = DT_NULL_TRAVERSE_REVERSE_LINK;
// Compress portal limits to a byte value.
@ -540,8 +540,8 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
// Add to linked list.
link->next = targetPoly->firstLink;
targetPoly->firstLink = idx;
link->jumpType = DT_NULL_TRAVERSE_TYPE;
link->jumpDist = 0;
link->traverseType = DT_NULL_TRAVERSE_TYPE;
link->traverseDist = 0;
link->reverseLink = DT_NULL_TRAVERSE_REVERSE_LINK;
}
@ -563,8 +563,8 @@ void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int
// Add to linked list.
tlink->next = landPoly->firstLink;
landPoly->firstLink = tidx;
tlink->jumpType = DT_NULL_TRAVERSE_TYPE;
tlink->jumpDist = 0;
tlink->traverseType = DT_NULL_TRAVERSE_TYPE;
tlink->traverseDist = 0;
tlink->reverseLink = DT_NULL_TRAVERSE_REVERSE_LINK;
}
}
@ -612,8 +612,8 @@ void dtNavMesh::connectIntLinks(dtMeshTile* tile)
// Add to linked list.
link->next = poly->firstLink;
poly->firstLink = idx;
link->jumpType = DT_NULL_TRAVERSE_TYPE;
link->jumpDist = 0;
link->traverseType = DT_NULL_TRAVERSE_TYPE;
link->traverseDist = 0;
link->reverseLink = DT_NULL_TRAVERSE_REVERSE_LINK;
}
}
@ -658,8 +658,8 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
// Add to linked list.
link->next = poly->firstLink;
poly->firstLink = idx;
link->jumpType = DT_NULL_TRAVERSE_TYPE;
link->jumpDist = 0;
link->traverseType = DT_NULL_TRAVERSE_TYPE;
link->traverseDist = 0;
link->reverseLink = DT_NULL_TRAVERSE_REVERSE_LINK;
}
@ -677,8 +677,8 @@ void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile)
// Add to linked list.
link->next = landPoly->firstLink;
landPoly->firstLink = tidx;
link->jumpType = DT_NULL_TRAVERSE_TYPE;
link->jumpDist = 0;
link->traverseType = DT_NULL_TRAVERSE_TYPE;
link->traverseDist = 0;
link->reverseLink = DT_NULL_TRAVERSE_REVERSE_LINK;
}
}

View File

@ -903,6 +903,8 @@ bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData,
con->refYaw = params->offMeshConRefYaw[i];
con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0;
con->side = offMeshConClass[i*2+1];
con->jumpType = params->offMeshConJumps[i];
con->unk1 = 1;
if (params->offMeshConUserID)
con->userId = params->offMeshConUserID[i];
n++;