forked from mirror/DotRecast
fix bug where return value of dynamic update result is reversed
This commit is contained in:
parent
668ebd0128
commit
26a1dfddeb
|
@ -3,5 +3,7 @@
|
||||||
public interface IRcRand
|
public interface IRcRand
|
||||||
{
|
{
|
||||||
float Next();
|
float Next();
|
||||||
|
double NextDouble();
|
||||||
|
int NextInt32();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,9 +6,13 @@ namespace DotRecast.Core
|
||||||
{
|
{
|
||||||
private readonly Random _r;
|
private readonly Random _r;
|
||||||
|
|
||||||
public RcRand()
|
public RcRand() : this(new Random())
|
||||||
{
|
{
|
||||||
_r = new Random();
|
}
|
||||||
|
|
||||||
|
public RcRand(Random r)
|
||||||
|
{
|
||||||
|
_r = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcRand(long seed)
|
public RcRand(long seed)
|
||||||
|
@ -21,6 +25,11 @@ namespace DotRecast.Core
|
||||||
return (float)_r.NextDouble();
|
return (float)_r.NextDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public double NextDouble()
|
||||||
|
{
|
||||||
|
return _r.NextDouble();
|
||||||
|
}
|
||||||
|
|
||||||
public int NextInt32()
|
public int NextInt32()
|
||||||
{
|
{
|
||||||
return _r.Next();
|
return _r.Next();
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace DotRecast.Detour.Dynamic
|
||||||
private readonly BlockingCollection<IDtDaynmicTileJob> updateQueue = new BlockingCollection<IDtDaynmicTileJob>();
|
private readonly BlockingCollection<IDtDaynmicTileJob> updateQueue = new BlockingCollection<IDtDaynmicTileJob>();
|
||||||
private readonly RcAtomicLong currentColliderId = new RcAtomicLong(0);
|
private readonly RcAtomicLong currentColliderId = new RcAtomicLong(0);
|
||||||
private DtNavMesh _navMesh;
|
private DtNavMesh _navMesh;
|
||||||
private bool dirty = true;
|
private bool _dirty = true;
|
||||||
|
|
||||||
public DtDynamicNavMesh(DtVoxelFile voxelFile)
|
public DtDynamicNavMesh(DtVoxelFile voxelFile)
|
||||||
{
|
{
|
||||||
|
@ -105,29 +105,6 @@ namespace DotRecast.Detour.Dynamic
|
||||||
updateQueue.Add(new DtDynamicTileColliderRemovalJob(colliderId, GetTilesByCollider(colliderId)));
|
updateQueue.Add(new DtDynamicTileColliderRemovalJob(colliderId, GetTilesByCollider(colliderId)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform full build of the nav mesh
|
|
||||||
*/
|
|
||||||
public void Build()
|
|
||||||
{
|
|
||||||
ProcessQueue();
|
|
||||||
Rebuild(_tiles.Values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform incremental update of the nav mesh
|
|
||||||
*/
|
|
||||||
public bool Update()
|
|
||||||
{
|
|
||||||
return Rebuild(ProcessQueue());
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool Rebuild(ICollection<DtDynamicTile> stream)
|
|
||||||
{
|
|
||||||
foreach (var dynamicTile in stream)
|
|
||||||
Rebuild(dynamicTile);
|
|
||||||
return UpdateNavMesh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private HashSet<DtDynamicTile> ProcessQueue()
|
private HashSet<DtDynamicTile> ProcessQueue()
|
||||||
{
|
{
|
||||||
|
@ -159,27 +136,49 @@ namespace DotRecast.Detour.Dynamic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Perform full build of the navmesh
|
||||||
* Perform full build concurrently using the given {@link ExecutorService}
|
public void Build()
|
||||||
*/
|
{
|
||||||
public Task<bool> Build(TaskFactory executor)
|
ProcessQueue();
|
||||||
|
Rebuild(_tiles.Values);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform full build concurrently using the given {@link ExecutorService}
|
||||||
|
public bool Build(TaskFactory executor)
|
||||||
{
|
{
|
||||||
ProcessQueue();
|
ProcessQueue();
|
||||||
return Rebuild(_tiles.Values, executor);
|
return Rebuild(_tiles.Values, executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform incremental update concurrently using the given {@link ExecutorService}
|
// Perform incremental update of the navmesh
|
||||||
*/
|
public bool Update()
|
||||||
public Task<bool> Update(TaskFactory executor)
|
{
|
||||||
|
return Rebuild(ProcessQueue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform incremental update concurrently using the given {@link ExecutorService}
|
||||||
|
public bool Update(TaskFactory executor)
|
||||||
{
|
{
|
||||||
return Rebuild(ProcessQueue(), executor);
|
return Rebuild(ProcessQueue(), executor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task<bool> Rebuild(ICollection<DtDynamicTile> tiles, TaskFactory executor)
|
private bool Rebuild(ICollection<DtDynamicTile> tiles)
|
||||||
{
|
{
|
||||||
var tasks = tiles.Select(tile => executor.StartNew(() => Rebuild(tile))).ToArray();
|
foreach (var tile in tiles)
|
||||||
return Task.WhenAll(tasks).ContinueWith(k => UpdateNavMesh());
|
Rebuild(tile);
|
||||||
|
|
||||||
|
return UpdateNavMesh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool Rebuild(ICollection<DtDynamicTile> tiles, TaskFactory executor)
|
||||||
|
{
|
||||||
|
var tasks = tiles
|
||||||
|
.Select(tile => executor.StartNew(() => Rebuild(tile)))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
Task.WaitAll(tasks);
|
||||||
|
return UpdateNavMesh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ICollection<DtDynamicTile> GetTiles(float[] bounds)
|
private ICollection<DtDynamicTile> GetTiles(float[] bounds)
|
||||||
|
@ -218,19 +217,19 @@ namespace DotRecast.Detour.Dynamic
|
||||||
{
|
{
|
||||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||||
option.walkableHeight = config.walkableHeight;
|
option.walkableHeight = config.walkableHeight;
|
||||||
dirty = dirty | tile.Build(builder, config, _context);
|
_dirty = _dirty | tile.Build(builder, config, _context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool UpdateNavMesh()
|
private bool UpdateNavMesh()
|
||||||
{
|
{
|
||||||
if (dirty)
|
if (_dirty)
|
||||||
{
|
{
|
||||||
DtNavMesh navMesh = new DtNavMesh(navMeshParams, MAX_VERTS_PER_POLY);
|
DtNavMesh navMesh = new DtNavMesh(navMeshParams, MAX_VERTS_PER_POLY);
|
||||||
foreach (var t in _tiles.Values)
|
foreach (var t in _tiles.Values)
|
||||||
t.AddTo(navMesh);
|
t.AddTo(navMesh);
|
||||||
|
|
||||||
this._navMesh = navMesh;
|
_navMesh = navMesh;
|
||||||
dirty = false;
|
_dirty = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
var bridgeGeom = DemoInputGeomProvider.LoadFile("bridge.obj");
|
var bridgeGeom = DemoInputGeomProvider.LoadFile("bridge.obj");
|
||||||
var houseGeom = DemoInputGeomProvider.LoadFile("house.obj");
|
var houseGeom = DemoInputGeomProvider.LoadFile("house.obj");
|
||||||
var convexGeom = DemoInputGeomProvider.LoadFile("convex.obj");
|
var convexGeom = DemoInputGeomProvider.LoadFile("convex.obj");
|
||||||
_tool = new(Random.Shared, bridgeGeom, houseGeom, convexGeom);
|
_tool = new(new RcRand(Random.Shared), bridgeGeom, houseGeom, convexGeom);
|
||||||
executor = Task.Factory;
|
executor = Task.Factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
long t = RcFrequency.Ticks;
|
long t = RcFrequency.Ticks;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bool updated = _tool.UpdateDynaMesh(executor);
|
bool updated = _tool.Update(executor);
|
||||||
if (updated)
|
if (updated)
|
||||||
{
|
{
|
||||||
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
||||||
|
@ -450,7 +450,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
||||||
long t = RcFrequency.Ticks;
|
long t = RcFrequency.Ticks;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var _ = dynaMesh.Build(executor).Result;
|
var _ = dynaMesh.Build(executor);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,12 +18,12 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
private DtDynamicNavMesh dynaMesh;
|
private DtDynamicNavMesh dynaMesh;
|
||||||
private readonly Dictionary<long, RcGizmo> colliderGizmos;
|
private readonly Dictionary<long, RcGizmo> colliderGizmos;
|
||||||
|
|
||||||
private readonly Random random;
|
private readonly IRcRand random;
|
||||||
private readonly DemoInputGeomProvider bridgeGeom;
|
private readonly DemoInputGeomProvider bridgeGeom;
|
||||||
private readonly DemoInputGeomProvider houseGeom;
|
private readonly DemoInputGeomProvider houseGeom;
|
||||||
private readonly DemoInputGeomProvider convexGeom;
|
private readonly DemoInputGeomProvider convexGeom;
|
||||||
|
|
||||||
public RcDynamicUpdateTool(Random rand, DemoInputGeomProvider bridgeGeom, DemoInputGeomProvider houseGeom, DemoInputGeomProvider convexGeom)
|
public RcDynamicUpdateTool(IRcRand rand, DemoInputGeomProvider bridgeGeom, DemoInputGeomProvider houseGeom, DemoInputGeomProvider convexGeom)
|
||||||
{
|
{
|
||||||
this.colliderGizmos = new Dictionary<long, RcGizmo>();
|
this.colliderGizmos = new Dictionary<long, RcGizmo>();
|
||||||
this.random = rand;
|
this.random = rand;
|
||||||
|
@ -339,20 +339,14 @@ namespace DotRecast.Recast.Toolset.Tools
|
||||||
return resultvector;
|
return resultvector;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool UpdateDynaMesh(TaskFactory executor)
|
public bool Update(TaskFactory executor)
|
||||||
{
|
{
|
||||||
if (dynaMesh == null)
|
if (dynaMesh == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool updated = dynaMesh.Update(executor).Result;
|
return dynaMesh.Update(executor);
|
||||||
if (updated)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Raycast(RcVec3f spos, RcVec3f epos, out float hitPos, out RcVec3f raycastHitPos)
|
public bool Raycast(RcVec3f spos, RcVec3f epos, out float hitPos, out RcVec3f raycastHitPos)
|
||||||
|
|
|
@ -10,7 +10,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Dynamic.Test;
|
namespace DotRecast.Detour.Dynamic.Test;
|
||||||
|
|
||||||
|
|
||||||
public class DynamicNavMeshTest
|
public class DynamicNavMeshTest
|
||||||
{
|
{
|
||||||
private static readonly RcVec3f START_POS = new RcVec3f(70.87453f, 0.0010070801f, 86.69021f);
|
private static readonly RcVec3f START_POS = new RcVec3f(70.87453f, 0.0010070801f, 86.69021f);
|
||||||
|
@ -32,9 +31,7 @@ public class DynamicNavMeshTest
|
||||||
// create dynamic navmesh
|
// create dynamic navmesh
|
||||||
DtDynamicNavMesh mesh = new DtDynamicNavMesh(f);
|
DtDynamicNavMesh mesh = new DtDynamicNavMesh(f);
|
||||||
// build navmesh asynchronously using multiple threads
|
// build navmesh asynchronously using multiple threads
|
||||||
Task<bool> future = mesh.Build(Task.Factory);
|
mesh.Build(Task.Factory);
|
||||||
// wait for build to complete
|
|
||||||
bool _ = future.Result;
|
|
||||||
|
|
||||||
// create new query
|
// create new query
|
||||||
DtNavMeshQuery query = new DtNavMeshQuery(mesh.NavMesh());
|
DtNavMeshQuery query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
@ -54,9 +51,8 @@ public class DynamicNavMeshTest
|
||||||
long colliderId = mesh.AddCollider(colldier);
|
long colliderId = mesh.AddCollider(colldier);
|
||||||
|
|
||||||
// update navmesh asynchronously
|
// update navmesh asynchronously
|
||||||
future = mesh.Update(Task.Factory);
|
mesh.Update(Task.Factory);
|
||||||
// wait for update to complete
|
|
||||||
_ = future.Result;
|
|
||||||
// create new query
|
// create new query
|
||||||
query = new DtNavMeshQuery(mesh.NavMesh());
|
query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
|
||||||
|
@ -70,9 +66,7 @@ public class DynamicNavMeshTest
|
||||||
// remove obstacle
|
// remove obstacle
|
||||||
mesh.RemoveCollider(colliderId);
|
mesh.RemoveCollider(colliderId);
|
||||||
// update navmesh asynchronously
|
// update navmesh asynchronously
|
||||||
future = mesh.Update(Task.Factory);
|
mesh.Update(Task.Factory);
|
||||||
// wait for update to complete
|
|
||||||
_ = future.Result;
|
|
||||||
// create new query
|
// create new query
|
||||||
query = new DtNavMeshQuery(mesh.NavMesh());
|
query = new DtNavMeshQuery(mesh.NavMesh());
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ using NUnit.Framework;
|
||||||
|
|
||||||
namespace DotRecast.Detour.Dynamic.Test;
|
namespace DotRecast.Detour.Dynamic.Test;
|
||||||
|
|
||||||
|
|
||||||
public class VoxelQueryTest
|
public class VoxelQueryTest
|
||||||
{
|
{
|
||||||
private const int TILE_WIDTH = 100;
|
private const int TILE_WIDTH = 100;
|
||||||
|
@ -101,12 +100,12 @@ public class VoxelQueryTest
|
||||||
// load voxels from file
|
// load voxels from file
|
||||||
DtVoxelFileReader reader = new DtVoxelFileReader(DtVoxelTileLZ4ForTestCompressor.Shared);
|
DtVoxelFileReader reader = new DtVoxelFileReader(DtVoxelTileLZ4ForTestCompressor.Shared);
|
||||||
DtVoxelFile f = reader.Read(br);
|
DtVoxelFile f = reader.Read(br);
|
||||||
|
|
||||||
// create dynamic navmesh
|
// create dynamic navmesh
|
||||||
var mesh = new DtDynamicNavMesh(f);
|
var mesh = new DtDynamicNavMesh(f);
|
||||||
|
|
||||||
// build navmesh asynchronously using multiple threads
|
// build navmesh asynchronously using multiple threads
|
||||||
Task<bool> future = mesh.Build(Task.Factory);
|
mesh.Build(Task.Factory);
|
||||||
// wait for build to complete
|
|
||||||
var _ = future.Result;
|
|
||||||
return mesh;
|
return mesh;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue