Pathfinding.NavMeshGraph.GenerateNodes C# (CSharp) Method

GenerateNodes() public method

public GenerateNodes ( Vector3 vectorVertices, int triangles, Vector3 &originalVertices, Int3 &vertices ) : void
vectorVertices UnityEngine.Vector3
triangles int
originalVertices UnityEngine.Vector3
vertices Int3
return void
		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");
		}
		

Usage Example

Ejemplo n.º 1
0
        public void ScanCRecast()
        {
            //#if (!UNITY_EDITOR && !UNITY_STANDALONE_OSX && !UNITY_STANDALONE_WIN) || UNITY_WEBPLAYER || UNITY_IPHONE || UNITY_ANDROID || UNITY_DASHBOARD_WIDGET || UNITY_XBOX360 || UNITY_PS3
        #if (UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN)
            System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
            myProcess.StartInfo.FileName = GetRecastPath();             //"/Users/arong/Recast/build/Debug/Recast";
            //System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo ();
            //startInfo.UseShellExecute = true;
            myProcess.StartInfo.UseShellExecute        = false;
            myProcess.StartInfo.RedirectStandardInput  = true;
            myProcess.StartInfo.RedirectStandardOutput = true;
            myProcess.StartInfo.Arguments = "";

            MeshFilter[] filters;
            ExtraMesh[]  extraMeshes;
            //Get all meshes which should be used
            CollectMeshes(out filters, out extraMeshes);

            Vector3[] inputVerts;
            int[]     inputTris;
            //Get polygon soup from meshes
            Voxelize.CollectMeshes(filters, extraMeshes, forcedBounds, out inputVerts, out inputTris);

            //Bild .obj file
            System.Text.StringBuilder arguments = new System.Text.StringBuilder();
            arguments.Append("o recastMesh.obj\n");
            for (int i = 0; i < inputVerts.Length; i++)
            {
                arguments.Append("v " + inputVerts[i].x.ToString("0.000") + " ").Append(inputVerts[i].y.ToString("0.000") + " ").Append(inputVerts[i].z.ToString("0.000"));
                arguments.Append("\n");
            }

            //Build .obj file tris
            for (int i = 0; i < inputTris.Length - 2; i += 3)
            {
                arguments.Append("f " + (inputTris[i] + 1) + "//0 ").Append((inputTris[i + 1] + 1) + "//0 ").Append((inputTris[i + 2] + 1) + "//0");
                //Debug.DrawLine (inputVerts[inputTris[i]],inputVerts[inputTris[i+1]],Color.red);
                //Debug.DrawLine (inputVerts[inputTris[i+1]],inputVerts[inputTris[i+2]],Color.red);
                //Debug.DrawLine (inputVerts[inputTris[i+2]],inputVerts[inputTris[i]],Color.red);

                arguments.Append("\n");
            }

            string tmpPath = System.IO.Path.GetTempPath();
            tmpPath += "recastMesh.obj";

            try {
                using (System.IO.StreamWriter outfile = new System.IO.StreamWriter(tmpPath)) {
                    outfile.Write(arguments.ToString());
                }

                myProcess.StartInfo.Arguments = tmpPath
                                                + "\n" + cellSize + "\n" +
                                                cellHeight + "\n" +
                                                walkableHeight + "\n" +
                                                walkableClimb + "\n" +
                                                maxSlope + "\n" +
                                                maxEdgeLength + "\n" +
                                                contourMaxError + "\n" +
                                                regionMinSize + "\n" +
                                                characterRadius;


                /*		public int erosionRadius = 2; /< Voxels to erode away from the edges of the mesh /
                 * public float contourMaxError = 2F; /< Max distance from simplified edge to real edge /
                 *
                 * public float cellSize = 0.5F; /< Voxel sample size (x,z) /
                 * public float cellHeight = 0.4F; /< Voxel sample size (y) /
                 * public float walkableHeight = 2F; /< Character height/
                 * public float walkableClimb = 0.5F; /< Height the character can climb /
                 * public float maxSlope = 30; /< Max slope in degrees the character can traverse /
                 * public float maxEdgeLength = 20; /< Longer edges will be subdivided. Reducing this value can im
                 * public bool useCRecast = true;
                 * public bool includeOutOfBounds = false;*/

                myProcess.Start();
                System.IO.StreamReader sOut = myProcess.StandardOutput;

                //string result = sOut.ReadToEnd ();
                //Debug.Log (result);
                //return;

                bool      failed            = false;
                bool      startedVerts      = false;
                int       readVerts         = 0;
                bool      startedTris       = false;
                int       vCount            = -1;
                int       readTris          = 0;
                int       trisCount         = 0;
                Vector3[] verts             = null;
                int[]     tris              = null;
                int       internalVertCount = 0;

                Vector3 bmin = Vector3.zero;

                float cs = 1F;
                float ch = 1F;

                while (sOut.Peek() >= 0)
                {
                    string line = sOut.ReadLine();
                    int    resultInt;

                    if (line == "")
                    {
                        continue;
                    }

                    if (!int.TryParse(line, out resultInt))
                    {
                        //Debug.Log ("Syntax Error at '"+line+"'");
                        failed = true;
                        break;
                    }

                    if (!startedVerts)
                    {
                        verts = new Vector3[resultInt];

                        if (resultInt == 0)
                        {
                            failed = true;
                            break;
                        }

                        bmin.x = float.Parse(sOut.ReadLine());
                        bmin.y = float.Parse(sOut.ReadLine());
                        bmin.z = float.Parse(sOut.ReadLine());
                        cs     = float.Parse(sOut.ReadLine());
                        ch     = float.Parse(sOut.ReadLine());

                        startedVerts = true;
                        //Debug.Log ("Starting Reading "+resultInt+" verts "+bmin.ToString ()+" - "+cs+" * "+ch);
                    }
                    else if (readVerts < verts.Length)
                    {
                        resultInt *= 1;
                        if (internalVertCount == 0)
                        {
                            verts[readVerts].x = resultInt * cs + bmin.x;
                        }
                        else if (internalVertCount == 1)
                        {
                            verts[readVerts].y = resultInt * ch + bmin.y;
                        }
                        else
                        {
                            verts[readVerts].z = resultInt * cs + bmin.z;
                        }

                        internalVertCount++;

                        if (internalVertCount == 3)
                        {
                            internalVertCount = 0;
                            readVerts++;
                        }
                    }
                    else if (!startedTris)
                    {
                        trisCount   = resultInt;
                        startedTris = true;
                    }
                    else if (vCount == -1)
                    {
                        vCount = resultInt;
                        tris   = new int[trisCount * vCount];
                        //Debug.Log ("Starting Reading "+trisCount+" - "+tris.Length+" tris at vertsCount "+readVerts);
                        //Debug.Log ("Max vertices per polygon: "+vCount);
                    }
                    else if (readTris < tris.Length)
                    {
                        tris[readTris] = resultInt;
                        readTris++;
                    }
                }

                if (!myProcess.HasExited)
                {
                    myProcess.Kill();
                }

                sOut.Close();
                myProcess.Close();

                if (failed)
                {
                    return;
                }

                matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one);

                NavMeshGraph.GenerateNodes(this, verts, tris, out _vectorVertices, out _vertices);
            } finally {
                //Debug.Log (tmpPath);
                System.IO.File.Delete(tmpPath);
            }
        #else
            Debug.LogError("The C++ version of recast can only be used in editor or standalone mode, I'm sure it cannot be used in the webplayer, but other platforms are not tested yet\n" +
                           "If you are in the Unity Editor, try switching Platform to Standalone just when scanning, scanned graphs can be cached to enable them to be used in a webplayer");
            _vectorVertices = new Vector3[0];
            _vertices       = new Int3[0];
            nodes           = new Node[0];
        #endif
        }
All Usage Examples Of Pathfinding.NavMeshGraph::GenerateNodes