Rectangle renderers work.

This commit is contained in:
Harrison Deng 2019-02-22 01:59:51 -06:00
parent c8e8bbf2be
commit 8d5435ad6c
6 changed files with 56 additions and 76 deletions

View File

@ -107,42 +107,13 @@ namespace CameraTest
protected override void Draw(GameTime gameTime) protected override void Draw(GameTime gameTime)
{ {
GraphicsDevice.Clear(Color.Black); GraphicsDevice.Clear(Color.Black);
rr.Begin(true);
rr.Draw(25, 25, 70, 70, Color.Purple); rr.Draw(25, 25, 70, 70, Color.Purple);
/* rr.End();
* float rotation = 0;
double width = 20;
double height = 20;
int x = 50;
int y = 50;
double topRightAngleFromOrig = Math.Atan(height / width);
pb.Begin(PrimitiveType.LineList);
rr.Begin(false);
Vector2 bottomLeft = new Vector2(x, y); rr.Draw(75, 75, 70, 70, Color.Green);
Vector2 bottomRight = new Vector2(x + (float)(Math.Cos(rotation) * width), y + (float)(Math.Sin(rotation) * width)); rr.End();
float origDiagonalHypotenuse = (float)Math.Sqrt(width * width + height * height);
Vector2 topRight = new Vector2(x + (float)Math.Cos(topRightAngleFromOrig + rotation) * origDiagonalHypotenuse, y + (float)Math.Sin(topRightAngleFromOrig + rotation) * origDiagonalHypotenuse);
Vector2 topLeft = new Vector2(x - (float)(Math.Cos((Math.PI / 2f) - rotation) * height), y + (float)(Math.Sin((Math.PI / 2f) - rotation) * height));
verts[0] = bottomLeft;
verts[1] = bottomRight;
verts[2] = topRight;
verts[3] = topLeft;
vertposcol[0] = new VertexPositionColor(new Vector3(verts[0], 0), Color.White);
vertposcol[1] = new VertexPositionColor(new Vector3(verts[1], 0), Color.White);
vertposcol[2] = new VertexPositionColor(new Vector3(verts[2], 0), Color.White);
vertposcol[3] = new VertexPositionColor(new Vector3(verts[3], 0), Color.White);
EffectTechnique effectTechnique = be.Techniques[0];
EffectPassCollection effectPassCollection = effectTechnique.Passes;
foreach (EffectPass pass in effectPassCollection)
{
pass.Apply();
GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineStrip, vertposcol, 0, 4);
}
pb.End();
*/
base.Draw(gameTime); base.Draw(gameTime);
} }
} }

View File

@ -31,16 +31,13 @@ namespace Demo
{ {
// TODO: Add your initialization logic here // TODO: Add your initialization logic here
basicEffect = new BasicEffect(GraphicsDevice); basicEffect = new BasicEffect(GraphicsDevice);
basicEffect.View = Matrix.CreateLookAt(new Vector3(graphics.PreferredBackBufferWidth/2f, graphics.PreferredBackBufferHeight/2f, 1f), Vector3.Forward, Vector3.Up);
basicEffect.World = Matrix.Identity;
basicEffect.Projection = Matrix.CreateOrthographic(GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1);
basicEffect.VertexColorEnabled = true; basicEffect.VertexColorEnabled = true;
vertices = new VertexPositionColor[5]; vertices = new VertexPositionColor[4];
vertices[0] = new VertexPositionColor(new Vector3(5, 5, 0), Color.Red); vertices[0] = new VertexPositionColor(new Vector3(0, 0, 0), Color.Red);
vertices[1] = new VertexPositionColor(new Vector3(10, 5, 0), Color.Red); vertices[1] = new VertexPositionColor(new Vector3(10, 0, 0), Color.Red);
vertices[2] = new VertexPositionColor(new Vector3(10, 10, 0), Color.Red); vertices[2] = new VertexPositionColor(new Vector3(10, 10, 0), Color.Red);
vertices[3] = new VertexPositionColor(new Vector3(5, 10, 0), Color.Red); vertices[3] = new VertexPositionColor(new Vector3(0, 10, 0), Color.Red);
base.Initialize(); base.Initialize();
} }
@ -52,6 +49,7 @@ namespace Demo
{ {
// Create a new SpriteBatch, which can be used to draw textures. // Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice); spriteBatch = new SpriteBatch(GraphicsDevice);
basicEffect.World = Matrix.CreateOrthographicOffCenter(new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), 0, 1);
// TODO: use this.Content to load your game content here // TODO: use this.Content to load your game content here
} }

View File

