summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Navmesh/Jobs/JobBuildNodes.cs
blob: 841c86d842a59d8fc41cfe7350d0da819612e27f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using Pathfinding.Jobs;
using Pathfinding.Util;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;
using UnityEngine.Profiling;

namespace Pathfinding.Graphs.Navmesh.Jobs {
	/// <summary>
	/// Builds nodes and tiles and prepares them for pathfinding.
	///
	/// Takes input from a <see cref="TileBuilder"/> job and outputs a <see cref="BuildNodeTilesOutput"/>.
	///
	/// This job takes the following steps:
	/// - Calculate connections between nodes inside each tile
	/// - Create node and tile objects
	/// - Connect adjacent tiles together
	/// </summary>
	public struct JobBuildNodes {
		AstarPath astar;
		uint graphIndex;
		public uint initialPenalty;
		public bool recalculateNormals;
		public float maxTileConnectionEdgeDistance;
		Matrix4x4 graphToWorldSpace;
		TileLayout tileLayout;

		public class BuildNodeTilesOutput : IProgress, System.IDisposable {
			public TileBuilder.TileBuilderOutput dependency;
			public NavmeshTile[] tiles;

			public float Progress => dependency.Progress;

			public void Dispose () {
			}
		}

		internal JobBuildNodes(RecastGraph graph, TileLayout tileLayout) {
			this.astar = graph.active;
			this.tileLayout = tileLayout;
			this.graphIndex = graph.graphIndex;
			this.initialPenalty = graph.initialPenalty;
			this.recalculateNormals = graph.RecalculateNormals;
			this.maxTileConnectionEdgeDistance = graph.MaxTileConnectionEdgeDistance;
			this.graphToWorldSpace = tileLayout.transform.matrix;
		}

		public Promise<BuildNodeTilesOutput> Schedule (DisposeArena arena, Promise<TileBuilder.TileBuilderOutput> dependency) {
			var input = dependency.GetValue();
			var tileRect = input.tileMeshes.tileRect;
			UnityEngine.Assertions.Assert.AreEqual(input.tileMeshes.tileMeshes.Length, tileRect.Area);
			var tiles = new NavmeshTile[tileRect.Area];
			var tilesGCHandle = System.Runtime.InteropServices.GCHandle.Alloc(tiles);
			var nodeConnections = new NativeArray<JobCalculateTriangleConnections.TileNodeConnectionsUnsafe>(tileRect.Area, Allocator.Persistent);

			var calculateConnectionsJob = new JobCalculateTriangleConnections {
				tileMeshes = input.tileMeshes.tileMeshes,
				nodeConnections = nodeConnections,
			}.Schedule(dependency.handle);

			var tileWorldSize = new Vector2(tileLayout.TileWorldSizeX, tileLayout.TileWorldSizeZ);
			var createTilesJob = new JobCreateTiles {
				tileMeshes = input.tileMeshes.tileMeshes,
				tiles = tilesGCHandle,
				tileRect = tileRect,
				graphTileCount = tileLayout.tileCount,
				graphIndex = graphIndex,
				initialPenalty = initialPenalty,
				recalculateNormals = recalculateNormals,
				graphToWorldSpace = this.graphToWorldSpace,
				tileWorldSize = tileWorldSize,
			}.Schedule(dependency.handle);

			var applyConnectionsJob = new JobWriteNodeConnections {
				nodeConnections = nodeConnections,
				tiles = tilesGCHandle,
			}.Schedule(JobHandle.CombineDependencies(calculateConnectionsJob, createTilesJob));

			Profiler.BeginSample("Scheduling ConnectTiles");
			var connectTilesDependency = JobConnectTiles.ScheduleBatch(tilesGCHandle, applyConnectionsJob, tileRect, tileWorldSize, maxTileConnectionEdgeDistance);
			Profiler.EndSample();

			arena.Add(tilesGCHandle);
			arena.Add(nodeConnections);

			return new Promise<BuildNodeTilesOutput>(connectTilesDependency, new BuildNodeTilesOutput {
				dependency = input,
				tiles = tiles,
			});
		}
	}
}