Implement rectangle rendering.
This commit is contained in:
parent
16bb3f41a7
commit
72cad718cb
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
public QuikFillStyle DefaultFill { get; set; } = new QuikFillStyle()
|
public QuikFillStyle DefaultFill { get; set; } = new QuikFillStyle()
|
||||||
{
|
{
|
||||||
Color = new QuikColor(0x101010FF)
|
Color = new QuikColor(0xA0A0A0FF)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Quik
|
namespace Quik
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A 2 dimensional Vector.
|
/// A 2 dimensional Vector.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("({X}, {Y})")]
|
||||||
public struct QuikVec2
|
public struct QuikVec2
|
||||||
{
|
{
|
||||||
public float X;
|
public float X;
|
||||||
@ -89,6 +92,7 @@ namespace Quik
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A RGBA color value.
|
/// A RGBA color value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("({R}, {G}, {B}, {A})")]
|
||||||
public struct QuikColor
|
public struct QuikColor
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -118,18 +122,20 @@ namespace Quik
|
|||||||
|
|
||||||
public QuikColor(byte r, byte g, byte b) : this(r, g, b, 1) { }
|
public QuikColor(byte r, byte g, byte b) : this(r, g, b, 1) { }
|
||||||
|
|
||||||
public QuikColor(int hexCode)
|
public QuikColor(uint hexCode)
|
||||||
{
|
{
|
||||||
R = (byte)((hexCode >> 24) & 0xFF);
|
R = (byte)((hexCode >> 24) & 0xFF);
|
||||||
G = (byte)((hexCode >> 16) & 0xFF);
|
G = (byte)((hexCode >> 16) & 0xFF);
|
||||||
B = (byte)((hexCode >> 8 ) & 0xFF);
|
B = (byte)((hexCode >> 8 ) & 0xFF);
|
||||||
A = (byte)((hexCode >> 0 ) & 0xFF);
|
A = (byte)((hexCode >> 0 ) & 0xFF);
|
||||||
}
|
}
|
||||||
|
public QuikColor(int hexCode) : this((uint)hexCode) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A bezier curve segment.
|
/// A bezier curve segment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Start} -- {ControlA} -- {ControlB} -- {End}")]
|
||||||
public struct QuikBezier
|
public struct QuikBezier
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -217,6 +223,7 @@ namespace Quik
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A line segment.
|
/// A line segment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{Start} -- {End}")]
|
||||||
public struct QuikLine
|
public struct QuikLine
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -247,22 +254,59 @@ namespace Quik
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A rectangle.
|
/// A rectangle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("({Right}, {Top}, {Left}, {Bottom})")]
|
||||||
public struct QuikRectangle
|
public struct QuikRectangle
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Rectangle minimum point.
|
|
||||||
/// </summary>
|
|
||||||
public QuikVec2 Min;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rectangle maximum point.
|
/// Rectangle maximum point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public QuikVec2 Max;
|
public QuikVec2 Max;
|
||||||
|
|
||||||
public QuikRectangle(float l, float t, float r, float b)
|
/// <summary>
|
||||||
|
/// Rectangle minimum point.
|
||||||
|
/// </summary>
|
||||||
|
public QuikVec2 Min;
|
||||||
|
|
||||||
|
public float Left
|
||||||
{
|
{
|
||||||
Min = new QuikVec2() {X = r, Y = b};
|
get => Min.X;
|
||||||
Max = new QuikVec2() {X = l, Y = t};
|
set => Min.X = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Right
|
||||||
|
{
|
||||||
|
get => Max.X;
|
||||||
|
set => Max.X = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Top
|
||||||
|
{
|
||||||
|
get => Max.Y;
|
||||||
|
set => Max.Y = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Bottom
|
||||||
|
{
|
||||||
|
get => Min.Y;
|
||||||
|
set => Min.Y = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuikVec2 Size
|
||||||
|
{
|
||||||
|
get => Max - Min;
|
||||||
|
set => Max = Min + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuikRectangle(QuikVec2 max, QuikVec2 min)
|
||||||
|
{
|
||||||
|
Max = max;
|
||||||
|
Min = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuikRectangle(float r, float t, float l, float b)
|
||||||
|
{
|
||||||
|
Max = new QuikVec2() {X = r, Y = t};
|
||||||
|
Min = new QuikVec2() {X = l, Y = b};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,6 +314,7 @@ namespace Quik
|
|||||||
/// An ellipse.
|
/// An ellipse.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>It is undefined to have an ellipse with non-orthogonal axes.</remarks>
|
/// <remarks>It is undefined to have an ellipse with non-orthogonal axes.</remarks>
|
||||||
|
[DebuggerDisplay("{Center} ellipse {AxisA}; {AxisB}")]
|
||||||
public struct QuikEllipse
|
public struct QuikEllipse
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -291,6 +336,7 @@ namespace Quik
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A triangle.
|
/// A triangle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("{A} -- {B} -- {C}")]
|
||||||
public struct QuikTriangle
|
public struct QuikTriangle
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Quik.VertexGenerator
|
namespace Quik.VertexGenerator
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a GPU vertex.
|
/// Represents a GPU vertex.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
[DebuggerDisplay("XY={Position} RGBA={Color}, UV={TextureCoordinates}")]
|
||||||
public struct QuikVertex
|
public struct QuikVertex
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -30,7 +30,7 @@ namespace Quik.VertexGenerator
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private int _vertexBufferPointer = 0;
|
private int _vertexBufferPointer = 0;
|
||||||
|
|
||||||
private float _vertexBufferUsage = 0;
|
private float _vertexUsage = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of element indices.
|
/// List of element indices.
|
||||||
@ -42,9 +42,19 @@ namespace Quik.VertexGenerator
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private int _elementBufferPointer = 0;
|
private int _elementBufferPointer = 0;
|
||||||
|
|
||||||
private float _elementBufferUsage;
|
private float _elementUsage;
|
||||||
private long _bufferUsageCounter;
|
private long _bufferUsageCounter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moving average of the vertex count.
|
||||||
|
/// </summary>
|
||||||
|
public float VertexUsage => _vertexUsage;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moving average of the element count.
|
||||||
|
/// </summary>
|
||||||
|
public float ElementUsage => _elementUsage;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a reference to the vertex buffer.
|
/// Get a reference to the vertex buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -147,11 +157,11 @@ namespace Quik.VertexGenerator
|
|||||||
int newElementSize;
|
int newElementSize;
|
||||||
|
|
||||||
_bufferUsageCounter++;
|
_bufferUsageCounter++;
|
||||||
MovingAverage(ref _vertexBufferUsage, _bufferUsageCounter, _elementBufferPointer);
|
MovingAverage(ref _vertexUsage, _bufferUsageCounter, _vertexBufferPointer);
|
||||||
MovingAverage(ref _elementBufferUsage, _bufferUsageCounter, _elementBufferPointer);
|
MovingAverage(ref _elementUsage, _bufferUsageCounter, _elementBufferPointer);
|
||||||
|
|
||||||
newVertexSize = (int)(Math.Ceiling(_vertexBufferUsage / BufferGranularity) * BufferGranularity);
|
newVertexSize = (int)(Math.Ceiling(_vertexUsage / BufferGranularity) * BufferGranularity);
|
||||||
newElementSize = (int)(Math.Ceiling(_elementBufferUsage / BufferGranularity) * BufferGranularity);
|
newElementSize = (int)(Math.Ceiling(_elementUsage / BufferGranularity) * BufferGranularity);
|
||||||
|
|
||||||
Array.Resize(ref _vertexBuffer, newVertexSize);
|
Array.Resize(ref _vertexBuffer, newVertexSize);
|
||||||
Array.Resize(ref _elementBuffer, newElementSize);
|
Array.Resize(ref _elementBuffer, newElementSize);
|
||||||
@ -160,39 +170,78 @@ namespace Quik.VertexGenerator
|
|||||||
_elementBufferPointer = 0;
|
_elementBufferPointer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private QuikDrawCall _call;
|
||||||
|
|
||||||
|
public event VertexGeneratorCommandHandler HandleCommand;
|
||||||
|
|
||||||
|
protected virtual void OnHandleCommand(QuikVertexGenerator generator, QuikCommand command, ref QuikDrawCall? call)
|
||||||
|
{
|
||||||
|
HandleCommand?.Invoke(generator, command, ref call);
|
||||||
|
}
|
||||||
|
|
||||||
public QuikDrawCall? ConsumeCommand(QuikCommand command)
|
public QuikDrawCall? ConsumeCommand(QuikCommand command)
|
||||||
{
|
{
|
||||||
QuikDrawCall call = new QuikDrawCall()
|
_call.Target = _renderStencilMask ? QuikRenderTarget.Stencil : QuikRenderTarget.Color;
|
||||||
{
|
|
||||||
Target = _renderStencilMask ? QuikRenderTarget.Stencil : QuikRenderTarget.Color
|
QuikDrawCall call = _call;
|
||||||
};
|
|
||||||
|
|
||||||
switch (command.Type)
|
switch (command.Type)
|
||||||
{
|
{
|
||||||
|
case QuikCommandType.Mask:
|
||||||
|
_call.Bounds = ((QuikCommandMask)command).Bounds;
|
||||||
|
break;
|
||||||
case QuikCommandType.StencilMaskClear:
|
case QuikCommandType.StencilMaskClear:
|
||||||
call.ClearStencil = true;
|
_call.ClearStencil = true;
|
||||||
break;
|
break;
|
||||||
case QuikCommandType.StencilMaskBegin:
|
case QuikCommandType.StencilMaskBegin:
|
||||||
_renderStencilMask = true;
|
_renderStencilMask = true;
|
||||||
call.Target = QuikRenderTarget.Stencil;
|
_call.Target = QuikRenderTarget.Stencil;
|
||||||
break;
|
break;
|
||||||
case QuikCommandType.StencilMaskEnd:
|
case QuikCommandType.StencilMaskEnd:
|
||||||
_renderStencilMask = false;
|
_renderStencilMask = false;
|
||||||
call.Target = QuikRenderTarget.Color;
|
_call.Target = QuikRenderTarget.Color;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QuikCommandType.Line:
|
case QuikCommandType.Line:
|
||||||
RenderLine(ref call, command as QuikCommandLine);
|
RenderLine(ref call, command as QuikCommandLine);
|
||||||
return call;
|
goto exit_with_call;
|
||||||
case QuikCommandType.Lines:
|
case QuikCommandType.Lines:
|
||||||
RenderLine(ref call, command as QuikCommandLines);
|
RenderLine(ref call, command as QuikCommandLines);
|
||||||
return call;
|
goto exit_with_call;
|
||||||
case QuikCommandType.Bezier:
|
case QuikCommandType.Bezier:
|
||||||
RenderBezier(ref call, command as QuikCommandBezier);
|
RenderBezier(ref _call, command as QuikCommandBezier);
|
||||||
return call;
|
goto exit_with_call;
|
||||||
|
|
||||||
|
case QuikCommandType.Rectangle:
|
||||||
|
RenderRectangles(ref call, command as QuikCommandRectangle);
|
||||||
|
goto exit_with_call;
|
||||||
|
case QuikCommandType.Rectangles:
|
||||||
|
RenderRectangles(ref call, command as QuikCommandRectangles);
|
||||||
|
goto exit_with_call;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
QuikDrawCall? subcall = null;
|
||||||
|
OnHandleCommand(this, command, ref subcall);
|
||||||
|
if (subcall.HasValue)
|
||||||
|
{
|
||||||
|
call = subcall.Value;
|
||||||
|
goto exit_with_call;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto exit_without_call;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
exit_without_call:
|
||||||
return null;
|
return null;
|
||||||
|
exit_with_call:
|
||||||
|
_call.ClearStencil = false;
|
||||||
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region Lines & Beziers
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates a basic line segment.
|
/// Generates a basic line segment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -237,13 +286,12 @@ namespace Quik.VertexGenerator
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the rounding resolution for a line segment.
|
/// Gets the rounding resolution for a line segment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="width">The width of the line.</param>
|
/// <param name="radius">The width of the line.</param>
|
||||||
/// <param name="arc">The angle of the cap or joint arc.</param>
|
/// <param name="arc">The angle of the cap or joint arc.</param>
|
||||||
/// <returns>The rounding resolution.</returns>
|
/// <returns>The rounding resolution.</returns>
|
||||||
private int GetRoundingResolution(float width, float arc)
|
private int GetRoundingResolution(float radius, float arc)
|
||||||
{
|
{
|
||||||
int endCapResolution = (int) Math.Ceiling(arc * width * CurveGranularity);
|
return (int) Math.Ceiling(arc * radius * CurveGranularity);
|
||||||
return endCapResolution;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -727,8 +775,622 @@ namespace Quik.VertexGenerator
|
|||||||
endNegativeIndex = (short) (_vertexBufferPointer - 1);
|
endNegativeIndex = (short) (_vertexBufferPointer - 1);
|
||||||
endPositiveIndex = (short) (_vertexBufferPointer - 2);
|
endPositiveIndex = (short) (_vertexBufferPointer - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Rectangles
|
||||||
|
|
||||||
|
private void RenderRectangles(ref QuikDrawCall call, QuikCommandRectangle rectangle)
|
||||||
|
{
|
||||||
|
QuikStrokeStyle stroke = rectangle.StrokeStyle ?? Context.DefaultStroke;
|
||||||
|
QuikFillStyle fill = rectangle.FillStyle ?? Context.DefaultFill;
|
||||||
|
|
||||||
|
short start = (short) _elementBufferPointer;
|
||||||
|
|
||||||
|
GenerateRectangle(rectangle.Rectangle, stroke, fill, rectangle.CornerRadius);
|
||||||
|
|
||||||
|
call.Offset = (short) (start * 2);
|
||||||
|
call.Count = (short) (_elementBufferPointer - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateRectangle(QuikRectangle rectangle, QuikStrokeStyle stroke, QuikFillStyle fill, float cornerRadius)
|
||||||
|
{
|
||||||
|
float semiStroke = 0.5f * stroke.Width;
|
||||||
|
|
||||||
|
if (cornerRadius == 0)
|
||||||
|
{
|
||||||
|
// If there is no stroke radius, draw a simpler rectangle.
|
||||||
|
if (stroke.Width == 0)
|
||||||
|
{
|
||||||
|
// If there is no border, just 4 points is enough.
|
||||||
|
|
||||||
|
GenerateRectangleSimple(rectangle, fill);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If there is a border, take it into account.
|
||||||
|
|
||||||
|
QuikRectangle innerRectangle = rectangle;
|
||||||
|
innerRectangle.Left += semiStroke;
|
||||||
|
innerRectangle.Top -= semiStroke;
|
||||||
|
innerRectangle.Right -= semiStroke;
|
||||||
|
innerRectangle.Bottom += semiStroke;
|
||||||
|
|
||||||
|
GenerateRectangleSimple(innerRectangle, fill);
|
||||||
|
GenerateRectangleBorderSimple(rectangle, stroke);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float innerRadius = cornerRadius - semiStroke;
|
||||||
|
|
||||||
|
if (innerRadius <= 0)
|
||||||
|
{
|
||||||
|
QuikRectangle innerRectangle = new QuikRectangle(
|
||||||
|
rectangle.Right - semiStroke,
|
||||||
|
rectangle.Top - semiStroke,
|
||||||
|
rectangle.Left + semiStroke,
|
||||||
|
rectangle.Bottom + semiStroke
|
||||||
|
);
|
||||||
|
|
||||||
|
GenerateRectangleSimple(innerRectangle, fill);
|
||||||
|
GenerateRectangleBorderNarrow(rectangle, stroke, cornerRadius);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Generate the inner rectangle.
|
||||||
|
QuikRectangle innerRectangle = new QuikRectangle(
|
||||||
|
rectangle.Right - semiStroke * 0.95f,
|
||||||
|
rectangle.Top - semiStroke * 0.95f,
|
||||||
|
rectangle.Left + semiStroke * 0.95f,
|
||||||
|
rectangle.Bottom + semiStroke * 0.95f
|
||||||
|
);
|
||||||
|
GenerateRectangleRound(innerRectangle, fill, innerRadius);
|
||||||
|
|
||||||
|
if (stroke.Width > 0)
|
||||||
|
{
|
||||||
|
GenerateRectangleBorderWide(rectangle, stroke, cornerRadius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateRectangleBorderNarrow(
|
||||||
|
QuikRectangle rectangle,
|
||||||
|
QuikStrokeStyle stroke,
|
||||||
|
float cornerRadius)
|
||||||
|
{
|
||||||
|
float semiStroke = 0.5f * stroke.Width;
|
||||||
|
float inset = cornerRadius - semiStroke;
|
||||||
|
short start = (short) _vertexBufferPointer;
|
||||||
|
|
||||||
|
QuikVertex baseVertex = new QuikVertex() {Color = stroke.Color};
|
||||||
|
QuikVertex a = baseVertex, b = baseVertex, c = baseVertex, d = baseVertex,
|
||||||
|
e = baseVertex, f = baseVertex, g = baseVertex, h = baseVertex,
|
||||||
|
i = baseVertex, j = baseVertex, k = baseVertex, l = baseVertex,
|
||||||
|
q1 = baseVertex, q2 = baseVertex, q3 = baseVertex, q4 = baseVertex;
|
||||||
|
|
||||||
|
a.Position = new QuikVec2(rectangle.Left + semiStroke, rectangle.Bottom + semiStroke);
|
||||||
|
b.Position = new QuikVec2(rectangle.Right - semiStroke, rectangle.Bottom + semiStroke);
|
||||||
|
c.Position = new QuikVec2(rectangle.Right - semiStroke, rectangle.Top - semiStroke);
|
||||||
|
d.Position = new QuikVec2(rectangle.Left + semiStroke, rectangle.Top - semiStroke);
|
||||||
|
|
||||||
|
q1.Position = new QuikVec2(rectangle.Left + inset, rectangle.Bottom + inset);
|
||||||
|
q2.Position = new QuikVec2(rectangle.Right - inset, rectangle.Bottom + inset);
|
||||||
|
q3.Position = new QuikVec2(rectangle.Right - inset, rectangle.Top - inset);
|
||||||
|
q4.Position = new QuikVec2(rectangle.Left + inset, rectangle.Top - inset);
|
||||||
|
|
||||||
|
e.Position = new QuikVec2(q1.Position.X, rectangle.Bottom - semiStroke);
|
||||||
|
f.Position = new QuikVec2(q2.Position.X, rectangle.Bottom - semiStroke);
|
||||||
|
g.Position = new QuikVec2(rectangle.Right + semiStroke, q2.Position.Y);
|
||||||
|
h.Position = new QuikVec2(rectangle.Right + semiStroke, q3.Position.Y);
|
||||||
|
i.Position = new QuikVec2(q3.Position.X, rectangle.Top + semiStroke);
|
||||||
|
j.Position = new QuikVec2(q4.Position.X, rectangle.Top + semiStroke);
|
||||||
|
k.Position = new QuikVec2(rectangle.Left - semiStroke, q4.Position.Y);
|
||||||
|
l.Position = new QuikVec2(rectangle.Left - semiStroke, q1.Position.Y);
|
||||||
|
|
||||||
|
AddVertex(a, b, c, d, e, f, g, h, i, j, k, l, q1, q2, q3, q4);
|
||||||
|
AddElement(
|
||||||
|
(short) (start + 4), (short) (start + 5), (short) (start + 13),
|
||||||
|
(short) (start + 4), (short) (start + 13), (short) (start + 12),
|
||||||
|
(short) (start + 12), (short) (start + 13), (short) (start + 1),
|
||||||
|
(short) (start + 12), (short) (start + 1), (short) (start + 0),
|
||||||
|
|
||||||
|
(short) (start + 13), (short) (start + 6), (short) (start + 7),
|
||||||
|
(short) (start + 13), (short) (start + 7), (short) (start + 14),
|
||||||
|
(short) (start + 13), (short) (start + 14), (short) (start + 2),
|
||||||
|
(short) (start + 13), (short) (start + 2), (short) (start + 1),
|
||||||
|
|
||||||
|
(short) (start + 3), (short) (start + 2), (short) (start + 14),
|
||||||
|
(short) (start + 3), (short) (start + 14), (short) (start + 15),
|
||||||
|
(short) (start + 15), (short) (start + 14), (short) (start + 8),
|
||||||
|
(short) (start + 15), (short) (start + 8), (short) (start + 9),
|
||||||
|
|
||||||
|
(short) (start + 0), (short) (start + 3), (short) (start + 15),
|
||||||
|
(short) (start + 0), (short) (start + 15), (short) (start + 12),
|
||||||
|
(short) (start + 12), (short) (start + 15), (short) (start + 10),
|
||||||
|
(short) (start + 12), (short) (start + 10), (short) (start + 11)
|
||||||
|
);
|
||||||
|
|
||||||
|
int resolution = GetRoundingResolution(cornerRadius, 0.5f * MathF.PI);
|
||||||
|
short last, next;
|
||||||
|
|
||||||
|
last = (short) (start + 7);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
QuikVertex vertex = baseVertex;
|
||||||
|
vertex.Position = q3.Position + cornerRadius * new QuikVec2(MathF.Cos(angle), MathF.Sin(angle));
|
||||||
|
|
||||||
|
next = (short) _vertexBufferPointer;
|
||||||
|
AddVertex(vertex);
|
||||||
|
AddElement((short)(start + 14), last, next);
|
||||||
|
last = next;
|
||||||
|
}
|
||||||
|
AddElement((short)(start + 14), last, (short)(start + 8));
|
||||||
|
|
||||||
|
last = (short) (start + 9);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
QuikVertex vertex = baseVertex;
|
||||||
|
vertex.Position = q4.Position + cornerRadius * new QuikVec2(-MathF.Sin(angle), MathF.Cos(angle));
|
||||||
|
|
||||||
|
next = (short) _vertexBufferPointer;
|
||||||
|
AddVertex(vertex);
|
||||||
|
AddElement((short)(start + 15), last, next);
|
||||||
|
last = next;
|
||||||
|
}
|
||||||
|
AddElement((short)(start + 15), last, (short)(start + 10));
|
||||||
|
|
||||||
|
last = (short) (start + 11);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
QuikVertex vertex = baseVertex;
|
||||||
|
vertex.Position = q1.Position + cornerRadius * new QuikVec2(-MathF.Cos(angle), -MathF.Sin(angle));
|
||||||
|
|
||||||
|
next = (short) _vertexBufferPointer;
|
||||||
|
AddVertex(vertex);
|
||||||
|
AddElement((short)(start + 12), last, next);
|
||||||
|
last = next;
|
||||||
|
}
|
||||||
|
AddElement((short)(start + 12), last, (short)(start + 4));
|
||||||
|
|
||||||
|
last = (short) (start + 5);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
QuikVertex vertex = baseVertex;
|
||||||
|
vertex.Position = q2.Position + cornerRadius * new QuikVec2(MathF.Sin(angle), -MathF.Cos(angle));
|
||||||
|
|
||||||
|
next = (short) _vertexBufferPointer;
|
||||||
|
AddVertex(vertex);
|
||||||
|
AddElement((short)(start + 13), last, next);
|
||||||
|
last = next;
|
||||||
|
}
|
||||||
|
AddElement((short)(start + 13), last, (short)(start + 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateRectangleBorderWide(QuikRectangle rectangle, QuikStrokeStyle stroke, float cornerRadius)
|
||||||
|
{
|
||||||
|
float semiStroke = 0.5f * stroke.Width;
|
||||||
|
float outerRadius = cornerRadius + semiStroke;
|
||||||
|
float innerRadius = cornerRadius - semiStroke;
|
||||||
|
short start = (short) _vertexBufferPointer;
|
||||||
|
|
||||||
|
// The corner foci.
|
||||||
|
QuikVec2 q1 = new QuikVec2(rectangle.Min.X + cornerRadius, rectangle.Min.Y + cornerRadius);
|
||||||
|
QuikVec2 q2 = new QuikVec2(rectangle.Max.X - cornerRadius, rectangle.Min.Y + cornerRadius);
|
||||||
|
QuikVec2 q3 = new QuikVec2(rectangle.Max.X - cornerRadius, rectangle.Max.Y - cornerRadius);
|
||||||
|
QuikVec2 q4 = new QuikVec2(rectangle.Min.X + cornerRadius, rectangle.Max.Y - cornerRadius);
|
||||||
|
|
||||||
|
QuikVertex baseVertex = new QuikVertex() {Color = stroke.Color};
|
||||||
|
QuikVertex a = baseVertex, b = baseVertex, c = baseVertex, d = baseVertex,
|
||||||
|
e = baseVertex, f = baseVertex, g = baseVertex, h = baseVertex,
|
||||||
|
i = baseVertex, j = baseVertex, k = baseVertex, l = baseVertex,
|
||||||
|
m = baseVertex, n = baseVertex, o = baseVertex, p = baseVertex;
|
||||||
|
|
||||||
|
a.Position = new QuikVec2(q1.X, q1.Y - innerRadius);
|
||||||
|
b.Position = new QuikVec2(q2.X, q2.Y - innerRadius);
|
||||||
|
c.Position = new QuikVec2(q2.X + innerRadius, q2.Y);
|
||||||
|
d.Position = new QuikVec2(q3.X + innerRadius, q3.Y);
|
||||||
|
e.Position = new QuikVec2(q3.X, q3.Y + innerRadius);
|
||||||
|
f.Position = new QuikVec2(q4.X, q4.Y + innerRadius);
|
||||||
|
g.Position = new QuikVec2(q4.X - innerRadius, q4.Y);
|
||||||
|
h.Position = new QuikVec2(q1.X - innerRadius, q1.Y);
|
||||||
|
|
||||||
|
i.Position = new QuikVec2(q1.X, rectangle.Bottom - semiStroke);
|
||||||
|
j.Position = new QuikVec2(q2.X, rectangle.Bottom - semiStroke);
|
||||||
|
k.Position = new QuikVec2(rectangle.Right + semiStroke, q2.Y);
|
||||||
|
l.Position = new QuikVec2(rectangle.Right + semiStroke, q3.Y);
|
||||||
|
m.Position = new QuikVec2(q3.X, rectangle.Top + semiStroke);
|
||||||
|
n.Position = new QuikVec2(q4.X, rectangle.Top + semiStroke);
|
||||||
|
o.Position = new QuikVec2(rectangle.Left - semiStroke, q4.Y);
|
||||||
|
p.Position = new QuikVec2(rectangle.Left - semiStroke, q1.Y);
|
||||||
|
|
||||||
|
AddVertex(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
|
||||||
|
AddElement(
|
||||||
|
(short)(start + 8), (short)(start + 1), (short)(start + 0),
|
||||||
|
(short)(start + 8), (short)(start + 9), (short)(start + 1),
|
||||||
|
(short)(start + 2), (short)(start + 11), (short)(start + 3),
|
||||||
|
(short)(start + 2), (short)(start + 10), (short)(start + 11),
|
||||||
|
(short)(start + 5), (short)(start + 12), (short)(start + 13),
|
||||||
|
(short)(start + 5), (short)(start + 4), (short)(start + 12),
|
||||||
|
(short)(start + 15), (short)(start + 6), (short)(start + 14),
|
||||||
|
(short)(start + 15), (short)(start + 7), (short)(start + 6)
|
||||||
|
);
|
||||||
|
|
||||||
|
int resolution = GetRoundingResolution(outerRadius, 0.5f * MathF.PI);
|
||||||
|
short last0, last1;
|
||||||
|
short next0, next1;
|
||||||
|
|
||||||
|
last0 = (short) (start + 3);
|
||||||
|
last1 = (short) (start + 11);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
QuikVec2 normal = new QuikVec2(MathF.Cos(angle), MathF.Sin(angle));
|
||||||
|
QuikVertex v0 = baseVertex, v1 = baseVertex;
|
||||||
|
|
||||||
|
v0.Position = q3 + innerRadius * normal;
|
||||||
|
v1.Position = q3 + outerRadius * normal;
|
||||||
|
|
||||||
|
next0 = (short) (_vertexBufferPointer + 0);
|
||||||
|
next1 = (short) (_vertexBufferPointer + 1);
|
||||||
|
|
||||||
|
AddVertex(v0, v1);
|
||||||
|
AddElement(
|
||||||
|
last0, next1, next0,
|
||||||
|
last0, last1, next1);
|
||||||
|
|
||||||
|
last0 = next0;
|
||||||
|
last1 = next1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(
|
||||||
|
last0, (short)(start + 12), (short)(start + 4),
|
||||||
|
last0, last1, (short)(start + 12)
|
||||||
|
);
|
||||||
|
|
||||||
|
last0 = (short) (start + 5);
|
||||||
|
last1 = (short) (start + 13);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
QuikVec2 normal = new QuikVec2(-MathF.Sin(angle), MathF.Cos(angle));
|
||||||
|
QuikVertex v0 = baseVertex, v1 = baseVertex;
|
||||||
|
|
||||||
|
v0.Position = q4 + innerRadius * normal;
|
||||||
|
v1.Position = q4 + outerRadius * normal;
|
||||||
|
|
||||||
|
next0 = (short) (_vertexBufferPointer + 0);
|
||||||
|
next1 = (short) (_vertexBufferPointer + 1);
|
||||||
|
|
||||||
|
AddVertex(v0, v1);
|
||||||
|
AddElement(
|
||||||
|
last0, next1, next0,
|
||||||
|
last0, last1, next1);
|
||||||
|
|
||||||
|
last0 = next0;
|
||||||
|
last1 = next1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(
|
||||||
|
last0, (short)(start + 14), (short)(start + 6),
|
||||||
|
last0, last1, (short)(start + 14)
|
||||||
|
);
|
||||||
|
|
||||||
|
last0 = (short) (start + 7);
|
||||||
|
last1 = (short) (start + 15);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
QuikVec2 normal = new QuikVec2(-MathF.Cos(angle), -MathF.Sin(angle));
|
||||||
|
QuikVertex v0 = baseVertex, v1 = baseVertex;
|
||||||
|
|
||||||
|
v0.Position = q1 + innerRadius * normal;
|
||||||
|
v1.Position = q1 + outerRadius * normal;
|
||||||
|
|
||||||
|
next0 = (short) (_vertexBufferPointer + 0);
|
||||||
|
next1 = (short) (_vertexBufferPointer + 1);
|
||||||
|
|
||||||
|
AddVertex(v0, v1);
|
||||||
|
AddElement(
|
||||||
|
last0, next1, next0,
|
||||||
|
last0, last1, next1);
|
||||||
|
|
||||||
|
last0 = next0;
|
||||||
|
last1 = next1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(
|
||||||
|
last0, (short)(start + 8), (short)(start + 0),
|
||||||
|
last0, last1, (short)(start + 8)
|
||||||
|
);
|
||||||
|
|
||||||
|
last0 = (short) (start + 1);
|
||||||
|
last1 = (short) (start + 9);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
QuikVec2 normal = new QuikVec2(MathF.Sin(angle), -MathF.Cos(angle));
|
||||||
|
QuikVertex v0 = baseVertex, v1 = baseVertex;
|
||||||
|
|
||||||
|
v0.Position = q2 + innerRadius * normal;
|
||||||
|
v1.Position = q2 + outerRadius * normal;
|
||||||
|
|
||||||
|
next0 = (short) (_vertexBufferPointer + 0);
|
||||||
|
next1 = (short) (_vertexBufferPointer + 1);
|
||||||
|
|
||||||
|
AddVertex(v0, v1);
|
||||||
|
AddElement(
|
||||||
|
last0, next1, next0,
|
||||||
|
last0, last1, next1);
|
||||||
|
|
||||||
|
last0 = next0;
|
||||||
|
last1 = next1;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(
|
||||||
|
last0, (short)(start + 10), (short)(start + 2),
|
||||||
|
last0, last1, (short)(start + 10)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateRectangleRound(
|
||||||
|
QuikRectangle rectangle,
|
||||||
|
QuikFillStyle fill,
|
||||||
|
float radius)
|
||||||
|
{
|
||||||
|
short baseElement = (short) _vertexBufferPointer;
|
||||||
|
QuikVertex baseVertex = new QuikVertex() {Color = fill.Color};
|
||||||
|
QuikVertex a = baseVertex,
|
||||||
|
b = baseVertex,
|
||||||
|
c = baseVertex,
|
||||||
|
d = baseVertex,
|
||||||
|
e = baseVertex,
|
||||||
|
f = baseVertex,
|
||||||
|
g = baseVertex,
|
||||||
|
h = baseVertex,
|
||||||
|
i = baseVertex,
|
||||||
|
j = baseVertex,
|
||||||
|
k = baseVertex,
|
||||||
|
l = baseVertex;
|
||||||
|
|
||||||
|
// Generate base 5 patches.
|
||||||
|
|
||||||
|
a.Position = new QuikVec2(
|
||||||
|
rectangle.Left + radius,
|
||||||
|
rectangle.Bottom + radius);
|
||||||
|
b.Position = new QuikVec2(
|
||||||
|
rectangle.Right - radius,
|
||||||
|
rectangle.Bottom + radius);
|
||||||
|
c.Position = new QuikVec2(
|
||||||
|
rectangle.Right - radius,
|
||||||
|
rectangle.Top - radius);
|
||||||
|
d.Position = new QuikVec2(
|
||||||
|
rectangle.Left + radius,
|
||||||
|
rectangle.Top - radius);
|
||||||
|
e.Position = new QuikVec2(
|
||||||
|
rectangle.Left + radius,
|
||||||
|
rectangle.Bottom);
|
||||||
|
f.Position = new QuikVec2(
|
||||||
|
rectangle.Right - radius,
|
||||||
|
rectangle.Bottom);
|
||||||
|
g.Position = new QuikVec2(
|
||||||
|
rectangle.Right,
|
||||||
|
rectangle.Bottom + radius);
|
||||||
|
h.Position = new QuikVec2(
|
||||||
|
rectangle.Right,
|
||||||
|
rectangle.Top - radius);
|
||||||
|
i.Position = new QuikVec2(
|
||||||
|
rectangle.Right - radius,
|
||||||
|
rectangle.Top);
|
||||||
|
j.Position = new QuikVec2(
|
||||||
|
rectangle.Left + radius,
|
||||||
|
rectangle.Top);
|
||||||
|
k.Position = new QuikVec2(
|
||||||
|
rectangle.Left,
|
||||||
|
rectangle.Top - radius);
|
||||||
|
l.Position = new QuikVec2(
|
||||||
|
rectangle.Left,
|
||||||
|
rectangle.Bottom + radius);
|
||||||
|
|
||||||
|
AddVertex(a, b, c, d, e, f, g, h, i, j, k, l);
|
||||||
|
AddElement(
|
||||||
|
(short) (baseElement + 0), (short) (baseElement + 1), (short) (baseElement + 2),
|
||||||
|
(short) (baseElement + 0), (short) (baseElement + 2), (short) (baseElement + 3),
|
||||||
|
(short) (baseElement + 4), (short) (baseElement + 5), (short) (baseElement + 1),
|
||||||
|
(short) (baseElement + 4), (short) (baseElement + 1), (short) (baseElement + 0),
|
||||||
|
(short) (baseElement + 1), (short) (baseElement + 6), (short) (baseElement + 7),
|
||||||
|
(short) (baseElement + 1), (short) (baseElement + 7), (short) (baseElement + 2),
|
||||||
|
(short) (baseElement + 3), (short) (baseElement + 2), (short) (baseElement + 8),
|
||||||
|
(short) (baseElement + 3), (short) (baseElement + 8), (short) (baseElement + 9),
|
||||||
|
(short) (baseElement + 11), (short) (baseElement + 0), (short) (baseElement + 3),
|
||||||
|
(short) (baseElement + 11), (short) (baseElement + 3), (short) (baseElement + 10));
|
||||||
|
|
||||||
|
// Now generate corner patches.
|
||||||
|
|
||||||
|
int resolution = GetRoundingResolution(radius, 0.5f * MathF.PI);
|
||||||
|
short focus, last, current;
|
||||||
|
|
||||||
|
focus = (short) (baseElement + 2);
|
||||||
|
last = (short) (baseElement + 7);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
QuikVertex vertex = baseVertex;
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
vertex.Position = c.Position + radius * new QuikVec2(MathF.Cos(angle), MathF.Sin(angle));
|
||||||
|
current = (short) _vertexBufferPointer;
|
||||||
|
|
||||||
|
AddVertex(vertex);
|
||||||
|
AddElement(focus, last, current);
|
||||||
|
|
||||||
|
last = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(focus, last, (short) (baseElement + 8));
|
||||||
|
|
||||||
|
|
||||||
|
focus = (short) (baseElement + 3);
|
||||||
|
last = (short) (baseElement + 9);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
QuikVertex vertex = baseVertex;
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
vertex.Position = d.Position + radius * new QuikVec2(-MathF.Sin(angle), MathF.Cos(angle));
|
||||||
|
current = (short) _vertexBufferPointer;
|
||||||
|
|
||||||
|
AddVertex(vertex);
|
||||||
|
AddElement(focus, last, current);
|
||||||
|
|
||||||
|
last = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(focus, last, (short) (baseElement + 10));
|
||||||
|
|
||||||
|
focus = (short) (baseElement + 0);
|
||||||
|
last = (short) (baseElement + 11);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
QuikVertex vertex = baseVertex;
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
vertex.Position = a.Position + radius * new QuikVec2(-MathF.Cos(angle), -MathF.Sin(angle));
|
||||||
|
current = (short) _vertexBufferPointer;
|
||||||
|
|
||||||
|
AddVertex(vertex);
|
||||||
|
AddElement(focus, last, current);
|
||||||
|
|
||||||
|
last = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(focus, last, (short) (baseElement + 4));
|
||||||
|
|
||||||
|
focus = (short) (baseElement + 1);
|
||||||
|
last = (short) (baseElement + 5);
|
||||||
|
for (int idx = 0; idx < resolution; idx++)
|
||||||
|
{
|
||||||
|
QuikVertex vertex = baseVertex;
|
||||||
|
float angle = 0.5f * MathF.PI * (idx + 1) / (resolution + 1);
|
||||||
|
vertex.Position = b.Position + radius * new QuikVec2(MathF.Sin(angle), -MathF.Cos(angle));
|
||||||
|
current = (short) _vertexBufferPointer;
|
||||||
|
|
||||||
|
AddVertex(vertex);
|
||||||
|
AddElement(focus, last, current);
|
||||||
|
|
||||||
|
last = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddElement(focus, last, (short) (baseElement + 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateRectangleBorderSimple(QuikRectangle rectangle, QuikStrokeStyle stroke)
|
||||||
|
{
|
||||||
|
QuikVertex baseStrokeVertex = new QuikVertex() {Color = stroke.Color};
|
||||||
|
float semiStroke = 0.5f * stroke.Width;
|
||||||
|
|
||||||
|
// AB
|
||||||
|
GenerateLineSegment(
|
||||||
|
baseStrokeVertex,
|
||||||
|
new QuikLine(
|
||||||
|
rectangle.Min.X + semiStroke,
|
||||||
|
rectangle.Min.Y,
|
||||||
|
rectangle.Max.X - semiStroke,
|
||||||
|
rectangle.Min.Y
|
||||||
|
),
|
||||||
|
stroke.Width,
|
||||||
|
out _,
|
||||||
|
out _);
|
||||||
|
|
||||||
|
// BC
|
||||||
|
GenerateLineSegment(
|
||||||
|
baseStrokeVertex,
|
||||||
|
new QuikLine(
|
||||||
|
rectangle.Max.X,
|
||||||
|
rectangle.Min.Y - semiStroke,
|
||||||
|
rectangle.Max.X,
|
||||||
|
rectangle.Max.Y + semiStroke
|
||||||
|
),
|
||||||
|
stroke.Width,
|
||||||
|
out _,
|
||||||
|
out _);
|
||||||
|
|
||||||
|
// CD
|
||||||
|
GenerateLineSegment(
|
||||||
|
baseStrokeVertex,
|
||||||
|
new QuikLine(
|
||||||
|
rectangle.Max.X - semiStroke,
|
||||||
|
rectangle.Max.Y,
|
||||||
|
rectangle.Min.X + semiStroke,
|
||||||
|
rectangle.Max.Y
|
||||||
|
),
|
||||||
|
stroke.Width,
|
||||||
|
out _,
|
||||||
|
out _);
|
||||||
|
|
||||||
|
// DA
|
||||||
|
GenerateLineSegment(
|
||||||
|
baseStrokeVertex,
|
||||||
|
new QuikLine(
|
||||||
|
rectangle.Min.X,
|
||||||
|
rectangle.Max.Y + semiStroke,
|
||||||
|
rectangle.Min.X,
|
||||||
|
rectangle.Min.Y - semiStroke
|
||||||
|
),
|
||||||
|
stroke.Width,
|
||||||
|
out _,
|
||||||
|
out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GenerateRectangleSimple(
|
||||||
|
QuikRectangle rectangle,
|
||||||
|
QuikFillStyle fill)
|
||||||
|
{
|
||||||
|
QuikVertex a, b, c, d;
|
||||||
|
a = b = c = d = new QuikVertex() {Color = fill.Color};
|
||||||
|
a.Position = rectangle.Min;
|
||||||
|
b.Position = new QuikVec2(rectangle.Right, rectangle.Bottom);
|
||||||
|
c.Position = rectangle.Max;
|
||||||
|
d.Position = new QuikVec2(rectangle.Left, rectangle.Top);
|
||||||
|
|
||||||
|
short idxA = (short) _vertexBufferPointer;
|
||||||
|
short idxB = (short) (idxA + 1);
|
||||||
|
short idxC = (short) (idxA + 2);
|
||||||
|
short idxD = (short) (idxA + 3);
|
||||||
|
|
||||||
|
AddVertex(a, b, c, d);
|
||||||
|
AddElement(
|
||||||
|
idxA,
|
||||||
|
idxB,
|
||||||
|
idxC,
|
||||||
|
idxA,
|
||||||
|
idxC,
|
||||||
|
idxD
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RenderRectangles(ref QuikDrawCall call, QuikCommandRectangles rectangles)
|
||||||
|
{
|
||||||
|
QuikStrokeStyle stroke = rectangles.StrokeStyle ?? Context.DefaultStroke;
|
||||||
|
QuikFillStyle fill = rectangles.FillStyle ?? Context.DefaultFill;
|
||||||
|
|
||||||
|
short start = (short) _elementBufferPointer;
|
||||||
|
|
||||||
|
for (int i = 0; i < rectangles.Rectangles.Length; i++)
|
||||||
|
{
|
||||||
|
GenerateRectangle(rectangles.Rectangles[i], stroke, fill, rectangles.CornerRadius);
|
||||||
|
}
|
||||||
|
|
||||||
|
call.Offset = (short) (start * 2);
|
||||||
|
call.Count = (short) (_elementBufferPointer - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public delegate void VertexGeneratorCommandHandler(QuikVertexGenerator generator, QuikCommand command, ref QuikDrawCall? call);
|
||||||
|
|
||||||
public enum QuikRenderTarget
|
public enum QuikRenderTarget
|
||||||
{
|
{
|
||||||
Color,
|
Color,
|
||||||
|
@ -115,6 +115,24 @@ void main()
|
|||||||
loc = GL.GetUniformLocation(sp, "matrix");
|
loc = GL.GetUniformLocation(sp, "matrix");
|
||||||
|
|
||||||
List<QuikDrawCall> calls = new List<QuikDrawCall>();
|
List<QuikDrawCall> calls = new List<QuikDrawCall>();
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
QuikStrokeStyle strokeBorder = new QuikStrokeStyle()
|
||||||
|
{
|
||||||
|
Color = new QuikColor(0xaaaaaaff),
|
||||||
|
Width = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
QuikStrokeStyle strokeNoBorder = new QuikStrokeStyle()
|
||||||
|
{
|
||||||
|
Color = new QuikColor(0xaaaaaaff),
|
||||||
|
Width = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
QuikFillStyle fill = new QuikFillStyle()
|
||||||
|
{
|
||||||
|
Color = new QuikColor(0xeeeeeeff)
|
||||||
|
};
|
||||||
|
|
||||||
for (;!window.IsExiting;)
|
for (;!window.IsExiting;)
|
||||||
{
|
{
|
||||||
@ -134,32 +152,53 @@ void main()
|
|||||||
-1);
|
-1);
|
||||||
GL.UniformMatrix4(loc, false, ref matrix);
|
GL.UniformMatrix4(loc, false, ref matrix);
|
||||||
|
|
||||||
context.DefaultStroke.Color = new QuikColor(40, 128, 60, 255);
|
context.Draw.Commands.Enqueue(
|
||||||
|
new QuikCommandRectangle(new QuikRectangle(120, 60, 20, 20))
|
||||||
|
{
|
||||||
|
CornerRadius = 0,
|
||||||
|
FillStyle = fill,
|
||||||
|
StrokeStyle = strokeNoBorder
|
||||||
|
});
|
||||||
|
|
||||||
context.Draw.Line(
|
context.Draw.Commands.Enqueue(
|
||||||
// >
|
new QuikCommandRectangle(new QuikRectangle(240, 60, 140, 20))
|
||||||
new QuikLine(10,10, 20, 20),
|
{
|
||||||
new QuikLine(20, 20, 10, 30),
|
CornerRadius = 4,
|
||||||
|
FillStyle = fill,
|
||||||
|
StrokeStyle = strokeNoBorder
|
||||||
|
});
|
||||||
|
|
||||||
// s
|
context.Draw.Commands.Enqueue(
|
||||||
new QuikLine(28, 10, 38, 10),
|
new QuikCommandRectangle(new QuikRectangle(360, 60, 260, 20))
|
||||||
new QuikLine(38, 10, 38, 20),
|
{
|
||||||
new QuikLine(38, 20, 28, 20),
|
CornerRadius = 15,
|
||||||
new QuikLine(28, 20, 28, 30),
|
FillStyle = fill,
|
||||||
new QuikLine(28, 30, 38, 30),
|
StrokeStyle = strokeNoBorder
|
||||||
|
});
|
||||||
|
|
||||||
// e
|
context.Draw.Commands.Enqueue(
|
||||||
new QuikLine(64, 20, 74, 20),
|
new QuikCommandRectangle(new QuikRectangle(120, 120, 20, 80))
|
||||||
new QuikLine(74, 20, 74, 30),
|
{
|
||||||
new QuikLine(74, 30, 64, 30),
|
CornerRadius = 0,
|
||||||
new QuikLine(64, 30, 64, 10),
|
FillStyle = fill,
|
||||||
new QuikLine(64, 10, 74, 10)
|
StrokeStyle = strokeBorder
|
||||||
);
|
});
|
||||||
|
|
||||||
context.Draw.Bezier(
|
context.Draw.Commands.Enqueue(
|
||||||
new QuikBezier(46, 10, 56, 10, 46, 30, 56, 30),
|
new QuikCommandRectangle(new QuikRectangle(240, 120, 140, 80))
|
||||||
new QuikBezier(56, 30, 46, 30, 56, 60, 46, 60),
|
{
|
||||||
new QuikBezier(46, 60, 56, 60, 46, 90, 56, 90));
|
CornerRadius = 4,
|
||||||
|
FillStyle = fill,
|
||||||
|
StrokeStyle = strokeBorder
|
||||||
|
});
|
||||||
|
|
||||||
|
context.Draw.Commands.Enqueue(
|
||||||
|
new QuikCommandRectangle(new QuikRectangle(360, 120, 260, 80))
|
||||||
|
{
|
||||||
|
CornerRadius = 15,
|
||||||
|
FillStyle = fill,
|
||||||
|
StrokeStyle = strokeBorder
|
||||||
|
});
|
||||||
|
|
||||||
QuikCommand command;
|
QuikCommand command;
|
||||||
while (context.Draw.Commands.TryDequeue(out command))
|
while (context.Draw.Commands.TryDequeue(out command))
|
||||||
@ -179,7 +218,14 @@ void main()
|
|||||||
gen.Clear();
|
gen.Clear();
|
||||||
calls.Clear();
|
calls.Clear();
|
||||||
|
|
||||||
|
if (++i % 60 == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Vertex Usage: {0} ; Element Usage: {1}", gen.VertexUsage, gen.ElementUsage);
|
||||||
|
}
|
||||||
|
|
||||||
window.Context.SwapBuffers();
|
window.Context.SwapBuffers();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user