Add composite line drawing methods to RgbaColorRenderer.

This commit is contained in:
Paul Chote
2015-12-10 16:02:27 +00:00
parent 50dfa6df8f
commit c5dbc5fab7

View File

@@ -67,6 +67,115 @@ namespace OpenRA.Graphics
vertices[nv++] = new Vertex(end - corner + Offset, r, g, b, a);
}
/// <summary>
/// Calculate the intersection of two lines.
/// Will behave badly if the lines are parallel
/// </summary>
float2 IntersectionOf(float2 a, float2 da, float2 b, float2 db)
{
var crossA = a.X * (a.Y + da.Y) - a.Y * (a.X + da.X);
var crossB = b.X * (b.Y + db.Y) - b.Y * (b.X + db.X);
var x = da.X * crossB - db.X * crossA;
var y = da.Y * crossB - db.Y * crossA;
var d = da.X * db.Y - da.Y * db.X;
return new float2(x, y) / d;
}
void DrawConnectedLine(float2[] points, float width, Color color, bool closed)
{
// Not a line
if (points.Length < 2)
return;
// Single segment
if (points.Length == 2)
{
DrawLine(points[0], points[1], width, color);
return;
}
renderer.CurrentBatchRenderer = this;
color = Util.PremultiplyAlpha(color);
var r = color.R / 255.0f;
var g = color.G / 255.0f;
var b = color.B / 255.0f;
var a = color.A / 255.0f;
var start = points[0];
var end = points[1];
var dir = (end - start) / (end - start).Length;
var corner = width / 2 * new float2(-dir.Y, dir.X);
// Corners for start of line segment
var ca = start - corner;
var cb = start + corner;
// Segment is part of closed loop
if (closed)
{
var prev = points[points.Length - 1];
var prevDir = (start - prev) / (start - prev).Length;
var prevCorner = width / 2 * new float2(-prevDir.Y, prevDir.X);
ca = IntersectionOf(start - prevCorner, prevDir, start - corner, dir);
cb = IntersectionOf(start + prevCorner, prevDir, start + corner, dir);
}
var limit = closed ? points.Length : points.Length - 1;
for (var i = 0; i < limit; i++)
{
var next = points[(i + 2) % points.Length];
var nextDir = (next - end) / (next - end).Length;
var nextCorner = width / 2 * new float2(-nextDir.Y, nextDir.X);
// Vertices for the corners joining start-end to end-next
var cc = closed || i < limit ? IntersectionOf(end + corner, dir, end + nextCorner, nextDir) : end + corner;
var cd = closed || i < limit ? IntersectionOf(end - corner, dir, end - nextCorner, nextDir) : end - corner;
// Fill segment
if (nv + 4 > renderer.TempBufferSize)
Flush();
vertices[nv++] = new Vertex(ca + Offset, r, g, b, a);
vertices[nv++] = new Vertex(cb + Offset, r, g, b, a);
vertices[nv++] = new Vertex(cc + Offset, r, g, b, a);
vertices[nv++] = new Vertex(cd + Offset, r, g, b, a);
// Advance line segment
end = next;
dir = nextDir;
corner = nextCorner;
ca = cd;
cb = cc;
}
}
public void DrawLine(float2[] points, float width, Color color, bool connectSegments = false)
{
if (!connectSegments)
{
if (points.Length < 2)
return;
for (var i = 1; i < points.Length; i++)
DrawLine(points[i - 1], points[i], width, color);
}
else
DrawConnectedLine(points, width, color, false);
}
public void DrawPolygon(float2[] vertices, float width, Color color)
{
DrawConnectedLine(vertices, width, color, true);
}
public void DrawRect(float2 tl, float2 br, float width, Color color)
{
var tr = new float2(br.X, tl.Y);
var bl = new float2(tl.X, br.Y);
DrawPolygon(new[] { tl, tr, br, bl }, width, color);
}
public void FillRect(float2 tl, float2 br, Color color)
{
renderer.CurrentBatchRenderer = this;