Create joint generating code for multi-segment lines and refactor code for end caps.
This commit is contained in:
parent
772906bec7
commit
502eb95278
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Quik.VertexGenerator;
|
||||||
|
|
||||||
namespace Quik
|
namespace Quik
|
||||||
{
|
{
|
||||||
@ -10,9 +11,15 @@ namespace Quik
|
|||||||
public float X;
|
public float X;
|
||||||
public float Y;
|
public float Y;
|
||||||
|
|
||||||
public float Length() => MathF.Sqrt(X * X + Y * Y);
|
public float Magnitude => MathF.Sqrt(X * X + Y * Y);
|
||||||
|
|
||||||
public QuikVec2 Normalize() => this * (1.0f / this.Length());
|
public QuikVec2(float x, float y)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuikVec2 Normalize() => this * (1.0f / Magnitude);
|
||||||
|
|
||||||
public float Atan2() => MathF.Atan2(Y, X);
|
public float Atan2() => MathF.Atan2(Y, X);
|
||||||
public static QuikVec2 operator +(QuikVec2 a, QuikVec2 b)
|
public static QuikVec2 operator +(QuikVec2 a, QuikVec2 b)
|
||||||
@ -52,6 +59,32 @@ namespace Quik
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static QuikVec2 operator *(QuikVec2 a, float b) => b * a;
|
public static QuikVec2 operator *(QuikVec2 a, float b) => b * a;
|
||||||
|
|
||||||
|
public static bool operator ==(QuikVec2 a, QuikVec2 b) => a.X == b.X && a.Y == b.Y;
|
||||||
|
|
||||||
|
public static bool operator !=(QuikVec2 a, QuikVec2 b) => a.X != b.X || a.Y != b.Y;
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is QuikVec2)
|
||||||
|
{
|
||||||
|
return (QuikVec2) obj == this;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return 63671 * X.GetHashCode() ^ 81083 * Y.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float Dot(QuikVec2 a, QuikVec2 b)
|
||||||
|
{
|
||||||
|
return a.X * b.X + a.Y * b.Y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -162,6 +195,20 @@ namespace Quik
|
|||||||
/// End point.
|
/// End point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public QuikVec2 End;
|
public QuikVec2 End;
|
||||||
|
|
||||||
|
public QuikLine(QuikVec2 start, QuikVec2 end)
|
||||||
|
{
|
||||||
|
Start = start;
|
||||||
|
End = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QuikLine(float startX, float startY, float endX, float endY)
|
||||||
|
{
|
||||||
|
Start.X = startX;
|
||||||
|
Start.Y = startY;
|
||||||
|
End.X = endX;
|
||||||
|
End.Y = endY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -190,6 +190,322 @@ namespace Quik.VertexGenerator
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a basic line segment.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseVertex">The vertex base to modify when generating vertices.</param>
|
||||||
|
/// <param name="line">The line segment.</param>
|
||||||
|
/// <param name="width">The width of the line.</param>
|
||||||
|
/// <param name="lineStartIndex">Start index of the generated line.</param>
|
||||||
|
/// <param name="normal">The line normal.</param>
|
||||||
|
private void GenerateLineSegment(
|
||||||
|
QuikVertex baseVertex,
|
||||||
|
QuikLine line,
|
||||||
|
float width,
|
||||||
|
out short lineStartIndex,
|
||||||
|
out QuikVec2 normal)
|
||||||
|
{
|
||||||
|
QuikVec2 tangent = (line.End - line.Start).Normalize();
|
||||||
|
normal = new QuikVec2() {X = -tangent.Y, Y = tangent.X};
|
||||||
|
lineStartIndex = (short)_vertexBufferPointer;
|
||||||
|
|
||||||
|
QuikVertex startA = baseVertex, startB = baseVertex;
|
||||||
|
QuikVertex endA = baseVertex, endB = baseVertex;
|
||||||
|
|
||||||
|
startA.Position = line.Start + width / 2 * normal;
|
||||||
|
startB.Position = line.Start - width / 2 * normal;
|
||||||
|
endA.Position = line.End + width / 2 * normal;
|
||||||
|
endB.Position = line.End - width / 2 * normal;
|
||||||
|
|
||||||
|
// Add the major line vertices.
|
||||||
|
AddVertex(startA, startB, endA, endB);
|
||||||
|
|
||||||
|
// Add the line indices.
|
||||||
|
AddElement(
|
||||||
|
(short) (lineStartIndex + 1),
|
||||||
|
(short) (lineStartIndex + 2),
|
||||||
|
(short) (lineStartIndex + 0),
|
||||||
|
(short) (lineStartIndex + 1),
|
||||||
|
(short) (lineStartIndex + 3),
|
||||||
|
(short) (lineStartIndex + 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the rounding resolution for a line segment.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="width">The width of the line.</param>
|
||||||
|
/// <param name="arc">The angle of the cap or joint arc.</param>
|
||||||
|
/// <returns>The rounding resolution.</returns>
|
||||||
|
private int GetRoundingResolution(float width, float arc)
|
||||||
|
{
|
||||||
|
int endCapResolution = (int) Math.Ceiling(arc * width * CurveGranularity);
|
||||||
|
return endCapResolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a round start cap on a line.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseVertex">The base vertex to modify for generation.</param>
|
||||||
|
/// <param name="start">The start point.</param>
|
||||||
|
/// <param name="normal">The line normal.</param>
|
||||||
|
/// <param name="width">The width of line to generate.</param>
|
||||||
|
/// <param name="resolution">End cap resolution.</param>
|
||||||
|
/// <param name="lineStartPositiveIndex">The positive vertex index of the line start.</param>
|
||||||
|
/// <param name="lineStartNegativeIndex">The negative vertex index of the line start.</param>
|
||||||
|
public void GenerateStartCap(
|
||||||
|
QuikVertex baseVertex,
|
||||||
|
QuikVec2 start,
|
||||||
|
QuikVec2 normal,
|
||||||
|
float width,
|
||||||
|
int resolution,
|
||||||
|
short lineStartPositiveIndex,
|
||||||
|
short lineStartNegativeIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
QuikVertex circlePoint = baseVertex;
|
||||||
|
short lastIndex = lineStartPositiveIndex;
|
||||||
|
for (int i = 0; i < resolution; i++)
|
||||||
|
{
|
||||||
|
float angle = (float) (i + 1) / (resolution + 1) * MathF.PI;
|
||||||
|
float cosT = MathF.Cos(angle);
|
||||||
|
float sinT = MathF.Sin(angle);
|
||||||
|
|
||||||
|
QuikVec2 displacement = new QuikVec2()
|
||||||
|
{
|
||||||
|
X = normal.X * cosT - normal.Y * sinT,
|
||||||
|
Y = normal.X * sinT + normal.Y * cosT
|
||||||
|
} * (width / 2);
|
||||||
|
|
||||||
|
circlePoint.Position = start + displacement;
|
||||||
|
|
||||||
|
short segmentIndex = (short)_vertexBufferPointer;
|
||||||
|
|
||||||
|
AddVertex(circlePoint);
|
||||||
|
AddElement(
|
||||||
|
lineStartNegativeIndex,
|
||||||
|
lastIndex,
|
||||||
|
segmentIndex);
|
||||||
|
|
||||||
|
lastIndex = segmentIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a round line end cap.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseVertex">Base vertex to modify for generation.</param>
|
||||||
|
/// <param name="end">The line end.</param>
|
||||||
|
/// <param name="normal">The line normal.</param>
|
||||||
|
/// <param name="width">The line width.</param>
|
||||||
|
/// <param name="resolution">Cap generation resolution.</param>
|
||||||
|
/// <param name="lineEndPositiveIndex">Vertex index of the positive line end.</param>
|
||||||
|
/// <param name="lineEndNegativeIndex">Vertex index of the negative line end.</param>
|
||||||
|
public void GenerateEndCap(
|
||||||
|
QuikVertex baseVertex,
|
||||||
|
QuikVec2 end,
|
||||||
|
QuikVec2 normal,
|
||||||
|
float width,
|
||||||
|
int resolution,
|
||||||
|
short lineEndPositiveIndex,
|
||||||
|
short lineEndNegativeIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
QuikVertex circlePoint = baseVertex;
|
||||||
|
short lastIndex = lineEndPositiveIndex;
|
||||||
|
for (int i = 0; i < resolution; i++)
|
||||||
|
{
|
||||||
|
float angle = -(float) (i + 1) / (resolution + 1) * MathF.PI;
|
||||||
|
float cosT = MathF.Cos(angle);
|
||||||
|
float sinT = MathF.Sin(angle);
|
||||||
|
|
||||||
|
QuikVec2 displacement = new QuikVec2()
|
||||||
|
{
|
||||||
|
X = normal.X * cosT - normal.Y * sinT,
|
||||||
|
Y = normal.X * sinT + normal.Y * cosT
|
||||||
|
} * (width / 2);
|
||||||
|
|
||||||
|
circlePoint.Position = end + displacement;
|
||||||
|
|
||||||
|
AddVertex(circlePoint);
|
||||||
|
AddElement(
|
||||||
|
lineEndNegativeIndex,
|
||||||
|
lastIndex,
|
||||||
|
(short) (_vertexBufferPointer - 1));
|
||||||
|
|
||||||
|
lastIndex = (short) (_vertexBufferPointer - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a joint on the line negative edge.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseVertex">Base vertex to modify for generation.</param>
|
||||||
|
/// <param name="focus">The focus of the joint.</param>
|
||||||
|
/// <param name="width">With of the lines.</param>
|
||||||
|
/// <param name="prevNegativeLineIndex">Index of the negative end vertex.</param>
|
||||||
|
/// <param name="nextNegativeLineIndex">Index of the negative start vertex.</param>
|
||||||
|
/// <param name="resolution">Joint resolution.</param>
|
||||||
|
/// <param name="arc">Arc length of the joint.</param>
|
||||||
|
/// <param name="prevNormal">Normal of the previous line.</param>
|
||||||
|
private void GenerateNegativeJoint(
|
||||||
|
QuikVertex baseVertex,
|
||||||
|
QuikVec2 focus,
|
||||||
|
float width,
|
||||||
|
short prevNegativeLineIndex,
|
||||||
|
short nextNegativeLineIndex,
|
||||||
|
int resolution,
|
||||||
|
float arc,
|
||||||
|
QuikVec2 prevNormal)
|
||||||
|
{
|
||||||
|
QuikVertex focusVertex = baseVertex;
|
||||||
|
short focusIndex = (short) _vertexBufferPointer;
|
||||||
|
short lastIndex = prevNegativeLineIndex;
|
||||||
|
|
||||||
|
focusVertex.Position = focus;
|
||||||
|
AddVertex(focusVertex);
|
||||||
|
|
||||||
|
for (int i = 0; i < resolution; i++)
|
||||||
|
{
|
||||||
|
float angle = (float) (i + 1) / (resolution + 1) * arc;
|
||||||
|
float cosT = MathF.Cos(angle);
|
||||||
|
float sinT = MathF.Sin(angle);
|
||||||
|
|
||||||
|
QuikVec2 displacement = new QuikVec2()
|
||||||
|
{
|
||||||
|
X = -prevNormal.X * cosT + prevNormal.Y * sinT,
|
||||||
|
Y = -prevNormal.X * sinT - prevNormal.Y * cosT
|
||||||
|
} * (width / 2);
|
||||||
|
|
||||||
|
QuikVertex segmentVertex = focusVertex;
|
||||||
|
segmentVertex.Position += displacement;
|
||||||
|
|
||||||
|
short segmentIndex = (short) _vertexBufferPointer;
|
||||||
|
AddVertex(segmentVertex);
|
||||||
|
|
||||||
|
AddElement(lastIndex, segmentIndex, focusIndex);
|
||||||
|
|
||||||
|
lastIndex = segmentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add final triangle.
|
||||||
|
AddElement(lastIndex, nextNegativeLineIndex, focusIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a joint on the line negative edge.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseVertex">Base vertex to modify for generation.</param>
|
||||||
|
/// <param name="focus">The focus of the joint.</param>
|
||||||
|
/// <param name="width">With of the lines.</param>
|
||||||
|
/// <param name="prevPositiveLineIndex">Index of the positive end vertex.</param>
|
||||||
|
/// <param name="nextPositiveLineIndex">Index of the positive start vertex.</param>
|
||||||
|
/// <param name="resolution">Joint resolution.</param>
|
||||||
|
/// <param name="arc">Arc length of the joint.</param>
|
||||||
|
/// <param name="nextNormal">Normal of the next line.</param>
|
||||||
|
private void GeneratePositiveJoint(
|
||||||
|
QuikVertex baseVertex,
|
||||||
|
QuikVec2 focus,
|
||||||
|
float width,
|
||||||
|
short prevPositiveLineIndex,
|
||||||
|
short nextPositiveLineIndex,
|
||||||
|
int resolution,
|
||||||
|
float arc,
|
||||||
|
QuikVec2 nextNormal)
|
||||||
|
{
|
||||||
|
QuikVertex focusVertex = baseVertex;
|
||||||
|
short focusIndex = (short) _vertexBufferPointer;
|
||||||
|
short lastIndex = nextPositiveLineIndex;
|
||||||
|
|
||||||
|
focusVertex.Position = focus;
|
||||||
|
AddVertex(focusVertex);
|
||||||
|
|
||||||
|
for (int i = 0; i < resolution; i++)
|
||||||
|
{
|
||||||
|
float angle = (float) (i + 1) / (resolution + 1) * arc;
|
||||||
|
float cosT = MathF.Cos(angle);
|
||||||
|
float sinT = MathF.Sin(angle);
|
||||||
|
|
||||||
|
QuikVec2 displacement = new QuikVec2()
|
||||||
|
{
|
||||||
|
X = nextNormal.X * cosT - nextNormal.Y * sinT,
|
||||||
|
Y = nextNormal.X * sinT + nextNormal.Y * cosT
|
||||||
|
} * (width / 2);
|
||||||
|
|
||||||
|
QuikVertex segmentVertex = focusVertex;
|
||||||
|
segmentVertex.Position += displacement;
|
||||||
|
|
||||||
|
short segmentIndex = (short) _vertexBufferPointer;
|
||||||
|
AddVertex(segmentVertex);
|
||||||
|
|
||||||
|
AddElement(lastIndex, segmentIndex, focusIndex);
|
||||||
|
|
||||||
|
lastIndex = segmentIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add final triangle.
|
||||||
|
AddElement(lastIndex, prevPositiveLineIndex, focusIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a joint.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseVertex">Base vertex to modify.</param>
|
||||||
|
/// <param name="focus">Focus of the joint.</param>
|
||||||
|
/// <param name="prevTangent">Tangent of the previous line segment.</param>
|
||||||
|
/// <param name="nextTangent">Tangent of the next line segment.</param>
|
||||||
|
/// <param name="width">Width of the lines.</param>
|
||||||
|
/// <param name="prevPositiveEndIndex">Vertex index of the positive end.</param>
|
||||||
|
/// <param name="prevNegativeEndIndex">Vertex index of the negative end.</param>
|
||||||
|
/// <param name="nextPositiveStartIndex">Vertex index of the positive start.</param>
|
||||||
|
/// <param name="nextNegativeStartIndex">Vertex index of the negative start.</param>
|
||||||
|
public void GenerateJoint(
|
||||||
|
QuikVertex baseVertex,
|
||||||
|
QuikVec2 focus,
|
||||||
|
QuikVec2 prevTangent,
|
||||||
|
QuikVec2 nextTangent,
|
||||||
|
float width,
|
||||||
|
short prevPositiveEndIndex,
|
||||||
|
short prevNegativeEndIndex,
|
||||||
|
short nextPositiveStartIndex,
|
||||||
|
short nextNegativeStartIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
QuikVec2 prevNormal, nextNormal;
|
||||||
|
QuikVec2 averageTangent;
|
||||||
|
|
||||||
|
prevNormal = new QuikVec2() { X = -prevTangent.Y, Y = prevTangent.X };
|
||||||
|
nextNormal = new QuikVec2() { X = -nextTangent.Y, Y = nextTangent.X };
|
||||||
|
|
||||||
|
averageTangent = 0.5f * (prevTangent + nextTangent);
|
||||||
|
|
||||||
|
// Figure out which side needs the joint.
|
||||||
|
QuikVec2 positiveEdge = ((focus + nextNormal) - (focus + prevNormal)).Normalize();
|
||||||
|
QuikVec2 negativeEdge = ((focus - nextNormal) - (focus - prevNormal)).Normalize();
|
||||||
|
|
||||||
|
float positiveDot, negativeDot;
|
||||||
|
positiveDot = QuikVec2.Dot(averageTangent, positiveEdge);
|
||||||
|
negativeDot = QuikVec2.Dot(averageTangent, negativeEdge);
|
||||||
|
|
||||||
|
float arc = MathF.Acos(QuikVec2.Dot(prevNormal, nextNormal));
|
||||||
|
int resolution = GetRoundingResolution(width, arc);
|
||||||
|
|
||||||
|
if (positiveDot < negativeDot)
|
||||||
|
{
|
||||||
|
// Negative edge rounding.
|
||||||
|
GenerateNegativeJoint(baseVertex, focus, width, prevNegativeEndIndex, nextNegativeStartIndex, resolution, arc, prevNormal);
|
||||||
|
}
|
||||||
|
else if (negativeDot < positiveDot)
|
||||||
|
{
|
||||||
|
// Positive edge rounding.
|
||||||
|
GeneratePositiveJoint(baseVertex, focus, width, prevPositiveEndIndex, nextPositiveStartIndex, resolution, arc, nextNormal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// There is no need to generate anything because the lines are the same???
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Renders a line.
|
/// Renders a line.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -199,97 +515,85 @@ namespace Quik.VertexGenerator
|
|||||||
{
|
{
|
||||||
// Skip over stipple patterns for now.
|
// Skip over stipple patterns for now.
|
||||||
QuikStrokeStyle style = line.Style ?? Context.DefaultStroke;
|
QuikStrokeStyle style = line.Style ?? Context.DefaultStroke;
|
||||||
int endCapResolution; // Resolution of the end cap.
|
|
||||||
short startOffset = (short) _vertexBufferPointer; // Starting index pointer.
|
|
||||||
QuikVec2 tangent;
|
|
||||||
QuikVec2 normal;
|
|
||||||
|
|
||||||
tangent = (line.Line.End - line.Line.Start).Normalize();
|
|
||||||
normal = new QuikVec2() {X = -tangent.Y, Y = tangent.X};
|
|
||||||
|
|
||||||
QuikVertex baseVertex = new QuikVertex() { Color = style.Color };
|
QuikVertex baseVertex = new QuikVertex() { Color = style.Color };
|
||||||
QuikVertex startA = baseVertex, startB = baseVertex;
|
|
||||||
QuikVertex endA = baseVertex, endB = baseVertex;
|
|
||||||
|
|
||||||
startA.Position = line.Line.Start + style.Width / 2 * normal;
|
GenerateLineSegment(baseVertex, line.Line, style.Width, out short startOffset, out QuikVec2 normal);
|
||||||
startB.Position = line.Line.Start - style.Width / 2 * normal;
|
|
||||||
endA.Position = line.Line.End + style.Width / 2 * normal;
|
|
||||||
endB.Position = line.Line.End - style.Width / 2 * normal;
|
|
||||||
|
|
||||||
// Add the major line vertices.
|
|
||||||
AddVertex(startA, startB, endA, endB);
|
|
||||||
|
|
||||||
// Add the line indices.
|
|
||||||
AddElement(
|
|
||||||
(short) (startOffset + 1),
|
|
||||||
(short) (startOffset + 2),
|
|
||||||
(short) (startOffset + 0),
|
|
||||||
(short) (startOffset + 1),
|
|
||||||
(short) (startOffset + 3),
|
|
||||||
(short) (startOffset + 2)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Now calculate the end caps.
|
// Now calculate the end caps.
|
||||||
endCapResolution = (int)Math.Ceiling(MathF.PI * style.Width * CurveGranularity);
|
int endCapResolution = GetRoundingResolution(style.Width, MathF.PI);
|
||||||
|
|
||||||
// Construct start cap.
|
// Construct start cap.
|
||||||
QuikVertex circlePoint = baseVertex;
|
GenerateStartCap(baseVertex, line.Line.Start, normal, style.Width, endCapResolution, startOffset, (short)
|
||||||
short lastIndex = startOffset;
|
(startOffset + 1));
|
||||||
for (int i = 0; i < endCapResolution; i++)
|
|
||||||
{
|
|
||||||
float angle = (float) (i + 1) / (endCapResolution + 1) * MathF.PI;
|
|
||||||
float cosT = MathF.Cos(angle);
|
|
||||||
float sinT = MathF.Sin(angle);
|
|
||||||
|
|
||||||
QuikVec2 displacement = new QuikVec2()
|
|
||||||
{
|
|
||||||
X = normal.X * cosT - normal.Y * sinT,
|
|
||||||
Y = normal.X * sinT + normal.Y * cosT
|
|
||||||
} * (style.Width / 2);
|
|
||||||
|
|
||||||
circlePoint.Position = line.Line.Start + displacement;
|
|
||||||
|
|
||||||
AddVertex(circlePoint);
|
|
||||||
AddElement(
|
|
||||||
(short)(startOffset + 1),
|
|
||||||
lastIndex,
|
|
||||||
(short)(_vertexBufferPointer - 1));
|
|
||||||
|
|
||||||
lastIndex = (short) (_vertexBufferPointer - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct end cap.
|
// Construct end cap.
|
||||||
lastIndex = (short)(startOffset + 2);
|
GenerateEndCap(baseVertex, line.Line.End, normal, style.Width, endCapResolution, (short) (startOffset + 2),(short)
|
||||||
for (int i = 0; i < endCapResolution; i++)
|
(startOffset + 3));
|
||||||
{
|
|
||||||
float angle = -(float) (i + 1) / (endCapResolution + 1) * MathF.PI;
|
|
||||||
float cosT = MathF.Cos(angle);
|
|
||||||
float sinT = MathF.Sin(angle);
|
|
||||||
|
|
||||||
QuikVec2 displacement = new QuikVec2()
|
|
||||||
{
|
|
||||||
X = normal.X * cosT - normal.Y * sinT,
|
|
||||||
Y = normal.X * sinT + normal.Y * cosT
|
|
||||||
} * (style.Width / 2);
|
|
||||||
|
|
||||||
circlePoint.Position = line.Line.End + displacement;
|
|
||||||
|
|
||||||
AddVertex(circlePoint);
|
|
||||||
AddElement(
|
|
||||||
(short)(startOffset + 3),
|
|
||||||
lastIndex,
|
|
||||||
(short)(_vertexBufferPointer - 1));
|
|
||||||
|
|
||||||
lastIndex = (short) (_vertexBufferPointer - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
call.Offset = (short) (startOffset * 2);
|
call.Offset = (short) (startOffset * 2);
|
||||||
call.Count = (short) (_elementBufferPointer - startOffset);
|
call.Count = (short) (_elementBufferPointer - startOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Render lines.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="call">The draw call to generate.</param>
|
||||||
|
/// <param name="lines">The lines command.</param>
|
||||||
private void RenderLine(ref QuikDrawCall call, QuikCommandLines lines)
|
private void RenderLine(ref QuikDrawCall call, QuikCommandLines lines)
|
||||||
{
|
{
|
||||||
|
// Skip over stipple patterns for now.
|
||||||
|
QuikStrokeStyle style = lines.Style ?? Context.DefaultStroke;
|
||||||
|
QuikVertex baseVertex = new QuikVertex() { Color = style.Color };
|
||||||
|
bool isStart;
|
||||||
|
bool isEnd;
|
||||||
|
short startOffset = (short)_elementBufferPointer;
|
||||||
|
short lastStartIndex = 0;
|
||||||
|
short lineStartIndex;
|
||||||
|
QuikVec2 normal;
|
||||||
|
int resolution = GetRoundingResolution(style.Width, MathF.PI);
|
||||||
|
|
||||||
|
for (int i = 0; i < lines.Lines.Length; i++)
|
||||||
|
{
|
||||||
|
QuikLine line = lines.Lines[i];
|
||||||
|
|
||||||
|
isStart = i == 0 || line.Start != lines.Lines[i - 1].End;
|
||||||
|
isEnd = i == lines.Lines.Length - 1 || line.End != lines.Lines[i + 1].Start;
|
||||||
|
|
||||||
|
GenerateLineSegment(baseVertex, line, style.Width, out lineStartIndex, out normal);
|
||||||
|
|
||||||
|
if (isStart)
|
||||||
|
{
|
||||||
|
GenerateStartCap(baseVertex, line.Start, normal, style.Width, resolution, lineStartIndex,
|
||||||
|
(short)(lineStartIndex + 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QuikLine prev = lines.Lines[i - 1];
|
||||||
|
QuikVec2 prevTangent = (prev.End - prev.Start).Normalize();
|
||||||
|
QuikVec2 nextTangent = (line.End - line.Start).Normalize();
|
||||||
|
|
||||||
|
GenerateJoint(
|
||||||
|
baseVertex,
|
||||||
|
line.Start,
|
||||||
|
prevTangent,
|
||||||
|
nextTangent,
|
||||||
|
style.Width,
|
||||||
|
(short) (lastStartIndex + 2),
|
||||||
|
(short) (lastStartIndex + 3),
|
||||||
|
lineStartIndex,
|
||||||
|
(short)(lineStartIndex + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEnd)
|
||||||
|
{
|
||||||
|
GenerateEndCap(baseVertex, line.End, normal, style.Width, resolution, (short)(lineStartIndex + 2), (short)(lineStartIndex + 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
lastStartIndex = lineStartIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
call.Offset = (short) (startOffset * 2);
|
||||||
|
call.Count = (short) (_elementBufferPointer - startOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,27 +127,34 @@ void main()
|
|||||||
|
|
||||||
Matrix4 matrix = Matrix4.CreateOrthographicOffCenter(
|
Matrix4 matrix = Matrix4.CreateOrthographicOffCenter(
|
||||||
0,
|
0,
|
||||||
window.Size.X,
|
(float)window.Size.X / 2,
|
||||||
0,
|
0,
|
||||||
window.Size.Y,
|
(float)window.Size.Y / 2,
|
||||||
1,
|
1,
|
||||||
-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.Line(
|
context.Draw.Line(
|
||||||
new QuikLine()
|
// >
|
||||||
{
|
new QuikLine(10,10, 20, 20),
|
||||||
Start = new QuikVec2()
|
new QuikLine(20, 20, 10, 30),
|
||||||
{
|
|
||||||
X = 20,
|
// s
|
||||||
Y = 40
|
new QuikLine(28, 10, 38, 10),
|
||||||
},
|
new QuikLine(38, 10, 38, 20),
|
||||||
End = new QuikVec2()
|
new QuikLine(38, 20, 28, 20),
|
||||||
{
|
new QuikLine(28, 20, 28, 30),
|
||||||
X=100,
|
new QuikLine(28, 30, 38, 30),
|
||||||
Y=100
|
|
||||||
}
|
// e
|
||||||
});
|
new QuikLine(64, 20, 74, 20),
|
||||||
|
new QuikLine(74, 20, 74, 30),
|
||||||
|
new QuikLine(74, 30, 64, 30),
|
||||||
|
new QuikLine(64, 30, 64, 10),
|
||||||
|
new QuikLine(64, 10, 74, 10)
|
||||||
|
);
|
||||||
|
|
||||||
QuikCommand command;
|
QuikCommand command;
|
||||||
while (context.Draw.Commands.TryDequeue(out command))
|
while (context.Draw.Commands.TryDequeue(out command))
|
||||||
|
Loading…
Reference in New Issue
Block a user