public GenerateGraph()
{
//get nav mesh characteristics from pre-made nav mesh. Will write script later that generates
//a nav-mesh for any map.
NavMeshTriangulation navmesh = NavMesh.CalculateTriangulation();
//initialize triangles array
Triangle[] meshTriangles = new Triangle[navmesh.indices.Length/3];
//will contain mapping from a string containing the Vector3 pair side and the lane type of a node(ex: (1,2,3) and (4,5,6)
//in "middle" will be respresented as "1,2,3 - 4,5,6 middle" with the smaller Vector3 coming first) to the node on that
//side with that lane type.
Dictionary<string, Node> sideToNode = new Dictionary<string, Node>();
//will contain mapping from a Node to the list of Triangles that contain that Node on a side
Dictionary<Node, List<Triangle>> nodeToTriangles = new Dictionary<Node, List<Triangle>>();
nodes = new List<Node>();
//will contain a mapping from Vector3 coordinates (ex: (1,2,3) will be represented as "1,2,3") to
//a Node
Dictionary<string, Node> coordinatesToNode = new Dictionary<string, Node>();
//Made sure nav mesh indices is a multiple of 3
for (int i = 0; i < navmesh.indices.Length / 3; i++) {
Vector3[] currentVectors = new Vector3[3];
Vector3 v1 = navmesh.vertices[navmesh.indices[i*3]];
Vector3 v2 = navmesh.vertices[navmesh.indices[i*3 + 1]];
Vector3 v3 = navmesh.vertices[navmesh.indices[i*3 + 2]];
meshTriangles[i] = new Triangle(v1, v2, v3, NavMesh.GetAreaCost(navmesh.areas[i]));
List<Vector3Pair> trianglePairs = new List<Vector3Pair>();
//Add the pair v1, v2 to trianglePairs
trianglePairs.Add(new Vector3Pair(v1, v2));
//Add the pair v2, v3 trianglePairs
trianglePairs.Add(new Vector3Pair(v2, v3));
//Add the pair v1, v3
trianglePairs.Add(new Vector3Pair(v1, v3));
//Calculate bisections. Needed to generate smoother paths
foreach (Vector3Pair currentVector3Pair in trianglePairs) {
Vector3 currentFirst = currentVector3Pair.first;
Vector3 currentSecond = currentVector3Pair.second;
Vector3 bisect1 = new Vector3((currentFirst.x + currentSecond.x)/2, (currentFirst.y + currentSecond.y)/2,
(currentFirst.z + currentSecond.z)/2);
Vector3 bisect2 = new Vector3((bisect1.x + currentFirst.x)/2, (bisect1.y + currentFirst.y)/2,
(bisect1.z + currentFirst.z)/2);
Vector3 bisect3 = new Vector3((bisect1.x + currentSecond.x)/2, (bisect1.y + currentSecond.y)/2,
(bisect1.z + currentSecond.z)/2);
Node bisect1Node = getNodeWithVectorCoordinates(ref coordinatesToNode, bisect1);
Node bisect2Node = getNodeWithVectorCoordinates(ref coordinatesToNode, bisect2);
Node bisect3Node = getNodeWithVectorCoordinates(ref coordinatesToNode, bisect3);
AddToDictionary(ref nodeToTriangles, bisect1Node, meshTriangles[i]);
AddToDictionary(ref nodeToTriangles, bisect2Node, meshTriangles[i]);
AddToDictionary(ref nodeToTriangles, bisect3Node, meshTriangles[i]);
sideToNode[GetPairString(currentFirst, currentSecond) + " middle"] = bisect1Node;
sideToNode[GetPairString(currentFirst, currentSecond) + " outer1"] = bisect2Node;
sideToNode[GetPairString(currentFirst, currentSecond) + " outer2"] = bisect3Node;
}
Vector3 currentCentroid = meshTriangles[i].Centroid ();
Node centroidNode = getNodeWithVectorCoordinates(ref coordinatesToNode, currentCentroid);
AddToDictionary(ref nodeToTriangles, centroidNode, meshTriangles[i]);
sideToNode[GetPairString (currentCentroid, currentCentroid) + " middle"] = centroidNode;
}
//create list of item nodes
List<Node> itemNodes = new List<Node>();
foreach (GameObject item in ItemsAI.itemList) {
Node currentItemNode = new Node (ItemsAI.objectToPosition [item]);
itemNodes.Add(currentItemNode);
PathPlanningDataStructures.nodeToCount[currentItemNode.position] = 0;
}
//set neighbors of each node
foreach (var item in nodeToTriangles) {
Node currentNode = item.Key;
//iterate through all triangles that contain the currentNode on a side
foreach (Triangle t in item.Value) {
//centroid of the triangle
Vector3 currentCentroid = t.Centroid();
//list of sides of the triangle
List<Vector3Pair> triangleSides = new List<Vector3Pair>();
triangleSides.Add(new Vector3Pair(t.vertex1, t.vertex2));
triangleSides.Add(new Vector3Pair(t.vertex2, t.vertex3));
triangleSides.Add(new Vector3Pair(t.vertex1, t.vertex3));
//iterate through each item node to check if it is contained within the current triangle; if so,
//make the centroid of the triangle, currentNode, and the item neighbors of each other
//bool[] nodeInTriangle = new bool[itemNodes.Count];
for(int i = 0; i < itemNodes.Count; i++) {
Node currentItemNode = itemNodes [i];
if (t.PointInTriangle (currentItemNode.position)) {
addNodeNeighbor(sideToNode, ref currentItemNode, currentCentroid, currentCentroid, "middle");
itemNodes[i].neighbors.Add (currentNode);
currentNode.neighbors.Add (itemNodes [i]);
}
}
foreach (Vector3Pair triangleSide in triangleSides) {
Vector3 currentFirst = triangleSide.first;
Vector3 currentSecond = triangleSide.second;
addNodeNeighbor(sideToNode, ref currentNode, currentFirst, currentSecond, "middle");
addNodeNeighbor(sideToNode, ref currentNode, currentFirst, currentSecond, "outer1");
addNodeNeighbor(sideToNode, ref currentNode, currentFirst, currentSecond, "outer2");
for (int i = 0; i < itemNodes.Count; i++) {
Node currentItemNode = itemNodes [i];
if (t.PointInTriangle (currentItemNode.position)) {
addNodeNeighbor(sideToNode, ref currentItemNode, currentFirst, currentSecond, "middle");
addNodeNeighbor(sideToNode, ref currentItemNode, currentFirst, currentSecond, "outer1");
addNodeNeighbor(sideToNode, ref currentItemNode, currentFirst, currentSecond, "outer2");
}
}
}
addNodeNeighbor(sideToNode, ref currentNode, currentCentroid, currentCentroid, "middle");
}
nodes.Add(currentNode);
PathPlanningDataStructures.nodeToCount[currentNode.position] = 0;
}
//set end node of the cars
endNode = getClosestNode (GameObject.Find("FinishLine").transform.position);
}