forked from mirror/DotRecast
75 lines
2.9 KiB
C#
75 lines
2.9 KiB
C#
using DotRecast.Core;
|
|
using DotRecast.Core.Numerics;
|
|
|
|
using DotRecast.Recast;
|
|
|
|
namespace DotRecast.Detour.Extras.Jumplink
|
|
{
|
|
class NavMeshGroundSampler : AbstractGroundSampler
|
|
{
|
|
public override void Sample(JumpLinkBuilderConfig acfg, RcBuilderResult result, EdgeSampler es)
|
|
{
|
|
DtNavMeshQuery navMeshQuery = CreateNavMesh(result, acfg.agentRadius, acfg.agentHeight, acfg.agentClimb);
|
|
SampleGround(acfg, es, (RcVec3f pt, float heightRange, out float height) => GetNavMeshHeight(navMeshQuery, pt, acfg.cellSize, heightRange, out height));
|
|
}
|
|
|
|
private DtNavMeshQuery CreateNavMesh(RcBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
|
|
{
|
|
DtNavMeshCreateParams option = new DtNavMeshCreateParams();
|
|
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.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));
|
|
}
|
|
|
|
|
|
private bool GetNavMeshHeight(DtNavMeshQuery navMeshQuery, RcVec3f pt, float cs, float heightRange, out float height)
|
|
{
|
|
height = default;
|
|
|
|
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, DtQueryNoOpFilter.Shared, new PolyQueryInvoker((tile, poly, refs) =>
|
|
{
|
|
var status = navMeshQuery.GetPolyHeight(refs, pt, out var h);
|
|
if (status.Succeeded())
|
|
{
|
|
if (h > minHeight.Get() && h < maxHeight)
|
|
{
|
|
minHeight.Exchange(h);
|
|
found.Set(true);
|
|
}
|
|
}
|
|
}));
|
|
|
|
if (found.Get())
|
|
{
|
|
height = minHeight.Get();
|
|
return true;
|
|
}
|
|
|
|
height = pt.Y;
|
|
return false;
|
|
}
|
|
}
|
|
} |