2
0

LineBatch.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using System;
  2. using FarseerPhysics.Collision.Shapes;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Graphics;
  5. namespace FarseerPhysics.SamplesFramework
  6. {
  7. public class LineBatch : IDisposable
  8. {
  9. private const int DefaultBufferSize = 500;
  10. // a basic effect, which contains the shaders that we will use to draw our
  11. // primitives.
  12. private BasicEffect _basicEffect;
  13. // the device that we will issue draw calls to.
  14. private GraphicsDevice _device;
  15. // hasBegun is flipped to true once Begin is called, and is used to make
  16. // sure users don't call End before Begin is called.
  17. private bool _hasBegun;
  18. private bool _isDisposed;
  19. private VertexPositionColor[] _lineVertices;
  20. private int _lineVertsCount;
  21. public LineBatch(GraphicsDevice graphicsDevice)
  22. : this(graphicsDevice, DefaultBufferSize)
  23. {
  24. }
  25. public LineBatch(GraphicsDevice graphicsDevice, int bufferSize)
  26. {
  27. if (graphicsDevice == null)
  28. {
  29. throw new ArgumentNullException("graphicsDevice");
  30. }
  31. _device = graphicsDevice;
  32. _lineVertices = new VertexPositionColor[bufferSize - bufferSize % 2];
  33. // set up a new basic effect, and enable vertex colors.
  34. _basicEffect = new BasicEffect(graphicsDevice);
  35. _basicEffect.VertexColorEnabled = true;
  36. }
  37. #region IDisposable Members
  38. public void Dispose()
  39. {
  40. Dispose(true);
  41. GC.SuppressFinalize(this);
  42. }
  43. #endregion
  44. protected virtual void Dispose(bool disposing)
  45. {
  46. if (disposing && !_isDisposed)
  47. {
  48. if (_basicEffect != null)
  49. _basicEffect.Dispose();
  50. _isDisposed = true;
  51. }
  52. }
  53. public void Begin(Matrix projection, Matrix view)
  54. {
  55. if (_hasBegun)
  56. {
  57. throw new InvalidOperationException("End must be called before Begin can be called again.");
  58. }
  59. _device.SamplerStates[0] = SamplerState.AnisotropicClamp;
  60. //tell our basic effect to begin.
  61. _basicEffect.Projection = projection;
  62. _basicEffect.View = view;
  63. _basicEffect.CurrentTechnique.Passes[0].Apply();
  64. // flip the error checking boolean. It's now ok to call DrawLineShape, Flush,
  65. // and End.
  66. _hasBegun = true;
  67. }
  68. public void DrawLineShape(Shape shape)
  69. {
  70. DrawLineShape(shape, Color.Black);
  71. }
  72. public void DrawLineShape(Shape shape, Color color)
  73. {
  74. if (!_hasBegun)
  75. {
  76. throw new InvalidOperationException("Begin must be called before DrawLineShape can be called.");
  77. }
  78. if (shape.ShapeType != ShapeType.Edge &&
  79. shape.ShapeType != ShapeType.Loop)
  80. {
  81. throw new NotSupportedException("The specified shapeType is not supported by LineBatch.");
  82. }
  83. if (shape.ShapeType == ShapeType.Edge)
  84. {
  85. if (_lineVertsCount >= _lineVertices.Length)
  86. {
  87. Flush();
  88. }
  89. EdgeShape edge = (EdgeShape)shape;
  90. _lineVertices[_lineVertsCount].Position = new Vector3(edge.Vertex1, 0f);
  91. _lineVertices[_lineVertsCount + 1].Position = new Vector3(edge.Vertex2, 0f);
  92. _lineVertices[_lineVertsCount].Color = _lineVertices[_lineVertsCount + 1].Color = color;
  93. _lineVertsCount += 2;
  94. }
  95. else if (shape.ShapeType == ShapeType.Loop)
  96. {
  97. LoopShape loop = (LoopShape)shape;
  98. for (int i = 0; i < loop.Vertices.Count; ++i)
  99. {
  100. if (_lineVertsCount >= _lineVertices.Length)
  101. {
  102. Flush();
  103. }
  104. _lineVertices[_lineVertsCount].Position = new Vector3(loop.Vertices[i], 0f);
  105. _lineVertices[_lineVertsCount + 1].Position = new Vector3(loop.Vertices.NextVertex(i), 0f);
  106. _lineVertices[_lineVertsCount].Color = _lineVertices[_lineVertsCount + 1].Color = color;
  107. _lineVertsCount += 2;
  108. }
  109. }
  110. }
  111. public void DrawLine(Vector2 v1, Vector2 v2)
  112. {
  113. DrawLine(v1, v2, Color.Black);
  114. }
  115. public void DrawLine(Vector2 v1, Vector2 v2, Color color)
  116. {
  117. if (!_hasBegun)
  118. {
  119. throw new InvalidOperationException("Begin must be called before DrawLineShape can be called.");
  120. }
  121. if (_lineVertsCount >= _lineVertices.Length)
  122. {
  123. Flush();
  124. }
  125. _lineVertices[_lineVertsCount].Position = new Vector3(v1, 0f);
  126. _lineVertices[_lineVertsCount + 1].Position = new Vector3(v2, 0f);
  127. _lineVertices[_lineVertsCount].Color = _lineVertices[_lineVertsCount + 1].Color = color;
  128. _lineVertsCount += 2;
  129. }
  130. // End is called once all the primitives have been drawn using AddVertex.
  131. // it will call Flush to actually submit the draw call to the graphics card, and
  132. // then tell the basic effect to end.
  133. public void End()
  134. {
  135. if (!_hasBegun)
  136. {
  137. throw new InvalidOperationException("Begin must be called before End can be called.");
  138. }
  139. // Draw whatever the user wanted us to draw
  140. Flush();
  141. _hasBegun = false;
  142. }
  143. private void Flush()
  144. {
  145. if (!_hasBegun)
  146. {
  147. throw new InvalidOperationException("Begin must be called before Flush can be called.");
  148. }
  149. if (_lineVertsCount >= 2)
  150. {
  151. int primitiveCount = _lineVertsCount / 2;
  152. // submit the draw call to the graphics card
  153. _device.DrawUserPrimitives(PrimitiveType.LineList, _lineVertices, 0, primitiveCount);
  154. _lineVertsCount -= primitiveCount * 2;
  155. }
  156. }
  157. }
  158. }