fix bug where return value of dynamic update result is reversed

This commit is contained in:
ikpil 2024-04-13 12:43:54 +09:00
parent 668ebd0128
commit 26a1dfddeb
7 changed files with 65 additions and 68 deletions

View File

@ -3,5 +3,7 @@
public interface IRcRand public interface IRcRand
{ {
float Next(); float Next();
double NextDouble();
int NextInt32();
} }
} }

View File

@ -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();

View File

@ -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;
} }

View File

@ -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)
{ {

View File

@ -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)

View File

@ -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());

View File

@ -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;
} }
} }