/// <summary> /// Resource disposal /// </summary> protected override void Dispose(bool disposing) { if (disposing) { for (int i = 0; i < this.foliageBuffers.Count; i++) { this.foliageBuffers[i]?.Dispose(); this.foliageBuffers[i] = null; } this.foliageBuffers.Clear(); foreach (var item in this.foliagePatches.Values) { foreach (var value in item) { value?.Dispose(); } } this.foliagePatches.Clear(); this.foliageMap?.Dispose(); this.foliageMap = null; for (int i = 0; i < this.foliageMapChannels.Count; i++) { this.foliageMapChannels[i]?.Dispose(); this.foliageMapChannels[i] = null; } this.foliageMapChannels.Clear(); this.textureRandom?.Dispose(); this.textureRandom = null; } }
/// <summary> /// Constructor /// </summary> /// <param name="game">Game</param> /// <param name="bufferManager">Buffer manager</param> /// <param name="description">Description</param> public GroundGardener(Scene scene, GroundGardenerDescription description) : base(scene, description) { if (description == null) { throw new EngineException("A gardener description should be specified."); } this.textureRandom = this.Game.ResourceManager.CreateResource(Guid.NewGuid(), 1024, -1, 1, 24); this.foliageSphere = new BoundingSphere(Vector3.Zero, description.VisibleRadius); //Material this.material = new MeshMaterial() { Material = description.Material != null?description.Material.GetMaterial() : Material.Default }; //Read foliage textures string contentPath = description.ContentPath; if (!string.IsNullOrEmpty(description.VegetationMap)) { var foliageMapImage = new ImageContent() { Streams = ContentManager.FindContent(contentPath, description.VegetationMap), }; this.foliageMap = FoliageMap.FromStream(foliageMapImage.Stream); } for (int i = 0; i < description.Channels.Length; i++) { var channelDesc = description.Channels[i]; if (channelDesc?.Enabled == true) { var newChannel = CreateChannel(channelDesc, i, contentPath); this.foliageMapChannels.Add(newChannel); } } for (int i = 0; i < MaxFoliageBuffers; i++) { this.foliageBuffers.Add(new FoliageBuffer(this.Game, this.BufferManager, description.Name)); } }
/// <summary> /// Launchs foliage population asynchronous task /// </summary> /// <param name="scene">Scene</param> /// <param name="node">Foliage Node</param> /// <param name="map">Foliage map</param> /// <param name="description">Terrain vegetation description</param> /// <param name="gbbox">Relative bounding box to plant</param> /// <param name="delay">Task delay</param> public void Plant(Scene scene, QuadTreeNode node, FoliageMap map, FoliageMapChannel description, BoundingBox gbbox, int delay) { if (!this.Planting) { //Start planting task this.CurrentNode = node; this.Channel = description.Index; this.Planting = true; Task .Run(async() => { await Task.Delay(delay); return(PlantTask(scene, node, map, description, gbbox)); }) .ContinueWith((t) => { this.Planting = false; this.Planted = true; this.foliageData = t.Result; }); } }
/// <summary> /// Asynchronous planting task /// </summary> /// <param name="scene">Scene</param> /// <param name="node">Node to process</param> /// <param name="map">Foliage map</param> /// <param name="description">Vegetation task</param> /// <param name="gbbox">Relative bounding box to plant</param> /// <returns>Returns generated vertex data</returns> private static IEnumerable <VertexBillboard> PlantTask(Scene scene, QuadTreeNode node, FoliageMap map, FoliageMapChannel description, BoundingBox gbbox) { if (node == null) { return(new VertexBillboard[] { }); } List <VertexBillboard> vertexData = new List <VertexBillboard>(MAX); Vector2 min = new Vector2(gbbox.Minimum.X, gbbox.Minimum.Z); Vector2 max = new Vector2(gbbox.Maximum.X, gbbox.Maximum.Z); Random rnd = new Random(description.Seed); var bbox = node.BoundingBox; int count = (int)Math.Min(MAX, MAX * description.Saturation); int iterations = MAX * 2; //Number of points while (count > 0 && iterations > 0) { iterations--; Vector3 pos = new Vector3( rnd.NextFloat(bbox.Minimum.X, bbox.Maximum.X), bbox.Maximum.Y + 1f, rnd.NextFloat(bbox.Minimum.Z, bbox.Maximum.Z)); bool plant = false; if (map != null) { var c = map.GetRelative(pos, min, max); if (c[description.Index] > 0) { plant = rnd.NextFloat(0, 1) < (c[description.Index]); } } else { plant = true; } if (plant) { var size = new Vector2( rnd.NextFloat(description.MinSize.X, description.MaxSize.X), rnd.NextFloat(description.MinSize.Y, description.MaxSize.Y)); var planted = Plant(scene, pos, size, out var res); if (planted) { vertexData.Add(res); count--; } } else { count--; } } return(vertexData.ToArray()); }