public static void GenerateTrees(TerrainContainerObject container, List <GameObject> m_treesPrefabs, float m_treeDensity, float TreeScaleFactor, float TreeRandomScaleFactor, float m_TreeDistance, float m_BillBoardStartDistance, Dictionary <string, OSMNode> nodes, Dictionary <string, OSMWay> ways, List <OSMMapMembers> relations)
        {
            TreeDistance           = m_TreeDistance;
            BillBoardStartDistance = m_BillBoardStartDistance;

            AddTreesToTerrains(container, m_treesPrefabs);

            treeNodes   = new List <OSMNode>();
            woodWays    = new List <OSMWay>();
            treeRowWays = new List <OSMWay>();

            foreach (KeyValuePair <string, OSMNode> pair in nodes)
            {
                OSMNode n = pair.Value;
                if (n.HasTag("natural", "tree"))
                {
                    treeNodes.Add(n);
                }
            }

            foreach (KeyValuePair <string, OSMWay> pair in ways)
            {
                OSMWay w = pair.Value;
                if (w.HasTag("natural", "wood") || w.HasTags("landuse", "forest", "park"))
                {
                    woodWays.Add(w);
                }
                else if (w.HasTag("natural", "tree_row"))
                {
                    treeRowWays.Add(w);
                }
            }


            totalTreeCount = treeNodes.Count + treeRowWays.Count + woodWays.Count;

            if (totalTreeCount == 0)
            {
                return;
            }

            alreadyCreated = new HashSet <string>();

            var treeDensity = m_treeDensity;

            var TLPMercator_X = container.TLPointMercator.x;
            var TLPMercator_Y = container.TLPointMercator.y;

            var DRPMercator_X = container.DRPointMercator.x;
            var DRPMercator_Y = container.DRPointMercator.y;


            for (int i = 0; i < treeNodes.Count; i++)
            {
                OSMNode node = treeNodes[i];

                if (alreadyCreated.Contains(node.id))
                {
                    continue;
                }

                alreadyCreated.Add(node.id);

                var NodeP_Merc = GeoRefConversion.LatLongToMercat(node.Longitude, node.Latitude);

                double Offest_x = (NodeP_Merc.x - TLPMercator_X) / (DRPMercator_X - TLPMercator_X);

                double Offest_y = 1 - (NodeP_Merc.y - TLPMercator_Y) / (DRPMercator_Y - TLPMercator_Y);

                Vector3 WSPos = new Vector3((float)(container.transform.position.x + container.size.x * Offest_x), 0, (float)(container.size.z + container.size.z * Offest_y));

                SetTreeToTerrain(TreeScaleFactor, TreeRandomScaleFactor, container, WSPos);
            }

            for (int index = 0; index < treeRowWays.Count; index++)
            {
                OSMWay way = treeRowWays[index];
                if (alreadyCreated.Contains(way.id))
                {
                    continue;
                }
                alreadyCreated.Add(way.id);
                List <Vector3> points = OSMWay.GetGlobalPointsFromWay(way, nodes);

                for (int i = 0; i < points.Count; i++)
                {
                    Vector3 WSPos = points[i];

                    var WSPos_Merc = GeoRefConversion.LatLongToMercat(WSPos.x, WSPos.z);

                    double Offest_x = (WSPos_Merc.x - TLPMercator_X) / (DRPMercator_X - TLPMercator_X);
                    double Offest_y = 1 - (WSPos_Merc.y - TLPMercator_Y) / (DRPMercator_Y - TLPMercator_Y);

                    WSPos.x = (float)(container.transform.position.x + container.size.x * Offest_x);
                    WSPos.z = (float)(container.transform.position.z + container.size.z * Offest_y);

                    points[i] = WSPos;
                }

                for (int i = 0; i < points.Count - 1; i++)
                {
                    int len = Mathf.RoundToInt((points[i] - points[i + 1]).magnitude / m_treeDensity);
                    if (len > 0)
                    {
                        for (int j = 0; j <= len; j++)
                        {
                            SetTreeToTerrain(TreeScaleFactor, TreeRandomScaleFactor, container, Vector3.Lerp(points[i], points[i + 1], j / (float)len));
                        }
                    }
                    else
                    {
                        SetTreeToTerrain(TreeScaleFactor, TreeRandomScaleFactor, container, points[i]);
                    }
                }
            }

            for (int index = 0; index < woodWays.Count; index++)
            {
                OSMWay way = woodWays[index];
                if (alreadyCreated.Contains(way.id))
                {
                    continue;
                }
                alreadyCreated.Add(way.id);
                List <Vector3> points = OSMWay.GetGlobalPointsFromWay(way, nodes);

                for (int i = 0; i < points.Count; i++)
                {
                    Vector3 p = points[i];

                    var sp = GeoRefConversion.LatLongToMercat(p.x, p.z);

                    double rx = (sp.x - TLPMercator_X) / (DRPMercator_X - TLPMercator_X);
                    double ry = 1 - (sp.y - TLPMercator_Y) / (DRPMercator_Y - TLPMercator_Y);

                    p.x = (float)(container.transform.position.x + container.size.x * rx);
                    p.z = (float)(container.transform.position.z + container.size.z * ry);

                    points[i] = p;
                }

                Rect rect = Extensions.GetRectFromPoints(points);
                int  lx   = Mathf.RoundToInt(rect.width / m_treeDensity);
                int  ly   = Mathf.RoundToInt(rect.height / m_treeDensity);

                if (lx > 0 && ly > 0)
                {
                    m_currentWayID = way.id;

                    GenerateTerrainsTrees(TreeScaleFactor, TreeRandomScaleFactor, container, treeDensity, lx, ly, rect, points);
                }
            }
        }
