private Block CreateStreetBlock(StreetNode street) { GameObject blockGameObject = (GameObject)GameObject.Instantiate(blockPrefab, Vector3.zero, Quaternion.identity); int childCount = street.nodes.GetLength(0); float leftMaxWidth = 0; float rightMaxWidth = 0; float offsetLeft = 0; float offsetRight = 0; Transform leftSide = blockGameObject.transform.Find("LeftSide").transform; Transform rightSide = blockGameObject.transform.Find("RightSide").transform; for (int i = 0; i < childCount; i++) { Node node = street.nodes [i]; Block childBlock = CreateBlock(node); GameObject childBlockGameObject = childBlock.gameObject; if (i % 2 == 1) { childBlockGameObject.transform.RotateAround(Vector3.zero, Vector3.up, -90); childBlockGameObject.transform.localPosition = new Vector3(0, 0, childBlock.width / 2 + offsetLeft); offsetLeft += childBlock.width; leftMaxWidth = (leftMaxWidth > childBlock.length) ? leftMaxWidth : childBlock.length; childBlockGameObject.transform.SetParent(leftSide, false); } else { childBlockGameObject.transform.RotateAround(Vector3.zero, Vector3.up, 90); childBlockGameObject.transform.localPosition = new Vector3(0, 0, childBlock.width / 2 + offsetRight); offsetRight += childBlock.width; rightMaxWidth = (rightMaxWidth > childBlock.length) ? rightMaxWidth : childBlock.length; childBlockGameObject.transform.SetParent(rightSide, false); } } float midpointOffset = (leftMaxWidth - rightMaxWidth) / 2; float length = ((offsetLeft > offsetRight) ? offsetLeft : offsetRight) * 1f; float streetWidth = length / 50; leftSide.Translate(new Vector3(-streetWidth / 2 + midpointOffset, 0, 0)); rightSide.Translate(new Vector3(streetWidth / 2 + midpointOffset, 0, 0)); GameObject streetGameObject = (GameObject)GameObject.Instantiate(streetPrefab, new Vector3(midpointOffset, 0, 0), Quaternion.identity); streetGameObject.transform.localScale = new Vector3(streetWidth, 1, length); streetGameObject.transform.SetParent(blockGameObject.transform, true); Block result = new Block(); result.gameObject = blockGameObject; result.width = (leftMaxWidth + streetWidth + rightMaxWidth) * 1f; result.length = length; return(result); }
private Node CreateModel(int depth) { int subTreeCount = (int)(depth / 2f + (Random.value * depth / 2f)); int leafCount = (int)(Random.value * subTreeCount * 70 / depth); List <Node> nodes = new List <Node> (); for (int i = 0; i < subTreeCount; i++) { nodes.Insert((int)(nodes.Count * Random.value), CreateModel(depth - 2)); } for (int i = 0; i < leafCount; i++) { nodes.Insert((int)(nodes.Count * Random.value), new BuildingNode()); } StreetNode street = new StreetNode(nodes.ToArray()); return(street); }
// Function to stitch the street to the current list of nodes public bool Stitch(XmlBaseFactory xmlBaseFactory, WaysFactory street) { // Create list to append List <StreetNode> append = new List <StreetNode>(); for (int i = 0; i < street.ndref.Count; i++) { StreetNode node = new StreetNode(); node.id = street.ndref[i]; node.position = xmlBaseFactory.allNodes[node.id] - xmlBaseFactory.boundsFactory.center; node.waterway = street.isWaterway; append.Add(node); } // Atemmpt to stitch append list to current list of nodes // If street is empty if (nodes.Count == 0) { nodes = append; } // if the first node in the street is the same as the first node in the street we're trying to stich else if (nodes[0].id == append[0].id) { nodes.Reverse(); nodes.AddRange(append); } // if the first node in the street is the same as the last node in the street we're trying to stitch else if (nodes[0].id == append[append.Count - 1].id) { append.AddRange(nodes); nodes = append; } // if the last node in the street is the same as the first node in the street we're trying to stitch else if (nodes[nodes.Count - 1].id == append[0].id) { nodes.AddRange(append); } // if the last node in the street is the same as the last node in the street we're trying to stitch else if (nodes[nodes.Count - 1].id == append[append.Count - 1].id) { append.Reverse(); nodes.AddRange(append); } else { return(false); } // Cleanup data // Remove duplicate ids List <StreetNode> copy = new List <StreetNode>(); for (int i = 0; i < nodes.Count; i++) { if (copy.Count == 0 || copy[copy.Count - 1].id != nodes[i].id) { copy.Add(nodes[i]); } } nodes = copy; // Remove single waterways for (int i = 0; i < nodes.Count; i++) { bool fPrev = i - 1 >= 0 ? nodes[i - 1].waterway : !nodes[i].waterway; bool fNext = i + 1 < nodes.Count ? nodes[i + 1].waterway : !nodes[i].waterway; bool fCurr = nodes[i].waterway; if (fCurr != fPrev && fCurr != fNext) { nodes[i].waterway = !(nodes[i].waterway); } } // Check if waterway is looped looped = nodes.Count > 2 && nodes[0].id == nodes[nodes.Count - 1].id; return(true); }
// Creates the waterways private void CreateWaterway(Street street, string name) { List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> triangles0 = new List <int>(); // road List <int> triangles1 = new List <int>(); // waterway for (int i = 1; i < street.nodes.Count; i++) { StreetNode s0; StreetNode s1 = street.nodes[i - 1]; StreetNode s2 = street.nodes[i]; StreetNode s3; // Get point 0 if (i > 1) { s0 = street.nodes[i - 2]; } else if (street.looped) { s0 = street.nodes[street.nodes.Count - 1]; } else { s0 = new StreetNode() { position = 2 * s1.position - s2.position, waterway = s1.waterway, }; } // Get point 3 if (i < street.nodes.Count - 1) { s3 = street.nodes[i + 1]; } else if (street.looped) { s3 = street.nodes[1]; } else { s3 = new StreetNode() { position = 2 * s2.position - s1.position, waterway = s2.waterway, }; } // Width of the waterway at each point float waterWidth = s0.waterway || s1.waterway || s2.waterway || s3.waterway ? riverWid : streamWid; // Calculate section vertices Vector3 v1 = Intersection( Perpendicular(s0.position, s1.position, -waterWidth), Perpendicular(s1.position, s0.position, +waterWidth), Perpendicular(s2.position, s1.position, +waterWidth), Perpendicular(s1.position, s2.position, -waterWidth) ); Vector3 v2 = Intersection( Perpendicular(s0.position, s1.position, +waterWidth), Perpendicular(s1.position, s0.position, -waterWidth), Perpendicular(s2.position, s1.position, -waterWidth), Perpendicular(s1.position, s2.position, +waterWidth) ); Vector3 v3 = Intersection( Perpendicular(s1.position, s2.position, -waterWidth), Perpendicular(s2.position, s1.position, +waterWidth), Perpendicular(s3.position, s2.position, +waterWidth), Perpendicular(s2.position, s3.position, -waterWidth) ); Vector3 v4 = Intersection( Perpendicular(s1.position, s2.position, +waterWidth), Perpendicular(s2.position, s1.position, -waterWidth), Perpendicular(s3.position, s2.position, -waterWidth), Perpendicular(s2.position, s3.position, +waterWidth) ); // Add vertices vertices.Add(v1); vertices.Add(v2); vertices.Add(v3); vertices.Add(v4); // Add normals normals.Add(Vector3.up); normals.Add(Vector3.up); normals.Add(Vector3.up); normals.Add(Vector3.up); // Add uvs uvs.Add(new Vector2(0, 0)); uvs.Add(new Vector2(1, 0)); uvs.Add(new Vector2(0, 1)); uvs.Add(new Vector2(1, 1)); // Set indices int p1 = vertices.Count - 4; int p2 = vertices.Count - 3; int p3 = vertices.Count - 2; int p4 = vertices.Count - 1; // Add triangles triangles1.Add(p1); triangles1.Add(p2); triangles1.Add(p3); triangles1.Add(p2); triangles1.Add(p4); triangles1.Add(p3); } // Find mesh center and move vertices Vector3 center = Vector3.zero; foreach (Vector3 v in vertices) { center += v; } center /= vertices.Count; for (int i = 0; i < vertices.Count; i++) { vertices[i] -= center; } // Create object GameObject go = new GameObject(name); MeshFilter mf = go.AddComponent <MeshFilter>(); MeshRenderer mr = go.AddComponent <MeshRenderer>(); MeshCollider mc = go.AddComponent <MeshCollider>(); go.transform.position = center; mf.mesh.vertices = vertices.ToArray(); mf.mesh.normals = normals.ToArray(); mf.mesh.uv = uvs.ToArray(); // Add triangles & materials if (triangles0.Count == 0) { mf.mesh.triangles = triangles1.ToArray(); mr.material = waterMat; } else if (triangles1.Count == 0) { mf.mesh.triangles = triangles0.ToArray(); mr.material = waterMat; } else { mf.mesh.subMeshCount = 2; mf.mesh.SetTriangles(triangles0.ToArray(), 0); mf.mesh.SetTriangles(triangles1.ToArray(), 1); mr.materials = new Material[] { waterMat }; } // Move object ontop of the terrain RaycastHit hit; if (Physics.Raycast(go.transform.position, Vector3.down, out hit)) { go.transform.position = hit.point + new Vector3(0, 0.035f, 0); } }
private void CreateStreet(Street street) { string name = street.nodes[0].name; List <Vector3> vertices = new List <Vector3>(); List <Vector3> normals = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> triangles0 = new List <int>(); // road List <int> triangles1 = new List <int>(); // footway for (int i = 1; i < street.nodes.Count; i++) { StreetNode s0; StreetNode s1 = street.nodes[i - 1]; StreetNode s2 = street.nodes[i]; StreetNode s3; // Get point 0 if (i > 1) { s0 = street.nodes[i - 2]; } else if (street.looped) { s0 = street.nodes[street.nodes.Count - 1]; } else { s0 = new StreetNode() { position = 2 * s1.position - s2.position, footway = s1.footway, }; } // Get point 3 if (i < street.nodes.Count - 1) { s3 = street.nodes[i + 1]; } else if (street.looped) { s3 = street.nodes[1]; } else { s3 = new StreetNode() { position = 2 * s2.position - s1.position, footway = s2.footway, }; } // Width of the road at each point float w0 = s0.footway ? 1.6f : 3.7f; float w1 = s1.footway ? 1.6f : 3.7f; float w2 = s2.footway ? 1.6f : 3.7f; float w3 = s3.footway ? 1.6f : 3.7f; // Calculate section vertices Vector3 v1 = Intersection( Perpendicular(s0.position, s1.position, -w0), Perpendicular(s1.position, s0.position, +w1), Perpendicular(s2.position, s1.position, +w2), Perpendicular(s1.position, s2.position, -w1) ); Vector3 v2 = Intersection( Perpendicular(s0.position, s1.position, +w0), Perpendicular(s1.position, s0.position, -w1), Perpendicular(s2.position, s1.position, -w2), Perpendicular(s1.position, s2.position, +w1) ); Vector3 v3 = Intersection( Perpendicular(s1.position, s2.position, -w1), Perpendicular(s2.position, s1.position, +w2), Perpendicular(s3.position, s2.position, +w3), Perpendicular(s2.position, s3.position, -w2) ); Vector3 v4 = Intersection( Perpendicular(s1.position, s2.position, +w1), Perpendicular(s2.position, s1.position, -w2), Perpendicular(s3.position, s2.position, -w3), Perpendicular(s2.position, s3.position, +w2) ); // Add vertices, normals and uvs vertices.Add(v1); vertices.Add(v2); vertices.Add(v3); vertices.Add(v4); normals.Add(Vector3.up); normals.Add(Vector3.up); normals.Add(Vector3.up); normals.Add(Vector3.up); uvs.Add(new Vector2(0, 0)); uvs.Add(new Vector2(1, 0)); uvs.Add(new Vector2(0, 1)); uvs.Add(new Vector2(1, 1)); int p1 = vertices.Count - 4; int p2 = vertices.Count - 3; int p3 = vertices.Count - 2; int p4 = vertices.Count - 1; // Add triangles if (s2.footway) { triangles1.Add(p1); triangles1.Add(p2); triangles1.Add(p3); triangles1.Add(p2); triangles1.Add(p4); triangles1.Add(p3); } else { triangles0.Add(p1); triangles0.Add(p2); triangles0.Add(p3); triangles0.Add(p2); triangles0.Add(p4); triangles0.Add(p3); } if (street.nodes[i].name != name || i >= street.nodes.Count - 1) { // Find mesh center and move vertices Vector3 center = Vector3.zero; foreach (Vector3 v in vertices) { center += v; } center /= vertices.Count; // Move vertices ontop of terrain for (int j = 0; j < vertices.Count; j++) { RaycastHit hit; if (Physics.Raycast(new Vector3(vertices[j].x, vertices[j].y + 200f, vertices[j].z), Vector3.down, out hit)) { vertices[j] = new Vector3(vertices[j].x, hit.point.y + 0.05f, vertices[j].z); } } // Move vertices based on center for (int j = 0; j < vertices.Count; j++) { vertices[j] -= center; } // Create object GameObject go = new GameObject(name); MeshFilter mf = go.AddComponent <MeshFilter>(); MeshRenderer mr = go.AddComponent <MeshRenderer>(); MeshCollider mc = go.AddComponent <MeshCollider>(); go.transform.position = center; mf.mesh.vertices = vertices.ToArray(); mf.mesh.normals = normals.ToArray(); mf.mesh.uv = uvs.ToArray(); /* Hide Road objects in the project hierarchy to make it more readable */ // go.hideFlags = HideFlags.HideInHierarchy; go.transform.parent = parent.transform; // Add triangles & materials if (triangles0.Count == 0) { mf.mesh.triangles = triangles1.ToArray(); mr.material = footway; } else if (triangles1.Count == 0) { mf.mesh.triangles = triangles0.ToArray(); mr.material = road; } else { mf.mesh.subMeshCount = 2; mf.mesh.SetTriangles(triangles0.ToArray(), 0); mf.mesh.SetTriangles(triangles1.ToArray(), 1); mr.materials = new Material[] { road, footway }; } // Clear data vertices.Clear(); normals.Clear(); uvs.Clear(); triangles0.Clear(); triangles1.Clear(); name = street.nodes[i].name; } } }