Inheritance: Pathfinding.MeshNode
Ejemplo n.º 1
0
		public override void CreateNodes (int number) {
			TriangleMeshNode[] tmp = new TriangleMeshNode[number];
			for (int i=0;i<number;i++) {
				tmp[i] = new TriangleMeshNode (active);
				tmp[i].Penalty = initialPenalty;
			}
		}
Ejemplo n.º 2
0
		/** Split funnel at node index \a splitIndex and throw the nodes up to that point away and replace with \a prefix.
		  * Used when the AI has happened to get sidetracked and entered a node outside the funnel.
		  */
		public void UpdateFunnelCorridor (int splitIndex, TriangleMeshNode prefix) {

			if (splitIndex > 0) {
				nodes.RemoveRange(0,splitIndex-1);
				//This is a node which should be removed, we replace it with the prefix
				nodes[0] = prefix;
			} else {
				nodes.Insert(0,prefix);
			}

			left.Clear();
			right.Clear();
			left.Add(exactStart);
			right.Add(exactStart);

			for (int i=0;i<nodes.Count-1;i++) {
				//NOTE should use return value in future versions
				nodes[i].GetPortal (nodes[i+1],left,right,false);
			}

			left.Add(exactEnd);
			right.Add(exactEnd);
		}
Ejemplo n.º 3
0
		/** Returns if the point is inside the node in XZ space */
		public bool ContainsPoint (TriangleMeshNode node, Vector3 pos) {
			if (	Polygon.IsClockwise ((Vector3)GetVertex(node.v0),(Vector3)GetVertex(node.v1), pos)
			    && 	Polygon.IsClockwise ((Vector3)GetVertex(node.v1),(Vector3)GetVertex(node.v2), pos)
			    && 	Polygon.IsClockwise ((Vector3)GetVertex(node.v2),(Vector3)GetVertex(node.v0), pos)) {
				return true;
			}
			return false;
		}
Ejemplo n.º 4
0
		/** Returns the closest point of the node */
		public Vector3 ClosestPointOnNode (TriangleMeshNode node, Vector3 pos) {
			return Polygon.ClosestPointOnTriangle ((Vector3)GetVertex(node.v0),(Vector3)GetVertex(node.v1),(Vector3)GetVertex(node.v2),pos);
		}
Ejemplo n.º 5
0
		public override void DeserializeExtraInfo (GraphSerializationContext ctx) {
			//NavMeshGraph.DeserializeMeshNodes (this,nodes,bytes);
			
			System.IO.BinaryReader reader = ctx.reader;
			
			tileXCount = reader.ReadInt32();
			
			if (tileXCount < 0) return;
				
			tileZCount = reader.ReadInt32();
			
			tiles = new NavmeshTile[tileXCount * tileZCount];
			
			//Make sure mesh nodes can reference this graph
			TriangleMeshNode.SetNavmeshHolder (ctx.graphIndex, this);
			
			for (int z=0;z<tileZCount;z++) {
				for (int x=0;x<tileXCount;x++) {
					
					int tileIndex = x + z*tileXCount;
					int tx = reader.ReadInt32();
					if (tx < 0) throw new System.Exception ("Invalid tile coordinates (x < 0)");
					
					int tz = reader.ReadInt32();
					if (tz < 0) throw new System.Exception ("Invalid tile coordinates (z < 0)");
					
					// This is not the origin of a large tile. Refer back to that tile.
					if (tx != x || tz != z) {
						tiles[tileIndex] = tiles[tz*tileXCount + tx];
						continue;
					}
					
					NavmeshTile tile = new NavmeshTile ();
					
					tile.x = tx;
					tile.z = tz;
					tile.w = reader.ReadInt32();
					tile.d = reader.ReadInt32();
					tile.bbTree = new BBTree (tile);
					
					tiles[tileIndex] = tile;
					
					int trisCount = reader.ReadInt32 ();
					
					if (trisCount % 3 != 0) throw new System.Exception ("Corrupt data. Triangle indices count must be divisable by 3. Got " + trisCount);
					
					tile.tris = new int[trisCount];
					for (int i=0;i<tile.tris.Length;i++) tile.tris[i] = reader.ReadInt32();
					
					tile.verts = new Int3[reader.ReadInt32()];
					for (int i=0;i<tile.verts.Length;i++) {
						tile.verts[i] = new Int3 (reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32());
					}
					
					int nodeCount = reader.ReadInt32();
					tile.nodes = new TriangleMeshNode[nodeCount];
					
					//Prepare for storing in vertex indices
					tileIndex <<= TileIndexOffset;
					
					for (int i=0;i<tile.nodes.Length;i++) {
						TriangleMeshNode node = new TriangleMeshNode (active);
						tile.nodes[i] = node;
						node.GraphIndex = (uint)ctx.graphIndex;
						
						node.DeserializeNode (ctx);
						node.v0 = tile.tris[i*3+0] | tileIndex;
						node.v1 = tile.tris[i*3+1] | tileIndex;
						node.v2 = tile.tris[i*3+2] | tileIndex;
						node.UpdatePositionFromVertices();
						
						tile.bbTree.Insert (node);
					}
				}
			}
		}
Ejemplo n.º 6
0
 private void CreateNodeConnections(TriangleMeshNode[] nodes)
 {
     List<MeshNode> list = ListPool<MeshNode>.Claim();
     List<uint> list2 = ListPool<uint>.Claim();
     Dictionary<Int2, int> dictionary = this.cachedInt2_int_dict;
     dictionary.Clear();
     for (int i = 0; i < nodes.Length; i++)
     {
         TriangleMeshNode triangleMeshNode = nodes[i];
         int vertexCount = triangleMeshNode.GetVertexCount();
         for (int j = 0; j < vertexCount; j++)
         {
             Int2 key = new Int2(triangleMeshNode.GetVertexIndex(j), triangleMeshNode.GetVertexIndex((j + 1) % vertexCount));
             if (!dictionary.ContainsKey(key))
             {
                 dictionary.Add(key, i);
             }
         }
     }
     for (int k = 0; k < nodes.Length; k++)
     {
         TriangleMeshNode triangleMeshNode2 = nodes[k];
         list.Clear();
         list2.Clear();
         int vertexCount2 = triangleMeshNode2.GetVertexCount();
         for (int l = 0; l < vertexCount2; l++)
         {
             int vertexIndex = triangleMeshNode2.GetVertexIndex(l);
             int vertexIndex2 = triangleMeshNode2.GetVertexIndex((l + 1) % vertexCount2);
             int num;
             if (dictionary.TryGetValue(new Int2(vertexIndex2, vertexIndex), out num))
             {
                 TriangleMeshNode triangleMeshNode3 = nodes[num];
                 int vertexCount3 = triangleMeshNode3.GetVertexCount();
                 for (int m = 0; m < vertexCount3; m++)
                 {
                     if (triangleMeshNode3.GetVertexIndex(m) == vertexIndex2 && triangleMeshNode3.GetVertexIndex((m + 1) % vertexCount3) == vertexIndex)
                     {
                         uint costMagnitude = (uint)(triangleMeshNode2.position - triangleMeshNode3.position).costMagnitude;
                         list.Add(triangleMeshNode3);
                         list2.Add(costMagnitude);
                         break;
                     }
                 }
             }
         }
         triangleMeshNode2.connections = list.ToArray();
         triangleMeshNode2.connectionCosts = list2.ToArray();
     }
     ListPool<MeshNode>.Release(list);
     ListPool<uint>.Release(list2);
 }
