/// <summary>Called when we're emitting a line segment.</summary> protected override void EmitLine(StrokePoint inner, StrokePoint outer) { // Emit two verts and UVs: Vertices[VertexIndex] = new Vector3(inner.X, inner.Y, 0f); UV1[VertexIndex] = new Vector2(inner.C * UvMultiplier.x, 0f); VertexIndex++; Vertices[VertexIndex] = new Vector3(outer.X, outer.Y, 0f); UV1[VertexIndex] = new Vector2(outer.C * UvMultiplier.x, UvMultiplier.y); VertexIndex++; // Emit the triangles next (if we can): if (FirstLine) { FirstLine = false; return; } // 4 important verts are.. // [VertexIndex-1, VertexIndex-2], [VertexIndex-3, VertexIndex-4] Triangles[TriangleIndex++] = VertexIndex - 1; Triangles[TriangleIndex++] = VertexIndex - 3; Triangles[TriangleIndex++] = VertexIndex - 2; Triangles[TriangleIndex++] = VertexIndex - 2; Triangles[TriangleIndex++] = VertexIndex - 3; Triangles[TriangleIndex++] = VertexIndex - 4; }
/// <summary>Adds points to the given set for a circle of the given angle, starting at a point about a center.</summary> private void DrawCircle(List <StrokePoint> set, ref int count, float angle, float pX, float pY, float c, Vector2 center) { // The length of the arc: float arc = (Width / 2f) * angle; if (arc < 0f) { arc = -arc; } // Divide it by accuracy to get the # of points to add: int segmentsToAdd = (int)(arc / Accuracy) - 1; if (segmentsToAdd <= 0) { return; } // Delta angle: float deltaAngle = -angle / (float)(segmentsToAdd + 1); // The point to rotate: float rotateX = pX - center.x; float rotateY = pY - center.y; arc = deltaAngle; for (int i = 0; i < segmentsToAdd; i++) { // Rotate the previous point about center // by 'arc' // Get cos/sin: float cs = (float)System.Math.Cos(arc); float sn = (float)System.Math.Sin(arc); // Compute the point: float rotatedX = (rotateX * cs - rotateY * sn) + center.x; float rotatedY = (rotateX * sn + rotateY * cs) + center.y; if (count == set.Count) { set.Add(new StrokePoint(rotatedX, rotatedY, c)); } else { set[count] = new StrokePoint(rotatedX, rotatedY, c); } count++; arc += deltaAngle; } }
public void AddPoint(float x, float y, float c) { // Note that we don't know the total line length yet because of how extrude works. List <StrokePoint> set; int count; if (Outer) { set = OuterSet; count = OuterCount; // Make c relative to the whole line (in terms of its length): c = OuterLength + c * CurrentLine.Length; } else { set = InnerSet; count = InnerCount; // Make c relative to the whole line (in terms of its length): c = InnerLength + c * CurrentLine.Length; } if (ApplyLineJoinNow) { // Clear: ApplyLineJoinNow = false; if (count > 0) { // Get the previous point: StrokePoint previous = set[count - 1]; // Apply join now! Compare set[count-1] to our incoming point. if (LineJoinMode == StrokeLineMode.Miter) { // Add a single point which occurs at the miter distance from the original line point // along the average of StartNormal and EndNormal. // Note that we've already made sure miter length is a suitable distance away. // So, first, average that normal: Vector2 avg = new Vector2( (StartNormal.x + EndNormal.x) / 2f, (StartNormal.y + EndNormal.y) / 2f ); float length = MiterLength / avg.magnitude; // The point to add is therefore.. float miterX = OriginalLinePoint.x + (avg.x * length); float miterY = OriginalLinePoint.y + (avg.y * length); float miterC = previous.C + ((c - previous.C) * 0.5f); if (count == set.Count) { set.Add(new StrokePoint(miterX, miterY, miterC)); } else { set[count] = new StrokePoint(miterX, miterY, miterC); } count++; } else if (LineJoinMode == StrokeLineMode.Round) { // Make a circle of radius halfWidth about the original line point. DrawCircle( set, ref count, LineAngle, previous.X, previous.Y, c, OriginalLinePoint ); } } } if (count == set.Count) { set.Add(new StrokePoint(x, y, c)); } else { set[count] = new StrokePoint(x, y, c); } if (Outer) { OuterCount = count + 1; } else { InnerCount = count + 1; } }
/// <summary>Called when a contour is completed.</summary> private void CompleteContour(bool closed) { AtLeastOneLine = false; if (InnerCount == 0 || OuterCount == 0) { return; } // We have a computed line to deal with! // First, make those C values relative to the total length of their lines. for (int i = 0; i < OuterCount; i++) { StrokePoint sp = OuterSet[i]; sp.C /= OuterLength; OuterSet[i] = sp; } for (int i = 0; i < InnerCount; i++) { StrokePoint sp = InnerSet[i]; sp.C /= InnerLength; InnerSet[i] = sp; } // Next, we'll step along the edges, pairing nodes together and emitting them. // Index in the other edge: int otherIndex = 0; int innerMax = InnerCount - 1; int outerMax = OuterCount - 1; // Biggest number of verts: if (InnerCount > OuterCount) { // We'll be emitting InnerCount lines: StartMesh(closed, InnerCount); // The inner edge is longer. It will set the pace. for (int i = 0; i < InnerCount; i++) { // Compare inner.C with the two nearest verts in OuterSet. // If this is the last index, we always emit both maxes: if (i == innerMax) { otherIndex = outerMax; } else if (otherIndex != outerMax) { // Get the two C values to compare with: float currentC = InnerSet[i].C; float firstC = currentC - OuterSet[otherIndex].C; float secondC = OuterSet[otherIndex + 1].C - currentC; // If firstC is -ve, then use otherIndex. // If secondC is -ve then use otherIndex+1. // Otherwise, the smallest +ve number wins. if (firstC > 0f && (secondC <= 0f || secondC < firstC)) { // Pair with otherIndex+1. otherIndex++; } } // Pair now: EmitLine(InnerSet[i], OuterSet[otherIndex]); } } else { // We'll be emitting OuterCount lines: StartMesh(closed, OuterCount); // The outer edge is longer. It will set the pace. for (int i = 0; i < OuterCount; i++) { // Compare outer.C with the two nearest verts in InnerSet. // If this is the last index, we always emit both maxes: if (i == outerMax) { otherIndex = innerMax; } else if (otherIndex != innerMax) { // Get the two C values to compare with: float currentC = OuterSet[i].C; float firstC = currentC - InnerSet[otherIndex].C; float secondC = InnerSet[otherIndex + 1].C - currentC; // If firstC is -ve, then use otherIndex. // If secondC is -ve then use otherIndex+1. // Otherwise, the smallest +ve number wins. if (firstC > 0f && (secondC <= 0f || secondC < firstC)) { // Pair with otherIndex+1. otherIndex++; } } // Pair now: EmitLine(InnerSet[otherIndex], OuterSet[i]); } } // Done! EndMesh(); // Clear the values: InnerCount = 0; OuterCount = 0; InnerLength = 0f; OuterLength = 0f; }
/// <summary>Called when we're emitting a line segment.</summary> protected virtual void EmitLine(StrokePoint inner, StrokePoint outer) { }