public void SetBezierCurve(Vector2 anchorA, Vector2 controlA, Vector2 controlB, Vector2 anchorB, int resolution = 32) { if (resolution < 3) { resolution = 3; } if (_points == null || _points.Length != resolution) { _points = new Vector2[resolution]; } _points[0] = anchorA; _points[resolution - 1] = anchorB; for (int r = 1; r < resolution - 1; r++) { float t = r / (resolution - 1f); float x = DrawMath.QuadraticInterpolation(anchorA.x, controlA.x, controlB.x, anchorB.x, t); float y = DrawMath.QuadraticInterpolation(anchorA.y, controlA.y, controlB.y, anchorB.y, t); _points[r] = new Vector2(x, y); } _isDirty = true; }
void Build() { if (!_mesh) { _mesh = new Mesh(); _mesh.hideFlags = HideFlags.HideAndDontSave; } if (_points.Length < 2) { _mesh.Clear(); return; } int pointCount = _points.Length; int vertexCount = 4 + (pointCount - 2) * 4; int quadIndexCount = (pointCount - 1) * 4; if (_mesh.vertexCount != vertexCount) { _mesh.Clear(); } if (_vertices == null || _vertices.Length != vertexCount) { _vertices = new Vector3[vertexCount]; _uv0 = new Vector4[vertexCount]; _uv1 = new Vector2[vertexCount]; _indices = new int[quadIndexCount]; _isDirty = true; } DrawMath.ComputeNormalizedDirections(_points, ref _directions); float halfStrokeThickness = _strokeThickness * 0.5f; int lastIndex = pointCount - 1; int i = 0, v = 0; Vector2 prev = Vector2.zero; Vector2 prevOffset = Vector2.zero; Vector2 nextPoint = Vector2.zero; for (int p = 0; p < pointCount; p++) { int v0 = v; Vector2 point = _points[p]; Vector2 dir = _directions[p]; Vector2 offset = new Vector2(-dir.y * halfStrokeThickness, dir.x * halfStrokeThickness); // Rotate 45 degrees and scale if (p < lastIndex) { nextPoint = _points[p + 1]; } if (p == 0 && _beginCap != Cap.None) { point -= dir * halfStrokeThickness; } else if (p == lastIndex - 1 && _endCap != Cap.None) { nextPoint += dir * halfStrokeThickness; } else if (p == lastIndex && _endCap != Cap.None) { point += dir * halfStrokeThickness; } if (p == 0 || p == lastIndex) { // Two verts for begin and end. _vertices[v++] = point + offset; _vertices[v++] = point - offset; } else { // Four verts for inner points. Vector2 intersection; if (DrawMath.TryIntersectLineLine(prev + prevOffset, point + prevOffset, point + offset, nextPoint + offset, out intersection)) { _vertices[v++] = intersection; } else { _vertices[v++] = point + offset; } if (DrawMath.TryIntersectLineLine(prev - prevOffset, point - prevOffset, point - offset, nextPoint - offset, out intersection)) { _vertices[v++] = intersection; } else { _vertices[v++] = point - offset; } _vertices[v++] = _vertices[v - 3]; _vertices[v++] = _vertices[v - 3]; v0 += 2; } if (p < lastIndex) { Vector4 points; Vector2 roundedCapFlags; if (p == 0) { points = new Vector4(point.x + dir.x * halfStrokeThickness, point.y + dir.y * halfStrokeThickness, nextPoint.x, nextPoint.y); roundedCapFlags = new Vector2(_beginCap == Cap.Round ? 1 : 0, 1); } else if (p == lastIndex - 1) { points = new Vector4(point.x, point.y, nextPoint.x - dir.x * halfStrokeThickness, nextPoint.y - dir.y * halfStrokeThickness); roundedCapFlags = new Vector2(1, _endCap == Cap.Round ? 1 : 0); } else { points = new Vector4(point.x, point.y, nextPoint.x, nextPoint.y); roundedCapFlags = Vector2.one; } for (int j = 0, vn = v0; j < 4; j++, vn++) { _uv0[vn] = points; _uv1[vn] = roundedCapFlags; } _indices[i++] = v0; _indices[i++] = v0 + 2; _indices[i++] = v0 + 3; _indices[i++] = v0 + 1; } prev = point; prevOffset = offset; } _mesh.SetVertices(_vertices); _mesh.SetUVs(0, _uv0); _mesh.SetUVs(1, _uv1); _mesh.SetIndices(_indices, MeshTopology.Quads, 0); _mesh.RecalculateBounds(); _isDirty = false; }