Ejemplo n.º 7
0
		/** Returns if the point is inside the node in XZ space */
		public static bool ContainsPoint (TriangleMeshNode node, Vector3 pos, Int3[] vertices) {
			if (!Polygon.IsClockwiseMargin ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1], (Vector3)vertices[node.v2])) {
				Debug.LogError ("Noes!");
			}
			
			if ( 	Polygon.IsClockwiseMargin ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1], pos)
			    && 	Polygon.IsClockwiseMargin ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2], pos)
			    && 	Polygon.IsClockwiseMargin ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0], pos)) {
				return true;
			}
			return false;
		}
Ejemplo n.º 8
0
		/** Returns the closest point of the node */
		public static Vector3 ClosestPointOnNode (TriangleMeshNode node, Int3[] vertices, Vector3 pos) {
			return Polygon.ClosestPointOnTriangle ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],(Vector3)vertices[node.v2],pos);
		}
Ejemplo n.º 9
0
		/** Generates a navmesh. Based on the supplied vertices and triangles. Memory usage is about O(n) */
		public void GenerateNodes (Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices) {
			
			Profiler.BeginSample ("Init");

			if (vectorVertices.Length == 0 || triangles.Length == 0) {
				originalVertices = vectorVertices;
				vertices = new Int3[0];
				//graph.CreateNodes (0);
				nodes = new TriangleMeshNode[0];
				return;
			}
			
			vertices = new Int3[vectorVertices.Length];
			
			//Backup the original vertices
			//for (int i=0;i<vectorVertices.Length;i++) {
			//	vectorVertices[i] = graph.matrix.MultiplyPoint (vectorVertices[i]);
			//}
			
			int c = 0;
			
			for (int i=0;i<vertices.Length;i++) {
				vertices[i] = (Int3)matrix.MultiplyPoint3x4 (vectorVertices[i]);
			}
			
			Dictionary<Int3,int> hashedVerts = new Dictionary<Int3,int> ();
			
			int[] newVertices = new int[vertices.Length];
				
			Profiler.EndSample ();
			Profiler.BeginSample ("Hashing");

			for (int i=0;i<vertices.Length;i++) {
				if (!hashedVerts.ContainsKey (vertices[i])) {
					newVertices[c] = i;
					hashedVerts.Add (vertices[i], c);
					c++;
				}// else {
					//Debug.Log ("Hash Duplicate "+hash+" "+vertices[i].ToString ());
				//}
			}
			
			/*newVertices[c] = vertices.Length-1;

			if (!hashedVerts.ContainsKey (vertices[newVertices[c]])) {
				
				hashedVerts.Add (vertices[newVertices[c]], c);
				c++;
			}*/
			
			for (int x=0;x<triangles.Length;x++) {
				Int3 vertex = vertices[triangles[x]];

				triangles[x] = hashedVerts[vertex];
			}
			
			/*for (int i=0;i<triangles.Length;i += 3) {
				
				Vector3 offset = Vector3.forward*i*0.01F;
				Debug.DrawLine (newVertices[triangles[i]]+offset,newVertices[triangles[i+1]]+offset,Color.blue);
				Debug.DrawLine (newVertices[triangles[i+1]]+offset,newVertices[triangles[i+2]]+offset,Color.blue);
				Debug.DrawLine (newVertices[triangles[i+2]]+offset,newVertices[triangles[i]]+offset,Color.blue);
			}*/
			
			Int3[] totalIntVertices = vertices;
			vertices = new Int3[c];
			originalVertices = new Vector3[c];
			for (int i=0;i<c;i++) {
				
				vertices[i] = totalIntVertices[newVertices[i]];//(Int3)graph.matrix.MultiplyPoint (vectorVertices[i]);
				originalVertices[i] = (Vector3)vectorVertices[newVertices[i]];//vectorVertices[newVertices[i]];
			}

			Profiler.EndSample ();
			Profiler.BeginSample ("Constructing Nodes");

			//graph.CreateNodes (triangles.Length/3);//new Node[triangles.Length/3];
			nodes = new TriangleMeshNode[triangles.Length/3];
			
			for (int i=0;i<nodes.Length;i++) {
				
				nodes[i] = new TriangleMeshNode(active);
				TriangleMeshNode node = nodes[i];//new MeshNode ();
				
				node.Penalty = initialPenalty;
				node.Walkable = true;
				
				
				node.v0 = triangles[i*3];
				node.v1 = triangles[i*3+1];
				node.v2 = triangles[i*3+2];
				
				if (!Polygon.IsClockwise (vertices[node.v0],vertices[node.v1],vertices[node.v2])) {
					//Debug.DrawLine (vertices[node.v0],vertices[node.v1],Color.red);
					//Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.red);
					//Debug.DrawLine (vertices[node.v2],vertices[node.v0],Color.red);
					
					int tmp = node.v0;
					node.v0 = node.v2;
					node.v2 = tmp;
				}
				
				if (Polygon.IsColinear (vertices[node.v0],vertices[node.v1],vertices[node.v2])) {
					Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.red);
				}
				
				// Make sure position is correctly set
				node.UpdatePositionFromVertices();
			}

			Profiler.EndSample ();

			Dictionary<Int2,TriangleMeshNode> sides = new Dictionary<Int2, TriangleMeshNode>();
			
			for (int i=0, j=0;i<triangles.Length; j+=1, i+=3) {
				sides[new Int2(triangles[i+0],triangles[i+1])] = nodes[j];
				sides[new Int2(triangles[i+1],triangles[i+2])] = nodes[j];
				sides[new Int2(triangles[i+2],triangles[i+0])] = nodes[j];
			}

			Profiler.BeginSample ("Connecting Nodes");

			List<MeshNode> connections = new List<MeshNode> ();
			List<uint> connectionCosts = new List<uint> ();
			
			int identicalError = 0;

			for (int i=0, j=0;i<triangles.Length; j+=1, i+=3) {
				connections.Clear ();
				connectionCosts.Clear ();
				
				//Int3 indices = new Int3(triangles[i],triangles[i+1],triangles[i+2]);
				
				TriangleMeshNode node = nodes[j];

				for ( int q = 0; q < 3; q++ ) {
					TriangleMeshNode other;
					if (sides.TryGetValue ( new Int2 (triangles[i+((q+1)%3)], triangles[i+q]), out other ) ) {
						connections.Add (other);
						connectionCosts.Add ((uint)(node.position-other.position).costMagnitude);
					}
				}

				node.connections = connections.ToArray ();
				node.connectionCosts = connectionCosts.ToArray ();
			}
			
			if (identicalError > 0) {
				Debug.LogError ("One or more triangles are identical to other triangles, this is not a good thing to have in a navmesh\nIncreasing the scale of the mesh might help\nNumber of triangles with error: "+identicalError+"\n");
			}

			Profiler.EndSample ();
			Profiler.BeginSample ("Rebuilding BBTree");

			RebuildBBTree (this);

			Profiler.EndSample ();

			//Debug.Log ("Graph Generation - NavMesh - Time to compute graph "+((Time.realtimeSinceStartup-startTime)*1000F).ToString ("0")+"ms");
		}
