LineManager2D.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. //-----------------------------------------------------------------------------
  2. // LineManager2D.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using Microsoft.Xna.Framework;
  8. using Microsoft.Xna.Framework.Graphics;
  9. using RacingGame.Graphics;
  10. using RacingGame.Helpers;
  11. using System;
  12. using System.Collections.Generic;
  13. using System.Text;
  14. using RacingGame.Shaders;
  15. namespace RacingGame.Graphics
  16. {
  17. /// <summary>
  18. /// LineManager class, used for drawing lines. We can't simply draw
  19. /// lines like in OpenGL (glLine) because we need to do everything with
  20. /// vertex buffers, which is a bit more work (and using DrawPrimitives
  21. /// directly produces way worse code).
  22. /// </summary>
  23. public class LineManager2D : IDisposable
  24. {
  25. /// <summary>
  26. /// Number of lines used this frame, will be set to 0 when rendering.
  27. /// </summary>
  28. private int numOfLines = 0;
  29. /// <summary>
  30. /// The actual list for all the lines, it will NOT be reseted each
  31. /// frame like numOfLines! We will remember the last lines and
  32. /// only change this list when anything changes (new line, old
  33. /// line missing, changing line data).
  34. /// When this happens buildVertexBuffer will be set to true.
  35. /// </summary>
  36. private List<Line> lines = new List<Line>();
  37. /// <summary>
  38. /// Struct for a line, instances of this struct will be added to lines.
  39. /// </summary>
  40. struct Line
  41. {
  42. /// <summary>
  43. /// Positions
  44. /// </summary>
  45. public Point startPoint, endPoint;
  46. /// <summary>
  47. /// Color
  48. /// </summary>
  49. public Color color;
  50. /// <summary>
  51. /// Create line
  52. /// </summary>
  53. /// <param name="setStartPoint">Set start point</param>
  54. /// <param name="setEndPoint">Set end point</param>
  55. /// <param name="setColor">Set color</param>
  56. public Line(Point setStartPoint,
  57. Point setEndPoint, Color setColor)
  58. {
  59. startPoint = setStartPoint;
  60. endPoint = setEndPoint;
  61. color = setColor;
  62. }
  63. /// <summary>
  64. /// Are these two Lines equal?
  65. /// </summary>
  66. public static bool operator ==(Line a, Line b)
  67. {
  68. return a.startPoint == b.startPoint &&
  69. a.endPoint == b.endPoint &&
  70. a.color == b.color;
  71. }
  72. /// <summary>
  73. /// Are these two Lines not equal?
  74. /// </summary>
  75. public static bool operator !=(Line a, Line b)
  76. {
  77. return a.startPoint != b.startPoint ||
  78. a.endPoint != b.endPoint ||
  79. a.color != b.color;
  80. }
  81. /// <summary>
  82. /// Support Equals(.) to keep the compiler happy
  83. /// (because we used == and !=)
  84. /// </summary>
  85. public override bool Equals(object a)
  86. {
  87. if (a is Line)
  88. return (Line)a == this;
  89. return false;
  90. }
  91. /// <summary>
  92. /// Support GetHashCode() to keep the compiler happy
  93. /// (because we used == and !=)
  94. /// </summary>
  95. public override int GetHashCode()
  96. {
  97. return 0; // Not supported or nessescary
  98. }
  99. }
  100. /// <summary>
  101. /// Build vertex buffer this frame because the line list was changed?
  102. /// Note: The vertex buffer implementation was removed some time ago,
  103. /// but this variable is still used to check for updates to lineVertices!
  104. /// </summary>
  105. private bool buildVertexBuffer = false;
  106. /// <summary>
  107. /// Vertex buffer for all lines
  108. /// </summary>
  109. VertexPositionColor[] lineVertices =
  110. new VertexPositionColor[MaxNumOfLines * 2];
  111. /// <summary>
  112. /// Real number of primitives currently used.
  113. /// </summary>
  114. private int numOfPrimitives = 0;
  115. /// <summary>
  116. /// Max. number of lines allowed.
  117. /// </summary>
  118. private const int MaxNumOfLines = 64;
  119. /// <summary>
  120. /// Create LineManager
  121. /// </summary>
  122. public LineManager2D()
  123. {
  124. }
  125. /// <summary>
  126. /// Dispose
  127. /// </summary>
  128. public void Dispose()
  129. {
  130. Dispose(true);
  131. GC.SuppressFinalize(this);
  132. }
  133. /// <summary>
  134. /// Dispose
  135. /// </summary>
  136. /// <param name="disposing">Disposing</param>
  137. protected virtual void Dispose(bool disposing)
  138. {
  139. }
  140. /// <summary>
  141. /// Update vertex buffer
  142. /// </summary>
  143. private void UpdateVertexBuffer()
  144. {
  145. // Don't do anything if we got no lines.
  146. if (numOfLines == 0 ||
  147. // Or if some data is invalid
  148. lines.Count < numOfLines)
  149. {
  150. numOfPrimitives = 0;
  151. return;
  152. }
  153. #if LOG_STUFF
  154. Log.Write("LineManager.UpdateVertexBuffer() numOfLines=" +
  155. numOfLines + ", buildVertexBuffer=" + buildVertexBuffer);
  156. #endif
  157. // Set all lines
  158. for (int lineNum = 0; lineNum < numOfLines; lineNum++)
  159. {
  160. Line line = (Line)lines[lineNum];
  161. lineVertices[lineNum * 2 + 0] = new VertexPositionColor(
  162. new Vector3(
  163. -1.0f + 2.0f * line.startPoint.X / BaseGame.Width,
  164. -(-1.0f + 2.0f * line.startPoint.Y / BaseGame.Height), 0),
  165. line.color);
  166. lineVertices[lineNum * 2 + 1] = new VertexPositionColor(
  167. new Vector3(
  168. -1.0f + 2.0f * line.endPoint.X / BaseGame.Width,
  169. -(-1.0f + 2.0f * line.endPoint.Y / BaseGame.Height), 0),
  170. line.color);
  171. }
  172. numOfPrimitives = numOfLines;
  173. // Vertex buffer was build
  174. buildVertexBuffer = false;
  175. }
  176. /// <summary>
  177. /// Add line
  178. /// </summary>
  179. public void AddLine(Point startPoint, Point endPoint, Color color)
  180. {
  181. // Don't add new lines if limit is reached
  182. if (numOfLines >= MaxNumOfLines)
  183. {
  184. Log.Write("Too many lines requested in LineManager2D. " +
  185. "Max lines = " + MaxNumOfLines);
  186. return;
  187. }
  188. // Build line
  189. Line line = new Line(startPoint, endPoint, color);
  190. // Check if this exact line exists at the current lines position.
  191. if (lines.Count > numOfLines)
  192. {
  193. if ((Line)lines[numOfLines] != line)
  194. {
  195. // overwrite old line, otherwise just increase numOfLines
  196. lines[numOfLines] = line;
  197. // Remember to build vertex buffer in Render()
  198. buildVertexBuffer = true;
  199. }
  200. }
  201. else
  202. {
  203. // Then just add new line
  204. lines.Add(line);
  205. // Remember to build vertex buffer in Render()
  206. buildVertexBuffer = true;
  207. }
  208. // nextUpValue line
  209. numOfLines++;
  210. }
  211. /// <summary>
  212. /// Add line with shadow
  213. /// </summary>
  214. /// <param name="startPoint">Start point</param>
  215. /// <param name="endPoint">End point</param>
  216. /// <param name="color">Color</param>
  217. public void AddLineWithShadow(Point startPoint, Point endPoint,
  218. Color color)
  219. {
  220. AddLine(new Point(startPoint.X, startPoint.Y + 1),
  221. new Point(endPoint.X, endPoint.Y + 1), Color.Black);
  222. AddLine(startPoint, endPoint, color);
  223. }
  224. /// <summary>
  225. /// Render all lines added this frame
  226. /// </summary>
  227. public virtual void Render()
  228. {
  229. // Need to build vertex buffer?
  230. if (buildVertexBuffer ||
  231. numOfPrimitives != numOfLines)
  232. {
  233. UpdateVertexBuffer();
  234. }
  235. // Render lines if we got any lines to render
  236. if (numOfPrimitives > 0)
  237. {
  238. BaseGame.SetAlphaBlendingEnabled(true);
  239. BaseGame.WorldMatrix = Matrix.Identity;
  240. ShaderEffect.lineRendering.Render(
  241. "LineRendering2D",
  242. delegate
  243. {
  244. BaseGame.Device.DrawUserPrimitives<VertexPositionColor>(
  245. PrimitiveType.LineList, lineVertices, 0, numOfPrimitives);
  246. });
  247. }
  248. // Ok, finally reset numOfLines for next frame
  249. numOfLines = 0;
  250. }
  251. }
  252. }