/// <summary> /// Static import of terrain files into project/scene. No streaming. /// </summary> /// <param name="folderPath"></param> public void ImportFolderIntoScene(int lodLevel, TaskProgressToken token) { /* Todo: * - Unify more code with the streaming system (i.e. this terrain is streamed once at startup, but same code) * - Allow iterative work flow (i.e. just reimporting splatmaps, not everything) * - support running batches, parallel processing */ Debug.Log("Importing lod level: " + lodLevel); try { var lod = ImportCfg.LodLevels[lodLevel]; List <string> heightmapFiles = FilterFolder(lod.FolderPath, ImportCfg.HeightmapTag, ImportCfg.HeightmapExtention); var terrainDatas = CreateTerrainDatas(lod.FolderPath, heightmapFiles, lod); if (heightmapFiles == null || heightmapFiles.Count == 0) { throw new ArgumentException(string.Format("No heightmaps found in folder after filtering: " + lod.FolderPath)); } ProcessHeightmapAssets(heightmapFiles, terrainDatas, lod, token); List <string> splatmapFiles = FilterFolder(lod.FolderPath, ImportCfg.SplatmapTag, ImportCfg.SplatmapExtention); if (splatmapFiles == null || splatmapFiles.Count != heightmapFiles.Count) { throw new ArgumentException(string.Format("The number of splatmaps {0} does not match the number of heightmaps {1}.", splatmapFiles.Count, heightmapFiles.Count)); } ProcessSplatmapAssets(splatmapFiles, terrainDatas, token); if (lod.HasDetailMap) { List <string> detailmapFiles = FilterFolder(lod.FolderPath, ImportCfg.DetailmapTag, ImportCfg.SplatmapExtention); if (detailmapFiles == null || detailmapFiles.Count != heightmapFiles.Count) { throw new ArgumentException(string.Format("The number of detailmaps {0} does not match the number of heightmaps {1}.", detailmapFiles.Count, heightmapFiles.Count)); } ProcessDetailmapAssets(detailmapFiles, terrainDatas, token); } if (lod.HasTreeMap) { List <string> treemapFiles = FilterFolder(lod.FolderPath, ImportCfg.TreemapTag, ImportCfg.SplatmapExtention); if (treemapFiles == null || treemapFiles.Count != heightmapFiles.Count) { throw new ArgumentException(string.Format("The number of treemaps {0} does not match the number of heightmaps {1}.", treemapFiles.Count, heightmapFiles.Count)); } ProcessTreemapAssets(treemapFiles, terrainDatas, token); } var terrains = InstantiateTerrainInScene(heightmapFiles, terrainDatas, lod); SetupLandmassUnityTerrain(terrains, lod, CustomShaderId, MaterialPath); } catch (Exception e) { Debug.LogError("Failed to import terrains into scene."); Debug.LogException(e); } IsProcessing = false; }
public void ProcessTreemapAssets(IList <string> assets, IList <TerrainData> terrainDatas, TaskProgressToken token) { IsProcessing = true; for (int i = 0; i < assets.Count; i++) { // Display progress bar with cancel button token.Progress = (i + 1) / (float)assets.Count; if (token.Cancel) { break; } string asset = assets[i]; TerrainData terrainData = terrainDatas[i]; LandmasImporter.Instance.ApplyTreePrototypes(terrainData, TreePrototypes); Texture2D treemapTexture = AssetDatabase.LoadAssetAtPath(asset, typeof(Texture2D)) as Texture2D; LandmasImporter.ParseTreemapTexturesToTerrain(treemapTexture, terrainData); if (i % ImportCfg.BatchLimit == 0) { FlushAssetsToDisk(); } } FlushAssetsToDisk(); IsProcessing = false; }
public void ProcessSplatmapAssets(IList <string> assets, IList <TerrainData> terrainDatas, TaskProgressToken token) { LandmasImporter.ValidateSplatPrototypes(SplatPrototypes); IsProcessing = true; for (int i = 0; i < assets.Count; i++) { // Display progress bar with cancel button token.Progress = (i + 1) / (float)assets.Count; if (token.Cancel) { break; } string asset = assets[i]; TerrainData terrainData = terrainDatas[i]; LandmasImporter.Instance.ApplySplatPrototypes(terrainData, SplatPrototypes); Texture2D splatmapTexture = AssetDatabase.LoadAssetAtPath(asset, typeof(Texture2D)) as Texture2D; var splatmap = new float[terrainData.alphamapResolution, terrainData.alphamapResolution, 4]; LandmasImporter.TextureToSplatMap(splatmapTexture, ref splatmap, false, false); LandmasImporter.Instance.ParseSplatmapToTerrain(splatmap, terrainData); if (i % ImportCfg.BatchLimit == 0) { FlushAssetsToDisk(); } } FlushAssetsToDisk(); IsProcessing = false; }
// Todo: process detail maps (grass and such) public void ProcessDetailmapAssets(IList <string> assets, IList <TerrainData> terrainDatas, TaskProgressToken token) { IsProcessing = true; for (int i = 0; i < assets.Count; i++) { // Display progress bar with cancel button token.Progress = (i + 1) / (float)assets.Count; if (token.Cancel) { break; } string asset = assets[i]; TerrainData terrainData = terrainDatas[i]; LandmasImporter.Instance.ApplyDetailPrototypes(terrainData, DetailPrototypes); Texture2D texture = AssetDatabase.LoadAssetAtPath(asset, typeof(Texture2D)) as Texture2D; int[][,] map = new int[DetailPrototypes.Count][, ]; for (int j = 0; j < map.Length; j++) { map[j] = new int[texture.width, texture.height]; } LandmasImporter.TextureToDetailMap(texture, ref map, false, false); LandmasImporter.Instance.ParseDetailmapToTerrain(map, terrainData); if (i % ImportCfg.BatchLimit == 0) { FlushAssetsToDisk(); } } FlushAssetsToDisk(); IsProcessing = false; }
public void ProcessHeightmapAssets(IList <string> assets, IList <TerrainData> terrains, LodLevel lod, TaskProgressToken token) { if (IsProcessing) { return; } IsProcessing = true; token.Title = "Processing heightmaps..."; // Todo: split out terrain data creation/retrieval, call it here to get List<TerrainData>, or something for (int i = 0; i < assets.Count; i++) { token.Progress = (float)(i + 1) / assets.Count; if (token.Cancel) { break; } string heightmapPath = assets[i]; TerrainData terrainData = terrains[i]; var heightData = new float[lod.HeightmapResolution, lod.HeightmapResolution]; LandmasImporter.LoadRawFileAsFloats( heightmapPath, ref heightData, ImportCfg.HeightFormat, false, true); // For 8-bit PNGs //var heightTexture = LandmasImporter.LoadTexture(heightmapPath, ImportCfg.HeightmapResolution); //LandmasImporter.TextureToHeightMap(heightTexture, ref heightData, false, true); terrainData.SetHeights(0, 0, heightData); // Save assets to disk and flush them from memory if (i % ImportCfg.BatchLimit == 0) { FlushAssetsToDisk(); } } FlushAssetsToDisk(); IsProcessing = false; }