Add NavMesh Modifier Volume actor type
This commit is contained in:
20
Source/Editor/SceneGraph/Actors/NavModifierVolumeNode.cs
Normal file
20
Source/Editor/SceneGraph/Actors/NavModifierVolumeNode.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEngine;
|
||||
|
||||
namespace FlaxEditor.SceneGraph.Actors
|
||||
{
|
||||
/// <summary>
|
||||
/// Actor node for <see cref="NavModifierVolume"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="BoxVolumeNode" />
|
||||
[HideInEditor]
|
||||
public sealed class NavModifierVolumeNode : BoxVolumeNode
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public NavModifierVolumeNode(Actor actor)
|
||||
: base(actor)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,6 +62,7 @@ namespace FlaxEditor.SceneGraph
|
||||
CustomNodesTypes.Add(typeof(NavMeshBoundsVolume), typeof(NavMeshBoundsVolumeNode));
|
||||
CustomNodesTypes.Add(typeof(BoxVolume), typeof(BoxVolumeNode));
|
||||
CustomNodesTypes.Add(typeof(NavLink), typeof(NavLinkNode));
|
||||
CustomNodesTypes.Add(typeof(NavModifierVolume), typeof(NavModifierVolumeNode));
|
||||
CustomNodesTypes.Add(typeof(ParticleEffect), typeof(ParticleEffectNode));
|
||||
CustomNodesTypes.Add(typeof(SceneAnimationPlayer), typeof(SceneAnimationPlayerNode));
|
||||
}
|
||||
|
||||
@@ -97,7 +97,8 @@ namespace FlaxEditor.Windows
|
||||
new KeyValuePair<string, Type>("Audio Listener", typeof(AudioListener)),
|
||||
new KeyValuePair<string, Type>("Scene Animation", typeof(SceneAnimationPlayer)),
|
||||
new KeyValuePair<string, Type>("Nav Mesh Bounds Volume", typeof(NavMeshBoundsVolume)),
|
||||
new KeyValuePair<string, Type>("Nav Mesh Link", typeof(NavLink)),
|
||||
new KeyValuePair<string, Type>("Nav Link", typeof(NavLink)),
|
||||
new KeyValuePair<string, Type>("Nav Modifier Volume", typeof(NavModifierVolume)),
|
||||
}
|
||||
},
|
||||
new ActorsGroup
|
||||
|
||||
@@ -165,7 +165,8 @@ namespace FlaxEditor.Windows
|
||||
groupOther.AddChild(CreateActorItem("Empty Actor", typeof(EmptyActor)));
|
||||
groupOther.AddChild(CreateActorItem("Scene Animation", typeof(SceneAnimationPlayer)));
|
||||
groupOther.AddChild(CreateActorItem("Nav Mesh Bounds Volume", typeof(NavMeshBoundsVolume)));
|
||||
groupOther.AddChild(CreateActorItem("Nav Mesh Link", typeof(NavLink)));
|
||||
groupOther.AddChild(CreateActorItem("Nav Link", typeof(NavLink)));
|
||||
groupOther.AddChild(CreateActorItem("Nav Modifier Volume", typeof(NavModifierVolume)));
|
||||
|
||||
var groupGui = CreateGroupWithList(actorGroups, "GUI");
|
||||
groupGui.AddChild(CreateActorItem("UI Control", typeof(UIControl)));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "NavigationTypes.h"
|
||||
|
||||
/// <summary>
|
||||
/// A special type of volume that defines the areas of the scene in which navigation meshes are generated.
|
||||
/// A special type of volume that defines the area of the scene in which navigation meshes are generated.
|
||||
/// </summary>
|
||||
API_CLASS() class FLAXENGINE_API NavMeshBoundsVolume : public BoxVolume
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "NavigationSettings.h"
|
||||
#include "NavMeshBoundsVolume.h"
|
||||
#include "NavLink.h"
|
||||
#include "NavModifierVolume.h"
|
||||
#include "NavMeshRuntime.h"
|
||||
#include "Engine/Core/Math/BoundingBox.h"
|
||||
#include "Engine/Core/Math/VectorInt.h"
|
||||
@@ -55,8 +56,14 @@ struct OffMeshLink
|
||||
int32 Id;
|
||||
};
|
||||
|
||||
struct Modifier
|
||||
{
|
||||
BoundingBox Bounds;
|
||||
};
|
||||
|
||||
struct NavigationSceneRasterization
|
||||
{
|
||||
NavMesh* NavMesh;
|
||||
BoundingBox TileBoundsNavMesh;
|
||||
Matrix WorldToNavMesh;
|
||||
rcContext* Context;
|
||||
@@ -66,18 +73,21 @@ struct NavigationSceneRasterization
|
||||
Array<Vector3> VertexBuffer;
|
||||
Array<int32> IndexBuffer;
|
||||
Array<OffMeshLink>* OffMeshLinks;
|
||||
Array<Modifier>* Modifiers;
|
||||
const bool IsWorldToNavMeshIdentity;
|
||||
|
||||
NavigationSceneRasterization(const BoundingBox& tileBoundsNavMesh, const Matrix& worldToNavMesh, rcContext* context, rcConfig* config, rcHeightfield* heightfield, Array<OffMeshLink>* offMeshLinks)
|
||||
NavigationSceneRasterization(::NavMesh* navMesh, const BoundingBox& tileBoundsNavMesh, const Matrix& worldToNavMesh, rcContext* context, rcConfig* config, rcHeightfield* heightfield, Array<OffMeshLink>* offMeshLinks, Array<Modifier>* modifiers)
|
||||
: TileBoundsNavMesh(tileBoundsNavMesh)
|
||||
, WorldToNavMesh(worldToNavMesh)
|
||||
, IsWorldToNavMeshIdentity(worldToNavMesh.IsIdentity())
|
||||
{
|
||||
NavMesh = navMesh;
|
||||
Context = context;
|
||||
Config = config;
|
||||
Heightfield = heightfield;
|
||||
WalkableThreshold = Math::Cos(config->walkableSlopeAngle * DegreesToRadians);
|
||||
OffMeshLinks = offMeshLinks;
|
||||
Modifiers = modifiers;
|
||||
}
|
||||
|
||||
void RasterizeTriangles()
|
||||
@@ -280,16 +290,30 @@ struct NavigationSceneRasterization
|
||||
|
||||
e.OffMeshLinks->Add(link);
|
||||
}
|
||||
else if (const auto* navModifierVolume = dynamic_cast<NavModifierVolume*>(actor))
|
||||
{
|
||||
if (navModifierVolume->AgentsMask.IsNavMeshSupported(e.NavMesh->Properties))
|
||||
{
|
||||
PROFILE_CPU_NAMED("NavModifierVolume");
|
||||
|
||||
Modifier modifier;
|
||||
OrientedBoundingBox bounds = navModifierVolume->GetOrientedBox();
|
||||
bounds.Transform(e.WorldToNavMesh);
|
||||
bounds.GetBoundingBox(modifier.Bounds);
|
||||
|
||||
e.Modifiers->Add(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void RasterizeGeometry(const BoundingBox& tileBoundsNavMesh, const Matrix& worldToNavMesh, rcContext* context, rcConfig* config, rcHeightfield* heightfield, Array<OffMeshLink>* offMeshLinks)
|
||||
void RasterizeGeometry(NavMesh* navMesh, const BoundingBox& tileBoundsNavMesh, const Matrix& worldToNavMesh, rcContext* context, rcConfig* config, rcHeightfield* heightfield, Array<OffMeshLink>* offMeshLinks, Array<Modifier>* modifiers)
|
||||
{
|
||||
PROFILE_CPU_NAMED("RasterizeGeometry");
|
||||
|
||||
NavigationSceneRasterization rasterization(tileBoundsNavMesh, worldToNavMesh, context, config, heightfield, offMeshLinks);
|
||||
NavigationSceneRasterization rasterization(navMesh, tileBoundsNavMesh, worldToNavMesh, context, config, heightfield, offMeshLinks, modifiers);
|
||||
Function<bool(Actor*, NavigationSceneRasterization&)> treeWalkFunction(NavigationSceneRasterization::Walk);
|
||||
SceneQuery::TreeExecute<NavigationSceneRasterization&>(treeWalkFunction, rasterization);
|
||||
}
|
||||
@@ -389,7 +413,8 @@ bool GenerateTile(NavMesh* navMesh, NavMeshRuntime* runtime, int32 x, int32 y, B
|
||||
}
|
||||
|
||||
Array<OffMeshLink> offMeshLinks;
|
||||
RasterizeGeometry(tileBoundsNavMesh, worldToNavMesh, &context, &config, heightfield, &offMeshLinks);
|
||||
Array<Modifier> modifiers;
|
||||
RasterizeGeometry(navMesh, tileBoundsNavMesh, worldToNavMesh, &context, &config, heightfield, &offMeshLinks, &modifiers);
|
||||
|
||||
rcFilterLowHangingWalkableObstacles(&context, config.walkableClimb, *heightfield);
|
||||
rcFilterLedgeSpans(&context, config.walkableHeight, config.walkableClimb, *heightfield);
|
||||
@@ -415,6 +440,12 @@ bool GenerateTile(NavMesh* navMesh, NavMeshRuntime* runtime, int32 x, int32 y, B
|
||||
return true;
|
||||
}
|
||||
|
||||
// Mark areas
|
||||
for (auto& modifier : modifiers)
|
||||
{
|
||||
rcMarkBoxArea(&context, &modifier.Bounds.Minimum.X, &modifier.Bounds.Maximum.X, RC_NULL_AREA, *compactHeightfield);
|
||||
}
|
||||
|
||||
if (!rcBuildDistanceField(&context, *compactHeightfield))
|
||||
{
|
||||
LOG(Warning, "Could not generate navmesh: Could not build distance field.");
|
||||
@@ -468,7 +499,7 @@ bool GenerateTile(NavMesh* navMesh, NavMeshRuntime* runtime, int32 x, int32 y, B
|
||||
|
||||
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_NULL_AREA ? 1 : 0;
|
||||
}
|
||||
|
||||
if (polyMesh->nverts == 0)
|
||||
|
||||
54
Source/Engine/Navigation/NavModifierVolume.cpp
Normal file
54
Source/Engine/Navigation/NavModifierVolume.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "NavModifierVolume.h"
|
||||
#include "Engine/Level/Scene/Scene.h"
|
||||
#include "Engine/Serialization/Serialization.h"
|
||||
#if USE_EDITOR
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/Managed/ManagedEditor.h"
|
||||
#include "NavMeshBuilder.h"
|
||||
#endif
|
||||
|
||||
NavModifierVolume::NavModifierVolume(const SpawnParams& params)
|
||||
: BoxVolume(params)
|
||||
{
|
||||
_size = 100.0f;
|
||||
}
|
||||
|
||||
void NavModifierVolume::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
{
|
||||
// Base
|
||||
BoxVolume::Serialize(stream, otherObj);
|
||||
|
||||
SERIALIZE_GET_OTHER_OBJ(NavModifierVolume);
|
||||
|
||||
SERIALIZE_MEMBER(AgentsMask, AgentsMask.Mask);
|
||||
}
|
||||
|
||||
void NavModifierVolume::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||
{
|
||||
// Base
|
||||
BoxVolume::Deserialize(stream, modifier);
|
||||
|
||||
DESERIALIZE_MEMBER(AgentsMask, AgentsMask.Mask);
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
void NavModifierVolume::OnBoundsChanged(const BoundingBox& prevBounds)
|
||||
{
|
||||
// Auto-rebuild modified navmesh area
|
||||
if (IsDuringPlay() && IsActiveInHierarchy() && !Editor::IsPlayMode && Editor::Managed->CanAutoBuildNavMesh())
|
||||
{
|
||||
BoundingBox dirtyBounds;
|
||||
BoundingBox::Merge(prevBounds, _box, dirtyBounds);
|
||||
NavMeshBuilder::Build(GetScene(), dirtyBounds, ManagedEditor::ManagedEditorOptions.AutoRebuildNavMeshTimeoutMs);
|
||||
}
|
||||
}
|
||||
|
||||
Color NavModifierVolume::GetWiresColor()
|
||||
{
|
||||
return Color::Red;
|
||||
}
|
||||
|
||||
#endif
|
||||
35
Source/Engine/Navigation/NavModifierVolume.h
Normal file
35
Source/Engine/Navigation/NavModifierVolume.h
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/Level/Actors/BoxVolume.h"
|
||||
#include "NavigationTypes.h"
|
||||
|
||||
/// <summary>
|
||||
/// A special type of volume that defines the area of the scene in which navigation is restricted (eg. higher traversal cost or dynamic obstacle block).
|
||||
/// </summary>
|
||||
API_CLASS() class FLAXENGINE_API NavModifierVolume : public BoxVolume
|
||||
{
|
||||
DECLARE_SCENE_OBJECT(NavModifierVolume);
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
/// The agent types used by this navmesh modifier volume (from navigation settings). Can be used to adjust navmesh for a certain set of agents.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorDisplay(\"Box Volume\"), EditorOrder(10)")
|
||||
NavAgentMask AgentsMask;
|
||||
|
||||
public:
|
||||
|
||||
// [BoxVolume]
|
||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
||||
|
||||
protected:
|
||||
|
||||
// [BoxVolume]
|
||||
#if USE_EDITOR
|
||||
void OnBoundsChanged(const BoundingBox& prevBounds) override;
|
||||
Color GetWiresColor() override;
|
||||
#endif
|
||||
};
|
||||
Reference in New Issue
Block a user