public void RemoveForeignTerrainDetails(List <SpawnerSettings> biomeSpawnerSettings, List <string> validTerrainNames = null) { ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign Terrain Details", "Removing..."); List <ResourceProtoDetail> knownTerrainDetails = new List <ResourceProtoDetail>(); Terrain currentTerrain = GetCurrentTerrain(); foreach (SpawnerSettings spawnerSettings in biomeSpawnerSettings) { foreach (SpawnRule sr in spawnerSettings.m_spawnerRules) { if (sr.m_resourceType == GaiaConstants.SpawnerResourceType.TerrainDetail) { knownTerrainDetails.Add(spawnerSettings.m_resources.m_detailPrototypes[sr.m_resourceIdx]); } } } GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(currentTerrain, transform, m_settings.m_range * 2f, false, validTerrainNames); operation.GetHeightmap(); operation.GetNormalmap(); operation.CollectTerrainDetails(); operation.CollectTerrainTrees(); operation.CollectTerrainGameObjects(); operation.CollectTerrainBakedMasks(); ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign Terrain Details", "Removing Terrain Details..."); operation.RemoveForeignTerrainDetails(ApplyBrush(operation, MultiTerrainOperationType.TerrainDetail), knownTerrainDetails, m_settings.m_removeForeignTerrainDetailsStrength); operation.CloseOperation(); ProgressBar.Clear(ProgressBarPriority.BiomeRemoval); }
public void RemoveForeignTrees(List <SpawnerSettings> biomeSpawnerSettings, List <string> validTerrainNames = null) { ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign Trees", "Removing..."); //Collect the "allowed" tree prefabs in a list, any tree that is not in this list will be affected by the removal operation List <GameObject> domesticTreePrefabs = new List <GameObject>(); //List<TreePrototype> treeProtosToRemove = new List<TreePrototype>(); Terrain currentTerrain = GetCurrentTerrain(); foreach (SpawnerSettings spawnerSettings in biomeSpawnerSettings) { foreach (SpawnRule sr in spawnerSettings.m_spawnerRules) { if (sr.m_resourceType == GaiaConstants.SpawnerResourceType.TerrainTree) { domesticTreePrefabs.Add(spawnerSettings.m_resources.m_treePrototypes[sr.m_resourceIdx].m_desktopPrefab); } } } GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(currentTerrain, transform, m_settings.m_range * 2f, false, validTerrainNames); operation.GetHeightmap(); operation.GetNormalmap(); operation.CollectTerrainDetails(); operation.CollectTerrainTrees(); operation.CollectTerrainGameObjects(); operation.CollectTerrainBakedMasks(); operation.RemoveForeignTrees(ApplyBrush(operation, MultiTerrainOperationType.Tree), domesticTreePrefabs, m_settings.m_removeForeignTreesStrength); ProgressBar.Clear(ProgressBarPriority.BiomeRemoval); operation.CloseOperation(); }
public static void BakeMaskStack(ImageMask[] maskStack, Terrain terrain, Transform transform, float range, int resolution, string path) { //Simulate an operation to allow the image masks to acces the current terrain data GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(terrain, transform, range); operation.GetHeightmap(); operation.GetNormalmap(); operation.CollectTerrainBakedMasks(); float maxCurrentTerrainHeight = 0f; float minCurrentTerrainHeight = 0f; float seaLevel; GaiaSessionManager gsm = GaiaSessionManager.GetSessionManager(); gsm.GetWorldMinMax(ref minCurrentTerrainHeight, ref maxCurrentTerrainHeight); seaLevel = gsm.GetSeaLevel(); if (maskStack.Length > 0) { //We start from a white texture, so we need the first mask action in the stack to always be "Multiply", otherwise there will be no result. maskStack[0].m_blendMode = ImageMaskBlendMode.Multiply; //Iterate through all image masks and set up the required data that masks might need to function properly foreach (ImageMask mask in maskStack) { //mask.m_heightmapContext = heightmapContext; //mask.m_normalmapContext = normalmapContext; //mask.m_collisionContext = collisionContext; mask.m_multiTerrainOperation = operation; mask.m_seaLevel = seaLevel; mask.m_maxWorldHeight = maxCurrentTerrainHeight; mask.m_minWorldHeight = minCurrentTerrainHeight; } } RenderTexture inputTexture = RenderTexture.GetTemporary(resolution, resolution, 0, RenderTextureFormat.ARGBFloat); RenderTexture currentRT = RenderTexture.active; RenderTexture.active = inputTexture; GL.Clear(true, true, Color.white); RenderTexture.active = currentRT; RenderTexture localOutputTexture = RenderTexture.GetTemporary(inputTexture.descriptor); RenderTexture globalOutputTexture = RenderTexture.GetTemporary(inputTexture.descriptor); localOutputTexture = ImageProcessing.ApplyMaskStack(inputTexture, localOutputTexture, maskStack, ImageMaskInfluence.Local); globalOutputTexture = ImageProcessing.ApplyMaskStack(localOutputTexture, globalOutputTexture, maskStack, ImageMaskInfluence.Global); WriteRenderTexture(path, globalOutputTexture); RenderTexture.ReleaseTemporary(inputTexture); RenderTexture.ReleaseTemporary(localOutputTexture); RenderTexture.ReleaseTemporary(globalOutputTexture); inputTexture = null; localOutputTexture = null; globalOutputTexture = null; operation.CloseOperation(); }
public void RemoveForeignGameObjects(List <SpawnerSettings> biomeSpawnerSettings, List <string> validTerrainNames = null) { ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign GameObjects", "Removing..."); List <ResourceProtoGameObjectInstance> knownProtoInstances = new List <ResourceProtoGameObjectInstance>(); List <ResourceProtoGameObjectInstance> GoProtoInstancesToRemove = new List <ResourceProtoGameObjectInstance>(); Terrain currentTerrain = GetCurrentTerrain(); foreach (SpawnerSettings spawnerSettings in biomeSpawnerSettings) { foreach (SpawnRule sr in spawnerSettings.m_spawnerRules) { if (sr.m_resourceType == GaiaConstants.SpawnerResourceType.GameObject) { foreach (ResourceProtoGameObjectInstance instance in spawnerSettings.m_resources.m_gameObjectPrototypes[sr.m_resourceIdx].m_instances) { knownProtoInstances.Add(instance); } } } } GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(currentTerrain, transform, m_settings.m_range * 2f, false, validTerrainNames); operation.GetHeightmap(); operation.GetNormalmap(); operation.CollectTerrainDetails(); operation.CollectTerrainTrees(); operation.CollectTerrainGameObjects(); operation.CollectTerrainBakedMasks(); int protoIndex = 0; var allSpawners = Resources.FindObjectsOfTypeAll <Spawner>(); foreach (Spawner spawner in allSpawners) { //During the removal we have to put the spawn settings in remove mode SpawnMode originalMode = spawner.m_settings.m_spawnMode; spawner.m_settings.m_spawnMode = SpawnMode.Remove; ProgressBar.Show(ProgressBarPriority.BiomeRemoval, "Removing Foreign GameObjects", "Removing Game Objects...", protoIndex, allSpawners.Length); foreach (SpawnRule sr in spawner.m_settings.m_spawnerRules) { if (sr.m_resourceType == GaiaConstants.SpawnerResourceType.GameObject) { ResourceProtoGameObject protoGO = spawner.m_settings.m_resources.m_gameObjectPrototypes[sr.m_resourceIdx]; foreach (ResourceProtoGameObjectInstance instance in protoGO.m_instances) { if (!knownProtoInstances.Contains(instance)) { operation.SetTerrainGameObjects(ApplyBrush(operation, MultiTerrainOperationType.GameObject), protoGO, sr, spawner.m_settings, 0, ref sr.m_spawnedInstances, m_settings.m_removeForeignGameObjectStrength, false); //no need to look at other instances if this one triggered the removal already break; } } } } spawner.m_settings.m_spawnMode = originalMode; protoIndex++; } operation.CloseOperation(); #if UNITY_EDITOR //need to dirty the scene when we remove game objects EditorSceneManager.MarkSceneDirty(gameObject.scene); #endif ProgressBar.Clear(ProgressBarPriority.BiomeRemoval); }
public void DrawBiomePreview() { if (m_drawPreview) { //Set up a multi-terrain operation once, all rules can then draw from the data collected here Terrain currentTerrain = GetCurrentTerrain(); if (currentTerrain == null) { return; } GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(currentTerrain, transform, m_settings.m_range * 2f); operation.GetHeightmap(); //only re-generate all textures etc. if settings have changed and the preview is dirty, otherwise we can just use the cached textures if (m_biomePreviewDirty == true) { //Get additional op data (required for certain image masks) operation.GetNormalmap(); operation.CollectTerrainBakedMasks(); //Clear texture cache first if (m_cachedPreviewRT != null) { m_cachedPreviewRT.Release(); DestroyImmediate(m_cachedPreviewRT); } m_cachedPreviewRT = new RenderTexture(operation.RTheightmap); RenderTexture currentRT = RenderTexture.active; RenderTexture.active = m_cachedPreviewRT; GL.Clear(true, true, Color.black); RenderTexture.active = currentRT; Graphics.Blit(ApplyBrush(operation), m_cachedPreviewRT); RenderTexture.active = currentRT; //Everything processed, preview not dirty anymore m_biomePreviewDirty = false; } //Now draw the preview according to the cached textures Material material = GaiaMultiTerrainOperation.GetDefaultGaiaSpawnerPreviewMaterial(); material.SetInt("_zTestMode", (int)UnityEngine.Rendering.CompareFunction.Always); //assign the first color texture in the material material.SetTexture("_colorTexture0", m_cachedPreviewRT); //remove all other potential color textures, there can be caching issues if other visualisers were used in the meantime for (int colorIndex = 1; colorIndex < GaiaConstants.maxPreviewedTextures; colorIndex++) { material.SetTexture("_colorTexture" + colorIndex, null); } //set the color material.SetColor("_previewColor0", m_settings.m_visualisationColor); Color seaLevelColor = GaiaSettings.m_stamperSeaLevelTintColor; if (!m_showSeaLevelinPreview) { seaLevelColor.a = 0f; } material.SetColor("_seaLevelTintColor", seaLevelColor); material.SetFloat("_seaLevel", SessionManager.m_session.m_seaLevel); operation.Visualize(MultiTerrainOperationType.Heightmap, operation.RTheightmap, material, 1); //Clean up operation.CloseOperation(); //Clean up temp textures GaiaUtils.ReleaseAllTempRenderTextures(); } }
public RenderTexture BakeTerrainWorldBiomeMask(Terrain terrain, string worldBiomeMaskGUID) { if (m_gaiaSessionManager == null) { m_gaiaSessionManager = GaiaSessionManager.GetSessionManager(false); } if (m_worldMapTerrain == null) { m_worldMapTerrain = TerrainHelper.GetWorldMapTerrain(); } if (m_worldMapTerrain == null) { Debug.LogWarning("Found no world map terrain for baking a world biome mask."); return(null); } if (String.IsNullOrEmpty(worldBiomeMaskGUID)) { return(null); } if (m_gaiaSessionManager.m_session == null) { Debug.LogWarning("Found no session for baking a world biome mask."); return(null); } if (m_gaiaSessionManager.m_session.m_worldBiomeMaskSettings == null) { Debug.LogWarning("Found no world designer settings in the session for baking a world biome mask."); return(null); } //we need to apply the mask stack for this biome mask on the world map to get the result, then copy the appropiate rectangle for the queried terrain into the cache & return it. bool worldMapActiveState = m_worldMapTerrain.gameObject.activeInHierarchy; m_worldMapTerrain.gameObject.SetActive(true); GameObject emptyGO = new GameObject(); emptyGO.transform.position = new Vector3(m_worldMapTerrain.transform.position.x + m_worldMapTerrain.terrainData.size.x / 2f, m_worldMapTerrain.transform.position.y, m_worldMapTerrain.transform.position.z + +m_worldMapTerrain.terrainData.size.z / 2f); GaiaMultiTerrainOperation operation = new GaiaMultiTerrainOperation(m_worldMapTerrain, emptyGO.transform, m_worldMapTerrain.terrainData.size.x); operation.m_isWorldMapOperation = true; operation.GetHeightmap(); operation.GetNormalmap(); operation.CollectTerrainBakedMasks(); RenderTextureDescriptor rtDescriptor = operation.RTbakedMask.descriptor; RenderTexture inputTexture = RenderTexture.GetTemporary(rtDescriptor); RenderTexture currentRT = RenderTexture.active; RenderTexture.active = inputTexture; GL.Clear(true, true, Color.white); RenderTexture.active = currentRT; RenderTexture ruleOutputTexture = RenderTexture.GetTemporary(rtDescriptor); ImageMask[] maskStack = m_gaiaSessionManager.m_session.m_worldBiomeMaskSettings.m_spawnerRules.Find(x => x.GUID == worldBiomeMaskGUID).m_imageMasks; //Calculate Target position &/ resolution BoundsDouble bounds = new BoundsDouble(); TerrainHelper.GetTerrainBounds(ref bounds); bounds.center -= TerrainLoaderManager.Instance.GetOrigin(); RenderTexture chunkContent = new RenderTexture(terrain.terrainData.heightmapTexture.descriptor); int maxTilesX = Mathf.RoundToInt((float)bounds.size.x / terrain.terrainData.size.x); int maxTilesZ = Mathf.RoundToInt((float)bounds.size.z / terrain.terrainData.size.z); int currentTileX = Mathf.RoundToInt((terrain.transform.position.x - (float)bounds.min.x) / terrain.terrainData.size.x); int currentTileZ = Mathf.RoundToInt((terrain.transform.position.z - (float)bounds.min.z) / terrain.terrainData.size.z); float res = (terrain.terrainData.heightmapResolution) / ((float)bounds.size.x / terrain.terrainData.bounds.size.x * (terrain.terrainData.heightmapResolution - 1)); Bounds worldSpaceBounds = terrain.terrainData.bounds; worldSpaceBounds.center = new Vector3(worldSpaceBounds.center.x + terrain.transform.position.x, worldSpaceBounds.center.y + terrain.transform.position.y, worldSpaceBounds.center.z + terrain.transform.position.z); float xPos = ((float)currentTileX * terrain.terrainData.heightmapResolution) / (maxTilesX * terrain.terrainData.heightmapResolution); float zPos = ((float)currentTileZ * terrain.terrainData.heightmapResolution) / (maxTilesZ * terrain.terrainData.heightmapResolution); Vector2 pos = new Vector2(xPos, zPos); //If we have a mask stack, we need to process it if (maskStack != null && maskStack.Length > 0) { //We start from a white texture, so we need the first mask action in the stack to always be "Multiply", otherwise there will be no result. maskStack[0].m_blendMode = ImageMaskBlendMode.Multiply; float maxWorldHeight = 0f; float minWorldHeight = 0f; m_gaiaSessionManager.GetWorldMinMax(ref minWorldHeight, ref maxWorldHeight, true); //Iterate through all image masks and set up the current paint context in case the shader uses heightmap data foreach (ImageMask mask in maskStack) { mask.m_multiTerrainOperation = operation; mask.m_seaLevel = m_gaiaSessionManager.GetSeaLevel(true); mask.m_maxWorldHeight = maxWorldHeight; mask.m_minWorldHeight = minWorldHeight; } Graphics.Blit(ImageProcessing.ApplyMaskStack(inputTexture, ruleOutputTexture, maskStack, ImageMaskInfluence.Local), ruleOutputTexture); } else { //no mask stack -> just blit the white input texture over as the output Graphics.Blit(inputTexture, ruleOutputTexture); } operation.CloseOperation(); DestroyImmediate(emptyGO); RenderTexture.ReleaseTemporary(inputTexture); m_worldMapTerrain.gameObject.SetActive(worldMapActiveState); //copy the rule output into the right size for the requested terrain chunk Graphics.Blit(ruleOutputTexture, chunkContent, new Vector2(res, res), pos); string filename = GetWorldBiomeMaskFilename(terrain, worldBiomeMaskGUID); SaveBakedMaskInCache(chunkContent, terrain, filename); RenderTexture.ReleaseTemporary(ruleOutputTexture); return(chunkContent); }