Exemple #2
0
        public void GenerateTerrains()
        {
            ListTerrainObjects = new List <TerrainObject>();

            const string containerName = "Terrains";
            string       cName         = containerName;

            //Destroy prv created terrain
            if (RemovePrevTerrain)
            {
                Destroy(GameObject.Find(cName));
            }
            else
            {
                int index = 1;
                while (GameObject.Find(cName) != null)
                {
                    cName = containerName + " " + index.ToString();
                    index++;
                }
            }


            var container = new GameObject(cName);

            container.transform.position = new Vector3(0, 0, 0);

            progress = 0;

            Vector2 TlimiteFrom = new Vector2(prefs.terrainDimensions.x, 0);
            Vector2 TlimiteTo   = new Vector2(prefs.terrainDimensions.y, 0);

            Vector2Int tCount = new Vector2Int((int)prefs.terrainCount.x, (int)prefs.terrainCount.y);

            float maxElevation   = floatReader.MaxElevation;
            float minElevation   = floatReader.MinElevation;
            float ElevationRange = maxElevation - minElevation;

            var sizeX = Mathf.Floor(prefs.terrainDimensions.x * prefs.terrainScale.x) / prefs.terrainCount.x;
            var sizeZ = Mathf.Floor(prefs.terrainDimensions.y * prefs.terrainScale.z) / prefs.terrainCount.y;
            var sizeY = (ElevationRange) / ElevationScaleValue * prefs.TerrainExaggeration * 100 * prefs.terrainScale.y;

            Vector3 size;

            if (prefs.TerrainElevation == TerrainElevation.RealWorldElevation)
            {
                sizeY = ((ElevationRange)) * prefs.terrainScale.y / 100;
                size  = new Vector3(sizeX, sizeY, sizeZ);
            }
            else
            {
                size = new Vector3(sizeX, sizeY, sizeZ);
            }

            terrains = new TerrainObject[tCount.x, tCount.y];

            container.AddComponent <TerrainContainerObject>();

            var terrainContainer = container.GetComponent <TerrainContainerObject>();

            Terrainscontainer = terrainContainer;

            terrainContainer.terrainCount = prefs.terrainCount;

            terrainContainer.scale = prefs.terrainScale;

            terrainContainer.size = new Vector3(size.x * tCount.x, size.y, size.z * tCount.y);

            //Set Terrain Coordinates to the container TerrainContainer script (Lat/lon) + Mercator
            terrainContainer.TLPointLatLong = floatReader.TopLeftPoint;
            terrainContainer.DRPointLatLong = floatReader.DownRightPoint;

            terrainContainer.TLPointMercator = GeoRefConversion.LatLongToMercat(terrainContainer.TLPointLatLong.x, terrainContainer.TLPointLatLong.y);
            terrainContainer.DRPointMercator = GeoRefConversion.LatLongToMercat(terrainContainer.DRPointLatLong.x, terrainContainer.DRPointLatLong.y);



            progress = 0;

            for (int x = 0; x < tCount.x; x++)
            {
                for (int y = 0; y < tCount.y; y++)
                {
                    terrains[x, y]           = CreateTerrain(container.transform, x, y, size, prefs.terrainScale);
                    terrains[x, y].container = terrainContainer;

                    ListTerrainObjects.Add(terrains[x, y]);
                }
            }

            terrainContainer.terrains = terrains;

            phase = GeneratingTerrainPhase.generateHeightmaps;
        }
        public void GenerateTerrains()
        {
            const string containerName = "Terrains";
            string       cName         = containerName;

            //Destroy prv created terrain
            if (RemovePrvTerrain)
            {
                DestroyImmediate(GameObject.Find(cName));
            }
            else
            {
                int index = 1;
                while (GameObject.Find(cName) != null)
                {
                    cName = containerName + " " + index.ToString();
                    index++;
                }
            }


            var container = new GameObject(cName);

            container.transform.position = new Vector3(0, 0, 0);
            CurrentTerrainIndex          = 0;

            Vector2Int tCount = new Vector2Int(terrainCount.x, terrainCount.y);

            float maxElevation   = floatReader.MaxElevation;
            float minElevation   = floatReader.MinElevation;
            float ElevationRange = maxElevation - minElevation;

            var sizeX = Mathf.Floor(m_terrainDimensions.x * terrainScale.x * 10) / terrainCount.x;
            var sizeZ = Mathf.Floor(m_terrainDimensions.y * terrainScale.z * 10) / terrainCount.y;
            var sizeY = (ElevationRange) / ElevationScaleValue * TerrainExaggeration * 100 * terrainScale.y * 10;

            Vector3 size;

            if (terrainElevation == TerrainElevation.RealWorldElevation)
            {
                sizeY = ((ElevationRange)) * terrainScale.y;
                size  = new Vector3(sizeX, sizeY, sizeZ);
            }
            else
            {
                sizeY = sizeY * 10;
                size  = new Vector3(sizeX, sizeY, sizeZ);
            }

            string resultFolder   = "Assets/Generated GIS Terrains";
            string resultFullPath = Path.Combine(Application.dataPath, "Generated GIS Terrains");

            if (!Directory.Exists(resultFullPath))
            {
                Directory.CreateDirectory(resultFullPath);
            }
            string dateStr = DateTime.Now.ToString("yyyy-MM-dd HH-mm-") + DateTime.Now.Second.ToString();

            resultFolder  += "/" + dateStr;
            resultFullPath = Path.Combine(resultFullPath, dateStr);
            if (!Directory.Exists(resultFullPath))
            {
                Directory.CreateDirectory(resultFullPath);
            }



            terrains = new TerrainObject[tCount.x, tCount.y];

            container.AddComponent <TerrainContainerObject>();

            var terrainContainer = container.GetComponent <TerrainContainerObject>();

            terrainContainer.terrainCount = new Vector2Int(terrainCount.x, terrainCount.y);

            terrainContainer.GeneratedTerrainfolder = resultFolder;

            terrainContainer.scale = terrainScale;

            terrainContainer.size = new Vector3(size.x * tCount.x, size.y, size.z * tCount.y);

            //Set Terrain Coordinates to the container TerrainContainer script (Lat/lon) + Mercator
            terrainContainer.TLPointLatLong = floatReader.TopLeftPoint;
            terrainContainer.DRPointLatLong = floatReader.DownRightPoint;

            terrainContainer.TLPointMercator = GeoRefConversion.LatLongToMercat(terrainContainer.TLPointLatLong.x, terrainContainer.TLPointLatLong.y);
            terrainContainer.DRPointMercator = GeoRefConversion.LatLongToMercat(terrainContainer.DRPointLatLong.x, terrainContainer.DRPointLatLong.y);

            //Terrain Size Bounds
            var centre = new Vector3(terrainContainer.size.x / 2, 0, terrainContainer.size.z / 2);

            terrainContainer.GlobalTerrainBounds = new Bounds(centre, new Vector3(centre.x + terrainContainer.size.x / 2, 0, centre.z + terrainContainer.size.z / 2));



            for (int x = 0; x < tCount.x; x++)
            {
                for (int y = 0; y < tCount.y; y++)
                {
                    terrains[x, y]           = CreateTerrain(terrainContainer, x, y, size, terrainScale);
                    terrains[x, y].container = terrainContainer;
                }
            }

            terrainContainer.terrains = terrains;

            GeneratedContainer = terrainContainer;

            phase = GeneratingTerrainPhase.generateHeightmaps;
        }
        public static void GenerateGrass(TerrainContainerObject m_container, List <GISTerrainLoaderSO_Grass> m_GrassPrefabs, float m_GrassDensity, float m_GrassScaleFactor, float m_DetailDistance, Dictionary <string, OSMNode> nodes, Dictionary <string, OSMWay> ways, List <OSMMapMembers> relations)
        {
            GrassPrefabs     = m_GrassPrefabs;
            container        = m_container;
            GrassScaleFactor = m_GrassScaleFactor;
            DetailDistance   = m_DetailDistance;

            AddDetailsLayersToTerrains();

            TerrainData tdata            = container.terrains[0, 0].terrainData;
            int         detailResolution = tdata.detailResolution;


            alreadyCreated = new List <string>();

            details = new List <int[, ]>(container.terrains.Length);

            foreach (var item in container.terrains)
            {
                for (int i = 0; i < GrassPrefabs.Count; i++)
                {
                    details.Add(new int[detailResolution, detailResolution]);
                }
            }

            var detailsInPoint = new float[GrassPrefabs.Count];

            var grassWays = new List <OSMWay>();

            foreach (KeyValuePair <string, OSMWay> pair in ways)
            {
                OSMWay w = pair.Value;
                if (w.HasTags("landuse", "grass", "farmland", "forest", "meadow", "park", "pasture", "recreation_ground") ||
                    w.HasTags("leisure", "park", "golf_course") || w.HasTags("natural", "scrub", "wood"))
                {
                    grassWays.Add(w);
                }
            }

            var totalCount = grassWays.Count + container.terrainCount.x;

            float density = m_GrassDensity / 100f;

            if (density > 1)
            {
                density = 1;
            }

            density *= 64;

            for (int i = 0; i < grassWays.Count; i++)
            {
                OSMWay way = grassWays[i];

                if (alreadyCreated.Contains(way.id))
                {
                    continue;
                }
                alreadyCreated.Add(way.id);

                if (way.nodeRefs.Count == 0)
                {
                    continue;
                }

                List <Vector3> Points = new List <Vector3>();

                float pxmin = float.MaxValue, pxmax = float.MinValue, pymin = float.MaxValue, pymax = float.MinValue;

                for (int m = 0; m < way.nodeRefs.Count; m++)
                {
                    string nodeRef = way.nodeRefs[m];

                    OSMNode node;
                    if (!nodes.TryGetValue(nodeRef, out node))
                    {
                        continue;
                    }


                    var NodeP_Merc = GeoRefConversion.LatLongToMercat(node.Longitude, node.Latitude);

                    Vector3 wspostion = GeoRefConversion.MercatCoordsToWorld(NodeP_Merc.x, 0, NodeP_Merc.y, container) - container.transform.position;

                    wspostion = new Vector3(wspostion.x / tdata.size.x * detailResolution, 0, wspostion.z / tdata.size.z * detailResolution);

                    if (wspostion.x < pxmin)
                    {
                        pxmin = wspostion.x;
                    }
                    if (wspostion.x > pxmax)
                    {
                        pxmax = wspostion.x;
                    }
                    if (wspostion.z < pymin)
                    {
                        pymin = wspostion.z;
                    }
                    if (wspostion.z > pymax)
                    {
                        pymax = wspostion.z;
                    }

                    Points.Add(wspostion);
                }

                if (Points.Count < 3)
                {
                    continue;
                }

                Vector3[] points = Points.ToArray();
                for (int x = (int)pxmin; x < pxmax; x++)
                {
                    int tix = Mathf.FloorToInt(x / (float)detailResolution);
                    if (tix < 0 || tix >= container.terrainCount.x)
                    {
                        continue;
                    }

                    int tx = x - tix * detailResolution;

                    for (int y = (int)pymin; y < pymax; y++)
                    {
                        int tiy = Mathf.FloorToInt(y / (float)detailResolution);
                        if (tiy >= container.terrainCount.y || tiy < 0)
                        {
                            continue;
                        }

                        int tIndex = tiy * container.terrainCount.x + tix;
                        if (tIndex < 0 || tIndex >= container.terrains.Length)
                        {
                            continue;
                        }

                        bool intersect = Extensions.IsPointInPolygon(points, x + 0.5f, y - 0.5f);
                        if (!intersect)
                        {
                            continue;
                        }

                        int ty = y - tiy * detailResolution;

                        if (GrassPrefabs.Count == 1)
                        {
                            details[tIndex][ty, tx] = (int)density;
                        }
                        else
                        {
                            float totalInPoint = 0;

                            int tIndex2 = tIndex * GrassPrefabs.Count;

                            for (int k = 0; k < GrassPrefabs.Count; k++)
                            {
                                float v = Random.Range(0f, 1f);
                                detailsInPoint[k] = v;
                                totalInPoint     += v;
                            }

                            for (int k = 0; k < GrassPrefabs.Count; k++)
                            {
                                int v = (int)(detailsInPoint[k] / totalInPoint * density);
                                if (v > 255)
                                {
                                    v = 255;
                                }
                                details[tIndex2 + k][ty, tx] = v;
                            }
                        }
                    }
                }
            }


            for (int x = 0; x < container.terrainCount.x; x++)
            {
                for (int y = 0; y < container.terrainCount.y; y++)
                {
                    for (int prefabIndex = 0; prefabIndex < GrassPrefabs.Count; prefabIndex++)
                    {
                        int tIndex = y * container.terrainCount.x + x;

                        container.terrains[x, y].terrainData.SetDetailLayer(0, 0, prefabIndex,
                                                                            details[tIndex * GrassPrefabs.Count + prefabIndex]);
                    }
                }
            }
        }