public static Vector3 MercatCoordsToWorld(double mx, float y, double mz, TerrainContainerObject container) { var sx = (mx - container.TLPointMercator.x) / (container.DRPointMercator.x - container.TLPointMercator.x) * container.size.x; var sz = (1 - (mz - container.TLPointMercator.y) / (container.DRPointMercator.y - container.TLPointMercator.y)) * container.size.z; return(new Vector3((float)sx, y * container.scale.y, (float)sz)); }
private TerrainObject CreateTerrain(TerrainContainerObject parent, int x, int y, Vector3 size, Vector3 scale) { TerrainData tdata = new TerrainData { baseMapResolution = 32, heightmapResolution = 32 }; tdata.heightmapResolution = heightmapResolution; tdata.baseMapResolution = baseMapResolution; tdata.SetDetailResolution(detailResolution, resolutionPerPatch); tdata.size = size; GameObject GO = Terrain.CreateTerrainGameObject(tdata); GO.gameObject.SetActive(true); GO.name = string.Format("{0}-{1}", x, y); GO.transform.parent = parent.gameObject.transform; GO.transform.position = new Vector3(size.x * x, 0, size.z * y); GO.isStatic = false; TerrainObject item = GO.AddComponent <TerrainObject>(); item.Number = new Vector2Int(x, y); item.size = size; item.ElevationFilePath = TerrainFilePath; string filename = Path.Combine(parent.GeneratedTerrainfolder, GO.name) + ".asset"; AssetDatabase.CreateAsset(tdata, filename); AssetDatabase.SaveAssets(); return(item); }
private static void AddTreesToTerrains(TerrainContainerObject container, List <GameObject> m_treesPrefabs) { TreePrototype[] prototypes = new TreePrototype[m_treesPrefabs.Count]; for (int i = 0; i < prototypes.Length; i++) { if (m_treesPrefabs[i] != null) { prototypes[i] = new TreePrototype { prefab = m_treesPrefabs[i] }; } } foreach (var item in container.terrains) { item.terrainData.treePrototypes = prototypes; item.terrainData.treeInstances = new TreeInstance[0]; } }
/// <summary> /// Generate HeightMaps by spliting Single terrain elevation file to tiles /// </summary> /// <param name="prefs"></param> /// <param name="item"></param> public void GenerateHeightMap(TerrainContainerObject container, TerrainObject item) { tdata = item.terrain.terrainData; if (tdataHeightmap == null) { tdataHeightmap = new float[tdata.heightmapHeight, tdata.heightmapWidth]; } //if (tdata == null) //{ // tdata.baseMapResolution = prefs.baseMapResolution; // tdata.SetDetailResolution(prefs.detailResolution, prefs.resolutionPerPatch); // tdata.heightmapResolution = prefs.heightmapResolution; // tdata.size = item.size; // if (tdataHeightmap == null) // tdataHeightmap = new float[tdata.heightmapHeight, tdata.heightmapWidth]; //} float elevationRange = MaxElevation - MinElevation; long startTime = DateTime.Now.Ticks; float thx = tdata.heightmapWidth - 1; float thy = tdata.heightmapHeight - 1; var y_Terrain_Col_num = (mapSize_row_y / container.terrainCount.x); var x_Terrain_row_num = (mapSize_col_x / container.terrainCount.y); // heightmap rotation int tw = tdata.heightmapWidth; int th = tdata.heightmapHeight; for (int x = lastX; x < tw; x++) { for (int y = 0; y < th; y++) { var x_from = item.Number.x * x_Terrain_row_num; var x_To = item.Number.x * x_Terrain_row_num + x_Terrain_row_num - 1; var y_from = item.Number.y * y_Terrain_Col_num; var y_To = item.Number.y * y_Terrain_Col_num + y_Terrain_Col_num - 1; float px = Mathf.Lerp(x_from, x_To, x / thx); float py = Mathf.Lerp(y_from, y_To, y / thy); var el = _floatheightData[(int)((px)), (int)(py)]; tdataHeightmap[y, x] = (el - MinElevation) / elevationRange; } lastX = x; //progress = hx / (float)tdata.heightmapWidth; if (new TimeSpan(DateTime.Now.Ticks - startTime).TotalSeconds > 1) { return; } } lastX = 0; tdata.SetHeights(0, 0, tdataHeightmap); tdata = null; generateComplete = true; }
private static void GenerateTerrainsTrees(float TreeScaleFactor, float TreeRandomScaleFactor, TerrainContainerObject container, float treeDensity, int factorX, int factorY, Rect rect, List <Vector3> points) { Bounds bounds = container.GlobalTerrainBounds; Vector3 Bmin = bounds.min; Vector3 Bmax = bounds.max; float TreeValue = 400f / treeDensity; float rectx = (rect.xMax - rect.xMin) / factorX; float recty = (rect.yMax - rect.yMin) / factorY; int counter = 0; Vector3[] ps = points.ToArray(); int Max_S_x = Mathf.Max(Mathf.FloorToInt((Bmin.x - rect.xMin) / rectx + 1), 0); int Min_E_x = Mathf.Min(Mathf.FloorToInt((Bmax.x - rect.xMin) / rectx), factorX); int Max_S_y = Mathf.Max(Mathf.FloorToInt((Bmin.z - rect.yMin) / recty + 1), 0); int Min_E_y = Mathf.Min(Mathf.FloorToInt((Bmax.z - rect.yMin) / recty), factorY); for (int x = Max_S_x; x < Min_E_x; x++) { float rx = x * rectx + rect.xMin; for (int y = Max_S_y; y < Min_E_y; y++) { float ry = y * recty + rect.yMin; float px = rx + UnityEngine.Random.Range(-TreeValue, TreeValue); float pz = ry + UnityEngine.Random.Range(-TreeValue, TreeValue); if (Extensions.IsPointInPolygon(ps, px, pz)) { SetTreeToTerrain(TreeScaleFactor, TreeRandomScaleFactor, container, new Vector3(px, 0, pz)); counter++; } } } }
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); } } }
private static void SetTreeToTerrain(float TreeScaleFactor, float RandomScaleFactor, TerrainContainerObject container, Vector3 pos) { for (int x = 0; x < container.terrainCount.x; x++) { for (int y = 0; y < container.terrainCount.y; y++) { TerrainObject item = container.terrains[x, y]; Terrain terrain = item.terrain; terrain.treeBillboardDistance = BillBoardStartDistance; terrain.treeDistance = TreeDistance; TerrainData tData = terrain.terrainData; Vector3 terPos = terrain.transform.position; Vector3 localPos = pos - terPos; float heightmapWidth = (tData.heightmapWidth - 1) * tData.heightmapScale.x; float heightmapHeight = (tData.heightmapHeight - 1) * tData.heightmapScale.z; if (localPos.x > 0 && localPos.z > 0 && localPos.x < heightmapWidth && localPos.z < heightmapHeight) { terrain.AddTreeInstance(new TreeInstance { color = Color.white, heightScale = TreeScaleFactor + UnityEngine.Random.Range(-RandomScaleFactor, RandomScaleFactor), lightmapColor = Color.white, position = new Vector3(localPos.x / heightmapWidth, 0, localPos.z / heightmapHeight), prototypeIndex = UnityEngine.Random.Range(0, tData.treePrototypes.Length), widthScale = TreeScaleFactor + UnityEngine.Random.Range(-RandomScaleFactor, RandomScaleFactor) }); break; } } } }
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 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 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]); } } } }