NavMeshGroundSampler.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. using System;
  2. using DotRecast.Core;
  3. using DotRecast.Recast;
  4. namespace DotRecast.Detour.Extras.Jumplink
  5. {
  6. class NavMeshGroundSampler : AbstractGroundSampler
  7. {
  8. public override void Sample(JumpLinkBuilderConfig acfg, RecastBuilderResult result, EdgeSampler es)
  9. {
  10. DtNavMeshQuery navMeshQuery = CreateNavMesh(result, acfg.agentRadius, acfg.agentHeight, acfg.agentClimb);
  11. SampleGround(acfg, es, (RcVec3f pt, float heightRange, out float height) => GetNavMeshHeight(navMeshQuery, pt, acfg.cellSize, heightRange, out height));
  12. }
  13. private DtNavMeshQuery CreateNavMesh(RecastBuilderResult r, float agentRadius, float agentHeight, float agentClimb)
  14. {
  15. DtNavMeshCreateParams option = new DtNavMeshCreateParams();
  16. option.verts = r.GetMesh().verts;
  17. option.vertCount = r.GetMesh().nverts;
  18. option.polys = r.GetMesh().polys;
  19. option.polyAreas = r.GetMesh().areas;
  20. option.polyFlags = r.GetMesh().flags;
  21. option.polyCount = r.GetMesh().npolys;
  22. option.nvp = r.GetMesh().nvp;
  23. option.detailMeshes = r.GetMeshDetail().meshes;
  24. option.detailVerts = r.GetMeshDetail().verts;
  25. option.detailVertsCount = r.GetMeshDetail().nverts;
  26. option.detailTris = r.GetMeshDetail().tris;
  27. option.detailTriCount = r.GetMeshDetail().ntris;
  28. option.walkableRadius = agentRadius;
  29. option.walkableHeight = agentHeight;
  30. option.walkableClimb = agentClimb;
  31. option.bmin = r.GetMesh().bmin;
  32. option.bmax = r.GetMesh().bmax;
  33. option.cs = r.GetMesh().cs;
  34. option.ch = r.GetMesh().ch;
  35. option.buildBvTree = true;
  36. return new DtNavMeshQuery(new DtNavMesh(DtNavMeshBuilder.CreateNavMeshData(option), option.nvp, 0));
  37. }
  38. private bool GetNavMeshHeight(DtNavMeshQuery navMeshQuery, RcVec3f pt, float cs, float heightRange, out float height)
  39. {
  40. height = default;
  41. RcVec3f halfExtents = new RcVec3f { x = cs, y = heightRange, z = cs };
  42. float maxHeight = pt.y + heightRange;
  43. RcAtomicBoolean found = new RcAtomicBoolean();
  44. RcAtomicFloat minHeight = new RcAtomicFloat(pt.y);
  45. navMeshQuery.QueryPolygons(pt, halfExtents, DtQueryNoOpFilter.Shared, new PolyQueryInvoker((tile, poly, refs) =>
  46. {
  47. var status = navMeshQuery.GetPolyHeight(refs, pt, out var h);
  48. if (status.Succeeded())
  49. {
  50. if (h > minHeight.Get() && h < maxHeight)
  51. {
  52. minHeight.Exchange(h);
  53. found.Set(true);
  54. }
  55. }
  56. }));
  57. if (found.Get())
  58. {
  59. height = minHeight.Get();
  60. return true;
  61. }
  62. height = pt.y;
  63. return false;
  64. }
  65. }
  66. }