Ejemplo n.º 10
0
		public override void DeserializeExtraInfo (GraphSerializationContext ctx) {

			uint graphIndex = (uint)ctx.graphIndex;
			TriangleMeshNode.SetNavmeshHolder ((int)graphIndex,this);

			int nodeCount = ctx.reader.ReadInt32();
			int vertexCount = ctx.reader.ReadInt32();

			if (nodeCount == -1) {
				nodes = new TriangleMeshNode[0];
				_vertices = new Int3[0];
				originalVertices = new Vector3[0];
			}

			nodes = new TriangleMeshNode[nodeCount];
			_vertices = new Int3[vertexCount];
			originalVertices = new Vector3[vertexCount];

			for (int i=0;i<vertexCount;i++) {
				_vertices[i] = new Int3(ctx.reader.ReadInt32(), ctx.reader.ReadInt32(), ctx.reader.ReadInt32());
				originalVertices[i] = new Vector3(ctx.reader.ReadSingle(), ctx.reader.ReadSingle(), ctx.reader.ReadSingle());
			}

			bbTree = new BBTree();

			for (int i = 0; i < nodeCount;i++) {
				nodes[i] = new TriangleMeshNode(active);
				TriangleMeshNode node = nodes[i];
				node.DeserializeNode(ctx);
				node.UpdatePositionFromVertices();
			}

			bbTree.RebuildFrom (nodes);
		}
Ejemplo n.º 11
0
		/** Generates a navmesh. Based on the supplied vertices and triangles */
		void GenerateNodes (Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices) {

			Profiler.BeginSample ("Init");

			if (vectorVertices.Length == 0 || triangles.Length == 0) {
				originalVertices = vectorVertices;
				vertices = new Int3[0];
				nodes = new TriangleMeshNode[0];
				return;
			}

			vertices = new Int3[vectorVertices.Length];

			int c = 0;

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

			var hashedVerts = new Dictionary<Int3,int> ();

			var newVertices = new int[vertices.Length];

			Profiler.EndSample ();
			Profiler.BeginSample ("Hashing");

			for (int i=0;i<vertices.Length;i++) {
				if (!hashedVerts.ContainsKey (vertices[i])) {
					newVertices[c] = i;
					hashedVerts.Add (vertices[i], c);
					c++;
				}
			}

			for (int x=0;x<triangles.Length;x++) {
				Int3 vertex = vertices[triangles[x]];

				triangles[x] = hashedVerts[vertex];
			}

			Int3[] totalIntVertices = vertices;
			vertices = new Int3[c];
			originalVertices = new Vector3[c];
			for (int i=0;i<c;i++) {

				vertices[i] = totalIntVertices[newVertices[i]];
				originalVertices[i] = vectorVertices[newVertices[i]];
			}

			Profiler.EndSample ();
			Profiler.BeginSample ("Constructing Nodes");

			nodes = new TriangleMeshNode[triangles.Length/3];

			int graphIndex = active.astarData.GetGraphIndex(this);

			// Does not have to set this, it is set in ScanInternal
			//TriangleMeshNode.SetNavmeshHolder ((int)graphIndex,this);

			for (int i=0;i<nodes.Length;i++) {

				nodes[i] = new TriangleMeshNode(active);
				TriangleMeshNode node = nodes[i];//new MeshNode ();

				node.GraphIndex = (uint)graphIndex;
				node.Penalty = initialPenalty;
				node.Walkable = true;


				node.v0 = triangles[i*3];
				node.v1 = triangles[i*3+1];
				node.v2 = triangles[i*3+2];

				if (!Polygon.IsClockwise (vertices[node.v0],vertices[node.v1],vertices[node.v2])) {
					//Debug.DrawLine (vertices[node.v0],vertices[node.v1],Color.red);
					//Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.red);
					//Debug.DrawLine (vertices[node.v2],vertices[node.v0],Color.red);

					int tmp = node.v0;
					node.v0 = node.v2;
					node.v2 = tmp;
				}

				if (Polygon.IsColinear (vertices[node.v0],vertices[node.v1],vertices[node.v2])) {
					Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.red);
				}

				// Make sure position is correctly set
				node.UpdatePositionFromVertices();
			}

			Profiler.EndSample ();

			var sides = new Dictionary<Int2, TriangleMeshNode>();

			for (int i=0, j=0;i<triangles.Length; j+=1, i+=3) {
				sides[new Int2(triangles[i+0],triangles[i+1])] = nodes[j];
				sides[new Int2(triangles[i+1],triangles[i+2])] = nodes[j];
				sides[new Int2(triangles[i+2],triangles[i+0])] = nodes[j];
			}

			Profiler.BeginSample ("Connecting Nodes");

			var connections = new List<MeshNode> ();
			var connectionCosts = new List<uint> ();

			for (int i=0, j = 0; i < triangles.Length; j+=1, i+=3) {
				connections.Clear ();
				connectionCosts.Clear ();

				TriangleMeshNode node = nodes[j];

				for ( int q = 0; q < 3; q++ ) {
					TriangleMeshNode other;
					if (sides.TryGetValue ( new Int2 (triangles[i+((q+1)%3)], triangles[i+q]), out other ) ) {
						connections.Add (other);
						connectionCosts.Add ((uint)(node.position-other.position).costMagnitude);
					}
				}

				node.connections = connections.ToArray ();
				node.connectionCosts = connectionCosts.ToArray ();
			}

			Profiler.EndSample ();
			Profiler.BeginSample ("Rebuilding BBTree");

			RebuildBBTree (this);

			Profiler.EndSample ();

#if ASTARDEBUG
			for (int i=0;i<nodes.Length;i++) {
				TriangleMeshNode node = nodes[i] as TriangleMeshNode;

				float a1 = Polygon.TriangleArea2 ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],(Vector3)vertices[node.v2]);

				long a2 = Polygon.TriangleArea2 (vertices[node.v0],vertices[node.v1],vertices[node.v2]);
				if (a1 * a2 < 0) Debug.LogError (a1+ " " + a2);


				if (Polygon.IsClockwise (vertices[node.v0],vertices[node.v1],vertices[node.v2])) {
					Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.green);
					Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.green);
					Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.green);
				} else {
					Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.red);
				}
			}
#endif
		}
