/// <summary> /// Creates splatmaps which are (by default) applied to terrain splat shaders. /// </summary> /// <param name="applySplats">When true, the generated splat is automatically applied to the terrain. /// Otherwise, it can be applied by calling ApplySplatmapsToShader</param> /// <param name="debug">When true, the generated alpha maps are saved to the disk. /// They're located at [Your project's root dir]/SplatImages/</param> /// <returns>Created alphamap textures</returns> public List <Texture2D> GenerateSplatmaps(bool applySplats = true) { //Ensure correct shader is set SetFirstPassShader(true); //Set amount of required maps List <Texture2D> maps = new List <Texture2D>(); for (int i = 0; i < Mathf.CeilToInt(SplatSettings.Count / 4f); i++) { maps.Add(new Texture2D(AlphaMapResolution, AlphaMapResolution)); } //Sample weights and fill in textures for (int x = 0; x < AlphaMapResolution; x++) { for (int y = 0; y < AlphaMapResolution; y++) { MeshSampler.MeshSample sample = Sampler.SampleAt(y / (float)AlphaMapResolution, x / (float)AlphaMapResolution); AddWeightsToTextures(CalculateWeights(sample), ref maps, y, x); } } if (TerraDebug.WRITE_SPLAT_TEXTURES) { TerrainTile tile = TerrainObject.GetComponent <TerrainTile>(); string tileName = tile != null ? "Tile[" + tile.Position.x + "_" + tile.Position.y + "]" : "Tile[0_0]"; string folderPath = Application.dataPath + "/SplatImages/"; if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } for (var i = 0; i < maps.Count; i++) { byte[] bytes = maps[i].EncodeToPNG(); string name = "Splat" + i + "_" + tileName + ".png"; File.WriteAllBytes(folderPath + name, bytes); } } //Apply set pixel values to textures maps.ForEach(t => t.Apply()); if (applySplats) { ApplySplatmapsToShaders(maps); } return(maps); }
/// <summary> /// First creates a poisson grid based on the passed density. /// Positions are then filtered based on the passed object placement /// type taking into account height and angle constraints. /// /// Unlike the <c>GetFilteredGrid(ObjectPlacementType, float)</c> method /// this method samples from the passed Mesh rather than pulling /// mesh information from TerraSettings. /// </summary> /// <param name="m">Mesh to sample height and angle values from</param> /// <param name="type">object placement type to sample</param> /// <returns>List of vectors within the grid and sample constraints</returns> public List <Vector3> GetFilteredGrid(Mesh m, ObjectPlacementType type) { MeshSampler sampler = new MeshSampler(m, Settings.MeshResolution); List <Vector2> grid = GetPoissonGrid(type.Spread / 10); List <Vector3> toAdd = new List <Vector3>(); foreach (Vector2 pos in grid) { MeshSampler.MeshSample sample = sampler.SampleAt(pos.x, pos.y); if (type.ShouldPlaceAt(sample.Height, sample.Angle)) { Vector3 newPos = new Vector3(pos.x, sample.Height, pos.y); toAdd.Add(newPos); } } return(toAdd); }
/// <summary> /// First creates a poisson grid based on the passed density. /// Positions are then filtered based on the passed object placement /// type taking into account height and angle constraints. /// /// Unlike the <c>GetFilteredGrid(ObjectPlacementType, float)</c> method /// this method samples from the passed Mesh rather than pulling /// mesh information from TerraSettings. /// </summary> /// <param name="m">Mesh to sample height and angle values from</param> /// <param name="objectPlacementData">object placement type to sample</param> /// <returns>List of vectors within the grid and sample constraints</returns> public List <Vector3> GetFilteredGrid(Mesh m, ObjectPlacementData objectPlacementData) { MeshSampler sampler = /**new MeshSampler(m, Settings.Generator.MeshResolution);*/ new MeshSampler(m, 128); //TODO Resolution from TerraSettings List <Vector2> grid = GetPoissonGrid(objectPlacementData.Spread / 10); List <Vector3> toAdd = new List <Vector3>(); foreach (Vector2 pos in grid) { MeshSampler.MeshSample sample = sampler.SampleAt(pos.x, pos.y); if (objectPlacementData.ShouldPlaceAt(sample.Height, sample.Angle)) { Vector3 newPos = new Vector3(pos.x, sample.Height, pos.y); toAdd.Add(newPos); } } return(toAdd); }