@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RecrownedAthenaeum.Tools",
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraTest", "CameraTest\CameraTest.csproj", "{4A9796EE-D10D-4ED8-AE6E-9CE96C3D4FE9}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CameraTest", "CameraTest\CameraTest.csproj", "{4A9796EE-D10D-4ED8-AE6E-9CE96C3D4FE9}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", "Demo\Demo.csproj", "{A56A7DFD-C5E7-4D9B-9A9F-25F94EC824BD}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -35,10 +33,6 @@ Global
{4A9796EE-D10D-4ED8-AE6E-9CE96C3D4FE9}.Debug|Any CPU.Build.0 = Debug|Any CPU {4A9796EE-D10D-4ED8-AE6E-9CE96C3D4FE9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A9796EE-D10D-4ED8-AE6E-9CE96C3D4FE9}.Release|Any CPU.ActiveCfg = Release|Any CPU {4A9796EE-D10D-4ED8-AE6E-9CE96C3D4FE9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A9796EE-D10D-4ED8-AE6E-9CE96C3D4FE9}.Release|Any CPU.Build.0 = Release|Any CPU {4A9796EE-D10D-4ED8-AE6E-9CE96C3D4FE9}.Release|Any CPU.Build.0 = Release|Any CPU
{A56A7DFD-C5E7-4D9B-9A9F-25F94EC824BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A56A7DFD-C5E7-4D9B-9A9F-25F94EC824BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A56A7DFD-C5E7-4D9B-9A9F-25F94EC824BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A56A7DFD-C5E7-4D9B-9A9F-25F94EC824BD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -76,7 +76,7 @@ namespace RecrownedAthenaeum.Camera
public virtual void Apply() public virtual void Apply()
{ {
ViewMatrix = Matrix.CreateLookAt(position, lookAt, upDirection); ViewMatrix = Matrix.CreateLookAt(position, lookAt, upDirection);
TransformationMatrix = worldMatrix * ViewMatrix * projectionMatrix; TransformationMatrix = projectionMatrix * ViewMatrix * worldMatrix;
} }
/// <summary> /// <summary>

View File

@ -15,11 +15,12 @@ namespace RecrownedAthenaeum.Render
int bufferPosition; int bufferPosition;
BasicEffect basicEffect; BasicEffect basicEffect;
PrimitiveType primitiveType; PrimitiveType primitiveType;
private int verticesPerPrimitive;
/// <summary> /// <summary>
/// Sets the vertices per primitive. Default is dependent on the primitive type. Lists will generally satisfy the amount of vertices they need, while strips should be set or it will all be interconnected. /// Amount of primitives.
/// </summary> /// </summary>
public int verticesPerPrimitive; public int primitiveCount;
GraphicsDevice graphicsDevice; GraphicsDevice graphicsDevice;
bool began; bool began;
@ -55,7 +56,8 @@ namespace RecrownedAthenaeum.Render
{ {
case PrimitiveType.LineList: verticesPerPrimitive = 2; break; case PrimitiveType.LineList: verticesPerPrimitive = 2; break;
case PrimitiveType.TriangleList: verticesPerPrimitive = 3; break; case PrimitiveType.TriangleList: verticesPerPrimitive = 3; break;
default: verticesPerPrimitive = 1; break; case PrimitiveType.LineStrip: verticesPerPrimitive = 1; break;
case PrimitiveType.TriangleStrip: verticesPerPrimitive = 3; break;
} }
basicEffect.World = camera.worldMatrix; basicEffect.World = camera.worldMatrix;
basicEffect.View = camera.ViewMatrix; basicEffect.View = camera.ViewMatrix;
@ -108,18 +110,21 @@ namespace RecrownedAthenaeum.Render
/// <summary> /// <summary>
/// Flushes the batch. Automatically called if required if using <see cref="PrimitiveType.LineList"/> or <see cref="PrimitiveType.TriangleList"/>. Otherwise, manual flushing is required. /// Flushes the batch. Automatically called if required if using <see cref="PrimitiveType.LineList"/> or <see cref="PrimitiveType.TriangleList"/>. Otherwise, manual flushing is required.
/// <see cref="primitiveCount"/> is used if not zero. Is reset to zero every flush.
/// </summary> /// </summary>
public void Flush() public void Flush()
{ {
if (!began) throw new InvalidOperationException("Begin needs to be called before flushing."); if (!began) throw new InvalidOperationException("Begin needs to be called before flushing.");
if (disposed) throw new ObjectDisposedException(this.GetType().Name); if (disposed) throw new ObjectDisposedException(this.GetType().Name);
if (bufferPosition == 0) return; if (bufferPosition == 0) return;
if (primitiveCount == 0) primitiveCount = bufferPosition / verticesPerPrimitive;
foreach (EffectPass effectPass in basicEffect.CurrentTechnique.Passes) foreach (EffectPass effectPass in basicEffect.CurrentTechnique.Passes)
{ {
effectPass.Apply(); effectPass.Apply();
graphicsDevice.DrawUserPrimitives(primitiveType, vertices, 0, bufferPosition/verticesPerPrimitive); graphicsDevice.DrawUserPrimitives(primitiveType, vertices, 0, primitiveCount);
} }
bufferPosition = 0; bufferPosition = 0;
primitiveCount = 0;
} }
/// <summary> /// <summary>

View File

@ -10,6 +10,7 @@ namespace RecrownedAthenaeum.Render
/// </summary> /// </summary>
public class RectangleRenderer : IDisposable public class RectangleRenderer : IDisposable
{ {
private bool filled;
private bool disposed; private bool disposed;
/// <summary> /// <summary>
/// The <see cref="PrimitiveBatch"/> used. Needs to be disposed. /// The <see cref="PrimitiveBatch"/> used. Needs to be disposed.
@ -23,7 +24,7 @@ namespace RecrownedAthenaeum.Render
/// <param name="graphicsDevice">Graphics device to use. Default will use <see cref="Configuration"/>.</param> /// <param name="graphicsDevice">Graphics device to use. Default will use <see cref="Configuration"/>.</param>
public RectangleRenderer(Camera2D camera = null, GraphicsDevice graphicsDevice = null) public RectangleRenderer(Camera2D camera = null, GraphicsDevice graphicsDevice = null)
{ {
primitiveBatch = new PrimitiveBatch(camera, graphicsDevice, 4); primitiveBatch = new PrimitiveBatch(camera, graphicsDevice);
} }
/// <summary> /// <summary>
@ -48,6 +49,23 @@ namespace RecrownedAthenaeum.Render
disposed = true; disposed = true;
} }
/// <summary>
/// Begins a batch for rectangles.
/// </summary>
/// <param name="filled">Whether or not this batch should be filled rectangles.</param>
public void Begin(bool filled = false)
{
this.filled = filled;
primitiveBatch.Begin(filled ? PrimitiveType.TriangleStrip : PrimitiveType.LineStrip);
}
/// <summary>
/// Ends the batch.
/// </summary>
public void End()
{
primitiveBatch.End();
}
/// <summary> /// <summary>
/// Draws a basic rectangle given bottom left and top right. /// Draws a basic rectangle given bottom left and top right.
/// </summary> /// </summary>
@ -58,35 +76,29 @@ namespace RecrownedAthenaeum.Render
/// <param name="color">Color of all vertices of this rectangle.</param> /// <param name="color">Color of all vertices of this rectangle.</param>
/// <param name="rotation">Rotation of rectangle. Default is 0 radians.</param> /// <param name="rotation">Rotation of rectangle. Default is 0 radians.</param>
/// <param name="filled">If this rectangle should be filled.</param> /// <param name="filled">If this rectangle should be filled.</param>
public void Draw(int x, int y, int width, int height, Color color, double rotation = 0, bool filled = false) public void Draw(int x, int y, int width, int height, Color color, float rotation = 0)
{ {
primitiveBatch.Begin(filled ? PrimitiveType.TriangleStrip : PrimitiveType.LineStrip); primitiveBatch.primitiveCount = filled ? 3 : 4;
Vector2[] corners = new Vector2[4]; Vector2[] corners = new Vector2[4];
double topRightAngleFromOrig = Math.Atan((double)height / width);
corners[0] = new Vector2(x, y); corners[0] = new Vector2(x, y);
corners[1] = new Vector2(x + (float)Math.Cos(rotation) * width, y + (float)Math.Sin(rotation) * width); corners[1] = new Vector2(x + width, y);
float origDiagonalHypotenuse = (float)Math.Sqrt((width * width) + (height * height)); corners[2] = new Vector2(x + width, y + height);
corners[2] = new Vector2(x + (float)Math.Cos(topRightAngleFromOrig + rotation) * origDiagonalHypotenuse, y + (float)Math.Sin(topRightAngleFromOrig + rotation) * origDiagonalHypotenuse); corners[3] = new Vector2(x, y + height);
corners[3] = new Vector2(x - (float)(Math.Cos((Math.PI / 2f) - rotation) * height), y + (float)(Math.Sin((Math.PI / 2f) - rotation) * height));
if (filled) if (rotation != 0)
{ {
primitiveBatch.AddVertex(corners[1], color); Matrix rotMat = Matrix.CreateRotationZ(rotation);
primitiveBatch.AddVertex(corners[2], color); for (int i = 0; i < corners.Length; i++)
primitiveBatch.AddVertex(corners[0], color); {
primitiveBatch.AddVertex(corners[3], color); Vector2.Transform(corners[i], rotMat);
} }
else
{
primitiveBatch.AddVertex(corners[0], color);
primitiveBatch.AddVertex(corners[1], color);
primitiveBatch.AddVertex(corners[2], color);
primitiveBatch.AddVertex(corners[3], color);
} }
primitiveBatch.End(); primitiveBatch.AddVertex(corners[0], color);
primitiveBatch.AddVertex(corners[1], color);
primitiveBatch.AddVertex(corners[2], color);
primitiveBatch.AddVertex(corners[3], color);
primitiveBatch.AddVertex(corners[0], color);
} }
} }
} }