Ejemplo n.º 12
0
 public void ReplaceTile(int x, int z, int w, int d, Int3[] verts, int[] tris, bool worldSpace)
 {
     if (x + w > this.tileXCount || z + d > this.tileZCount || x < 0 || z < 0)
     {
         throw new ArgumentException(string.Concat(new object[]
         {
             "Tile is placed at an out of bounds position or extends out of the graph bounds (",
             x,
             ", ",
             z,
             " [",
             w,
             ", ",
             d,
             "] ",
             this.tileXCount,
             " ",
             this.tileZCount,
             ")"
         }));
     }
     if (w < 1 || d < 1)
     {
         throw new ArgumentException(string.Concat(new object[]
         {
             "width and depth must be greater or equal to 1. Was ",
             w,
             ", ",
             d
         }));
     }
     for (int i = z; i < z + d; i++)
     {
         for (int j = x; j < x + w; j++)
         {
             RecastGraph.NavmeshTile navmeshTile = this.tiles[j + i * this.tileXCount];
             if (navmeshTile != null)
             {
                 this.RemoveConnectionsFromTile(navmeshTile);
                 for (int k = 0; k < navmeshTile.nodes.Length; k++)
                 {
                     navmeshTile.nodes[k].Destroy();
                 }
                 for (int l = navmeshTile.z; l < navmeshTile.z + navmeshTile.d; l++)
                 {
                     for (int m = navmeshTile.x; m < navmeshTile.x + navmeshTile.w; m++)
                     {
                         RecastGraph.NavmeshTile navmeshTile2 = this.tiles[m + l * this.tileXCount];
                         if (navmeshTile2 == null || navmeshTile2 != navmeshTile)
                         {
                             throw new Exception("This should not happen");
                         }
                         if (l < z || l >= z + d || m < x || m >= x + w)
                         {
                             this.tiles[m + l * this.tileXCount] = RecastGraph.NewEmptyTile(m, l);
                             if (this.batchTileUpdate)
                             {
                                 this.batchUpdatedTiles.Add(m + l * this.tileXCount);
                             }
                         }
                         else
                         {
                             this.tiles[m + l * this.tileXCount] = null;
                         }
                     }
                 }
             }
         }
     }
     RecastGraph.NavmeshTile navmeshTile3 = new RecastGraph.NavmeshTile();
     navmeshTile3.x = x;
     navmeshTile3.z = z;
     navmeshTile3.w = w;
     navmeshTile3.d = d;
     navmeshTile3.tris = tris;
     navmeshTile3.verts = verts;
     navmeshTile3.bbTree = new BBTree();
     if (navmeshTile3.tris.Length % 3 != 0)
     {
         throw new ArgumentException("Triangle array's length must be a multiple of 3 (tris)");
     }
     if (navmeshTile3.verts.Length > 65535)
     {
         throw new ArgumentException("Too many vertices per tile (more than 65535)");
     }
     if (!worldSpace)
     {
         if (!Mathf.Approximately((float)(x * this.tileSizeX) * this.cellSize * 1000f, (float)Math.Round((double)((float)(x * this.tileSizeX) * this.cellSize * 1000f))))
         {
             UnityEngine.Debug.LogWarning("Possible numerical imprecision. Consider adjusting tileSize and/or cellSize");
         }
         if (!Mathf.Approximately((float)(z * this.tileSizeZ) * this.cellSize * 1000f, (float)Math.Round((double)((float)(z * this.tileSizeZ) * this.cellSize * 1000f))))
         {
             UnityEngine.Debug.LogWarning("Possible numerical imprecision. Consider adjusting tileSize and/or cellSize");
         }
         Int3 rhs = (Int3)(new Vector3((float)(x * this.tileSizeX) * this.cellSize, 0f, (float)(z * this.tileSizeZ) * this.cellSize) + this.forcedBounds.min);
         for (int n = 0; n < verts.Length; n++)
         {
             verts[n] += rhs;
         }
     }
     TriangleMeshNode[] array = new TriangleMeshNode[navmeshTile3.tris.Length / 3];
     navmeshTile3.nodes = array;
     int graphIndex = AstarPath.active.astarData.graphs.Length;
     TriangleMeshNode.SetNavmeshHolder(graphIndex, navmeshTile3);
     int num = x + z * this.tileXCount;
     num <<= 12;
     for (int num2 = 0; num2 < array.Length; num2++)
     {
         TriangleMeshNode triangleMeshNode = new TriangleMeshNode(this.active);
         array[num2] = triangleMeshNode;
         triangleMeshNode.GraphIndex = (uint)graphIndex;
         triangleMeshNode.v0 = (navmeshTile3.tris[num2 * 3] | num);
         triangleMeshNode.v1 = (navmeshTile3.tris[num2 * 3 + 1] | num);
         triangleMeshNode.v2 = (navmeshTile3.tris[num2 * 3 + 2] | num);
         if (!Polygon.IsClockwise(triangleMeshNode.GetVertex(0), triangleMeshNode.GetVertex(1), triangleMeshNode.GetVertex(2)))
         {
             int v = triangleMeshNode.v0;
             triangleMeshNode.v0 = triangleMeshNode.v2;
             triangleMeshNode.v2 = v;
         }
         triangleMeshNode.Walkable = true;
         triangleMeshNode.Penalty = this.initialPenalty;
         triangleMeshNode.UpdatePositionFromVertices();
     }
     navmeshTile3.bbTree.RebuildFrom(array);
     this.CreateNodeConnections(navmeshTile3.nodes);
     for (int num3 = z; num3 < z + d; num3++)
     {
         for (int num4 = x; num4 < x + w; num4++)
         {
             this.tiles[num4 + num3 * this.tileXCount] = navmeshTile3;
         }
     }
     if (this.batchTileUpdate)
     {
         this.batchUpdatedTiles.Add(x + z * this.tileXCount);
     }
     else
     {
         this.ConnectTileWithNeighbours(navmeshTile3);
     }
     TriangleMeshNode.SetNavmeshHolder(graphIndex, null);
     graphIndex = AstarPath.active.astarData.GetGraphIndex(this);
     for (int num5 = 0; num5 < array.Length; num5++)
     {
         array[num5].GraphIndex = (uint)graphIndex;
     }
 }
Ejemplo n.º 13
0
 public override void DeserializeExtraInfo(GraphSerializationContext ctx)
 {
     BinaryReader reader = ctx.reader;
     this.tileXCount = reader.ReadInt32();
     if (this.tileXCount < 0)
     {
         return;
     }
     this.tileZCount = reader.ReadInt32();
     this.tiles = new RecastGraph.NavmeshTile[this.tileXCount * this.tileZCount];
     TriangleMeshNode.SetNavmeshHolder(ctx.graphIndex, this);
     for (int i = 0; i < this.tileZCount; i++)
     {
         for (int j = 0; j < this.tileXCount; j++)
         {
             int num = j + i * this.tileXCount;
             int num2 = reader.ReadInt32();
             if (num2 < 0)
             {
                 throw new Exception("Invalid tile coordinates (x < 0)");
             }
             int num3 = reader.ReadInt32();
             if (num3 < 0)
             {
                 throw new Exception("Invalid tile coordinates (z < 0)");
             }
             if (num2 != j || num3 != i)
             {
                 this.tiles[num] = this.tiles[num3 * this.tileXCount + num2];
             }
             else
             {
                 RecastGraph.NavmeshTile navmeshTile = new RecastGraph.NavmeshTile();
                 navmeshTile.x = num2;
                 navmeshTile.z = num3;
                 navmeshTile.w = reader.ReadInt32();
                 navmeshTile.d = reader.ReadInt32();
                 navmeshTile.bbTree = new BBTree();
                 this.tiles[num] = navmeshTile;
                 int num4 = reader.ReadInt32();
                 if (num4 % 3 != 0)
                 {
                     throw new Exception("Corrupt data. Triangle indices count must be divisable by 3. Got " + num4);
                 }
                 navmeshTile.tris = new int[num4];
                 for (int k = 0; k < navmeshTile.tris.Length; k++)
                 {
                     navmeshTile.tris[k] = reader.ReadInt32();
                 }
                 navmeshTile.verts = new Int3[reader.ReadInt32()];
                 for (int l = 0; l < navmeshTile.verts.Length; l++)
                 {
                     navmeshTile.verts[l] = new Int3(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32());
                 }
                 int num5 = reader.ReadInt32();
                 navmeshTile.nodes = new TriangleMeshNode[num5];
                 num <<= 12;
                 for (int m = 0; m < navmeshTile.nodes.Length; m++)
                 {
                     TriangleMeshNode triangleMeshNode = new TriangleMeshNode(this.active);
                     navmeshTile.nodes[m] = triangleMeshNode;
                     triangleMeshNode.DeserializeNode(ctx);
                     triangleMeshNode.v0 = (navmeshTile.tris[m * 3] | num);
                     triangleMeshNode.v1 = (navmeshTile.tris[m * 3 + 1] | num);
                     triangleMeshNode.v2 = (navmeshTile.tris[m * 3 + 2] | num);
                     triangleMeshNode.UpdatePositionFromVertices();
                 }
                 navmeshTile.bbTree.RebuildFrom(navmeshTile.nodes);
             }
         }
     }
 }
