/// <summary> /// Goes road by road to create sidewalks /// Once a side of the road (designated by a road and the intersection it comes from) is used, don't try to use it again /// </summary> private IEnumerator GenerateBlock() { GameObject parentObject = new GameObject(); parentObject.name = "Block"; parentObject.isStatic = true; HashSet <SidewalkCheckHelper> usedRoads = new HashSet <SidewalkCheckHelper>(); List <Sidewalk> sidewalks = new List <Sidewalk>(); SidewalkCheckHelper check = new SidewalkCheckHelper(); // TODO: Add list of all roads to city info to optimize this for (int i = 0; i < city.Nodes.Count; i++) { for (int j = 0; j < city.Nodes[i].Roads.Count; j++) { check.Intersection = city.Nodes[i]; check.Road = city.Nodes[i].Roads[j]; if (!usedRoads.Contains(check)) { usedRoads.Add(check); sidewalks.Add(CreateSidewalk(city.Nodes[i], city.Nodes[i].Roads[j], usedRoads, parentObject)); } } } // Create buildings // Use collisions to make sure buildings don't collide with roads // TODO: Add list of all roads to city info to optimize this GameObject buildingObject = new GameObject(); buildingObject.name = "Buildings"; buildingObject.transform.parent = parentObject.transform; buildingObject.isStatic = true; HashSet <RoadSegment> roads = new HashSet <RoadSegment>(); for (int i = 0; i < city.Nodes.Count; i++) { for (int j = 0; j < city.Nodes[i].Roads.Count; j++) { if (!roads.Contains(city.Nodes[i].Roads[j])) { roads.Add(city.Nodes[i].Roads[j]); yield return(EditorCoroutineUtility.StartCoroutine(CreateBuildings(city.Nodes[i].Roads[j], buildingObject), this)); } } } // After buildings are created, create the infill mesh for (int i = 0; i < sidewalks.Count; i++) { if (!sidewalks[i].IsSurroundingSidewalk()) { sidewalks[i].CreateFillMesh(); } } }
/// <summary> /// Gets all the points that will form a sidewalk /// </summary> /// <param name="startIntersection"></param> /// <param name="roadSegment"></param> /// <param name="checks"></param> /// <param name="parent"></param> private Sidewalk CreateSidewalk(Intersection startIntersection, RoadSegment roadSegment, HashSet <SidewalkCheckHelper> checks, GameObject parent) { Intersection current = startIntersection; Intersection next = roadSegment.GetOtherSide(startIntersection); RoadSegment nextSegment = null; GameObject go = new GameObject(); go.name = "Sidewalk Mesh"; Sidewalk sidewalk = go.AddComponent <Sidewalk>(); sidewalk.OriginalVertices.Add(roadSegment.GetVertexWorldPosition(startIntersection, false)); SidewalkCheckHelper check = new SidewalkCheckHelper(); while (next != startIntersection) { int nextIndex = (next.Roads.IndexOf(roadSegment) + 1) % (next.Roads.Count); nextSegment = next.Roads[nextIndex]; check.Intersection = next; check.Road = nextSegment; checks.Add(check); if (next.Roads.Count == 1) { sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, true)); sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, false)); } else if (!(Mathf.Approximately(roadSegment.GetVertexWorldPosition(next, true).x, nextSegment.GetVertexWorldPosition(next, false).x) && Mathf.Approximately(roadSegment.GetVertexWorldPosition(next, true).z, nextSegment.GetVertexWorldPosition(next, false).z))) { sidewalk.OriginalVertices.Add(roadSegment.GetVertexWorldPosition(next, true)); sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, false)); } else { sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, false)); } current = next; next = nextSegment.GetOtherSide(next); roadSegment = nextSegment; } if (nextSegment != null && !(Mathf.Approximately(sidewalk.OriginalVertices[0].x, nextSegment.GetVertexWorldPosition(next, true).x) && Mathf.Approximately(sidewalk.OriginalVertices[0].z, nextSegment.GetVertexWorldPosition(next, true).z))) { sidewalk.OriginalVertices.Add(nextSegment.GetVertexWorldPosition(next, true)); } Vector3 sum = Vector3.zero; for (int i = 0; i < sidewalk.OriginalVertices.Count; i++) { sum += sidewalk.OriginalVertices[i]; } go.transform.position = sum / sidewalk.OriginalVertices.Count; sidewalk.SidewalkMaterial = city.SidewalkMaterial; sidewalk.InnerMaterial = city.InnerBlockMaterial; sidewalk.FixMeshOffset(); sidewalk.FindDirection(); sidewalk.CalculateVertices(); sidewalk.CreateMesh(); go.transform.parent = parent.transform; go.isStatic = true; return(sidewalk); }