Add support for multiple navmeshes on a scene

This commit is contained in:
Wojtek Figat
2021-01-13 14:28:46 +01:00
parent dba43c4e9f
commit 27ed23c1b9
15 changed files with 1012 additions and 626 deletions

View File

@@ -8,7 +8,10 @@
#include "Engine/Physics/Colliders/MeshCollider.h"
#include "Engine/Level/Actors/StaticModel.h"
#include "Engine/Level/ActorsCache.h"
#include "Engine/Navigation/NavigationScene.h"
#include "Engine/Navigation/NavigationSettings.h"
#include "Engine/Navigation/NavMeshBoundsVolume.h"
#include "Engine/Navigation/NavMesh.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Serialization/Serialization.h"
REGISTER_JSON_ASSET(SceneAsset, "FlaxEngine.SceneAsset");
@@ -27,7 +30,6 @@ Scene::Scene(const SpawnParams& params)
, Ticking(this)
, LightmapsData(this)
, CSGData(this)
, Navigation(::New<NavigationScene>(this))
{
// Default name
_name = TEXT("Scene");
@@ -42,7 +44,6 @@ Scene::Scene(const SpawnParams& params)
Scene::~Scene()
{
Delete(Navigation);
}
LightmapSettings Scene::GetLightmapSettings() const
@@ -55,6 +56,31 @@ void Scene::SetLightmapSettings(const LightmapSettings& value)
Info.LightmapSettings = value;
}
BoundingBox Scene::GetNavigationBounds()
{
if (NavigationVolumes.IsEmpty())
return BoundingBox::Empty;
PROFILE_CPU_NAMED("GetNavigationBounds");
auto box = NavigationVolumes[0]->GetBox();
for (int32 i = 1; i < NavigationVolumes.Count(); i++)
BoundingBox::Merge(box, NavigationVolumes[i]->GetBox(), box);
return box;
}
NavMeshBoundsVolume* Scene::FindNavigationBoundsOverlap(const BoundingBox& bounds)
{
NavMeshBoundsVolume* result = nullptr;
for (int32 i = 0; i < NavigationVolumes.Count(); i++)
{
if (NavigationVolumes[i]->GetBox().Intersects(bounds))
{
result = NavigationVolumes[i];
break;
}
}
return result;
}
void Scene::ClearLightmaps()
{
LightmapsData.ClearLightmaps();
@@ -216,12 +242,6 @@ void Scene::Serialize(SerializeStream& stream, const void* otherObj)
// Update scene info object
SaveTime = DateTime::NowUTC();
#if USE_EDITOR
// Save navmesh tiles to asset (if modified)
if (Navigation->IsDataDirty)
Navigation->SaveNavMesh();
#endif
LightmapsData.SaveLightmaps(Info.Lightmaps);
Info.Serialize(stream, other ? &other->Info : nullptr);
@@ -230,8 +250,6 @@ void Scene::Serialize(SerializeStream& stream, const void* otherObj)
stream.JKEY("CSG");
stream.Object(&CSGData, other ? &other->CSGData : nullptr);
}
SERIALIZE_MEMBER(NavMesh, Navigation->DataAsset);
}
void Scene::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
@@ -243,7 +261,37 @@ void Scene::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
LightmapsData.LoadLightmaps(Info.Lightmaps);
CSGData.DeserializeIfExists(stream, "CSG", modifier);
DESERIALIZE_MEMBER(NavMesh, Navigation->DataAsset);
// [Deprecated on 13.01.2021, expires on 13.01.2023]
if (modifier->EngineBuild <= 6215 && NavigationMeshes.IsEmpty())
{
const auto e = SERIALIZE_FIND_MEMBER(stream, "NavMesh");
if (e != stream.MemberEnd())
{
// Upgrade from old single hidden navmesh data into NavMesh actors on a scene
AssetReference<RawDataAsset> dataAsset;
Serialization::Deserialize(e->value, dataAsset, modifier);
const auto settings = NavigationSettings::Get();
if (dataAsset && settings->NavMeshes.HasItems())
{
auto navMesh = New<NavMesh>();
navMesh->SetStaticFlags(StaticFlags::FullyStatic);
navMesh->SetName(TEXT("NavMesh.") + settings->NavMeshes[0].Name);
navMesh->DataAsset = dataAsset;
navMesh->Properties = settings->NavMeshes[0];
if (IsDuringPlay())
{
navMesh->SetParent(this, false);
}
else
{
navMesh->_parent = this;
navMesh->_scene = this;
Children.Add(navMesh);
navMesh->CreateManaged();
}
}
}
}
}
void Scene::OnDeleteObject()
@@ -309,22 +357,6 @@ void Scene::EndPlay()
Actor::EndPlay();
}
void Scene::OnEnable()
{
// Base
Actor::OnEnable();
Navigation->OnEnable();
}
void Scene::OnDisable()
{
Navigation->OnDisable();
// Base
Actor::OnDisable();
}
void Scene::OnTransformChanged()
{
// Base

View File

@@ -12,8 +12,9 @@
class MeshCollider;
class Level;
class NavigationScene;
class ReloadScriptsAction;
class NavMeshBoundsVolume;
class NavMesh;
/// <summary>
/// The scene root object that contains a hierarchy of actors.
@@ -69,11 +70,6 @@ public:
/// </summary>
CSG::SceneCSGData CSGData;
/// <summary>
/// The navigation scene (always valid).
/// </summary>
NavigationScene* Navigation;
/// <summary>
/// Gets the lightmap settings (per scene).
/// </summary>
@@ -85,6 +81,31 @@ public:
/// </summary>
API_PROPERTY() void SetLightmapSettings(const LightmapSettings& value);
public:
/// <summary>
/// The list of registered navigation bounds volumes (in the scene).
/// </summary>
Array<NavMeshBoundsVolume*> NavigationVolumes;
/// <summary>
/// The list of registered navigation meshes (in the scene).
/// </summary>
Array<NavMesh*> NavigationMeshes;
/// <summary>
/// Gets the total navigation volumes bounds.
/// </summary>
/// <returns>The navmesh bounds.</returns>
BoundingBox GetNavigationBounds();
/// <summary>
/// Finds the navigation volume bounds that have intersection with the given world-space bounding box.
/// </summary>
/// <param name="bounds">The bounds.</param>
/// <returns>The intersecting volume or null if none found.</returns>
NavMeshBoundsVolume* FindNavigationBoundsOverlap(const BoundingBox& bounds);
public:
/// <summary>
@@ -148,12 +169,10 @@ public:
protected:
// [Scene]
// [Actor]
void PostLoad() override;
void PostSpawn() override;
void BeginPlay(SceneBeginData* data) override;
void OnEnable() override;
void OnDisable() override;
void OnTransformChanged() override;
};