public virtual TileMeshDraw Build(TileGridBlock block, ITileDefinitionSource tileDefinitionSource, GraphicsContext graphicsContext, ref Vector2 cellSize) { TileMeshDraw tileMeshDraw = null; AggregateTiles(block, tileDefinitionSource, graphicsContext, ref cellSize); CompleteBuild(graphicsContext, block.BlockSize * block.BlockSize, ref tileMeshDraw); return(tileMeshDraw); }
public void Draw(TileMeshDraw tileMeshDraw) { CheckBeginHasBeenCalled(); GraphicsContext.CommandList.SetVertexBuffer(0, tileMeshDraw.VertexBuffer.Buffer, tileMeshDraw.VertexBuffer.Offset, tileMeshDraw.VertexBuffer.Stride); GraphicsContext.CommandList.SetIndexBuffer(tileMeshDraw.IndexBuffer.Buffer, 0, tileMeshDraw.IndexBuffer.Is32Bit); foreach (var range in tileMeshDraw.Ranges) { if (textureUpdater.HasValue) { Parameters.Set(textureUpdater.Value, range.Texture); } Effect.Apply(GraphicsContext); GraphicsContext.CommandList.DrawIndexed(range.IndexCount, range.StartIndex); } }
private static TileMeshDraw New <TVertex, TIndex>(GraphicsDevice graphicsDevice, VertexDeclaration layout, TVertex[] vertexBuffer, TIndex[] indexBuffer, IEnumerable <DrawRange> ranges) where TVertex : struct, IVertex where TIndex : struct { if (graphicsDevice == null) { throw new ArgumentNullException(nameof(graphicsDevice)); } if (layout == null) { throw new ArgumentNullException(nameof(layout)); } if (vertexBuffer == null) { throw new ArgumentNullException(nameof(vertexBuffer)); } if (indexBuffer == null) { throw new ArgumentNullException(nameof(indexBuffer)); } if (ranges == null) { throw new ArgumentNullException(nameof(ranges)); } var batch = new TileMeshDraw() { VertexBuffer = new VertexBufferBinding(Buffer.Vertex.New <TVertex>(graphicsDevice, vertexBuffer, GraphicsResourceUsage.Default), layout, vertexBuffer.Length), IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indexBuffer, GraphicsResourceUsage.Default), Utilities.SizeOf <TIndex>() == sizeof(Int32), indexBuffer.Length), Ranges = new List <DrawRange>(ranges), }; return(batch); }
public void GetTileMeshDraws(IList <TileGridBlock> blocks, GraphicsContext graphicsContext, ref Vector2 cellSize, IList <TileMeshDraw> tileMeshDrawsOut) { if (blocks == null) { throw new ArgumentNullException(nameof(blocks)); } if (graphicsContext == null) { throw new ArgumentNullException(nameof(graphicsContext)); } if (tileMeshDrawsOut == null) { throw new ArgumentNullException(nameof(tileMeshDrawsOut)); } if (tileMeshDrawBuilder == null) { return; } for (int i = 0; i < blocks.Count; i++) { var currentBlock = blocks[i]; TileMeshDraw tileMeshDraw = null; if (previousTileMeshDraws.TryGetValue(currentBlock.Location, out tileMeshDraw)) { if (currentBlock.VisualyInvalidated) { pendingBlocks.Add(currentBlock); tileMeshDrawsForRecycle.Add(tileMeshDraw); } else { tileMeshDraws[currentBlock.Location] = tileMeshDraw; tileMeshDrawsOut.Add(tileMeshDraw); } previousTileMeshDraws.Remove(currentBlock.Location); } else { pendingBlocks.Add(currentBlock); } } if (pendingBlocks.Count > 0) { for (int i = 0; i < pendingBlocks.Count; i++) { var currentBlock = pendingBlocks[i]; TileMeshDraw tileMeshDraw = null; if (tileMeshDrawsForRecycle.Count > 0) { var lastIndex = tileMeshDrawsForRecycle.Count - 1; tileMeshDraw = tileMeshDrawsForRecycle[lastIndex]; tileMeshDrawsForRecycle.RemoveAt(lastIndex); tileMeshDrawBuilder.Recycle(tileMeshDraw, currentBlock, tileDefinitionSource, graphicsContext, ref cellSize); } else { tileMeshDraw = tileMeshDrawBuilder.Build(currentBlock, tileDefinitionSource, graphicsContext, ref cellSize); } tileMeshDraws[currentBlock.Location] = tileMeshDraw; currentBlock.VisualyInvalidated = false; tileMeshDrawsOut.Add(tileMeshDraw); } } tileMeshDrawsForRecycle.AddRange(previousTileMeshDraws.Values); previousTileMeshDraws.Clear(); pendingBlocks.Clear(); Utilities.Swap(ref tileMeshDraws, ref previousTileMeshDraws); //Reduce cache. while (tileMeshDrawsForRecycle.Count > 4) //Should be configurable. Yes it should. { var lastIndex = tileMeshDrawsForRecycle.Count - 1; tileMeshDrawsForRecycle[lastIndex].Dispose(); tileMeshDrawsForRecycle.RemoveAt(lastIndex); } }
public virtual void Recycle(TileMeshDraw tileMeshDraw, TileGridBlock block, ITileDefinitionSource tileDefinitionSource, GraphicsContext graphicsContext, ref Vector2 cellSize) { AggregateTiles(block, tileDefinitionSource, graphicsContext, ref cellSize); CompleteBuild(graphicsContext, block.BlockSize * block.BlockSize, ref tileMeshDraw); }
protected virtual void CompleteBuild(GraphicsContext graphicsContext, int maxTileCount, ref TileMeshDraw tileMeshDraw) { var indexBufferLength = maxTileCount * IndiciesPerTile; bool updateIndexBuffer = false; if (indexBuffer == null || indexBuffer.Length != indexBufferLength) { indexBuffer = new short[indexBufferLength]; BuildIndicies(indexBuffer, maxTileCount); updateIndexBuffer = true; } var vertexBufferLength = maxTileCount * VerticiesPerTile; if (vertexBuffer == null || vertexBuffer.Length != vertexBufferLength) { vertexBuffer = new TVertex[vertexBufferLength]; } tileMeshDraw?.Ranges.Clear(); var ranges = tileMeshDraw?.Ranges ?? new List <TileMeshDraw.DrawRange>(); int tileCount = 0; int vertexIndex = 0; foreach (var tileGroup in tilesByTexture) { var textureWidth = tileGroup.Key.Width; var textureHeight = tileGroup.Key.Height; foreach (var tile in tileGroup.Value) { var source = tile.Item1; var dest = tile.Item2; BuildTile(vertexBuffer, ref vertexIndex, textureWidth, textureHeight, source, dest); } ranges.Add(new TileMeshDraw.DrawRange { Texture = tileGroup.Key, StartIndex = tileCount * IndiciesPerTile, IndexCount = tileGroup.Value.Count * IndiciesPerTile }); tileCount += tileGroup.Value.Count; } if (tileMeshDraw == null) { tileMeshDraw = TileMeshDraw.New <TVertex>(graphicsContext.CommandList.GraphicsDevice, layout, vertexBuffer, indexBuffer, ranges); } else { tileMeshDraw.VertexBuffer = UpdateVertexBuffer(graphicsContext, tileMeshDraw.VertexBuffer); if (updateIndexBuffer) { tileMeshDraw.IndexBuffer = UpdateIndexBuffer(graphicsContext, tileMeshDraw.IndexBuffer); } } tilesByTexture.Clear(); }