- Main Page
- Classes
- Files

- File List

# C:/Users/Andreas Schiffler/Desktop/SVN/NewGamePhysics/NewGamePhysics/Utilities/PrimitiveBatch.cs

    00001 //-----------------------------------------------------------------------------
    00002 // PrimitiveBatch.cs
    00003 // (Based on XNA Community Game Platform Demo, Microsoft Corp., 2008)
    00004 //-----------------------------------------------------------------------------
    00005
    00006 namespace NewGamePhysics.Utilities
    00007 {
    00008     using System;
    00009     using Microsoft.Xna.Framework;
    00010     using Microsoft.Xna.Framework.Graphics;
    00011
    00016     public class PrimitiveBatch : IDisposable
    00017     {
    00018         #region Constants and Fields
    00019
    00026         const int DefaultBufferSize = 1024;
    00027
    00033         VertexPositionColor[] vertices = new VertexPositionColor[DefaultBufferSize];
    00034
    00040         int positionInBuffer = 0;
    00041
    00046         VertexDeclaration vertexDeclaration;
    00047
    00052         BasicEffect basicEffect;
    00053
    00057         GraphicsDevice device;
    00058
    00063         PrimitiveType primitiveType;
    00064
    00069         int numVertsPerPrimitive;
    00070
    00075         bool hasBegun = false;
    00076
    00080         bool isDisposed = false;
    00081
    00082         #endregion
    00083
    00087         public PrimitiveBatch(GraphicsDevice graphicsDevice)
    00088         {
    00089             if (graphicsDevice == null)
    00090             {
    00091                 throw new ArgumentNullException("graphicsDevice");
    00092             }
    00093
    00094             device = graphicsDevice;
    00095
    00096             // create a vertex declaration, which tells the graphics card what kind of
    00097             // data to expect during a draw call. We're drawing using
    00098             // VertexPositionColors, so we'll use those vertex elements.
    00099             vertexDeclaration = new VertexDeclaration(graphicsDevice,
    00100                 VertexPositionColor.VertexElements);
    00101
    00102             // set up a new basic effect, and enable vertex colors.
    00103             basicEffect = new BasicEffect(graphicsDevice, null);
    00104             basicEffect.VertexColorEnabled = true;
    00105
    00106             // projection uses CreateOrthographicOffCenter to create 2d projection
    00107             // matrix with 0,0 in the upper left.
    00108             basicEffect.Projection = Matrix.CreateOrthographicOffCenter
    00109                 (0, graphicsDevice.Viewport.Width,
    00110                 graphicsDevice.Viewport.Height, 0,
    00111                 0, 1);
    00112         }
    00113
    00117         public void Dispose()
    00118         {
    00119             this.Dispose(true);
    00120             GC.SuppressFinalize(this);
    00121         }
    00122
    00127         protected virtual void Dispose(bool disposing)
    00128         {
    00129             if (disposing && !isDisposed)
    00130             {
    00131                 if (vertexDeclaration != null)
    00132                 {
    00133                     vertexDeclaration.Dispose();
    00134                 }
    00135
    00136                 if (basicEffect != null)
    00137                 {
    00138                     basicEffect.Dispose();
    00139                 }
    00140
    00141                 isDisposed = true;
    00142             }
    00143         }
    00144
    00150         public void Begin(PrimitiveType primitiveType)
    00151         {
    00152             if (hasBegun)
    00153             {
    00154                 throw new InvalidOperationException
    00155                     ("End must be called before Begin can be called again.");
    00156             }
    00157
    00158             // these three types reuse vertices, so we can't flush properly without more
    00159             // complex logic.
    00160             if (primitiveType == PrimitiveType.LineStrip ||
    00161                 primitiveType == PrimitiveType.TriangleFan ||
    00162                 primitiveType == PrimitiveType.TriangleStrip)
    00163             {
    00164                 throw new NotSupportedException
    00165                     ("The specified primitiveType is not supported by PrimitiveBatch.");
    00166             }
    00167
    00168             this.primitiveType = primitiveType;
    00169
    00170             // how many verts will each of these primitives require?
    00171             this.numVertsPerPrimitive = NumVertsPerPrimitive(primitiveType);
    00172
    00173             // prepare the graphics device for drawing by setting the vertex declaration
    00174             // and telling our basic effect to begin.
    00175             device.VertexDeclaration = vertexDeclaration;
    00176             basicEffect.Begin();
    00177             basicEffect.CurrentTechnique.Passes[0].Begin();
    00178
    00179             // flip the error checking boolean. It's now ok to call AddVertex, Flush,
    00180             // and End.
    00181             hasBegun = true;
    00182         }
    00183
    00193         public void AddVertex(Vector2 vertex, Color color)
    00194         {
    00195             if (!hasBegun)
    00196             {
    00197                 throw new InvalidOperationException
    00198                     ("Begin must be called before AddVertex can be called.");
    00199             }
    00200
    00201             // are we starting a new primitive? if so, and there will not be enough room
    00202             // for a whole primitive, flush.
    00203             bool newPrimitive = ((positionInBuffer % numVertsPerPrimitive) == 0);
    00204
    00205             if (newPrimitive &&
    00206                 (positionInBuffer + numVertsPerPrimitive) >= vertices.Length)
    00207             {
    00208                 Flush();
    00209             }
    00210
    00211             // once we know there's enough room, set the vertex in the buffer,
    00212             // and increase position.
    00213             vertices[positionInBuffer].Position = new Vector3(vertex, 0);
    00214             vertices[positionInBuffer].Color = color;
    00215
    00216             positionInBuffer++;
    00217         }
    00218
    00224         public void End()
    00225         {
    00226             if (!hasBegun)
    00227             {
    00228                 throw new InvalidOperationException
    00229                     ("Begin must be called before End can be called.");
    00230             }
    00231
    00232             // Draw whatever the user wanted us to draw
    00233             Flush();
    00234
    00235             // and then tell basic effect that we're done.
    00236             basicEffect.CurrentTechnique.Passes[0].End();
    00237             basicEffect.End();
    00238             hasBegun = false;
    00239         }
    00240
    00248         private void Flush()
    00249         {
    00250             if (!hasBegun)
    00251             {
    00252                 throw new InvalidOperationException
    00253                     ("Begin must be called before Flush can be called.");
    00254             }
    00255
    00256             // no work to do
    00257             if (positionInBuffer == 0)
    00258             {
    00259                 return;
    00260             }
    00261
    00262             // how many primitives will we draw?
    00263             int primitiveCount = positionInBuffer / numVertsPerPrimitive;
    00264
    00265             // submit the draw call to the graphics card
    00266             device.DrawUserPrimitives<VertexPositionColor>(primitiveType, vertices, 0,
    00267                 primitiveCount);
    00268
    00269             // now that we've drawn, it's ok to reset positionInBuffer back to zero,
    00270             // and write over any vertices that may have been set previously.
    00271             positionInBuffer = 0;
    00272         }
    00273
    00274         #region Helper functions
    00275
    00282         static private int NumVertsPerPrimitive(PrimitiveType primitive)
    00283         {
    00284             int numVertsPerPrimitive;
    00285             switch (primitive)
    00286             {
    00287                 case PrimitiveType.PointList:
    00288                     numVertsPerPrimitive = 1;
    00289                     break;
    00290                 case PrimitiveType.LineList:
    00291                     numVertsPerPrimitive = 2;
    00292                     break;
    00293                 case PrimitiveType.TriangleList:
    00294                     numVertsPerPrimitive = 3;
    00295                     break;
    00296                 default:
    00297                     throw new InvalidOperationException("Primitive is not valid");
    00298             }
    00299             return numVertsPerPrimitive;
    00300         }
    00301
    00302         #endregion
    00303
    00304     }
    00305 }