Ejemplo n.º 14
0
 public bool ContainsPoint(TriangleMeshNode node, Vector3 pos)
 {
     return Polygon.IsClockwise((Vector3)this.GetVertex(node.v0), (Vector3)this.GetVertex(node.v1), pos) && Polygon.IsClockwise((Vector3)this.GetVertex(node.v1), (Vector3)this.GetVertex(node.v2), pos) && Polygon.IsClockwise((Vector3)this.GetVertex(node.v2), (Vector3)this.GetVertex(node.v0), pos);
 }
Ejemplo n.º 15
0
 private RecastGraph.NavmeshTile CreateTile(Voxelize vox, VoxelMesh mesh, int x, int z)
 {
     if (mesh.tris == null)
     {
         throw new ArgumentNullException("mesh.tris");
     }
     if (mesh.verts == null)
     {
         throw new ArgumentNullException("mesh.verts");
     }
     RecastGraph.NavmeshTile navmeshTile = new RecastGraph.NavmeshTile();
     navmeshTile.x = x;
     navmeshTile.z = z;
     navmeshTile.w = 1;
     navmeshTile.d = 1;
     navmeshTile.tris = mesh.tris;
     navmeshTile.verts = mesh.verts;
     navmeshTile.bbTree = new BBTree();
     if (navmeshTile.tris.Length % 3 != 0)
     {
         throw new ArgumentException("Indices array's length must be a multiple of 3 (mesh.tris)");
     }
     if (navmeshTile.verts.Length >= 4095)
     {
         throw new ArgumentException("Too many vertices per tile (more than " + 4095 + ").\nTry enabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* Inspector");
     }
     Dictionary<Int3, int> dictionary = this.cachedInt3_int_dict;
     dictionary.Clear();
     int[] array = new int[navmeshTile.verts.Length];
     int num = 0;
     for (int i = 0; i < navmeshTile.verts.Length; i++)
     {
         if (!dictionary.ContainsKey(navmeshTile.verts[i]))
         {
             dictionary.Add(navmeshTile.verts[i], num);
             array[i] = num;
             navmeshTile.verts[num] = navmeshTile.verts[i];
             num++;
         }
         else
         {
             array[i] = dictionary[navmeshTile.verts[i]];
         }
     }
     for (int j = 0; j < navmeshTile.tris.Length; j++)
     {
         navmeshTile.tris[j] = array[navmeshTile.tris[j]];
     }
     Int3[] array2 = new Int3[num];
     for (int k = 0; k < num; k++)
     {
         array2[k] = navmeshTile.verts[k];
     }
     navmeshTile.verts = array2;
     TriangleMeshNode[] array3 = new TriangleMeshNode[navmeshTile.tris.Length / 3];
     navmeshTile.nodes = array3;
     int graphIndex = AstarPath.active.astarData.graphs.Length;
     TriangleMeshNode.SetNavmeshHolder(graphIndex, navmeshTile);
     int num2 = x + z * this.tileXCount;
     num2 <<= 12;
     for (int l = 0; l < array3.Length; l++)
     {
         TriangleMeshNode triangleMeshNode = new TriangleMeshNode(this.active);
         array3[l] = triangleMeshNode;
         triangleMeshNode.GraphIndex = (uint)graphIndex;
         triangleMeshNode.v0 = (navmeshTile.tris[l * 3] | num2);
         triangleMeshNode.v1 = (navmeshTile.tris[l * 3 + 1] | num2);
         triangleMeshNode.v2 = (navmeshTile.tris[l * 3 + 2] | num2);
         if (!Polygon.IsClockwise(triangleMeshNode.GetVertex(0), triangleMeshNode.GetVertex(1), triangleMeshNode.GetVertex(2)))
         {
             int v = triangleMeshNode.v0;
             triangleMeshNode.v0 = triangleMeshNode.v2;
             triangleMeshNode.v2 = v;
         }
         triangleMeshNode.Walkable = true;
         triangleMeshNode.Penalty = this.initialPenalty;
         triangleMeshNode.UpdatePositionFromVertices();
     }
     navmeshTile.bbTree.RebuildFrom(array3);
     this.CreateNodeConnections(navmeshTile.nodes);
     TriangleMeshNode.SetNavmeshHolder(graphIndex, null);
     return navmeshTile;
 }
Ejemplo n.º 16
0
		public override void DeserializeExtraInfo (GraphSerializationContext ctx)
		{
			
			uint graphIndex = (uint)active.astarData.GetGraphIndex(this);
			TriangleMeshNode.SetNavmeshHolder ((int)graphIndex,this);
			
			int c1 = ctx.reader.ReadInt32();
			int c2 = ctx.reader.ReadInt32();
			
			if (c1 == -1) {
				nodes = new TriangleMeshNode[0];
				_vertices = new Int3[0];
				originalVertices = new Vector3[0];
			}
			
			nodes = new TriangleMeshNode[c1];
			_vertices = new Int3[c2];
			originalVertices = new Vector3[c2];
			
			for (int i=0;i<c2;i++) {
				_vertices[i] = new Int3(ctx.reader.ReadInt32(), ctx.reader.ReadInt32(), ctx.reader.ReadInt32());
				originalVertices[i] = new Vector3(ctx.reader.ReadSingle(), ctx.reader.ReadSingle(), ctx.reader.ReadSingle());
			}
			
			bbTree = new BBTree(this);
			
			for (int i=0;i<c1;i++) {
				nodes[i] = new TriangleMeshNode(active);
				TriangleMeshNode node = nodes[i];
				node.DeserializeNode(ctx);
				node.GraphIndex = graphIndex;
				node.UpdatePositionFromVertices();
				bbTree.Insert (node);
			}
		}
