private static void AnalizeHouseRoofType(OnlineMapsOSMWay way, ref float baseHeight, ref OnlineMapsBuildingRoofType roofType, ref float roofHeight) { string roofShape = way.GetTagValue("roof:shape"); string roofHeightStr = way.GetTagValue("roof:height"); string minHeightStr = way.GetTagValue("min_height"); if (!String.IsNullOrEmpty(roofShape)) { if ((roofShape == "dome" || roofShape == "pyramidal") && !String.IsNullOrEmpty(roofHeightStr)) { GetHeightFromString(roofHeightStr, ref roofHeight); baseHeight -= roofHeight; roofType = OnlineMapsBuildingRoofType.dome; } } else if (!String.IsNullOrEmpty(roofHeightStr)) { GetHeightFromString(roofHeightStr, ref roofHeight); baseHeight -= roofHeight; roofType = OnlineMapsBuildingRoofType.dome; } else if (!String.IsNullOrEmpty(minHeightStr)) { float totalHeight = baseHeight; GetHeightFromString(minHeightStr, ref baseHeight); roofHeight = totalHeight - baseHeight; roofType = OnlineMapsBuildingRoofType.dome; } }
private static void CreateHouseRoofTriangles(List <Vector3> vertices, OnlineMapsBuildingRoofType roofType, List <Vector2> roofPoints, float baseHeight, float roofHeight, ref List <int> triangles) { if (roofType == OnlineMapsBuildingRoofType.flat) { triangles.AddRange(OnlineMapsUtils.Triangulate(roofPoints).Select(index => index)); } else if (roofType == OnlineMapsBuildingRoofType.dome) { CreateHouseRoofDome(baseHeight + roofHeight, vertices, triangles); } }
private static void CreateHouseRoofTriangles(int countVertices, List <Vector3> vertices, OnlineMapsBuildingRoofType roofType, float[] roofPoints, float baseHeight, float roofHeight, ref List <int> triangles) { if (roofType == OnlineMapsBuildingRoofType.flat) { if (roofIndices == null) { roofIndices = new List <int>(60); } triangles.AddRange(OnlineMapsUtils.Triangulate(roofPoints, countVertices, roofIndices)); } else if (roofType == OnlineMapsBuildingRoofType.dome) { CreateHouseRoofDome(baseHeight + roofHeight, vertices, triangles); } }
private void CreateHouseRoof(List <Vector3> baseVerticles, float baseHeight, float roofHeight, OnlineMapsBuildingRoofType roofType, ref List <Vector3> vertices, ref List <Vector2> uvs, ref List <int> triangles) { float[] roofPoints = new float[baseVerticles.Count * 2]; List <Vector3> roofVertices = new List <Vector3>(baseVerticles.Count); try { int countVertices = CreateHouseRoofVerticles(baseVerticles, roofVertices, roofPoints, baseHeight); CreateHouseRoofTriangles(countVertices, roofVertices, roofType, roofPoints, baseHeight, roofHeight, ref triangles); if (triangles.Count == 0) { hasErrors = true; return; } Vector3 side1 = roofVertices[triangles[1]] - roofVertices[triangles[0]]; Vector3 side2 = roofVertices[triangles[2]] - roofVertices[triangles[0]]; Vector3 perp = Vector3.Cross(side1, side2); bool reversed = perp.y < 0; if (reversed) { triangles.Reverse(); } float minX = float.MaxValue; float minZ = float.MaxValue; float maxX = float.MinValue; float maxZ = float.MinValue; foreach (Vector3 v in roofVertices) { if (v.x < minX) { minX = v.x; } if (v.z < minZ) { minZ = v.z; } if (v.x > maxX) { maxX = v.x; } if (v.z > maxZ) { maxZ = v.z; } } float offX = maxX - minX; float offZ = maxZ - minZ; foreach (Vector3 v in roofVertices) { uvs.Add(new Vector2((v.x - minX) / offX, (v.z - minZ) / offZ)); } //uvs.AddRange(roofVertices.Select(v => new Vector2((v.x - minX) / offX, (v.z - minZ) / offZ))); int triangleOffset = vertices.Count; for (int i = 0; i < triangles.Count; i++) { triangles[i] += triangleOffset; } vertices.AddRange(roofVertices); } catch (Exception) { Debug.Log(triangles.Count + " " + roofVertices.Count); hasErrors = true; throw; } }
private static void AnalizeHouseRoofType(OnlineMapsOSMWay way, ref float baseHeight, ref OnlineMapsBuildingRoofType roofType, ref float roofHeight) { string roofShape = way.GetTagValue("roof:shape"); string roofHeightStr = way.GetTagValue("roof:height"); string minHeightStr = way.GetTagValue("min_height"); if (!String.IsNullOrEmpty(roofShape)) { if ((roofShape == "dome" || roofShape == "pyramidal") && !String.IsNullOrEmpty(roofHeightStr)) { GetHeightFromString(roofHeightStr, ref roofHeight); baseHeight -= roofHeight; roofType = OnlineMapsBuildingRoofType.dome; } } else if (!String.IsNullOrEmpty(roofHeightStr)) { GetHeightFromString(roofHeightStr, ref roofHeight); baseHeight -= roofHeight; roofType = OnlineMapsBuildingRoofType.dome; } else if (!String.IsNullOrEmpty(minHeightStr)) { float totalHeight = baseHeight; GetHeightFromString(minHeightStr, ref baseHeight); roofHeight = totalHeight - baseHeight; roofType = OnlineMapsBuildingRoofType.dome; } }
/// <summary> /// Creates a new building, based on Open Street Map. /// </summary> /// <param name="container">Reference to OnlineMapsBuildings.</param> /// <param name="way">Way of building.</param> /// <param name="nodes">Nodes obtained from Open Street Maps.</param> /// <returns>Building instance.</returns> public static OnlineMapsBuildingBase Create(OnlineMapsBuildings container, OnlineMapsOSMWay way, Dictionary <string, OnlineMapsOSMNode> nodes) { if (CheckIgnoredBuildings(way)) { return(null); } if (usedNodes == null) { usedNodes = new List <OnlineMapsOSMNode>(30); } way.GetNodes(nodes, usedNodes); List <Vector3> points = GetLocalPoints(usedNodes); if (points.Count < 3) { return(null); } if (points[0] == points[points.Count - 1]) { points.RemoveAt(points.Count - 1); } if (points.Count < 3) { return(null); } for (int i = 0; i < points.Count; i++) { int prev = i - 1; if (prev < 0) { prev = points.Count - 1; } int next = i + 1; if (next >= points.Count) { next = 0; } float a1 = OnlineMapsUtils.Angle2D(points[prev], points[i]); float a2 = OnlineMapsUtils.Angle2D(points[i], points[next]); if (Mathf.Abs(a1 - a2) < 5) { points.RemoveAt(i); i--; } } if (points.Count < 3) { return(null); } Vector4 cp = new Vector4(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue); foreach (Vector3 point in points) { if (point.x < cp.x) { cp.x = point.x; } if (point.z < cp.y) { cp.y = point.z; } if (point.x > cp.z) { cp.z = point.x; } if (point.z > cp.w) { cp.w = point.z; } } Vector3 centerPoint = new Vector3((cp.z + cp.x) / 2, 0, (cp.y + cp.w) / 2); for (int i = 0; i < points.Count; i++) { points[i] -= centerPoint; } bool generateWall = true; if (way.HasTagKey("building")) { string buildingType = way.GetTagValue("building"); if (buildingType == "roof") { generateWall = false; } } float baseHeight = 15; float roofHeight = 0; OnlineMapsBuildingMaterial material = GetRandomMaterial(container); Material wallMaterial; Material roofMaterial; Vector2 scale = Vector2.one; if (material != null) { wallMaterial = new Material(material.wall); roofMaterial = new Material(material.roof); scale = material.scale; } else { Shader shader = Shader.Find("Diffuse"); wallMaterial = new Material(shader); roofMaterial = new Material(shader); } OnlineMapsBuildingRoofType roofType = OnlineMapsBuildingRoofType.flat; AnalizeHouseTags(way, ref wallMaterial, ref roofMaterial, ref baseHeight); AnalizeHouseRoofType(way, ref baseHeight, ref roofType, ref roofHeight); GameObject houseGO = CreateGameObject(way.id); MeshRenderer renderer = houseGO.AddComponent <MeshRenderer>(); MeshFilter meshFilter = houseGO.AddComponent <MeshFilter>(); Mesh mesh = new Mesh { name = way.id }; meshFilter.sharedMesh = mesh; renderer.sharedMaterials = new [] { wallMaterial, roofMaterial }; OnlineMapsBuildingBuiltIn building = houseGO.AddComponent <OnlineMapsBuildingBuiltIn>(); houseGO.transform.localPosition = centerPoint; houseGO.transform.localRotation = Quaternion.Euler(Vector3.zero); Vector2 centerCoords = Vector2.zero; float minCX = float.MaxValue, minCY = float.MaxValue, maxCX = float.MinValue, maxCY = float.MinValue; foreach (OnlineMapsOSMNode node in usedNodes) { Vector2 nodeCoords = node; centerCoords += nodeCoords; if (nodeCoords.x < minCX) { minCX = nodeCoords.x; } if (nodeCoords.y < minCY) { minCY = nodeCoords.y; } if (nodeCoords.x > maxCX) { maxCX = nodeCoords.x; } if (nodeCoords.y > maxCY) { maxCY = nodeCoords.y; } } building.id = way.id; building.initialZoom = OnlineMaps.instance.zoom; building.centerCoordinates = new Vector2((maxCX + minCX) / 2, (maxCY + minCY) / 2); building.boundsCoords = new Bounds(building.centerCoordinates, new Vector3(maxCX - minCX, maxCY - minCY)); int wallVerticesCount = (points.Count + 1) * 2; int roofVerticesCount = points.Count; int verticesCount = wallVerticesCount + roofVerticesCount; int countTriangles = wallVerticesCount * 3; List <Vector3> vertices = new List <Vector3>(verticesCount); List <Vector2> uvs = new List <Vector2>(verticesCount); List <int> wallTriangles = new List <int>(countTriangles); List <int> roofTriangles = new List <int>(); if (generateWall) { building.CreateHouseWall(points, baseHeight, wallMaterial, scale, ref vertices, ref uvs, ref wallTriangles); } building.CreateHouseRoof(points, baseHeight, roofHeight, roofType, ref vertices, ref uvs, ref roofTriangles); if (building.hasErrors) { OnlineMapsUtils.DestroyImmediate(building.gameObject); return(null); } mesh.vertices = vertices.ToArray(); mesh.uv = uvs.ToArray(); mesh.subMeshCount = 2; mesh.SetTriangles(wallTriangles.ToArray(), 0); mesh.SetTriangles(roofTriangles.ToArray(), 1); mesh.RecalculateBounds(); mesh.RecalculateNormals(); building.buildingCollider = houseGO.AddComponent <MeshCollider>(); (building.buildingCollider as MeshCollider).sharedMesh = mesh; return(building); }
private void CreateHouseRoof(Vector3[] baseVerticles, float baseHeight, float roofHeight, OnlineMapsBuildingRoofType roofType, ref List<Vector3> vertices, ref List<Vector2> uvs, ref List<int> triangles) { List<Vector2> roofPoints = new List<Vector2>(); List<Vector3> roofVertices = new List<Vector3>(); try { CreateHouseRoofVerticles(baseVerticles, roofVertices, roofPoints, baseHeight); CreateHouseRoofTriangles(roofVertices, roofType, roofPoints, baseHeight, roofHeight, ref triangles); if (triangles.Count == 0) { hasErrors = true; return; } Vector3 side1 = roofVertices[triangles[1]] - roofVertices[triangles[0]]; Vector3 side2 = roofVertices[triangles[2]] - roofVertices[triangles[0]]; Vector3 perp = Vector3.Cross(side1, side2); bool reversed = perp.y < 0; if (reversed) triangles.Reverse(); float minX = float.MaxValue; float minZ = float.MaxValue; float maxX = float.MinValue; float maxZ = float.MinValue; foreach (Vector3 v in roofVertices) { if (v.x < minX) minX = v.x; if (v.z < minZ) minZ = v.z; if (v.x > maxX) maxX = v.x; if (v.z > maxZ) maxZ = v.z; } float offX = maxX - minX; float offZ = maxZ - minZ; uvs.AddRange(roofVertices.Select(v => new Vector2((v.x - minX) / offX, (v.z - minZ) / offZ))); int triangleOffset = vertices.Count; for (int i = 0; i < triangles.Count; i++) triangles[i] += triangleOffset; vertices.AddRange(roofVertices); } catch (Exception) { Debug.Log(triangles.Count + " " + roofVertices.Count); hasErrors = true; throw; } }
private static void CreateHouseRoofTriangles(List<Vector3> vertices, OnlineMapsBuildingRoofType roofType, List<Vector2> roofPoints, float baseHeight, float roofHeight, ref List<int> triangles) { if (roofType == OnlineMapsBuildingRoofType.flat) triangles.AddRange(OnlineMapsUtils.Triangulate(roofPoints).Select(index => index)); else if (roofType == OnlineMapsBuildingRoofType.dome) CreateHouseRoofDome(baseHeight + roofHeight, vertices, triangles); }