571 lines
22 KiB
C++
571 lines
22 KiB
C++
|
|
#include "pathserver/PathServer_Store.h"
|
|
#include "pathserver/PathServer.h"
|
|
#include "pathserver/PathServerThread.h"
|
|
#include "fwscene/world/WorldLimits.h" // TODO: find out the new way to get min/max possible world extents
|
|
#include "ModelInfo/ModelInfo.h"
|
|
#include "ModelInfo/ModelInfo_Factories.h"
|
|
#include "modelinfo/VehicleModelInfo.h"
|
|
|
|
NAVMESH_OPTIMISATIONS()
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void DefaultAdjoinNavmeshesAcrossMapSwap(CNavMesh * pMainMapMesh, CNavMesh * pSwapMesh, eNavMeshEdge iSideOfMainMapMesh);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void aiNavMeshStoreInterfaceGta::FindVehicleForDynamicNavMesh(atHashString iNameHash, CModelInfoNavMeshRef &dynNavInf) const
|
|
{
|
|
//****************************************************************************************************************
|
|
// Go through modelinfos which might have an associated dynamic navmesh (vehicles only for now..) and look
|
|
// for a string match. Once we find the matching modelinfo, then store its model index in the dynNavInf entry.
|
|
|
|
fwArchetypeDynamicFactory<CVehicleModelInfo> & vehStore = CModelInfo::GetVehicleModelInfoStore();
|
|
atArray<CVehicleModelInfo*> vehicleTypes;
|
|
vehStore.GatherPtrs(vehicleTypes);
|
|
|
|
NAVMESH_OPTIMISATIONS_OFF_ONLY( ASSERT_ONLY(bool bFoundModel=false;) )
|
|
|
|
int i;
|
|
for(i=0; i<vehicleTypes.GetCount(); i++)
|
|
{
|
|
CVehicleModelInfo * pInfo = vehicleTypes[i];
|
|
|
|
if(iNameHash == pInfo->GetHashKey())
|
|
{
|
|
dynNavInf.m_iModelIndex = CModelInfo::GetModelIdFromName(iNameHash).GetModelIndex();
|
|
NAVMESH_OPTIMISATIONS_OFF_ONLY( ASSERT_ONLY(bFoundModel = true;) )
|
|
break;
|
|
}
|
|
}
|
|
|
|
NAVMESH_OPTIMISATIONS_OFF_ONLY( Assertf(bFoundModel, "The vehicle \"%s\" wasn't found in the game, although a navmesh for it exists in navmeshes.img.", iNameHash.GetCStr() ); )
|
|
}
|
|
|
|
|
|
void aiNavMeshStoreInterfaceGta::NavMeshesHaveChanged() const
|
|
{
|
|
CPathServer::GetAmbientPedGen().NotifyNavmeshesHaveChanged();
|
|
CPathServer::GetOpponentPedGen().NotifyNavmeshesHaveChanged();
|
|
}
|
|
|
|
|
|
void aiNavMeshStoreInterfaceGta::ApplyAreaSwitchesToNewlyLoadedNavMesh(CNavMesh &mesh, aiNavDomain domain) const
|
|
{
|
|
// Apply any region switches to disable ped generation & wandering in this navmesh
|
|
CPathServer::ApplyPedAreaSwitchesToNewlyLoadedNavMesh(&mesh, domain);
|
|
}
|
|
|
|
#if __HIERARCHICAL_NODES_ENABLED
|
|
|
|
void aiNavMeshStoreInterfaceGta::ApplyAreaSwitchesToNewlyLoadedNavNodes(CHierarchicalNavData &navNodes) const
|
|
{
|
|
CPathServer::ApplyPedAreaSwitchesToNewlyLoadedNavNodes(&navNodes);
|
|
}
|
|
|
|
#endif // __HIERARCHICAL_NODES_ENABLED
|
|
|
|
// HACK_GTA
|
|
#define HACK_NUM_ADJACENCIES 64
|
|
void aiNavMeshStoreInterfaceGta::ApplyHacksToNewlyLoadedNavMesh(CNavMesh * pNavMesh, aiNavDomain domain) const
|
|
{
|
|
if(domain != kNavDomainRegular)
|
|
return;
|
|
|
|
Vector3 vAdjacenciesToDisable[HACK_NUM_ADJACENCIES];
|
|
int iAdjacencyCount = 0;
|
|
|
|
const TNavMeshIndex iMesh = pNavMesh->GetIndexOfMesh();
|
|
|
|
switch(iMesh)
|
|
{
|
|
case 3133:
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-945.5f, -1249.5f, 7.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-944.5f, -1248.9f, 7.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-943.2f, -1248.2f, 7.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-941.6f, -1247.3f, 7.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-940.4f, -1246.7f, 7.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-939.4f, -1246.2f, 7.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-937.5f, -1246.0f, 7.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-935.2f, -1247.5f, 7.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-933.9f, -1250.0f, 7.0f);
|
|
break;
|
|
|
|
case 3428:
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1713.6f, -765.7f, 9.5f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1697.5f, -778.3f, 9.4f);
|
|
break;
|
|
|
|
case 3527:
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1803.1f, -688.5f, 9.9f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1803.8f, -687.9f, 9.9f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1804.4f, -687.6f, 9.8f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1828.1f, -667.6f, 9.8f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1829.3f, -666.5f, 9.8f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1840.6f, -657.1f, 9.9f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1841.3f, -656.4f, 10.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1841.8f, -656.1f, 9.8f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1903.7f, -600.9f, 11.1f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1904.3f, -600.6f, 11.2f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1904.5f, -600.3f, 11.0f);
|
|
break;
|
|
|
|
case 3528:
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1795.2f, -694.4f, 9.8f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1795.7f, -694.1f, 9.9f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1796.4f, -693.4f, 9.8f);
|
|
break;
|
|
|
|
case 3626:
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1959.7f, -553.9f, 11.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1960.2f, -553.6f, 11.2f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1960.9f, -552.9f, 11.1f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1967.6f, -548.1f, 11.1f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1968.3f, -547.4f, 11.2f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1968.8f, -547.1f, 11.1f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1995.6f, -524.7f, 11.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1996.5f, -524.1f, 11.0f);
|
|
break;
|
|
|
|
case 3627:
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1916.7f, -590.0f, 11.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1917.4f, -589.5f, 11.1f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1923.9f, -584.7f, 11.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1924.3f, -584.2f, 11.2f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1924.8f, -583.8f, 11.2f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1925.3f, -583.6f, 11.1f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1934.7f, -575.0f, 11.0f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1935.3f, -574.6f, 11.2f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1935.9f, -574.0f, 11.0f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1936.5f, -574.1f, 11.1f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1938.0f, -572.9f, 11.0f);
|
|
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1947.2f, -564.4f, 11.1f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1947.7f, -564.1f, 11.2f);
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-1948.6f, -563.4f, 11.0f);
|
|
break;
|
|
|
|
case 4336:
|
|
vAdjacenciesToDisable[iAdjacencyCount++] = Vector3(-513.5f, 573.6f, 119.4f);
|
|
break;
|
|
}
|
|
|
|
Assert(iAdjacencyCount < HACK_NUM_ADJACENCIES);
|
|
iAdjacencyCount = Min(iAdjacencyCount, HACK_NUM_ADJACENCIES);
|
|
|
|
for(s32 d=0; d<iAdjacencyCount; d++)
|
|
{
|
|
Vector3 vPos = vAdjacenciesToDisable[d];
|
|
TAdjPoly * adjPoly = NULL;
|
|
|
|
bool bFoundAdjacency = pNavMesh->GetNonStandardAdjacancyAtPosition(vPos, 1.0f, adjPoly);
|
|
|
|
Assertf(bFoundAdjacency, "Adjacency not found in navmesh %i, at (%.2f, %.2f, %.2f)", iMesh, vPos.x, vPos.y, vPos.z);
|
|
if(bFoundAdjacency)
|
|
{
|
|
if(adjPoly)
|
|
{
|
|
adjPoly->SetAdjacencyType(ADJACENCY_TYPE_NORMAL);
|
|
adjPoly->SetNavMeshIndex(NAVMESH_NAVMESH_INDEX_NONE, pNavMesh->GetAdjacentMeshes());
|
|
adjPoly->SetOriginalNavMeshIndex(NAVMESH_NAVMESH_INDEX_NONE, pNavMesh->GetAdjacentMeshes());
|
|
adjPoly->SetPolyIndex(NAVMESH_POLY_INDEX_NONE);
|
|
adjPoly->SetOriginalPolyIndex(NAVMESH_POLY_INDEX_NONE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool aiNavMeshStoreInterfaceGta::IsDefragmentCopyBlocked() const
|
|
{
|
|
LOCK_REQUESTS
|
|
|
|
if(CPathServer::GetPathServerThread()->GetNumPendingRequests() > 0)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
#if __BANK
|
|
bool aiNavMeshStoreInterfaceGta::ms_bDebugMapSwapUnmatchedAdjacencies = false;
|
|
#endif
|
|
|
|
void aiNavMeshStoreInterfaceGta::AdjoinNavmeshesAcrossMapSwap(CNavMesh * pMainMapMesh, CNavMesh * pSwapMesh, eNavMeshEdge iSideOfMainMapMesh) const
|
|
{
|
|
DefaultAdjoinNavmeshesAcrossMapSwap(pMainMapMesh, pSwapMesh, iSideOfMainMapMesh);
|
|
}
|
|
|
|
struct TExternalEdgePolys
|
|
{
|
|
Vector3 vPoly_v1;
|
|
Vector3 vPoly_v2;
|
|
TAdjPoly * pAdj;
|
|
s32 pindex;
|
|
}; // 48 bytes
|
|
|
|
atArray<TExternalEdgePolys> externalNav2Polys(0, 256); // 12kb
|
|
|
|
void aiNavMeshStoreInterfaceGta::RestoreNavmeshesAcrossMapSwap(CNavMesh * pMainMapMesh, CNavMesh * pSwappedBackMesh, eNavMeshEdge iSideOfMainMapMesh) const
|
|
{
|
|
Assert( pMainMapMesh->GetDLCGroup()==-1 );
|
|
Assert( pSwappedBackMesh->GetDLCGroup()==-1 );
|
|
|
|
const float fSameVertEpsXYSqr = square(0.05f);
|
|
const float fSameVertEpsZ = 0.25f;
|
|
|
|
const float fSharedEdgeCoord =
|
|
(iSideOfMainMapMesh == eNegX) ? pMainMapMesh->GetNonResourcedData()->m_vMinOfNavMesh.x :
|
|
(iSideOfMainMapMesh == ePosX) ? pMainMapMesh->GetNonResourcedData()->m_vMinOfNavMesh.x + pMainMapMesh->GetExtents().x :
|
|
(iSideOfMainMapMesh == eNegY) ? pMainMapMesh->GetNonResourcedData()->m_vMinOfNavMesh.y :
|
|
pMainMapMesh->GetNonResourcedData()->m_vMinOfNavMesh.y + pMainMapMesh->GetExtents().y;
|
|
|
|
s32 p1;
|
|
s32 a1;
|
|
|
|
pMainMapMesh->SetAdjoinedDLCGroup(iSideOfMainMapMesh, pSwappedBackMesh->GetDLCGroup());
|
|
pSwappedBackMesh->SetAdjoinedDLCGroup(GetOppositeEdge(iSideOfMainMapMesh), pMainMapMesh->GetDLCGroup());
|
|
|
|
pMainMapMesh->SetFlags( pMainMapMesh->GetFlags() | NAVMESH_MODIFIED_FOR_DLC_SWAP );
|
|
pSwappedBackMesh->SetFlags( pSwappedBackMesh->GetFlags() | NAVMESH_MODIFIED_FOR_DLC_SWAP );
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// Restore all non-standard adjacencies from the pMainMapMesh to the pSwappedBackMesh
|
|
|
|
for(a1=0; a1<pMainMapMesh->GetSizeOfPools(); a1++)
|
|
{
|
|
TAdjPoly * pAdj = pMainMapMesh->GetAdjacentPolysArray().Get(a1);
|
|
|
|
if( pAdj->GetOriginalNavMeshIndex(pMainMapMesh->GetAdjacentMeshes()) == pSwappedBackMesh->GetIndexOfMesh() )
|
|
{
|
|
if( pAdj->GetAdjacencyType() != ADJACENCY_TYPE_NORMAL )
|
|
{
|
|
pAdj->SetAdjacencyDisabled(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// Disable all special-links from the pMainMapMesh to the pSwappedBackMesh
|
|
|
|
for(s32 s=0; s<pMainMapMesh->GetNumSpecialLinks(); s++)
|
|
{
|
|
CSpecialLinkInfo & specialLink = pMainMapMesh->GetSpecialLinks()[s];
|
|
if(specialLink.GetOriginalLinkToNavMesh() == pSwappedBackMesh->GetIndexOfMesh())
|
|
{
|
|
specialLink.SetIsDisabled(false);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------------------
|
|
// Cache a list of which polygons are along the appropriate side of pSwapMesh, so as to avoid doing this for every poly in pMainMapMesh
|
|
|
|
externalNav2Polys.clear();
|
|
|
|
{
|
|
Vector3 vPoly2_v1, vPoly2_v2;
|
|
s32 p2, a2;
|
|
|
|
for(p2=0; p2<pSwappedBackMesh->GetNumPolys(); p2++)
|
|
{
|
|
TNavMeshPoly * pPoly2 = pSwappedBackMesh->GetPoly(p2);
|
|
if(pPoly2->GetLiesAlongEdgeOfMesh())
|
|
{
|
|
for(a2=0; a2<pPoly2->GetNumVertices(); a2++)
|
|
{
|
|
TAdjPoly * pAdj2 = pSwappedBackMesh->GetAdjacentPolysArray().Get( pPoly2->GetFirstVertexIndex() + a2 );
|
|
if(pAdj2->GetIsExternalEdge()) // && pAdj2->GetNavMeshIndex(pSwappedBackMesh->GetAdjacentMeshes())==NAVMESH_NAVMESH_INDEX_NONE)
|
|
{
|
|
pSwappedBackMesh->GetVertex( pSwappedBackMesh->GetPolyVertexIndex(pPoly2, a2), vPoly2_v1 );
|
|
|
|
if( VertexLiesAlongEdge(vPoly2_v1, iSideOfMainMapMesh, fSharedEdgeCoord) )
|
|
{
|
|
pSwappedBackMesh->GetVertex( pSwappedBackMesh->GetPolyVertexIndex(pPoly2, (a2+1)%pPoly2->GetNumVertices()), vPoly2_v2 );
|
|
|
|
if( VertexLiesAlongEdge(vPoly2_v2, iSideOfMainMapMesh, fSharedEdgeCoord))
|
|
{
|
|
TExternalEdgePolys externalPoly;
|
|
externalPoly.pAdj = pAdj2;
|
|
externalPoly.vPoly_v1 = vPoly2_v1;
|
|
externalPoly.vPoly_v2 = vPoly2_v2;
|
|
externalPoly.pindex = p2;
|
|
|
|
externalNav2Polys.PushAndGrow(externalPoly);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------
|
|
// Retarget matching adjacencies along edge
|
|
|
|
Vector3 vPoly1_v1, vPoly1_v2;
|
|
|
|
for(p1=0; p1<pMainMapMesh->GetNumPolys(); p1++)
|
|
{
|
|
TNavMeshPoly * pPoly1 = pMainMapMesh->GetPoly(p1);
|
|
if(pPoly1->GetLiesAlongEdgeOfMesh())
|
|
{
|
|
for(a1=0; a1<pPoly1->GetNumVertices(); a1++)
|
|
{
|
|
TAdjPoly * pAdj1 = pMainMapMesh->GetAdjacentPolysArray().Get( pPoly1->GetFirstVertexIndex() + a1 );
|
|
if(pAdj1->GetIsExternalEdge())
|
|
{
|
|
bool bAdjacencyFound = false;
|
|
|
|
pMainMapMesh->GetVertex( pMainMapMesh->GetPolyVertexIndex(pPoly1, a1), vPoly1_v1 );
|
|
|
|
if(!VertexLiesAlongEdge(vPoly1_v1, iSideOfMainMapMesh, fSharedEdgeCoord))
|
|
continue;
|
|
|
|
pMainMapMesh->GetVertex( pMainMapMesh->GetPolyVertexIndex(pPoly1, (a1+1)%pPoly1->GetNumVertices()), vPoly1_v2 );
|
|
|
|
if(!VertexLiesAlongEdge(vPoly1_v2, iSideOfMainMapMesh, fSharedEdgeCoord))
|
|
continue;
|
|
|
|
for(s32 f=0; f<externalNav2Polys.GetCount(); f++)
|
|
{
|
|
TExternalEdgePolys & edgePoly2 = externalNav2Polys[f];
|
|
PrefetchDC(&externalNav2Polys.GetElements()[f+1]);
|
|
|
|
if( (IsStitchVertSame( vPoly1_v1, edgePoly2.vPoly_v2, fSameVertEpsXYSqr, fSameVertEpsZ ) && IsStitchVertSame( vPoly1_v2, edgePoly2.vPoly_v1, fSameVertEpsXYSqr, fSameVertEpsZ ) ) ||
|
|
(IsStitchVertSame( vPoly1_v1, edgePoly2.vPoly_v1, fSameVertEpsXYSqr, fSameVertEpsZ ) && IsStitchVertSame( vPoly1_v2, edgePoly2.vPoly_v2, fSameVertEpsXYSqr, fSameVertEpsZ ) ) )
|
|
{
|
|
pAdj1->SetOriginalNavMeshIndex( pSwappedBackMesh->GetIndexOfMesh(), pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj1->SetNavMeshIndex( pSwappedBackMesh->GetIndexOfMesh(), pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj1->SetOriginalPolyIndex( edgePoly2.pindex );
|
|
pAdj1->SetPolyIndex( edgePoly2.pindex );
|
|
pAdj1->SetAdjacencyType( ADJACENCY_TYPE_NORMAL );
|
|
|
|
edgePoly2.pAdj->SetOriginalNavMeshIndex( pMainMapMesh->GetIndexOfMesh(), pSwappedBackMesh->GetAdjacentMeshes() );
|
|
edgePoly2.pAdj->SetNavMeshIndex( pMainMapMesh->GetIndexOfMesh(), pSwappedBackMesh->GetAdjacentMeshes() );
|
|
edgePoly2.pAdj->SetOriginalPolyIndex( p1 );
|
|
edgePoly2.pAdj->SetPolyIndex( p1 );
|
|
edgePoly2.pAdj->SetAdjacencyType( ADJACENCY_TYPE_NORMAL );
|
|
|
|
bAdjacencyFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Assert(bAdjacencyFound);
|
|
if(!bAdjacencyFound)
|
|
{
|
|
pAdj1->SetOriginalNavMeshIndex( NAVMESH_NAVMESH_INDEX_NONE, pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj1->SetNavMeshIndex( NAVMESH_NAVMESH_INDEX_NONE, pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj1->SetOriginalPolyIndex( NAVMESH_POLY_INDEX_NONE );
|
|
pAdj1->SetPolyIndex( NAVMESH_POLY_INDEX_NONE );
|
|
pAdj1->SetAdjacencyType( ADJACENCY_TYPE_NORMAL );
|
|
|
|
#if __BANK
|
|
if(ms_bDebugMapSwapUnmatchedAdjacencies)
|
|
{
|
|
grcDebugDraw::Line(vPoly1_v1 + (ZAXIS*0.2f), vPoly1_v2 + (ZAXIS*0.2f), Color_green, Color_green, 4000);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO : Add a new parameter, passed in from calling function to avoid repeatedly iterating edge polygons in pMainMapMesh for each side which required stitching
|
|
// const atArray<TExternalEdgePolys> & inputEdgePolys
|
|
|
|
void DefaultAdjoinNavmeshesAcrossMapSwap(CNavMesh * pMainMapMesh, CNavMesh * pSwapMesh, eNavMeshEdge iSideOfMainMapMesh)
|
|
{
|
|
//Assert( (pMainMapMesh->GetFlags()&NAVMESH_DLC)==0 );
|
|
//Assert( (pSwapMesh->GetFlags()&NAVMESH_DLC)!=0 );
|
|
|
|
Assert( pMainMapMesh->GetDLCGroup()==-1 );
|
|
//Assert( pSwapMesh->GetSwapGroup()==-1 );
|
|
|
|
const float fSameVertEpsXYSqr = square(0.05f);
|
|
const float fSameVertEpsZ = 0.25f;
|
|
|
|
const float fSharedEdgeCoord =
|
|
(iSideOfMainMapMesh == eNegX) ? pMainMapMesh->GetNonResourcedData()->m_vMinOfNavMesh.x :
|
|
(iSideOfMainMapMesh == ePosX) ? pMainMapMesh->GetNonResourcedData()->m_vMinOfNavMesh.x + pMainMapMesh->GetExtents().x :
|
|
(iSideOfMainMapMesh == eNegY) ? pMainMapMesh->GetNonResourcedData()->m_vMinOfNavMesh.y :
|
|
pMainMapMesh->GetNonResourcedData()->m_vMinOfNavMesh.y + pMainMapMesh->GetExtents().y;
|
|
|
|
|
|
s32 p1;
|
|
s32 a1;
|
|
|
|
pMainMapMesh->SetAdjoinedDLCGroup(iSideOfMainMapMesh, pSwapMesh->GetDLCGroup());
|
|
pSwapMesh->SetAdjoinedDLCGroup(GetOppositeEdge(iSideOfMainMapMesh), pMainMapMesh->GetDLCGroup());
|
|
|
|
pMainMapMesh->SetFlags( pMainMapMesh->GetFlags() | NAVMESH_MODIFIED_FOR_DLC_SWAP );
|
|
pSwapMesh->SetFlags( pSwapMesh->GetFlags() | NAVMESH_MODIFIED_FOR_DLC_SWAP );
|
|
|
|
//-------------------------------------------------------------------------------
|
|
// Disable all non-standard adjacencies from the pMainMapMesh to the pSwapMesh
|
|
|
|
for(a1=0; a1<pMainMapMesh->GetSizeOfPools(); a1++)
|
|
{
|
|
TAdjPoly * pAdj = pMainMapMesh->GetAdjacentPolysArray().Get(a1);
|
|
|
|
if( pAdj->GetOriginalNavMeshIndex(pMainMapMesh->GetAdjacentMeshes()) == pSwapMesh->GetIndexOfMesh() )
|
|
{
|
|
if( pAdj->GetAdjacencyType() == ADJACENCY_TYPE_NORMAL )
|
|
{
|
|
pAdj->SetOriginalNavMeshIndex( NAVMESH_NAVMESH_INDEX_NONE, pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj->SetNavMeshIndex( NAVMESH_NAVMESH_INDEX_NONE, pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj->SetOriginalPolyIndex( NAVMESH_POLY_INDEX_NONE );
|
|
pAdj->SetPolyIndex( NAVMESH_POLY_INDEX_NONE );
|
|
}
|
|
else
|
|
{
|
|
pAdj->SetAdjacencyDisabled(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// Disable all special-links from the pMainMapMesh to the pSwapMesh
|
|
|
|
for(s32 s=0; s<pMainMapMesh->GetNumSpecialLinks(); s++)
|
|
{
|
|
CSpecialLinkInfo & specialLink = pMainMapMesh->GetSpecialLinks()[s];
|
|
if(specialLink.GetOriginalLinkToNavMesh() == pSwapMesh->GetIndexOfMesh())
|
|
{
|
|
specialLink.SetIsDisabled(true);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------------------
|
|
// Cache a list of which polygons are along the appropriate side of pSwapMesh, so as to avoid doing this for every poly in pMainMapMesh
|
|
|
|
externalNav2Polys.clear();
|
|
|
|
{
|
|
Vector3 vPoly2_v1, vPoly2_v2;
|
|
s32 p2, a2;
|
|
|
|
for(p2=0; p2<pSwapMesh->GetNumPolys(); p2++)
|
|
{
|
|
TNavMeshPoly * pPoly2 = pSwapMesh->GetPoly(p2);
|
|
if(pPoly2->GetIsZeroAreaStichPolyDLC())
|
|
{
|
|
for(a2=0; a2<pPoly2->GetNumVertices(); a2++)
|
|
{
|
|
TAdjPoly * pAdj2 = pSwapMesh->GetAdjacentPolysArray().Get( pPoly2->GetFirstVertexIndex() + a2 );
|
|
if(pAdj2->GetIsExternalEdge()) // && pAdj2->GetNavMeshIndex(pSwapMesh->GetAdjacentMeshes())==NAVMESH_NAVMESH_INDEX_NONE)
|
|
{
|
|
pSwapMesh->GetVertex( pSwapMesh->GetPolyVertexIndex(pPoly2, a2), vPoly2_v1 );
|
|
|
|
if( VertexLiesAlongEdge(vPoly2_v1, iSideOfMainMapMesh, fSharedEdgeCoord) )
|
|
{
|
|
pSwapMesh->GetVertex( pSwapMesh->GetPolyVertexIndex(pPoly2, (a2+1)%pPoly2->GetNumVertices()), vPoly2_v2 );
|
|
|
|
if( VertexLiesAlongEdge(vPoly2_v2, iSideOfMainMapMesh, fSharedEdgeCoord))
|
|
{
|
|
TExternalEdgePolys externalPoly;
|
|
externalPoly.pAdj = pAdj2;
|
|
externalPoly.vPoly_v1 = vPoly2_v1;
|
|
externalPoly.vPoly_v2 = vPoly2_v2;
|
|
externalPoly.pindex = p2;
|
|
|
|
externalNav2Polys.PushAndGrow(externalPoly);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------
|
|
// Retarget matching adjacencies along edge
|
|
|
|
Vector3 vPoly1_v1, vPoly1_v2;
|
|
|
|
for(p1=0; p1<pMainMapMesh->GetNumPolys(); p1++)
|
|
{
|
|
TNavMeshPoly * pPoly1 = pMainMapMesh->GetPoly(p1);
|
|
|
|
if(pPoly1->GetLiesAlongEdgeOfMesh())
|
|
{
|
|
for(a1=0; a1<pPoly1->GetNumVertices(); a1++)
|
|
{
|
|
TAdjPoly * pAdj1 = pMainMapMesh->GetAdjacentPolysArray().Get( pPoly1->GetFirstVertexIndex() + a1 );
|
|
if(pAdj1->GetIsExternalEdge())
|
|
{
|
|
bool bAdjacencyFound = false;
|
|
|
|
pMainMapMesh->GetVertex( pMainMapMesh->GetPolyVertexIndex(pPoly1, a1), vPoly1_v1 );
|
|
|
|
if(!VertexLiesAlongEdge(vPoly1_v1, iSideOfMainMapMesh, fSharedEdgeCoord))
|
|
continue;
|
|
|
|
pMainMapMesh->GetVertex( pMainMapMesh->GetPolyVertexIndex(pPoly1, (a1+1)%pPoly1->GetNumVertices()), vPoly1_v2 );
|
|
|
|
if(!VertexLiesAlongEdge(vPoly1_v2, iSideOfMainMapMesh, fSharedEdgeCoord))
|
|
continue;
|
|
|
|
for(s32 f=0; f<externalNav2Polys.GetCount(); f++)
|
|
{
|
|
TExternalEdgePolys & edgePoly2 = externalNav2Polys[f];
|
|
|
|
PrefetchDC(&externalNav2Polys.GetElements()[f+1]);
|
|
|
|
if( (IsStitchVertSame( vPoly1_v1, edgePoly2.vPoly_v2, fSameVertEpsXYSqr, fSameVertEpsZ ) && IsStitchVertSame( vPoly1_v2, edgePoly2.vPoly_v1, fSameVertEpsXYSqr, fSameVertEpsZ ) ) ||
|
|
(IsStitchVertSame( vPoly1_v1, edgePoly2.vPoly_v1, fSameVertEpsXYSqr, fSameVertEpsZ ) && IsStitchVertSame( vPoly1_v2, edgePoly2.vPoly_v2, fSameVertEpsXYSqr, fSameVertEpsZ ) ) )
|
|
{
|
|
pAdj1->SetOriginalNavMeshIndex( pSwapMesh->GetIndexOfMesh(), pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj1->SetNavMeshIndex( pSwapMesh->GetIndexOfMesh(), pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj1->SetOriginalPolyIndex( edgePoly2.pindex );
|
|
pAdj1->SetPolyIndex( edgePoly2.pindex );
|
|
pAdj1->SetAdjacencyType( ADJACENCY_TYPE_NORMAL );
|
|
|
|
edgePoly2.pAdj->SetOriginalNavMeshIndex( pMainMapMesh->GetIndexOfMesh(), pSwapMesh->GetAdjacentMeshes() );
|
|
edgePoly2.pAdj->SetNavMeshIndex( pMainMapMesh->GetIndexOfMesh(), pSwapMesh->GetAdjacentMeshes() );
|
|
edgePoly2.pAdj->SetOriginalPolyIndex( p1 );
|
|
edgePoly2.pAdj->SetPolyIndex( p1 );
|
|
edgePoly2.pAdj->SetAdjacencyType( ADJACENCY_TYPE_NORMAL );
|
|
|
|
bAdjacencyFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//Assert(bAdjacencyFound);
|
|
if(!bAdjacencyFound)
|
|
{
|
|
pAdj1->SetOriginalNavMeshIndex( NAVMESH_NAVMESH_INDEX_NONE, pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj1->SetNavMeshIndex( NAVMESH_NAVMESH_INDEX_NONE, pMainMapMesh->GetAdjacentMeshes() );
|
|
pAdj1->SetOriginalPolyIndex( NAVMESH_POLY_INDEX_NONE );
|
|
pAdj1->SetPolyIndex( NAVMESH_POLY_INDEX_NONE );
|
|
pAdj1->SetAdjacencyType( ADJACENCY_TYPE_NORMAL );
|
|
|
|
#if __BANK && defined(GTA_ENGINE)
|
|
static dev_bool bDebugMapSwapUnmatchedAdjacencies = false;
|
|
if(bDebugMapSwapUnmatchedAdjacencies)
|
|
{
|
|
grcDebugDraw::Line(vPoly1_v1 + (ZAXIS*0.25f), vPoly1_v2 + (ZAXIS*0.25f), Color_red, Color_red, 4000);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|