/* INFINITY CODE */ /* https://infinity-code.com */ using System; using System.IO; using System.Text.RegularExpressions; using InfinityCode.RealWorldTerrain.Generators; using InfinityCode.RealWorldTerrain.Windows; using UnityEditor; using UnityEngine; namespace InfinityCode.RealWorldTerrain.Phases { public class RealWorldTerrainGenerateTerrainsPhase : RealWorldTerrainPhase { public static RealWorldTerrainItem activeTerrainItem; private RealWorldTerrainContainer container; private double maxElevation; private double minElevation; private Vector3 size; private Vector3 scale; public override string title { get { return "Generate Terrains..."; } } private static RealWorldTerrainItem AddTerrainItem(int x, int y, double x1, double y1, double x2, double y2, Vector3 size, Vector3 scale, double maxElevation, double minElevation, GameObject GO) { RealWorldTerrainItem item = GO.AddComponent(); prefs.Apply(item); double tlx, tly, brx, bry; RealWorldTerrainUtils.MercatToLatLong(x1, y1, out tlx, out tly); RealWorldTerrainUtils.MercatToLatLong(x2, y2, out brx, out bry); item.SetCoordinates(x1, y1, x2, y2, tlx, tly, brx, bry); item.maxElevation = maxElevation; item.minElevation = minElevation; item.scale = scale; item.size = size; item.x = x; item.ry = prefs.terrainCount.y - y - 1; item.y = y; item.bounds = new Bounds(item.transform.position + size / 2, size); activeTerrainItem = item; return item; } private RealWorldTerrainItem CreateMesh(Transform parent, int x, int y, double x1, double y1, double x2, double y2, Vector3 size, Vector3 scale, double maxElevation, double minElevation) { GameObject GO = new GameObject(); GO.transform.parent = parent; GO.transform.localPosition = new Vector3(size.x * x, 0, size.z * y); RealWorldTerrainItem item = AddTerrainItem(x, y, x1, y1, x2, y2, size, scale, maxElevation, minElevation, GO); GO.name = Regex.Replace(RealWorldTerrainPrefs.LoadPref("TerrainName", "Terrain {x}x{y}"), @"{\w+}", ReplaceTerrainToken); return item; } private RealWorldTerrainItem CreateTerrain(Transform parent, int x, int y, double x1, double y1, double x2, double y2, Vector3 size, Vector3 scale, double maxElevation, double minElevation) { TerrainData tdata = new TerrainData { baseMapResolution = prefs.baseMapResolution, heightmapResolution = prefs.heightmapResolution, alphamapResolution = prefs.controlTextureResolution }; tdata.SetDetailResolution(prefs.detailResolution, prefs.resolutionPerPatch); tdata.size = size; GameObject GO = Terrain.CreateTerrainGameObject(tdata); GO.transform.parent = parent; GO.transform.localPosition = new Vector3(size.x * x, 0, size.z * y); #if UNITY_2019_2_OR_NEWER GameObjectUtility.SetStaticEditorFlags(GO, GameObjectUtility.GetStaticEditorFlags(GO) & ~StaticEditorFlags.ContributeGI); #else GameObjectUtility.SetStaticEditorFlags(GO, GameObjectUtility.GetStaticEditorFlags(GO) & ~StaticEditorFlags.LightmapStatic); #endif RealWorldTerrainItem item = AddTerrainItem(x, y, x1, y1, x2, y2, size, scale, maxElevation, minElevation, GO); item.terrain = GO.GetComponent(); GO.name = Regex.Replace(RealWorldTerrainPrefs.LoadPref("TerrainName", "Terrain {x}x{y}"), @"{\w+}", ReplaceTerrainToken); string filename = Path.Combine(container.folder, GO.name) + ".asset"; AssetDatabase.CreateAsset(tdata, filename); AssetDatabase.SaveAssets(); return item; } public override void Enter() { if (index >= prefs.terrainCount) { Complete(); return; } RealWorldTerrainVector2i tCount = prefs.terrainCount; int x = index % tCount.x; int y = index / tCount.x; double fromX = prefs.leftLongitude; double fromY = prefs.topLatitude; double toX = prefs.rightLongitude; double toY = prefs.bottomLatitude; RealWorldTerrainUtils.LatLongToMercat(ref fromX, ref fromY); RealWorldTerrainUtils.LatLongToMercat(ref toX, ref toY); double tx1 = (toX - fromX) * (x / (double)tCount.x) + fromX; double ty1 = toY - (toY - fromY) * ((y + 1) / (double)tCount.y); double tx2 = (toX - fromX) * ((x + 1) / (double)tCount.x) + fromX; double ty2 = toY - (toY - fromY) * (y / (double)tCount.y); int tIndex = y * tCount.x + x; progress = index / (float)tCount; if (prefs.resultType == RealWorldTerrainResultType.terrain) { terrains[x, y] = container.terrains[tIndex] = CreateTerrain(container.transform, x, y, tx1, ty1, tx2, ty2, size, scale, maxElevation, minElevation); } else if (prefs.resultType == RealWorldTerrainResultType.mesh) { terrains[x, y] = container.terrains[tIndex] = CreateMesh(container.transform, x, y, tx1, ty1, tx2, ty2, size, scale, maxElevation, minElevation); } container.terrains[tIndex].container = container; index++; } public override void Finish() { activeTerrainItem = null; container = null; } private string ReplaceResultToken(Match match) { string v = match.Value.ToLower().Trim('{', '}'); if (v == "title") return prefs.title; if (v == "tllat") return prefs.topLatitude.ToString(); if (v == "tllng") return prefs.leftLongitude.ToString(); if (v == "brlat") return prefs.bottomLatitude.ToString(); if (v == "brlng") return prefs.rightLongitude.ToString(); if (v == "cx") return prefs.terrainCount.x.ToString(); if (v == "cy") return prefs.terrainCount.y.ToString(); if (v == "st") return prefs.sizeType.ToString(); if (v == "me") return prefs.maxElevationType.ToString(); if (v == "mu") return prefs.nodataValue.ToString(); if (v == "ds") return prefs.depthSharpness.ToString(); if (v == "dr") return prefs.detailResolution.ToString(); if (v == "rpp") return prefs.resolutionPerPatch.ToString(); if (v == "bmr") return prefs.baseMapResolution.ToString(); if (v == "hmr") return prefs.heightmapResolution.ToString(); if (v == "tp") return prefs.textureProvider.ToString(); if (v == "tw") return prefs.textureSize.x.ToString(); if (v == "th") return prefs.textureSize.y.ToString(); if (v == "tml") return prefs.maxTextureLevel.ToString(); if (v == "ticks") return DateTime.Now.Ticks.ToString(); return v; } private string ReplaceTerrainToken(Match match) { string v = match.Value.ToLower().Trim('{', '}'); if (v == "tllat") return activeTerrainItem.topLatitude.ToString(); if (v == "tllng") return activeTerrainItem.leftLongitude.ToString(); if (v == "brlat") return activeTerrainItem.bottomLatitude.ToString(); if (v == "brlng") return activeTerrainItem.rightLongitude.ToString(); if (v == "x") return activeTerrainItem.x.ToString(); if (v == "y") return activeTerrainItem.ry.ToString(); return v; } public override void Start() { string resultFolder = "Assets/RWT_Result"; string resultFullPath = Path.Combine(Application.dataPath, "RWT_Result"); if (!Directory.Exists(resultFullPath)) Directory.CreateDirectory(resultFullPath); string dateStr = DateTime.Now.ToString("yyyy-MM-dd HH-mm"); resultFolder += "/" + dateStr; resultFullPath = Path.Combine(resultFullPath, dateStr); if (!Directory.Exists(resultFullPath)) Directory.CreateDirectory(resultFullPath); else { int index = 1; while (true) { string path = resultFullPath + "_" + index; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); resultFolder += "_" + index; break; } index++; } } const float scaleYCoof = 1000; const float baseScale = 1000; double fromX = prefs.leftLongitude; double fromY = prefs.topLatitude; double toX = prefs.rightLongitude; double toY = prefs.bottomLatitude; double rangeX = toX - fromX; double rangeY = fromY - toY; RealWorldTerrainVector2i tCount = prefs.terrainCount; double sizeX = 0; double sizeZ = 0; if (prefs.sizeType == 0 || prefs.sizeType == 2) { double scfY = Math.Sin(fromY * Mathf.Deg2Rad); double sctY = Math.Sin(toY * Mathf.Deg2Rad); double ccfY = Math.Cos(fromY * Mathf.Deg2Rad); double cctY = Math.Cos(toY * Mathf.Deg2Rad); double cX = Math.Cos(rangeX * Mathf.Deg2Rad); double sizeX1 = Math.Abs(RealWorldTerrainUtils.EARTH_RADIUS * Math.Acos(scfY * scfY + ccfY * ccfY * cX)); double sizeX2 = Math.Abs(RealWorldTerrainUtils.EARTH_RADIUS * Math.Acos(sctY * sctY + cctY * cctY * cX)); sizeX = (sizeX1 + sizeX2) / 2.0; sizeZ = RealWorldTerrainUtils.EARTH_RADIUS * Math.Acos(scfY * sctY + ccfY * cctY); } else if (prefs.sizeType == 1) { sizeX = Math.Abs(rangeX / 360 * RealWorldTerrainUtils.EQUATOR_LENGTH); sizeZ = Math.Abs(rangeY / 360 * RealWorldTerrainUtils.EQUATOR_LENGTH); } maxElevation = RealWorldTerrainUtils.MAX_ELEVATION; minElevation = -RealWorldTerrainUtils.MAX_ELEVATION; double sX = sizeX / tCount.x * baseScale * prefs.terrainScale.x; double sY; double sZ = sizeZ / tCount.y * baseScale * prefs.terrainScale.z; if (prefs.elevationRange == RealWorldTerrainElevationRange.autoDetect) { double maxEl, minEl; RealWorldTerrainElevationGenerator.GetElevationRange(out minEl, out maxEl); if (prefs.generateUnderWater && prefs.nodataValue != 0 && minEl > prefs.nodataValue) minEl = prefs.nodataValue; maxElevation = maxEl + prefs.autoDetectElevationOffset.y; minElevation = minEl - prefs.autoDetectElevationOffset.x; } else if (prefs.elevationRange == RealWorldTerrainElevationRange.fixedValue) { maxElevation = prefs.fixedMaxElevation; minElevation = prefs.fixedMinElevation; } sY = (maxElevation - minElevation) / scaleYCoof * baseScale * prefs.terrainScale.y; if (prefs.sizeType == 2) { double scaleX = sX / prefs.fixedTerrainSize.x; double scaleZ = sZ / prefs.fixedTerrainSize.z; sX = prefs.fixedTerrainSize.x; sZ = prefs.fixedTerrainSize.z; sY /= (scaleX + scaleZ) / 2; } sX = Math.Round(sX); sY = Math.Round(sY); sZ = Math.Round(sZ); if (sY < 1) sY = 1; RealWorldTerrainWindow.terrains = new RealWorldTerrainItem[tCount.x, tCount.y]; scale = new Vector3((float)(sX * tCount.x / rangeX), (float)(sY / (maxElevation - minElevation)), (float)(sZ * tCount.y / rangeY)); string baseName = Regex.Replace(RealWorldTerrainPrefs.LoadPref("ResultName", "RealWorld Terrain"), @"{\w+}", ReplaceResultToken); string containerName = baseName; if (RealWorldTerrainPrefs.LoadPref("AppendIndex", true)) { int nameIndex = 0; while (GameObject.Find("/" + containerName)) { nameIndex++; containerName = baseName + " " + nameIndex; } } size = new Vector3((float)sX, (float)sY, (float)sZ); container = RealWorldTerrainWindow.container = new GameObject(containerName).AddComponent(); prefs.Apply(container); double mx1, my1, mx2, my2; RealWorldTerrainUtils.LatLongToMercat(fromX, fromY, out mx1, out my1); RealWorldTerrainUtils.LatLongToMercat(toX, toY, out mx2, out my2); container.SetCoordinates(mx1, my1, mx2, my2, fromX, fromY, toX, toY); container.folder = resultFolder; container.scale = scale; container.size = new Vector3(size.x * tCount.x, size.y, size.z * tCount.y); container.terrainCount = prefs.terrainCount; container.terrains = new RealWorldTerrainItem[prefs.terrainCount.x * prefs.terrainCount.y]; container.minElevation = minElevation; container.maxElevation = maxElevation; container.title = prefs.title; if (prefs.useAnchor) { RealWorldTerrainUtils.LatLongToMercat(prefs.anchorLongitude, prefs.anchorLatitude, out mx1, out my1); Vector3 p = RealWorldTerrainEditorUtils.CoordsToWorld(mx1, 0, my1, container); container.transform.position = -p; } if (prefs.alignWaterLine) { Vector3 p = new Vector3(0, -(float)minElevation * scale.y, 0); container.transform.position -= p; } container.bounds = new Bounds(container.transform.position + container.size / 2, container.size); } } }