This commit is contained in:
ikpil 2024-05-09 00:34:22 +09:00
parent 59849e1dac
commit e926c23195
5 changed files with 45 additions and 27 deletions

View File

@ -317,11 +317,12 @@ namespace DotRecast.Detour.Crowd
public bool MovePosition(RcVec3f npos, DtNavMeshQuery navquery, IDtQueryFilter filter) public bool MovePosition(RcVec3f npos, DtNavMeshQuery navquery, IDtQueryFilter filter)
{ {
// Move along navmesh and update new position. // Move along navmesh and update new position.
var visited = new List<long>(); const int MAX_VISITED = 16;
var status = navquery.MoveAlongSurface(m_path[0], m_pos, npos, filter, out var result, ref visited); Span<long> visited = stackalloc long[MAX_VISITED];
var status = navquery.MoveAlongSurface(m_path[0], m_pos, npos, filter, out var result, visited, out var nvisited, MAX_VISITED);
if (status.Succeeded()) if (status.Succeeded())
{ {
m_npath = DtPathUtils.MergeCorridorStartMoved(ref m_path, m_npath, m_maxPath, visited, visited.Count); m_npath = DtPathUtils.MergeCorridorStartMoved(ref m_path, m_npath, m_maxPath, visited, nvisited);
// Adjust the position to stay on top of the navmesh. // Adjust the position to stay on top of the navmesh.
m_pos = result; m_pos = result;
@ -359,11 +360,13 @@ namespace DotRecast.Detour.Crowd
public bool MoveTargetPosition(RcVec3f npos, DtNavMeshQuery navquery, IDtQueryFilter filter) public bool MoveTargetPosition(RcVec3f npos, DtNavMeshQuery navquery, IDtQueryFilter filter)
{ {
// Move along navmesh and update new position. // Move along navmesh and update new position.
var visited = new List<long>(); const int MAX_VISITED = 16;
var status = navquery.MoveAlongSurface(m_path[^1], m_target, npos, filter, out var result, ref visited); Span<long> visited = stackalloc long[MAX_VISITED];
int nvisited = 0;
var status = navquery.MoveAlongSurface(m_path[^1], m_target, npos, filter, out var result, visited, out nvisited, MAX_VISITED);
if (status.Succeeded()) if (status.Succeeded())
{ {
m_npath = DtPathUtils.MergeCorridorEndMoved(ref m_path, m_npath, m_maxPath, visited, visited.Count); m_npath = DtPathUtils.MergeCorridorEndMoved(ref m_path, m_npath, m_maxPath, visited, nvisited);
// TODO: should we do that? // TODO: should we do that?
// Adjust the position to stay on top of the navmesh. // Adjust the position to stay on top of the navmesh.

View File

@ -1790,12 +1790,11 @@ namespace DotRecast.Detour
/// @returns The status flags for the query. /// @returns The status flags for the query.
public DtStatus MoveAlongSurface(long startRef, RcVec3f startPos, RcVec3f endPos, public DtStatus MoveAlongSurface(long startRef, RcVec3f startPos, RcVec3f endPos,
IDtQueryFilter filter, IDtQueryFilter filter,
out RcVec3f resultPos, ref List<long> visited) out RcVec3f resultPos, Span<long> visited, out int visitedCount, int maxVisitedSize)
{ {
resultPos = RcVec3f.Zero; resultPos = RcVec3f.Zero;
if (null != visited) visitedCount = 0;
visited.Clear();
// Validate input // Validate input
if (!m_nav.IsValidPolyRef(startRef) || !startPos.IsFinite() if (!m_nav.IsValidPolyRef(startRef) || !startPos.IsFinite()
@ -1804,6 +1803,8 @@ namespace DotRecast.Detour
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM; return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
} }
DtStatus status = DtStatus.DT_SUCCESS;
m_tinyNodePool.Clear(); m_tinyNodePool.Clear();
DtNode startNode = m_tinyNodePool.GetNode(startRef); DtNode startNode = m_tinyNodePool.GetNode(startRef);
@ -1938,6 +1939,7 @@ namespace DotRecast.Detour
} }
} }
int n = 0;
if (bestNode != null) if (bestNode != null)
{ {
// Reverse the path. // Reverse the path.
@ -1955,14 +1957,21 @@ namespace DotRecast.Detour
node = prev; node = prev;
do do
{ {
visited.Add(node.id); visited[n++] = node.id;
if (n >= maxVisitedSize)
{
status |= DtStatus.DT_BUFFER_TOO_SMALL;;
break;
}
node = m_tinyNodePool.GetNodeAtIdx(node.pidx); node = m_tinyNodePool.GetNodeAtIdx(node.pidx);
} while (node != null); } while (node != null);
} }
resultPos = bestPos; resultPos = bestPos;
visitedCount = n;
return DtStatus.DT_SUCCESS; return status;
} }
protected DtStatus GetPortalPoints(long from, long to, out RcVec3f left, out RcVec3f right, out int fromType, out int toType) protected DtStatus GetPortalPoints(long from, long to, out RcVec3f left, out RcVec3f right, out int fromType, out int toType)

View File

@ -146,7 +146,7 @@ namespace DotRecast.Detour
return npath; return npath;
} }
public static int MergeCorridorStartMoved(ref List<long> path, int npath, int maxPath, List<long> visited, int nvisited) public static int MergeCorridorStartMoved(ref List<long> path, int npath, int maxPath, Span<long> visited, int nvisited)
{ {
int furthestPath = -1; int furthestPath = -1;
int furthestVisited = -1; int furthestVisited = -1;
@ -193,7 +193,7 @@ namespace DotRecast.Detour
return result.Count; return result.Count;
} }
public static int MergeCorridorEndMoved(ref List<long> path, int npath, int maxPath, List<long> visited, int nvisited) public static int MergeCorridorEndMoved(ref List<long> path, int npath, int maxPath, Span<long> visited, int nvisited)
{ {
int furthestPath = -1; int furthestPath = -1;
int furthestVisited = -1; int furthestVisited = -1;
@ -226,7 +226,10 @@ namespace DotRecast.Detour
// Concatenate paths. // Concatenate paths.
List<long> result = path.GetRange(0, furthestPath); List<long> result = path.GetRange(0, furthestPath);
result.AddRange(visited.GetRange(furthestVisited, nvisited - furthestVisited)); foreach (var v in visited.Slice(furthestVisited, nvisited - furthestVisited))
{
result.Add(v);
}
path = result; path = result;
return result.Count; return result.Count;

View File

@ -37,16 +37,16 @@ namespace DotRecast.Recast.Toolset.Tools
pathIterPolys.Clear(); pathIterPolys.Clear();
pathIterPolyCount = 0; pathIterPolyCount = 0;
smoothPath.Clear(); smoothPath.Clear();
var opt = new DtFindPathOption(enableRaycast ? DtFindPathOptions.DT_FINDPATH_ANY_ANGLE : 0, float.MaxValue); var opt = new DtFindPathOption(enableRaycast ? DtFindPathOptions.DT_FINDPATH_ANY_ANGLE : 0, float.MaxValue);
navQuery.FindPath(startRef, endRef, startPt, endPt, filter, ref pathIterPolys, opt); navQuery.FindPath(startRef, endRef, startPt, endPt, filter, ref pathIterPolys, opt);
if (0 >= pathIterPolys.Count) if (0 >= pathIterPolys.Count)
return DtStatus.DT_FAILURE; return DtStatus.DT_FAILURE;
pathIterPolyCount = pathIterPolys.Count; pathIterPolyCount = pathIterPolys.Count;
// Iterate over the path to find smooth path on the detail mesh surface. // Iterate over the path to find smooth path on the detail mesh surface.
navQuery.ClosestPointOnPoly(startRef, startPt, out var iterPos, out var _); navQuery.ClosestPointOnPoly(startRef, startPt, out var iterPos, out var _);
navQuery.ClosestPointOnPoly(pathIterPolys[pathIterPolys.Count - 1], endPt, out var targetPos, out var _); navQuery.ClosestPointOnPoly(pathIterPolys[pathIterPolys.Count - 1], endPt, out var targetPos, out var _);
@ -56,8 +56,10 @@ namespace DotRecast.Recast.Toolset.Tools
smoothPath.Clear(); smoothPath.Clear();
smoothPath.Add(iterPos); smoothPath.Add(iterPos);
var visited = new List<long>();
Span<long> visited = stackalloc long[16];
int nvisited = 0;
// Move towards target a small advancement at a time until target reached or // Move towards target a small advancement at a time until target reached or
// when ran out of memory to store the path. // when ran out of memory to store the path.
@ -69,7 +71,7 @@ namespace DotRecast.Recast.Toolset.Tools
{ {
break; break;
} }
bool endOfPath = (steerPosFlag & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0 bool endOfPath = (steerPosFlag & DtStraightPathFlags.DT_STRAIGHTPATH_END) != 0
? true ? true
: false; : false;
@ -89,15 +91,15 @@ namespace DotRecast.Recast.Toolset.Tools
{ {
len = STEP_SIZE / len; len = STEP_SIZE / len;
} }
RcVec3f moveTgt = RcVecUtils.Mad(iterPos, delta, len); RcVec3f moveTgt = RcVecUtils.Mad(iterPos, delta, len);
// Move // Move
navQuery.MoveAlongSurface(pathIterPolys[0], iterPos, moveTgt, filter, out var result, ref visited); navQuery.MoveAlongSurface(pathIterPolys[0], iterPos, moveTgt, filter, out var result, visited, out nvisited, 16);
iterPos = result; iterPos = result;
pathIterPolyCount = DtPathUtils.MergeCorridorStartMoved(ref pathIterPolys, pathIterPolyCount, MAX_POLYS, visited, visited.Count); pathIterPolyCount = DtPathUtils.MergeCorridorStartMoved(ref pathIterPolys, pathIterPolyCount, MAX_POLYS, visited, nvisited);
pathIterPolyCount = DtPathUtils.FixupShortcuts(ref pathIterPolys, pathIterPolyCount, navQuery); pathIterPolyCount = DtPathUtils.FixupShortcuts(ref pathIterPolys, pathIterPolyCount, navQuery);
var status = navQuery.GetPolyHeight(pathIterPolys[0], result, out var h); var status = navQuery.GetPolyHeight(pathIterPolys[0], result, out var h);

View File

@ -16,13 +16,13 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using DotRecast.Core.Numerics; using DotRecast.Core.Numerics;
using NUnit.Framework; using NUnit.Framework;
namespace DotRecast.Detour.Test; namespace DotRecast.Detour.Test;
public class MoveAlongSurfaceTest : AbstractDetourTest public class MoveAlongSurfaceTest : AbstractDetourTest
{ {
private static readonly long[][] VISITED = private static readonly long[][] VISITED =
@ -69,20 +69,21 @@ public class MoveAlongSurfaceTest : AbstractDetourTest
public void TestMoveAlongSurface() public void TestMoveAlongSurface()
{ {
IDtQueryFilter filter = new DtQueryDefaultFilter(); IDtQueryFilter filter = new DtQueryDefaultFilter();
var visited = new List<long>(); const int MAX_VISITED = 32;
Span<long> visited = stackalloc long[MAX_VISITED];
for (int i = 0; i < startRefs.Length; i++) for (int i = 0; i < startRefs.Length; i++)
{ {
long startRef = startRefs[i]; long startRef = startRefs[i];
RcVec3f startPos = startPoss[i]; RcVec3f startPos = startPoss[i];
RcVec3f endPos = endPoss[i]; RcVec3f endPos = endPoss[i];
var status = query.MoveAlongSurface(startRef, startPos, endPos, filter, out var result, ref visited); var status = query.MoveAlongSurface(startRef, startPos, endPos, filter, out var result, visited, out var nvisited, MAX_VISITED);
Assert.That(status.Succeeded(), Is.True); Assert.That(status.Succeeded(), Is.True);
Assert.That(result.X, Is.EqualTo(POSITION[i].X).Within(0.01f)); Assert.That(result.X, Is.EqualTo(POSITION[i].X).Within(0.01f));
Assert.That(result.Y, Is.EqualTo(POSITION[i].Y).Within(0.01f)); Assert.That(result.Y, Is.EqualTo(POSITION[i].Y).Within(0.01f));
Assert.That(result.Z, Is.EqualTo(POSITION[i].Z).Within(0.01f)); Assert.That(result.Z, Is.EqualTo(POSITION[i].Z).Within(0.01f));
Assert.That(visited.Count, Is.EqualTo(VISITED[i].Length)); Assert.That(nvisited, Is.EqualTo(VISITED[i].Length));
for (int j = 0; j < 3; j++) for (int j = 0; j < 3; j++)
{ {
Assert.That(visited[j], Is.EqualTo(VISITED[i][j])); Assert.That(visited[j], Is.EqualTo(VISITED[i][j]));