forked from mirror/DotRecast
Compare commits
27 Commits
3157c1e764
...
897748285f
Author | SHA1 | Date |
---|---|---|
wrenge | 897748285f | |
wrenge | 331e35ecbb | |
ikpil | f49f9eb558 | |
ikpil | 6b2bd27b71 | |
ikpil | 50ea674cce | |
ikpil | 8fe46a6450 | |
ikpil | 80e07ebb3c | |
ikpil | 97ffaf8700 | |
ikpil | 17c1c18372 | |
ikpil | 9210eb58fe | |
ikpil | da82d6ba4d | |
ikpil | 26a1dfddeb | |
ikpil | 668ebd0128 | |
ikpil | 402b25a436 | |
ikpil | 7874b4403c | |
ikpil | 82027dffd7 | |
ikpil | 573386c473 | |
ikpil | daf826f5f4 | |
wreng | b67ebeaec3 | |
Andrew Gilewsky | 7dfac39408 | |
ikpil | 4b8cd8e31b | |
ikpil | 6a57c067ac | |
ikpil | 0c6921ad6b | |
ikpil | b0644a70b7 | |
ikpil | 2f2d68c29f | |
ikpil | 30bce34eaf | |
ikpil | d8ae9f2297 |
|
@ -20,6 +20,7 @@ dotnet_sort_system_directives_first = true
|
|||
csharp_preserve_single_line_statements = false
|
||||
csharp_preserve_single_line_blocks = true
|
||||
|
||||
#
|
||||
# ReSharper properties
|
||||
resharper_csharp_wrap_lines = false
|
||||
resharper_csharp_space_before_trailing_comment = true
|
||||
resharper_csharp_space_after_operator_keyword = true
|
||||
|
|
|
@ -3,5 +3,7 @@
|
|||
public interface IRcRand
|
||||
{
|
||||
float Next();
|
||||
double NextDouble();
|
||||
int NextInt32();
|
||||
}
|
||||
}
|
|
@ -6,9 +6,13 @@ namespace DotRecast.Core
|
|||
{
|
||||
private readonly Random _r;
|
||||
|
||||
public RcRand()
|
||||
public RcRand() : this(new Random())
|
||||
{
|
||||
_r = new Random();
|
||||
}
|
||||
|
||||
public RcRand(Random r)
|
||||
{
|
||||
_r = r;
|
||||
}
|
||||
|
||||
public RcRand(long seed)
|
||||
|
@ -21,6 +25,11 @@ namespace DotRecast.Core
|
|||
return (float)_r.NextDouble();
|
||||
}
|
||||
|
||||
public double NextDouble()
|
||||
{
|
||||
return _r.NextDouble();
|
||||
}
|
||||
|
||||
public int NextInt32()
|
||||
{
|
||||
return _r.Next();
|
||||
|
|
|
@ -22,6 +22,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using DotRecast.Core;
|
||||
using DotRecast.Core.Buffers;
|
||||
using DotRecast.Core.Collections;
|
||||
using DotRecast.Core.Numerics;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ freely, subject to the following restrictions:
|
|||
|
||||
using System;
|
||||
using DotRecast.Core;
|
||||
using DotRecast.Core.Buffers;
|
||||
using DotRecast.Core.Numerics;
|
||||
|
||||
|
||||
|
@ -402,7 +403,7 @@ namespace DotRecast.Detour.Crowd
|
|||
debug.Reset();
|
||||
|
||||
// Build sampling pattern aligned to desired velocity.
|
||||
float[] pat = new float[(DT_MAX_PATTERN_DIVS * DT_MAX_PATTERN_RINGS + 1) * 2];
|
||||
using var pat = RcRentedArray.Rent<float>((DT_MAX_PATTERN_DIVS * DT_MAX_PATTERN_RINGS + 1) * 2);
|
||||
int npat = 0;
|
||||
|
||||
int ndivs = m_params.adaptiveDivs;
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace DotRecast.Detour.Dynamic
|
|||
private readonly BlockingCollection<IDtDaynmicTileJob> updateQueue = new BlockingCollection<IDtDaynmicTileJob>();
|
||||
private readonly RcAtomicLong currentColliderId = new RcAtomicLong(0);
|
||||
private DtNavMesh _navMesh;
|
||||
private bool dirty = true;
|
||||
private bool _dirty = true;
|
||||
|
||||
public DtDynamicNavMesh(DtVoxelFile voxelFile)
|
||||
{
|
||||
|
@ -105,29 +105,6 @@ namespace DotRecast.Detour.Dynamic
|
|||
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()
|
||||
{
|
||||
|
@ -159,27 +136,49 @@ namespace DotRecast.Detour.Dynamic
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform full build concurrently using the given {@link ExecutorService}
|
||||
*/
|
||||
public Task<bool> Build(TaskFactory executor)
|
||||
// Perform full build of the navmesh
|
||||
public void Build()
|
||||
{
|
||||
ProcessQueue();
|
||||
Rebuild(_tiles.Values);
|
||||
}
|
||||
|
||||
// Perform full build concurrently using the given {@link ExecutorService}
|
||||
public bool Build(TaskFactory executor)
|
||||
{
|
||||
ProcessQueue();
|
||||
return Rebuild(_tiles.Values, executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform incremental update concurrently using the given {@link ExecutorService}
|
||||
*/
|
||||
public Task<bool> Update(TaskFactory executor)
|
||||
|
||||
// Perform incremental update of the navmesh
|
||||
public bool Update()
|
||||
{
|
||||
return Rebuild(ProcessQueue());
|
||||
}
|
||||
|
||||
// Perform incremental update concurrently using the given {@link ExecutorService}
|
||||
public bool Update(TaskFactory 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();
|
||||
return Task.WhenAll(tasks).ContinueWith(k => UpdateNavMesh());
|
||||
foreach (var tile in tiles)
|
||||
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)
|
||||
|
@ -218,19 +217,19 @@ namespace DotRecast.Detour.Dynamic
|
|||
{
|
||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||
option.walkableHeight = config.walkableHeight;
|
||||
dirty = dirty | tile.Build(builder, config, _context);
|
||||
_dirty = _dirty | tile.Build(builder, config, _context);
|
||||
}
|
||||
|
||||
private bool UpdateNavMesh()
|
||||
{
|
||||
if (dirty)
|
||||
if (_dirty)
|
||||
{
|
||||
DtNavMesh navMesh = new DtNavMesh(navMeshParams, MAX_VERTS_PER_POLY);
|
||||
foreach (var t in _tiles.Values)
|
||||
t.AddTo(navMesh);
|
||||
|
||||
this._navMesh = navMesh;
|
||||
dirty = false;
|
||||
_navMesh = navMesh;
|
||||
_dirty = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,8 +132,8 @@ namespace DotRecast.Detour.Dynamic
|
|||
private DtNavMeshCreateParams NavMeshCreateParams(int tilex, int tileZ, float cellSize, float cellHeight,
|
||||
DtDynamicNavMeshConfig config, RcBuilderResult rcResult)
|
||||
{
|
||||
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
||||
RcPolyMesh m_pmesh = rcResult.Mesh;
|
||||
RcPolyMeshDetail m_dmesh = rcResult.MeshDetail;
|
||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||
{
|
||||
|
|
|
@ -109,13 +109,13 @@ namespace DotRecast.Detour.Dynamic.Io
|
|||
};
|
||||
foreach (RcBuilderResult r in results)
|
||||
{
|
||||
f.tiles.Add(new DtVoxelTile(r.tileX, r.tileZ, r.GetSolidHeightfield()));
|
||||
f.bounds[0] = Math.Min(f.bounds[0], r.GetSolidHeightfield().bmin.X);
|
||||
f.bounds[1] = Math.Min(f.bounds[1], r.GetSolidHeightfield().bmin.Y);
|
||||
f.bounds[2] = Math.Min(f.bounds[2], r.GetSolidHeightfield().bmin.Z);
|
||||
f.bounds[3] = Math.Max(f.bounds[3], r.GetSolidHeightfield().bmax.X);
|
||||
f.bounds[4] = Math.Max(f.bounds[4], r.GetSolidHeightfield().bmax.Y);
|
||||
f.bounds[5] = Math.Max(f.bounds[5], r.GetSolidHeightfield().bmax.Z);
|
||||
f.tiles.Add(new DtVoxelTile(r.TileX, r.TileZ, r.SolidHeightfiled));
|
||||
f.bounds[0] = Math.Min(f.bounds[0], r.SolidHeightfiled.bmin.X);
|
||||
f.bounds[1] = Math.Min(f.bounds[1], r.SolidHeightfiled.bmin.Y);
|
||||
f.bounds[2] = Math.Min(f.bounds[2], r.SolidHeightfiled.bmin.Z);
|
||||
f.bounds[3] = Math.Max(f.bounds[3], r.SolidHeightfiled.bmax.X);
|
||||
f.bounds[4] = Math.Max(f.bounds[4], r.SolidHeightfiled.bmax.Y);
|
||||
f.bounds[5] = Math.Max(f.bounds[5], r.SolidHeightfiled.bmax.Z);
|
||||
}
|
||||
|
||||
return f;
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
|||
public JumpLinkBuilder(IList<RcBuilderResult> results)
|
||||
{
|
||||
this.results = results;
|
||||
edges = results.Select(r => edgeExtractor.ExtractEdges(r.GetMesh())).ToList();
|
||||
edges = results.Select(r => edgeExtractor.ExtractEdges(r.Mesh)).ToList();
|
||||
}
|
||||
|
||||
public List<JumpLink> Build(JumpLinkBuilderConfig acfg, JumpLinkType type)
|
||||
|
@ -43,7 +43,7 @@ namespace DotRecast.Detour.Extras.Jumplink
|
|||
{
|
||||
EdgeSampler es = edgeSamplerFactory.Get(acfg, type, edge);
|
||||
groundSampler.Sample(acfg, result, es);
|
||||
trajectorySampler.Sample(acfg, result.GetSolidHeightfield(), es);
|
||||
trajectorySampler.Sample(acfg, result.SolidHeightfiled, es);
|
||||
JumpSegment[] jumpSegments = jumpSegmentBuilder.Build(acfg, es);
|
||||
return BuildJumpLinks(acfg, es, jumpSegments);
|
||||
}
|
||||
|
|
|
@ -16,25 +16,25 @@ namespace DotRecast.Detour.Extras.Jumplink
|
|||
private DtNavMeshQuery CreateNavMesh(RcBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
|
||||
{
|
||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||
option.verts = r.GetMesh().verts;
|
||||
option.vertCount = r.GetMesh().nverts;
|
||||
option.polys = r.GetMesh().polys;
|
||||
option.polyAreas = r.GetMesh().areas;
|
||||
option.polyFlags = r.GetMesh().flags;
|
||||
option.polyCount = r.GetMesh().npolys;
|
||||
option.nvp = r.GetMesh().nvp;
|
||||
option.detailMeshes = r.GetMeshDetail().meshes;
|
||||
option.detailVerts = r.GetMeshDetail().verts;
|
||||
option.detailVertsCount = r.GetMeshDetail().nverts;
|
||||
option.detailTris = r.GetMeshDetail().tris;
|
||||
option.detailTriCount = r.GetMeshDetail().ntris;
|
||||
option.verts = r.Mesh.verts;
|
||||
option.vertCount = r.Mesh.nverts;
|
||||
option.polys = r.Mesh.polys;
|
||||
option.polyAreas = r.Mesh.areas;
|
||||
option.polyFlags = r.Mesh.flags;
|
||||
option.polyCount = r.Mesh.npolys;
|
||||
option.nvp = r.Mesh.nvp;
|
||||
option.detailMeshes = r.MeshDetail.meshes;
|
||||
option.detailVerts = r.MeshDetail.verts;
|
||||
option.detailVertsCount = r.MeshDetail.nverts;
|
||||
option.detailTris = r.MeshDetail.tris;
|
||||
option.detailTriCount = r.MeshDetail.ntris;
|
||||
option.walkableRadius = agentRadius;
|
||||
option.walkableHeight = agentHeight;
|
||||
option.walkableClimb = agentClimb;
|
||||
option.bmin = r.GetMesh().bmin;
|
||||
option.bmax = r.GetMesh().bmax;
|
||||
option.cs = r.GetMesh().cs;
|
||||
option.ch = r.GetMesh().ch;
|
||||
option.bmin = r.Mesh.bmin;
|
||||
option.bmax = r.Mesh.bmax;
|
||||
option.cs = r.Mesh.cs;
|
||||
option.ch = r.Mesh.ch;
|
||||
option.buildBvTree = true;
|
||||
return new DtNavMeshQuery(new DtNavMesh(DtNavMeshBuilder.CreateNavMeshData(option), option.nvp, 0));
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ freely, subject to the following restrictions:
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DotRecast.Core;
|
||||
using DotRecast.Core.Buffers;
|
||||
using DotRecast.Core.Numerics;
|
||||
|
||||
namespace DotRecast.Detour
|
||||
|
@ -358,8 +359,8 @@ namespace DotRecast.Detour
|
|||
var tbmax = tile.data.header.bmax;
|
||||
float qfac = tile.data.header.bvQuantFactor;
|
||||
// Calculate quantized box
|
||||
int[] bmin = new int[3];
|
||||
int[] bmax = new int[3];
|
||||
Span<int> bmin = stackalloc int[3];
|
||||
Span<int> bmax = stackalloc int[3];
|
||||
// dtClamp query box to world box.
|
||||
float minx = Math.Clamp(qmin.X, tbmin.X, tbmax.X) - tbmin.X;
|
||||
float miny = Math.Clamp(qmin.Y, tbmin.Y, tbmax.Y) - tbmin.Y;
|
||||
|
@ -1246,14 +1247,14 @@ namespace DotRecast.Detour
|
|||
|
||||
int ip = poly.index;
|
||||
|
||||
float[] verts = new float[m_maxVertPerPoly * 3];
|
||||
using var verts = RcRentedArray.Rent<float>(m_maxVertPerPoly * 3);
|
||||
int nv = poly.vertCount;
|
||||
for (int i = 0; i < nv; ++i)
|
||||
{
|
||||
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts, i * 3, 3);
|
||||
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts.AsArray(), i * 3, 3);
|
||||
}
|
||||
|
||||
if (!DtUtils.PointInPolygon(pos, verts, nv))
|
||||
if (!DtUtils.PointInPolygon(pos, verts.AsArray(), nv))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ freely, subject to the following restrictions:
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DotRecast.Core;
|
||||
using DotRecast.Core.Buffers;
|
||||
using DotRecast.Core.Collections;
|
||||
using DotRecast.Core.Numerics;
|
||||
|
||||
|
@ -41,9 +42,9 @@ namespace DotRecast.Detour
|
|||
public DtNavMeshQuery(DtNavMesh nav)
|
||||
{
|
||||
m_nav = nav;
|
||||
m_tinyNodePool = new DtNodePool();
|
||||
m_nodePool = new DtNodePool();
|
||||
m_openList = new DtNodeQueue();
|
||||
m_tinyNodePool = new DtNodePool();
|
||||
}
|
||||
|
||||
/// Returns random location on navmesh.
|
||||
|
@ -137,18 +138,18 @@ namespace DotRecast.Detour
|
|||
}
|
||||
|
||||
// Randomly pick point on polygon.
|
||||
float[] verts = new float[3 * m_nav.GetMaxVertsPerPoly()];
|
||||
float[] areas = new float[m_nav.GetMaxVertsPerPoly()];
|
||||
RcArrays.Copy(tile.data.verts, poly.verts[0] * 3, verts, 0, 3);
|
||||
using var verts = RcRentedArray.Rent<float>(3 * m_nav.GetMaxVertsPerPoly());
|
||||
using var areas = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly());
|
||||
RcArrays.Copy(tile.data.verts, poly.verts[0] * 3, verts.AsArray(), 0, 3);
|
||||
for (int j = 1; j < poly.vertCount; ++j)
|
||||
{
|
||||
RcArrays.Copy(tile.data.verts, poly.verts[j] * 3, verts, j * 3, 3);
|
||||
RcArrays.Copy(tile.data.verts, poly.verts[j] * 3, verts.AsArray(), j * 3, 3);
|
||||
}
|
||||
|
||||
float s = frand.Next();
|
||||
float t = frand.Next();
|
||||
|
||||
var pt = DtUtils.RandomPointInConvexPoly(verts, poly.vertCount, areas, s, t);
|
||||
var pt = DtUtils.RandomPointInConvexPoly(verts.AsArray(), poly.vertCount, areas.AsArray(), s, t);
|
||||
ClosestPointOnPoly(polyRef, pt, out var closest, out var _);
|
||||
|
||||
randomRef = polyRef;
|
||||
|
@ -386,8 +387,8 @@ namespace DotRecast.Detour
|
|||
float s = frand.Next();
|
||||
float t = frand.Next();
|
||||
|
||||
float[] areas = new float[randomPolyVerts.Length / 3];
|
||||
RcVec3f pt = DtUtils.RandomPointInConvexPoly(randomPolyVerts, randomPolyVerts.Length / 3, areas, s, t);
|
||||
using var areas = RcRentedArray.Rent<float>(randomPolyVerts.Length / 3);
|
||||
RcVec3f pt = DtUtils.RandomPointInConvexPoly(randomPolyVerts, randomPolyVerts.Length / 3, areas.AsArray(), s, t);
|
||||
ClosestPointOnPoly(randomPolyRef, pt, out var closest, out var _);
|
||||
|
||||
randomRef = randomPolyRef;
|
||||
|
@ -457,16 +458,16 @@ namespace DotRecast.Detour
|
|||
}
|
||||
|
||||
// Collect vertices.
|
||||
float[] verts = new float[m_nav.GetMaxVertsPerPoly() * 3];
|
||||
float[] edged = new float[m_nav.GetMaxVertsPerPoly()];
|
||||
float[] edget = new float[m_nav.GetMaxVertsPerPoly()];
|
||||
using var verts = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly() * 3);
|
||||
using var edged = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly());
|
||||
using var edget = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly());
|
||||
int nv = poly.vertCount;
|
||||
for (int i = 0; i < nv; ++i)
|
||||
{
|
||||
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts, i * 3, 3);
|
||||
RcArrays.Copy(tile.data.verts, poly.verts[i] * 3, verts.AsArray(), i * 3, 3);
|
||||
}
|
||||
|
||||
if (DtUtils.DistancePtPolyEdgesSqr(pos, verts, nv, edged, edget))
|
||||
if (DtUtils.DistancePtPolyEdgesSqr(pos, verts.AsArray(), nv, edged.AsArray(), edget.AsArray()))
|
||||
{
|
||||
closest = pos;
|
||||
}
|
||||
|
@ -486,7 +487,7 @@ namespace DotRecast.Detour
|
|||
|
||||
int va = imin * 3;
|
||||
int vb = ((imin + 1) % nv) * 3;
|
||||
closest = RcVecUtils.Lerp(verts, va, vb, edget[imin]);
|
||||
closest = RcVecUtils.Lerp(verts.AsArray(), va, vb, edget[imin]);
|
||||
}
|
||||
|
||||
return DtStatus.DT_SUCCESS;
|
||||
|
@ -583,8 +584,8 @@ namespace DotRecast.Detour
|
|||
var tbmax = tile.data.header.bmax;
|
||||
float qfac = tile.data.header.bvQuantFactor;
|
||||
// Calculate quantized box
|
||||
int[] bmin = new int[3];
|
||||
int[] bmax = new int[3];
|
||||
Span<int> bmin = stackalloc int[3];
|
||||
Span<int> bmax = stackalloc int[3];
|
||||
// dtClamp query box to world box.
|
||||
float minx = Math.Clamp(qmin.X, tbmin.X, tbmax.X) - tbmin.X;
|
||||
float miny = Math.Clamp(qmin.Y, tbmin.Y, tbmax.Y) - tbmin.Y;
|
||||
|
@ -1793,7 +1794,9 @@ namespace DotRecast.Detour
|
|||
resultPos = RcVec3f.Zero;
|
||||
|
||||
if (null != visited)
|
||||
{
|
||||
visited.Clear();
|
||||
}
|
||||
|
||||
// Validate input
|
||||
if (!m_nav.IsValidPolyRef(startRef) || !startPos.IsFinite()
|
||||
|
@ -1822,7 +1825,10 @@ namespace DotRecast.Detour
|
|||
var searchPos = RcVec3f.Lerp(startPos, endPos, 0.5f);
|
||||
float searchRadSqr = RcMath.Sqr(RcVec3f.Distance(startPos, endPos) / 2.0f + 0.001f);
|
||||
|
||||
float[] verts = new float[m_nav.GetMaxVertsPerPoly() * 3];
|
||||
using var verts = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly() * 3);
|
||||
|
||||
const int MAX_NEIS = 8;
|
||||
Span<long> neis = stackalloc long[MAX_NEIS];
|
||||
|
||||
while (0 < stack.Count)
|
||||
{
|
||||
|
@ -1839,11 +1845,11 @@ namespace DotRecast.Detour
|
|||
int nverts = curPoly.vertCount;
|
||||
for (int i = 0; i < nverts; ++i)
|
||||
{
|
||||
RcArrays.Copy(curTile.data.verts, curPoly.verts[i] * 3, verts, i * 3, 3);
|
||||
RcArrays.Copy(curTile.data.verts, curPoly.verts[i] * 3, verts.AsArray(), i * 3, 3);
|
||||
}
|
||||
|
||||
// If target is inside the poly, stop search.
|
||||
if (DtUtils.PointInPolygon(endPos, verts, nverts))
|
||||
if (DtUtils.PointInPolygon(endPos, verts.AsArray(), nverts))
|
||||
{
|
||||
bestNode = curNode;
|
||||
bestPos = endPos;
|
||||
|
@ -1854,9 +1860,7 @@ namespace DotRecast.Detour
|
|||
for (int i = 0, j = curPoly.vertCount - 1; i < curPoly.vertCount; j = i++)
|
||||
{
|
||||
// Find links to neighbours.
|
||||
int MAX_NEIS = 8;
|
||||
int nneis = 0;
|
||||
long[] neis = new long[MAX_NEIS];
|
||||
|
||||
if ((curPoly.neis[j] & DtNavMesh.DT_EXT_LINK) != 0)
|
||||
{
|
||||
|
@ -1896,11 +1900,11 @@ namespace DotRecast.Detour
|
|||
// Wall edge, calc distance.
|
||||
int vj = j * 3;
|
||||
int vi = i * 3;
|
||||
var distSqr = DtUtils.DistancePtSegSqr2D(endPos, verts, vj, vi, out var tseg);
|
||||
var distSqr = DtUtils.DistancePtSegSqr2D(endPos, verts.AsArray(), vj, vi, out var tseg);
|
||||
if (distSqr < bestDist)
|
||||
{
|
||||
// Update nearest distance.
|
||||
bestPos = RcVecUtils.Lerp(verts, vj, vi, tseg);
|
||||
bestPos = RcVecUtils.Lerp(verts.AsArray(), vj, vi, tseg);
|
||||
bestDist = distSqr;
|
||||
bestNode = curNode;
|
||||
}
|
||||
|
@ -1920,7 +1924,7 @@ namespace DotRecast.Detour
|
|||
// TODO: Maybe should use GetPortalPoints(), but this one is way faster.
|
||||
int vj = j * 3;
|
||||
int vi = i * 3;
|
||||
var distSqr = DtUtils.DistancePtSegSqr2D(searchPos, verts, vj, vi, out var _);
|
||||
var distSqr = DtUtils.DistancePtSegSqr2D(searchPos, verts.AsArray(), vj, vi, out var _);
|
||||
if (distSqr > searchRadSqr)
|
||||
{
|
||||
continue;
|
||||
|
@ -2244,7 +2248,7 @@ namespace DotRecast.Detour
|
|||
hit.path.Clear();
|
||||
hit.pathCost = 0;
|
||||
|
||||
RcVec3f[] verts = new RcVec3f[m_nav.GetMaxVertsPerPoly() + 1];
|
||||
using var verts = RcRentedArray.Rent<RcVec3f>(m_nav.GetMaxVertsPerPoly() + 1);
|
||||
|
||||
RcVec3f curPos = RcVec3f.Zero;
|
||||
RcVec3f lastPos = RcVec3f.Zero;
|
||||
|
@ -2278,7 +2282,7 @@ namespace DotRecast.Detour
|
|||
nv++;
|
||||
}
|
||||
|
||||
bool intersects = DtUtils.IntersectSegmentPoly2D(startPos, endPos, verts, nv, out var tmin, out var tmax, out var segMin, out var segMax);
|
||||
bool intersects = DtUtils.IntersectSegmentPoly2D(startPos, endPos, verts.AsArray(), nv, out var tmin, out var tmax, out var segMin, out var segMax);
|
||||
if (!intersects)
|
||||
{
|
||||
// Could not hit the polygon, keep the old t and report hit.
|
||||
|
@ -2873,8 +2877,8 @@ namespace DotRecast.Detour
|
|||
|
||||
float radiusSqr = RcMath.Sqr(radius);
|
||||
|
||||
float[] pa = new float[m_nav.GetMaxVertsPerPoly() * 3];
|
||||
float[] pb = new float[m_nav.GetMaxVertsPerPoly() * 3];
|
||||
using var pa = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly() * 3);
|
||||
using var pb = RcRentedArray.Rent<float>(m_nav.GetMaxVertsPerPoly() * 3);
|
||||
|
||||
while (0 < stack.Count)
|
||||
{
|
||||
|
@ -2945,7 +2949,7 @@ namespace DotRecast.Detour
|
|||
int npa = neighbourPoly.vertCount;
|
||||
for (int k = 0; k < npa; ++k)
|
||||
{
|
||||
RcArrays.Copy(neighbourTile.data.verts, neighbourPoly.verts[k] * 3, pa, k * 3, 3);
|
||||
RcArrays.Copy(neighbourTile.data.verts, neighbourPoly.verts[k] * 3, pa.AsArray(), k * 3, 3);
|
||||
}
|
||||
|
||||
bool overlap = false;
|
||||
|
@ -2976,10 +2980,10 @@ namespace DotRecast.Detour
|
|||
int npb = pastPoly.vertCount;
|
||||
for (int k = 0; k < npb; ++k)
|
||||
{
|
||||
RcArrays.Copy(pastTile.data.verts, pastPoly.verts[k] * 3, pb, k * 3, 3);
|
||||
RcArrays.Copy(pastTile.data.verts, pastPoly.verts[k] * 3, pb.AsArray(), k * 3, 3);
|
||||
}
|
||||
|
||||
if (DtUtils.OverlapPolyPoly2D(pa, npa, pb, npb))
|
||||
if (DtUtils.OverlapPolyPoly2D(pa.AsArray(), npa, pb.AsArray(), npb))
|
||||
{
|
||||
overlap = true;
|
||||
break;
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace DotRecast.Detour
|
|||
/// @param[in] bmax Maximum bounds of box B. [(x, y, z)]
|
||||
/// @return True if the two AABB's overlap.
|
||||
/// @see dtOverlapBounds
|
||||
public static bool OverlapQuantBounds(int[] amin, int[] amax, int[] bmin, int[] bmax)
|
||||
public static bool OverlapQuantBounds(Span<int> amin, Span<int> amax, Span<int> bmin, Span<int> bmax)
|
||||
{
|
||||
bool overlap = true;
|
||||
overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0"/>
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0"/>
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6"/>
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
||||
<PackageReference Include="Silk.NET" Version="2.20.0" />
|
||||
<PackageReference Include="Silk.NET.OpenGL.Extensions.ImGui" Version="2.20.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -123,80 +123,80 @@ public class NavMeshRenderer
|
|||
|
||||
foreach (RcBuilderResult rcBuilderResult in rcBuilderResults)
|
||||
{
|
||||
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT)
|
||||
if (rcBuilderResult.CompactHeightfield != null && drawMode == DrawMode.DRAWMODE_COMPACT)
|
||||
{
|
||||
_debugDraw.DebugDrawCompactHeightfieldSolid(rcBuilderResult.GetCompactHeightfield());
|
||||
_debugDraw.DebugDrawCompactHeightfieldSolid(rcBuilderResult.CompactHeightfield);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT_DISTANCE)
|
||||
if (rcBuilderResult.CompactHeightfield != null && drawMode == DrawMode.DRAWMODE_COMPACT_DISTANCE)
|
||||
{
|
||||
_debugDraw.DebugDrawCompactHeightfieldDistance(rcBuilderResult.GetCompactHeightfield());
|
||||
_debugDraw.DebugDrawCompactHeightfieldDistance(rcBuilderResult.CompactHeightfield);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_COMPACT_REGIONS)
|
||||
if (rcBuilderResult.CompactHeightfield != null && drawMode == DrawMode.DRAWMODE_COMPACT_REGIONS)
|
||||
{
|
||||
_debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.GetCompactHeightfield());
|
||||
_debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.CompactHeightfield);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetSolidHeightfield() != null && drawMode == DrawMode.DRAWMODE_VOXELS)
|
||||
if (rcBuilderResult.SolidHeightfiled != null && drawMode == DrawMode.DRAWMODE_VOXELS)
|
||||
{
|
||||
_debugDraw.Fog(true);
|
||||
_debugDraw.DebugDrawHeightfieldSolid(rcBuilderResult.GetSolidHeightfield());
|
||||
_debugDraw.DebugDrawHeightfieldSolid(rcBuilderResult.SolidHeightfiled);
|
||||
_debugDraw.Fog(false);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetSolidHeightfield() != null && drawMode == DrawMode.DRAWMODE_VOXELS_WALKABLE)
|
||||
if (rcBuilderResult.SolidHeightfiled != null && drawMode == DrawMode.DRAWMODE_VOXELS_WALKABLE)
|
||||
{
|
||||
_debugDraw.Fog(true);
|
||||
_debugDraw.DebugDrawHeightfieldWalkable(rcBuilderResult.GetSolidHeightfield());
|
||||
_debugDraw.DebugDrawHeightfieldWalkable(rcBuilderResult.SolidHeightfiled);
|
||||
_debugDraw.Fog(false);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_RAW_CONTOURS)
|
||||
if (rcBuilderResult.ContourSet != null && drawMode == DrawMode.DRAWMODE_RAW_CONTOURS)
|
||||
{
|
||||
_debugDraw.DepthMask(false);
|
||||
_debugDraw.DebugDrawRawContours(rcBuilderResult.GetContourSet(), 1f);
|
||||
_debugDraw.DebugDrawRawContours(rcBuilderResult.ContourSet, 1f);
|
||||
_debugDraw.DepthMask(true);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_BOTH_CONTOURS)
|
||||
if (rcBuilderResult.ContourSet != null && drawMode == DrawMode.DRAWMODE_BOTH_CONTOURS)
|
||||
{
|
||||
_debugDraw.DepthMask(false);
|
||||
_debugDraw.DebugDrawRawContours(rcBuilderResult.GetContourSet(), 0.5f);
|
||||
_debugDraw.DebugDrawContours(rcBuilderResult.GetContourSet());
|
||||
_debugDraw.DebugDrawRawContours(rcBuilderResult.ContourSet, 0.5f);
|
||||
_debugDraw.DebugDrawContours(rcBuilderResult.ContourSet);
|
||||
_debugDraw.DepthMask(true);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetContourSet() != null && drawMode == DrawMode.DRAWMODE_CONTOURS)
|
||||
if (rcBuilderResult.ContourSet != null && drawMode == DrawMode.DRAWMODE_CONTOURS)
|
||||
{
|
||||
_debugDraw.DepthMask(false);
|
||||
_debugDraw.DebugDrawContours(rcBuilderResult.GetContourSet());
|
||||
_debugDraw.DebugDrawContours(rcBuilderResult.ContourSet);
|
||||
_debugDraw.DepthMask(true);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetCompactHeightfield() != null && drawMode == DrawMode.DRAWMODE_REGION_CONNECTIONS)
|
||||
if (rcBuilderResult.CompactHeightfield != null && drawMode == DrawMode.DRAWMODE_REGION_CONNECTIONS)
|
||||
{
|
||||
_debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.GetCompactHeightfield());
|
||||
_debugDraw.DebugDrawCompactHeightfieldRegions(rcBuilderResult.CompactHeightfield);
|
||||
_debugDraw.DepthMask(false);
|
||||
if (rcBuilderResult.GetContourSet() != null)
|
||||
if (rcBuilderResult.ContourSet != null)
|
||||
{
|
||||
_debugDraw.DebugDrawRegionConnections(rcBuilderResult.GetContourSet());
|
||||
_debugDraw.DebugDrawRegionConnections(rcBuilderResult.ContourSet);
|
||||
}
|
||||
|
||||
_debugDraw.DepthMask(true);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetMesh() != null && drawMode == DrawMode.DRAWMODE_POLYMESH)
|
||||
if (rcBuilderResult.Mesh != null && drawMode == DrawMode.DRAWMODE_POLYMESH)
|
||||
{
|
||||
_debugDraw.DepthMask(false);
|
||||
_debugDraw.DebugDrawPolyMesh(rcBuilderResult.GetMesh());
|
||||
_debugDraw.DebugDrawPolyMesh(rcBuilderResult.Mesh);
|
||||
_debugDraw.DepthMask(true);
|
||||
}
|
||||
|
||||
if (rcBuilderResult.GetMeshDetail() != null && drawMode == DrawMode.DRAWMODE_POLYMESH_DETAIL)
|
||||
if (rcBuilderResult.MeshDetail != null && drawMode == DrawMode.DRAWMODE_POLYMESH_DETAIL)
|
||||
{
|
||||
_debugDraw.DepthMask(false);
|
||||
_debugDraw.DebugDrawPolyMeshDetail(rcBuilderResult.GetMeshDetail());
|
||||
_debugDraw.DebugDrawPolyMeshDetail(rcBuilderResult.MeshDetail);
|
||||
_debugDraw.DepthMask(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -537,6 +537,7 @@ public class RecastDemo : IRecastDemoChannel
|
|||
bool hasBound = false;
|
||||
RcVec3f bminN = RcVec3f.Zero;
|
||||
RcVec3f bmaxN = RcVec3f.Zero;
|
||||
|
||||
if (_sample.GetInputGeom() != null)
|
||||
{
|
||||
bminN = _sample.GetInputGeom().GetMeshBoundsMin();
|
||||
|
@ -552,7 +553,7 @@ public class RecastDemo : IRecastDemoChannel
|
|||
{
|
||||
foreach (RcBuilderResult result in _sample.GetRecastResults())
|
||||
{
|
||||
if (result.GetSolidHeightfield() != null)
|
||||
if (result.CompactHeightfield != null)
|
||||
{
|
||||
if (!hasBound)
|
||||
{
|
||||
|
@ -561,15 +562,15 @@ public class RecastDemo : IRecastDemoChannel
|
|||
}
|
||||
|
||||
bminN = new RcVec3f(
|
||||
Math.Min(bminN.X, result.GetSolidHeightfield().bmin.X),
|
||||
Math.Min(bminN.Y, result.GetSolidHeightfield().bmin.Y),
|
||||
Math.Min(bminN.Z, result.GetSolidHeightfield().bmin.Z)
|
||||
Math.Min(bminN.X, result.CompactHeightfield.bmin.X),
|
||||
Math.Min(bminN.Y, result.CompactHeightfield.bmin.Y),
|
||||
Math.Min(bminN.Z, result.CompactHeightfield.bmin.Z)
|
||||
);
|
||||
|
||||
bmaxN = new RcVec3f(
|
||||
Math.Max(bmaxN.X, result.GetSolidHeightfield().bmax.X),
|
||||
Math.Max(bmaxN.Y, result.GetSolidHeightfield().bmax.Y),
|
||||
Math.Max(bmaxN.Z, result.GetSolidHeightfield().bmax.Z)
|
||||
Math.Max(bmaxN.X, result.CompactHeightfield.bmax.X),
|
||||
Math.Max(bmaxN.Y, result.CompactHeightfield.bmax.Y),
|
||||
Math.Max(bmaxN.Z, result.CompactHeightfield.bmax.Z)
|
||||
);
|
||||
|
||||
hasBound = true;
|
||||
|
@ -577,12 +578,15 @@ public class RecastDemo : IRecastDemoChannel
|
|||
}
|
||||
}
|
||||
|
||||
// Reset camera and fog to match the mesh bounds.
|
||||
if (hasBound)
|
||||
{
|
||||
RcVec3f bmin = bminN;
|
||||
RcVec3f bmax = bmaxN;
|
||||
|
||||
camr = (float)(Math.Sqrt(RcMath.Sqr(bmax.X - bmin.X) + RcMath.Sqr(bmax.Y - bmin.Y) + RcMath.Sqr(bmax.Z - bmin.Z)) / 2);
|
||||
camr = (float)(Math.Sqrt(RcMath.Sqr(bmax.X - bmin.X) +
|
||||
RcMath.Sqr(bmax.Y - bmin.Y) +
|
||||
RcMath.Sqr(bmax.Z - bmin.Z)) / 2);
|
||||
cameraPos.X = (bmax.X + bmin.X) / 2 + camr;
|
||||
cameraPos.Y = (bmax.Y + bmin.Y) / 2 + camr;
|
||||
cameraPos.Z = (bmax.Z + bmin.Z) / 2 + camr;
|
||||
|
@ -688,14 +692,15 @@ public class RecastDemo : IRecastDemoChannel
|
|||
|
||||
NavMeshBuildResult buildResult;
|
||||
|
||||
var geom = _sample.GetInputGeom();
|
||||
var settings = _sample.GetSettings();
|
||||
if (settings.tiled)
|
||||
{
|
||||
buildResult = tileNavMeshBuilder.Build(_sample.GetInputGeom(), settings);
|
||||
buildResult = tileNavMeshBuilder.Build(geom, settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
buildResult = soloNavMeshBuilder.Build(_sample.GetInputGeom(), settings);
|
||||
buildResult = soloNavMeshBuilder.Build(geom, settings);
|
||||
}
|
||||
|
||||
if (!buildResult.Success)
|
||||
|
@ -713,7 +718,7 @@ public class RecastDemo : IRecastDemoChannel
|
|||
Logger.Information($"build times");
|
||||
Logger.Information($"-----------------------------------------");
|
||||
var telemetries = buildResult.RecastBuilderResults
|
||||
.Select(x => x.GetTelemetry())
|
||||
.Select(x => x.Context)
|
||||
.SelectMany(x => x.ToList())
|
||||
.GroupBy(x => x.Key)
|
||||
.ToImmutableSortedDictionary(x => x.Key, x => x.Sum(y => y.Millis));
|
||||
|
|
|
@ -91,7 +91,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
|||
var bridgeGeom = DemoInputGeomProvider.LoadFile("bridge.obj");
|
||||
var houseGeom = DemoInputGeomProvider.LoadFile("house.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;
|
||||
}
|
||||
|
||||
|
@ -406,7 +406,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
|||
long t = RcFrequency.Ticks;
|
||||
try
|
||||
{
|
||||
bool updated = _tool.UpdateDynaMesh(executor);
|
||||
bool updated = _tool.Update(executor);
|
||||
if (updated)
|
||||
{
|
||||
buildTime = (RcFrequency.Ticks - t) / TimeSpan.TicksPerMillisecond;
|
||||
|
@ -450,7 +450,7 @@ public class DynamicUpdateSampleTool : ISampleTool
|
|||
long t = RcFrequency.Ticks;
|
||||
try
|
||||
{
|
||||
var _ = dynaMesh.Build(executor).Result;
|
||||
var _ = dynaMesh.Build(executor);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@ freely, subject to the following restrictions:
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
using System.Linq;
|
||||
using DotRecast.Core.Numerics;
|
||||
using DotRecast.Detour.Extras.Jumplink;
|
||||
using DotRecast.Recast.Demo.Draw;
|
||||
|
@ -96,13 +97,25 @@ public class JumpLinkBuilderSampleTool : ISampleTool
|
|||
|
||||
if (build || _cfg.buildOffMeshConnections)
|
||||
{
|
||||
if (0 < _sample.GetRecastResults().Count)
|
||||
do
|
||||
{
|
||||
if (0 >= _sample.GetRecastResults().Count)
|
||||
{
|
||||
Logger.Error("build navmesh");
|
||||
break;
|
||||
}
|
||||
|
||||
if (_sample.GetRecastResults().Any(x => null == x.SolidHeightfiled))
|
||||
{
|
||||
Logger.Error("Tick 'Keep Itermediate Results' option");
|
||||
break;
|
||||
}
|
||||
|
||||
var geom = _sample.GetInputGeom();
|
||||
var settings = _sample.GetSettings();
|
||||
|
||||
_tool.Build(geom, settings, _sample.GetRecastResults(), _cfg);
|
||||
}
|
||||
} while (false);
|
||||
}
|
||||
|
||||
ImGui.NewLine();
|
||||
|
|
|
@ -166,6 +166,10 @@ public class RcSettingsView : IRcView
|
|||
ImGui.SliderFloat("Max Sample Error", ref settings.detailSampleMaxError, 0f, 16f, "%.1f");
|
||||
ImGui.NewLine();
|
||||
|
||||
ImGui.Checkbox("Keep Itermediate Results", ref settings.keepInterResults);
|
||||
ImGui.Checkbox("Build All Tiles", ref settings.buildAll);
|
||||
ImGui.NewLine();
|
||||
|
||||
ImGui.Text("Tiling");
|
||||
ImGui.Separator();
|
||||
ImGui.Checkbox("Enable", ref settings.tiled);
|
||||
|
@ -228,6 +232,12 @@ public class RcSettingsView : IRcView
|
|||
DrawMode.Values.ForEach(dm => { ImGui.RadioButton(dm.Text, ref drawMode, dm.Idx); });
|
||||
ImGui.NewLine();
|
||||
|
||||
ImGui.Separator();
|
||||
ImGui.Text("Tick 'Keep Itermediate Results'");
|
||||
ImGui.Text("rebuild some tiles to see");
|
||||
ImGui.Text("more debug mode options.");
|
||||
ImGui.NewLine();
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
float cellHeight, float agentHeight, float agentRadius, float agentMaxClimb,
|
||||
RcBuilderResult rcResult)
|
||||
{
|
||||
RcPolyMesh pmesh = rcResult.GetMesh();
|
||||
RcPolyMeshDetail dmesh = rcResult.GetMeshDetail();
|
||||
RcPolyMesh pmesh = rcResult.Mesh;
|
||||
RcPolyMeshDetail dmesh = rcResult.MeshDetail;
|
||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||
for (int i = 0; i < pmesh.npolys; ++i)
|
||||
{
|
||||
|
|
|
@ -34,7 +34,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
settings.edgeMaxLen, settings.edgeMaxError,
|
||||
settings.vertsPerPoly,
|
||||
settings.detailSampleDist, settings.detailSampleMaxError,
|
||||
settings.filterLowHangingObstacles, settings.filterLedgeSpans, settings.filterWalkableLowHeightSpans);
|
||||
settings.filterLowHangingObstacles, settings.filterLedgeSpans, settings.filterWalkableLowHeightSpans,
|
||||
settings.keepInterResults);
|
||||
}
|
||||
|
||||
public NavMeshBuildResult Build(DemoInputGeomProvider geom,
|
||||
|
@ -45,7 +46,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
float edgeMaxLen, float edgeMaxError,
|
||||
int vertsPerPoly,
|
||||
float detailSampleDist, float detailSampleMaxError,
|
||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
|
||||
bool keepInterResults)
|
||||
{
|
||||
RcConfig cfg = new RcConfig(
|
||||
partitionType,
|
||||
|
@ -58,7 +60,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
||||
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
||||
|
||||
RcBuilderResult rcResult = BuildRecastResult(geom, cfg);
|
||||
RcBuilderResult rcResult = BuildRecastResult(geom, cfg, keepInterResults);
|
||||
var meshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, rcResult);
|
||||
if (null == meshData)
|
||||
{
|
||||
|
@ -74,11 +76,26 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
return new DtNavMesh(meshData, vertsPerPoly, 0);
|
||||
}
|
||||
|
||||
private RcBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg)
|
||||
private RcBuilderResult BuildRecastResult(DemoInputGeomProvider geom, RcConfig cfg, bool keepInterResults)
|
||||
{
|
||||
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||
RcBuilder rcBuilder = new RcBuilder();
|
||||
return rcBuilder.Build(geom, bcfg);
|
||||
var result = rcBuilder.Build(geom, bcfg);
|
||||
if (!keepInterResults)
|
||||
{
|
||||
return new RcBuilderResult(
|
||||
result.TileX,
|
||||
result.TileZ,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
result.Mesh,
|
||||
result.MeshDetail,
|
||||
result.Context
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public DtMeshData BuildMeshData(DemoInputGeomProvider geom,
|
||||
|
|
|
@ -41,7 +41,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
settings.minRegionSize, settings.mergedRegionSize,
|
||||
settings.edgeMaxLen, settings.edgeMaxError,
|
||||
settings.vertsPerPoly, settings.detailSampleDist, settings.detailSampleMaxError,
|
||||
settings.filterLowHangingObstacles, settings.filterLedgeSpans, settings.filterWalkableLowHeightSpans);
|
||||
settings.filterLowHangingObstacles, settings.filterLedgeSpans, settings.filterWalkableLowHeightSpans,
|
||||
settings.keepInterResults, settings.buildAll);
|
||||
}
|
||||
|
||||
public NavMeshBuildResult Build(IInputGeomProvider geom,
|
||||
|
@ -53,7 +54,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
float edgeMaxLen, float edgeMaxError,
|
||||
int vertsPerPoly,
|
||||
float detailSampleDist, float detailSampleMaxError,
|
||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
|
||||
bool keepInterResults, bool buildAll)
|
||||
{
|
||||
List<RcBuilderResult> results = BuildRecastResult(
|
||||
geom,
|
||||
|
@ -65,7 +67,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
edgeMaxLen, edgeMaxError,
|
||||
vertsPerPoly,
|
||||
detailSampleDist, detailSampleMaxError,
|
||||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans
|
||||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
||||
keepInterResults, buildAll
|
||||
);
|
||||
|
||||
var tileMeshData = BuildMeshData(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, results);
|
||||
|
@ -82,7 +85,8 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
float edgeMaxLen, float edgeMaxError,
|
||||
int vertsPerPoly,
|
||||
float detailSampleDist, float detailSampleMaxError,
|
||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans)
|
||||
bool filterLowHangingObstacles, bool filterLedgeSpans, bool filterWalkableLowHeightSpans,
|
||||
bool keepInterResults, bool buildAll)
|
||||
|
||||
{
|
||||
RcConfig cfg = new RcConfig(true, tileSize, tileSize,
|
||||
|
@ -97,7 +101,7 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
filterLowHangingObstacles, filterLedgeSpans, filterWalkableLowHeightSpans,
|
||||
SampleAreaModifications.SAMPLE_AREAMOD_WALKABLE, true);
|
||||
RcBuilder rcBuilder = new RcBuilder();
|
||||
return rcBuilder.BuildTiles(geom, cfg, Task.Factory);
|
||||
return rcBuilder.BuildTiles(geom, cfg, keepInterResults, buildAll, Environment.ProcessorCount + 1, Task.Factory);
|
||||
}
|
||||
|
||||
public DtNavMesh BuildNavMesh(IInputGeomProvider geom, List<DtMeshData> meshData, float cellSize, int tileSize, int vertsPerPoly)
|
||||
|
@ -123,10 +127,9 @@ namespace DotRecast.Recast.Toolset.Builder
|
|||
List<DtMeshData> meshData = new List<DtMeshData>();
|
||||
foreach (RcBuilderResult result in results)
|
||||
{
|
||||
int x = result.tileX;
|
||||
int z = result.tileZ;
|
||||
DtNavMeshCreateParams option = DemoNavMeshBuilder
|
||||
.GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result);
|
||||
int x = result.TileX;
|
||||
int z = result.TileZ;
|
||||
DtNavMeshCreateParams option = DemoNavMeshBuilder.GetNavMeshCreateParams(geom, cellSize, cellHeight, agentHeight, agentRadius, agentMaxClimb, result);
|
||||
|
||||
option.tileX = x;
|
||||
option.tileZ = z;
|
||||
|
|
|
@ -34,5 +34,8 @@ namespace DotRecast.Recast.Toolset
|
|||
|
||||
public bool tiled = false;
|
||||
public int tileSize = 32;
|
||||
|
||||
public bool keepInterResults = false;
|
||||
public bool buildAll = true;
|
||||
}
|
||||
}
|
|
@ -18,12 +18,12 @@ namespace DotRecast.Recast.Toolset.Tools
|
|||
private DtDynamicNavMesh dynaMesh;
|
||||
private readonly Dictionary<long, RcGizmo> colliderGizmos;
|
||||
|
||||
private readonly Random random;
|
||||
private readonly IRcRand random;
|
||||
private readonly DemoInputGeomProvider bridgeGeom;
|
||||
private readonly DemoInputGeomProvider houseGeom;
|
||||
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.random = rand;
|
||||
|
@ -339,20 +339,14 @@ namespace DotRecast.Recast.Toolset.Tools
|
|||
return resultvector;
|
||||
}
|
||||
|
||||
public bool UpdateDynaMesh(TaskFactory executor)
|
||||
public bool Update(TaskFactory executor)
|
||||
{
|
||||
if (dynaMesh == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool updated = dynaMesh.Update(executor).Result;
|
||||
if (updated)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return dynaMesh.Update(executor);
|
||||
}
|
||||
|
||||
public bool Raycast(RcVec3f spos, RcVec3f epos, out float hitPos, out RcVec3f raycastHitPos)
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace DotRecast.Recast.Toolset.Tools
|
|||
|
||||
var beginTick = RcFrequency.Ticks;
|
||||
var rb = new RcBuilder();
|
||||
var result = rb.BuildTile(geom, cfg, bmin, bmax, tx, ty, new RcAtomicInteger(0), 1);
|
||||
var result = rb.BuildTile(geom, cfg, bmin, bmax, tx, ty, new RcAtomicInteger(0), 1, settings.keepInterResults);
|
||||
|
||||
var tb = new TileNavMeshBuilder();
|
||||
var meshData = tb.BuildMeshData(geom, settings.cellSize, settings.cellHeight, settings.agentHeight, settings.agentRadius, settings.agentMaxClimb, RcImmutableArray.Create(result)
|
||||
|
|
|
@ -19,7 +19,9 @@ freely, subject to the following restrictions:
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using DotRecast.Core;
|
||||
|
@ -45,129 +47,123 @@ namespace DotRecast.Recast
|
|||
_progressListener = progressListener;
|
||||
}
|
||||
|
||||
public List<RcBuilderResult> BuildTiles(IInputGeomProvider geom, RcConfig cfg, TaskFactory taskFactory)
|
||||
public List<RcBuilderResult> BuildTiles(IInputGeomProvider geom, RcConfig cfg, bool keepInterResults, bool buildAll,
|
||||
int threads = 0, TaskFactory taskFactory = null, CancellationToken cancellation = default)
|
||||
{
|
||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
||||
CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
|
||||
List<RcBuilderResult> results = new List<RcBuilderResult>();
|
||||
if (null != taskFactory)
|
||||
|
||||
if (1 < threads)
|
||||
{
|
||||
BuildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, default);
|
||||
return BuildMultiThread(geom, cfg, bmin, bmax, tw, th, threads, taskFactory ?? Task.Factory, cancellation, keepInterResults, buildAll);
|
||||
}
|
||||
else
|
||||
|
||||
return BuildSingleThread(geom, cfg, bmin, bmax, tw, th, keepInterResults, buildAll);
|
||||
}
|
||||
|
||||
private List<RcBuilderResult> BuildSingleThread(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tw, int th,
|
||||
bool keepInterResults, bool buildAll)
|
||||
{
|
||||
var results = new List<RcBuilderResult>(th * tw);
|
||||
RcAtomicInteger counter = new RcAtomicInteger(0);
|
||||
|
||||
for (int y = 0; y < th; ++y)
|
||||
{
|
||||
BuildSingleThreadAsync(geom, cfg, bmin, bmax, tw, th, results);
|
||||
for (int x = 0; x < tw; ++x)
|
||||
{
|
||||
var result = BuildTile(geom, cfg, bmin, bmax, x, y, counter, tw * th, keepInterResults);
|
||||
results.Add(result);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
public Task BuildTilesAsync(IInputGeomProvider geom, RcConfig cfg, int threads, List<RcBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
|
||||
private List<RcBuilderResult> BuildMultiThread(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tw, int th,
|
||||
int threads, TaskFactory taskFactory, CancellationToken cancellation,
|
||||
bool keepInterResults, bool buildAll)
|
||||
{
|
||||
RcVec3f bmin = geom.GetMeshBoundsMin();
|
||||
RcVec3f bmax = geom.GetMeshBoundsMax();
|
||||
CalcTileCount(bmin, bmax, cfg.Cs, cfg.TileSizeX, cfg.TileSizeZ, out var tw, out var th);
|
||||
Task task;
|
||||
if (1 < threads)
|
||||
{
|
||||
task = BuildMultiThreadAsync(geom, cfg, bmin, bmax, tw, th, results, taskFactory, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
task = BuildSingleThreadAsync(geom, cfg, bmin, bmax, tw, th, results);
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
private Task BuildSingleThreadAsync(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax,
|
||||
int tw, int th, List<RcBuilderResult> results)
|
||||
{
|
||||
RcAtomicInteger counter = new RcAtomicInteger(0);
|
||||
for (int y = 0; y < th; ++y)
|
||||
{
|
||||
for (int x = 0; x < tw; ++x)
|
||||
{
|
||||
results.Add(BuildTile(geom, cfg, bmin, bmax, x, y, counter, tw * th));
|
||||
}
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task BuildMultiThreadAsync(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax,
|
||||
int tw, int th, List<RcBuilderResult> results, TaskFactory taskFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
RcAtomicInteger counter = new RcAtomicInteger(0);
|
||||
CountdownEvent latch = new CountdownEvent(tw * th);
|
||||
List<Task> tasks = new List<Task>();
|
||||
var results = new ConcurrentQueue<RcBuilderResult>();
|
||||
RcAtomicInteger progress = new RcAtomicInteger(0);
|
||||
|
||||
List<Task> limits = new List<Task>(threads);
|
||||
for (int x = 0; x < tw; ++x)
|
||||
{
|
||||
for (int y = 0; y < th; ++y)
|
||||
{
|
||||
int tx = x;
|
||||
int ty = y;
|
||||
var task = taskFactory.StartNew(() =>
|
||||
var task = taskFactory.StartNew(state =>
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
if (cancellation.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
RcBuilderResult tile = BuildTile(geom, cfg, bmin, bmax, tx, ty, counter, tw * th);
|
||||
lock (results)
|
||||
{
|
||||
results.Add(tile);
|
||||
}
|
||||
RcBuilderResult result = BuildTile(geom, cfg, bmin, bmax, tx, ty, progress, tw * th, keepInterResults);
|
||||
results.Enqueue(result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
}, null, cancellation);
|
||||
|
||||
|
||||
latch.Signal();
|
||||
}, cancellationToken);
|
||||
|
||||
tasks.Add(task);
|
||||
limits.Add(task);
|
||||
if (threads <= limits.Count)
|
||||
{
|
||||
Task.WaitAll(limits.ToArray());
|
||||
limits.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
latch.Wait();
|
||||
}
|
||||
catch (ThreadInterruptedException)
|
||||
if (0 < limits.Count)
|
||||
{
|
||||
Task.WaitAll(limits.ToArray());
|
||||
limits.Clear();
|
||||
}
|
||||
|
||||
return Task.WhenAll(tasks.ToArray());
|
||||
var list = results.ToList();
|
||||
return list;
|
||||
}
|
||||
|
||||
public RcBuilderResult BuildTile(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tx,
|
||||
int ty, RcAtomicInteger counter, int total)
|
||||
public RcBuilderResult BuildTile(IInputGeomProvider geom, RcConfig cfg, RcVec3f bmin, RcVec3f bmax, int tx, int ty, RcAtomicInteger progress, int total, bool keepInterResults)
|
||||
{
|
||||
RcBuilderResult result = Build(geom, new RcBuilderConfig(cfg, bmin, bmax, tx, ty));
|
||||
var bcfg = new RcBuilderConfig(cfg, bmin, bmax, tx, ty);
|
||||
RcBuilderResult result = Build(geom, bcfg);
|
||||
if (_progressListener != null)
|
||||
{
|
||||
_progressListener.OnProgress(counter.IncrementAndGet(), total);
|
||||
_progressListener.OnProgress(progress.IncrementAndGet(), total);
|
||||
}
|
||||
|
||||
if (!keepInterResults)
|
||||
{
|
||||
return new RcBuilderResult(
|
||||
result.TileX,
|
||||
result.TileZ,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
result.Mesh,
|
||||
result.MeshDetail,
|
||||
result.Context
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public RcBuilderResult Build(IInputGeomProvider geom, RcBuilderConfig builderCfg)
|
||||
public RcBuilderResult Build(IInputGeomProvider geom, RcBuilderConfig bcfg)
|
||||
{
|
||||
RcConfig cfg = builderCfg.cfg;
|
||||
RcConfig cfg = bcfg.cfg;
|
||||
RcContext ctx = new RcContext();
|
||||
//
|
||||
// Step 1. Rasterize input polygon soup.
|
||||
//
|
||||
RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(ctx, geom, builderCfg);
|
||||
return Build(ctx, builderCfg.tileX, builderCfg.tileZ, geom, cfg, solid);
|
||||
RcHeightfield solid = RcVoxelizations.BuildSolidHeightfield(ctx, geom, bcfg);
|
||||
return Build(ctx, bcfg.tileX, bcfg.tileZ, geom, cfg, solid);
|
||||
}
|
||||
|
||||
public RcBuilderResult Build(RcContext ctx, int tileX, int tileZ, IInputGeomProvider geom, RcConfig cfg, RcHeightfield solid)
|
||||
|
|
|
@ -4,56 +4,26 @@ namespace DotRecast.Recast
|
|||
{
|
||||
public class RcBuilderResult
|
||||
{
|
||||
public readonly int tileX;
|
||||
public readonly int tileZ;
|
||||
public readonly int TileX;
|
||||
public readonly int TileZ;
|
||||
|
||||
private readonly RcCompactHeightfield chf;
|
||||
private readonly RcContourSet cs;
|
||||
private readonly RcPolyMesh pmesh;
|
||||
private readonly RcPolyMeshDetail dmesh;
|
||||
private readonly RcHeightfield solid;
|
||||
private readonly RcContext _context;
|
||||
public readonly RcHeightfield SolidHeightfiled;
|
||||
public readonly RcCompactHeightfield CompactHeightfield;
|
||||
public readonly RcContourSet ContourSet;
|
||||
public readonly RcPolyMesh Mesh;
|
||||
public readonly RcPolyMeshDetail MeshDetail;
|
||||
public readonly RcContext Context;
|
||||
|
||||
public RcBuilderResult(int tileX, int tileZ, RcHeightfield solid, RcCompactHeightfield chf, RcContourSet cs, RcPolyMesh pmesh, RcPolyMeshDetail dmesh, RcContext ctx)
|
||||
public RcBuilderResult(int tileX, int tileZ, RcHeightfield solidHeightfiled, RcCompactHeightfield compactHeightfield, RcContourSet contourSet, RcPolyMesh mesh, RcPolyMeshDetail meshDetail, RcContext ctx)
|
||||
{
|
||||
this.tileX = tileX;
|
||||
this.tileZ = tileZ;
|
||||
this.solid = solid;
|
||||
this.chf = chf;
|
||||
this.cs = cs;
|
||||
this.pmesh = pmesh;
|
||||
this.dmesh = dmesh;
|
||||
_context = ctx;
|
||||
}
|
||||
|
||||
public RcPolyMesh GetMesh()
|
||||
{
|
||||
return pmesh;
|
||||
}
|
||||
|
||||
public RcPolyMeshDetail GetMeshDetail()
|
||||
{
|
||||
return dmesh;
|
||||
}
|
||||
|
||||
public RcCompactHeightfield GetCompactHeightfield()
|
||||
{
|
||||
return chf;
|
||||
}
|
||||
|
||||
public RcContourSet GetContourSet()
|
||||
{
|
||||
return cs;
|
||||
}
|
||||
|
||||
public RcHeightfield GetSolidHeightfield()
|
||||
{
|
||||
return solid;
|
||||
}
|
||||
|
||||
public RcContext GetTelemetry()
|
||||
{
|
||||
return _context;
|
||||
TileX = tileX;
|
||||
TileZ = tileZ;
|
||||
SolidHeightfiled = solidHeightfiled;
|
||||
CompactHeightfield = compactHeightfield;
|
||||
ContourSet = contourSet;
|
||||
Mesh = mesh;
|
||||
MeshDetail = meshDetail;
|
||||
Context = ctx;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,29 +22,21 @@ using DotRecast.Core.Numerics;
|
|||
|
||||
namespace DotRecast.Recast
|
||||
{
|
||||
/** Represents a heightfield layer within a layer set. */
|
||||
/// A dynamic heightfield representing obstructed space.
|
||||
/// @ingroup recast
|
||||
public class RcHeightfield
|
||||
{
|
||||
/** The width of the heightfield. (Along the x-axis in cell units.) */
|
||||
public readonly int width;
|
||||
public readonly int width; //< The width of the heightfield. (Along the x-axis in cell units.)
|
||||
public readonly int height; //< The height of the heightfield. (Along the z-axis in cell units.)
|
||||
public readonly RcVec3f bmin; //< The minimum bounds in world space. [(x, y, z)]
|
||||
public RcVec3f bmax; //< The maximum bounds in world space. [(x, y, z)]
|
||||
public readonly float cs; //< The size of each cell. (On the xz-plane.)
|
||||
public readonly float ch; //< The height of each cell. (The minimum increment along the y-axis.)
|
||||
public readonly RcSpan[] spans; //< Heightfield of spans (width*height).
|
||||
|
||||
/** The height of the heightfield. (Along the z-axis in cell units.) */
|
||||
public readonly int height;
|
||||
|
||||
/** The minimum bounds in world space. [(x, y, z)] */
|
||||
public readonly RcVec3f bmin;
|
||||
|
||||
/** The maximum bounds in world space. [(x, y, z)] */
|
||||
public RcVec3f bmax;
|
||||
|
||||
/** The size of each cell. (On the xz-plane.) */
|
||||
public readonly float cs;
|
||||
|
||||
/** The height of each cell. (The minimum increment along the y-axis.) */
|
||||
public readonly float ch;
|
||||
|
||||
/** Heightfield of spans (width*height). */
|
||||
public readonly RcSpan[] spans;
|
||||
// memory pool for rcSpan instances.
|
||||
public RcSpanPool pools; //< Linked list of span pools.
|
||||
public RcSpan freelist; //< The next free span.
|
||||
|
||||
/** Border size in cell units */
|
||||
public readonly int borderSize;
|
||||
|
|
|
@ -30,9 +30,9 @@ namespace DotRecast.Recast
|
|||
hitTime = 0.0f;
|
||||
foreach (RcBuilderResult result in results)
|
||||
{
|
||||
if (result.GetMeshDetail() != null)
|
||||
if (result.MeshDetail != null)
|
||||
{
|
||||
if (Raycast(result.GetMesh(), result.GetMeshDetail(), src, dst, out hitTime))
|
||||
if (Raycast(result.Mesh, result.MeshDetail, src, dst, out hitTime))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,63 @@ namespace DotRecast.Recast
|
|||
aMin.Z <= bMax.Z && aMax.Z >= bMin.Z;
|
||||
}
|
||||
|
||||
/// Allocates a new span in the heightfield.
|
||||
/// Use a memory pool and free list to minimize actual allocations.
|
||||
///
|
||||
/// @param[in] heightfield The heightfield
|
||||
/// @returns A pointer to the allocated or re-used span memory.
|
||||
private static RcSpan AllocSpan(RcHeightfield heightfield)
|
||||
{
|
||||
// If necessary, allocate new page and update the freelist.
|
||||
if (heightfield.freelist == null || heightfield.freelist.next == null)
|
||||
{
|
||||
// Create new page.
|
||||
// Allocate memory for the new pool.
|
||||
RcSpanPool spanPool = new RcSpanPool();
|
||||
if (spanPool == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add the pool into the list of pools.
|
||||
spanPool.next = heightfield.pools;
|
||||
heightfield.pools = spanPool;
|
||||
|
||||
// Add new spans to the free list.
|
||||
RcSpan freeList = heightfield.freelist;
|
||||
int head = 0;
|
||||
int it = RC_SPANS_PER_POOL;
|
||||
do
|
||||
{
|
||||
--it;
|
||||
spanPool.items[it].next = freeList;
|
||||
freeList = spanPool.items[it];
|
||||
} while (it != head);
|
||||
|
||||
heightfield.freelist = spanPool.items[it];
|
||||
}
|
||||
|
||||
// Pop item from the front of the free list.
|
||||
RcSpan newSpan = heightfield.freelist;
|
||||
heightfield.freelist = heightfield.freelist.next;
|
||||
return newSpan;
|
||||
}
|
||||
|
||||
/// Releases the memory used by the span back to the heightfield, so it can be re-used for new spans.
|
||||
/// @param[in] heightfield The heightfield.
|
||||
/// @param[in] span A pointer to the span to free
|
||||
private static void FreeSpan(RcHeightfield heightfield, RcSpan span)
|
||||
{
|
||||
if (span == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the span to the front of the free list.
|
||||
span.next = heightfield.freelist;
|
||||
heightfield.freelist = span;
|
||||
}
|
||||
|
||||
|
||||
/// Adds a span to the heightfield. If the new span overlaps existing spans,
|
||||
/// it will merge the new span with the existing ones.
|
||||
|
@ -156,7 +213,7 @@ namespace DotRecast.Recast
|
|||
float axisOffset, int axis)
|
||||
{
|
||||
// How far positive or negative away from the separating axis is each vertex.
|
||||
float[] inVertAxisDelta = new float[12];
|
||||
Span<float> inVertAxisDelta = stackalloc float[12];
|
||||
for (int inVert = 0; inVert < inVertsCount; ++inVert)
|
||||
{
|
||||
inVertAxisDelta[inVert] = axisOffset - inVerts[inVertsOffset + inVert * 3 + axis];
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
|
||||
DotRecast Copyright (c) 2023 Choi Ikpil ikpil@naver.com
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
namespace DotRecast.Recast
|
||||
{
|
||||
/// A memory pool used for quick allocation of spans within a heightfield.
|
||||
/// @see rcHeightfield
|
||||
public class RcSpanPool
|
||||
{
|
||||
public RcSpanPool next; //< The next span pool.
|
||||
public readonly RcSpan[] items; //< Array of spans in the pool.
|
||||
|
||||
public RcSpanPool()
|
||||
{
|
||||
items = new RcSpan[RcConstants.RC_SPANS_PER_POOL];
|
||||
for (int i = 0; i < items.Length; ++i)
|
||||
{
|
||||
items[i] = new RcSpan();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using DotRecast.Core.Buffers;
|
||||
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Serialization;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace DotRecast.Core.Test;
|
||||
|
@ -56,4 +59,50 @@ public class RcRentedArrayTest
|
|||
Assert.Throws<NullReferenceException>(() => rentedArray[^1] = 0);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSame()
|
||||
{
|
||||
// not same
|
||||
{
|
||||
using var r1 = RcRentedArray.Rent<float>(1024);
|
||||
using var r2 = RcRentedArray.Rent<float>(1024);
|
||||
|
||||
Assert.That(r2.AsArray() != r1.AsArray(), Is.EqualTo(true));
|
||||
}
|
||||
|
||||
// same
|
||||
{
|
||||
// error case
|
||||
float[] r1Array;
|
||||
using (var r1 = RcRentedArray.Rent<float>(1024))
|
||||
{
|
||||
r1Array = r1.AsArray();
|
||||
for (int i = 0; i < r1.Length; ++i)
|
||||
{
|
||||
r1[i] = 123;
|
||||
}
|
||||
}
|
||||
|
||||
using var r2 = RcRentedArray.Rent<float>(1024);
|
||||
|
||||
Assert.That(r2.AsArray() == r1Array, Is.EqualTo(true));
|
||||
Assert.That(r2.AsArray().Sum(), Is.EqualTo(0));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDispose()
|
||||
{
|
||||
var r1 = RcRentedArray.Rent<float>(1024);
|
||||
for (int i = 0; i < r1.Length; ++i)
|
||||
{
|
||||
r1[i] = 123;
|
||||
}
|
||||
|
||||
Assert.That(r1.IsDisposed, Is.EqualTo(false));
|
||||
r1.Dispose();
|
||||
Assert.That(r1.IsDisposed, Is.EqualTo(true));
|
||||
Assert.That(r1.AsArray(), Is.Null);
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
@ -73,13 +73,13 @@ public class RecastTestMeshBuilder
|
|||
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||
RcBuilder rcBuilder = new RcBuilder();
|
||||
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
|
||||
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||
RcPolyMesh m_pmesh = rcResult.Mesh;
|
||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||
{
|
||||
m_pmesh.flags[i] = 1;
|
||||
}
|
||||
|
||||
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
||||
RcPolyMeshDetail m_dmesh = rcResult.MeshDetail;
|
||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||
option.verts = m_pmesh.verts;
|
||||
option.vertCount = m_pmesh.nverts;
|
||||
|
|
|
@ -9,17 +9,17 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -10,7 +10,6 @@ using NUnit.Framework;
|
|||
|
||||
namespace DotRecast.Detour.Dynamic.Test;
|
||||
|
||||
|
||||
public class DynamicNavMeshTest
|
||||
{
|
||||
private static readonly RcVec3f START_POS = new RcVec3f(70.87453f, 0.0010070801f, 86.69021f);
|
||||
|
@ -32,9 +31,7 @@ public class DynamicNavMeshTest
|
|||
// create dynamic navmesh
|
||||
DtDynamicNavMesh mesh = new DtDynamicNavMesh(f);
|
||||
// build navmesh asynchronously using multiple threads
|
||||
Task<bool> future = mesh.Build(Task.Factory);
|
||||
// wait for build to complete
|
||||
bool _ = future.Result;
|
||||
mesh.Build(Task.Factory);
|
||||
|
||||
// create new query
|
||||
DtNavMeshQuery query = new DtNavMeshQuery(mesh.NavMesh());
|
||||
|
@ -54,9 +51,8 @@ public class DynamicNavMeshTest
|
|||
long colliderId = mesh.AddCollider(colldier);
|
||||
|
||||
// update navmesh asynchronously
|
||||
future = mesh.Update(Task.Factory);
|
||||
// wait for update to complete
|
||||
_ = future.Result;
|
||||
mesh.Update(Task.Factory);
|
||||
|
||||
// create new query
|
||||
query = new DtNavMeshQuery(mesh.NavMesh());
|
||||
|
||||
|
@ -70,9 +66,7 @@ public class DynamicNavMeshTest
|
|||
// remove obstacle
|
||||
mesh.RemoveCollider(colliderId);
|
||||
// update navmesh asynchronously
|
||||
future = mesh.Update(Task.Factory);
|
||||
// wait for update to complete
|
||||
_ = future.Result;
|
||||
mesh.Update(Task.Factory);
|
||||
// create new query
|
||||
query = new DtNavMeshQuery(mesh.NavMesh());
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@ using NUnit.Framework;
|
|||
|
||||
namespace DotRecast.Detour.Dynamic.Test;
|
||||
|
||||
|
||||
public class VoxelQueryTest
|
||||
{
|
||||
private const int TILE_WIDTH = 100;
|
||||
|
@ -101,12 +100,12 @@ public class VoxelQueryTest
|
|||
// load voxels from file
|
||||
DtVoxelFileReader reader = new DtVoxelFileReader(DtVoxelTileLZ4ForTestCompressor.Shared);
|
||||
DtVoxelFile f = reader.Read(br);
|
||||
|
||||
// create dynamic navmesh
|
||||
var mesh = new DtDynamicNavMesh(f);
|
||||
|
||||
// build navmesh asynchronously using multiple threads
|
||||
Task<bool> future = mesh.Build(Task.Factory);
|
||||
// wait for build to complete
|
||||
var _ = future.Result;
|
||||
mesh.Build(Task.Factory);
|
||||
return mesh;
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
@ -73,13 +73,13 @@ public class RecastTestMeshBuilder
|
|||
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax());
|
||||
RcBuilder rcBuilder = new RcBuilder();
|
||||
RcBuilderResult rcResult = rcBuilder.Build(geom, bcfg);
|
||||
RcPolyMesh m_pmesh = rcResult.GetMesh();
|
||||
RcPolyMesh m_pmesh = rcResult.Mesh;
|
||||
for (int i = 0; i < m_pmesh.npolys; ++i)
|
||||
{
|
||||
m_pmesh.flags[i] = 1;
|
||||
}
|
||||
|
||||
RcPolyMeshDetail m_dmesh = rcResult.GetMeshDetail();
|
||||
RcPolyMeshDetail m_dmesh = rcResult.MeshDetail;
|
||||
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
||||
option.verts = m_pmesh.verts;
|
||||
option.vertCount = m_pmesh.nverts;
|
||||
|
|
|
@ -28,7 +28,7 @@ public class TestDetourBuilder : DetourBuilder
|
|||
{
|
||||
RcBuilder rcBuilder = new RcBuilder();
|
||||
RcBuilderResult rcResult = rcBuilder.Build(geom, rcConfig);
|
||||
RcPolyMesh pmesh = rcResult.GetMesh();
|
||||
RcPolyMesh pmesh = rcResult.Mesh;
|
||||
|
||||
if (applyRecastDemoFlags)
|
||||
{
|
||||
|
@ -58,7 +58,7 @@ public class TestDetourBuilder : DetourBuilder
|
|||
}
|
||||
}
|
||||
|
||||
RcPolyMeshDetail dmesh = rcResult.GetMeshDetail();
|
||||
RcPolyMeshDetail dmesh = rcResult.MeshDetail;
|
||||
DtNavMeshCreateParams option = GetNavMeshCreateParams(rcConfig.cfg, pmesh, dmesh, agentHeight, agentRadius,
|
||||
agentMaxClimb);
|
||||
return Build(option, x, y);
|
||||
|
|
|
@ -78,13 +78,13 @@ public class TestTiledNavMeshBuilder
|
|||
true, true, true,
|
||||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||
RcBuilder rcBuilder = new RcBuilder();
|
||||
List<RcBuilderResult> rcResult = rcBuilder.BuildTiles(geom, cfg, null);
|
||||
List<RcBuilderResult> rcResult = rcBuilder.BuildTiles(geom, cfg, false, true);
|
||||
|
||||
// Add tiles to nav mesh
|
||||
|
||||
foreach (RcBuilderResult result in rcResult)
|
||||
{
|
||||
RcPolyMesh pmesh = result.GetMesh();
|
||||
RcPolyMesh pmesh = result.Mesh;
|
||||
if (pmesh.npolys == 0)
|
||||
{
|
||||
continue;
|
||||
|
@ -103,7 +103,7 @@ public class TestTiledNavMeshBuilder
|
|||
option.polyFlags = pmesh.flags;
|
||||
option.polyCount = pmesh.npolys;
|
||||
option.nvp = pmesh.nvp;
|
||||
RcPolyMeshDetail dmesh = result.GetMeshDetail();
|
||||
RcPolyMeshDetail dmesh = result.MeshDetail;
|
||||
option.detailMeshes = dmesh.meshes;
|
||||
option.detailVerts = dmesh.verts;
|
||||
option.detailVertsCount = dmesh.nverts;
|
||||
|
@ -116,8 +116,8 @@ public class TestTiledNavMeshBuilder
|
|||
option.bmax = pmesh.bmax;
|
||||
option.cs = cellSize;
|
||||
option.ch = cellHeight;
|
||||
option.tileX = result.tileX;
|
||||
option.tileZ = result.tileZ;
|
||||
option.tileX = result.TileX;
|
||||
option.tileZ = result.TileZ;
|
||||
option.buildBvTree = true;
|
||||
navMesh.AddTile(DtNavMeshBuilder.CreateNavMeshData(option), 0, 0);
|
||||
}
|
||||
|
|
|
@ -9,17 +9,17 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="NUnit" Version="4.0.1" />
|
||||
<PackageReference Include="NUnit" Version="4.1.0" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0"/>
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.0.1">
|
||||
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
|
|
@ -27,7 +27,6 @@ using NUnit.Framework;
|
|||
|
||||
namespace DotRecast.Recast.Test;
|
||||
|
||||
|
||||
public class RecastTileMeshTest
|
||||
{
|
||||
private const float m_cellSize = 0.3f;
|
||||
|
@ -71,28 +70,28 @@ public class RecastTileMeshTest
|
|||
SampleAreaModifications.SAMPLE_AREAMOD_GROUND, true);
|
||||
RcBuilderConfig bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 7, 8);
|
||||
RcBuilderResult rcResult = builder.Build(geom, bcfg);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(1));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(5));
|
||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 6, 9);
|
||||
rcResult = builder.Build(geom, bcfg);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(7));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(2));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(7));
|
||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 9);
|
||||
rcResult = builder.Build(geom, bcfg);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(9));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(2));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(9));
|
||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 4, 3);
|
||||
rcResult = builder.Build(geom, bcfg);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(6));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(3));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(6));
|
||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 2, 8);
|
||||
rcResult = builder.Build(geom, bcfg);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(17));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(5));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(17));
|
||||
bcfg = new RcBuilderConfig(cfg, geom.GetMeshBoundsMin(), geom.GetMeshBoundsMax(), 0, 8);
|
||||
rcResult = builder.Build(geom, bcfg);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(6));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(15));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -138,28 +137,27 @@ public class RecastTileMeshTest
|
|||
private void Build(IInputGeomProvider geom, RcBuilder builder, RcConfig cfg, int threads, bool validate)
|
||||
{
|
||||
CancellationTokenSource cts = new CancellationTokenSource();
|
||||
List<RcBuilderResult> tiles = new();
|
||||
var task = builder.BuildTilesAsync(geom, cfg, threads, tiles, Task.Factory, cts.Token);
|
||||
List<RcBuilderResult> tiles = builder.BuildTiles(geom, cfg, false, true, threads, Task.Factory, cts.Token);
|
||||
if (validate)
|
||||
{
|
||||
RcBuilderResult rcResult = GetTile(tiles, 7, 8);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(1));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(5));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(1));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(5));
|
||||
rcResult = GetTile(tiles, 6, 9);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(7));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(2));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(7));
|
||||
rcResult = GetTile(tiles, 2, 9);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(2));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(9));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(2));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(9));
|
||||
rcResult = GetTile(tiles, 4, 3);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(3));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(6));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(3));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(6));
|
||||
rcResult = GetTile(tiles, 2, 8);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(5));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(17));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(5));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(17));
|
||||
rcResult = GetTile(tiles, 0, 8);
|
||||
Assert.That(rcResult.GetMesh().npolys, Is.EqualTo(6));
|
||||
Assert.That(rcResult.GetMesh().nverts, Is.EqualTo(15));
|
||||
Assert.That(rcResult.Mesh.npolys, Is.EqualTo(6));
|
||||
Assert.That(rcResult.Mesh.nverts, Is.EqualTo(15));
|
||||
}
|
||||
|
||||
try
|
||||
|
@ -175,6 +173,6 @@ public class RecastTileMeshTest
|
|||
|
||||
private RcBuilderResult GetTile(List<RcBuilderResult> tiles, int x, int z)
|
||||
{
|
||||
return tiles.FirstOrDefault(tile => tile.tileX == x && tile.tileZ == z);
|
||||
return tiles.FirstOrDefault(tile => tile.TileX == x && tile.TileZ == z);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue