forked from mirror/DotRecast
Compare commits
6 Commits
master
...
risky_opti
Author | SHA1 | Date |
---|---|---|
|
96ffed87e3 | |
|
1315de063f | |
|
a6db4344e4 | |
|
a7b9b772c4 | |
|
7aeb31d369 | |
|
18b544845f |
|
@ -1,8 +0,0 @@
|
||||||
{
|
|
||||||
"name": "rnd/dotrecastnetsim",
|
|
||||||
"description": "DotRecast",
|
|
||||||
"homepage": "https://git.bit5.ru/rnd/DotRecastNetSim.git",
|
|
||||||
"require": {
|
|
||||||
"php": ">=7.4"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +1,78 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace DotRecast.Core.Buffers
|
namespace DotRecast.Core.Buffers
|
||||||
{
|
{
|
||||||
public static class RcRentedArray
|
public static class RcRentedArray
|
||||||
{
|
{
|
||||||
|
private sealed class RentIdPool
|
||||||
|
{
|
||||||
|
private int[] _generations;
|
||||||
|
private readonly Queue<int> _freeIds;
|
||||||
|
private int _maxId;
|
||||||
|
|
||||||
|
public RentIdPool(int capacity)
|
||||||
|
{
|
||||||
|
_generations = new int[capacity];
|
||||||
|
_freeIds = new Queue<int>(capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal RentIdGen AcquireId()
|
||||||
|
{
|
||||||
|
if (!_freeIds.TryDequeue(out int id))
|
||||||
|
{
|
||||||
|
id = _maxId++;
|
||||||
|
if(_generations.Length <= id)
|
||||||
|
Array.Resize(ref _generations, _generations.Length << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RentIdGen(id, _generations[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ReturnId(int id)
|
||||||
|
{
|
||||||
|
_generations[id]++;
|
||||||
|
_freeIds.Enqueue(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal int GetGeneration(int id)
|
||||||
|
{
|
||||||
|
return _generations.Length <= id ? 0 : _generations[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public const int START_RENT_ID_POOL_CAPACITY = 16;
|
||||||
|
private static readonly ThreadLocal<RentIdPool> _rentPool = new ThreadLocal<RentIdPool>(() => new RentIdPool(START_RENT_ID_POOL_CAPACITY));
|
||||||
|
|
||||||
public static RcRentedArray<T> Rent<T>(int minimumLength)
|
public static RcRentedArray<T> Rent<T>(int minimumLength)
|
||||||
{
|
{
|
||||||
var array = ArrayPool<T>.Shared.Rent(minimumLength);
|
var array = ArrayPool<T>.Shared.Rent(minimumLength);
|
||||||
return new RcRentedArray<T>(ArrayPool<T>.Shared, array, minimumLength);
|
return new RcRentedArray<T>(ArrayPool<T>.Shared, _rentPool.Value.AcquireId(), array, minimumLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool IsDisposed(RentIdGen rentIdGen)
|
||||||
|
{
|
||||||
|
return _rentPool.Value.GetGeneration(rentIdGen.Id) != rentIdGen.Gen;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ReturnId(RentIdGen rentIdGen)
|
||||||
|
{
|
||||||
|
_rentPool.Value.ReturnId(rentIdGen.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly struct RentIdGen
|
||||||
|
{
|
||||||
|
public readonly int Id;
|
||||||
|
public readonly int Gen;
|
||||||
|
|
||||||
|
public RentIdGen(int id, int gen)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Gen = gen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,15 +80,17 @@ namespace DotRecast.Core.Buffers
|
||||||
{
|
{
|
||||||
private ArrayPool<T> _owner;
|
private ArrayPool<T> _owner;
|
||||||
private T[] _array;
|
private T[] _array;
|
||||||
|
private readonly RentIdGen _rentIdGen;
|
||||||
|
|
||||||
public int Length { get; }
|
public int Length { get; }
|
||||||
public bool IsDisposed => null == _owner || null == _array;
|
public bool IsDisposed => null == _owner || null == _array || RcRentedArray.IsDisposed(_rentIdGen);
|
||||||
|
|
||||||
internal RcRentedArray(ArrayPool<T> owner, T[] array, int length)
|
internal RcRentedArray(ArrayPool<T> owner, RentIdGen rentIdGen, T[] array, int length)
|
||||||
{
|
{
|
||||||
_owner = owner;
|
_owner = owner;
|
||||||
_array = array;
|
_array = array;
|
||||||
Length = length;
|
Length = length;
|
||||||
|
_rentIdGen = rentIdGen;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref T this[int index]
|
public ref T this[int index]
|
||||||
|
@ -34,6 +99,8 @@ namespace DotRecast.Core.Buffers
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
RcThrowHelper.ThrowExceptionIfIndexOutOfRange(index, Length);
|
RcThrowHelper.ThrowExceptionIfIndexOutOfRange(index, Length);
|
||||||
|
if (IsDisposed)
|
||||||
|
throw new NullReferenceException();
|
||||||
return ref _array[index];
|
return ref _array[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,12 +118,14 @@ namespace DotRecast.Core.Buffers
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (null != _owner && null != _array)
|
if (null != _owner && null != _array && !RcRentedArray.IsDisposed(_rentIdGen))
|
||||||
{
|
{
|
||||||
|
RcRentedArray.ReturnId(_rentIdGen);
|
||||||
_owner.Return(_array, true);
|
_owner.Return(_array, true);
|
||||||
_owner = null;
|
|
||||||
_array = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_owner = null;
|
||||||
|
_array = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Core",
|
|
||||||
"rootNamespace": "DotRecast.Core",
|
|
||||||
"references": [],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour.Crowd",
|
|
||||||
"rootNamespace": "DotRecast.Detour.Crowd",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core",
|
|
||||||
"DotRecast.Detour"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -22,7 +22,6 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using DotRecast.Core;
|
using DotRecast.Core;
|
||||||
using DotRecast.Core.Buffers;
|
|
||||||
using DotRecast.Core.Collections;
|
using DotRecast.Core.Collections;
|
||||||
using DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
|
@ -425,13 +424,11 @@ namespace DotRecast.Detour.Crowd
|
||||||
// Optimize path topology.
|
// Optimize path topology.
|
||||||
UpdateTopologyOptimization(agents, dt);
|
UpdateTopologyOptimization(agents, dt);
|
||||||
|
|
||||||
#region Disabled for performance issues
|
|
||||||
// Register agents to proximity grid.
|
// Register agents to proximity grid.
|
||||||
// BuildProximityGrid(agents);
|
BuildProximityGrid(agents);
|
||||||
|
|
||||||
// Get nearby navmesh segments and agents to collide with.
|
// Get nearby navmesh segments and agents to collide with.
|
||||||
// BuildNeighbours(agents);
|
BuildNeighbours(agents);
|
||||||
#endregion
|
|
||||||
|
|
||||||
// Find next corner to steer to.
|
// Find next corner to steer to.
|
||||||
FindCorners(agents, debug);
|
FindCorners(agents, debug);
|
||||||
|
@ -1059,7 +1056,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check
|
// Check
|
||||||
float triggerRadius = ag.option.radius * 0.25f;//todo make parameterizable
|
float triggerRadius = ag.option.radius * 2.25f;
|
||||||
if (ag.OverOffmeshConnection(triggerRadius))
|
if (ag.OverOffmeshConnection(triggerRadius))
|
||||||
{
|
{
|
||||||
// Prepare to off-mesh connection.
|
// Prepare to off-mesh connection.
|
||||||
|
@ -1208,9 +1205,6 @@ namespace DotRecast.Detour.Crowd
|
||||||
for (int j = 0; j < ag.nneis; ++j)
|
for (int j = 0; j < ag.nneis; ++j)
|
||||||
{
|
{
|
||||||
DtCrowdAgent nei = ag.neis[j].agent;
|
DtCrowdAgent nei = ag.neis[j].agent;
|
||||||
if(!nei.option.contributeObstacleAvoidance || nei.option.obstacleAvoidanceWeight < ag.option.obstacleAvoidanceWeight)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
_obstacleQuery.AddCircle(nei.npos, nei.option.radius, nei.vel, nei.dvel);
|
_obstacleQuery.AddCircle(nei.npos, nei.option.radius, nei.vel, nei.dvel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,9 +45,6 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
|
/// [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]
|
||||||
public int obstacleAvoidanceType;
|
public int obstacleAvoidanceType;
|
||||||
|
|
||||||
public bool contributeObstacleAvoidance;
|
|
||||||
public float obstacleAvoidanceWeight;
|
|
||||||
|
|
||||||
/// The index of the query filter used by this agent.
|
/// The index of the query filter used by this agent.
|
||||||
public int queryFilterType;
|
public int queryFilterType;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
|
|
||||||
public int pathQueueSize = 32; // Max number of path requests in the queue
|
public int pathQueueSize = 32; // Max number of path requests in the queue
|
||||||
public int maxFindPathIterations = 100; // Max number of sliced path finding iterations executed per update (used to handle longer paths and replans)
|
public int maxFindPathIterations = 100; // Max number of sliced path finding iterations executed per update (used to handle longer paths and replans)
|
||||||
public int maxTargetFindPathIterations = 100; // Max number of sliced path finding iterations executed per agent to find the initial path to target
|
public int maxTargetFindPathIterations = 20; // Max number of sliced path finding iterations executed per agent to find the initial path to target
|
||||||
public float topologyOptimizationTimeThreshold = 0.5f; // Min time between topology optimizations (in seconds)
|
public float topologyOptimizationTimeThreshold = 0.5f; // Min time between topology optimizations (in seconds)
|
||||||
public int checkLookAhead = 10; // The number of polygons from the beginning of the corridor to check to ensure path validity
|
public int checkLookAhead = 10; // The number of polygons from the beginning of the corridor to check to ensure path validity
|
||||||
public float targetReplanDelay = 1.0f; // Min time between target re-planning (in seconds)
|
public float targetReplanDelay = 1.0f; // Min time between target re-planning (in seconds)
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace DotRecast.Detour.Crowd
|
||||||
/// @ingroup crowd
|
/// @ingroup crowd
|
||||||
/// @see dtQueryFilter, dtCrowd::GetFilter() dtCrowd::GetEditableFilter(),
|
/// @see dtQueryFilter, dtCrowd::GetFilter() dtCrowd::GetEditableFilter(),
|
||||||
/// dtCrowdAgentParams::queryFilterType
|
/// dtCrowdAgentParams::queryFilterType
|
||||||
public const int DT_CROWD_MAX_QUERY_FILTER_TYPE = 32;
|
public const int DT_CROWD_MAX_QUERY_FILTER_TYPE = 16;
|
||||||
|
|
||||||
public const int MAX_ITERS_PER_UPDATE = 100;
|
public const int MAX_ITERS_PER_UPDATE = 100;
|
||||||
public const int MAX_PATHQUEUE_NODES = 4096;
|
public const int MAX_PATHQUEUE_NODES = 4096;
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour.Dynamic",
|
|
||||||
"rootNamespace": "DotRecast.Detour.Dynamic",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Detour",
|
|
||||||
"DotRecast.Recast",
|
|
||||||
"DotRecast.Core"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour.Extras",
|
|
||||||
"rootNamespace": "DotRecast.Detour.Extras",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core",
|
|
||||||
"DotRecast.Detour",
|
|
||||||
"DotRecast.Recast"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour.TileCache",
|
|
||||||
"rootNamespace": "DotRecast.Detour.TileCache",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core",
|
|
||||||
"DotRecast.Detour",
|
|
||||||
"DotRecast.Recast"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Detour",
|
|
||||||
"rootNamespace": "DotRecast.Detour",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -18,11 +18,8 @@ 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;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
[Serializable]
|
|
||||||
public class DtMeshData
|
public class DtMeshData
|
||||||
{
|
{
|
||||||
public DtMeshHeader header; //< The tile header.
|
public DtMeshHeader header; //< The tile header.
|
||||||
|
|
|
@ -18,13 +18,11 @@ 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 DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/** Provides high level information related to a dtMeshTile object. */
|
/** Provides high level information related to a dtMeshTile object. */
|
||||||
[Serializable]
|
|
||||||
public class DtMeshHeader
|
public class DtMeshHeader
|
||||||
{
|
{
|
||||||
/** Tile magic number. (Used to identify the data format.) */
|
/** Tile magic number. (Used to identify the data format.) */
|
||||||
|
|
|
@ -18,7 +18,6 @@ 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 DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
|
|
|
@ -1637,20 +1637,20 @@ namespace DotRecast.Detour
|
||||||
DtStatus stat = DtStatus.DT_STATUS_NOTHING;
|
DtStatus stat = DtStatus.DT_STATUS_NOTHING;
|
||||||
|
|
||||||
// TODO: Should this be callers responsibility?
|
// TODO: Should this be callers responsibility?
|
||||||
// var closestStartPosRes = ClosestPointOnPolyBoundary(path[0], startPos, out var closestStartPos);
|
var closestStartPosRes = ClosestPointOnPolyBoundary(path[0], startPos, out var closestStartPos);
|
||||||
// if (closestStartPosRes.Failed())
|
if (closestStartPosRes.Failed())
|
||||||
// {
|
{
|
||||||
// return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
|
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// var closestEndPosRes = ClosestPointOnPolyBoundary(path[pathSize - 1], endPos, out var closestEndPos);
|
var closestEndPosRes = ClosestPointOnPolyBoundary(path[pathSize - 1], endPos, out var closestEndPos);
|
||||||
// if (closestEndPosRes.Failed())
|
if (closestEndPosRes.Failed())
|
||||||
// {
|
{
|
||||||
// return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
|
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Add start point.
|
// Add start point.
|
||||||
stat = AppendVertex(startPos, DtStraightPathFlags.DT_STRAIGHTPATH_START, path[0], straightPath, ref straightPathCount, maxStraightPath);
|
stat = AppendVertex(closestStartPos, DtStraightPathFlags.DT_STRAIGHTPATH_START, path[0], straightPath, ref straightPathCount, maxStraightPath);
|
||||||
if (!stat.InProgress())
|
if (!stat.InProgress())
|
||||||
{
|
{
|
||||||
return stat;
|
return stat;
|
||||||
|
@ -1658,7 +1658,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
if (pathSize > 1)
|
if (pathSize > 1)
|
||||||
{
|
{
|
||||||
RcVec3f portalApex = startPos;
|
RcVec3f portalApex = closestStartPos;
|
||||||
RcVec3f portalLeft = portalApex;
|
RcVec3f portalLeft = portalApex;
|
||||||
RcVec3f portalRight = portalApex;
|
RcVec3f portalRight = portalApex;
|
||||||
int apexIndex = 0;
|
int apexIndex = 0;
|
||||||
|
@ -1687,21 +1687,21 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
// Failed to get portal points, in practice this means that path[i+1] is invalid polygon.
|
// Failed to get portal points, in practice this means that path[i+1] is invalid polygon.
|
||||||
// Clamp the end point to path[i], and return the path so far.
|
// Clamp the end point to path[i], and return the path so far.
|
||||||
// var cpStatus = ClosestPointOnPolyBoundary(path[i], endPos, out closestEndPos);
|
var cpStatus = ClosestPointOnPolyBoundary(path[i], endPos, out closestEndPos);
|
||||||
// if (cpStatus.Failed())
|
if (cpStatus.Failed())
|
||||||
// {
|
{
|
||||||
// return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
|
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Append portals along the current straight path segment.
|
// Append portals along the current straight path segment.
|
||||||
if ((options & (DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS | DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
if ((options & (DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS | DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
||||||
{
|
{
|
||||||
// Ignore status return value as we're just about to return anyway.
|
// Ignore status return value as we're just about to return anyway.
|
||||||
AppendPortals(apexIndex, i, endPos, path, straightPath, ref straightPathCount, maxStraightPath, options);
|
AppendPortals(apexIndex, i, closestEndPos, path, straightPath, ref straightPathCount, maxStraightPath, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore status return value as we're just about to return anyway.
|
// Ignore status return value as we're just about to return anyway.
|
||||||
AppendVertex(endPos, 0, path[i], straightPath, ref straightPathCount, maxStraightPath);
|
AppendVertex(closestEndPos, 0, path[i], straightPath, ref straightPathCount, maxStraightPath);
|
||||||
|
|
||||||
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM | (straightPathCount >= maxStraightPath ? DtStatus.DT_BUFFER_TOO_SMALL : DtStatus.DT_STATUS_NOTHING);
|
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM | (straightPathCount >= maxStraightPath ? DtStatus.DT_BUFFER_TOO_SMALL : DtStatus.DT_STATUS_NOTHING);
|
||||||
}
|
}
|
||||||
|
@ -1719,8 +1719,8 @@ namespace DotRecast.Detour
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// End of the path.
|
// End of the path.
|
||||||
left = endPos;
|
left = closestEndPos;
|
||||||
right = endPos;
|
right = closestEndPos;
|
||||||
toType = DtPolyTypes.DT_POLYTYPE_GROUND;
|
toType = DtPolyTypes.DT_POLYTYPE_GROUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1840,7 +1840,7 @@ namespace DotRecast.Detour
|
||||||
// Append portals along the current straight path segment.
|
// Append portals along the current straight path segment.
|
||||||
if ((options & (DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS | DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
if ((options & (DtStraightPathOptions.DT_STRAIGHTPATH_AREA_CROSSINGS | DtStraightPathOptions.DT_STRAIGHTPATH_ALL_CROSSINGS)) != 0)
|
||||||
{
|
{
|
||||||
stat = AppendPortals(apexIndex, pathSize - 1, endPos, path, straightPath, ref straightPathCount, maxStraightPath, options);
|
stat = AppendPortals(apexIndex, pathSize - 1, closestEndPos, path, straightPath, ref straightPathCount, maxStraightPath, options);
|
||||||
if (!stat.InProgress())
|
if (!stat.InProgress())
|
||||||
{
|
{
|
||||||
return stat;
|
return stat;
|
||||||
|
@ -1849,7 +1849,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore status return value as we're just about to return anyway.
|
// Ignore status return value as we're just about to return anyway.
|
||||||
AppendVertex(endPos, DtStraightPathFlags.DT_STRAIGHTPATH_END, 0, straightPath, ref straightPathCount, maxStraightPath);
|
AppendVertex(closestEndPos, DtStraightPathFlags.DT_STRAIGHTPATH_END, 0, straightPath, ref straightPathCount, maxStraightPath);
|
||||||
return DtStatus.DT_SUCCESS | (straightPathCount >= maxStraightPath ? DtStatus.DT_BUFFER_TOO_SMALL : DtStatus.DT_STATUS_NOTHING);
|
return DtStatus.DT_SUCCESS | (straightPathCount >= maxStraightPath ? DtStatus.DT_BUFFER_TOO_SMALL : DtStatus.DT_STATUS_NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2077,11 +2077,19 @@ namespace DotRecast.Detour
|
||||||
fromType = 0;
|
fromType = 0;
|
||||||
toType = 0;
|
toType = 0;
|
||||||
|
|
||||||
m_nav.GetTileAndPolyByRefUnsafe(from, out var fromTile, out var fromPoly);
|
var status = m_nav.GetTileAndPolyByRef(from, out var fromTile, out var fromPoly);
|
||||||
|
if (status.Failed())
|
||||||
|
{
|
||||||
|
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
fromType = fromPoly.GetPolyType();
|
fromType = fromPoly.GetPolyType();
|
||||||
|
|
||||||
m_nav.GetTileAndPolyByRefUnsafe(to, out var toTile, out var toPoly);
|
status = m_nav.GetTileAndPolyByRef(to, out var toTile, out var toPoly);
|
||||||
|
if (status.Failed())
|
||||||
|
{
|
||||||
|
return DtStatus.DT_FAILURE | DtStatus.DT_INVALID_PARAM;
|
||||||
|
}
|
||||||
|
|
||||||
toType = toPoly.GetPolyType();
|
toType = toPoly.GetPolyType();
|
||||||
|
|
||||||
|
@ -2533,7 +2541,7 @@ namespace DotRecast.Detour
|
||||||
// int va = a * 3;
|
// int va = a * 3;
|
||||||
// int vb = b * 3;
|
// int vb = b * 3;
|
||||||
float dx = verts[b].X - verts[a].X;
|
float dx = verts[b].X - verts[a].X;
|
||||||
float dz = verts[b].Z - verts[a].Z;
|
float dz = verts[b].Z - verts[a].X;
|
||||||
hit.hitNormal = RcVec3f.Normalize(new RcVec3f(dz, 0, -dx));
|
hit.hitNormal = RcVec3f.Normalize(new RcVec3f(dz, 0, -dx));
|
||||||
return DtStatus.DT_SUCCESS;
|
return DtStatus.DT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,8 @@ 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 System.Linq;
|
using System.Linq;
|
||||||
using DotRecast.Core.Buffers;
|
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
|
@ -29,68 +27,24 @@ namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
private readonly Dictionary<long, List<DtNode>> m_map;
|
private readonly Dictionary<long, List<DtNode>> m_map;
|
||||||
|
|
||||||
private int m_usedNodesCount;
|
private int m_nodeCount;
|
||||||
private List<DtNode[]> m_buckets;
|
private readonly List<DtNode> m_nodes;
|
||||||
private readonly int m_initialBufferCapacityBase;
|
|
||||||
private readonly RcObjectPool<List<DtNode>> m_listPool;
|
|
||||||
|
|
||||||
public DtNodePool(int initialBufferCapacityBase = 6) // initial size 64
|
public DtNodePool()
|
||||||
{
|
{
|
||||||
m_map = new Dictionary<long, List<DtNode>>();
|
m_map = new Dictionary<long, List<DtNode>>();
|
||||||
m_listPool = new RcObjectPool<List<DtNode>>(() => new List<DtNode>());
|
m_nodes = new List<DtNode>();
|
||||||
m_buckets = new List<DtNode[]>();
|
|
||||||
m_initialBufferCapacityBase = initialBufferCapacityBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddNewBucket()
|
|
||||||
{
|
|
||||||
var bucketIndex = m_buckets.Count;
|
|
||||||
var bucket = new DtNode[1 << (bucketIndex + m_initialBufferCapacityBase)];
|
|
||||||
m_buckets.Add(bucket);
|
|
||||||
FillBucket(bucketIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void FillBucket(int bucketIndex)
|
|
||||||
{
|
|
||||||
var bucket = m_buckets[bucketIndex];
|
|
||||||
var startIndex = GetBucketStartIndex(bucketIndex);
|
|
||||||
for (int i = 0; i < bucket.Length; i++)
|
|
||||||
{
|
|
||||||
bucket[i] = new DtNode(startIndex + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetBucketStartIndex(int bucketIndex)
|
|
||||||
{
|
|
||||||
return ((1 << (bucketIndex + m_initialBufferCapacityBase)) - 1) ^ ((1 << m_initialBufferCapacityBase) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DtNode[] EnsureBucket(int bucketIndex)
|
|
||||||
{
|
|
||||||
if (m_buckets.Count == bucketIndex)
|
|
||||||
AddNewBucket();
|
|
||||||
else if (m_buckets.Count < bucketIndex)
|
|
||||||
throw new Exception();
|
|
||||||
return m_buckets[bucketIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetBucketIndexByElementIndex(int elementIndex)
|
|
||||||
{
|
|
||||||
return DtUtils.Ilog2((elementIndex >> m_initialBufferCapacityBase) + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
foreach (var pair in m_map)
|
|
||||||
m_listPool.Return(pair.Value);
|
|
||||||
|
|
||||||
m_map.Clear();
|
m_map.Clear();
|
||||||
m_usedNodesCount = 0;
|
m_nodeCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetNodeCount()
|
public int GetNodeCount()
|
||||||
{
|
{
|
||||||
return m_usedNodesCount;
|
return m_nodeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int FindNodes(long id, out List<DtNode> nodes)
|
public int FindNodes(long id, out List<DtNode> nodes)
|
||||||
|
@ -130,8 +84,7 @@ namespace DotRecast.Detour
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nodes = m_listPool.Get();
|
nodes = new List<DtNode>();
|
||||||
nodes.Clear();
|
|
||||||
m_map.Add(id, nodes);
|
m_map.Add(id, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,10 +93,15 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
private DtNode Create(long id, int state, List<DtNode> nodes)
|
private DtNode Create(long id, int state, List<DtNode> nodes)
|
||||||
{
|
{
|
||||||
int i = m_usedNodesCount++;
|
if (m_nodes.Count <= m_nodeCount)
|
||||||
int bucketIndex = GetBucketIndexByElementIndex(i);
|
{
|
||||||
int bucketStartIndex = GetBucketStartIndex(bucketIndex);
|
var newNode = new DtNode(m_nodeCount);
|
||||||
var node = EnsureBucket(bucketIndex)[i - bucketStartIndex];
|
m_nodes.Add(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = m_nodeCount;
|
||||||
|
m_nodeCount++;
|
||||||
|
var node = m_nodes[i];
|
||||||
node.pidx = 0;
|
node.pidx = 0;
|
||||||
node.cost = 0;
|
node.cost = 0;
|
||||||
node.total = 0;
|
node.total = 0;
|
||||||
|
@ -165,16 +123,9 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public DtNode GetNodeAtIdx(int idx)
|
public DtNode GetNodeAtIdx(int idx)
|
||||||
{
|
{
|
||||||
if (idx == 0)
|
return idx != 0
|
||||||
return null;
|
? m_nodes[idx - 1]
|
||||||
|
: null;
|
||||||
int bucketIndex = GetBucketIndexByElementIndex(idx - 1);
|
|
||||||
if (m_buckets.Count <= bucketIndex)
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
|
|
||||||
int bucketStartIndex = GetBucketStartIndex(bucketIndex);
|
|
||||||
var node = EnsureBucket(bucketIndex)[idx - bucketStartIndex - 1];
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DtNode GetNode(long refs)
|
public DtNode GetNode(long refs)
|
||||||
|
@ -184,7 +135,7 @@ namespace DotRecast.Detour
|
||||||
|
|
||||||
public IEnumerable<DtNode> AsEnumerable()
|
public IEnumerable<DtNode> AsEnumerable()
|
||||||
{
|
{
|
||||||
return m_buckets.SelectMany(x => x);
|
return m_nodes.Take(m_nodeCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,14 +18,12 @@ 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 DotRecast.Core.Numerics;
|
using DotRecast.Core.Numerics;
|
||||||
|
|
||||||
namespace DotRecast.Detour
|
namespace DotRecast.Detour
|
||||||
{
|
{
|
||||||
/// Defines an navigation mesh off-mesh connection within a dtMeshTile object.
|
/// Defines an navigation mesh off-mesh connection within a dtMeshTile object.
|
||||||
/// An off-mesh connection is a user defined traversable connection made up to two vertices.
|
/// An off-mesh connection is a user defined traversable connection made up to two vertices.
|
||||||
[Serializable]
|
|
||||||
public class DtOffMeshConnection
|
public class DtOffMeshConnection
|
||||||
{
|
{
|
||||||
/// The endpoints of the connection. [(ax, ay, az, bx, by, bz)]
|
/// The endpoints of the connection. [(ax, ay, az, bx, by, bz)]
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Recast.Demo",
|
|
||||||
"rootNamespace": "DotRecast.Recast.Demo",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [
|
|
||||||
"Android",
|
|
||||||
"Editor",
|
|
||||||
"EmbeddedLinux",
|
|
||||||
"GameCoreScarlett",
|
|
||||||
"GameCoreXboxOne",
|
|
||||||
"iOS",
|
|
||||||
"LinuxStandalone64",
|
|
||||||
"CloudRendering",
|
|
||||||
"macOSStandalone",
|
|
||||||
"PS4",
|
|
||||||
"PS5",
|
|
||||||
"QNX",
|
|
||||||
"Stadia",
|
|
||||||
"Switch",
|
|
||||||
"tvOS",
|
|
||||||
"WSA",
|
|
||||||
"VisionOS",
|
|
||||||
"WebGL",
|
|
||||||
"WindowsStandalone32",
|
|
||||||
"WindowsStandalone64",
|
|
||||||
"XboxOne"
|
|
||||||
],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [
|
|
||||||
{
|
|
||||||
"name": "Select...",
|
|
||||||
"expression": "",
|
|
||||||
"define": "USE_RECAST_DEMO"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Recast.Toolset",
|
|
||||||
"rootNamespace": "DotRecast.Recast.Toolset",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core",
|
|
||||||
"DotRecast.Recast",
|
|
||||||
"DotRecast.Detour",
|
|
||||||
"DotRecast.Detour.Crowd",
|
|
||||||
"DotRecast.Detour.Dynamic",
|
|
||||||
"DotRecast.Detour.Extras",
|
|
||||||
"DotRecast.Detour.TileCache"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -46,13 +46,13 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
if (null != _geom)
|
if (null != _geom)
|
||||||
{
|
{
|
||||||
var offMeshConnections = _geom.GetOffMeshConnections();
|
var offMeshConnections = _geom.GetOffMeshConnections();
|
||||||
option.offMeshConCount = offMeshConnections.Count;
|
|
||||||
option.offMeshConVerts = new float[option.offMeshConCount * 6];
|
option.offMeshConVerts = new float[option.offMeshConCount * 6];
|
||||||
option.offMeshConRad = new float[option.offMeshConCount];
|
option.offMeshConRad = new float[option.offMeshConCount];
|
||||||
option.offMeshConDir = new int[option.offMeshConCount];
|
option.offMeshConDir = new int[option.offMeshConCount];
|
||||||
option.offMeshConAreas = new int[option.offMeshConCount];
|
option.offMeshConAreas = new int[option.offMeshConCount];
|
||||||
option.offMeshConFlags = new int[option.offMeshConCount];
|
option.offMeshConFlags = new int[option.offMeshConCount];
|
||||||
option.offMeshConUserID = new int[option.offMeshConCount];
|
option.offMeshConUserID = new int[option.offMeshConCount];
|
||||||
|
option.offMeshConCount = offMeshConnections.Count;
|
||||||
for (int i = 0; i < option.offMeshConCount; i++)
|
for (int i = 0; i < option.offMeshConCount; i++)
|
||||||
{
|
{
|
||||||
RcOffMeshConnection offMeshCon = offMeshConnections[i];
|
RcOffMeshConnection offMeshCon = offMeshConnections[i];
|
||||||
|
@ -65,7 +65,7 @@ namespace DotRecast.Recast.Toolset.Geom
|
||||||
option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0;
|
option.offMeshConDir[i] = offMeshCon.bidir ? 1 : 0;
|
||||||
option.offMeshConAreas[i] = offMeshCon.area;
|
option.offMeshConAreas[i] = offMeshCon.area;
|
||||||
option.offMeshConFlags[i] = offMeshCon.flags;
|
option.offMeshConFlags[i] = offMeshCon.flags;
|
||||||
option.offMeshConUserID[i] = offMeshCon.userId;
|
// option.offMeshConUserID[i] = offMeshCon.userId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"name": "DotRecast.Recast",
|
|
||||||
"rootNamespace": "DotRecast.Recast",
|
|
||||||
"references": [
|
|
||||||
"DotRecast.Core"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": true
|
|
||||||
}
|
|
|
@ -33,7 +33,7 @@ namespace DotRecast.Recast.Geom
|
||||||
public readonly int flags;
|
public readonly int flags;
|
||||||
public readonly int userId;
|
public readonly int userId;
|
||||||
|
|
||||||
public RcOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags, int userId = 0)
|
public RcOffMeshConnection(RcVec3f start, RcVec3f end, float radius, bool bidir, int area, int flags)
|
||||||
{
|
{
|
||||||
verts = new float[6];
|
verts = new float[6];
|
||||||
verts[0] = start.X;
|
verts[0] = start.X;
|
||||||
|
@ -46,7 +46,6 @@ namespace DotRecast.Recast.Geom
|
||||||
this.bidir = bidir;
|
this.bidir = bidir;
|
||||||
this.area = area;
|
this.area = area;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
this.userId = userId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"name": "com.rnd.dotrecast",
|
|
||||||
"displayName": "DotRecast",
|
|
||||||
"version": "0.4.1"
|
|
||||||
}
|
|
|
@ -103,4 +103,19 @@ public class RcRentedArrayTest
|
||||||
Assert.That(r1.IsDisposed, Is.EqualTo(true));
|
Assert.That(r1.IsDisposed, Is.EqualTo(true));
|
||||||
Assert.That(r1.AsArray(), Is.Null);
|
Assert.That(r1.AsArray(), Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestIdPoolCapacity()
|
||||||
|
{
|
||||||
|
var buffer = new RcRentedArray<int>[RcRentedArray.START_RENT_ID_POOL_CAPACITY + 2];
|
||||||
|
for (int i = 0; i < buffer.Length; i++)
|
||||||
|
{
|
||||||
|
Assert.DoesNotThrow(() => buffer[i] = RcRentedArray.Rent<int>(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < buffer.Length; i++)
|
||||||
|
{
|
||||||
|
Assert.DoesNotThrow(() => buffer[i].Dispose());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue