using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace Kav { public class MeshSprite : IIndexDrawable { public enum FlipOptions { None, Horizontal, Vertical, Both } private static readonly int PixelScale = 40; private static readonly short[] Indices = new short[] { 0, 1, 2, 1, 3, 2 }; public Texture2D Texture { get; } public Texture2D Normal { get; } public IndexBuffer IndexBuffer { get; } public VertexBuffer VertexBuffer { get; } public BoundingBox BoundingBox { get; } public MeshSprite( GraphicsDevice graphicsDevice, Texture2D texture, FlipOptions flipOptions ) { Texture = texture; Normal = null; IndexBuffer = new IndexBuffer( graphicsDevice, IndexElementSize.SixteenBits, 6, BufferUsage.WriteOnly ); IndexBuffer.SetData(Indices); var vertexArray = GenerateVertexArray(Texture, flipOptions); VertexBuffer = new VertexBuffer( graphicsDevice, typeof(VertexPositionNormalTexture), 4, BufferUsage.WriteOnly ); VertexBuffer.SetData(vertexArray); BoundingBox = BoundingBox.CreateFromPoints(Positions(vertexArray)); } public MeshSprite( GraphicsDevice graphicsDevice, Texture2D texture, Texture2D normal, FlipOptions flipOptions ) { Texture = texture; Normal = normal; IndexBuffer = new IndexBuffer( graphicsDevice, IndexElementSize.SixteenBits, 6, BufferUsage.WriteOnly ); IndexBuffer.SetData(Indices); var vertexArray = GenerateVertexArray(Texture, flipOptions); VertexBuffer = new VertexBuffer( graphicsDevice, typeof(VertexPositionNormalTexture), 4, BufferUsage.WriteOnly ); VertexBuffer.SetData(vertexArray); BoundingBox = BoundingBox.CreateFromPoints(Positions(vertexArray)); } private static VertexPositionNormalTexture[] GenerateVertexArray(Texture2D texture, FlipOptions flipOptions) { VertexPositionNormalTexture[] result = new VertexPositionNormalTexture[4]; var xLeft = 0; var xRight = 1; var yTop = 0; var yBottom = 1; if (flipOptions == FlipOptions.Horizontal || flipOptions == FlipOptions.Both) { xLeft = 1; xRight = 0; } if (flipOptions == FlipOptions.Vertical || flipOptions == FlipOptions.Both) { yTop = 1; yBottom = 0; } result[0].Position = new Vector3(-texture.Width / 2, texture.Height / 2, 0) / PixelScale; result[0].Normal = new Vector3(0, 0, 1); result[0].TextureCoordinate = new Vector2(xLeft, yTop); result[1].Position = new Vector3(texture.Width / 2, texture.Height / 2, 0) / PixelScale; result[1].Normal = new Vector3(0, 0, 1); result[1].TextureCoordinate = new Vector2(xRight, yTop); result[2].Position = new Vector3(-texture.Width / 2, -texture.Height / 2, 0) / PixelScale; result[2].Normal = new Vector3(0, 0, 1); result[2].TextureCoordinate = new Vector2(xLeft, yBottom); result[3].Position = new Vector3(texture.Width / 2, -texture.Height / 2, 0) / PixelScale; result[3].Normal = new Vector3(0, 0, 1); result[3].TextureCoordinate = new Vector2(xRight, yBottom); return result; } private static IEnumerable Positions(IEnumerable vertices) { foreach (var vertex in vertices) { yield return vertex.Position; } } } }