summaryrefslogtreecommitdiff
path: root/Other/AstarPathfindingDemo/Packages/com.arongranberg.astar/Graphs/Navmesh/Jobs/JobBuildTileMeshFromVertices.cs
blob: f68ed2ba06c57f9e8aff469840b39d552eed15dc (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
93
94
95
96
97
98
99
100
101
102
103
104
105
using Pathfinding.Util;
using Unity.Burst;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using UnityEngine;

namespace Pathfinding.Graphs.Navmesh.Jobs {
	/// <summary>
	/// Builds tiles from raw mesh vertices and indices.
	///
	/// This job takes the following steps:
	/// - Transform all vertices using the <see cref="meshToGraph"/> matrix.
	/// - Remove duplicate vertices
	/// - If <see cref="recalculateNormals"/> is enabled: ensure all triangles are laid out in the clockwise direction.
	/// </summary>
	[BurstCompile(FloatMode = FloatMode.Default)]
	public struct JobBuildTileMeshFromVertices : IJob {
		public NativeArray<Vector3> vertices;
		public NativeArray<int> indices;
		public Matrix4x4 meshToGraph;
		public NativeArray<TileMesh.TileMeshUnsafe> outputBuffers;
		public bool recalculateNormals;


		[BurstCompile(FloatMode = FloatMode.Fast)]
		public struct JobTransformTileCoordinates : IJob {
			public NativeArray<Vector3> vertices;
			public NativeArray<Int3> outputVertices;
			public Matrix4x4 matrix;

			public void Execute () {
				for (int i = 0; i < vertices.Length; i++) {
					outputVertices[i] = (Int3)matrix.MultiplyPoint3x4(vertices[i]);
				}
			}
		}

		public struct BuildNavmeshOutput : IProgress, System.IDisposable {
			public NativeArray<TileMesh.TileMeshUnsafe> tiles;

			public float Progress => 0.0f;

			public void Dispose () {
				for (int i = 0; i < tiles.Length; i++) tiles[i].Dispose();
				tiles.Dispose();
			}
		}

		public static Promise<BuildNavmeshOutput> Schedule (NativeArray<Vector3> vertices, NativeArray<int> indices, Matrix4x4 meshToGraph, bool recalculateNormals) {
			if (vertices.Length > NavmeshBase.VertexIndexMask) throw new System.ArgumentException("Too many vertices in the navmesh graph. Provided " + vertices.Length + ", but the maximum number of vertices per tile is " + NavmeshBase.VertexIndexMask + ". You can raise this limit by enabling ASTAR_RECAST_LARGER_TILES in the A* Inspector Optimizations tab");

			var outputBuffers = new NativeArray<TileMesh.TileMeshUnsafe>(1, Allocator.Persistent);

			var job = new JobBuildTileMeshFromVertices {
				vertices = vertices,
				indices = indices,
				meshToGraph = meshToGraph,
				outputBuffers = outputBuffers,
				recalculateNormals = recalculateNormals,
			}.Schedule();
			return new Promise<BuildNavmeshOutput>(job, new BuildNavmeshOutput {
				tiles = outputBuffers,
			});
		}

		public void Execute () {
			var int3vertices = new NativeArray<Int3>(vertices.Length, Allocator.Temp);
			var tags = new NativeArray<int>(indices.Length / 3, Allocator.Temp, NativeArrayOptions.ClearMemory);

			new JobTransformTileCoordinates {
				vertices = vertices,
				outputVertices = int3vertices,
				matrix = meshToGraph,
			}.Execute();

			unsafe {
				UnityEngine.Assertions.Assert.IsTrue(this.outputBuffers.Length == 1);
				var tile = (TileMesh.TileMeshUnsafe*) this.outputBuffers.GetUnsafePtr();
				var outputVertices = &tile->verticesInTileSpace;
				var outputTriangles = &tile->triangles;
				var outputTags = &tile->tags;
				*outputVertices = new UnsafeAppendBuffer(0, 4, Allocator.Persistent);
				*outputTriangles = new UnsafeAppendBuffer(0, 4, Allocator.Persistent);
				*outputTags = new UnsafeAppendBuffer(0, 4, Allocator.Persistent);
				new MeshUtility.JobRemoveDuplicateVertices {
					vertices = int3vertices,
					triangles = indices,
					tags = tags,
					outputVertices = outputVertices,
					outputTriangles = outputTriangles,
					outputTags = outputTags,
				}.Execute();

				if (recalculateNormals) {
					var verticesSpan = outputVertices->AsUnsafeSpan<Int3>();
					var trianglesSpan = outputTriangles->AsUnsafeSpan<int>();
					MeshUtility.MakeTrianglesClockwise(ref verticesSpan, ref trianglesSpan);
				}
			}

			int3vertices.Dispose();
		}
	}
}