Ejemplo n.º 17
0
		/** Create a tile at tile index \a x , \a z from the mesh.
		 * \warning This implementation is not thread safe. It uses cached variables to improve performance
		 */
		NavmeshTile CreateTile (Voxelize vox, VoxelMesh mesh, int x, int z) {
			
			if (mesh.tris == null) throw new System.ArgumentNullException ("The mesh must be valid. tris is null.");
			if (mesh.verts == null) throw new System.ArgumentNullException ("The mesh must be valid. verts is null.");
			
			//Create a new navmesh tile and assign its settings
			NavmeshTile tile = new NavmeshTile();
			
			tile.x = x;
			tile.z = z;
			tile.w = 1;
			tile.d = 1;
			tile.tris = mesh.tris;
			tile.verts = mesh.verts;
			tile.bbTree = new BBTree(tile);
			
			if (tile.tris.Length % 3 != 0) throw new System.ArgumentException ("Indices array's length must be a multiple of 3 (mesh.tris)");
			
			if (tile.verts.Length >= VertexIndexMask) throw new System.ArgumentException ("Too many vertices per tile (more than "+VertexIndexMask+")." +
				"\nTry enabling ASTAR_RECAST_LARGER_TILES under the 'Optimizations' tab in the A* Inspector");
			
			//Dictionary<Int3, int> firstVerts = new Dictionary<Int3, int> ();
			Dictionary<Int3, int> firstVerts = cachedInt3_int_dict;
			firstVerts.Clear();
			
			int[] compressedPointers = new int[tile.verts.Length];
			
			int count = 0;
			for (int i=0;i<tile.verts.Length;i++) {
				try {
					firstVerts.Add (tile.verts[i], count);
					compressedPointers[i] = count;
					tile.verts[count] = tile.verts[i];
					count++;
				} catch {
					//There are some cases, rare but still there, that vertices are identical
					compressedPointers[i] = firstVerts[tile.verts[i]];
				}
			}
			
			for (int i=0;i<tile.tris.Length;i++) {
				tile.tris[i] = compressedPointers[tile.tris[i]];
			}
			
			Int3[] compressed = new Int3[count];
			for (int i=0;i<count;i++) compressed[i] = tile.verts[i];
			
			tile.verts = compressed;
			
			TriangleMeshNode[] nodes = new TriangleMeshNode[tile.tris.Length/3];
			tile.nodes = nodes;
			
			//Here we are faking a new graph
			//The tile is not added to any graphs yet, but to get the position querys from the nodes
			//to work correctly (not throw exceptions because the tile is not calculated) we fake a new graph
			//and direct the position queries directly to the tile
			int graphIndex = AstarPath.active.astarData.graphs.Length;
			
			TriangleMeshNode.SetNavmeshHolder (graphIndex, tile);
			
			//This index will be ORed to the triangle indices
			int tileIndex = x + z*tileXCount;
			tileIndex <<= TileIndexOffset;
			
			//Create nodes and assign triangle indices
			for (int i=0;i<nodes.Length;i++) {
				TriangleMeshNode node = new TriangleMeshNode(active);
				nodes[i] = node;
				node.GraphIndex = (uint)graphIndex;
				node.v0 = tile.tris[i*3+0] | tileIndex;
				node.v1 = tile.tris[i*3+1] | tileIndex;
				node.v2 = tile.tris[i*3+2] | tileIndex;
				
				//Degenerate triangles might ocurr, but they will not cause any large troubles anymore
				//if (Polygon.IsColinear (node.GetVertex(0), node.GetVertex(1), node.GetVertex(2))) {
				//	Debug.Log ("COLINEAR!!!!!!");
				//}
				
				//Make sure the triangle is clockwise
				if (!Polygon.IsClockwise (node.GetVertex(0), node.GetVertex(1), node.GetVertex(2))) {
					int tmp = node.v0;
					node.v0 = node.v2;
					node.v2 = tmp;
				}
				
				node.Walkable = true;
				node.Penalty = initialPenalty;
				node.UpdatePositionFromVertices();
				tile.bbTree.Insert (node);
			}
			
			CreateNodeConnections (tile.nodes);
			
			//Remove the fake graph
			TriangleMeshNode.SetNavmeshHolder (graphIndex, null);
			
			return tile;
		}
Ejemplo n.º 18
0
		/** Create connections between all nodes.
		 * \warning This implementation is not thread safe. It uses cached variables to improve performance
		 */
		void CreateNodeConnections (TriangleMeshNode[] nodes) {
			
			List<MeshNode> connections = Pathfinding.Util.ListPool<MeshNode>.Claim (); //new List<MeshNode>();
			List<uint> connectionCosts = Pathfinding.Util.ListPool<uint>.Claim (); //new List<uint>();
			
			Dictionary<Int2,int> nodeRefs = cachedInt2_int_dict;
			nodeRefs.Clear();
			
			//Build node neighbours
			for (int i=0;i<nodes.Length;i++) {
				
				TriangleMeshNode node = nodes[i];
				
				int av = node.GetVertexCount ();
				
				for (int a=0;a<av;a++) {
					
					//Recast can in some very special cases generate degenerate triangles which are simply lines
					//In that case, duplicate keys might be added and thus an exception will be thrown
					//It is safe to ignore the second edge though... I think (only found one case where this happens)
					try {
						nodeRefs.Add (new Int2 (node.GetVertexIndex(a), node.GetVertexIndex ((a+1) % av)), i);
					} catch (System.Exception) {
					}
				}
			}
			
			
			for (int i=0;i<nodes.Length;i++) {
				
				TriangleMeshNode node = nodes[i];
				
				connections.Clear ();
				connectionCosts.Clear ();
				
				int av = node.GetVertexCount ();
				
				for (int a=0;a<av;a++) {
					int first = node.GetVertexIndex(a);
					int second = node.GetVertexIndex((a+1) % av);
					int connNode;
					
					if (nodeRefs.TryGetValue (new Int2 (second, first), out connNode)) {
						TriangleMeshNode other = nodes[connNode];
						
						int bv = other.GetVertexCount ();
						
						for (int b=0;b<bv;b++) {
							/** \todo This will fail on edges which are only partially shared */
							if (other.GetVertexIndex (b) == second && other.GetVertexIndex ((b+1) % bv) == first) {
								uint cost = (uint)(node.position - other.position).costMagnitude;									
								connections.Add (other);
								connectionCosts.Add (cost);
								break;
							}
						}
					}
				}
				
				node.connections = connections.ToArray ();
				node.connectionCosts = connectionCosts.ToArray ();
			}
			
			Pathfinding.Util.ListPool<MeshNode>.Release (connections);
			Pathfinding.Util.ListPool<uint>.Release (connectionCosts);
		}
Ejemplo n.º 19
0
		/** Returns if the point is inside the node in XZ space */
		public bool ContainsPoint (TriangleMeshNode node, Vector3 pos) {
			if (	Polygon.IsClockwise ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1], pos)
			    && 	Polygon.IsClockwise ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2], pos)
			    && 	Polygon.IsClockwise ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0], pos)) {
				return true;
			}
			return false;
		}
