Add FindRandomPoint and FindRandomPointAroundCircle to the navigation utilities

This commit is contained in:
Wojtek Figat
2021-03-01 14:32:35 +01:00
parent 31d1932d55
commit 99bc3289e8
4 changed files with 114 additions and 1 deletions

View File

@@ -4,7 +4,7 @@
#include "NavigationSettings.h"
#include "NavMesh.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Math/Matrix.h"
#include "Engine/Core/Random.h"
#include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Threading/Threading.h"
#include <ThirdParty/recastnavigation/DetourNavMesh.h>
@@ -231,6 +231,71 @@ bool NavMeshRuntime::ProjectPoint(const Vector3& point, Vector3& result) const
return true;
}
bool NavMeshRuntime::FindRandomPoint(Vector3& result) const
{
ScopeLock lock(Locker);
const auto query = GetNavMeshQuery();
if (!query || !_navMesh)
{
return false;
}
dtQueryFilter filter;
InitFilter(filter);
dtPolyRef randomPoly = 0;
query->findRandomPoint(&filter, Random::Rand, &randomPoly, &result.X);
if (!randomPoly)
{
return false;
}
Quaternion invRotation;
Quaternion::Invert(Properties.Rotation, invRotation);
Vector3::Transform(result, invRotation, result);
return true;
}
bool NavMeshRuntime::FindRandomPointAroundCircle(const Vector3& center, float radius, Vector3& result) const
{
ScopeLock lock(Locker);
const auto query = GetNavMeshQuery();
if (!query || !_navMesh)
{
return false;
}
dtQueryFilter filter;
InitFilter(filter);
Vector3 extent(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL);
Vector3 centerNavMesh;
Vector3::Transform(center, Properties.Rotation, centerNavMesh);
dtPolyRef centerPoly = 0;
query->findNearestPoly(&centerNavMesh.X, &extent.X, &filter, &centerPoly, nullptr);
if (!centerPoly)
{
return false;
}
dtPolyRef randomPoly = 0;
query->findRandomPointAroundCircle(centerPoly, &centerNavMesh.X, radius, &filter, Random::Rand, &randomPoly, &result.X);
if (!randomPoly)
{
return false;
}
Quaternion invRotation;
Quaternion::Invert(Properties.Rotation, invRotation);
Vector3::Transform(result, invRotation, result);
return true;
}
bool NavMeshRuntime::RayCast(const Vector3& startPosition, const Vector3& endPosition, NavMeshHit& hitInfo) const
{
ScopeLock lock(Locker);
@@ -522,6 +587,7 @@ void NavMeshRuntime::RemoveTiles(bool (* prediction)(const NavMeshRuntime* navMe
#if COMPILE_WITH_DEBUG_DRAW
#include "Engine/Debug/DebugDraw.h"
#include "Engine/Core/Math/Matrix.h"
void DrawPoly(NavMeshRuntime* navMesh, const Matrix& navMeshToWorld, const dtMeshTile& tile, const dtPoly& poly)
{

View File

@@ -127,6 +127,22 @@ public:
/// <returns>True if found valid location on the navmesh, otherwise false.</returns>
bool ProjectPoint(const Vector3& point, Vector3& result) const;
/// <summary>
/// Finds random location on nav mesh.
/// </summary>
/// <param name="result">The result position on the navmesh (valid only if method returns true).</param>
/// <returns>True if found valid location on the navmesh, otherwise false.</returns>
bool FindRandomPoint(Vector3& result) const;
/// <summary>
/// Finds random location on nav mesh within the reach of specified location.
/// </summary>
/// <param name="center">The source point to find random location around it.</param>
/// <param name="radius">The search distance for a random point. Maximum distance for a result point from the center of the circle.</param>
/// <param name="result">The result position on the navmesh (valid only if method returns true).</param>
/// <returns>True if found valid location on the navmesh, otherwise false.</returns>
bool FindRandomPointAroundCircle(const Vector3& center, float radius, Vector3& result) const;
/// <summary>
/// Casts a 'walkability' ray along the surface of the navigation mesh from the start position toward the end position.
/// </summary>

View File

@@ -315,6 +315,20 @@ bool Navigation::ProjectPoint(const Vector3& point, Vector3& result)
return NavMeshes.First()->ProjectPoint(point, result);
}
bool Navigation::FindRandomPoint(Vector3& result)
{
if (NavMeshes.IsEmpty())
return false;
return NavMeshes.First()->FindRandomPoint(result);
}
bool Navigation::FindRandomPointAroundCircle(const Vector3& center, float radius, Vector3& result)
{
if (NavMeshes.IsEmpty())
return false;
return NavMeshes.First()->FindRandomPointAroundCircle(center, radius, result);
}
bool Navigation::RayCast(const Vector3& startPosition, const Vector3& endPosition, NavMeshHit& hitInfo)
{
if (NavMeshes.IsEmpty())

View File

@@ -48,6 +48,23 @@ public:
/// <returns>True if found valid location on the navmesh, otherwise false.</returns>
API_FUNCTION() static bool ProjectPoint(const Vector3& point, API_PARAM(Out) Vector3& result);
/// <summary>
/// Finds random location on nav mesh.
/// </summary>
/// <param name="result">The result position on the navmesh (valid only if method returns true).</param>
/// <returns>True if found valid location on the navmesh, otherwise false.</returns>
API_FUNCTION() static bool FindRandomPoint(API_PARAM(Out) Vector3& result);
/// <summary>
/// Finds random location on nav mesh within the reach of specified location.
/// </summary>
/// <remarks>If the result location doesn't need to be exactly inside the circle but just in local are aof the navigation mesh polys, then use more optimized <see cref="FindRandomPointAround"/>.</remarks>
/// <param name="center">The source point to find random location around it.</param>
/// <param name="radius">The search distance for a random point. Maximum distance for a result point from the center of the circle.</param>
/// <param name="result">The result position on the navmesh (valid only if method returns true).</param>
/// <returns>True if found valid location on the navmesh, otherwise false.</returns>
API_FUNCTION() static bool FindRandomPointAroundCircle(const Vector3& center, float radius, API_PARAM(Out) Vector3& result);
/// <summary>
/// Casts a 'walkability' ray along the surface of the navigation mesh from the start position toward the end position.
/// </summary>