TC_Generate.cs 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5. using System.IO;
  6. namespace TerrainComposer2
  7. {
  8. [ExecuteInEditMode]
  9. public class TC_Generate : MonoBehaviour
  10. {
  11. public static TC_Generate instance;
  12. public float globalScale = 1;
  13. public TC_Area2D area2D;
  14. public bool assignTerrainHeightmap;
  15. public bool hideHierarchy;
  16. public bool generate;
  17. public bool generateSplat;
  18. public bool generateSplatSingle;
  19. public bool generateTree;
  20. public bool generateObject;
  21. public bool generateGrass;
  22. public bool generateColor;
  23. public bool resetTrees;
  24. public bool generateSingle;
  25. public int threadActive = 0;
  26. public bool isMesh;
  27. public bool resetObjects;
  28. public bool autoGenerate;
  29. public bool cmdGenerate;
  30. public Rect autoGenerateRect = new Rect (0,0,1,1);
  31. public bool generateNextFrame;
  32. public int generateDone;
  33. public int generateDoneOld;
  34. public bool isGeneratingHeight;
  35. public int jobs = 0;
  36. public bool autoGenerateOld;
  37. float[] heightsReadback;
  38. float[,] heights;
  39. int[,] grass;
  40. List<TreeInstance> trees;
  41. int restoreAutoGenerateFrame = 0;
  42. bool restoreAutoGenerate;
  43. public List<GenerateStackEntry> stackEntry = new List<GenerateStackEntry>();
  44. public Transform objectParent;
  45. [System.NonSerialized] TC_Terrain firstTreeTerrain;
  46. [System.NonSerialized] TC_Terrain firstObjectTerrain;
  47. // Octree octree;
  48. // static public EditorCoroutine co;
  49. void Awake()
  50. {
  51. // octree = new Octree();
  52. autoGenerateOld = autoGenerate;
  53. // Debug.Log("Awake " + autoGenerate);
  54. autoGenerate = false;
  55. restoreAutoGenerate = true;
  56. }
  57. void OnEnable()
  58. {
  59. instance = this;
  60. isGeneratingHeight = false;
  61. #if UNITY_EDITOR
  62. UnityEditor.EditorApplication.update += MyUpdate;
  63. #if UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017_1
  64. UnityEditor.EditorApplication.playmodeStateChanged += BeforePlayMode;
  65. #else
  66. UnityEditor.EditorApplication.playModeStateChanged += BeforePlayMode;
  67. #endif
  68. if (!UnityEditor.EditorApplication.isPlaying)
  69. {
  70. restoreAutoGenerate = true;
  71. }
  72. #endif
  73. }
  74. #if UNITY_EDITOR
  75. #if UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017_1
  76. void BeforePlayMode()
  77. #else
  78. void BeforePlayMode(UnityEditor.PlayModeStateChange state)
  79. #endif
  80. {
  81. TC_Settings settings = TC_Settings.instance;
  82. if (!UnityEditor.EditorApplication.isPlaying && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
  83. {
  84. // autoGenerateOld = autoGenerate;
  85. // autoGenerate = false;
  86. // UnityEditor.EditorUtility.SetDirty(this);
  87. // Debug.Log("Start");
  88. if (!area2D.terrainAreas[0]) return;
  89. if (settings.isRTPDetected && area2D.terrainAreas[0].IsRTPAddedToTerrains())
  90. {
  91. if (settings.autoColormapRTP) ExportColormap(settings.exportPath, true);
  92. if (settings.autoColormapRTP) ExportNormalmap(settings.exportPath, true);
  93. }
  94. }
  95. }
  96. #endif
  97. void OnDisable()
  98. {
  99. autoGenerateOld = autoGenerate;
  100. autoGenerate = false;
  101. #if UNITY_EDITOR
  102. UnityEditor.EditorApplication.update -= MyUpdate;
  103. #if UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017_1
  104. UnityEditor.EditorApplication.playmodeStateChanged -= BeforePlayMode;
  105. #else
  106. UnityEditor.EditorApplication.playModeStateChanged -= BeforePlayMode;
  107. #endif
  108. #endif
  109. }
  110. void OnDestroy()
  111. {
  112. instance = null;
  113. #if UNITY_EDITOR
  114. UnityEditor.EditorApplication.update -= MyUpdate;
  115. #if UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 || UNITY_5_6 || UNITY_2017_1
  116. UnityEditor.EditorApplication.playmodeStateChanged -= BeforePlayMode;
  117. #else
  118. UnityEditor.EditorApplication.playModeStateChanged -= BeforePlayMode;
  119. #endif
  120. #endif
  121. }
  122. int frame = 0;
  123. bool updateCamCapture;
  124. public void Update()
  125. {
  126. #if UNITY_EDITOR
  127. if (Application.isPlaying) MyUpdate();
  128. #else
  129. MyUpdate();
  130. #endif
  131. }
  132. public void MyUpdate()
  133. {
  134. TC_Settings settings = TC_Settings.instance;
  135. if (settings != null)
  136. {
  137. if (settings.version == 0)
  138. {
  139. settings.version = TC.GetVersionNumber();
  140. TC.RefreshOutputReferences(7);
  141. TC.AddMessage("TerrainComposer2 is updated to " + TC.GetVersionNumber().ToString());
  142. }
  143. }
  144. area2D = TC_Area2D.current;
  145. if (area2D == null) return;
  146. if (area2D.terrainLayer == null) return;
  147. if (area2D.terrainLayer.layerGroups[0] == null) TC.RefreshOutputReferences(TC.allOutput);
  148. RefreshOutputReferences(TC.GetRefreshOutputReferences(), TC.refreshPreviewImages);
  149. if (cmdGenerate)
  150. {
  151. cmdGenerate = false;
  152. if (autoGenerate)
  153. {
  154. TC_Reporter.Log("Generate from auto", 2);
  155. Generate(false, autoGenerateRect);
  156. }
  157. else TC.autoGenerateCallTimeStart = Time.realtimeSinceStartup;
  158. autoGenerateRect = new Rect (0,0,1,1);
  159. }
  160. if (restoreAutoGenerate)
  161. {
  162. if (restoreAutoGenerateFrame > 1)
  163. {
  164. restoreAutoGenerate = false;
  165. restoreAutoGenerateFrame = 0;
  166. autoGenerate = autoGenerateOld;
  167. }
  168. ++restoreAutoGenerateFrame;
  169. }
  170. generate = false;
  171. // if (frame >= 0)
  172. //{
  173. RunGenerateStack();
  174. // frame = 0;
  175. // }
  176. ++frame;
  177. }
  178. public void RefreshOutputReferences(int outputId, bool refreshPreviewImages)
  179. {
  180. if (outputId >= 0)
  181. {
  182. TC.refreshPreviewImages = refreshPreviewImages;
  183. // Debug.Log("GetItems " + outputId);
  184. if (outputId >= 6) area2D.terrainLayer.GetItems(false, true, outputId == 7); else area2D.terrainLayer.GetItem(outputId, true, false);
  185. TC.RefreshOutputReferences(-1);
  186. TC.refreshPreviewImages = false;
  187. TC.repaintNodeWindow = true;
  188. }
  189. }
  190. public void RunGenerateStack()
  191. {
  192. // if (stack.Count > 0) Debug.Log(stack.Count);
  193. if (stackEntry.Count > 0)
  194. {
  195. if (stackEntry[0].stack.Count == 0) stackEntry.RemoveAt(0);
  196. }
  197. if (stackEntry.Count > 0 && !generate)
  198. {
  199. // Debug.Log(stack.Count);
  200. List<GenerateStack> stack = stackEntry[0].stack;
  201. GenerateStack curStack = stack[0];
  202. int outputId = curStack.outputId;
  203. //TODO Debug.Log ("TC_Generate.RunGenerateStack: Generating ID " + outputId + " in Stack of length " + stackEntry.Count + "/" + stack.Count + "!");
  204. TCUnityTerrain tcTerrain = curStack.tcTerrain;
  205. assignTerrainHeightmap = curStack.assignTerrainHeightmap;
  206. stack.RemoveAt(0);
  207. // Debug.Log(stack[0].tcTerrain.terrain.name);
  208. GenerateTerrain(tcTerrain, outputId);
  209. Compute(tcTerrain, outputId, curStack.generateRect);
  210. }
  211. if (stackEntry.Count == 0 && disableHeightOuput)
  212. {
  213. disableHeightOuput = false;
  214. area2D.terrainLayer.layerGroups[TC.heightOutput].visible = false;
  215. }
  216. }
  217. bool disableHeightOuput;
  218. public void Compute(TCUnityTerrain tcTerrain, int outputId, Rect generateRect)
  219. {
  220. //TODO Debug.Log ("TC_Generate.Compute: Computing ID " + outputId + "!");
  221. // Debug.Log(frame);
  222. if (outputId == TC.heightOutput) ComputeHeight(generateRect);
  223. else if (outputId == TC.splatOutput) ComputeSplat(generateRect);
  224. else if (outputId == TC.colorOutput) ComputeColor();
  225. else if (outputId == TC.treeOutput) ComputeTree();
  226. else if (outputId == TC.grassOutput) ComputeGrass();
  227. else if (outputId == TC.objectOutput) ComputeObject();
  228. tcTerrain.generateStatus &= (byte)(255 - Mathw.bit8[outputId]);
  229. if (tcTerrain.generateStatus == 0)
  230. {
  231. if (tcTerrain.tasks > 0)
  232. {
  233. --tcTerrain.tasks;
  234. }
  235. // tcTerrain.terrain.Flush();
  236. // Debug.Log("Flush terrain");
  237. if (!tcTerrain.terrain.gameObject.activeSelf)
  238. {
  239. // tcTerrain.terrain.enabled = true;
  240. tcTerrain.terrain.gameObject.SetActive(true);
  241. }
  242. }
  243. TC_Compute.instance.camCapture.DisposeRTCapture();
  244. }
  245. public bool CheckForTerrain(bool selectTerrainArea = true)
  246. {
  247. if (area2D.terrainAreas == null) area2D.terrainAreas = new TC_TerrainArea[1];
  248. else if (area2D.terrainAreas.Length == 0) area2D.terrainAreas = new TC_TerrainArea[1];
  249. if (area2D.terrainAreas[0] == null)
  250. {
  251. GameObject go = GameObject.Find("Terrain Area");
  252. if (go != null)
  253. {
  254. TC_TerrainArea terrainArea = go.GetComponent<TC_TerrainArea>();
  255. if (terrainArea != null) area2D.terrainAreas[0] = terrainArea;
  256. else
  257. {
  258. TC.AddMessage("The Terrain Area GameObject is missing the 'TC_TerrainArea' script.");
  259. #if UNITY_EDITOR
  260. if (UnityEditor.EditorUtility.DisplayDialog("The Terrain Area GameObject is missing the 'TC_TerrainArea' script.", "Do you want to TC2 to add the 'TC_TerrainArea' script now?", "Yes", "Cancel"))
  261. {
  262. area2D.terrainAreas[0] = go.AddComponent<TC_TerrainArea>();
  263. }
  264. else return false;
  265. #else
  266. return false;
  267. #endif
  268. }
  269. }
  270. else { TC.AddMessage("No Terrain Area is created."); return false; }
  271. }
  272. bool hasTerrain = true;
  273. if (area2D.terrainAreas[0].terrains.Count == 0)
  274. {
  275. area2D.terrainAreas[0].terrains.Add(new TCUnityTerrain());
  276. hasTerrain = false;
  277. }
  278. for (int i = 0; i < area2D.terrainAreas[0].terrains.Count; i++)
  279. {
  280. if (!area2D.terrainAreas[0].terrains[i].CheckValidUnityTerrain())
  281. {
  282. if (selectTerrainArea) TC.AddMessage("Terrain missing on X" + area2D.terrainAreas[0].terrains[i].tileX + "_Y"+area2D.terrainAreas[0].terrains[i].tileZ + "\n\nTC2 has automatically selected the Terrain Area GameObject.");
  283. hasTerrain = false;
  284. }
  285. }
  286. if (!hasTerrain)
  287. {
  288. TC.AddMessage("Please create a terrain first.");
  289. #if UNITY_EDITOR
  290. if (selectTerrainArea) UnityEditor.Selection.activeGameObject = area2D.terrainAreas[0].gameObject;
  291. #endif
  292. return false;
  293. }
  294. return hasTerrain;
  295. }
  296. public void Generate(bool instantGenerate, int outputId = TC.allOutput)
  297. {
  298. Generate (instantGenerate, new Rect (0,0,1,1), outputId);
  299. }
  300. public void Generate(bool instantGenerate, Rect generateRect, int outputId = TC.allOutput)
  301. {
  302. // Debug.Log("Generate");
  303. if (!CheckForTerrain()) return;
  304. area2D = TC_Area2D.current;
  305. if (area2D == null) return;
  306. if (area2D.terrainLayer == null) return;
  307. TC_Settings settings = TC_Settings.instance;
  308. if (settings == null)
  309. {
  310. TC.AddMessage("Settings GameObject not found."); return;
  311. }
  312. generateRect = Mathw.ClampRect (generateRect, new Rect (0,0,1,1));
  313. if (area2D.terrainAreas[0].terrains[0].texHeight == null)
  314. {
  315. // TC.AddMessage("The 'Height' output is not generated. Enable 'Height' output for TC2 to regenerate the height textures.", 0, 4);
  316. if (!area2D.terrainLayer.layerGroups[TC.heightOutput].visible)
  317. {
  318. Debug.Log("Not Active");
  319. area2D.terrainLayer.layerGroups[TC.heightOutput].visible = true;
  320. area2D.terrainLayer.layerGroups[TC.heightOutput].GetItems(true, false, false);
  321. disableHeightOuput = true;
  322. }
  323. }
  324. isMesh = false;
  325. bool firstTerrain = true;
  326. //TODO Debug.Log ("TC_Generate.Generate: Generating ID " + outputId + " " + (instantGenerate? "instantly" : "delayed") + " in rect " + generateRect.ToString () + "!");
  327. TC_TerrainArea terrainArea = area2D.terrainAreas[0];
  328. for (int i = 0; i < terrainArea.terrains.Count; i++)
  329. {
  330. TCUnityTerrain tcTerrain = terrainArea.terrains[i];
  331. Vector2 terrainLocalPos = new Vector2 ((float)tcTerrain.tileX/terrainArea.tiles.x, (float)tcTerrain.tileZ/terrainArea.tiles.y);
  332. Vector2 terrainLocalSize = new Vector2 (1f/terrainArea.tiles.x, 1f/terrainArea.tiles.y);
  333. Rect terrainRect = new Rect (terrainLocalPos, terrainLocalSize);
  334. //Debug.Log ("Terrain tile " + tcTerrain.tileX + "/" + tcTerrain.tileZ + " in " + terrainArea.tiles.x + "/" + terrainArea.tiles.y + " tiles has rect " + terrainRect);
  335. Rect terrainGenRect;
  336. if (tcTerrain.active && Mathw.OverlapRect (generateRect, terrainRect, out terrainGenRect))
  337. {
  338. Rect relTerrainGenRect = new Rect ((terrainGenRect.x-terrainLocalPos.x)*terrainArea.tiles.x, (terrainGenRect.y-terrainLocalPos.y)*terrainArea.tiles.y,
  339. terrainGenRect.width*terrainArea.tiles.x, terrainGenRect.height*terrainArea.tiles.y);
  340. relTerrainGenRect = Mathw.ClampRect (relTerrainGenRect, new Rect (0,0,1,1));
  341. //TODO Debug.Log ("Terrain tile " + tcTerrain.tileX + "/" + tcTerrain.tileZ + " generates global rect " + terrainGenRect.ToString () + " and relative rect " + relTerrainGenRect.ToString ());
  342. if (firstTerrain)
  343. {
  344. if (area2D.terrainLayer.layerGroups[TC.treeOutput].active && (outputId == TC.allOutput || outputId == TC.treeOutput)) firstTreeTerrain = tcTerrain;
  345. if (area2D.terrainLayer.layerGroups[TC.objectOutput].active && (outputId == TC.allOutput || outputId == TC.objectOutput)) firstObjectTerrain = tcTerrain;
  346. firstTerrain = false;
  347. }
  348. TC_Compute.instance.camCapture.collisionMask = 0;
  349. if (outputId == TC.allOutput) Generate(tcTerrain, instantGenerate, relTerrainGenRect);
  350. else
  351. {
  352. if (outputId == TC.heightOutput) GenerateHeight(tcTerrain, instantGenerate, relTerrainGenRect, false); else GenerateOutput(tcTerrain, outputId, instantGenerate, relTerrainGenRect);
  353. }
  354. }
  355. }
  356. }
  357. public void GenerateMesh()
  358. {
  359. isMesh = true;
  360. }
  361. public void Generate(TCUnityTerrain tcTerrain, bool instantGenerate, int outputId = TC.allOutput)
  362. {
  363. Generate(tcTerrain, instantGenerate, new Rect(0, 0, 1, 1));
  364. }
  365. public void Generate(TCUnityTerrain tcTerrain, bool instantGenerate, Rect generateRect)
  366. {
  367. // Debug.Log(instantGenerate);
  368. // if (disableTerrain) tcTerrain.terrain.enabled = false;
  369. //TODO Debug.Log ("TC_Generate.Generate/Terrain: Generating terrain " + tcTerrain.index + "!");
  370. if (area2D.terrainLayer.layerGroups[TC.heightOutput].active || area2D.terrainLayer.layerGroups[TC.objectOutput].active) GenerateHeight(tcTerrain, instantGenerate, generateRect, false);
  371. for (int i = 1; i <= 4; i++)
  372. {
  373. if (area2D.terrainLayer.layerGroups[i].active) GenerateOutput(tcTerrain, i, instantGenerate, generateRect);
  374. }
  375. // TC.repaintNodeWindow = true;
  376. }
  377. public void GenerateOutput(TCUnityTerrain tcTerrain, int outputId, bool instantGenerate, Rect generateRect)
  378. {
  379. if (area2D.terrainLayer.layerGroups[outputId] != null)
  380. {
  381. // Debug.Log("Generate "+generate+ " +"+instantGenerate);
  382. tcTerrain.generateStatus |= (byte)Mathw.bit8[outputId];
  383. if (generate && !instantGenerate)
  384. {
  385. //TODO Debug.Log ("TC_Generate.GenerateOutput/Terrain: Enqueueing terrain " + tcTerrain.index + " output " + outputId + "!");
  386. bool addToStack = true;
  387. if (stackEntry.Count == 0) stackEntry.Add(new GenerateStackEntry(frame));
  388. else
  389. {
  390. if (stackEntry[0].frame != frame && stackEntry.Count == 1)
  391. {
  392. stackEntry.Add(new GenerateStackEntry(frame));
  393. }
  394. }
  395. if (stackEntry.Count == 2)
  396. {
  397. List<GenerateStack> stack = stackEntry[1].stack;
  398. for (int i = 0; i < stack.Count; i++)
  399. {
  400. GenerateStack genEntry = stack[i];
  401. if (genEntry.tcTerrain == tcTerrain && genEntry.outputId == outputId && genEntry.assignTerrainHeightmap == assignTerrainHeightmap)
  402. { // Ensure generate rect includes the rectangle
  403. Mathw.EncapsulteRect (ref genEntry.generateRect, generateRect);
  404. addToStack = false;
  405. break;
  406. }
  407. }
  408. }
  409. if (addToStack)
  410. {
  411. List<GenerateStack> stack = stackEntry[stackEntry.Count - 1].stack;
  412. stack.Add(new GenerateStack(outputId, tcTerrain, assignTerrainHeightmap, generateRect));
  413. }
  414. }
  415. else
  416. {
  417. //TODO Debug.Log ("TC_Generate.GenerateOutput/Terrain: Generating terrain " + tcTerrain.index + " output " + outputId + "!");
  418. // Debug.Log("Generate Output");
  419. ++tcTerrain.tasks;
  420. GenerateTerrain(tcTerrain, outputId);
  421. Compute(tcTerrain, outputId, generateRect);
  422. }
  423. }
  424. }
  425. public void GenerateHeight(TCUnityTerrain tcTerrain, bool instantGenerate, Rect generateRect, bool disableTerrain)
  426. {
  427. //TODO Debug.Log ("TC_Generate.GenerateHeight/Terrain: Generating terrain " + tcTerrain.index + " height!");
  428. // Debug.Log(instantGenerate);
  429. // if (disableTerrain) tcTerrain.terrain.enabled = false;
  430. TC_Compute.instance.camCapture.collisionMask = 0;
  431. assignTerrainHeightmap = true;
  432. if (area2D.terrainLayer.layerGroups[TC.heightOutput].active && area2D.terrainLayer.layerGroups[TC.objectOutput].active)
  433. {
  434. if (area2D.terrainLayer.layerGroups[TC.heightOutput].ContainsCollisionNode()) assignTerrainHeightmap = false;
  435. }
  436. if (area2D.terrainLayer.layerGroups[TC.heightOutput].active) GenerateOutput(tcTerrain, TC.heightOutput, instantGenerate, generateRect);
  437. if (area2D.terrainLayer.layerGroups[TC.objectOutput].active) GenerateOutput(tcTerrain, TC.objectOutput, instantGenerate, generateRect);
  438. if (!assignTerrainHeightmap)
  439. {
  440. // Debug.Log("Second pass");
  441. assignTerrainHeightmap = true;
  442. GenerateOutput(tcTerrain, TC.heightOutput, instantGenerate, generateRect);
  443. }
  444. if (area2D.terrainLayer.layerGroups[TC.objectOutput].active) GenerateOutput(tcTerrain, TC.objectOutput, instantGenerate, generateRect);
  445. // TC.repaintNodeWindow = true;
  446. }
  447. public bool GenerateStart()
  448. {
  449. TC_Area2D.current = area2D;
  450. // area2D.currentTerrainArea = area2D.terrainAreas[0];
  451. // Debug.Log("Generate Start");
  452. if (area2D.terrainAreas[0] == null) return false;
  453. if (area2D.previewArea != null)
  454. {
  455. if (area2D.previewArea.manual) area2D.SetManualTotalArea();
  456. else if (!area2D.CalcTotalArea()) return false;
  457. }
  458. else if (!area2D.CalcTotalArea()) return false;
  459. area2D.terrainsDone = 0;
  460. area2D.terrainsToDo = 0;
  461. generate = true;
  462. for (int i = 0; i < area2D.terrainAreas.Length; i++) area2D.terrainsToDo += area2D.terrainAreas[i].terrains.Count;
  463. return true;
  464. }
  465. public void GenerateStop()
  466. {
  467. ++generateDone;
  468. }
  469. public void ComputeTerrainAreas()
  470. {
  471. if (!GenerateStart()) return;
  472. for (int j = 0; j < area2D.terrainAreas.Length; j++)
  473. {
  474. area2D.currentTerrainArea = area2D.terrainAreas[j];
  475. for (int i = 0; i < area2D.currentTerrainArea.terrains.Count; i++)
  476. {
  477. // if (ComputeTerrain(, area2D.currentTerrainArea.terrains[i], false)) ++area2D.terrainsDone;
  478. }
  479. }
  480. // isGeneratingHeight = false;
  481. GenerateStop();
  482. }
  483. public void ComputeMeshTerrainAreas()
  484. {
  485. float t = Time.realtimeSinceStartup;
  486. if (!GenerateStart()) return;
  487. for (int j = 0; j < area2D.meshTerrainAreas.Length; j++)
  488. {
  489. area2D.currentMeshTerrainArea = area2D.meshTerrainAreas[j];
  490. for (int i = 0; i < area2D.currentMeshTerrainArea.terrains.Count; i++)
  491. {
  492. area2D.currentMeshTerrainArea.terrains[i].SetNodesActive(true);
  493. // area2D.terrainLayer.GetItem(TC.heightOutput);
  494. if (ComputeMeshTerrain(TC.heightOutput, area2D.currentMeshTerrainArea.terrains[i], false)) ++area2D.terrainsDone;
  495. area2D.currentMeshTerrainArea.terrains[i].SetNodesActive(false);
  496. // Debug.Log("MeshTerrain " + i);
  497. }
  498. }
  499. // isGeneratingHeight = false;
  500. GenerateStop();
  501. float f = 1 / (Time.realtimeSinceStartup - t);
  502. Debug.Log("Mesh Frames " + f);
  503. }
  504. public bool GenerateTerrain(TCUnityTerrain tcTerrain, int outputId, bool doGenerateStart = true)
  505. {
  506. if (tcTerrain == null) return false;
  507. if (doGenerateStart)
  508. {
  509. if (!GenerateStart()) return false;
  510. }
  511. // TC_TerrainLayer.current = area2D.terrainLayer;
  512. if (tcTerrain.updateTerrainPos)
  513. {
  514. tcTerrain.updateTerrainPos = false;
  515. tcTerrain.terrain.gameObject.SetActive(false);
  516. if (tcTerrain.terrain.terrainData.treeInstanceCount > 0) tcTerrain.terrain.terrainData.treeInstances = new TreeInstance[0];
  517. tcTerrain.terrain.transform.position = tcTerrain.newPos;
  518. }
  519. area2D.SetCurrentArea(tcTerrain, outputId);
  520. // Debug.Log(i);
  521. // Debug.Log("resolution " + resolution.x);
  522. // ReportArea();
  523. //a Debug.Log("Preview Resolution " + area2D.previewResolution);
  524. // area2D.terrainLayer.GetItem(outputId);
  525. return true;
  526. }
  527. public void ReportArea()
  528. {
  529. Debug.Log("Resolution X " + area2D.resolution.x + " Y " + area2D.resolution.y);
  530. Debug.Log("IntResolution " + area2D.intResolution.ToString());
  531. Debug.Log("ResToTerrain X " + area2D.resolutionPM.x + " Y " + area2D.resolutionPM.y);
  532. Debug.Log("Bounds " + area2D.bounds);
  533. Debug.Log("StartPos X " + area2D.startPos.x + " Y " + area2D.startPos.y);
  534. Debug.Log("TerrainSize X " + area2D.terrainSize.x + " Y " + area2D.terrainSize.y);
  535. Debug.Log("Preview Resolution " + area2D.previewResolution);
  536. Debug.Log("ResToPreview X " + area2D.resToPreview.x + " Y " + area2D.resToPreview.y);
  537. Debug.Log("-------------------------------------------------------");
  538. }
  539. public bool ComputeMeshTerrain(int outputId, MeshTerrain tcMeshTerrain, bool doGenerateStart = true)
  540. {
  541. if (doGenerateStart)
  542. {
  543. if (!GenerateStart()) return false;
  544. }
  545. area2D.currentMeshTerrain = tcMeshTerrain;
  546. // if (!area2D.currentTCTerrain.active) return false;
  547. Int2 resolution = new Int2();
  548. Int2 resolution2 = new Int2();
  549. if (outputId == TC.heightOutput) { resolution.x = resolution.y = area2D.terrainLayer.meshResolution + 2; resolution2 = new Int2(resolution.x - 2, resolution.y - 2); }
  550. else if (outputId == TC.splatOutput) { resolution.x = resolution.y = area2D.terrainLayer.meshResolution; resolution2 = resolution; }
  551. // else if (computeGenerate.GetType() == typeof(ComputeGenerateTrees)) { resolution.x = resolution.y = area2D.layerLevel.meshResolution; resolution2 = resolution; }
  552. // else if (computeGenerate.GetType() == typeof(ComputeGenerateGrass)) { resolution.x = resolution.y = terrain.terrainData.detailResolution; resolution2 = resolution; }
  553. // else if (computeGenerate.GetType() == typeof(ComputeGenerateObjects)) { resolution.x = resolution.y = area2D.layerLevel.objectResolution; resolution2 = resolution; }
  554. else if (outputId == TC.colorOutput) { resolution.x = resolution.y = area2D.terrainLayer.meshResolution; resolution2 = resolution; }
  555. area2D.resolution = new Vector2(resolution.x, resolution.y);
  556. area2D.intResolution = resolution;
  557. TC_Reporter.Log("Resolution" + resolution.ToString());
  558. MeshTerrain meshTerrain = area2D.currentMeshTerrain;
  559. Vector2 size = new Vector2(meshTerrain.t.lossyScale.x * 10, meshTerrain.t.lossyScale.z * 10);
  560. area2D.resolutionPM = new Vector2(size.x / (resolution2.x), size.y / (resolution2.y));
  561. // Debug.Log("size " + size);
  562. // Debug.Log("con" + area2D.resToTerrain);
  563. area2D.area = new Rect(meshTerrain.t.position.x - (size.x / 2), meshTerrain.t.position.z - (size.y / 2), resolution.x, resolution.y);
  564. area2D.terrainSize = new Vector3(size.x, 4800, size.y);
  565. area2D.bounds = new Bounds(new Vector3(meshTerrain.t.position.x, 0, meshTerrain.t.position.z), area2D.terrainSize);
  566. area2D.startPos = new Vector3(area2D.area.xMin, meshTerrain.t.position.y, area2D.area.yMin);
  567. // Debug.Log(i);
  568. return true;
  569. }
  570. public void ExportHeightmap(string path)
  571. {
  572. byte[] bytes = null;
  573. Color32[] colors;
  574. int i = 0;
  575. int offset = TC_Area2D.current.resExpandBorder;
  576. for (int y = 0; y < area2D.terrainAreas[0].tiles.y; ++y)
  577. {
  578. for (int x = 0; x < area2D.terrainAreas[0].tiles.x; ++x)
  579. {
  580. TCUnityTerrain terrain = area2D.terrainAreas[0].terrains[i];
  581. Texture2D texHeight = terrain.texHeight;
  582. if (texHeight == null) continue;
  583. string filePath = path + "/" + TC_Settings.instance.heightmapFilename + "_x" + x + "_y" + y + ".raw";
  584. FileStream fs = new FileStream(filePath, FileMode.Create);
  585. colors = terrain.texHeight.GetPixels32();
  586. Int2 resolution = new Int2(texHeight.width - (offset * 2), texHeight.height - (offset * 2));
  587. int size = resolution.x * resolution.y;
  588. if (bytes == null) bytes = new byte[size * 2];
  589. else if (bytes.Length != size * 2) bytes = new byte[size * 2];
  590. for (int yy = 0; yy < resolution.y; yy++)
  591. {
  592. for (int xx = 0; xx < resolution.x; xx++)
  593. {
  594. int index = ((yy * resolution.x) + xx) * 2;
  595. int index2 = ((texHeight.height - yy - 1 - offset) * texHeight.width) + xx + offset;
  596. bytes[index] = colors[index2].g;
  597. bytes[index + 1] = colors[index2].r;
  598. }
  599. }
  600. fs.Write(bytes, 0, bytes.Length);
  601. fs.Close();
  602. i++;
  603. }
  604. }
  605. #if UNITY_EDITOR
  606. UnityEditor.AssetDatabase.Refresh();
  607. #endif
  608. }
  609. public void ExportHeightmapCombined(string path)
  610. {
  611. TC_Settings settings = TC_Settings.instance;
  612. byte[] bytes = null;
  613. int i = 0;
  614. // int offset = TC_Area2D.current.resExpandBorder;
  615. string filePath = path + "/" + TC_Settings.instance.heightmapFilename + ".raw";
  616. FileStream fs = new FileStream(filePath, FileMode.Create);
  617. Int2 tiles;
  618. if (settings.importSource == TC_Settings.ImportSource.TC2_TerrainArea) tiles = area2D.terrainAreas[0].tiles;
  619. else tiles = settings.importTiles;
  620. for (int y = 0; y < tiles.y; ++y)
  621. {
  622. for (int x = 0; x < tiles.x; ++x)
  623. {
  624. TerrainData terrainData;
  625. if (settings.importSource == TC_Settings.ImportSource.TC2_TerrainArea) terrainData = area2D.terrainAreas[0].terrains[i].terrain.terrainData;
  626. else terrainData = settings.importTerrains[i];
  627. if (terrainData == null) { TC.AddMessage("TerrainData X" + x + "_Y" + y + " is null"); i++; continue; }
  628. //Texture2D texHeight = terrain.texHeight;
  629. //if (texHeight == null) continue;
  630. //colors = terrain.texHeight.GetPixels32();
  631. //Int2 resolution = new Int2(texHeight.width - (offset * 2), texHeight.height - (offset * 2));
  632. int resolution = terrainData.heightmapResolution;
  633. float[,] heights = terrainData.GetHeights(0, 0, resolution, resolution);
  634. // int size = resolution.x * resolution.y;
  635. if (bytes == null) bytes = new byte[resolution * 2];
  636. else if (bytes.Length != resolution * 2) bytes = new byte[resolution * 2];
  637. fs.Seek((x * resolution * 2) + ((tiles.y - y - 1) * resolution * (resolution * 2 * tiles.x)), SeekOrigin.Begin);
  638. for (int yy = 0; yy < resolution; yy++)
  639. {
  640. int index = 0;
  641. for (int xx = 0; xx < resolution; xx++)
  642. {
  643. int height = (int)(heights[resolution - yy - 1, xx] * 65536);
  644. byte hiByte = (byte)(height >> 8);
  645. bytes[index++] = (byte)(height - (hiByte << 8));
  646. bytes[index++] = hiByte;
  647. }
  648. fs.Write(bytes, 0, bytes.Length);
  649. fs.Seek(resolution * 2 * (tiles.x - 1), SeekOrigin.Current);
  650. }
  651. i++;
  652. }
  653. }
  654. fs.Close();
  655. #if UNITY_EDITOR
  656. UnityEditor.AssetDatabase.Refresh();
  657. #endif
  658. }
  659. public void CreateLayerFromExportedHeightmap(string path)
  660. {
  661. #if UNITY_EDITOR
  662. if (!path.Contains("RawFiles")) { TC.AddMessage("You need to save the heightmap in a RawFiles folder for TC2 to make a stamp out of it."); return; }
  663. string filePath = path.Replace(Application.dataPath, "Assets");
  664. filePath = filePath.Replace("RawFiles" , "") + TC_Settings.instance.heightmapFilename + ".Jpg";
  665. // Debug.Log(filePath);
  666. Texture tex = UnityEditor.AssetDatabase.LoadAssetAtPath(filePath, typeof(Texture)) as Texture;
  667. if (tex == null) { TC.AddMessage("'" + filePath + "' not found."); return; }
  668. TC_LayerGroup heightLayerGroup = area2D.terrainLayer.layerGroups[TC.heightOutput];
  669. TC_Layer layer = heightLayerGroup.groupResult.Add<TC_Layer>("", false) as TC_Layer;
  670. layer.GetItems(false, false, false);
  671. TC_Node node = layer.selectNodeGroup.itemList[0] as TC_Node;
  672. node.DropTextureEditor(tex);
  673. #endif
  674. }
  675. public void ExportNormalmap(string path, bool assignRTP)
  676. {
  677. Color32[] colors, normalColors = null;
  678. int i = 0;
  679. int offset = TC_Area2D.current.resExpandBorder;
  680. float nx, ny, nz;
  681. float normalmapStrength = TC_Settings.instance.normalmapStrength;
  682. for (int y = 0; y < area2D.terrainAreas[0].tiles.y; ++y)
  683. {
  684. for (int x = 0; x < area2D.terrainAreas[0].tiles.x; ++x)
  685. {
  686. TCUnityTerrain tcTerrain = area2D.terrainAreas[0].terrains[i];
  687. Texture2D texHeight = tcTerrain.texHeight;
  688. if (texHeight == null) continue;
  689. colors = tcTerrain.texHeight.GetPixels32();
  690. Int2 resolution = new Int2(texHeight.width - (offset * 2), texHeight.height - (offset * 2));
  691. int size = resolution.x * resolution.y;
  692. TC_Compute.InitTexture(ref tcTerrain.texNormalmap, TC_Settings.instance.normalmapFilename, resolution.x, true, TextureFormat.RGB24);
  693. if (normalColors == null) normalColors = new Color32[size];
  694. else if (normalColors.Length != size) normalColors = new Color32[size];
  695. for (int yy = 0; yy < resolution.y; yy++)
  696. {
  697. for (int xx = 0; xx < resolution.x; xx++)
  698. {
  699. int index = ((yy * resolution.x) + xx);
  700. int index2 = ((yy + offset) * texHeight.width) + xx + offset;
  701. nx = ((((float)colors[index2].b / 255.0f) * 2) - 1) * normalmapStrength;
  702. nz = ((((float)colors[index2].a / 255.0f) * 2) - 1) * normalmapStrength;
  703. ny = Mathf.Sqrt(1 - nx * nx - nz * nz);
  704. normalColors[index].r = colors[index2].b;
  705. normalColors[index].g = colors[index2].a;
  706. normalColors[index].b = (byte)(ny * 255f);
  707. }
  708. }
  709. tcTerrain.texNormalmap.SetPixels32(normalColors);
  710. tcTerrain.texNormalmap.Apply();
  711. #if UNITY_EDITOR
  712. string filePath = ExportImage(path + "/" + TC_Settings.instance.normalmapFilename + "_x" + x + "_y" + y, tcTerrain.texNormalmap);
  713. filePath = filePath.Replace(Application.dataPath, "Assets");
  714. UnityEditor.AssetDatabase.Refresh();
  715. UnityEditor.TextureImporter textureImporter = (UnityEditor.TextureImporter)UnityEditor.AssetImporter.GetAtPath(filePath);
  716. if (textureImporter)
  717. {
  718. #if UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4
  719. textureImporter.normalmap = true;
  720. #else
  721. textureImporter.textureType = UnityEditor.TextureImporterType.NormalMap;
  722. #endif
  723. textureImporter.SaveAndReimport();
  724. UnityEditor.AssetDatabase.ImportAsset(filePath, UnityEditor.ImportAssetOptions.ForceUpdate);
  725. // Debug.Log("Normalmap");
  726. }
  727. if (TC_Settings.instance.isRTPDetected && TC_Settings.instance.autoNormalmapRTP && assignRTP)
  728. {
  729. // Debug.Log(filePath);
  730. Texture2D tex = (Texture2D)UnityEditor.AssetDatabase.LoadAssetAtPath(filePath, typeof(Texture2D));
  731. if (tex != null)
  732. {
  733. tcTerrain.AssignTextureRTP("NormalGlobal", tex);
  734. }
  735. }
  736. #endif
  737. i++;
  738. }
  739. }
  740. #if UNITY_EDITOR
  741. UnityEditor.AssetDatabase.Refresh();
  742. #endif
  743. }
  744. public void ExportColormap(string path, bool assignRTP)
  745. {
  746. #if UNITY_EDITOR
  747. int i = 0;
  748. for (int y = 0; y < area2D.terrainAreas[0].tiles.y; ++y)
  749. {
  750. for (int x = 0; x < area2D.terrainAreas[0].tiles.x; ++x)
  751. {
  752. TCUnityTerrain tcTerrain = area2D.terrainAreas[0].terrains[i];
  753. if (tcTerrain.texColormap == null) continue;
  754. string filePath = ExportImage(path + "/" + TC_Settings.instance.colormapFilename + "_x" + x + "_y" + y, tcTerrain.texColormap);
  755. if (TC_Settings.instance.isRTPDetected && TC_Settings.instance.autoColormapRTP && assignRTP)
  756. {
  757. filePath = filePath.Replace(Application.dataPath, "Assets");
  758. // Debug.Log(filePath);
  759. Texture2D tex = (Texture2D)UnityEditor.AssetDatabase.LoadAssetAtPath(filePath, typeof(Texture2D));
  760. if (tex != null)
  761. {
  762. tcTerrain.AssignTextureRTP("ColorGlobal", tex);
  763. }
  764. }
  765. ++i;
  766. }
  767. }
  768. UnityEditor.AssetDatabase.Refresh();
  769. #endif
  770. }
  771. public string ExportImage(string filePath, Texture2D tex)
  772. {
  773. #if !UNITY_WEBPLAYER
  774. byte[] bytes;
  775. string extension;
  776. if (TC_Settings.instance.imageExportFormat == TC_Settings.ImageExportFormat.PNG)
  777. {
  778. bytes = tex.EncodeToPNG(); extension = "png";
  779. }
  780. else
  781. {
  782. bytes = tex.EncodeToJPG(); extension = "jpg";
  783. }
  784. filePath = filePath + "." + extension;
  785. File.WriteAllBytes(filePath, bytes);
  786. #endif
  787. return filePath;
  788. }
  789. public void ExportSplatmap(string path)
  790. {
  791. int i = 0;
  792. for (int y = 0; y < area2D.terrainAreas[0].tiles.y; ++y)
  793. {
  794. for (int x = 0; x < area2D.terrainAreas[0].tiles.x; ++x)
  795. {
  796. TCUnityTerrain tcTerrain = area2D.terrainAreas[0].terrains[i];
  797. Terrain terrain = tcTerrain.terrain;
  798. if (terrain == null) continue;
  799. if (terrain.terrainData == null) continue;
  800. Texture2D[] texSplatmaps = terrain.terrainData.alphamapTextures;
  801. for (int j = 0; j < texSplatmaps.Length; j++)
  802. {
  803. if (texSplatmaps[j] == null) continue;
  804. ExportImage(path + "/" + TC_Settings.instance.splatmapFilename + j + "_x" + x + "_y" + y, texSplatmaps[j]);
  805. }
  806. ++i;
  807. }
  808. }
  809. #if UNITY_EDITOR
  810. UnityEditor.AssetDatabase.Refresh();
  811. #endif
  812. }
  813. public void ComputeHeight(Rect generateRect)
  814. {
  815. // Debug.Log("ComputeHeight");
  816. TC_LayerGroup heightLayerGroup = area2D.terrainLayer.layerGroups[TC.heightOutput];
  817. // Debug.Log(area2D.currentTCUnityTerrain.terrain.name + " " + assignTerrainHeightmap);
  818. // Debug.Log("ComputeHeight");
  819. if (heightLayerGroup == null) return;
  820. if (!heightLayerGroup.active) return;
  821. if (!assignTerrainHeightmap)
  822. {
  823. area2D.currentTCUnityTerrain.ResetObjects();
  824. area2D.terrainLayer.ResetObjects();
  825. }
  826. TC_Compute compute = TC_Compute.instance;
  827. // isGeneratingHeight = true;
  828. int resolution = area2D.intResolution.x;
  829. ComputeBuffer buffer = null;
  830. // TC_Reporter.BenchmarkStart();
  831. heightLayerGroup.ComputeSingle(ref buffer, 0, true);
  832. // TC_Reporter.BenchmarkStop("Height compute");
  833. if (buffer == null) { TC_Reporter.Log("final buffer is null"); return; }
  834. // if (tcGenerate.isMesh) Debug.Log("Frames generate " + area2D.currentMeshTerrain.t.name + " " + f.ToString("F2"));
  835. // else
  836. // Debug.Log("Frames generate " + area2D.currentTerrain.name + " " + f.ToString("F2"));
  837. // Debug.Log("Is mesh " + isMesh);
  838. if (!isMesh)
  839. {
  840. // Debug.Log(area2D.currentTCUnityTerrain.terrain.transform.name);
  841. // Debug.Log(((TCUnityTerrain)area2D.currentTCTerrain).terrain.name);
  842. compute.RunTerrainTex(buffer, ref area2D.currentTCTerrain.rtHeight, resolution);
  843. // else Debug.Log("Pass");
  844. RenderTexture rtHeight = area2D.currentTCTerrain.rtHeight;
  845. TC_Compute.InitTexture(ref area2D.currentTCTerrain.texHeight, "HeightTexture "+area2D.currentTCUnityTerrain.terrain.name, rtHeight.width, true);
  846. // Debug.Log(area2D.currentTCTerrain.texHeight.mipmapCount);
  847. RenderTexture rtActiveOld = RenderTexture.active;
  848. RenderTexture.active = rtHeight;
  849. area2D.currentTCTerrain.texHeight.ReadPixels(new Rect(0, 0, rtHeight.width, rtHeight.height), 0, 0);
  850. area2D.currentTCTerrain.texHeight.Apply();
  851. RenderTexture.active = rtActiveOld;
  852. //if (TC_Settings.instance.isRTPDetected && TC_Settings.instance.autoNormalmapRTP)
  853. //{
  854. // ExportNormalmap(TC_Settings.instance.exportPath);
  855. // area2D.currentTCUnityTerrain.AssignTextureRTP("NormalGlobal");
  856. //}
  857. //if (!assignTerrainHeightmap)
  858. //{
  859. // // Debug.Log("!!!!!!!!!!!!!!");
  860. // compute.DisposeBuffer(ref buffer);
  861. // return;
  862. //}
  863. int offset = area2D.resExpandBorder;
  864. int heightResolution = resolution - (offset * 2);
  865. generateRect = Mathw.ClampRect (generateRect, new Rect (0,0,1,1));
  866. //TODO Debug.Log ("TC_Generate.ComputeHeight: Computing Height of terrain " + area2D.currentTCUnityTerrain.tileX + "/" + area2D.currentTCUnityTerrain.tileZ + " at " + generateRect.ToString () + "!");
  867. Rect pixelRect = new Rect (Mathf.Floor (heightResolution*generateRect.x), Mathf.Floor (heightResolution*generateRect.y),
  868. Mathf.Ceil (heightResolution*generateRect.width), Mathf.Ceil (heightResolution*generateRect.height));
  869. TC.InitArray(ref heights, (int)pixelRect.height, (int)pixelRect.width);
  870. TC.InitArray(ref heightsReadback, resolution * resolution);
  871. // TODO: Can read directly into heights with rearranging the array
  872. buffer.GetData(heightsReadback);
  873. compute.DisposeBuffer(ref buffer);
  874. // Debug.Log(resolution);
  875. // Debug.Log(heightResolution);
  876. // Debug.Log(offset);
  877. //for (int x = 0; x < 32; x++)
  878. //{
  879. // Int2 pixel = new Int2(x, 0);
  880. // Color color = area2D.currentTCTerrain.texHeight.GetPixel(pixel.x, pixel.y + 1);
  881. // float red = (color.r * 255) * 256;
  882. // float green = (color.g * 255);
  883. // float height = (red + green);
  884. // float height2 = (heightsReadback[x] * 65535);
  885. // Debug.Log(height2 + " - " + height + " = " + (height2 - height));
  886. //}
  887. int yLength = (int)pixelRect.height;
  888. int xLength = (int)pixelRect.width;
  889. int pixelRectX = (int)pixelRect.x;
  890. int pixelRectY = (int)pixelRect.y;
  891. for (int y = 0; y < yLength; y++)
  892. {
  893. for (int x = 0; x < xLength; x++)
  894. {
  895. //Debug.Log ("Sampling pixel " + x + "/" + y + " from " + (x + offset + ((y + offset) * resolution)));
  896. heights[y, x] = heightsReadback[x + offset + pixelRectX + ((y + offset + pixelRectY) * resolution)];
  897. }
  898. }
  899. if (area2D.currentTCUnityTerrain.tileX == 0 && area2D.currentTCUnityTerrain.tileZ == 0)// && !exportHeightmap)
  900. {
  901. area2D.currentTerrainArea.ResetNeighbors();
  902. }
  903. area2D.currentTerrain.terrainData.SetHeights(pixelRectX, pixelRectY, heights);
  904. if (area2D.currentTCUnityTerrain.tileX == area2D.currentTerrainArea.tiles.x - 1 && area2D.currentTCUnityTerrain.tileZ == area2D.currentTerrainArea.tiles.y - 1)
  905. {
  906. area2D.currentTerrainArea.SetNeighbors();
  907. }
  908. // area2D.currentTerrain.materialTemplate.SetTexture("_NormalMapGlobal", area2D.currentTCUnityTerrain.renderTex);
  909. // Debug.Log("Set heights");
  910. }
  911. else
  912. {
  913. // Debug.Log(area2D.currentMeshTerrain.t.name);
  914. // compute.RunTerrainTex(buffer, ref area2D.currentTCTerrain.rtHeight, true);
  915. // compute.DisposeBuffer(ref buffer);
  916. // Debug.Log(area2D.currentMeshTerrain.t.name);
  917. // Debug.Log("Assign RTP material");
  918. }
  919. }
  920. //void OnDrawGizmos()
  921. //{
  922. // // Debug.Log("help");
  923. // if (octree == null) return;
  924. // if (octree.cell != null) octree.cell.Draw(false);
  925. //}
  926. public void ComputeColor()
  927. {
  928. if (area2D.terrainLayer.layerGroups[TC.colorOutput] == null) return;
  929. TC_Compute compute = TC_Compute.instance;
  930. compute.SetPreviewColors(compute.colors);
  931. ComputeBuffer maskBuffer = null;
  932. TC_Compute.InitRenderTextures(ref compute.rtsColor, "rtsColor", 1);
  933. TC_Compute.InitRenderTexture(ref compute.rtResult, "rtResult");
  934. area2D.terrainLayer.layerGroups[TC.colorOutput].ComputeMulti(ref compute.rtsColor, ref maskBuffer, 0);
  935. area2D.currentTerrainArea.rtColormap = compute.rtsColor[0];
  936. if (maskBuffer != null) compute.DisposeBuffer(ref maskBuffer);
  937. if (!isMesh)
  938. {
  939. // compute.RunColormap(ref colorRTexture, ref area2D.currentTCUnityTerrain.colormap);
  940. RenderTexture rtActiveOld = RenderTexture.active;
  941. TC_Compute.InitTexture(ref area2D.currentTCUnityTerrain.texColormap, "texColormap", -1, true, TextureFormat.RGB24, true, false);
  942. Texture2D texColormap = area2D.currentTCUnityTerrain.texColormap;
  943. RenderTexture.active = area2D.currentTerrainArea.rtColormap;
  944. texColormap.ReadPixels(new Rect(0, 0, texColormap.width, texColormap.height), 0, 0);
  945. texColormap.Apply();
  946. if (TC_Settings.instance.isRTPDetected && TC_Settings.instance.autoColormapRTP)
  947. {
  948. area2D.currentTCUnityTerrain.AssignTextureRTP("ColorGlobal", area2D.currentTCUnityTerrain.texColormap);
  949. }
  950. RenderTexture.active = rtActiveOld;
  951. // if (area2D.currentTCUnityTerrain.terrain.materialTemplate != null) area2D.currentTCUnityTerrain.terrain.materialTemplate.SetTexture("_Colormap", area2D.currentTCUnityTerrain.texColormap);
  952. // else
  953. // {
  954. // TC.AddMessage("The TC2 Colormap material is not assigned to the terrain. So it won't show.");
  955. // TC.AddMessage("This will be added in the next beta.");
  956. // // TC.AddMessage("Please go to the Setting tab in the inspector on Terrain Area GameObject and assign the custom material 'TC2_TerrainMaterial'.");
  957. // // TC.AddMessage("The 'TC2_TerrainMaterial' is in the folder TerrainComposer2 -> Shaders -> Terrain.");
  958. //#if UNITY_EDITOR
  959. // // UnityEditor.Selection.activeTransform = area2D.terrainAreas[0].transform;
  960. //#endif
  961. // }
  962. // Material rtpMat = area2D.currentTerrain.materialTemplate;
  963. // rtpMat.SetTexture("_ColorMapGlobal", area2D.currentTCUnityTerrain.colormapTex);
  964. // area2D.currentTerrain.GetComponent<ReliefTerrain>().ColorGlobal = texColormap;
  965. }
  966. else
  967. {
  968. // compute.RunColormap(ref colorRTexture, ref area2D.currentMeshTerrain.colormap);
  969. area2D.currentMeshTerrain.rtpMat.SetTexture("_ColorMapGlobal", area2D.currentTerrainArea.rtColormap);
  970. }
  971. }
  972. public void ComputeSplat(Rect generateRect)
  973. {
  974. if (area2D.terrainLayer.layerGroups[TC.splatOutput] == null) return;
  975. int splatLength = area2D.splatLength;
  976. int splatmapLength = area2D.splatmapLength;
  977. // Debug.Log("Splat Compute " + TC_Area2D.current.currentTCUnityTerrain.terrain.name);
  978. if (splatLength == 0)
  979. {
  980. TC.AddMessage("No splat textures assigned to terrain '" + area2D.currentTerrain.name + "'");
  981. TC.AddMessage("Splat textures can be assigned on the Terrain Area GameObject -> Splat tab.", 2);
  982. return;
  983. }
  984. else if (splatLength > TC.splatLimit)
  985. {
  986. TC.AddMessage("TC2 supports generating maximum " + TC.splatLimit + " splat textures. There are " + splatLength + " on " + area2D.currentTerrain.name + " assigned.", 0, 4);
  987. return;
  988. }
  989. TC_Compute compute = TC_Compute.instance;
  990. ComputeBuffer maskBuffer = null;
  991. RenderTexture[] rtSplatmaps;
  992. compute.SetPreviewColors(compute.splatColors);
  993. if (!isMesh)
  994. {
  995. TC_Compute.InitRenderTextures(ref area2D.currentTerrainArea.rtSplatmaps, "splatmapRTextures", splatmapLength);
  996. }
  997. else
  998. {
  999. // TCCompute.InitRenderTextures(ref area2D.currentTerrainArea.splatmapRTextures, "splatmapRTextures");
  1000. // splatmapRTextures = area2D.currentTerrainArea.splatmapRTextures;
  1001. // area2D.terrainTex = area2D.currentTerrainArea.renderTex;
  1002. }
  1003. TC_Compute.InitRenderTextures(ref compute.rtsResult, "resultRTextures", splatmapLength);
  1004. rtSplatmaps = area2D.currentTerrainArea.rtSplatmaps;
  1005. area2D.terrainLayer.layerGroups[TC.splatOutput].ComputeMulti(ref rtSplatmaps, ref maskBuffer, 0);
  1006. if (maskBuffer != null) compute.DisposeBuffer(ref maskBuffer);
  1007. if (!isMesh)
  1008. {
  1009. Texture2D[] texSplatmaps = area2D.currentTerrain.terrainData.alphamapTextures;
  1010. generateRect = Mathw.ClampRect (generateRect, new Rect (0,0,1,1));
  1011. // The rect has to be transformed into pixel-space, accounting for different source(RT) and target (Tex) resolutions
  1012. // First, rect has to be transformed to tex, then to RT space in order to sync destX/Y and srcRect
  1013. // This prevents flickering and small sporadic movements of the splatmap on the terrain
  1014. Int2 dest;
  1015. Rect srcRect = Mathw.UniformRectToResolution (generateRect, new Int2 (rtSplatmaps[0].width, rtSplatmaps[0].height), new Int2 (texSplatmaps[0].width, texSplatmaps[0].height), out dest);
  1016. // For some odd reason, y-position has to be inverted
  1017. srcRect.y = rtSplatmaps[0].width-srcRect.y-srcRect.height;
  1018. //TODO Debug.Log ("Assigning splats at " + generateRect.ToString () + " from source pixel rect " + srcRect.ToString ());
  1019. RenderTexture rtActiveOld = RenderTexture.active;
  1020. // Debug.Log(area2D.currentTerrain.name + " " + splatmapRTextures.Length);
  1021. for (int i = 0; i < rtSplatmaps.Length; i++)
  1022. {
  1023. RenderTexture.active = rtSplatmaps[i];
  1024. texSplatmaps[i].ReadPixels(srcRect, dest.x, dest.y);
  1025. texSplatmaps[i].Apply();
  1026. }
  1027. RenderTexture.active = rtActiveOld;
  1028. }
  1029. else
  1030. {
  1031. area2D.currentMeshTerrain.rtpMat.SetTexture("_Control1", rtSplatmaps[0]);
  1032. area2D.currentMeshTerrain.rtpMat.SetTexture("_Control2", rtSplatmaps[1]);
  1033. area2D.currentMeshTerrain.rtpMat.SetTexture("_Control3", rtSplatmaps[1]);
  1034. // Debug.Log("Assign rtp splat");
  1035. }
  1036. // Debug.Log("Frames generate " + area2D.currentTerrain.name + " " + f.ToString("F2"));
  1037. }
  1038. // TODO: Same as splat
  1039. public void ComputeGrass()
  1040. {
  1041. if (area2D.terrainLayer.layerGroups[TC.grassOutput] == null) return;
  1042. int grassLength = area2D.currentTerrain.terrainData.detailPrototypes.Length;
  1043. if (grassLength == 0)
  1044. {
  1045. TC.AddMessage("No grass assigned to terrain '" + area2D.currentTerrain.name + "'");
  1046. TC.AddMessage("Grass can be assigned on the Terrain Area GameObject -> Grass tab.", 2);
  1047. return;
  1048. }
  1049. else if (grassLength > TC.grassLimit)
  1050. {
  1051. TC.AddMessage("TC2 supports generating maximum " + TC.grassLimit + " grass textures. There are " + grassLength + " on " + area2D.currentTerrain.name + " assigned.", 0, 4);
  1052. return;
  1053. }
  1054. int resolution = area2D.intResolution.x;
  1055. TC_Compute compute = TC_Compute.instance;
  1056. compute.SetPreviewColors(compute.splatColors);
  1057. ComputeBuffer maskBuffer = null;
  1058. int grassCount = area2D.currentTerrain.terrainData.detailPrototypes.Length;
  1059. int grassmapCount = Mathf.CeilToInt(grassCount / 4.0f);
  1060. // Debug.Log(grassCount);
  1061. // TC_Compute.InitRenderTextures(ref area2D.currentTerrainArea.rtSplatmaps, "splatmapRTextures");
  1062. TC_Compute.InitRenderTextures(ref compute.rtsSplatmap, "rtsSplatmap", grassmapCount);
  1063. TC_Compute.InitRenderTextures(ref compute.rtsResult, "rtsResult", grassmapCount);
  1064. RenderTexture[] rtGrassmaps = compute.rtsSplatmap;
  1065. area2D.terrainLayer.layerGroups[TC.grassOutput].ComputeMulti(ref rtGrassmaps, ref maskBuffer, 0);
  1066. compute.DisposeBuffer(ref maskBuffer);
  1067. TC_Compute.InitTextures(ref compute.texGrassmaps, "grassTextures", grassmapCount);
  1068. compute.InitBytesArray(grassmapCount);
  1069. TC_Compute.BytesArray[] bytesArray = compute.bytesArray;
  1070. RenderTexture rtActiveOld = RenderTexture.active;
  1071. for (int i = 0; i < rtGrassmaps.Length; i++)
  1072. {
  1073. RenderTexture.active = rtGrassmaps[i];
  1074. compute.texGrassmaps[i].ReadPixels(new Rect(0, 0, rtGrassmaps[i].width, rtGrassmaps[i].height), 0, 0);
  1075. bytesArray[i].bytes = compute.texGrassmaps[i].GetRawTextureData();
  1076. }
  1077. RenderTexture.active = rtActiveOld;
  1078. TC.InitArray(ref grass, resolution, resolution);
  1079. int index, colorIndex, byteIndex;
  1080. for (int i = 0; i < grassCount; ++i)
  1081. {
  1082. index = i / 4;
  1083. colorIndex = (1 + (i - (index * 4))) % 4;
  1084. for (int y = 0; y < resolution; ++y)
  1085. {
  1086. for (int x = 0; x < resolution; ++x)
  1087. {
  1088. byteIndex = (y * resolution * 4) + (x * 4) + colorIndex;
  1089. grass[y, x] = (int)(((float)bytesArray[index].bytes[byteIndex] / 255.0f) * 16.0f);
  1090. }
  1091. }
  1092. area2D.currentTerrain.terrainData.SetDetailLayer(0, 0, i, grass);
  1093. }
  1094. }
  1095. public void ComputeTree()
  1096. {
  1097. if (area2D.terrainLayer.layerGroups[TC.treeOutput] == null) return;
  1098. if (area2D.currentTerrain.terrainData.treePrototypes.Length == 0)
  1099. {
  1100. TC.AddMessage("No trees assigned to terrain '" + area2D.currentTerrain.name + "'");
  1101. TC.AddMessage("Trees can be assigned on the Terrain Area GameObject -> Trees tab.", 2);
  1102. return;
  1103. }
  1104. if (firstTreeTerrain == area2D.currentTCTerrain)
  1105. {
  1106. area2D.terrainLayer.ResetPlaced();
  1107. firstTreeTerrain = null;
  1108. //if (octree == null) octree = new Octree();
  1109. //if (octree.cell == null)
  1110. //{
  1111. // octree.cell = new Octree.Cell(null, 0, area2D.totalTerrainBounds);
  1112. // octree.cell.maxLevels = 8;// Mathf.RoundToInt(octree.cell.bounds.size.x / 32);
  1113. // //Debug.Log(octree.cell.maxLevels);
  1114. //}
  1115. //else if (octree.cell.bounds != area2D.totalTerrainBounds) octree.cell.bounds = area2D.totalTerrainBounds;
  1116. //Debug.Log(octree.cell.bounds.size);
  1117. //octree.cell.Reset();
  1118. }
  1119. int resolution = area2D.intResolution.x;
  1120. TC_Compute compute = TC_Compute.instance;
  1121. compute.SetPreviewColors(compute.splatColors);
  1122. ComputeBuffer itemMapBuffer = null;
  1123. area2D.terrainLayer.layerGroups[TC.treeOutput].ComputeSingle(ref itemMapBuffer, 0, true);
  1124. // compute.RunItemPositionCompute(itemMapBuffer, TC.treeOutput);
  1125. ItemMap[] itemMap = new ItemMap[resolution * resolution];
  1126. itemMapBuffer.GetData(itemMap);
  1127. compute.DisposeBuffer(ref itemMapBuffer);
  1128. if (trees == null) trees = new List<TreeInstance>();
  1129. Vector3 terrainSize = area2D.currentTerrain.terrainData.size;
  1130. Vector3 terrainPos = area2D.currentTerrain.transform.position;
  1131. Vector3 outputOffset = area2D.outputOffsetV3;
  1132. List<TC_SelectItem> treeItems = TC_Area2D.current.terrainLayer.treeSelectItems;
  1133. for (int y = 0; y < resolution; ++y)
  1134. {
  1135. for (int x = 0; x < resolution; ++x)
  1136. {
  1137. // TODO: Move more to compute shader
  1138. int index = (y * resolution) + x;
  1139. float density = itemMap[index].density * itemMap[index].maskValue;
  1140. if (density == 0) continue;
  1141. Vector3 pos = new Vector3((float)x / resolution, 0, (float)y / resolution);
  1142. Vector3 pos2 = pos + itemMap[index].pos;
  1143. if (pos2.x < 0 || pos2.x > 1 || pos2.z < 0 || pos2.z > 1)
  1144. {
  1145. // Debug.Log(position.x + ", "+position.y+", "+position.z);
  1146. continue;
  1147. }
  1148. // Debug.Log("x " + itemMap[index].pos.x + " z " + itemMap[index].pos.z);
  1149. int id = itemMap[index].index;
  1150. if (id > treeItems.Count - 1)
  1151. {
  1152. TC.AddMessage("Tree index is out of bounds, index = " + id + ". Try the 'Refresh' button.");
  1153. return;
  1154. }
  1155. TC_SelectItem item = treeItems[id];
  1156. int treeIndex = item.selectIndex;
  1157. TC_SelectItem.Tree tree = item.tree;
  1158. Vector2 posSeed = new Vector2(pos.x * terrainSize.x, pos.z * terrainSize.z) + new Vector2(terrainPos.x - outputOffset.x, terrainPos.z - outputOffset.z);
  1159. posSeed = Mathw.SnapVector2(posSeed + new Vector2(area2D.resolutionPM.x / 4, area2D.resolutionPM.x / 4), area2D.resolutionPM.x / 2);
  1160. // pos.y += tree.heightOffset / terrainSize.y;
  1161. // Debug.Log(id + " " + treeIndex);
  1162. TreeInstance treeInstance = new TreeInstance();
  1163. treeInstance.color = Color.white;
  1164. treeInstance.lightmapColor = Color.white;
  1165. treeInstance.position = pos + itemMap[index].pos;
  1166. treeInstance.prototypeIndex = treeIndex;
  1167. //#if UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3
  1168. // Random.seed = (int)posSeed.x + ((int)posSeed.y * resolution);
  1169. //#else
  1170. // Random.InitState((int)posSeed.x + ((int)posSeed.z * resolution));
  1171. //#endif
  1172. treeInstance.rotation = RandomPos(posSeed + new Vector2(225.5f, 350.5f)) * 360;
  1173. Vector2 scaleRange = new Vector2(tree.scaleRange.x * item.parentItem.scaleMinMaxMulti.x, tree.scaleRange.y * item.parentItem.scaleMinMaxMulti.y);
  1174. float scaleRangeDelta = scaleRange.y - scaleRange.x;
  1175. if (scaleRangeDelta == 0) scaleRangeDelta = 0.001f;
  1176. treeInstance.heightScale = (tree.scaleCurve.Evaluate(RandomPos(posSeed)) * scaleRangeDelta) + scaleRange.x;
  1177. float scaleMulti = tree.scaleMulti * item.parentItem.scaleMulti;
  1178. treeInstance.heightScale *= scaleMulti;
  1179. if (item.parentItem.linkScaleToMask) treeInstance.heightScale *= Mathf.Lerp(1, itemMap[index].maskValue, item.parentItem.linkScaleToMaskAmount);
  1180. if (treeInstance.heightScale < scaleRange.x * scaleMulti) treeInstance.heightScale = scaleRange.x * scaleMulti;
  1181. treeInstance.widthScale = treeInstance.heightScale * ((RandomPos(posSeed + new Vector2(997.5f, 500.5f)) * tree.nonUniformScale * 2) + (1 - tree.nonUniformScale));
  1182. trees.Add(treeInstance);
  1183. ++item.placed;
  1184. // Octree.SpawnedObject obj = new Octree.SpawnedObject(index, new Vector3(treeInstance.position.x * terrainSize.x, treeInstance.position.y * terrainSize.y, treeInstance.position.z * terrainSize.z) + terrainPos);
  1185. // octree.cell.AddObject(obj);
  1186. }
  1187. }
  1188. area2D.currentTerrain.terrainData.treeInstances = trees.ToArray();
  1189. float[,] height1 = area2D.currentTerrain.terrainData.GetHeights(0, 0, 1, 1);
  1190. area2D.currentTerrain.terrainData.SetHeights(0, 0, height1);
  1191. trees.Clear();
  1192. area2D.terrainLayer.CalcTreePlaced();
  1193. }
  1194. public void ComputeObject()
  1195. {
  1196. // float minHeight = Mathf.Infinity, maxHeight = 0;
  1197. if (objectParent != null) DestroyImmediate(objectParent);
  1198. if (area2D.terrainLayer.layerGroups[TC.objectOutput] == null) return;
  1199. if (area2D.terrainLayer.objectSelectItems.Count == 0)
  1200. {
  1201. TC.AddMessage("No objects nodes are active.");
  1202. return;
  1203. }
  1204. if (firstObjectTerrain == area2D.currentTCTerrain) { area2D.terrainLayer.ResetPlaced(); firstObjectTerrain = null; }
  1205. int resolution = area2D.intResolution.x;
  1206. Transform objectsParent = CheckObjectsParent(area2D.currentTCUnityTerrain);
  1207. if (assignTerrainHeightmap)
  1208. {
  1209. area2D.currentTCUnityTerrain.ResetObjects();
  1210. area2D.terrainLayer.ResetObjects();
  1211. }
  1212. TC_Compute compute = TC_Compute.instance;
  1213. compute.SetPreviewColors(compute.splatColors);
  1214. ComputeBuffer itemMapBuffer = null;
  1215. area2D.terrainLayer.layerGroups[TC.objectOutput].ComputeSingle(ref itemMapBuffer, 0, true);
  1216. // compute.RunItemPositionCompute(itemMapBuffer, TC.objectOutput);
  1217. ItemMap[] itemMap = new ItemMap[resolution * resolution];
  1218. itemMapBuffer.GetData(itemMap);
  1219. compute.DisposeBuffer(ref itemMapBuffer);
  1220. // Vector2 terrainSize = area2D.area.size;
  1221. // Vector2 terrainPos = area2D.area.position;
  1222. Vector3 terrainSize = area2D.currentTerrain.terrainData.size;
  1223. Vector3 terrainPos = area2D.currentTerrain.transform.position;
  1224. Vector3 outputOffset = area2D.outputOffsetV3;
  1225. // tcGenerate.ClearSpawnedObjects();
  1226. // for (int i = 0; i < tcGenerate.objectItems.Length; i++) tcGenerate.objectItems[i].objectCount = 0;
  1227. // Debug.Log(TCLayerLevel.current.objectitems.Count);
  1228. // return;
  1229. List<TC_SelectItem> objectItems = TC_Area2D.current.terrainLayer.objectSelectItems;
  1230. for (int y = 0; y < resolution; ++y)
  1231. {
  1232. for (int x = 0; x < resolution; ++x)
  1233. {
  1234. int index = (y * resolution) + x;
  1235. float density = itemMap[index].density * itemMap[index].maskValue;
  1236. if (density == 0) continue;
  1237. Vector3 pos = new Vector3(((float)x / resolution), 0, ((float)y / resolution));
  1238. Vector3 pos2 = pos + itemMap[index].pos;
  1239. if (pos2.x < 0 || pos2.x > 1 || pos2.z < 0 || pos2.z > 1)
  1240. {
  1241. // Debug.Log(position.x + ", "+position.y+", "+position.z);
  1242. continue;
  1243. }
  1244. // Debug.Log("x " + itemMap[index].pos.x + " z " + itemMap[index].pos.z);
  1245. int id = itemMap[index].index;
  1246. if (id > objectItems.Count - 1)
  1247. {
  1248. // Debug.Log("Object index is out of bounds, index = " + id);
  1249. TC.AddMessage("Object index is out of bounds, index = " + id + ". Try the 'Refresh' button.");
  1250. return;
  1251. }
  1252. TC_SelectItem item = objectItems[id];
  1253. TC_SelectItem.SpawnObject spawnObject = item.spawnObject;
  1254. // Debug.Log("x " + itemMap[index].pos.x + " z " + itemMap[index].pos.z);
  1255. // Debug.Log(itemMap[index].pos);
  1256. pos = new Vector3(pos.x * terrainSize.x, pos.y, pos.z * terrainSize.z) + terrainPos; // - item.t.parent.parent.position;
  1257. Vector3 posSeed = Mathw.SnapVector3(pos + new Vector3(area2D.resolutionPM.x / 4, 0, area2D.resolutionPM.x / 4), area2D.resolutionPM.x / 2) - outputOffset;
  1258. pos += new Vector3(itemMap[index].pos.x * terrainSize.x, 0, itemMap[index].pos.z * terrainSize.z);
  1259. // Debug.Log(itemMap[index].pos.x +", "+itemMap[index].pos.z);
  1260. if (spawnObject.includeTerrainHeight) pos.y = area2D.currentTerrain.SampleHeight(pos);
  1261. else pos.y = 0;
  1262. pos.y += TC_Settings.instance.generateOffset.y;
  1263. // Debug.Log((posSeed.x - pos.x) + ", " + (posSeed.z - pos.z));
  1264. #if UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3
  1265. Random.seed = (int)posSeed.x + ((int)posSeed.z * resolution);
  1266. #else
  1267. Random.InitState((int)posSeed.x + ((int)posSeed.z * resolution));
  1268. #endif
  1269. Vector3 rotation;
  1270. if (spawnObject.includeTerrainAngle)
  1271. {
  1272. Vector3 normal = area2D.currentTerrain.terrainData.GetInterpolatedNormal(pos2.x, pos2.z);
  1273. rotation.x = normal.z * 90;
  1274. rotation.y = 0;
  1275. rotation.z = normal.x * -90;
  1276. }
  1277. else rotation = Vector3.zero;
  1278. if (spawnObject.lookAtTarget != null)
  1279. {
  1280. rotation = Quaternion.LookRotation(spawnObject.lookAtTarget.position - pos).eulerAngles;
  1281. if (!spawnObject.lookAtX) rotation.x = rotation.z = 0;
  1282. }
  1283. #if UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3
  1284. Random.seed = (int)posSeed.x + ((int)posSeed.z * resolution);
  1285. #else
  1286. Random.InitState((int)posSeed.x + ((int)posSeed.z * resolution));
  1287. #endif
  1288. Vector3 scale;
  1289. float scaleMulti = spawnObject.scaleMulti * item.parentItem.scaleMulti;
  1290. if (!spawnObject.customScaleRange)
  1291. {
  1292. float scaleRangeDelta = spawnObject.scaleRange.y - spawnObject.scaleRange.x;
  1293. if (scaleRangeDelta == 0) scaleRangeDelta = 0.001f;
  1294. scale.x = (spawnObject.scaleCurve.Evaluate(Random.value) * scaleRangeDelta) + spawnObject.scaleRange.x;
  1295. scale.x *= scaleMulti;
  1296. if (item.parentItem.linkScaleToMask) scale.x *= Mathf.Lerp(1, itemMap[index].maskValue, item.parentItem.linkScaleToMaskAmount);
  1297. if (scale.x < spawnObject.scaleRange.x * scaleMulti) scale.x = spawnObject.scaleRange.x * scaleMulti;
  1298. scale.y = scale.x * Random.Range(1 - spawnObject.nonUniformScale, 1 + spawnObject.nonUniformScale);
  1299. scale.z = scale.x * Random.Range(1 - spawnObject.nonUniformScale, 1 + spawnObject.nonUniformScale);
  1300. }
  1301. else
  1302. {
  1303. float scaleRangeDeltaX = spawnObject.scaleRangeX.y - spawnObject.scaleRangeX.x;
  1304. if (scaleRangeDeltaX == 0) scaleRangeDeltaX = 0.001f;
  1305. float scaleRangeDeltaY = spawnObject.scaleRangeY.y - spawnObject.scaleRangeY.x;
  1306. if (scaleRangeDeltaY == 0) scaleRangeDeltaY = 0.001f;
  1307. float scaleRangeDeltaZ = spawnObject.scaleRangeZ.y - spawnObject.scaleRangeZ.x;
  1308. if (scaleRangeDeltaZ == 0) scaleRangeDeltaZ = 0.001f;
  1309. scale.x = (spawnObject.scaleCurve.Evaluate(Random.value) * scaleRangeDeltaX) + spawnObject.scaleRangeX.x;
  1310. scale.y = (spawnObject.scaleCurve.Evaluate(Random.value) * scaleRangeDeltaY) + spawnObject.scaleRangeY.x;
  1311. scale.z = (spawnObject.scaleCurve.Evaluate(Random.value) * scaleRangeDeltaZ) + spawnObject.scaleRangeZ.x;
  1312. scale *= scaleMulti;
  1313. if (item.parentItem.linkScaleToMask) scale *= Mathf.Lerp(1, itemMap[index].maskValue, item.parentItem.linkScaleToMaskAmount);
  1314. if (scale.x < spawnObject.scaleRangeX.x * scaleMulti) scale.x = spawnObject.scaleRangeX.x * scaleMulti;
  1315. if (scale.y < spawnObject.scaleRangeY.x * scaleMulti) scale.y = spawnObject.scaleRangeY.x * scaleMulti;
  1316. if (scale.z < spawnObject.scaleRangeZ.x * scaleMulti) scale.z = spawnObject.scaleRangeZ.x * scaleMulti;
  1317. }
  1318. pos.y += spawnObject.heightOffset;
  1319. if (spawnObject.includeScale) pos.y += Random.Range(spawnObject.heightRange.x, spawnObject.heightRange.y) * scale.y;
  1320. else pos.y += Random.Range(spawnObject.heightRange.x, spawnObject.heightRange.y);
  1321. GameObject go;
  1322. Transform t;
  1323. #if !UNITY_EDITOR
  1324. go = (GameObject)Instantiate(spawnObject.go, pos, Quaternion.Euler(rotation));
  1325. t = go.transform;
  1326. #else
  1327. // TODO rotation can be returned as Quaternion
  1328. if (!spawnObject.linkToPrefab) {
  1329. go = (GameObject)Instantiate(spawnObject.go, pos, Quaternion.Euler(rotation));
  1330. t = go.transform;
  1331. }
  1332. else
  1333. {
  1334. go = (GameObject)UnityEditor.PrefabUtility.InstantiatePrefab(spawnObject.go);
  1335. t = go.transform;
  1336. t.position = pos;
  1337. t.rotation = Quaternion.Euler(rotation);
  1338. }
  1339. #endif
  1340. t.Rotate(new Vector3(Random.Range(spawnObject.rotRangeX.x, spawnObject.rotRangeX.y), Random.Range(spawnObject.rotRangeY.x, spawnObject.rotRangeY.y), Random.Range(spawnObject.rotRangeZ.x, spawnObject.rotRangeZ.y)), Space.Self);
  1341. if (spawnObject.isSnapRot)
  1342. {
  1343. if (spawnObject.isSnapRotX) rotation.x = ((int)(rotation.x / spawnObject.snapRotX)) * spawnObject.snapRotX;
  1344. if (spawnObject.isSnapRotY) rotation.y = ((int)(rotation.y / spawnObject.snapRotY)) * spawnObject.snapRotY;
  1345. if (spawnObject.isSnapRotZ) rotation.z = ((int)(rotation.z / spawnObject.snapRotZ)) * spawnObject.snapRotZ;
  1346. }
  1347. //if (tcObject.spawnList.Count <= tcGenerate.objectItems[objectIndex].objectCount)
  1348. //{
  1349. go.name = spawnObject.go.name;
  1350. if (spawnObject.parentMode == TC_SelectItem.SpawnObject.ParentMode.Terrain) t.parent = objectsParent;
  1351. else if (spawnObject.parentMode == TC_SelectItem.SpawnObject.ParentMode.Existing) t.parent = spawnObject.parentT;
  1352. else if (spawnObject.parentMode == TC_SelectItem.SpawnObject.ParentMode.Create)
  1353. {
  1354. if (spawnObject.newParentT == null)
  1355. {
  1356. GameObject parentGO = new GameObject(spawnObject.parentName);
  1357. if (spawnObject.parentToTerrain) parentGO.transform.parent = objectsParent;
  1358. spawnObject.newParentT = parentGO.transform;
  1359. }
  1360. t.parent = spawnObject.newParentT;
  1361. }
  1362. t.localScale = Vector3.Scale(spawnObject.go.transform.localScale, scale);
  1363. ++item.placed;
  1364. // tcObject.spawnList.Add(go.transform);
  1365. //}
  1366. //else
  1367. //{
  1368. // tcObject.spawnList[tcGenerate.objectItems[objectIndex].objectCount].position = position;
  1369. // tcObject.spawnList[tcGenerate.objectItems[objectIndex].objectCount].rotation = Quaternion.Euler(rotation);
  1370. // tcObject.spawnList[tcGenerate.objectItems[objectIndex].objectCount].localScale = scale;
  1371. // tcObject.spawnList[tcGenerate.objectItems[objectIndex].objectCount].gameObject.SetActive(true);
  1372. //}
  1373. // ++tcGenerate.objectItems[objectIndex].objectCount;
  1374. //}
  1375. // if (pos.y > maxHeight) maxHeight = pos.y;
  1376. // else if (pos.y < minHeight) minHeight = pos.y;
  1377. }
  1378. }
  1379. // Debug.Log("Min height " + minHeight + " Max height " + maxHeight);
  1380. area2D.terrainLayer.CalcObjectPlaced();
  1381. //for (int j = 0; j < tcGenerate.objectItems.Length; ++j)
  1382. //{
  1383. // for (int i = tcGenerate.objectItems[j].objectCount; i < tcObjects[j].spawnList.Count; i++) tcObjects[j].spawnList[i].gameObject.SetActive(false);
  1384. //}
  1385. }
  1386. public float RandomPos(Vector2 pos)
  1387. {
  1388. return Mathw.Frac(Mathf.Sin(Vector2.Dot(pos, new Vector2(12.9898f, 78.233f))) * 43758.5453123f);
  1389. }
  1390. public Transform CheckObjectsParent(TCUnityTerrain tcUnityTerrain)
  1391. {
  1392. if (tcUnityTerrain.objectsParent == null)
  1393. {
  1394. tcUnityTerrain.objectsParent = new GameObject("TerrainComposer Objects").transform;
  1395. tcUnityTerrain.objectsParent.parent = tcUnityTerrain.terrain.transform;
  1396. }
  1397. return tcUnityTerrain.objectsParent;
  1398. }
  1399. struct ItemMap
  1400. {
  1401. public int index;
  1402. public float density;
  1403. public float maskValue;
  1404. public Vector3 pos;
  1405. };
  1406. [System.Serializable]
  1407. public class GenerateStackEntry
  1408. {
  1409. public List<GenerateStack> stack = new List<GenerateStack>();
  1410. public int frame;
  1411. public GenerateStackEntry(int frame)
  1412. {
  1413. this.frame = frame;
  1414. }
  1415. }
  1416. [System.Serializable]
  1417. public class GenerateStack
  1418. {
  1419. public TCUnityTerrain tcTerrain;
  1420. public int outputId;
  1421. public bool assignTerrainHeightmap;
  1422. public Rect generateRect;
  1423. public GenerateStack(int outputId, TCUnityTerrain tcTerrain, bool assignTerrainHeightmap)
  1424. {
  1425. this.tcTerrain = tcTerrain;
  1426. this.outputId = outputId;
  1427. this.assignTerrainHeightmap = assignTerrainHeightmap;
  1428. }
  1429. public GenerateStack(int outputId, TCUnityTerrain tcTerrain, bool assignTerrainHeightmap, Rect generateRect)
  1430. {
  1431. this.tcTerrain = tcTerrain;
  1432. this.outputId = outputId;
  1433. this.assignTerrainHeightmap = assignTerrainHeightmap;
  1434. this.generateRect = generateRect;
  1435. }
  1436. }
  1437. }
  1438. }