source: 2014/24/EemeliK/Zombieland/Jypeli/Graphics/ShapeBatch.cs @ 5974

Revision 5974, 4.4 KB checked in by empaheik, 4 years ago (diff)
Line 
1
2using System;
3using System.Diagnostics;
4using Microsoft.Xna.Framework;
5using Microsoft.Xna.Framework.Graphics;
6
7namespace Jypeli
8{
9    /// <summary>
10    /// Draws simple shapes efficiently.
11    /// Draw() calls should be made only between Begin() and End() calls.
12    /// Other drawing operations can be done between Begin() and
13    /// End().
14    /// </summary>
15    /// <remarks>
16    /// The shapes are added to a buffer. Only when
17    /// the buffer is full, a draw call is made to the graphics device.
18    /// </remarks>
19    internal class ShapeBatch
20    {
21        const int DefaultBufferSize = 512;
22
23        VertexPositionColor[] vertexBuffer;
24
25        /// <summary>
26        /// Buffer for index values to the vertex buffer.
27        /// </summary>
28        /// <remarks>
29        /// Since some low-end graphics cards don't support 32-bit indices,
30        /// 16-bit indices must be used. Which is fine, as it means less traffic
31        /// to the graphics card. We just have to make sure that the buffer size
32        /// isn't larger than 16000.
33        /// </remarks>
34        Int16[] indexBuffer;
35
36        Effect effect;
37        Matrix matrix;
38
39        static readonly SamplerState samplerState = new SamplerState
40        {
41            AddressU = TextureAddressMode.Clamp,
42            AddressW = TextureAddressMode.Clamp,
43            AddressV = TextureAddressMode.Clamp,
44        };
45
46        int iVertexBuffer = 0;
47        int iIndexBuffer = 0;
48        bool beginHasBeenCalled = false;
49
50        public bool LightingEnabled = true;
51
52
53        public void Initialize()
54        {
55            //var capabilities = Game.GraphicsDevice.GraphicsDeviceCapabilities;
56            // Capabilities no longer supported in XNA 4.0
57            // GraphicsProfile.Reach maximum primitive count = 65535
58            int vertexBufferSize = Math.Min( DefaultBufferSize, 65535 * 3 );
59           
60            vertexBuffer = new VertexPositionColor[vertexBufferSize];
61            indexBuffer = new Int16[vertexBufferSize * 2];
62        }
63
64        public void Begin( ref Matrix matrix )
65        {
66            Debug.Assert( !beginHasBeenCalled );
67            beginHasBeenCalled = true;
68
69            this.matrix = matrix;
70            iVertexBuffer = 0;
71            iIndexBuffer = 0;
72        }
73
74        public void End()
75        {
76            Debug.Assert( beginHasBeenCalled );
77            Flush();
78            beginHasBeenCalled = false;
79        }
80
81        private void Flush()
82        {
83            if ( iIndexBuffer != 0 )
84            {
85                Game.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
86                Game.GraphicsDevice.SamplerStates[0] = samplerState;
87
88                effect = Graphics.GetColorEffect(ref matrix, LightingEnabled);
89                effect.CurrentTechnique.Passes[0].Apply();
90
91                Game.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(
92                    PrimitiveType.TriangleList,
93                    vertexBuffer, 0, iVertexBuffer,
94                    indexBuffer, 0,
95                    iIndexBuffer / 3 );
96            }
97
98            iVertexBuffer = 0;
99            iIndexBuffer = 0;
100        }
101
102        public void Draw( Vector[] vertices, Int16[] indices, Color color, Vector2 position, Vector2 size, float angle )
103        {
104            if ( ( iVertexBuffer + vertices.Length ) > vertexBuffer.Length ||
105                ( iIndexBuffer + indices.Length ) > indexBuffer.Length )
106            {
107                Flush();
108            }
109
110            Matrix matrix =
111                Matrix.CreateScale( size.X, size.Y, 1f )
112                * Matrix.CreateRotationZ( angle )
113                * Matrix.CreateTranslation( position.X, position.Y, 0 )
114                ;
115
116            int startIndex = iVertexBuffer;
117
118            for ( int i = 0; i < vertices.Length; i++ )
119            {
120                Vector p = vertices[i];
121                Vector3 p3 = new Vector3( (float)p.X, (float)p.Y, 0f );
122                vertexBuffer[iVertexBuffer].Position = Vector3.Transform( p3, matrix );
123                vertexBuffer[iVertexBuffer].Color = color.AsXnaColor();
124                iVertexBuffer++;
125            }
126
127            for ( int i = 0; i < indices.Length; i++ )
128            {
129                indexBuffer[iIndexBuffer] = (Int16)( startIndex + indices[i] );
130                iIndexBuffer++;
131            }
132        }
133    }
134}
Note: See TracBrowser for help on using the repository browser.