LineManager3D.cs 8.8 KB

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