123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- using UnityEngine;
- using System.Collections.Generic;
- namespace Pathfinding {
- using Pathfinding.Util;
- using Pathfinding.Serialization;
- public interface INavmesh {
- void GetNodes(System.Action<GraphNode> del);
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [JsonOptIn]
- [Pathfinding.Util.Preserve]
- public class NavMeshGraph : NavmeshBase, IUpdatableGraph {
-
- [JsonMember]
- public Mesh sourceMesh;
-
- [JsonMember]
- public Vector3 offset;
-
- [JsonMember]
- public Vector3 rotation;
-
- [JsonMember]
- public float scale = 1;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- [JsonMember]
- public bool recalculateNormals = true;
-
-
-
-
-
- [JsonMember]
- Vector3 cachedSourceMeshBoundsMin;
- protected override bool RecalculateNormals { get { return recalculateNormals; } }
- public override float TileWorldSizeX {
- get {
- return forcedBoundsSize.x;
- }
- }
- public override float TileWorldSizeZ {
- get {
- return forcedBoundsSize.z;
- }
- }
- protected override float MaxTileConnectionEdgeDistance {
- get {
-
- return 0f;
- }
- }
- public override GraphTransform CalculateTransform () {
- return new GraphTransform(Matrix4x4.TRS(offset, Quaternion.Euler(rotation), Vector3.one) * Matrix4x4.TRS(sourceMesh != null ? sourceMesh.bounds.min * scale : cachedSourceMeshBoundsMin * scale, Quaternion.identity, Vector3.one));
- }
- GraphUpdateThreading IUpdatableGraph.CanUpdateAsync (GraphUpdateObject o) {
- return GraphUpdateThreading.UnityThread;
- }
- void IUpdatableGraph.UpdateAreaInit (GraphUpdateObject o) {}
- void IUpdatableGraph.UpdateAreaPost (GraphUpdateObject o) {}
- void IUpdatableGraph.UpdateArea (GraphUpdateObject o) {
- UpdateArea(o, this);
- }
- public static void UpdateArea (GraphUpdateObject o, INavmeshHolder graph) {
- Bounds bounds = graph.transform.InverseTransform(o.bounds);
-
- var irect = new IntRect(
- Mathf.FloorToInt(bounds.min.x*Int3.Precision),
- Mathf.FloorToInt(bounds.min.z*Int3.Precision),
- Mathf.CeilToInt(bounds.max.x*Int3.Precision),
- Mathf.CeilToInt(bounds.max.z*Int3.Precision)
- );
-
- var a = new Int3(irect.xmin, 0, irect.ymin);
- var b = new Int3(irect.xmin, 0, irect.ymax);
- var c = new Int3(irect.xmax, 0, irect.ymin);
- var d = new Int3(irect.xmax, 0, irect.ymax);
- var ymin = ((Int3)bounds.min).y;
- var ymax = ((Int3)bounds.max).y;
-
- graph.GetNodes(_node => {
- var node = _node as TriangleMeshNode;
- bool inside = false;
- int allLeft = 0;
- int allRight = 0;
- int allTop = 0;
- int allBottom = 0;
-
- for (int v = 0; v < 3; v++) {
- Int3 p = node.GetVertexInGraphSpace(v);
- if (irect.Contains(p.x, p.z)) {
- inside = true;
- break;
- }
- if (p.x < irect.xmin) allLeft++;
- if (p.x > irect.xmax) allRight++;
- if (p.z < irect.ymin) allTop++;
- if (p.z > irect.ymax) allBottom++;
- }
- if (!inside && (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3)) {
- return;
- }
-
- for (int v = 0; v < 3; v++) {
- int v2 = v > 1 ? 0 : v+1;
- Int3 vert1 = node.GetVertexInGraphSpace(v);
- Int3 vert2 = node.GetVertexInGraphSpace(v2);
- if (VectorMath.SegmentsIntersectXZ(a, b, vert1, vert2)) { inside = true; break; }
- if (VectorMath.SegmentsIntersectXZ(a, c, vert1, vert2)) { inside = true; break; }
- if (VectorMath.SegmentsIntersectXZ(c, d, vert1, vert2)) { inside = true; break; }
- if (VectorMath.SegmentsIntersectXZ(d, b, vert1, vert2)) { inside = true; break; }
- }
-
- if (inside || node.ContainsPointInGraphSpace(a) || node.ContainsPointInGraphSpace(b) || node.ContainsPointInGraphSpace(c) || node.ContainsPointInGraphSpace(d)) {
- inside = true;
- }
- if (!inside) {
- return;
- }
- int allAbove = 0;
- int allBelow = 0;
-
- for (int v = 0; v < 3; v++) {
- Int3 p = node.GetVertexInGraphSpace(v);
- if (p.y < ymin) allBelow++;
- if (p.y > ymax) allAbove++;
- }
-
- if (allBelow == 3 || allAbove == 3) return;
-
-
- o.WillUpdateNode(node);
- o.Apply(node);
- });
- }
- protected override IEnumerable<Progress> ScanInternal () {
- cachedSourceMeshBoundsMin = sourceMesh != null ? sourceMesh.bounds.min : Vector3.zero;
- transform = CalculateTransform();
- tileZCount = tileXCount = 1;
- tiles = new NavmeshTile[tileZCount*tileXCount];
- TriangleMeshNode.SetNavmeshHolder(AstarPath.active.data.GetGraphIndex(this), this);
- if (sourceMesh == null) {
- FillWithEmptyTiles();
- yield break;
- }
- yield return new Progress(0.0f, "Transforming Vertices");
- forcedBoundsSize = sourceMesh.bounds.size * scale;
- Vector3[] vectorVertices = sourceMesh.vertices;
- var intVertices = ListPool<Int3>.Claim(vectorVertices.Length);
- var matrix = Matrix4x4.TRS(-sourceMesh.bounds.min * scale, Quaternion.identity, Vector3.one * scale);
-
-
-
- for (int i = 0; i < vectorVertices.Length; i++) {
- intVertices.Add((Int3)matrix.MultiplyPoint3x4(vectorVertices[i]));
- }
- yield return new Progress(0.1f, "Compressing Vertices");
-
- Int3[] compressedVertices = null;
- int[] compressedTriangles = null;
- Polygon.CompressMesh(intVertices, new List<int>(sourceMesh.triangles), out compressedVertices, out compressedTriangles);
- ListPool<Int3>.Release(ref intVertices);
- yield return new Progress(0.2f, "Building Nodes");
- ReplaceTile(0, 0, compressedVertices, compressedTriangles);
-
- navmeshUpdateData.OnRecalculatedTiles(tiles);
- if (OnRecalculatedTiles != null) OnRecalculatedTiles(tiles.Clone() as NavmeshTile[]);
- }
- protected override void DeserializeSettingsCompatibility (GraphSerializationContext ctx) {
- base.DeserializeSettingsCompatibility(ctx);
- sourceMesh = ctx.DeserializeUnityObject() as Mesh;
- offset = ctx.DeserializeVector3();
- rotation = ctx.DeserializeVector3();
- scale = ctx.reader.ReadSingle();
- nearestSearchOnlyXZ = !ctx.reader.ReadBoolean();
- }
- }
- }
|