00001
00002
00003
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
00097
00098
00099 vertexDeclaration = new VertexDeclaration(graphicsDevice,
00100 VertexPositionColor.VertexElements);
00101
00102
00103 basicEffect = new BasicEffect(graphicsDevice, null);
00104 basicEffect.VertexColorEnabled = true;
00105
00106
00107
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
00159
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
00171 this.numVertsPerPrimitive = NumVertsPerPrimitive(primitiveType);
00172
00173
00174
00175 device.VertexDeclaration = vertexDeclaration;
00176 basicEffect.Begin();
00177 basicEffect.CurrentTechnique.Passes[0].Begin();
00178
00179
00180
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
00202
00203 bool newPrimitive = ((positionInBuffer % numVertsPerPrimitive) == 0);
00204
00205 if (newPrimitive &&
00206 (positionInBuffer + numVertsPerPrimitive) >= vertices.Length)
00207 {
00208 Flush();
00209 }
00210
00211
00212
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
00233 Flush();
00234
00235
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
00257 if (positionInBuffer == 0)
00258 {
00259 return;
00260 }
00261
00262
00263 int primitiveCount = positionInBuffer / numVertsPerPrimitive;
00264
00265
00266 device.DrawUserPrimitives<VertexPositionColor>(primitiveType, vertices, 0,
00267 primitiveCount);
00268
00269
00270
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 }