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;
     }
 }
Beispiel #2
0
 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);
 }