RealWorldTerrainGenerateTerrainsPhase.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /* INFINITY CODE */
  2. /* https://infinity-code.com */
  3. using System;
  4. using System.IO;
  5. using System.Text.RegularExpressions;
  6. using InfinityCode.RealWorldTerrain.Generators;
  7. using InfinityCode.RealWorldTerrain.Windows;
  8. using UnityEditor;
  9. using UnityEngine;
  10. namespace InfinityCode.RealWorldTerrain.Phases
  11. {
  12. public class RealWorldTerrainGenerateTerrainsPhase : RealWorldTerrainPhase
  13. {
  14. public static RealWorldTerrainItem activeTerrainItem;
  15. private RealWorldTerrainContainer container;
  16. private double maxElevation;
  17. private double minElevation;
  18. private Vector3 size;
  19. private Vector3 scale;
  20. public override string title
  21. {
  22. get { return "Generate Terrains..."; }
  23. }
  24. 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)
  25. {
  26. RealWorldTerrainItem item = GO.AddComponent<RealWorldTerrainItem>();
  27. prefs.Apply(item);
  28. double tlx, tly, brx, bry;
  29. RealWorldTerrainUtils.MercatToLatLong(x1, y1, out tlx, out tly);
  30. RealWorldTerrainUtils.MercatToLatLong(x2, y2, out brx, out bry);
  31. item.SetCoordinates(x1, y1, x2, y2, tlx, tly, brx, bry);
  32. item.maxElevation = maxElevation;
  33. item.minElevation = minElevation;
  34. item.scale = scale;
  35. item.size = size;
  36. item.x = x;
  37. item.ry = prefs.terrainCount.y - y - 1;
  38. item.y = y;
  39. item.bounds = new Bounds(item.transform.position + size / 2, size);
  40. activeTerrainItem = item;
  41. return item;
  42. }
  43. 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)
  44. {
  45. GameObject GO = new GameObject();
  46. GO.transform.parent = parent;
  47. GO.transform.localPosition = new Vector3(size.x * x, 0, size.z * y);
  48. RealWorldTerrainItem item = AddTerrainItem(x, y, x1, y1, x2, y2, size, scale, maxElevation, minElevation, GO);
  49. GO.name = Regex.Replace(RealWorldTerrainPrefs.LoadPref("TerrainName", "Terrain {x}x{y}"), @"{\w+}", ReplaceTerrainToken);
  50. return item;
  51. }
  52. 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)
  53. {
  54. TerrainData tdata = new TerrainData
  55. {
  56. baseMapResolution = prefs.baseMapResolution,
  57. heightmapResolution = prefs.heightmapResolution,
  58. alphamapResolution = prefs.controlTextureResolution
  59. };
  60. tdata.SetDetailResolution(prefs.detailResolution, prefs.resolutionPerPatch);
  61. tdata.size = size;
  62. GameObject GO = Terrain.CreateTerrainGameObject(tdata);
  63. GO.transform.parent = parent;
  64. GO.transform.localPosition = new Vector3(size.x * x, 0, size.z * y);
  65. #if UNITY_2019_2_OR_NEWER
  66. GameObjectUtility.SetStaticEditorFlags(GO, GameObjectUtility.GetStaticEditorFlags(GO) & ~StaticEditorFlags.ContributeGI);
  67. #else
  68. GameObjectUtility.SetStaticEditorFlags(GO, GameObjectUtility.GetStaticEditorFlags(GO) & ~StaticEditorFlags.LightmapStatic);
  69. #endif
  70. RealWorldTerrainItem item = AddTerrainItem(x, y, x1, y1, x2, y2, size, scale, maxElevation, minElevation, GO);
  71. item.terrain = GO.GetComponent<Terrain>();
  72. GO.name = Regex.Replace(RealWorldTerrainPrefs.LoadPref("TerrainName", "Terrain {x}x{y}"), @"{\w+}", ReplaceTerrainToken);
  73. string filename = Path.Combine(container.folder, GO.name) + ".asset";
  74. AssetDatabase.CreateAsset(tdata, filename);
  75. AssetDatabase.SaveAssets();
  76. return item;
  77. }
  78. public override void Enter()
  79. {
  80. if (index >= prefs.terrainCount)
  81. {
  82. Complete();
  83. return;
  84. }
  85. RealWorldTerrainVector2i tCount = prefs.terrainCount;
  86. int x = index % tCount.x;
  87. int y = index / tCount.x;
  88. double fromX = prefs.leftLongitude;
  89. double fromY = prefs.topLatitude;
  90. double toX = prefs.rightLongitude;
  91. double toY = prefs.bottomLatitude;
  92. RealWorldTerrainUtils.LatLongToMercat(ref fromX, ref fromY);
  93. RealWorldTerrainUtils.LatLongToMercat(ref toX, ref toY);
  94. double tx1 = (toX - fromX) * (x / (double)tCount.x) + fromX;
  95. double ty1 = toY - (toY - fromY) * ((y + 1) / (double)tCount.y);
  96. double tx2 = (toX - fromX) * ((x + 1) / (double)tCount.x) + fromX;
  97. double ty2 = toY - (toY - fromY) * (y / (double)tCount.y);
  98. int tIndex = y * tCount.x + x;
  99. progress = index / (float)tCount;
  100. if (prefs.resultType == RealWorldTerrainResultType.terrain)
  101. {
  102. terrains[x, y] = container.terrains[tIndex] = CreateTerrain(container.transform, x, y, tx1, ty1, tx2, ty2, size, scale, maxElevation, minElevation);
  103. }
  104. else if (prefs.resultType == RealWorldTerrainResultType.mesh)
  105. {
  106. terrains[x, y] = container.terrains[tIndex] = CreateMesh(container.transform, x, y, tx1, ty1, tx2, ty2, size, scale, maxElevation, minElevation);
  107. }
  108. container.terrains[tIndex].container = container;
  109. index++;
  110. }
  111. public override void Finish()
  112. {
  113. activeTerrainItem = null;
  114. container = null;
  115. }
  116. private string ReplaceResultToken(Match match)
  117. {
  118. string v = match.Value.ToLower().Trim('{', '}');
  119. if (v == "title") return prefs.title;
  120. if (v == "tllat") return prefs.topLatitude.ToString();
  121. if (v == "tllng") return prefs.leftLongitude.ToString();
  122. if (v == "brlat") return prefs.bottomLatitude.ToString();
  123. if (v == "brlng") return prefs.rightLongitude.ToString();
  124. if (v == "cx") return prefs.terrainCount.x.ToString();
  125. if (v == "cy") return prefs.terrainCount.y.ToString();
  126. if (v == "st") return prefs.sizeType.ToString();
  127. if (v == "me") return prefs.maxElevationType.ToString();
  128. if (v == "mu") return prefs.nodataValue.ToString();
  129. if (v == "ds") return prefs.depthSharpness.ToString();
  130. if (v == "dr") return prefs.detailResolution.ToString();
  131. if (v == "rpp") return prefs.resolutionPerPatch.ToString();
  132. if (v == "bmr") return prefs.baseMapResolution.ToString();
  133. if (v == "hmr") return prefs.heightmapResolution.ToString();
  134. if (v == "tp") return prefs.textureProvider.ToString();
  135. if (v == "tw") return prefs.textureSize.x.ToString();
  136. if (v == "th") return prefs.textureSize.y.ToString();
  137. if (v == "tml") return prefs.maxTextureLevel.ToString();
  138. if (v == "ticks") return DateTime.Now.Ticks.ToString();
  139. return v;
  140. }
  141. private string ReplaceTerrainToken(Match match)
  142. {
  143. string v = match.Value.ToLower().Trim('{', '}');
  144. if (v == "tllat") return activeTerrainItem.topLatitude.ToString();
  145. if (v == "tllng") return activeTerrainItem.leftLongitude.ToString();
  146. if (v == "brlat") return activeTerrainItem.bottomLatitude.ToString();
  147. if (v == "brlng") return activeTerrainItem.rightLongitude.ToString();
  148. if (v == "x") return activeTerrainItem.x.ToString();
  149. if (v == "y") return activeTerrainItem.ry.ToString();
  150. return v;
  151. }
  152. public override void Start()
  153. {
  154. string resultFolder = "Assets/RWT_Result";
  155. string resultFullPath = Path.Combine(Application.dataPath, "RWT_Result");
  156. if (!Directory.Exists(resultFullPath)) Directory.CreateDirectory(resultFullPath);
  157. string dateStr = DateTime.Now.ToString("yyyy-MM-dd HH-mm");
  158. resultFolder += "/" + dateStr;
  159. resultFullPath = Path.Combine(resultFullPath, dateStr);
  160. if (!Directory.Exists(resultFullPath)) Directory.CreateDirectory(resultFullPath);
  161. else
  162. {
  163. int index = 1;
  164. while (true)
  165. {
  166. string path = resultFullPath + "_" + index;
  167. if (!Directory.Exists(path))
  168. {
  169. Directory.CreateDirectory(path);
  170. resultFolder += "_" + index;
  171. break;
  172. }
  173. index++;
  174. }
  175. }
  176. const float scaleYCoof = 1000;
  177. const float baseScale = 1000;
  178. double fromX = prefs.leftLongitude;
  179. double fromY = prefs.topLatitude;
  180. double toX = prefs.rightLongitude;
  181. double toY = prefs.bottomLatitude;
  182. double rangeX = toX - fromX;
  183. double rangeY = fromY - toY;
  184. RealWorldTerrainVector2i tCount = prefs.terrainCount;
  185. double sizeX = 0;
  186. double sizeZ = 0;
  187. if (prefs.sizeType == 0 || prefs.sizeType == 2)
  188. {
  189. double scfY = Math.Sin(fromY * Mathf.Deg2Rad);
  190. double sctY = Math.Sin(toY * Mathf.Deg2Rad);
  191. double ccfY = Math.Cos(fromY * Mathf.Deg2Rad);
  192. double cctY = Math.Cos(toY * Mathf.Deg2Rad);
  193. double cX = Math.Cos(rangeX * Mathf.Deg2Rad);
  194. double sizeX1 = Math.Abs(RealWorldTerrainUtils.EARTH_RADIUS * Math.Acos(scfY * scfY + ccfY * ccfY * cX));
  195. double sizeX2 = Math.Abs(RealWorldTerrainUtils.EARTH_RADIUS * Math.Acos(sctY * sctY + cctY * cctY * cX));
  196. sizeX = (sizeX1 + sizeX2) / 2.0;
  197. sizeZ = RealWorldTerrainUtils.EARTH_RADIUS * Math.Acos(scfY * sctY + ccfY * cctY);
  198. }
  199. else if (prefs.sizeType == 1)
  200. {
  201. sizeX = Math.Abs(rangeX / 360 * RealWorldTerrainUtils.EQUATOR_LENGTH);
  202. sizeZ = Math.Abs(rangeY / 360 * RealWorldTerrainUtils.EQUATOR_LENGTH);
  203. }
  204. maxElevation = RealWorldTerrainUtils.MAX_ELEVATION;
  205. minElevation = -RealWorldTerrainUtils.MAX_ELEVATION;
  206. double sX = sizeX / tCount.x * baseScale * prefs.terrainScale.x;
  207. double sY;
  208. double sZ = sizeZ / tCount.y * baseScale * prefs.terrainScale.z;
  209. if (prefs.elevationRange == RealWorldTerrainElevationRange.autoDetect)
  210. {
  211. double maxEl, minEl;
  212. RealWorldTerrainElevationGenerator.GetElevationRange(out minEl, out maxEl);
  213. if (prefs.generateUnderWater && prefs.nodataValue != 0 && minEl > prefs.nodataValue) minEl = prefs.nodataValue;
  214. maxElevation = maxEl + prefs.autoDetectElevationOffset.y;
  215. minElevation = minEl - prefs.autoDetectElevationOffset.x;
  216. }
  217. else if (prefs.elevationRange == RealWorldTerrainElevationRange.fixedValue)
  218. {
  219. maxElevation = prefs.fixedMaxElevation;
  220. minElevation = prefs.fixedMinElevation;
  221. }
  222. sY = (maxElevation - minElevation) / scaleYCoof * baseScale * prefs.terrainScale.y;
  223. if (prefs.sizeType == 2)
  224. {
  225. double scaleX = sX / prefs.fixedTerrainSize.x;
  226. double scaleZ = sZ / prefs.fixedTerrainSize.z;
  227. sX = prefs.fixedTerrainSize.x;
  228. sZ = prefs.fixedTerrainSize.z;
  229. sY /= (scaleX + scaleZ) / 2;
  230. }
  231. sX = Math.Round(sX);
  232. sY = Math.Round(sY);
  233. sZ = Math.Round(sZ);
  234. if (sY < 1) sY = 1;
  235. RealWorldTerrainWindow.terrains = new RealWorldTerrainItem[tCount.x, tCount.y];
  236. scale = new Vector3((float)(sX * tCount.x / rangeX), (float)(sY / (maxElevation - minElevation)), (float)(sZ * tCount.y / rangeY));
  237. string baseName = Regex.Replace(RealWorldTerrainPrefs.LoadPref("ResultName", "RealWorld Terrain"), @"{\w+}", ReplaceResultToken);
  238. string containerName = baseName;
  239. if (RealWorldTerrainPrefs.LoadPref("AppendIndex", true))
  240. {
  241. int nameIndex = 0;
  242. while (GameObject.Find("/" + containerName))
  243. {
  244. nameIndex++;
  245. containerName = baseName + " " + nameIndex;
  246. }
  247. }
  248. size = new Vector3((float)sX, (float)sY, (float)sZ);
  249. container = RealWorldTerrainWindow.container = new GameObject(containerName).AddComponent<RealWorldTerrainContainer>();
  250. prefs.Apply(container);
  251. double mx1, my1, mx2, my2;
  252. RealWorldTerrainUtils.LatLongToMercat(fromX, fromY, out mx1, out my1);
  253. RealWorldTerrainUtils.LatLongToMercat(toX, toY, out mx2, out my2);
  254. container.SetCoordinates(mx1, my1, mx2, my2, fromX, fromY, toX, toY);
  255. container.folder = resultFolder;
  256. container.scale = scale;
  257. container.size = new Vector3(size.x * tCount.x, size.y, size.z * tCount.y);
  258. container.terrainCount = prefs.terrainCount;
  259. container.terrains = new RealWorldTerrainItem[prefs.terrainCount.x * prefs.terrainCount.y];
  260. container.minElevation = minElevation;
  261. container.maxElevation = maxElevation;
  262. container.title = prefs.title;
  263. if (prefs.useAnchor)
  264. {
  265. RealWorldTerrainUtils.LatLongToMercat(prefs.anchorLongitude, prefs.anchorLatitude, out mx1, out my1);
  266. Vector3 p = RealWorldTerrainEditorUtils.CoordsToWorld(mx1, 0, my1, container);
  267. container.transform.position = -p;
  268. }
  269. if (prefs.alignWaterLine)
  270. {
  271. Vector3 p = new Vector3(0, -(float)minElevation * scale.y, 0);
  272. container.transform.position -= p;
  273. }
  274. container.bounds = new Bounds(container.transform.position + container.size / 2, container.size);
  275. }
  276. }
  277. }