DotRecastNetSim/src/DotRecast.Detour.Extras/Jumplink/NavMeshGroundSampler.cs

72 lines
2.9 KiB
C#

using System;
using DotRecast.Core;
using DotRecast.Detour.QueryResults;
using DotRecast.Recast;
namespace DotRecast.Detour.Extras.Jumplink
{
class NavMeshGroundSampler : AbstractGroundSampler
{
private readonly IQueryFilter filter = new NoOpFilter();
public override void Sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es)
{
NavMeshQuery navMeshQuery = CreateNavMesh(result, acfg.agentRadius, acfg.agentHeight, acfg.agentClimb);
SampleGround(acfg, es, (pt, h) => GetNavMeshHeight(navMeshQuery, pt, acfg.cellSize, h));
}
private NavMeshQuery CreateNavMesh(RecastBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
{
NavMeshDataCreateParams option = new NavMeshDataCreateParams();
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.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.buildBvTree = true;
return new NavMeshQuery(new NavMesh(NavMeshBuilder.CreateNavMeshData(option), option.nvp, 0));
}
private Tuple<bool, float> GetNavMeshHeight(NavMeshQuery navMeshQuery, RcVec3f pt, float cs, float heightRange)
{
RcVec3f halfExtents = new RcVec3f { x = cs, y = heightRange, z = cs };
float maxHeight = pt.y + heightRange;
RcAtomicBoolean found = new RcAtomicBoolean();
RcAtomicFloat minHeight = new RcAtomicFloat(pt.y);
navMeshQuery.QueryPolygons(pt, halfExtents, filter, new PolyQueryInvoker((tile, poly, refs) =>
{
Result<float> h = navMeshQuery.GetPolyHeight(refs, pt);
if (h.Succeeded())
{
float y = h.result;
if (y > minHeight.Get() && y < maxHeight)
{
minHeight.Exchange(y);
found.Set(true);
}
}
}));
if (found.Get())
{
return Tuple.Create(true, minHeight.Get());
}
return Tuple.Create(false, pt.y);
}
}
}