| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- //-----------------------------------------------------------------------------
- // LineManager3D.cs
- //
- // Microsoft XNA Community Game Platform
- // Copyright (C) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- using System;
- using System.Collections;
- using System.Text;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using RacingGame;
- using System.Collections.Generic;
- using RacingGame.Helpers;
- using RacingGame.Shaders;
- namespace RacingGame.Graphics
- {
- /// <summary>
- /// Helper class for game for rendering lines.
- /// This class will collect all line calls, then build a new vertex buffer
- /// if any line has changed or the line number changed and finally will
- /// render all lines in the vertex buffer at the end of the frame (so this
- /// class is obviously only for 2D lines directly on screen, no z buffer
- /// and no stuff will be in front of the lines, because everything is
- /// rendered at the end of the frame).
- /// </summary>
- internal class LineManager3D : IDisposable
- {
- /// <summary>
- /// Struct for a line, instances of this class will be added to lines.
- /// </summary>
- struct Line
- {
- // Positions
- public Vector3 startPoint, endPoint;
- // Colors
- public Color startColor, endColor;
- /// <summary>
- /// Constructor
- /// </summary>
- public Line(
- Vector3 setStartPoint, Color setStartColor,
- Vector3 setEndPoint, Color setEndColor)
- {
- startPoint = setStartPoint;
- startColor = setStartColor;
- endPoint = setEndPoint;
- endColor = setEndColor;
- }
- /// <summary>
- /// Are these two Lines equal?
- /// </summary>
- public static bool operator ==(Line a, Line b)
- {
- return
- a.startPoint == b.startPoint &&
- a.endPoint == b.endPoint &&
- a.startColor == b.startColor &&
- a.endColor == b.endColor;
- }
- /// <summary>
- /// Are these two Lines not equal?
- /// </summary>
- public static bool operator !=(Line a, Line b)
- {
- return
- a.startPoint != b.startPoint ||
- a.endPoint != b.endPoint ||
- a.startColor != b.startColor ||
- a.endColor != b.endColor;
- }
- /// <summary>
- /// Support Equals(.) to keep the compiler happy
- /// (because we used == and !=)
- /// </summary>
- public override bool Equals(object a)
- {
- if (a is Line)
- return (Line)a == this;
- return false;
- }
- /// <summary>
- /// Support GetHashCode() to keep the compiler happy
- /// (because we used == and !=)
- /// </summary>
- public override int GetHashCode()
- {
- return 0; // Not supported or nessescary
- }
- }
- /// <summary>
- /// Number of lines used this frame, will be set to 0 when rendering.
- /// </summary>
- private int numOfLines = 0;
- /// <summary>
- /// The actual list for all the lines, it will NOT be reseted each
- /// frame like numOfLines! We will remember the last lines and
- /// only change this list when anything changes (new line, old
- /// line missing, changing line data).
- /// When this happens buildVertexBuffer will be set to true.
- /// </summary>
- private List<Line> lines = new List<Line>();
- /// <summary>
- /// Build vertex buffer this frame because the line list was changed?
- /// </summary>
- private bool buildVertexBuffer = false;
- /// <summary>
- /// Vertex buffer for all lines
- /// </summary>
- VertexPositionColor[] lineVertices =
- new VertexPositionColor[MaxNumOfLines * 2];
- /// <summary>
- /// Real number of primitives currently used.
- /// </summary>
- private int numOfPrimitives = 0;
- /// <summary>
- /// Max. number of lines allowed to prevent to big buffer, will never
- /// be reached, but in case something goes wrong or numOfLines is not
- /// reseted each frame, we won't add unlimited lines (all new lines
- /// will be ignored if this max. number is reached).
- /// </summary>
- protected const int MaxNumOfLines =
- 4096;
- /// <summary>
- /// Init LineManager
- /// </summary>
- public LineManager3D()
- {
- if (BaseGame.Device == null)
- throw new ArgumentNullException(
- "XNA device is not initialized, can't init line manager.");
- }
- /// <summary>
- /// Dispose
- /// </summary>
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- /// <summary>
- /// Dispose
- /// </summary>
- /// <param name="disposing">Disposing</param>
- protected virtual void Dispose(bool disposing)
- {
- }
- /// <summary>
- /// Add line
- /// </summary>
- public void AddLine(
- Vector3 startPoint, Color startColor,
- Vector3 endPoint, Color endColor)
- {
- // Don't add new lines if limit is reached
- if (numOfLines >= MaxNumOfLines)
- {
- /*ignore
- Log.Write("Too many lines requested in LineManager3D. " +
- "Max lines = " + MaxNumOfLines);
- */
- return;
- }
- // Build line
- Line line = new Line(startPoint, startColor, endPoint, endColor);
- // Check if this exact line exists at the current lines position.
- if (lines.Count > numOfLines)
- {
- if ((Line)lines[numOfLines] != line)
- {
- // overwrite old line, otherwise just increase numOfLines
- lines[numOfLines] = line;
- // Remember to build vertex buffer in Render()
- buildVertexBuffer = true;
- }
- }
- else
- {
- // Then just add new line
- lines.Add(line);
- // Remember to build vertex buffer in Render()
- buildVertexBuffer = true;
- }
- // nextUpValue line
- numOfLines++;
- }
- /// <summary>
- /// Add line (only 1 color for start and end version)
- /// </summary>
- public void AddLine(Vector3 startPoint, Vector3 endPoint,
- Color color)
- {
- AddLine(startPoint, color, endPoint, color);
- }
- protected void UpdateVertexBuffer()
- {
- // Don't do anything if we got no lines.
- if (numOfLines == 0 ||
- // Or if some data is invalid
- lines.Count < numOfLines)
- {
- numOfPrimitives = 0;
- return;
- }
- // Set all lines
- for (int lineNum = 0; lineNum < numOfLines; lineNum++)
- {
- Line line = (Line)lines[lineNum];
- lineVertices[lineNum * 2 + 0] = new VertexPositionColor(
- line.startPoint, line.startColor);
- lineVertices[lineNum * 2 + 1] = new VertexPositionColor(
- line.endPoint, line.endColor);
- }
- numOfPrimitives = numOfLines;
- // Vertex buffer was build
- buildVertexBuffer = false;
- }
- /// <summary>
- /// Render all lines added this frame
- /// </summary>
- public void Render()
- {
- // Need to build vertex buffer?
- if (buildVertexBuffer ||
- numOfPrimitives != numOfLines)
- {
- UpdateVertexBuffer();
- }
- // Render lines if we got any lines to render
- if (numOfPrimitives > 0)
- {
- BaseGame.WorldMatrix = Matrix.Identity;
- ShaderEffect.lineRendering.Render(
- "LineRendering3D",
- delegate
- {
- BaseGame.SetAlphaBlendingEnabled(true);
- BaseGame.Device.DrawUserPrimitives<VertexPositionColor>(
- PrimitiveType.LineList, lineVertices, 0, numOfPrimitives);
- });
- }
- // Ok, finally reset numOfLines for next frame
- numOfLines = 0;
- }
- }
- }
|