Ejemplo n.º 20
0
		public void ReplaceTile (int x, int z, int w, int d, Int3[] verts, int[] tris, bool worldSpace) {
			
			if(x + w > tileXCount || z+d > tileZCount || x < 0 || z < 0) {
				throw new System.ArgumentException ("Tile is placed at an out of bounds position or extends out of the graph bounds ("+x+", " + z + " [" + w + ", " + d+ "] " + tileXCount + " " + tileZCount + ")");
			}
			
			if (w < 1 || d < 1) throw new System.ArgumentException ("width and depth must be greater or equal to 1");
			
			//Remove previous tiles
			for (int cz=z; cz < z+d;cz++) {
				for (int cx=x; cx < x+w;cx++) {
					
					NavmeshTile otile = tiles[cx + cz*tileXCount];
					if (otile == null) continue;
					
					//Remove old tile connections
					RemoveConnectionsFromTile (otile);
					
					for (int i=0;i<otile.nodes.Length;i++) {
						otile.nodes[i].Destroy();
					}
					
					for (int qz=otile.z; qz < otile.z+otile.d;qz++) {
						for (int qx=otile.x; qx < otile.x+otile.w;qx++) {
							NavmeshTile qtile = tiles[qx + qz*tileXCount];
							if (qtile == null || qtile != otile) throw new System.Exception("This should not happen");
							
							if (qz < z || qz >= z+d || qx < x || qx >= x+w) {
								//if out of this tile's bounds, replace with empty tile
								tiles[qx + qz*tileXCount] = NewEmptyTile(qx,qz);
								
								if (batchTileUpdate) {
									batchUpdatedTiles.Add (qx + qz*tileXCount);
								}
							} else {
								//Will be replaced by the new tile
								tiles[qx + qz*tileXCount] = null;
							}
						}
					}
				}
			}
			
			//Create a new navmesh tile and assign its settings
			NavmeshTile tile = new NavmeshTile();
			
			tile.x = x;
			tile.z = z;
			tile.w = w;
			tile.d = d;
			tile.tris = tris;
			tile.verts = verts;
			tile.bbTree = new BBTree(tile);
			
			if (tile.tris.Length % 3 != 0) throw new System.ArgumentException ("Triangle array's length must be a multiple of 3 (tris)");
			
			if (tile.verts.Length > 0xFFFF) throw new System.ArgumentException ("Too many vertices per tile (more than 65535)");
			
			if (!worldSpace) {
				if (!Mathf.Approximately (x*tileSizeX*cellSize*Int3.FloatPrecision, (float)System.Math.Round(x*tileSizeX*cellSize*Int3.FloatPrecision))) Debug.LogWarning ("Possible numerical imprecision. Consider adjusting tileSize and/or cellSize");
				if (!Mathf.Approximately (z*tileSizeZ*cellSize*Int3.FloatPrecision, (float)System.Math.Round(z*tileSizeZ*cellSize*Int3.FloatPrecision))) Debug.LogWarning ("Possible numerical imprecision. Consider adjusting tileSize and/or cellSize");
			
				Int3 offset = (Int3)(new Vector3((x * tileSizeX * cellSize),0,(z * tileSizeZ * cellSize)) + forcedBounds.min);
				
				for (int i=0;i<verts.Length;i++) {
					verts[i] += offset;
				}
				
			}
			
			TriangleMeshNode[] nodes = new TriangleMeshNode[tile.tris.Length/3];
			tile.nodes = nodes;
			
			//Here we are faking a new graph
			//The tile is not added to any graphs yet, but to get the position querys from the nodes
			//to work correctly (not throw exceptions because the tile is not calculated) we fake a new graph
			//and direct the position queries directly to the tile
			int graphIndex = AstarPath.active.astarData.graphs.Length;
			
			TriangleMeshNode.SetNavmeshHolder (graphIndex, tile);
			
			//This index will be ORed to the triangle indices
			int tileIndex = x + z*tileXCount;
			tileIndex <<= TileIndexOffset;
			
			//Create nodes and assign triangle indices
			for (int i=0;i<nodes.Length;i++) {
				TriangleMeshNode node = new TriangleMeshNode(active);
				nodes[i] = node;
				node.GraphIndex = (uint)graphIndex;
				node.v0 = tile.tris[i*3+0] | tileIndex;
				node.v1 = tile.tris[i*3+1] | tileIndex;
				node.v2 = tile.tris[i*3+2] | tileIndex;
				
				//Degenerate triangles might ocurr, but they will not cause any large troubles anymore
				//if (Polygon.IsColinear (node.GetVertex(0), node.GetVertex(1), node.GetVertex(2))) {
				//	Debug.Log ("COLINEAR!!!!!!");
				//}
				
				//Make sure the triangle is clockwise
				if (!Polygon.IsClockwise (node.GetVertex(0), node.GetVertex(1), node.GetVertex(2))) {
					int tmp = node.v0;
					node.v0 = node.v2;
					node.v2 = tmp;
				}
				
				node.Walkable = true;
				node.Penalty = initialPenalty;
				node.UpdatePositionFromVertices();
				
				tile.bbTree.Insert (node);
			}
			
			CreateNodeConnections (tile.nodes);
			
			//Set tile
			for (int cz=z; cz < z+d;cz++) {
				for (int cx=x; cx < x+w;cx++) {
					tiles[cx + cz*tileXCount] = tile;
				}
			}
			
			if (batchTileUpdate) {
				batchUpdatedTiles.Add (x + z*tileXCount);
			} else {
				ConnectTileWithNeighbours(tile);
				/*if (x > 0) ConnectTiles (tiles[(x-1) + z*tileXCount], tile);
				if (z > 0) ConnectTiles (tiles[x + (z-1)*tileXCount], tile);
				if (x < tileXCount-1) ConnectTiles (tiles[(x+1) + z*tileXCount], tile);
				if (z < tileZCount-1) ConnectTiles (tiles[x + (z+1)*tileXCount], tile);*/
			}
			
			//Remove the fake graph
			TriangleMeshNode.SetNavmeshHolder (graphIndex, null);
			
			//Real graph index
			//TODO, could this step be changed for this function, is a fake index required?
			graphIndex = AstarPath.active.astarData.GetGraphIndex (this);
			
			for (int i=0;i<nodes.Length;i++) nodes[i].GraphIndex = (uint)graphIndex;			
			
		}
