/** Generates a navmesh. Based on the supplied vertices and triangles. Memory usage is about O(n) */
public static void GenerateNodes (NavGraph graph, Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices) {
if (!(graph is INavmesh)) {
Debug.LogError ("The specified graph does not implement interface 'INavmesh'");
originalVertices = vectorVertices;
vertices = new Int3[0];
graph.nodes = graph.CreateNodes (0);
return;
}
if (vectorVertices.Length == 0 || triangles.Length == 0) {
originalVertices = vectorVertices;
vertices = new Int3[0];
graph.nodes = graph.CreateNodes (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)graph.matrix.MultiplyPoint (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] = vertices[i];//vectorVertices[newVertices[i]];
}
Node[] nodes = graph.CreateNodes (triangles.Length/3);//new Node[triangles.Length/3];
graph.nodes = nodes;
for (int i=0;i<nodes.Length;i++) {
MeshNode node = (MeshNode)nodes[i];//new MeshNode ();
node.walkable = true;
node.position = (vertices[triangles[i*3]] + vertices[triangles[i*3+1]] + vertices[triangles[i*3+2]])/3F;
node.v1 = triangles[i*3];
node.v2 = triangles[i*3+1];
node.v3 = triangles[i*3+2];
if (!Polygon.IsClockwise (vertices[node.v1],vertices[node.v2],vertices[node.v3])) {
//Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.red);
//Debug.DrawLine (vertices[node.v2],vertices[node.v3],Color.red);
//Debug.DrawLine (vertices[node.v3],vertices[node.v1],Color.red);
int tmp = node.v1;
node.v1 = node.v3;
node.v3 = tmp;
}
if (Polygon.IsColinear (vertices[node.v1],vertices[node.v2],vertices[node.v3])) {
Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.red);
Debug.DrawLine (vertices[node.v2],vertices[node.v3],Color.red);
Debug.DrawLine (vertices[node.v3],vertices[node.v1],Color.red);
}
nodes[i] = node;
}
List<Node> connections = new List<Node> ();
List<int> connectionCosts = new List<int> ();
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]);
Node 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 (vertices[triangles[x]],vertices[triangles[x+1]],Color.red);
Debug.DrawLine (vertices[triangles[x]],vertices[triangles[x+2]],Color.red);
Debug.DrawLine (vertices[triangles[x+2]],vertices[triangles[x+1]],Color.red);
}
if (count == 2) {
Node other = nodes[x/3];
connections.Add (other);
connectionCosts.Add (Mathf.RoundToInt ((node.position-other.position).magnitude));
}
}
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 (graph);
//Debug.Log ("Graph Generation - NavMesh - Time to compute graph "+((Time.realtimeSinceStartup-startTime)*1000F).ToString ("0")+"ms");
}