Jypeli  5
The simple game programming library
ImageBatch.cs
Siirry tämän tiedoston dokumentaatioon.
1 using System;
2 using System.Diagnostics;
3 using System.Collections.Generic;
4 using Microsoft.Xna.Framework;
5 using Microsoft.Xna.Framework.Graphics;
6 using Jypeli.Effects;
7 
8 namespace Jypeli
9 {
10  internal class TextureCoordinates
11  {
12  public Vector2 TopLeft;
13  public Vector2 TopRight;
14  public Vector2 BottomLeft;
15  public Vector2 BottomRight;
16  }
17 
28  internal class ImageBatch
29  {
30  private const int DefaultBufferSize = 512;
31 
32  static readonly Vector3[] Vertices = new Vector3[]
33  {
34  // Triangle 1
35  new Vector3(-0.5f, 0.5f, 0),
36  new Vector3(-0.5f, -0.5f, 0),
37  new Vector3(0.5f, 0.5f, 0),
38 
39  // Triangle 2
40  new Vector3(-0.5f, -0.5f, 0),
41  new Vector3(0.5f, -0.5f, 0),
42  new Vector3(0.5f, 0.5f, 0),
43  };
44 
45  static readonly int VerticesPerTexture = Vertices.Length;
46 
47  Matrix matrix;
48  Texture2D texture;
49  Effect effect;
50  VertexPositionTexture[] vertexBuffer;
51  int BufferSize;
52  int iTexture = 0;
53  bool beginHasBeenCalled = false;
54 
55  public bool LightingEnabled = true;
56 
57 
58  public ImageBatch()
59  {
60  }
61 
62  public void Initialize()
63  {
64  //var capabilities = Game.GraphicsDevice.GraphicsDeviceCapabilities;
65  // Capabilities no longer supported in XNA 4.0
66  // GraphicsProfile.Reach maximum primitive count = 65535
67  this.BufferSize = Math.Min( DefaultBufferSize, 65535 / 2 );
68  vertexBuffer = new VertexPositionTexture[BufferSize * VerticesPerTexture];
69  }
70 
71  public void Begin( ref Matrix matrix, Texture2D texture )
72  {
73  Debug.Assert( !beginHasBeenCalled );
74  beginHasBeenCalled = true;
75 
76  this.matrix = matrix;
77  this.texture = texture;
78  iTexture = 0;
79  }
80 
81  public void End()
82  {
83  Debug.Assert( beginHasBeenCalled );
84 
85  Flush();
86 
87  int textureCount = iTexture;
88  beginHasBeenCalled = false;
89  }
90 
91  private void Flush()
92  {
93  if ( iTexture > 0 )
94  {
95  var device = Game.GraphicsDevice;
96  device.RasterizerState = RasterizerState.CullClockwise;
97  device.BlendState = BlendState.AlphaBlend;
98 
99  effect = Graphics.GetTextureEffect(ref matrix, texture, LightingEnabled);
100  effect.CurrentTechnique.Passes[0].Apply();
101 
102  // When drawing individual textures, set the texture addressing modes
103  // to clamp in order to avoid unwanted edges.
104  // EDIT (Denis Zhidkikh): changeable clamp state
105  device.SamplerStates[0] = Graphics.GetDefaultSamplerState();
106 
107  device.DrawUserPrimitives<VertexPositionTexture>(
108  PrimitiveType.TriangleList,
109  vertexBuffer, 0,
110  iTexture * 2 );
111  }
112 
113  iTexture = 0;
114  }
115 
116  public void Draw( TextureCoordinates c, Vector2 position, Vector2 size, float angle )
117  {
118  Debug.Assert( beginHasBeenCalled );
119 
120  if ( iTexture >= BufferSize )
121  Flush();
122 
123  Matrix matrix =
124  Matrix.CreateScale( size.X, size.Y, 1f )
125  * Matrix.CreateRotationZ( angle )
126  * Matrix.CreateTranslation( position.X, position.Y, 0 )
127  ;
128  Vector3[] transformedPoints = new Vector3[VerticesPerTexture];
129  Vector3.Transform( Vertices, ref matrix, transformedPoints );
130 
131  int startIndex = ( iTexture * VerticesPerTexture );
132 
133  for ( int i = 0; i < VerticesPerTexture; i++ )
134  {
135  int bi = ( iTexture * VerticesPerTexture ) + i;
136  vertexBuffer[bi].Position = transformedPoints[i];
137  }
138 
139  // Triangle 1
140  vertexBuffer[startIndex + 0].TextureCoordinate = c.TopLeft;
141  vertexBuffer[startIndex + 1].TextureCoordinate = c.BottomLeft;
142  vertexBuffer[startIndex + 2].TextureCoordinate = c.TopRight;
143 
144  // Triangle 2
145  vertexBuffer[startIndex + 3].TextureCoordinate = c.BottomLeft;
146  vertexBuffer[startIndex + 4].TextureCoordinate = c.BottomRight;
147  vertexBuffer[startIndex + 5].TextureCoordinate = c.TopRight;
148 
149  iTexture++;
150  }
151  }
152 }