static void InterpolatePoints( ref PointsList.PointsData lineData, Vector2 prevPosition, Vector2 position, Vector2 nextPosition, PointListProperties pointListProperties, int index ) { tmpBackV.x = prevPosition.x - position.x; tmpBackV.y = prevPosition.y - position.y; float backLength = Mathf.Sqrt(tmpBackV.x * tmpBackV.x + tmpBackV.y * tmpBackV.y); tmpBackNormV.x = tmpBackV.x / backLength; tmpBackNormV.y = tmpBackV.y / backLength; tmpForwV.x = nextPosition.x - position.x; tmpForwV.y = nextPosition.y - position.y; float forwLength = Mathf.Sqrt(tmpForwV.x * tmpForwV.x + tmpForwV.y * tmpForwV.y); tmpForwNormV.x = tmpForwV.x / forwLength; tmpForwNormV.y = tmpForwV.y / forwLength; float cos = (tmpBackNormV.x * tmpForwNormV.x + tmpBackNormV.y * tmpForwNormV.y); float angle = Mathf.Acos(cos); // ignore points along straight line if (cos <= -0.9999f) { return; } if (pointListProperties.RoundingDistance > 0.0f) { AddRoundedPoints( ref lineData, tmpBackNormV, position, tmpForwNormV, pointListProperties, angle, Mathf.Min(backLength, forwLength) * 0.49f ); } else { if (angle < pointListProperties.MaxAngle) { lineData.Positions.Add(position + tmpBackNormV * 0.5f); lineData.Positions.Add(position + tmpForwNormV * 0.5f); } else { lineData.Positions.Add(position); } } }
static void AddRoundedPoints( ref PointsList.PointsData lineData, Vector2 backNormV, Vector2 position, Vector2 forwNormV, PointListProperties pointListProperties, float angle, float maxDistance ) { float roundingDistance = Mathf.Min(maxDistance, pointListProperties.RoundingDistance); tmpBackPos.x = position.x + backNormV.x * roundingDistance; tmpBackPos.y = position.y + backNormV.y * roundingDistance; tmpForwPos.x = position.x + forwNormV.x * roundingDistance; tmpForwPos.y = position.y + forwNormV.y * roundingDistance; pointListProperties.CornerRounding.UpdateAdjusted(roundingDistance / 4.0f, 0.0f, (GeoUtils.TwoPI - angle) / Mathf.PI); float interpolator; int resolution = pointListProperties.CornerRounding.AdjustedResolution; float resolutionF = (float)pointListProperties.CornerRounding.AdjustedResolution - 1.0f; if (lineData.Positions.Capacity < lineData.Positions.Count + resolution) { lineData.Positions.Capacity = lineData.Positions.Count + resolution; } for (int i = 0; i < resolution; i++) { interpolator = (float)i / resolutionF; tmpPos.x = Mathf.LerpUnclamped( Mathf.LerpUnclamped(tmpBackPos.x, position.x, interpolator), Mathf.LerpUnclamped(position.x, tmpForwPos.x, interpolator), interpolator ); tmpPos.y = Mathf.LerpUnclamped( Mathf.LerpUnclamped(tmpBackPos.y, position.y, interpolator), Mathf.LerpUnclamped(position.y, tmpForwPos.y, interpolator), interpolator ); lineData.Positions.Add(tmpPos); } }
public static void AddRoundedCap( ref VertexHelper vh, bool isStart, int firstVertIndex, Vector2 position, Vector2 normal, Vector2 capOffset, int invertIndices, LineProperties lineProperties, GeoUtils.OutlineProperties outlineProperties, Color32 color, Vector2 uv, PointsList.PointsData pointsData, GeoUtils.EdgeGradientData edgeGradientData, Vector2[] capOffsets, Vector2[] uvOffsets, float uvXMin, float uvXLength, int currentVertCount ) { int baseIndex = currentVertCount; float innerOffset = outlineProperties.GetCenterDistace(); float capOffsetAmount = (edgeGradientData.ShadowOffset + outlineProperties.HalfLineWeight) * edgeGradientData.InnerScale; if (isStart) { uv.x = uvXMin; } else { uv.x = uvXMin + uvXLength; } #if CENTER_ROUNDED_CAPS // add center vert tmpPos.x = position.x; tmpPos.y = position.y; uv.y = 0.5f; vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); #endif for (int i = 0; i < capOffsets.Length; i++) { { tmpPos.x = position.x + normal.x * innerOffset + capOffsets[i].x * capOffsetAmount; tmpPos.y = position.y + normal.y * innerOffset + capOffsets[i].y * capOffsetAmount; } if (isStart) { uv.x = Mathf.LerpUnclamped(uvXMin, 0.0f, uvOffsets[i].x); } else { uv.x = Mathf.LerpUnclamped(uvXMin + uvXLength, 1.0f, uvOffsets[i].x); } uv.y = uvOffsets[i].y; vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); if (i > 0) { #if CENTER_ROUNDED_CAPS vh.AddTriangle(baseIndex, baseIndex + i - 1, baseIndex + i); #else vh.AddTriangle(firstVertIndex, baseIndex + i - 1, baseIndex + i); #endif } } // last fans if (isStart) { #if CENTER_ROUNDED_CAPS // starting triangle vh.AddTriangle(baseIndex + 1, baseIndex, firstVertIndex); // end triangles vh.AddTriangle(baseIndex, baseIndex + capOffsets.Length - 1, baseIndex + capOffsets.Length); vh.AddTriangle(baseIndex, baseIndex + capOffsets.Length, firstVertIndex + 1); #else vh.AddTriangle(baseIndex + capOffsets.Length - 1, firstVertIndex + 1, firstVertIndex); #endif } else { #if CENTER_ROUNDED_CAPS // starting triangle vh.AddTriangle(baseIndex + 1, baseIndex, firstVertIndex + 1); // end triangles vh.AddTriangle(baseIndex, baseIndex + capOffsets.Length - 1, baseIndex + capOffsets.Length); vh.AddTriangle(baseIndex, baseIndex + capOffsets.Length, firstVertIndex); #else vh.AddTriangle(baseIndex, firstVertIndex, firstVertIndex + 1); #endif } if (edgeGradientData.IsActive) { color.a = 0; innerOffset = outlineProperties.GetCenterDistace(); capOffsetAmount = outlineProperties.HalfLineWeight + edgeGradientData.SizeAdd + edgeGradientData.ShadowOffset; int antiAliasedIndex = firstVertIndex + pointsData.NumPositions * 2; for (int i = 0; i < capOffsets.Length; i++) { { tmpPos.x = position.x + normal.x * innerOffset + capOffsets[i].x * capOffsetAmount; tmpPos.y = position.y + normal.y * innerOffset + capOffsets[i].y * capOffsetAmount; } if (isStart) { uv.x = Mathf.LerpUnclamped(uvXMin, 0.0f, uvOffsets[i].x); } else { uv.x = Mathf.LerpUnclamped(uvXMin + uvXLength, 1.0f, uvOffsets[i].x); } uv.y = uvOffsets[i].y; vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); if (i > 0) { vh.AddTriangle(baseIndex + i - 1, baseIndex + capOffsets.Length + i - 1, baseIndex + i); vh.AddTriangle(baseIndex + capOffsets.Length + i, baseIndex + i, baseIndex + capOffsets.Length + i - 1); } } if (!isStart) { vh.AddTriangle(baseIndex, firstVertIndex + 1, antiAliasedIndex + 1); vh.AddTriangle(antiAliasedIndex + 1, baseIndex + capOffsets.Length, baseIndex); vh.AddTriangle(baseIndex + capOffsets.Length * 2 - 1, antiAliasedIndex, firstVertIndex); vh.AddTriangle(baseIndex + capOffsets.Length - 1, baseIndex + capOffsets.Length * 2 - 1, firstVertIndex); } else { vh.AddTriangle(firstVertIndex + 1, baseIndex + capOffsets.Length - 1, baseIndex + capOffsets.Length * 2 - 1); vh.AddTriangle(antiAliasedIndex + 1, firstVertIndex + 1, baseIndex + capOffsets.Length * 2 - 1); vh.AddTriangle(antiAliasedIndex, baseIndex, firstVertIndex); vh.AddTriangle(baseIndex + capOffsets.Length, baseIndex, antiAliasedIndex); } } }
public static void AddProjectedCap( ref VertexHelper vh, bool isStart, int firstVertIndex, Vector2 position, Vector2 normal, Vector2 capOffset, int invertIndices, LineProperties lineProperties, GeoUtils.OutlineProperties outlineProperties, Color32 color, Vector2 uv, PointsList.PointsData pointsData, GeoUtils.EdgeGradientData edgeGradientData, int currentVertCount ) { int baseIndex = currentVertCount; if (isStart) { uv.x = 0.0f; } else { uv.x = 1.0f; } float innerOffset = outlineProperties.GetCenterDistace() - (outlineProperties.HalfLineWeight + edgeGradientData.ShadowOffset) * edgeGradientData.InnerScale; float outerOffset = outlineProperties.GetCenterDistace() + (outlineProperties.HalfLineWeight + edgeGradientData.ShadowOffset) * edgeGradientData.InnerScale; float capOffsetAmount = edgeGradientData.ShadowOffset + outlineProperties.LineWeight * 0.5f; capOffsetAmount *= edgeGradientData.InnerScale; // add lineWeight to position { tmpPos.x = position.x + normal.x * innerOffset + capOffset.x * capOffsetAmount; tmpPos.y = position.y + normal.y * innerOffset + capOffset.y * capOffsetAmount; } uv.y = 0.0f; vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); { tmpPos.x = position.x + normal.x * outerOffset + capOffset.x * capOffsetAmount; tmpPos.y = position.y + normal.y * outerOffset + capOffset.y * capOffsetAmount; } uv.y = 1.0f; vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); vh.AddTriangle(firstVertIndex, baseIndex + invertIndices, baseIndex + 1 - invertIndices); vh.AddTriangle(firstVertIndex + invertIndices, baseIndex + 1, firstVertIndex + 1 - invertIndices); if (edgeGradientData.IsActive) { innerOffset = outlineProperties.GetCenterDistace() - (outlineProperties.HalfLineWeight + edgeGradientData.ShadowOffset) - edgeGradientData.SizeAdd; outerOffset = outlineProperties.GetCenterDistace() + (outlineProperties.HalfLineWeight + edgeGradientData.ShadowOffset) + edgeGradientData.SizeAdd; capOffsetAmount = outlineProperties.HalfLineWeight + edgeGradientData.SizeAdd + edgeGradientData.ShadowOffset; color.a = 0; { tmpPos.x = position.x + normal.x * innerOffset + capOffset.x * capOffsetAmount; tmpPos.y = position.y + normal.y * innerOffset + capOffset.y * capOffsetAmount; } uv.y = 0.0f; vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); { tmpPos.x = position.x + normal.x * outerOffset + capOffset.x * capOffsetAmount; tmpPos.y = position.y + normal.y * outerOffset + capOffset.y * capOffsetAmount; } uv.y = 1.0f; vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); int antiAliasedIndex = firstVertIndex + pointsData.NumPositions * 2; baseIndex += 2; if (invertIndices != 0) { vh.AddTriangle(firstVertIndex, baseIndex, antiAliasedIndex); vh.AddTriangle(firstVertIndex + 1, antiAliasedIndex + 1, baseIndex + 1); vh.AddTriangle(baseIndex - 2, baseIndex - 1, baseIndex); vh.AddTriangle(baseIndex + 1, baseIndex, baseIndex - 1); vh.AddTriangle(firstVertIndex, baseIndex - 2, baseIndex); vh.AddTriangle(firstVertIndex + 1, baseIndex + 1, baseIndex - 1); } else { vh.AddTriangle(firstVertIndex, antiAliasedIndex, baseIndex); vh.AddTriangle(firstVertIndex + 1, baseIndex + 1, antiAliasedIndex + 1); vh.AddTriangle(baseIndex - 2, baseIndex, baseIndex - 1); vh.AddTriangle(baseIndex + 1, baseIndex - 1, baseIndex); vh.AddTriangle(firstVertIndex, baseIndex, baseIndex - 2); vh.AddTriangle(firstVertIndex + 1, baseIndex - 1, baseIndex + 1); } } }
public static void AddEndCap( ref VertexHelper vh, LineProperties lineProperties, Vector2 positionOffset, GeoUtils.OutlineProperties outlineProperties, Color32 color, Vector2 uv, float uvXMin, float uvXLength, PointsList.PointsData pointsData, GeoUtils.EdgeGradientData edgeGradientData ) { int currentVertCount = vh.currentVertCount; int startIndex = currentVertCount; if (edgeGradientData.IsActive) { startIndex -= pointsData.NumPositions * 2; } int lastPositionIndex = pointsData.NumPositions - 1; tmpPos2.x = positionOffset.x + pointsData.Positions[lastPositionIndex].x; tmpPos2.y = positionOffset.y + pointsData.Positions[lastPositionIndex].y; switch (lineProperties.LineCap) { case LineProperties.LineCapTypes.Close: startIndex -= 4; AddCloseCap( ref vh, false, startIndex, tmpPos2, pointsData.PositionNormals[lastPositionIndex], pointsData.EndCapOffset, 1, lineProperties, outlineProperties, color, uv, pointsData, edgeGradientData, currentVertCount ); break; case LineProperties.LineCapTypes.Projected: startIndex -= 6; AddProjectedCap( ref vh, false, startIndex, tmpPos2, pointsData.PositionNormals[lastPositionIndex], pointsData.EndCapOffset, 1, lineProperties, outlineProperties, color, uv, pointsData, edgeGradientData, currentVertCount ); break; case LineProperties.LineCapTypes.Round: #if CENTER_ROUNDED_CAPS startIndex -= pointsData.RoundedCapResolution + 3; #else startIndex -= pointsData.RoundedCapResolution + 2; #endif if (edgeGradientData.IsActive) { startIndex -= pointsData.RoundedCapResolution; } AddRoundedCap( ref vh, false, startIndex, tmpPos2, pointsData.PositionNormals[lastPositionIndex], pointsData.EndCapOffset, 1, lineProperties, outlineProperties, color, uv, pointsData, edgeGradientData, pointsData.EndCapOffsets, pointsData.EndCapUVs, uvXMin, uvXLength, currentVertCount ); break; } }
public static void AddLine( ref VertexHelper vh, LineProperties lineProperties, PointsList.PointListProperties pointListProperties, Vector2 positionOffset, GeoUtils.OutlineProperties outlineProperties, Color32 color, Vector2 uv, ref PointsList.PointsData pointsData, GeoUtils.EdgeGradientData edgeGradientData ) { pointListProperties.SetPoints(); pointsData.IsClosed = lineProperties.Closed && pointListProperties.Positions.Length > 2; pointsData.GenerateRoundedCaps = lineProperties.LineCap == LineProperties.LineCapTypes.Round; pointsData.LineWeight = outlineProperties.LineWeight; if (pointsData.GenerateRoundedCaps) { lineProperties.RoundedCapResolution.UpdateAdjusted(outlineProperties.HalfLineWeight, 0.0f, 2.0f); pointsData.RoundedCapResolution = lineProperties.RoundedCapResolution.AdjustedResolution; } if (!PointsList.SetLineData(pointListProperties, ref pointsData)) { return; } // scale uv x for caps float uvXMin = 0.0f; float uvXLength = 1.0f; if ( !lineProperties.Closed && lineProperties.LineCap != LineProperties.LineCapTypes.Close ) { float uvStartOffset = outlineProperties.LineWeight / pointsData.TotalLength; uvXMin = uvStartOffset * 0.5f; uvXLength = 1.0f - uvXMin * 2.0f; } float innerOffset = outlineProperties.GetCenterDistace() - (outlineProperties.HalfLineWeight + edgeGradientData.ShadowOffset) * edgeGradientData.InnerScale; float outerOffset = outlineProperties.GetCenterDistace() + (outlineProperties.HalfLineWeight + edgeGradientData.ShadowOffset) * edgeGradientData.InnerScale; float capOffsetAmount = 0.0f; if (!lineProperties.Closed && lineProperties.LineCap == LineProperties.LineCapTypes.Close) { capOffsetAmount = edgeGradientData.ShadowOffset * (edgeGradientData.InnerScale * 2.0f - 1.0f); } int numVertices = vh.currentVertCount; int startVertex = numVertices - 1; int baseIndex; uv.x = uvXMin + pointsData.NormalizedPositionDistances[0] * uvXLength; uv.y = 0.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[0].x + pointsData.PositionNormals[0].x * innerOffset + pointsData.StartCapOffset.x * capOffsetAmount; tmpPos.y = positionOffset.y + pointsData.Positions[0].y + pointsData.PositionNormals[0].y * innerOffset + pointsData.StartCapOffset.y * capOffsetAmount; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); uv.y = 1.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[0].x + pointsData.PositionNormals[0].x * outerOffset + pointsData.StartCapOffset.x * capOffsetAmount; tmpPos.y = positionOffset.y + pointsData.Positions[0].y + pointsData.PositionNormals[0].y * outerOffset + pointsData.StartCapOffset.y * capOffsetAmount; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); for (int i = 1; i < pointsData.NumPositions - 1; i++) { uv.x = uvXMin + pointsData.NormalizedPositionDistances[i] * uvXLength; uv.y = 0.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[i].x + pointsData.PositionNormals[i].x * innerOffset; tmpPos.y = positionOffset.y + pointsData.Positions[i].y + pointsData.PositionNormals[i].y * innerOffset; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); uv.y = 1.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[i].x + pointsData.PositionNormals[i].x * outerOffset; tmpPos.y = positionOffset.y + pointsData.Positions[i].y + pointsData.PositionNormals[i].y * outerOffset; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); baseIndex = startVertex + i * 2; vh.AddTriangle(baseIndex - 1, baseIndex, baseIndex + 1); vh.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 1); } // add end vertices int endIndex = pointsData.NumPositions - 1; uv.x = uvXMin + pointsData.NormalizedPositionDistances[endIndex] * uvXLength; uv.y = 0.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[endIndex].x + pointsData.PositionNormals[endIndex].x * innerOffset + pointsData.EndCapOffset.x * capOffsetAmount; tmpPos.y = positionOffset.y + pointsData.Positions[endIndex].y + pointsData.PositionNormals[endIndex].y * innerOffset + pointsData.EndCapOffset.y * capOffsetAmount; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); uv.y = 1.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[endIndex].x + pointsData.PositionNormals[endIndex].x * outerOffset + pointsData.EndCapOffset.x * capOffsetAmount; tmpPos.y = positionOffset.y + pointsData.Positions[endIndex].y + pointsData.PositionNormals[endIndex].y * outerOffset + pointsData.EndCapOffset.y * capOffsetAmount; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); baseIndex = startVertex + endIndex * 2; vh.AddTriangle(baseIndex - 1, baseIndex, baseIndex + 1); vh.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 1); if (lineProperties.Closed) { uv.x = 1.0f; uv.y = 0.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[0].x + pointsData.PositionNormals[0].x * innerOffset + pointsData.StartCapOffset.x * capOffsetAmount; tmpPos.y = positionOffset.y + pointsData.Positions[0].y + pointsData.PositionNormals[0].y * innerOffset + pointsData.StartCapOffset.y * capOffsetAmount; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); uv.y = 1.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[0].x + pointsData.PositionNormals[0].x * outerOffset + pointsData.StartCapOffset.x * capOffsetAmount; tmpPos.y = positionOffset.y + pointsData.Positions[0].y + pointsData.PositionNormals[0].y * outerOffset + pointsData.StartCapOffset.y * capOffsetAmount; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); baseIndex = startVertex + endIndex * 2 + 2; vh.AddTriangle(baseIndex - 1, baseIndex, baseIndex + 1); vh.AddTriangle(baseIndex, baseIndex + 2, baseIndex + 1); } if (edgeGradientData.IsActive) { byte colorAlpha = color.a; innerOffset = outlineProperties.GetCenterDistace() - (outlineProperties.HalfLineWeight + edgeGradientData.ShadowOffset); outerOffset = outlineProperties.GetCenterDistace() + (outlineProperties.HalfLineWeight + edgeGradientData.ShadowOffset); innerOffset -= edgeGradientData.SizeAdd; outerOffset += edgeGradientData.SizeAdd; color.a = 0; int outerBaseIndex = numVertices + pointsData.NumPositions * 2; if (lineProperties.Closed) { outerBaseIndex += 2; } uv.x = uvXMin + pointsData.NormalizedPositionDistances[0] * uvXLength; uv.y = 0.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[0].x + pointsData.PositionNormals[0].x * innerOffset; tmpPos.y = positionOffset.y + pointsData.Positions[0].y + pointsData.PositionNormals[0].y * innerOffset; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); uv.y = 1.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[0].x + pointsData.PositionNormals[0].x * outerOffset; tmpPos.y = positionOffset.y + pointsData.Positions[0].y + pointsData.PositionNormals[0].y * outerOffset; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); for (int i = 1; i < pointsData.NumPositions; i++) { uv.x = uvXMin + pointsData.NormalizedPositionDistances[i] * uvXLength; uv.y = 0.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[i].x + pointsData.PositionNormals[i].x * innerOffset; tmpPos.y = positionOffset.y + pointsData.Positions[i].y + pointsData.PositionNormals[i].y * innerOffset; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); uv.y = 1.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[i].x + pointsData.PositionNormals[i].x * outerOffset; tmpPos.y = positionOffset.y + pointsData.Positions[i].y + pointsData.PositionNormals[i].y * outerOffset; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); // inner quad vh.AddTriangle(startVertex + i * 2 - 1, startVertex + i * 2 + 1, outerBaseIndex + i * 2); vh.AddTriangle(startVertex + i * 2 - 1, outerBaseIndex + i * 2, outerBaseIndex + i * 2 - 2); // outer quad vh.AddTriangle(startVertex + i * 2, outerBaseIndex + i * 2 - 1, startVertex + i * 2 + 2); vh.AddTriangle(startVertex + i * 2 + 2, outerBaseIndex + i * 2 - 1, outerBaseIndex + i * 2 + 1); } if (lineProperties.Closed) { int lastIndex = pointsData.NumPositions; uv.x = 1.0f; uv.y = 0.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[0].x + pointsData.PositionNormals[0].x * innerOffset; tmpPos.y = positionOffset.y + pointsData.Positions[0].y + pointsData.PositionNormals[0].y * innerOffset; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); uv.y = 1.0f; { tmpPos.x = positionOffset.x + pointsData.Positions[0].x + pointsData.PositionNormals[0].x * outerOffset; tmpPos.y = positionOffset.y + pointsData.Positions[0].y + pointsData.PositionNormals[0].y * outerOffset; } vh.AddVert(tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); // inner quad vh.AddTriangle(startVertex + lastIndex * 2 - 1, startVertex + lastIndex * 2 + 1, outerBaseIndex + lastIndex * 2); vh.AddTriangle(startVertex + lastIndex * 2 - 1, outerBaseIndex + lastIndex * 2, outerBaseIndex + lastIndex * 2 - 2); // outer quad vh.AddTriangle(startVertex + lastIndex * 2, outerBaseIndex + lastIndex * 2 - 1, startVertex + lastIndex * 2 + 2); vh.AddTriangle(startVertex + lastIndex * 2 + 2, outerBaseIndex + lastIndex * 2 - 1, outerBaseIndex + lastIndex * 2 + 1); } color.a = colorAlpha; } // close line or add caps if (!lineProperties.Closed) { AddStartCap( ref vh, lineProperties, positionOffset, outlineProperties, color, uv, uvXMin, uvXLength, pointsData, edgeGradientData ); AddEndCap( ref vh, lineProperties, positionOffset, outlineProperties, color, uv, uvXMin, uvXLength, pointsData, edgeGradientData ); } }
public static void AddStartCap( ref VertexHelper vh, LineProperties lineProperties, Vector2 positionOffset, GeoUtils.OutlineProperties outlineProperties, Color32 color, Vector2 uv, float uvXMin, float uvXLength, PointsList.PointsData pointsData, GeoUtils.EdgeGradientData edgeGradientData ) { int currentVertCount = vh.currentVertCount; int startIndex = currentVertCount - pointsData.NumPositions * 2; if (edgeGradientData.IsActive) { startIndex -= pointsData.NumPositions * 2; } tmpPos2.x = positionOffset.x + pointsData.Positions[0].x; tmpPos2.y = positionOffset.y + pointsData.Positions[0].y; switch (lineProperties.LineCap) { case LineProperties.LineCapTypes.Close: AddCloseCap( ref vh, true, startIndex, tmpPos2, pointsData.PositionNormals[0], pointsData.StartCapOffset, 0, lineProperties, outlineProperties, color, uv, pointsData, edgeGradientData, currentVertCount ); break; case LineProperties.LineCapTypes.Projected: AddProjectedCap( ref vh, true, startIndex, tmpPos2, pointsData.PositionNormals[0], pointsData.StartCapOffset, 0, lineProperties, outlineProperties, color, uv, pointsData, edgeGradientData, currentVertCount ); break; case LineProperties.LineCapTypes.Round: AddRoundedCap( ref vh, true, startIndex, tmpPos2, pointsData.PositionNormals[0], pointsData.StartCapOffset, 0, lineProperties, outlineProperties, color, uv, pointsData, edgeGradientData, pointsData.StartCapOffsets, pointsData.StartCapUVs, uvXMin, uvXLength, currentVertCount ); break; } }
public static void AddPolygon( ref VertexHelper vh, PolygonProperties polygonProperties, PointsList.PointListProperties pointListProperties, Vector2 positionOffset, Color32 color, Vector2 uv, ref PointsList.PointsData pointsData, GeoUtils.EdgeGradientData edgeGradientData ) { pointListProperties.SetPoints(); PointsList.SetLineData(pointListProperties, ref pointsData); int numVertices = vh.currentVertCount; int firstOuterVertex = vh.currentVertCount + polygonProperties.CutoutProperties.Resolution - 1; bool usesCutout = polygonProperties.CenterType == PolygonProperties.CenterTypes.Cutout; if (usesCutout) { float cutoutOffsetDistance = polygonProperties.CutoutProperties.Radius - edgeGradientData.ShadowOffset; cutoutOffsetDistance += Mathf.LerpUnclamped( pointsData.PositionNormals[0].magnitude * edgeGradientData.ShadowOffset * 3.0f, 0.0f, edgeGradientData.InnerScale ); for (int i = 0; i < polygonProperties.CutoutProperties.Resolution; i++) { tmpPos.x = polygonProperties.AdjustedCenter.x + positionOffset.x + polygonProperties.CutoutProperties.UnitPositionData.UnitPositions[i].x * cutoutOffsetDistance; tmpPos.y = polygonProperties.AdjustedCenter.y + positionOffset.y + polygonProperties.CutoutProperties.UnitPositionData.UnitPositions[i].y * cutoutOffsetDistance; tmpPos.z = 0.0f; vh.AddVert( tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent ); } } else { // add center tmpPos.x = polygonProperties.AdjustedCenter.x + positionOffset.x; tmpPos.y = polygonProperties.AdjustedCenter.y + positionOffset.y; tmpPos.z = 0.0f; vh.AddVert( tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent ); } // add first position tmpPos.x = positionOffset.x + Mathf.LerpUnclamped( polygonProperties.AdjustedCenter.x, pointsData.Positions[0].x + pointsData.PositionNormals[0].x * edgeGradientData.ShadowOffset, edgeGradientData.InnerScale ); tmpPos.y = positionOffset.y + Mathf.LerpUnclamped( polygonProperties.AdjustedCenter.y, pointsData.Positions[0].y + pointsData.PositionNormals[0].y * edgeGradientData.ShadowOffset, edgeGradientData.InnerScale ); tmpPos.z = 0.0f; vh.AddVert( tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent ); for (int i = 1; i < pointsData.NumPositions; i++) { tmpPos.x = positionOffset.x + Mathf.LerpUnclamped( polygonProperties.AdjustedCenter.x, pointsData.Positions[i].x + pointsData.PositionNormals[i].x * edgeGradientData.ShadowOffset, edgeGradientData.InnerScale ); tmpPos.y = positionOffset.y + Mathf.LerpUnclamped( polygonProperties.AdjustedCenter.y, pointsData.Positions[i].y + pointsData.PositionNormals[i].y * edgeGradientData.ShadowOffset, edgeGradientData.InnerScale ); vh.AddVert( tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent ); if (!usesCutout) { vh.AddTriangle(numVertices, numVertices + i, numVertices + i + 1); } } // add cutout indices if (usesCutout) { for (int i = 1; i < pointsData.NumPositions; i++) { vh.AddTriangle( numVertices + GeoUtils.SimpleMap(i, pointsData.NumPositions, polygonProperties.CutoutProperties.Resolution), firstOuterVertex + i, firstOuterVertex + i + 1 ); } for (int i = 1; i < polygonProperties.CutoutProperties.Resolution; i++) { vh.AddTriangle( numVertices + i, numVertices + i - 1, firstOuterVertex + Mathf.CeilToInt(GeoUtils.SimpleMap((float)i, (float)polygonProperties.CutoutProperties.Resolution, (float)pointsData.NumPositions)) ); } } // add last triangle if (usesCutout) { vh.AddTriangle( numVertices, firstOuterVertex + pointsData.NumPositions, firstOuterVertex + 1 ); vh.AddTriangle( numVertices, firstOuterVertex, firstOuterVertex + pointsData.NumPositions ); } else { vh.AddTriangle(numVertices, numVertices + pointsData.NumPositions, numVertices + 1); } if (edgeGradientData.IsActive) { color.a = 0; int outerFirstIndex = numVertices + pointsData.NumPositions; if (usesCutout) { outerFirstIndex = firstOuterVertex + pointsData.NumPositions; } else { firstOuterVertex = numVertices; } float offset = edgeGradientData.SizeAdd + edgeGradientData.ShadowOffset; vh.AddVert(positionOffset + pointsData.Positions[0] + pointsData.PositionNormals[0] * offset, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); for (int i = 1; i < pointsData.NumPositions; i++) { vh.AddVert(positionOffset + pointsData.Positions[i] + pointsData.PositionNormals[i] * offset, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent); vh.AddTriangle(firstOuterVertex + i + 1, outerFirstIndex + i, outerFirstIndex + i + 1); vh.AddTriangle(firstOuterVertex + i + 1, outerFirstIndex + i + 1, firstOuterVertex + i + 2); } // fill last outer quad vh.AddTriangle(firstOuterVertex + 1, outerFirstIndex, outerFirstIndex + 1); vh.AddTriangle(firstOuterVertex + 2, firstOuterVertex + 1, outerFirstIndex + 1); if (usesCutout) { float radius = (polygonProperties.CutoutProperties.Radius - offset); for (int i = 0; i < polygonProperties.CutoutProperties.Resolution; i++) { tmpPos.x = polygonProperties.AdjustedCenter.x + positionOffset.x + polygonProperties.CutoutProperties.UnitPositionData.UnitPositions[i].x * radius; tmpPos.y = polygonProperties.AdjustedCenter.y + positionOffset.y + polygonProperties.CutoutProperties.UnitPositionData.UnitPositions[i].y * radius; tmpPos.z = 0.0f; vh.AddVert( tmpPos, color, uv, GeoUtils.ZeroV2, GeoUtils.UINormal, GeoUtils.UITangent ); } for (int i = 1; i < polygonProperties.CutoutProperties.Resolution; i++) { vh.AddTriangle( numVertices + i - 1, numVertices + i, outerFirstIndex + pointsData.NumPositions + i ); vh.AddTriangle( numVertices + i, outerFirstIndex + pointsData.NumPositions + i + 1, outerFirstIndex + pointsData.NumPositions + i ); } vh.AddTriangle( firstOuterVertex, numVertices, outerFirstIndex + pointsData.NumPositions + polygonProperties.CutoutProperties.Resolution ); vh.AddTriangle( numVertices, outerFirstIndex + pointsData.NumPositions + 1, outerFirstIndex + pointsData.NumPositions + polygonProperties.CutoutProperties.Resolution ); } } }
public static bool SetLineData( PointListProperties pointListProperties, ref PointsList.PointsData lineData ) { if ( pointListProperties.Positions == null || pointListProperties.Positions.Length <= 1 ) { return(false); } bool needsUpdate = lineData.NeedsUpdate || lineData.Positions == null; if (needsUpdate) { SetPositions( pointListProperties, ref lineData ); } int numPositions = lineData.NumPositions; if ( lineData.PositionNormals == null || lineData.PositionNormals.Length != numPositions ) { lineData.PositionTangents = new Vector2[numPositions]; lineData.PositionNormals = new Vector2[numPositions]; lineData.PositionDistances = new float[numPositions]; lineData.NormalizedPositionDistances = new float[numPositions]; for (int i = 0; i < numPositions; i++) { lineData.PositionNormals[i] = GeoUtils.ZeroV2; lineData.PositionTangents[i] = GeoUtils.ZeroV2; } needsUpdate = true; } if (needsUpdate) { int numPositionsMinusOne = numPositions - 1; lineData.TotalLength = 0.0f; float distance; Vector2 lastUnitTangent = GeoUtils.ZeroV2; Vector2 currentUnitTangent = GeoUtils.ZeroV2; // set data for first point if (!lineData.IsClosed) { lineData.PositionTangents[0].x = lineData.Positions[0].x - lineData.Positions[1].x; lineData.PositionTangents[0].y = lineData.Positions[0].y - lineData.Positions[1].y; distance = Mathf.Sqrt( lineData.PositionTangents[0].x * lineData.PositionTangents[0].x + lineData.PositionTangents[0].y * lineData.PositionTangents[0].y ); lineData.PositionDistances[0] = distance; lineData.TotalLength += distance; lineData.PositionNormals[0].x = lineData.PositionTangents[0].y / distance; lineData.PositionNormals[0].y = -lineData.PositionTangents[0].x / distance; lastUnitTangent.x = -lineData.PositionTangents[0].x / distance; lastUnitTangent.y = -lineData.PositionTangents[0].y / distance; lineData.StartCapOffset.x = -lastUnitTangent.x; lineData.StartCapOffset.y = -lastUnitTangent.y; } else { lastUnitTangent.x = lineData.Positions[0].x - lineData.Positions[numPositionsMinusOne].x; lastUnitTangent.y = lineData.Positions[0].y - lineData.Positions[numPositionsMinusOne].y; distance = Mathf.Sqrt( lastUnitTangent.x * lastUnitTangent.x + lastUnitTangent.y * lastUnitTangent.y ); lastUnitTangent.x /= distance; lastUnitTangent.y /= distance; SetPointData( lineData.Positions[0], lineData.Positions[1], ref currentUnitTangent, ref lineData.PositionTangents[0], ref lineData.PositionNormals[0], ref lastUnitTangent, ref lineData.PositionDistances[0] ); lineData.TotalLength += lineData.PositionDistances[0]; } for (int i = 1; i < numPositionsMinusOne; i++) { SetPointData( lineData.Positions[i], lineData.Positions[i + 1], ref currentUnitTangent, ref lineData.PositionTangents[i], ref lineData.PositionNormals[i], ref lastUnitTangent, ref lineData.PositionDistances[i] ); lineData.TotalLength += lineData.PositionDistances[i]; } // set data for last point if (!lineData.IsClosed) { lineData.PositionTangents[numPositionsMinusOne].x = lineData.Positions[numPositionsMinusOne].x - lineData.Positions[numPositionsMinusOne - 1].x; lineData.PositionTangents[numPositionsMinusOne].y = lineData.Positions[numPositionsMinusOne].y - lineData.Positions[numPositionsMinusOne - 1].y; distance = Mathf.Sqrt( lineData.PositionTangents[numPositionsMinusOne].x * lineData.PositionTangents[numPositionsMinusOne].x + lineData.PositionTangents[numPositionsMinusOne].y * lineData.PositionTangents[numPositionsMinusOne].y ); lineData.EndCapOffset.x = lineData.PositionTangents[numPositionsMinusOne].x / distance; lineData.EndCapOffset.y = lineData.PositionTangents[numPositionsMinusOne].y / distance; lineData.PositionNormals[numPositionsMinusOne].x = -lineData.PositionTangents[numPositionsMinusOne].y / distance; lineData.PositionNormals[numPositionsMinusOne].y = lineData.PositionTangents[numPositionsMinusOne].x / distance; } else { SetPointData( lineData.Positions[numPositionsMinusOne], lineData.Positions[0], ref currentUnitTangent, ref lineData.PositionTangents[numPositionsMinusOne], ref lineData.PositionNormals[numPositionsMinusOne], ref lastUnitTangent, ref lineData.PositionDistances[numPositionsMinusOne] ); lineData.TotalLength += lineData.PositionDistances[numPositionsMinusOne]; } if (lineData.GenerateRoundedCaps) { SetRoundedCapPointData( Mathf.Atan2(-lineData.PositionNormals[0].x, -lineData.PositionNormals[0].y), ref lineData.StartCapOffsets, ref lineData.StartCapUVs, lineData.RoundedCapResolution, true ); SetRoundedCapPointData( Mathf.Atan2(lineData.PositionNormals[numPositionsMinusOne].x, lineData.PositionNormals[numPositionsMinusOne].y), ref lineData.EndCapOffsets, ref lineData.EndCapUVs, lineData.RoundedCapResolution, false ); } float accumulatedLength = 0.0f; for (int i = 0; i < lineData.PositionDistances.Length; i++) { lineData.NormalizedPositionDistances[i] = accumulatedLength / lineData.TotalLength; accumulatedLength += lineData.PositionDistances[i]; } } lineData.NeedsUpdate = false; return(true); }
public static void SetPositions( PointListProperties pointListProperties, ref PointsList.PointsData lineData ) { if (lineData.Positions == null) { lineData.Positions = new List <Vector2>(pointListProperties.Positions.Length); } CheckMinPointDistances( ref pointListProperties.Positions, ref tmpCachedPositions, lineData.LineWeight * 0.5f, lineData.IsClosed ); lineData.Positions.Clear(); int inputNumPositions = tmpCachedPositions.Count; if (lineData.Positions.Capacity < inputNumPositions) { lineData.Positions.Capacity = lineData.Positions.Capacity + inputNumPositions + 1; } // add first position if (lineData.IsClosed) { InterpolatePoints( ref lineData, tmpCachedPositions[inputNumPositions - 1], tmpCachedPositions[0], tmpCachedPositions[1], pointListProperties, 0 ); } else { lineData.Positions.Add(tmpCachedPositions[0]); } for (int i = 1; i < inputNumPositions - 1; i++) { InterpolatePoints( ref lineData, tmpCachedPositions[i - 1], tmpCachedPositions[i], tmpCachedPositions[i + 1], pointListProperties, i ); } // add end point if (lineData.IsClosed) { InterpolatePoints( ref lineData, tmpCachedPositions[inputNumPositions - 2], tmpCachedPositions[inputNumPositions - 1], tmpCachedPositions[0], pointListProperties, inputNumPositions - 1 ); } else { lineData.Positions.Add(tmpCachedPositions[inputNumPositions - 1]); } lineData.NumPositions = lineData.Positions.Count; }