Refactor NavMesh into NavMeshRuntime and make it internal

This commit is contained in:
Wojtek Figat
2020-12-15 15:48:42 +01:00
parent 3c3e0b93f0
commit 4a79df860d
7 changed files with 65 additions and 68 deletions

View File

@@ -14,7 +14,6 @@ NavLink::NavLink(const SpawnParams& params)
void NavLink::UpdateBounds() void NavLink::UpdateBounds()
{ {
// Cache bounds
const auto start = _transform.LocalToWorld(Start); const auto start = _transform.LocalToWorld(Start);
const auto end = _transform.LocalToWorld(End); const auto end = _transform.LocalToWorld(End);
BoundingBox::FromPoints(start, end, _box); BoundingBox::FromPoints(start, end, _box);

View File

@@ -18,9 +18,9 @@
#include "NavigationScene.h" #include "NavigationScene.h"
#include "NavigationSettings.h" #include "NavigationSettings.h"
#include "NavMeshBoundsVolume.h" #include "NavMeshBoundsVolume.h"
#include "NavMesh.h"
#include "NavLink.h" #include "NavLink.h"
#include "Navigation.h" #include "Navigation.h"
#include "NavMeshRuntime.h"
#include <ThirdParty/recastnavigation/Recast.h> #include <ThirdParty/recastnavigation/Recast.h>
#include <ThirdParty/recastnavigation/DetourNavMeshBuilder.h> #include <ThirdParty/recastnavigation/DetourNavMeshBuilder.h>
#include <ThirdParty/recastnavigation/DetourNavMesh.h> #include <ThirdParty/recastnavigation/DetourNavMesh.h>
@@ -184,9 +184,9 @@ void RasterizeGeometry(const BoundingBox& tileBounds, rcContext* context, rcConf
bool GetNavMeshTileBounds(NavigationScene* scene, int32 x, int32 y, float tileSize, BoundingBox& tileBounds) bool GetNavMeshTileBounds(NavigationScene* scene, int32 x, int32 y, float tileSize, BoundingBox& tileBounds)
{ {
// Build initial tile bounds (with infinite extent) // Build initial tile bounds (with infinite extent)
tileBounds.Minimum.X = x * tileSize; tileBounds.Minimum.X = (float)x * tileSize;
tileBounds.Minimum.Y = -NAV_MESH_TILE_MAX_EXTENT; tileBounds.Minimum.Y = -NAV_MESH_TILE_MAX_EXTENT;
tileBounds.Minimum.Z = y * tileSize; tileBounds.Minimum.Z = (float)y * tileSize;
tileBounds.Maximum.X = tileBounds.Minimum.X + tileSize; tileBounds.Maximum.X = tileBounds.Minimum.X + tileSize;
tileBounds.Maximum.Y = NAV_MESH_TILE_MAX_EXTENT; tileBounds.Maximum.Y = NAV_MESH_TILE_MAX_EXTENT;
tileBounds.Maximum.Z = tileBounds.Minimum.Z + tileSize; tileBounds.Maximum.Z = tileBounds.Minimum.Z + tileSize;
@@ -224,7 +224,7 @@ bool GetNavMeshTileBounds(NavigationScene* scene, int32 x, int32 y, float tileSi
return foundAnyVolume; return foundAnyVolume;
} }
void RemoveTile(NavMesh* navMesh, NavigationScene* scene, int32 x, int32 y, int32 layer) void RemoveTile(NavMeshRuntime* navMesh, NavigationScene* scene, int32 x, int32 y, int32 layer)
{ {
ScopeLock lock(navMesh->Locker); ScopeLock lock(navMesh->Locker);
@@ -250,7 +250,7 @@ bool GenerateTile(NavigationScene* scene, int32 x, int32 y, BoundingBox& tileBou
int32 layer = 0; int32 layer = 0;
// Expand tile bounds by a certain margin // Expand tile bounds by a certain margin
const float tileBorderSize = (1 + config.borderSize) * config.cs; const float tileBorderSize = (1.0f + (float)config.borderSize) * config.cs;
tileBounds.Minimum -= tileBorderSize; tileBounds.Minimum -= tileBorderSize;
tileBounds.Maximum += tileBorderSize; tileBounds.Maximum += tileBorderSize;
@@ -347,7 +347,7 @@ bool GenerateTile(NavigationScene* scene, int32 x, int32 y, BoundingBox& tileBou
rcFreeCompactHeightfield(compactHeightfield); rcFreeCompactHeightfield(compactHeightfield);
rcFreeContourSet(contourSet); rcFreeContourSet(contourSet);
for (int i = 0; i < polyMesh->npolys; ++i) for (int i = 0; i < polyMesh->npolys; i++)
{ {
polyMesh->flags[i] = polyMesh->areas[i] == RC_WALKABLE_AREA ? 1 : 0; polyMesh->flags[i] = polyMesh->areas[i] == RC_WALKABLE_AREA ? 1 : 0;
} }
@@ -355,7 +355,7 @@ bool GenerateTile(NavigationScene* scene, int32 x, int32 y, BoundingBox& tileBou
if (polyMesh->nverts == 0) if (polyMesh->nverts == 0)
{ {
// Empty tile // Empty tile
RemoveTile(Navigation::GetNavMesh(), scene, x, y, layer); RemoveTile(NavMeshRuntime::Get(), scene, x, y, layer);
return false; return false;
} }
@@ -373,9 +373,9 @@ bool GenerateTile(NavigationScene* scene, int32 x, int32 y, BoundingBox& tileBou
params.detailVertsCount = detailMesh->nverts; params.detailVertsCount = detailMesh->nverts;
params.detailTris = detailMesh->tris; params.detailTris = detailMesh->tris;
params.detailTriCount = detailMesh->ntris; params.detailTriCount = detailMesh->ntris;
params.walkableHeight = config.walkableHeight * config.ch; params.walkableHeight = (float)config.walkableHeight * config.ch;
params.walkableRadius = config.walkableRadius * config.cs; params.walkableRadius = (float)config.walkableRadius * config.cs;
params.walkableClimb = config.walkableClimb * config.ch; params.walkableClimb = (float)config.walkableClimb * config.ch;
params.tileX = x; params.tileX = x;
params.tileY = y; params.tileY = y;
params.tileLayer = layer; params.tileLayer = layer;
@@ -438,7 +438,7 @@ bool GenerateTile(NavigationScene* scene, int32 x, int32 y, BoundingBox& tileBou
{ {
PROFILE_CPU_NAMED("Navigation.CreateTile"); PROFILE_CPU_NAMED("Navigation.CreateTile");
ScopeLock lock(Navigation::GetNavMesh()->Locker); ScopeLock lock(NavMeshRuntime::Get()->Locker);
// Add tile data // Add tile data
scene->IsDataDirty = true; scene->IsDataDirty = true;
@@ -451,7 +451,7 @@ bool GenerateTile(NavigationScene* scene, int32 x, int32 y, BoundingBox& tileBou
tile.Data.Copy(navData, navDataSize); tile.Data.Copy(navData, navDataSize);
// Add tile to navmesh // Add tile to navmesh
Navigation::GetNavMesh()->AddTile(scene, tile); NavMeshRuntime::Get()->AddTile(scene, tile);
} }
dtFree(navData); dtFree(navData);
@@ -635,7 +635,7 @@ void BuildTileAsync(NavigationScene* scene, int32 x, int32 y, rcConfig& config,
void BuildWholeScene(NavigationScene* scene) void BuildWholeScene(NavigationScene* scene)
{ {
const float tileSize = GetTileSize(); const float tileSize = GetTileSize();
const auto navMesh = Navigation::GetNavMesh(); const auto navMesh = NavMeshRuntime::Get();
// Compute total navigation area bounds // Compute total navigation area bounds
const BoundingBox worldBounds = scene->GetNavigationBounds(); const BoundingBox worldBounds = scene->GetNavigationBounds();
@@ -674,9 +674,9 @@ void BuildWholeScene(NavigationScene* scene)
{ {
PROFILE_CPU_NAMED("StartBuildingTiles"); PROFILE_CPU_NAMED("StartBuildingTiles");
for (int32 y = tilesMin.Z; y < tilesMax.Z; y ++) for (int32 y = tilesMin.Z; y < tilesMax.Z; y++)
{ {
for (int32 x = tilesMin.X; x < tilesMax.X; x ++) for (int32 x = tilesMin.X; x < tilesMax.X; x++)
{ {
BoundingBox tileBounds; BoundingBox tileBounds;
if (GetNavMeshTileBounds(scene, x, y, tileSize, tileBounds)) if (GetNavMeshTileBounds(scene, x, y, tileSize, tileBounds))
@@ -695,7 +695,7 @@ void BuildWholeScene(NavigationScene* scene)
void BuildDirtyBounds(NavigationScene* scene, const BoundingBox& dirtyBounds) void BuildDirtyBounds(NavigationScene* scene, const BoundingBox& dirtyBounds)
{ {
const float tileSize = GetTileSize(); const float tileSize = GetTileSize();
const auto navMesh = Navigation::GetNavMesh(); const auto navMesh = NavMeshRuntime::Get();
// Align dirty bounds to tile size // Align dirty bounds to tile size
BoundingBox dirtyBoundsAligned; BoundingBox dirtyBoundsAligned;
@@ -739,9 +739,9 @@ void BuildDirtyBounds(NavigationScene* scene, const BoundingBox& dirtyBounds)
{ {
PROFILE_CPU_NAMED("StartBuildingTiles"); PROFILE_CPU_NAMED("StartBuildingTiles");
for (int32 y = tilesMin.Z; y < tilesMax.Z; y ++) for (int32 y = tilesMin.Z; y < tilesMax.Z; y++)
{ {
for (int32 x = tilesMin.X; x < tilesMax.X; x ++) for (int32 x = tilesMin.X; x < tilesMax.X; x++)
{ {
BoundingBox tileBounds; BoundingBox tileBounds;
if (GetNavMeshTileBounds(scene, x, y, tileSize, tileBounds)) if (GetNavMeshTileBounds(scene, x, y, tileSize, tileBounds))

View File

@@ -1,8 +1,8 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
#include "NavMesh.h" #include "NavMeshRuntime.h"
#include "Engine/Core/Log.h"
#include "NavigationScene.h" #include "NavigationScene.h"
#include "Engine/Core/Log.h"
#include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Threading/Threading.h" #include "Engine/Threading/Threading.h"
#include <ThirdParty/recastnavigation/DetourNavMesh.h> #include <ThirdParty/recastnavigation/DetourNavMesh.h>
@@ -12,25 +12,25 @@
#define USE_DATA_LINK 0 #define USE_DATA_LINK 0
#define USE_NAV_MESH_ALLOC 1 #define USE_NAV_MESH_ALLOC 1
NavMesh::NavMesh() NavMeshRuntime::NavMeshRuntime()
{ {
_navMesh = nullptr; _navMesh = nullptr;
_navMeshQuery = dtAllocNavMeshQuery(); _navMeshQuery = dtAllocNavMeshQuery();
_tileSize = 0; _tileSize = 0;
} }
NavMesh::~NavMesh() NavMeshRuntime::~NavMeshRuntime()
{ {
dtFreeNavMesh(_navMesh); dtFreeNavMesh(_navMesh);
dtFreeNavMeshQuery(_navMeshQuery); dtFreeNavMeshQuery(_navMeshQuery);
} }
int32 NavMesh::GetTilesCapacity() const int32 NavMeshRuntime::GetTilesCapacity() const
{ {
return _navMesh ? _navMesh->getMaxTiles() : 0; return _navMesh ? _navMesh->getMaxTiles() : 0;
} }
void NavMesh::SetTileSize(float tileSize) void NavMeshRuntime::SetTileSize(float tileSize)
{ {
ScopeLock lock(Locker); ScopeLock lock(Locker);
@@ -49,7 +49,7 @@ void NavMesh::SetTileSize(float tileSize)
_tileSize = tileSize; _tileSize = tileSize;
} }
void NavMesh::EnsureCapacity(int32 tilesToAddCount) void NavMeshRuntime::EnsureCapacity(int32 tilesToAddCount)
{ {
ScopeLock lock(Locker); ScopeLock lock(Locker);
@@ -58,7 +58,7 @@ void NavMesh::EnsureCapacity(int32 tilesToAddCount)
if (newTilesCount <= capacity) if (newTilesCount <= capacity)
return; return;
PROFILE_CPU_NAMED("NavMesh.EnsureCapacity"); PROFILE_CPU_NAMED("NavMeshRuntime.EnsureCapacity");
// Navmesh tiles capacity growing rule // Navmesh tiles capacity growing rule
int32 newCapacity = 0; int32 newCapacity = 0;
@@ -132,7 +132,7 @@ void NavMesh::EnsureCapacity(int32 tilesToAddCount)
} }
} }
void NavMesh::AddTiles(NavigationScene* scene) void NavMeshRuntime::AddTiles(NavigationScene* scene)
{ {
// Skip if no data // Skip if no data
ASSERT(scene); ASSERT(scene);
@@ -140,7 +140,7 @@ void NavMesh::AddTiles(NavigationScene* scene)
return; return;
auto& data = scene->Data; auto& data = scene->Data;
PROFILE_CPU_NAMED("NavMesh.AddTiles"); PROFILE_CPU_NAMED("NavMeshRuntime.AddTiles");
ScopeLock lock(Locker); ScopeLock lock(Locker);
@@ -168,12 +168,12 @@ void NavMesh::AddTiles(NavigationScene* scene)
} }
} }
void NavMesh::AddTile(NavigationScene* scene, NavMeshTileData& tileData) void NavMeshRuntime::AddTile(NavigationScene* scene, NavMeshTileData& tileData)
{ {
ASSERT(scene); ASSERT(scene);
auto& data = scene->Data; auto& data = scene->Data;
PROFILE_CPU_NAMED("NavMesh.AddTile"); PROFILE_CPU_NAMED("NavMeshRuntime.AddTile");
ScopeLock lock(Locker); ScopeLock lock(Locker);
@@ -198,17 +198,17 @@ void NavMesh::AddTile(NavigationScene* scene, NavMeshTileData& tileData)
AddTileInternal(scene, tileData); AddTileInternal(scene, tileData);
} }
bool IsTileFromScene(const NavMesh* navMesh, const NavMeshTile& tile, void* customData) bool IsTileFromScene(const NavMeshRuntime* navMesh, const NavMeshTile& tile, void* customData)
{ {
return tile.Scene == (NavigationScene*)customData; return tile.Scene == (NavigationScene*)customData;
} }
void NavMesh::RemoveTiles(NavigationScene* scene) void NavMeshRuntime::RemoveTiles(NavigationScene* scene)
{ {
RemoveTiles(IsTileFromScene, scene); RemoveTiles(IsTileFromScene, scene);
} }
void NavMesh::RemoveTile(int32 x, int32 y, int32 layer) void NavMeshRuntime::RemoveTile(int32 x, int32 y, int32 layer)
{ {
ScopeLock lock(Locker); ScopeLock lock(Locker);
@@ -216,7 +216,7 @@ void NavMesh::RemoveTile(int32 x, int32 y, int32 layer)
if (!_navMesh) if (!_navMesh)
return; return;
PROFILE_CPU_NAMED("NavMesh.RemoveTile"); PROFILE_CPU_NAMED("NavMeshRuntime.RemoveTile");
const auto tileRef = _navMesh->getTileRefAt(x, y, layer); const auto tileRef = _navMesh->getTileRefAt(x, y, layer);
if (tileRef == 0) if (tileRef == 0)
@@ -240,7 +240,7 @@ void NavMesh::RemoveTile(int32 x, int32 y, int32 layer)
} }
} }
void NavMesh::RemoveTiles(bool (* prediction)(const NavMesh* navMesh, const NavMeshTile& tile, void* customData), void* userData) void NavMeshRuntime::RemoveTiles(bool (* prediction)(const NavMeshRuntime* navMesh, const NavMeshTile& tile, void* customData), void* userData)
{ {
ScopeLock lock(Locker); ScopeLock lock(Locker);
@@ -249,7 +249,7 @@ void NavMesh::RemoveTiles(bool (* prediction)(const NavMesh* navMesh, const NavM
if (!_navMesh) if (!_navMesh)
return; return;
PROFILE_CPU_NAMED("NavMesh.RemoveTiles"); PROFILE_CPU_NAMED("NavMeshRuntime.RemoveTiles");
for (int32 i = 0; i < _tiles.Count(); i++) for (int32 i = 0; i < _tiles.Count(); i++)
{ {
@@ -274,7 +274,7 @@ void NavMesh::RemoveTiles(bool (* prediction)(const NavMesh* navMesh, const NavM
} }
} }
void NavMesh::Dispose() void NavMeshRuntime::Dispose()
{ {
if (_navMesh) if (_navMesh)
{ {
@@ -284,7 +284,7 @@ void NavMesh::Dispose()
_tiles.Resize(0); _tiles.Resize(0);
} }
void NavMesh::AddTileInternal(NavigationScene* scene, NavMeshTileData& tileData) void NavMeshRuntime::AddTileInternal(NavigationScene* scene, NavMeshTileData& tileData)
{ {
// Check if that tile has been added to navmesh // Check if that tile has been added to navmesh
NavMeshTile* tile = nullptr; NavMeshTile* tile = nullptr;

View File

@@ -21,8 +21,12 @@ public:
BytesContainer Data; BytesContainer Data;
}; };
class FLAXENGINE_API NavMesh class NavMeshRuntime
{ {
public:
static NavMeshRuntime* Get();
private: private:
dtNavMesh* _navMesh; dtNavMesh* _navMesh;
@@ -32,14 +36,13 @@ private:
public: public:
NavMesh(); NavMeshRuntime();
~NavMeshRuntime();
~NavMesh();
public: public:
/// <summary> /// <summary>
/// The NavMesh object locker. /// The object locker.
/// </summary> /// </summary>
CriticalSection Locker; CriticalSection Locker;
@@ -110,7 +113,7 @@ public:
/// </summary> /// </summary>
/// <param name="prediction">The prediction callback, returns true for tiles to remove and false for tiles to preserve.</param> /// <param name="prediction">The prediction callback, returns true for tiles to remove and false for tiles to preserve.</param>
/// <param name="userData">The user data passed to the callback method.</param> /// <param name="userData">The user data passed to the callback method.</param>
void RemoveTiles(bool (*prediction)(const NavMesh* navMesh, const NavMeshTile& tile, void* customData), void* userData); void RemoveTiles(bool (*prediction)(const NavMeshRuntime* navMesh, const NavMeshTile& tile, void* customData), void* userData);
/// <summary> /// <summary>
/// Releases the navmesh. /// Releases the navmesh.

View File

@@ -1,11 +1,12 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
#include "Navigation.h" #include "Navigation.h"
#include "NavMeshRuntime.h"
#include "NavMeshBuilder.h"
#include "Engine/Threading/Threading.h" #include "Engine/Threading/Threading.h"
#include "Engine/Level/Scene/Scene.h" #include "Engine/Level/Scene/Scene.h"
#include "Engine/Engine/EngineService.h" #include "Engine/Engine/EngineService.h"
#include "NavMeshBuilder.h" #include "Engine/Profiler/ProfilerCPU.h"
#include "NavMesh.h"
#include <ThirdParty/recastnavigation/RecastAlloc.h> #include <ThirdParty/recastnavigation/RecastAlloc.h>
#include <ThirdParty/recastnavigation/DetourNavMesh.h> #include <ThirdParty/recastnavigation/DetourNavMesh.h>
#include <ThirdParty/recastnavigation/DetourNavMeshQuery.h> #include <ThirdParty/recastnavigation/DetourNavMeshQuery.h>
@@ -13,7 +14,15 @@
#define DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL 50.0f #define DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL 50.0f
#define DEFAULT_NAV_QUERY_EXTENT_VERTICAL 250.0f #define DEFAULT_NAV_QUERY_EXTENT_VERTICAL 250.0f
NavMesh* _navMesh = nullptr; namespace
{
NavMeshRuntime* _navMesh;
}
NavMeshRuntime* NavMeshRuntime::Get()
{
return ::_navMesh;
}
class NavigationService : public EngineService class NavigationService : public EngineService
{ {
@@ -36,11 +45,6 @@ public:
NavigationService NavigationServiceInstance; NavigationService NavigationServiceInstance;
NavMesh* Navigation::GetNavMesh()
{
return _navMesh;
}
void* dtAllocDefault(size_t size, dtAllocHint) void* dtAllocDefault(size_t size, dtAllocHint)
{ {
return Allocator::Allocate(size); return Allocator::Allocate(size);
@@ -58,7 +62,7 @@ bool NavigationService::Init()
rcAllocSetCustom(rcAllocDefault, Allocator::Free); rcAllocSetCustom(rcAllocDefault, Allocator::Free);
// Create global nav mesh // Create global nav mesh
_navMesh = New<NavMesh>(); _navMesh = New<NavMeshRuntime>();
return false; return false;
} }

View File

@@ -6,7 +6,6 @@
#include "Engine/Core/Math/Vector3.h" #include "Engine/Core/Math/Vector3.h"
class Scene; class Scene;
class NavMesh;
#define NAV_MESH_PATH_MAX_SIZE 200 #define NAV_MESH_PATH_MAX_SIZE 200
@@ -39,14 +38,6 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(NavMeshHit);
API_CLASS(Static) class FLAXENGINE_API Navigation API_CLASS(Static) class FLAXENGINE_API Navigation
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Navigation); DECLARE_SCRIPTING_TYPE_NO_SPAWN(Navigation);
public:
/// <summary>
/// Gets the navigation mesh (read-only). Use the other API to request data to use safe access to the navigation system.
/// </summary>
/// <returns>The navigation mesh.</returns>
static NavMesh* GetNavMesh();
public: public:
/// <summary> /// <summary>

View File

@@ -1,8 +1,8 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
#include "NavigationScene.h" #include "NavigationScene.h"
#include "NavMesh.h"
#include "Navigation.h" #include "Navigation.h"
#include "NavMeshRuntime.h"
#include "NavMeshBoundsVolume.h" #include "NavMeshBoundsVolume.h"
#include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Level/Scene/Scene.h" #include "Engine/Level/Scene/Scene.h"
@@ -101,14 +101,14 @@ void NavigationScene::SaveNavMesh()
void NavigationScene::OnEnable() void NavigationScene::OnEnable()
{ {
auto navMesh = Navigation::GetNavMesh(); auto navMesh = NavMeshRuntime::Get();
if (navMesh) CHECK(navMesh);
navMesh->AddTiles(this); navMesh->AddTiles(this);
} }
void NavigationScene::OnDisable() void NavigationScene::OnDisable()
{ {
auto navMesh = Navigation::GetNavMesh(); auto navMesh = NavMeshRuntime::Get();
if (navMesh) if (navMesh)
navMesh->RemoveTiles(this); navMesh->RemoveTiles(this);
} }