123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- using System;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- namespace FarseerPhysics.DebugViews
- {
- public class PrimitiveBatch : IDisposable
- {
- private const int DefaultBufferSize = 500;
- // a basic effect, which contains the shaders that we will use to draw our
- // primitives.
- private BasicEffect _basicEffect;
- // the device that we will issue draw calls to.
- private GraphicsDevice _device;
- // hasBegun is flipped to true once Begin is called, and is used to make
- // sure users don't call End before Begin is called.
- private bool _hasBegun;
- private bool _isDisposed;
- private VertexPositionColor[] _lineVertices;
- private int _lineVertsCount;
- private VertexPositionColor[] _triangleVertices;
- private int _triangleVertsCount;
- /// <summary>
- /// the constructor creates a new PrimitiveBatch and sets up all of the internals
- /// that PrimitiveBatch will need.
- /// </summary>
- /// <param name="graphicsDevice">The graphics device.</param>
- public PrimitiveBatch(GraphicsDevice graphicsDevice)
- : this(graphicsDevice, DefaultBufferSize)
- {
- }
- public PrimitiveBatch(GraphicsDevice graphicsDevice, int bufferSize)
- {
- if (graphicsDevice == null)
- {
- throw new ArgumentNullException("graphicsDevice");
- }
- _device = graphicsDevice;
- _triangleVertices = new VertexPositionColor[bufferSize - bufferSize % 3];
- _lineVertices = new VertexPositionColor[bufferSize - bufferSize % 2];
- // set up a new basic effect, and enable vertex colors.
- _basicEffect = new BasicEffect(graphicsDevice);
- _basicEffect.VertexColorEnabled = true;
- }
- #region IDisposable Members
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- #endregion
- public void SetProjection(ref Matrix projection)
- {
- _basicEffect.Projection = projection;
- }
- protected virtual void Dispose(bool disposing)
- {
- if (disposing && !_isDisposed)
- {
- if (_basicEffect != null)
- _basicEffect.Dispose();
- _isDisposed = true;
- }
- }
- /// <summary>
- /// Begin is called to tell the PrimitiveBatch what kind of primitives will be
- /// drawn, and to prepare the graphics card to render those primitives.
- /// </summary>
- /// <param name="projection">The projection.</param>
- /// <param name="view">The view.</param>
- public void Begin(ref Matrix projection, ref Matrix view)
- {
- if (_hasBegun)
- {
- throw new InvalidOperationException("End must be called before Begin can be called again.");
- }
- //tell our basic effect to begin.
- _basicEffect.Projection = projection;
- _basicEffect.View = view;
- _basicEffect.CurrentTechnique.Passes[0].Apply();
- // flip the error checking boolean. It's now ok to call AddVertex, Flush,
- // and End.
- _hasBegun = true;
- }
- public bool IsReady()
- {
- return _hasBegun;
- }
- public void AddVertex(Vector2 vertex, Color color, PrimitiveType primitiveType)
- {
- if (!_hasBegun)
- {
- throw new InvalidOperationException("Begin must be called before AddVertex can be called.");
- }
- if (primitiveType == PrimitiveType.LineStrip ||
- primitiveType == PrimitiveType.TriangleStrip)
- {
- throw new NotSupportedException("The specified primitiveType is not supported by PrimitiveBatch.");
- }
- if (primitiveType == PrimitiveType.TriangleList)
- {
- if (_triangleVertsCount >= _triangleVertices.Length)
- {
- FlushTriangles();
- }
- _triangleVertices[_triangleVertsCount].Position = new Vector3(vertex, -0.1f);
- _triangleVertices[_triangleVertsCount].Color = color;
- _triangleVertsCount++;
- }
- if (primitiveType == PrimitiveType.LineList)
- {
- if (_lineVertsCount >= _lineVertices.Length)
- {
- FlushLines();
- }
- _lineVertices[_lineVertsCount].Position = new Vector3(vertex, 0f);
- _lineVertices[_lineVertsCount].Color = color;
- _lineVertsCount++;
- }
- }
- /// <summary>
- /// End is called once all the primitives have been drawn using AddVertex.
- /// it will call Flush to actually submit the draw call to the graphics card, and
- /// then tell the basic effect to end.
- /// </summary>
- public void End()
- {
- if (!_hasBegun)
- {
- throw new InvalidOperationException("Begin must be called before End can be called.");
- }
- // Draw whatever the user wanted us to draw
- FlushTriangles();
- FlushLines();
- _hasBegun = false;
- }
- private void FlushTriangles()
- {
- if (!_hasBegun)
- {
- throw new InvalidOperationException("Begin must be called before Flush can be called.");
- }
- if (_triangleVertsCount >= 3)
- {
- int primitiveCount = _triangleVertsCount / 3;
- // submit the draw call to the graphics card
- _device.SamplerStates[0] = SamplerState.AnisotropicClamp;
- _device.DrawUserPrimitives(PrimitiveType.TriangleList, _triangleVertices, 0, primitiveCount);
- _triangleVertsCount -= primitiveCount * 3;
- }
- }
- private void FlushLines()
- {
- if (!_hasBegun)
- {
- throw new InvalidOperationException("Begin must be called before Flush can be called.");
- }
- if (_lineVertsCount >= 2)
- {
- int primitiveCount = _lineVertsCount / 2;
- // submit the draw call to the graphics card
- _device.SamplerStates[0] = SamplerState.AnisotropicClamp;
- _device.DrawUserPrimitives(PrimitiveType.LineList, _lineVertices, 0, primitiveCount);
- _lineVertsCount -= primitiveCount * 2;
- }
- }
- }
- }
|