summaryrefslogtreecommitdiff
path: root/Plugins/MonoGame.Extended/source/MonoGame.Extended.Tiled/Renderers/TiledMapLayerModelBuilder.cs
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2024-06-03 10:15:45 +0800
committerchai <215380520@qq.com>2024-06-03 10:15:45 +0800
commitacea7b2e728787a0d83bbf83c8c1f042d2c32e7e (patch)
tree0bfec05c1ca2d71be2c337bcd110a0421f19318b /Plugins/MonoGame.Extended/source/MonoGame.Extended.Tiled/Renderers/TiledMapLayerModelBuilder.cs
parent88febcb02bf127d961c6471d9e846c0e1315f5c3 (diff)
+ plugins project
Diffstat (limited to 'Plugins/MonoGame.Extended/source/MonoGame.Extended.Tiled/Renderers/TiledMapLayerModelBuilder.cs')
-rw-r--r--Plugins/MonoGame.Extended/source/MonoGame.Extended.Tiled/Renderers/TiledMapLayerModelBuilder.cs125
1 files changed, 125 insertions, 0 deletions
diff --git a/Plugins/MonoGame.Extended/source/MonoGame.Extended.Tiled/Renderers/TiledMapLayerModelBuilder.cs b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Tiled/Renderers/TiledMapLayerModelBuilder.cs
new file mode 100644
index 0000000..fbc99d6
--- /dev/null
+++ b/Plugins/MonoGame.Extended/source/MonoGame.Extended.Tiled/Renderers/TiledMapLayerModelBuilder.cs
@@ -0,0 +1,125 @@
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace MonoGame.Extended.Tiled.Renderers
+{
+ public abstract class TiledMapLayerModelBuilder<T>
+ {
+ protected TiledMapLayerModelBuilder()
+ {
+ Indices = new List<ushort>();
+ Vertices = new List<VertexPositionTexture>();
+ }
+
+ public List<ushort> Indices { get; }
+ public List<VertexPositionTexture> Vertices { get; }
+ public bool IsFull => Vertices.Count + TiledMapHelper.VerticesPerTile >= TiledMapHelper.MaximumVerticesPerModel;
+ public bool IsBuildable => Vertices.Any();
+
+ protected abstract void ClearBuffers();
+ protected abstract T CreateModel(GraphicsDevice graphicsDevice, Texture2D texture);
+
+ public T Build(GraphicsDevice graphicsDevice, Texture2D texture)
+ {
+ var model = CreateModel(graphicsDevice, texture);
+ Vertices.Clear();
+ Indices.Clear();
+ ClearBuffers();
+ return model;
+ }
+
+ public void AddSprite(Texture2D texture, Point2 position, Rectangle sourceRectangle, TiledMapTileFlipFlags flipFlags)
+ {
+ Indices.AddRange(CreateTileIndices(Vertices.Count));
+ Debug.Assert(Indices.Count <= TiledMapHelper.MaximumIndicesPerModel);
+
+ Vertices.AddRange(CreateVertices(texture, position, sourceRectangle, flipFlags));
+ Debug.Assert(Vertices.Count <= TiledMapHelper.MaximumVerticesPerModel);
+ }
+
+ private static IEnumerable<VertexPositionTexture> CreateVertices(Texture2D texture, Vector2 position, Rectangle sourceRectangle, TiledMapTileFlipFlags flags = TiledMapTileFlipFlags.None)
+ {
+ var reciprocalWidth = 1f / texture.Width;
+ var reciprocalHeight = 1f / texture.Height;
+ var texelLeft = sourceRectangle.X * reciprocalWidth;
+ var texelTop = sourceRectangle.Y * reciprocalHeight;
+ var texelRight = (sourceRectangle.X + sourceRectangle.Width) * reciprocalWidth;
+ var texelBottom = (sourceRectangle.Y + sourceRectangle.Height) * reciprocalHeight;
+
+ VertexPositionTexture vertexTopLeft, vertexTopRight, vertexBottomLeft, vertexBottomRight;
+
+ vertexTopLeft.Position = new Vector3(position, 0);
+ vertexTopRight.Position = new Vector3(position + new Vector2(sourceRectangle.Width, 0), 0);
+ vertexBottomLeft.Position = new Vector3(position + new Vector2(0, sourceRectangle.Height), 0);
+ vertexBottomRight.Position = new Vector3(position + new Vector2(sourceRectangle.Width, sourceRectangle.Height), 0);
+
+ vertexTopLeft.TextureCoordinate.Y = texelTop;
+ vertexTopLeft.TextureCoordinate.X = texelLeft;
+
+ vertexTopRight.TextureCoordinate.Y = texelTop;
+ vertexTopRight.TextureCoordinate.X = texelRight;
+
+ vertexBottomLeft.TextureCoordinate.Y = texelBottom;
+ vertexBottomLeft.TextureCoordinate.X = texelLeft;
+
+ vertexBottomRight.TextureCoordinate.Y = texelBottom;
+ vertexBottomRight.TextureCoordinate.X = texelRight;
+
+ var flipDiagonally = (flags & TiledMapTileFlipFlags.FlipDiagonally) != 0;
+ var flipHorizontally = (flags & TiledMapTileFlipFlags.FlipHorizontally) != 0;
+ var flipVertically = (flags & TiledMapTileFlipFlags.FlipVertically) != 0;
+
+ if (flipDiagonally)
+ {
+ FloatHelper.Swap(ref vertexTopRight.TextureCoordinate.X, ref vertexBottomLeft.TextureCoordinate.X);
+ FloatHelper.Swap(ref vertexTopRight.TextureCoordinate.Y, ref vertexBottomLeft.TextureCoordinate.Y);
+ }
+
+ if (flipHorizontally)
+ {
+ if (flipDiagonally)
+ {
+ FloatHelper.Swap(ref vertexTopLeft.TextureCoordinate.Y, ref vertexTopRight.TextureCoordinate.Y);
+ FloatHelper.Swap(ref vertexBottomLeft.TextureCoordinate.Y, ref vertexBottomRight.TextureCoordinate.Y);
+ }
+ else
+ {
+ FloatHelper.Swap(ref vertexTopLeft.TextureCoordinate.X, ref vertexTopRight.TextureCoordinate.X);
+ FloatHelper.Swap(ref vertexBottomLeft.TextureCoordinate.X, ref vertexBottomRight.TextureCoordinate.X);
+ }
+ }
+
+ if (flipVertically)
+ {
+ if (flipDiagonally)
+ {
+ FloatHelper.Swap(ref vertexTopLeft.TextureCoordinate.X, ref vertexBottomLeft.TextureCoordinate.X);
+ FloatHelper.Swap(ref vertexTopRight.TextureCoordinate.X, ref vertexBottomRight.TextureCoordinate.X);
+ }
+ else
+ {
+ FloatHelper.Swap(ref vertexTopLeft.TextureCoordinate.Y, ref vertexBottomLeft.TextureCoordinate.Y);
+ FloatHelper.Swap(ref vertexTopRight.TextureCoordinate.Y, ref vertexBottomRight.TextureCoordinate.Y);
+ }
+ }
+
+ yield return vertexTopLeft;
+ yield return vertexTopRight;
+ yield return vertexBottomLeft;
+ yield return vertexBottomRight;
+ }
+
+ private static IEnumerable<ushort> CreateTileIndices(int indexOffset)
+ {
+ yield return (ushort)(0 + indexOffset);
+ yield return (ushort)(1 + indexOffset);
+ yield return (ushort)(2 + indexOffset);
+ yield return (ushort)(1 + indexOffset);
+ yield return (ushort)(3 + indexOffset);
+ yield return (ushort)(2 + indexOffset);
+ }
+ }
+}