JumpLinkBuilder.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using DotRecast.Core;
  5. using DotRecast.Recast;
  6. using static DotRecast.Core.RcMath;
  7. namespace DotRecast.Detour.Extras.Jumplink
  8. {
  9. public class JumpLinkBuilder
  10. {
  11. private readonly EdgeExtractor edgeExtractor = new EdgeExtractor();
  12. private readonly EdgeSamplerFactory edgeSamplerFactory = new EdgeSamplerFactory();
  13. private readonly IGroundSampler groundSampler = new NavMeshGroundSampler();
  14. private readonly TrajectorySampler trajectorySampler = new TrajectorySampler();
  15. private readonly JumpSegmentBuilder jumpSegmentBuilder = new JumpSegmentBuilder();
  16. private readonly List<JumpEdge[]> edges;
  17. private readonly IList<RecastBuilderResult> results;
  18. public JumpLinkBuilder(IList<RecastBuilderResult> results)
  19. {
  20. this.results = results;
  21. edges = results.Select(r => edgeExtractor.ExtractEdges(r.GetMesh())).ToList();
  22. }
  23. public List<JumpLink> Build(JumpLinkBuilderConfig acfg, JumpLinkType type)
  24. {
  25. List<JumpLink> links = new List<JumpLink>();
  26. for (int tile = 0; tile < results.Count; tile++)
  27. {
  28. JumpEdge[] edges = this.edges[tile];
  29. foreach (JumpEdge edge in edges)
  30. {
  31. links.AddRange(ProcessEdge(acfg, results[tile], type, edge));
  32. }
  33. }
  34. return links;
  35. }
  36. private List<JumpLink> ProcessEdge(JumpLinkBuilderConfig acfg, RecastBuilderResult result, JumpLinkType type, JumpEdge edge)
  37. {
  38. EdgeSampler es = edgeSamplerFactory.Get(acfg, type, edge);
  39. groundSampler.Sample(acfg, result, es);
  40. trajectorySampler.Sample(acfg, result.GetSolidHeightfield(), es);
  41. JumpSegment[] jumpSegments = jumpSegmentBuilder.Build(acfg, es);
  42. return BuildJumpLinks(acfg, es, jumpSegments);
  43. }
  44. private List<JumpLink> BuildJumpLinks(JumpLinkBuilderConfig acfg, EdgeSampler es, JumpSegment[] jumpSegments)
  45. {
  46. List<JumpLink> links = new List<JumpLink>();
  47. foreach (JumpSegment js in jumpSegments)
  48. {
  49. RcVec3f sp = es.start.gsamples[js.startSample].p;
  50. RcVec3f sq = es.start.gsamples[js.startSample + js.samples - 1].p;
  51. GroundSegment end = es.end[js.groundSegment];
  52. RcVec3f ep = end.gsamples[js.startSample].p;
  53. RcVec3f eq = end.gsamples[js.startSample + js.samples - 1].p;
  54. float d = Math.Min(RcVec3f.Dist2DSqr(sp, sq), RcVec3f.Dist2DSqr(ep, eq));
  55. if (d >= 4 * acfg.agentRadius * acfg.agentRadius)
  56. {
  57. JumpLink link = new JumpLink();
  58. links.Add(link);
  59. link.startSamples = RcArrayUtils.CopyOf(es.start.gsamples, js.startSample, js.samples);
  60. link.endSamples = RcArrayUtils.CopyOf(end.gsamples, js.startSample, js.samples);
  61. link.start = es.start;
  62. link.end = end;
  63. link.trajectory = es.trajectory;
  64. for (int j = 0; j < link.nspine; ++j)
  65. {
  66. float u = ((float)j) / (link.nspine - 1);
  67. RcVec3f p = es.trajectory.Apply(sp, ep, u);
  68. link.spine0[j * 3] = p.x;
  69. link.spine0[j * 3 + 1] = p.y;
  70. link.spine0[j * 3 + 2] = p.z;
  71. p = es.trajectory.Apply(sq, eq, u);
  72. link.spine1[j * 3] = p.x;
  73. link.spine1[j * 3 + 1] = p.y;
  74. link.spine1[j * 3 + 2] = p.z;
  75. }
  76. }
  77. }
  78. return links;
  79. }
  80. public List<JumpEdge[]> GetEdges()
  81. {
  82. return edges;
  83. }
  84. }
  85. }