Ejemplo n.º 21
0
		/** Generates a navmesh. Based on the supplied vertices and triangles. Memory usage is about O(n) */
		public void GenerateNodes (Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices) {
			
			
			if (vectorVertices.Length == 0 || triangles.Length == 0) {
				originalVertices = vectorVertices;
				vertices = new Int3[0];
				//graph.CreateNodes (0);
				nodes = new TriangleMeshNode[0];
				return;
			}
			
			vertices = new Int3[vectorVertices.Length];
			
			//Backup the original vertices
			//for (int i=0;i<vectorVertices.Length;i++) {
			//	vectorVertices[i] = graph.matrix.MultiplyPoint (vectorVertices[i]);
			//}
			
			int c = 0;
			/*int maxX = 0;
			int maxZ = 0;
			
			//Almost infinity
			int minX = 0xFFFFFFF;
			int minZ = 0xFFFFFFF;*/
			
			for (int i=0;i<vertices.Length;i++) {
				vertices[i] = (Int3)matrix.MultiplyPoint3x4 (vectorVertices[i]);
				/*maxX = Mathfx.Max (vertices[i].x, maxX);
				maxZ = Mathfx.Max (vertices[i].z, maxZ);
				minX = Mathfx.Min (vertices[i].x, minX);
				minZ = Mathfx.Min (vertices[i].z, minZ);*/
			}
			
			//maxX = maxX-minX;
			//maxZ = maxZ-minZ;
			
			Dictionary<Int3,int> hashedVerts = new Dictionary<Int3,int> ();
			
			int[] newVertices = new int[vertices.Length];
				
			for (int i=0;i<vertices.Length-1;i++) {
				
				//int hash = Mathfx.ComputeVertexHash (vertices[i].x,vertices[i].y,vertices[i].z);
				
				//(vertices[i].x-minX)+(vertices[i].z-minX)*maxX+vertices[i].y*maxX*maxZ;
				//if (sortedVertices[i] != sortedVertices[i+1]) {
				if (!hashedVerts.ContainsKey (vertices[i])) {
					newVertices[c] = i;
					hashedVerts.Add (vertices[i], c);
					c++;
				}// else {
					//Debug.Log ("Hash Duplicate "+hash+" "+vertices[i].ToString ());
				//}
			}
			
			newVertices[c] = vertices.Length-1;
			
			//int hash2 = (newVertices[c].x-minX)+(newVertices[c].z-minX)*maxX+newVertices[c].y*maxX*maxZ;
			//int hash2 = Mathfx.ComputeVertexHash (newVertices[c].x,newVertices[c].y,newVertices[c].z);
			if (!hashedVerts.ContainsKey (vertices[newVertices[c]])) {
				
				hashedVerts.Add (vertices[newVertices[c]], c);
				c++;
			}
			
			for (int x=0;x<triangles.Length;x++) {
				Int3 vertex = vertices[triangles[x]];
				
				//int hash3 = (vertex.x-minX)+(vertex.z-minX)*maxX+vertex.y*maxX*maxZ;
				//int hash3 = Mathfx.ComputeVertexHash (vertex.x,vertex.y,vertex.z);
				//for (int y=0;y<newVertices.Length;y++) {
				triangles[x] = hashedVerts[vertex];
			}
			
			/*for (int i=0;i<triangles.Length;i += 3) {
				
				Vector3 offset = Vector3.forward*i*0.01F;
				Debug.DrawLine (newVertices[triangles[i]]+offset,newVertices[triangles[i+1]]+offset,Color.blue);
				Debug.DrawLine (newVertices[triangles[i+1]]+offset,newVertices[triangles[i+2]]+offset,Color.blue);
				Debug.DrawLine (newVertices[triangles[i+2]]+offset,newVertices[triangles[i]]+offset,Color.blue);
			}*/
			
			//Debug.Log ("NavMesh - Old vertice count "+vertices.Length+", new vertice count "+c+" "+maxX+" "+maxZ+" "+maxX*maxZ);
			
			Int3[] totalIntVertices = vertices;
			vertices = new Int3[c];
			originalVertices = new Vector3[c];
			for (int i=0;i<c;i++) {
				
				vertices[i] = totalIntVertices[newVertices[i]];//(Int3)graph.matrix.MultiplyPoint (vectorVertices[i]);
				originalVertices[i] = (Vector3)vectorVertices[newVertices[i]];//vectorVertices[newVertices[i]];
			}
			
			//graph.CreateNodes (triangles.Length/3);//new Node[triangles.Length/3];
			nodes = new TriangleMeshNode[triangles.Length/3];
			
			for (int i=0;i<nodes.Length;i++) {
				
				nodes[i] = new TriangleMeshNode(active);
				TriangleMeshNode node = nodes[i];//new MeshNode ();
				
				node.Penalty = initialPenalty;
				node.Walkable = true;
				
				
				node.v0 = triangles[i*3];
				node.v1 = triangles[i*3+1];
				node.v2 = triangles[i*3+2];
				
				if (!Polygon.IsClockwise (vertices[node.v0],vertices[node.v1],vertices[node.v2])) {
					//Debug.DrawLine (vertices[node.v0],vertices[node.v1],Color.red);
					//Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.red);
					//Debug.DrawLine (vertices[node.v2],vertices[node.v0],Color.red);
					
					int tmp = node.v0;
					node.v0 = node.v2;
					node.v2 = tmp;
				}
				
				if (Polygon.IsColinear (vertices[node.v0],vertices[node.v1],vertices[node.v2])) {
					Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.red);
				}
				
				// Make sure position is correctly set
				node.UpdatePositionFromVertices();
			}
			
			List<MeshNode> connections = new List<MeshNode> ();
			List<uint> connectionCosts = new List<uint> ();
			
			int identicalError = 0;
			
			for (int i=0;i<triangles.Length;i+=3) {
				
				connections.Clear ();
				connectionCosts.Clear ();
				
				//Int3 indices = new Int3(triangles[i],triangles[i+1],triangles[i+2]);
				
				TriangleMeshNode node = nodes[i/3];
				
				for (int x=0;x<triangles.Length;x+=3) {
					
					if (x == i) {
						continue;
					}
					
					int count = 0;
					if (triangles[x] 	== 	triangles[i]) { count++; }
					if (triangles[x+1]	== 	triangles[i]) { count++; }
					if (triangles[x+2] 	== 	triangles[i]) { count++; }
					if (triangles[x] 	== 	triangles[i+1]) { count++; }
					if (triangles[x+1] 	== 	triangles[i+1]) { count++; }
					if (triangles[x+2] 	== 	triangles[i+1]) { count++; }
					if (triangles[x] 	== 	triangles[i+2]) { count++; }
					if (triangles[x+1] 	== 	triangles[i+2]) { count++; }
					if (triangles[x+2] 	== 	triangles[i+2]) { count++; }
					
					if (count >= 3) {
						identicalError++;
						Debug.DrawLine ((Vector3)vertices[triangles[x]],(Vector3)vertices[triangles[x+1]],Color.red);
						Debug.DrawLine ((Vector3)vertices[triangles[x]],(Vector3)vertices[triangles[x+2]],Color.red);
						Debug.DrawLine ((Vector3)vertices[triangles[x+2]],(Vector3)vertices[triangles[x+1]],Color.red);
					}
					
					if (count == 2) {
						GraphNode other = nodes[x/3];
						connections.Add (other as MeshNode);
						connectionCosts.Add ((uint)(node.position-other.position).costMagnitude);
					}
				}
				
				node.connections = connections.ToArray ();
				node.connectionCosts = connectionCosts.ToArray ();
			}
			
			if (identicalError > 0) {
				Debug.LogError ("One or more triangles are identical to other triangles, this is not a good thing to have in a navmesh\nIncreasing the scale of the mesh might help\nNumber of triangles with error: "+identicalError+"\n");
			}
			RebuildBBTree (this);
			
#if ASTARDEBUG
			for (int i=0;i<nodes.Length;i++) {
				TriangleMeshNode node = nodes[i] as TriangleMeshNode;
				
				float a1 = Polygon.TriangleArea2 ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],(Vector3)vertices[node.v2]);
				
				long a2 = Polygon.TriangleArea2 (vertices[node.v0],vertices[node.v1],vertices[node.v2]);
				if (a1 * a2 < 0) Debug.LogError (a1+ " " + a2);
				
				
				if (Polygon.IsClockwise (vertices[node.v0],vertices[node.v1],vertices[node.v2])) {
					Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.green);
					Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.green);
					Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.green);
				} else {
					Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.red);
					Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.red);
				}
			}
#endif
			//Debug.Log ("Graph Generation - NavMesh - Time to compute graph "+((Time.realtimeSinceStartup-startTime)*1000F).ToString ("0")+"ms");
		}
Ejemplo n.º 22
0
 public void UpdateFunnelCorridor(int splitIndex, TriangleMeshNode prefix)
 {
     if (splitIndex > 0)
     {
         this.nodes.RemoveRange(0, splitIndex - 1);
         this.nodes[0] = prefix;
     }
     else
     {
         this.nodes.Insert(0, prefix);
     }
     this.left.Clear();
     this.right.Clear();
     this.left.Add(this.exactStart);
     this.right.Add(this.exactStart);
     for (int i = 0; i < this.nodes.Count - 1; i++)
     {
         this.nodes[i].GetPortal(this.nodes[i + 1], this.left, this.right, false);
     }
     this.left.Add(this.exactEnd);
     this.right.Add(this.exactEnd);
 }