2023-06-23 21:56:07 +02:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using Quik.CommandMachine;
|
|
|
|
|
|
|
|
namespace Quik.VertexGenerator
|
|
|
|
{
|
|
|
|
public class VertexGeneratorEngine : CommandEngine
|
|
|
|
{
|
|
|
|
public DrawQueue DrawQueue { get; } = new DrawQueue();
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Granularity for rounded geometry.
|
|
|
|
/// </summary>
|
|
|
|
protected float CurveGranularity =>
|
|
|
|
(Style["-vertex-curve-granularity"] is float value) ? value : 1.0f;
|
|
|
|
protected QuikVertex StrokeVertex => new QuikVertex()
|
|
|
|
{
|
|
|
|
ZIndex = Style.ZIndex ?? this.ZIndex,
|
|
|
|
Color = Style.StrokeColor ?? QuikColor.Black,
|
|
|
|
};
|
|
|
|
protected QuikVertex FillVertex => new QuikVertex()
|
|
|
|
{
|
|
|
|
ZIndex = Style.ZIndex ?? this.ZIndex,
|
|
|
|
Color = Style.Color ?? QuikColor.White,
|
|
|
|
};
|
|
|
|
|
|
|
|
protected override void ChildProcessCommand(Command name, CommandQueue queue)
|
|
|
|
{
|
|
|
|
base.ChildProcessCommand(name, queue);
|
|
|
|
|
|
|
|
switch(name)
|
|
|
|
{
|
2023-06-28 14:22:48 +02:00
|
|
|
case Command.Line: LineProc(queue); break;
|
|
|
|
case Command.Bezier: BezierProc(queue); break;
|
|
|
|
case Command.Rectangle: RectangleProc(queue); break;
|
|
|
|
default: break;
|
2023-06-23 21:56:07 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the rounding resolution for a line segment or border radius.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="radius">The width of the line.</param>
|
|
|
|
/// <param name="arc">The angle of the cap or joint arc.</param>
|
|
|
|
/// <returns>The rounding resolution.</returns>
|
|
|
|
protected int GetRoundingResolution(float radius, float arc)
|
|
|
|
{
|
|
|
|
return (int) Math.Ceiling(arc * radius * CurveGranularity);
|
|
|
|
}
|
|
|
|
|
|
|
|
private readonly List<QuikLine> LineList = new List<QuikLine>();
|
|
|
|
private void LineProc(CommandQueue queue)
|
|
|
|
{
|
|
|
|
Frame frame = queue.Dequeue();
|
|
|
|
|
|
|
|
// Clear temporary vector list and retreive all line segments.
|
|
|
|
LineList.Clear();
|
|
|
|
if (frame.Type == FrameType.IVec1)
|
|
|
|
{
|
|
|
|
int count = (int)frame;
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
frame = queue.Dequeue();
|
|
|
|
LineList.Add((QuikLine)frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LineList.Add((QuikLine)frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
float width = Style.StrokeWidth ?? 1;
|
|
|
|
|
|
|
|
DrawQueue.StartDrawCall(Viewport);
|
|
|
|
LineInfo prevBase, nextBase = default;
|
|
|
|
for (int i = 0; i < LineList.Count; i++)
|
|
|
|
{
|
|
|
|
QuikLine line = LineList[i];
|
|
|
|
// A line segment needs a start cap if it is the first segment in
|
|
|
|
// the list, or the last end point is not the current start point.
|
|
|
|
bool isStart = (i == 0 || line.Start != LineList[i - 1].End);
|
|
|
|
// A line segment needs an end cap if it is the last line segment
|
|
|
|
// in the list or if the next start point is not the current end point.
|
|
|
|
bool isEnd = (i == LineList.Count - 1 || line.End != LineList[i+1].Start);
|
|
|
|
|
|
|
|
// Generate the main line segment.
|
|
|
|
prevBase = nextBase;
|
|
|
|
nextBase = GenerateLineSegment(line);
|
|
|
|
|
|
|
|
if (isStart)
|
|
|
|
{
|
|
|
|
// Then a start cap if necessary.
|
|
|
|
GenerateCap(line.Start, line.Normal(), prevBase, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Otherwise generate the required joint.
|
|
|
|
GenerateJoint(line.Start, LineList[i-1].Normal(), line.Normal(), prevBase, nextBase);
|
|
|
|
}
|
|
|
|
if (isEnd)
|
|
|
|
{
|
|
|
|
// Then generate the end cap if necessary.
|
|
|
|
GenerateCap(line.End, line.Normal(), nextBase, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DrawQueue.EndDrawCall();
|
|
|
|
}
|
|
|
|
|
|
|
|
private LineInfo GenerateLineSegment(in QuikLine line)
|
|
|
|
{
|
|
|
|
QuikVertex vertex = StrokeVertex;
|
|
|
|
QuikVertex a, b, c, d;
|
|
|
|
QuikVec2 normal = line.Normal();
|
|
|
|
float width = Style.StrokeWidth ?? 1;
|
|
|
|
|
|
|
|
a = b = c = d = vertex;
|
|
|
|
a.Position = line.Start + width / 2 * normal;
|
|
|
|
b.Position = line.Start - width / 2 * normal;
|
|
|
|
c.Position = line.End + width / 2 * normal;
|
|
|
|
d.Position = line.End - width / 2 * normal;
|
|
|
|
|
|
|
|
DrawQueue.RestoreOffset();
|
|
|
|
DrawQueue.AddVertex(a);
|
|
|
|
DrawQueue.AddVertex(b);
|
|
|
|
DrawQueue.AddVertex(c);
|
|
|
|
DrawQueue.AddVertex(d);
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(2); DrawQueue.AddElement(0);
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(3); DrawQueue.AddElement(2);
|
|
|
|
return new LineInfo(DrawQueue.BaseOffset, 0, 1, 2, 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void GenerateJoint(
|
|
|
|
in QuikVec2 center,
|
|
|
|
in QuikVec2 prevNormal,
|
|
|
|
in QuikVec2 nextNormal,
|
|
|
|
in LineInfo prevInfo,
|
|
|
|
in LineInfo nextInfo)
|
|
|
|
{
|
|
|
|
// Figure out which side needs the joint.
|
|
|
|
QuikVec2 meanNormal = 0.5f * (prevNormal + nextNormal);
|
|
|
|
QuikVec2 meanTangent = new QuikVec2(meanNormal.Y, -meanNormal.X);
|
|
|
|
QuikVec2 positiveEdge = ((center + nextNormal) - (center + prevNormal)).Normalize();
|
|
|
|
QuikVec2 negativeEdge = ((center - nextNormal) - (center - prevNormal)).Normalize();
|
|
|
|
float positive, negative;
|
|
|
|
positive = QuikVec2.Dot(meanTangent, positiveEdge);
|
|
|
|
negative = QuikVec2.Dot(meanNormal, negativeEdge);
|
|
|
|
|
|
|
|
if (positive == negative)
|
|
|
|
{
|
|
|
|
// To be fair this is highly unlikely considering the nature of
|
|
|
|
// floats, but, generate an end cap to handle a cusp.
|
|
|
|
GenerateCap(center, nextNormal, nextInfo, true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QuikVertex vertex = StrokeVertex;
|
|
|
|
float radius = Style.StrokeWidth/2 ?? 0.5f;
|
|
|
|
float arc = MathF.Acos(QuikVec2.Dot(prevNormal, nextNormal));
|
|
|
|
int resolution = GetRoundingResolution(radius, arc);
|
|
|
|
bool isNegative = positive < negative;
|
|
|
|
|
|
|
|
vertex.Position = center;
|
|
|
|
DrawQueue.RestoreOffset();
|
|
|
|
DrawQueue.AddVertex(vertex);
|
|
|
|
|
|
|
|
int lastIndex, endIndex;
|
|
|
|
if (isNegative)
|
|
|
|
{
|
|
|
|
lastIndex = DrawQueue.RelativeElement(prevInfo.BaseOffset, prevInfo.EndNegative);
|
|
|
|
endIndex = DrawQueue.RelativeElement(nextInfo.BaseOffset, nextInfo.StartNegative);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lastIndex = DrawQueue.RelativeElement(nextInfo.BaseOffset, nextInfo.StartNegative);
|
|
|
|
endIndex = DrawQueue.RelativeElement(prevInfo.BaseOffset, prevInfo.EndPositive);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < resolution; i++)
|
|
|
|
{
|
|
|
|
float angle = (float)(i+1) / (resolution + 1) * arc;
|
|
|
|
float cos = MathF.Cos(angle);
|
|
|
|
float sin = MathF.Sin(angle);
|
|
|
|
|
|
|
|
QuikVec2 displacement;
|
|
|
|
if (isNegative)
|
|
|
|
{
|
|
|
|
displacement = new QuikVec2()
|
|
|
|
{
|
|
|
|
X = -prevNormal.X * cos + prevNormal.Y * sin,
|
|
|
|
Y = -prevNormal.X * sin - prevNormal.Y * cos
|
|
|
|
} * radius;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
displacement = new QuikVec2()
|
|
|
|
{
|
|
|
|
X = nextNormal.X * cos - nextNormal.Y * sin,
|
|
|
|
Y = nextNormal.X * sin + nextNormal.Y * cos
|
|
|
|
} * radius;
|
|
|
|
}
|
|
|
|
|
|
|
|
vertex.Position = center + displacement;
|
|
|
|
|
|
|
|
DrawQueue.AddVertex(vertex);
|
|
|
|
DrawQueue.AddElement(lastIndex);
|
|
|
|
DrawQueue.AddElement(i);
|
|
|
|
DrawQueue.AddElement(0);
|
|
|
|
|
|
|
|
lastIndex = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
DrawQueue.AddElement(lastIndex);
|
|
|
|
DrawQueue.AddElement(endIndex);
|
|
|
|
DrawQueue.AddElement(0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private void GenerateCap(
|
|
|
|
in QuikVec2 center,
|
|
|
|
in QuikVec2 normal,
|
|
|
|
in LineInfo info,
|
|
|
|
bool endCap)
|
|
|
|
{
|
|
|
|
int lastIndex, startIndex;
|
|
|
|
QuikVertex vertex = StrokeVertex;
|
|
|
|
float radius = Style.StrokeWidth ?? 1.0f;
|
|
|
|
int resolution = GetRoundingResolution(radius, MathF.PI);
|
|
|
|
|
|
|
|
DrawQueue.RestoreOffset();
|
|
|
|
if (endCap)
|
|
|
|
{
|
|
|
|
lastIndex = DrawQueue.RelativeElement(info.BaseOffset, info.EndPositive);
|
|
|
|
startIndex = DrawQueue.RelativeElement(info.BaseOffset, info.EndNegative);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lastIndex = DrawQueue.RelativeElement(info.BaseOffset, info.StartPositive);
|
|
|
|
startIndex = DrawQueue.RelativeElement(info.BaseOffset, info.StartNegative);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < resolution; i++)
|
|
|
|
{
|
|
|
|
float angle = (float) (i + 1) / (resolution + 1) * MathF.PI;
|
|
|
|
float cos = MathF.Cos(angle);
|
|
|
|
float sin = MathF.Sin(angle);
|
|
|
|
|
|
|
|
QuikVec2 displacement;
|
|
|
|
if (endCap)
|
|
|
|
{
|
|
|
|
displacement = new QuikVec2()
|
|
|
|
{
|
|
|
|
X = normal.X * cos + normal.Y * sin,
|
|
|
|
Y = -normal.X * sin + normal.Y * cos
|
|
|
|
} * radius;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
displacement = new QuikVec2()
|
|
|
|
{
|
|
|
|
X = normal.X * cos - normal.Y * sin,
|
|
|
|
Y = normal.X * sin + normal.Y * cos
|
|
|
|
} * radius;
|
|
|
|
}
|
|
|
|
|
|
|
|
vertex.Position = center + displacement;
|
|
|
|
|
|
|
|
DrawQueue.AddVertex(vertex);
|
|
|
|
DrawQueue.AddElement(startIndex);
|
|
|
|
DrawQueue.AddElement(lastIndex);
|
|
|
|
DrawQueue.AddElement(i);
|
|
|
|
|
|
|
|
lastIndex = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private readonly List<QuikBezier> BezierList = new List<QuikBezier>();
|
|
|
|
private void BezierProc(CommandQueue queue)
|
|
|
|
{
|
|
|
|
Frame a = queue.Dequeue();
|
|
|
|
Frame b;
|
|
|
|
|
|
|
|
// Clear temporary vector list and retreive all bezier segments.
|
|
|
|
BezierList.Clear();
|
|
|
|
if (a.Type == FrameType.IVec1)
|
|
|
|
{
|
|
|
|
int count = (int)a;
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
a = queue.Dequeue();
|
|
|
|
b = queue.Dequeue();
|
|
|
|
|
|
|
|
BezierList.Add(
|
|
|
|
new QuikBezier(
|
|
|
|
new QuikVec2(a.GetF(0), a.GetF(1)),
|
|
|
|
new QuikVec2(b.GetF(0), b.GetF(1)),
|
|
|
|
new QuikVec2(b.GetF(2), b.GetF(3)),
|
|
|
|
new QuikVec2(a.GetF(2), a.GetF(3))
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
b = queue.Dequeue();
|
|
|
|
|
|
|
|
BezierList.Add(
|
|
|
|
new QuikBezier(
|
|
|
|
new QuikVec2(a.GetF(0), a.GetF(1)),
|
|
|
|
new QuikVec2(b.GetF(0), b.GetF(1)),
|
|
|
|
new QuikVec2(b.GetF(2), b.GetF(3)),
|
|
|
|
new QuikVec2(a.GetF(2), a.GetF(3))
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
float width = Style.StrokeWidth ?? 1;
|
|
|
|
|
|
|
|
DrawQueue.StartDrawCall(Viewport);
|
|
|
|
LineInfo prevBase, nextBase = default;
|
|
|
|
for (int i = 0; i < LineList.Count; i++)
|
|
|
|
{
|
|
|
|
QuikBezier bezier = BezierList[i];
|
|
|
|
// A line segment needs a start cap if it is the first segment in
|
|
|
|
// the list, or the last end point is not the current start point.
|
|
|
|
bool isStart = (i == 0 || bezier.Start != BezierList[i - 1].End);
|
|
|
|
// A line segment needs an end cap if it is the last line segment
|
|
|
|
// in the list or if the next start point is not the current end point.
|
|
|
|
bool isEnd = (i == LineList.Count - 1 || bezier.End != BezierList[i+1].Start);
|
|
|
|
|
|
|
|
// Generate the main line segment.
|
|
|
|
prevBase = nextBase;
|
|
|
|
nextBase = GenerateBezierSegment(bezier);
|
|
|
|
|
|
|
|
if (isStart)
|
|
|
|
{
|
|
|
|
// Then a start cap if necessary.
|
|
|
|
GenerateCap(bezier.Start, bezier.GetBezierNormal(0), prevBase, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Otherwise generate the required joint.
|
|
|
|
GenerateJoint(bezier.Start, BezierList[i-1].GetBezierNormal(1), bezier.GetBezierNormal(0), prevBase, nextBase);
|
|
|
|
}
|
|
|
|
if (isEnd)
|
|
|
|
{
|
|
|
|
// Then generate the end cap if necessary.
|
|
|
|
GenerateCap(bezier.End, bezier.GetBezierNormal(1), nextBase, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DrawQueue.EndDrawCall();
|
|
|
|
}
|
|
|
|
|
|
|
|
private LineInfo GenerateBezierSegment(in QuikBezier bezier)
|
|
|
|
{
|
|
|
|
QuikVec2 startTangent = bezier.GetBezierTangent(0);
|
|
|
|
QuikVec2 endTangent = bezier.GetBezierTangent(1);
|
|
|
|
QuikVec2 startNormal = new QuikVec2(-startTangent.Y, startTangent.X).Normalize();
|
|
|
|
QuikVec2 endNormal = new QuikVec2(-endTangent.Y, endTangent.X).Normalize();
|
|
|
|
|
|
|
|
float width = Style.StrokeWidth ?? 1;
|
|
|
|
float radius = 0.5f * width;
|
|
|
|
int resolution = GetRoundingResolution(radius, bezier.RasterizationArc);
|
|
|
|
|
|
|
|
DrawQueue.RestoreOffset();
|
|
|
|
QuikVertex v = StrokeVertex;
|
|
|
|
int vbase = DrawQueue.BaseOffset;
|
|
|
|
int index = 2;
|
|
|
|
|
|
|
|
v.Position = bezier.Start + radius * startNormal;
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = bezier.Start - radius * startNormal;
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
for (int i = 0; i < resolution; i++, index += 2)
|
|
|
|
{
|
|
|
|
float t = (i + 1.0f) / resolution;
|
|
|
|
QuikVec2 at = bezier.GetBezierTangent(t).Normalize();
|
|
|
|
QuikVec2 a = bezier.GetBezierPoint(t);
|
|
|
|
QuikVec2 an = radius * new QuikVec2(-at.Y, at.X);
|
|
|
|
|
|
|
|
v.Position = a + an;
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = a - an;
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(index - 2); DrawQueue.AddElement(index - 1); DrawQueue.AddElement(index + 0);
|
|
|
|
DrawQueue.AddElement(index - 1); DrawQueue.AddElement(index + 1); DrawQueue.AddElement(index + 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new LineInfo(vbase, 0, 1, index - 2, index - 1);
|
|
|
|
}
|
|
|
|
|
2023-06-28 14:22:48 +02:00
|
|
|
private readonly List<QuikRectangle> RectangleList = new List<QuikRectangle>();
|
|
|
|
private void RectangleProc(CommandQueue queue)
|
|
|
|
{
|
|
|
|
Frame frame = queue.Dequeue();
|
|
|
|
RectangleList.Clear();
|
|
|
|
if (frame.Type == FrameType.IVec1)
|
|
|
|
{
|
|
|
|
int count = (int)frame;
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
frame = queue.Dequeue();
|
|
|
|
RectangleList.Add((QuikRectangle)frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RectangleList.Add((QuikRectangle)frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
float stroke = Style.StrokeWidth ?? 1.0f;
|
|
|
|
float radius = (float?)Style["radius"] ?? 0.0f; // TODO: not this.
|
|
|
|
DrawQueue.StartDrawCall(Viewport);
|
|
|
|
for (int i = 0; i < RectangleList.Count; i++)
|
|
|
|
{
|
|
|
|
QuikRectangle outer = RectangleList[i];
|
|
|
|
QuikRectangle inner = new QuikRectangle(
|
|
|
|
outer.Right - stroke, outer.Top - stroke,
|
|
|
|
outer.Left + stroke, outer.Bottom + stroke);
|
|
|
|
|
|
|
|
GenerateRectangleBase(inner, Math.Max(radius - stroke, 0.0f));
|
|
|
|
|
|
|
|
if (stroke == 0.0f)
|
|
|
|
continue;
|
|
|
|
if (radius == 0.0f)
|
|
|
|
{
|
|
|
|
GenerateRectangleStripStraight(outer);
|
|
|
|
}
|
|
|
|
else if (radius < stroke)
|
|
|
|
{
|
|
|
|
GenerateRectangleStripNarrow(outer, radius);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GenerateRectangleStripWide(outer, radius);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DrawQueue.EndDrawCall();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void GenerateRectangleBase(in QuikRectangle rectangle, float radius)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
+--j-------i--+
|
|
|
|
|NW| N |NE|
|
|
|
|
k--d-------c--h
|
|
|
|
| | | |
|
|
|
|
|W | C | E|
|
|
|
|
| | | |
|
|
|
|
l--a-------b--g
|
|
|
|
|SW| S |SE|
|
|
|
|
+--e-------f--+
|
|
|
|
|
|
|
|
a b c d e f g h i j k l
|
|
|
|
0 1 2 3 4 5 6 7 8 9 10 11
|
|
|
|
*/
|
|
|
|
|
|
|
|
DrawQueue.RestoreOffset();
|
|
|
|
|
|
|
|
// Draw center rectangle.
|
|
|
|
|
|
|
|
QuikVec2 aPos, bPos, cPos, dPos;
|
|
|
|
|
|
|
|
QuikVertex v = FillVertex;
|
|
|
|
aPos = v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
bPos = v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
cPos = v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
dPos = v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2);
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(2); DrawQueue.AddElement(3);
|
|
|
|
|
|
|
|
if (radius == 0.0f)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Draw south rectangle.
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(5); DrawQueue.AddElement(1);
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(1); DrawQueue.AddElement(0);
|
|
|
|
|
|
|
|
// Draw east rectangle.
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(6); DrawQueue.AddElement(7);
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(7); DrawQueue.AddElement(3);
|
|
|
|
|
|
|
|
// Draw north rectangle.
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(3); DrawQueue.AddElement(2); DrawQueue.AddElement(8);
|
|
|
|
DrawQueue.AddElement(3); DrawQueue.AddElement(8); DrawQueue.AddElement(0);
|
|
|
|
|
|
|
|
// Draw west rectangle.
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(11); DrawQueue.AddElement(0); DrawQueue.AddElement(3);
|
|
|
|
DrawQueue.AddElement(11); DrawQueue.AddElement(3); DrawQueue.AddElement(10);
|
|
|
|
|
|
|
|
// Draw north east corner.
|
|
|
|
|
|
|
|
int resolution = GetRoundingResolution(radius, 0.5f * MathF.PI);
|
|
|
|
int previous = 7, current = 12;
|
|
|
|
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = MathF.Cos(theta) * radius;
|
|
|
|
float yoff = MathF.Sin(theta) * radius;
|
|
|
|
|
|
|
|
v.Position = cPos + new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
DrawQueue.AddElement(2); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(2); DrawQueue.AddElement(previous); DrawQueue.AddElement(8);
|
|
|
|
|
|
|
|
// Draw the north west corner.
|
|
|
|
|
|
|
|
previous = 9;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = -MathF.Sin(theta) * radius;
|
|
|
|
float yoff = MathF.Cos(theta) * radius;
|
|
|
|
|
|
|
|
v.Position = dPos + new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
DrawQueue.AddElement(3); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(3); DrawQueue.AddElement(previous); DrawQueue.AddElement(10);
|
|
|
|
|
|
|
|
// Draw south west corner.
|
|
|
|
|
|
|
|
previous = 11;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = -MathF.Cos(theta) * radius;
|
|
|
|
float yoff = -MathF.Sin(theta) * radius;
|
|
|
|
|
|
|
|
v.Position = aPos + new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
DrawQueue.AddElement(0); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(0); DrawQueue.AddElement(previous); DrawQueue.AddElement(4);
|
|
|
|
|
|
|
|
// Draw the south east corner.
|
|
|
|
|
|
|
|
previous = 5;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = -MathF.Sin(theta) * radius;
|
|
|
|
float yoff = MathF.Cos(theta) * radius;
|
|
|
|
|
|
|
|
v.Position = bPos + new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(previous); DrawQueue.AddElement(6);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void GenerateRectangleStripStraight(in QuikRectangle rectangle)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
h---------g
|
|
|
|
|\ N /|
|
|
|
|
| \ / |
|
|
|
|
| d---c |
|
|
|
|
|W | | E|
|
|
|
|
| a---b |
|
|
|
|
| / \ |
|
|
|
|
|/ S \|
|
|
|
|
e---------f
|
|
|
|
|
|
|
|
a b c d e f g h
|
|
|
|
0 1 2 3 4 5 6 7
|
|
|
|
*/
|
|
|
|
|
|
|
|
QuikVertex v = StrokeVertex;
|
|
|
|
float stroke = Style.StrokeWidth ?? 1.0f;
|
|
|
|
|
|
|
|
DrawQueue.RestoreOffset();
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + stroke, rectangle.Bottom + stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - stroke, rectangle.Bottom + stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - stroke, rectangle.Top - stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + stroke, rectangle.Top - stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(5); DrawQueue.AddElement(1); // SSW
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(1); DrawQueue.AddElement(0); // SSE
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(5); DrawQueue.AddElement(6); // SEE
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(6); DrawQueue.AddElement(2); // NEE
|
|
|
|
DrawQueue.AddElement(3); DrawQueue.AddElement(2); DrawQueue.AddElement(6); // NNE
|
|
|
|
DrawQueue.AddElement(3); DrawQueue.AddElement(6); DrawQueue.AddElement(7); // NNW
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(0); DrawQueue.AddElement(3); // NWW
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(3); DrawQueue.AddElement(7); // SWW
|
|
|
|
}
|
|
|
|
|
|
|
|
private void GenerateRectangleStripNarrow(in QuikRectangle rectangle, float radius)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
v-j---i-u
|
|
|
|
| | | |
|
|
|
|
x-w | N | t-s
|
|
|
|
| \| |/ |
|
|
|
|
k---d---c---h
|
|
|
|
| | | |
|
|
|
|
| W | | E |
|
|
|
|
| | | |
|
|
|
|
l---a---b---g
|
|
|
|
| /| |\ |
|
|
|
|
m-n | S | q-r
|
|
|
|
| | | |
|
|
|
|
o-e---f-p
|
|
|
|
|
|
|
|
a b c d e f g h i j
|
|
|
|
00: 0 1 2 3 4 5 6 7 8 9
|
|
|
|
k l m n o p q r s t
|
|
|
|
10: 0 1 2 3 4 5 6 7 8 9
|
|
|
|
u v w x
|
|
|
|
20: 0 1 2 3
|
|
|
|
*/
|
|
|
|
QuikVertex v = StrokeVertex;
|
|
|
|
QuikVec2 nPos, qPos, tPos, wPos;
|
|
|
|
float stroke = Style.StrokeWidth ?? 1.0f;
|
|
|
|
|
|
|
|
DrawQueue.RestoreOffset();
|
|
|
|
|
|
|
|
// a-b-c-d
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + stroke, rectangle.Bottom + stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - stroke, rectangle.Bottom + stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - stroke, rectangle.Top - stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + stroke, rectangle.Top - stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
// ef-gh-ij-kl
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + stroke, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + stroke, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Bottom + stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Top - stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - stroke, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - stroke, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Top - stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Bottom + stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
// mno
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
nPos = v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
// pqr
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
qPos = v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
// stu
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
tPos = v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
// vwx
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
wPos = v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
// E
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(6); DrawQueue.AddElement(7);
|
|
|
|
DrawQueue.AddElement(1); DrawQueue.AddElement(7); DrawQueue.AddElement(2);
|
|
|
|
|
|
|
|
// N
|
|
|
|
DrawQueue.AddElement(3); DrawQueue.AddElement(2); DrawQueue.AddElement(8);
|
|
|
|
DrawQueue.AddElement(3); DrawQueue.AddElement(8); DrawQueue.AddElement(9);
|
|
|
|
|
|
|
|
// W
|
|
|
|
DrawQueue.AddElement(11); DrawQueue.AddElement(0); DrawQueue.AddElement(3);
|
|
|
|
DrawQueue.AddElement(11); DrawQueue.AddElement(3); DrawQueue.AddElement(10);
|
|
|
|
|
|
|
|
// S
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(5); DrawQueue.AddElement(1);
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(1); DrawQueue.AddElement(0);
|
|
|
|
|
|
|
|
// NEE
|
|
|
|
DrawQueue.AddElement(2); DrawQueue.AddElement(7); DrawQueue.AddElement(18);
|
|
|
|
DrawQueue.AddElement(2); DrawQueue.AddElement(18); DrawQueue.AddElement(19);
|
|
|
|
// NNE
|
|
|
|
DrawQueue.AddElement(2); DrawQueue.AddElement(19); DrawQueue.AddElement(20);
|
|
|
|
DrawQueue.AddElement(2); DrawQueue.AddElement(20); DrawQueue.AddElement(8);
|
|
|
|
|
|
|
|
// NNW
|
|
|
|
DrawQueue.AddElement(22); DrawQueue.AddElement(3); DrawQueue.AddElement(19);
|
|
|
|
DrawQueue.AddElement(22); DrawQueue.AddElement(19); DrawQueue.AddElement(21);
|
|
|
|
// NWW
|
|
|
|
DrawQueue.AddElement(10); DrawQueue.AddElement(3); DrawQueue.AddElement(22);
|
|
|
|
DrawQueue.AddElement(10); DrawQueue.AddElement(22); DrawQueue.AddElement(23);
|
|
|
|
|
|
|
|
// SWW
|
|
|
|
DrawQueue.AddElement(12); DrawQueue.AddElement(13); DrawQueue.AddElement(0);
|
|
|
|
DrawQueue.AddElement(12); DrawQueue.AddElement(0); DrawQueue.AddElement(11);
|
|
|
|
// SSW
|
|
|
|
DrawQueue.AddElement(14); DrawQueue.AddElement(4); DrawQueue.AddElement(0);
|
|
|
|
DrawQueue.AddElement(14); DrawQueue.AddElement(0); DrawQueue.AddElement(13);
|
|
|
|
|
|
|
|
// NE
|
|
|
|
|
|
|
|
int resolution = GetRoundingResolution(radius, 0.5f * MathF.PI);
|
|
|
|
int previous = 18, current = 24;
|
|
|
|
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = MathF.Cos(theta) * radius;
|
|
|
|
float yoff = MathF.Sin(theta) * radius;
|
|
|
|
|
|
|
|
v.Position = tPos + new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
DrawQueue.AddElement(19); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(19); DrawQueue.AddElement(previous); DrawQueue.AddElement(20);
|
|
|
|
|
|
|
|
// NW
|
|
|
|
|
|
|
|
previous = 21;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = -MathF.Sin(theta) * radius;
|
|
|
|
float yoff = MathF.Cos(theta) * radius;
|
|
|
|
|
|
|
|
v.Position = wPos + new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
DrawQueue.AddElement(22); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(22); DrawQueue.AddElement(previous); DrawQueue.AddElement(23);
|
|
|
|
|
|
|
|
// SW
|
|
|
|
|
|
|
|
previous = 12;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = -MathF.Cos(theta) * radius;
|
|
|
|
float yoff = -MathF.Sin(theta) * radius;
|
|
|
|
|
|
|
|
v.Position = nPos + new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
DrawQueue.AddElement(23); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(23); DrawQueue.AddElement(previous); DrawQueue.AddElement(14);
|
|
|
|
|
|
|
|
// SE
|
|
|
|
|
|
|
|
previous = 15;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = -MathF.Sin(theta) * radius;
|
|
|
|
float yoff = MathF.Cos(theta) * radius;
|
|
|
|
|
|
|
|
v.Position = qPos + new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
DrawQueue.AddElement(16); DrawQueue.AddElement(previous); DrawQueue.AddElement((previous = current++));
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(16); DrawQueue.AddElement(previous); DrawQueue.AddElement(17);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void GenerateRectangleStripWide(in QuikRectangle rectangle, float radius)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
l---k
|
|
|
|
| N |
|
|
|
|
i---j
|
|
|
|
p---o h---g
|
|
|
|
| W | | E |
|
|
|
|
m---n e---f
|
|
|
|
d---c
|
|
|
|
| S |
|
|
|
|
a---b
|
|
|
|
|
|
|
|
a b c d e f g h i j
|
|
|
|
00: 0 1 2 3 4 5 6 7 8 9
|
|
|
|
k l m n o p q r s t
|
|
|
|
10: 0 1 2 3 4 5
|
|
|
|
*/
|
|
|
|
|
|
|
|
QuikVertex v = StrokeVertex;
|
|
|
|
float stroke = Style.StrokeWidth ?? 1.0f;
|
|
|
|
float innerRadius = radius - stroke;
|
|
|
|
DrawQueue.RestoreOffset();
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Bottom);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Bottom + stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Bottom + stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - stroke, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - stroke, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Top - stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Top - stroke);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Right - radius, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + radius, rectangle.Top);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + stroke, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left + stroke, rectangle.Top - radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = new QuikVec2(rectangle.Left, rectangle.Bottom + radius);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
// S
|
|
|
|
DrawQueue.AddElement(0); DrawQueue.AddElement(1); DrawQueue.AddElement(2);
|
|
|
|
DrawQueue.AddElement(0); DrawQueue.AddElement(2); DrawQueue.AddElement(3);
|
|
|
|
// E
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(5); DrawQueue.AddElement(6);
|
|
|
|
DrawQueue.AddElement(4); DrawQueue.AddElement(6); DrawQueue.AddElement(7);
|
|
|
|
// N
|
|
|
|
DrawQueue.AddElement(8); DrawQueue.AddElement(9); DrawQueue.AddElement(10);
|
|
|
|
DrawQueue.AddElement(8); DrawQueue.AddElement(10); DrawQueue.AddElement(11);
|
|
|
|
// W
|
|
|
|
DrawQueue.AddElement(12); DrawQueue.AddElement(13); DrawQueue.AddElement(14);
|
|
|
|
DrawQueue.AddElement(12); DrawQueue.AddElement(14); DrawQueue.AddElement(15);
|
|
|
|
|
|
|
|
// Draw NE arc.
|
|
|
|
int resolution = GetRoundingResolution(radius, 0.5f * MathF.PI);
|
|
|
|
int current = 16;
|
|
|
|
|
|
|
|
QuikVec2 center = new QuikVec2(rectangle.Right - radius, rectangle.Top - radius);
|
|
|
|
int s1 = 7, s2 = 6;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = MathF.Cos(theta);
|
|
|
|
float yoff = MathF.Sin(theta);
|
|
|
|
|
|
|
|
v.Position = center + radius * new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = center + innerRadius * new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 0);
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 1);
|
|
|
|
|
|
|
|
s1 = current; s2 = current + 1;
|
|
|
|
current += 2;
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(10);
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(9);
|
|
|
|
|
|
|
|
// Draw NW arc
|
|
|
|
center = new QuikVec2(rectangle.Left + radius, rectangle.Top - radius);
|
|
|
|
s1 = 8; s2 = 11;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = -MathF.Sin(theta);
|
|
|
|
float yoff = MathF.Cos(theta);
|
|
|
|
|
|
|
|
v.Position = center + radius * new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = center + innerRadius * new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 0);
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 1);
|
|
|
|
|
|
|
|
s1 = current; s2 = current + 1;
|
|
|
|
current += 2;
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(15);
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(14);
|
|
|
|
|
|
|
|
// Draw SW arc
|
|
|
|
center = new QuikVec2(rectangle.Left + radius, rectangle.Bottom + radius);
|
|
|
|
s1 = 13; s2 = 12;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = -MathF.Cos(theta);
|
|
|
|
float yoff = -MathF.Sin(theta);
|
|
|
|
|
|
|
|
v.Position = center + radius * new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = center + innerRadius * new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 0);
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 1);
|
|
|
|
|
|
|
|
s1 = current; s2 = current + 1;
|
|
|
|
current += 2;
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(0);
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(3);
|
|
|
|
|
|
|
|
// Draw SW arc
|
|
|
|
center = new QuikVec2(rectangle.Right - radius, rectangle.Bottom + radius);
|
|
|
|
s1 = 2; s2 = 1;
|
|
|
|
for (int i = 0; i < resolution - 1; i++)
|
|
|
|
{
|
|
|
|
float theta = (i + 1.0f) / (resolution + 1);
|
|
|
|
float xoff = MathF.Sin(theta);
|
|
|
|
float yoff = -MathF.Cos(theta);
|
|
|
|
|
|
|
|
v.Position = center + radius * new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
v.Position = center + innerRadius * new QuikVec2(xoff, yoff);
|
|
|
|
DrawQueue.AddVertex(v);
|
|
|
|
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 0);
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(current + 1);
|
|
|
|
|
|
|
|
s1 = current; s2 = current + 1;
|
|
|
|
current += 2;
|
|
|
|
}
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(5);
|
|
|
|
DrawQueue.AddElement(s1); DrawQueue.AddElement(s2); DrawQueue.AddElement(4);
|
|
|
|
}
|
|
|
|
|
2023-06-23 21:56:07 +02:00
|
|
|
private struct LineInfo
|
|
|
|
{
|
|
|
|
public int BaseOffset { get; }
|
|
|
|
public int StartPositive { get; }
|
|
|
|
public int StartNegative { get; }
|
|
|
|
public int EndPositive { get; }
|
|
|
|
public int EndNegative { get; }
|
|
|
|
|
|
|
|
public LineInfo(int baseOffset, int startPositive, int startNegative, int endPositive, int endNegative)
|
|
|
|
{
|
|
|
|
BaseOffset = baseOffset;
|
|
|
|
StartPositive = startPositive;
|
|
|
|
StartNegative = startNegative;
|
|
|
|
EndPositive = endPositive;
|
|
|
|
EndNegative = endNegative;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|