UGUI绘制过多点连续的平滑曲线

来源:互联网 发布:阿里巴巴一件代发淘宝 编辑:程序博客网 时间:2024/06/05 08:18

绘制

实现自定义的MaskableGraphic挂载在UGUI的UI节点上

public class UGUIObjectRender : MaskableGraphic{    /**    * points 为需要穿过的点    * segments 为曲线细分度    * linewidth 为曲线粗细    */    protected override void OnPopulateMesh(VertexHelper vh)    {        vh.DrawBeziers(points,segments,linewidth);    }}

需要时用的工具类在后面

二次贝塞尔工具类

using UnityEngine;namespace ViVi.UIExtensions{/** * Created by vivi on 16/5/11. */    public class BezierUtils {        public float P0x;        public float P1x;        public float P2x;        public float P3x;        public float P0y;        public float P1y;        public float P2y;        public float P3y;        public  BezierUtils(float p0x,float p0y,float p1x,float p1y,float p2x,float p2y,float p3x,float p3y) {            P0x = p0x;            P0y = p0y;            P1x = p1x;            P1y = p1y;            P2x = p2x;            P2y = p2y;            P3x = p3x;            P3y = p3y;        }        public  BezierUtils(Vector2 p0,Vector2 p1,Vector2 p2,Vector2 p3) {            P0x = p0.x;            P0y = p0.y;            P1x = p1.x;            P1y = p1.y;            P2x = p2.x;            P2y = p2.y;            P3x = p3.x;            P3y = p3.y;        }        public float beze_x(float t){            float it = 1-t;            return it*it*it*P0x + 3*it*it*t*P1x + 3*it*t*t*P2x + t*t*t*P3x;        }        public float beze_y(float t){            float it = 1-t;            return it*it*it*P0y + 3*it*it*t*P1y + 3*it*t*t*P2y + t*t*t*P3y;        }        //-------------------------------------------------------------------------------------        public float beze_speed_x(float t)        {            float it = 1-t;            return -3*P0x*it*it + 3*P1x*it*it - 6*P1x*it*t + 6*P2x*it*t - 3*P2x*t*t + 3*P3x*t*t;        }        public float beze_speed_y(float t)        {            float it = 1-t;            return -3*P0y*it*it + 3*P1y*it*it - 6*P1y*it*t + 6*P2y*it*t - 3*P2y*t*t + 3*P3y*t*t;        }        private float beze_speed(float t)        {            float sx = beze_speed_x(t);            float sy = beze_speed_y(t);            return (float) Mathf.Sqrt(Mathf.Pow(sx,2)+Mathf.Pow(sy,2));        }        //-------------------------------------------------------------------------------------        private float beze_length(float t)        {            float LATESTCOUNT = 10000;            int steps = (int) Mathf.Ceil(LATESTCOUNT * t);            if (steps == 0)                return 0;            if (steps % 2 != 0)                steps++;            float halfSteps = steps * .5f;            float nSum = 0;            float n1Sum = 0;            float disStep = t / steps;            for (int i = 0; i < halfSteps; i++ ) {                n1Sum += beze_speed((2 * i + 1) * disStep);                nSum += beze_speed(2 * i * disStep);            }            return (beze_speed(0) + beze_speed(1) + 2 * n1Sum + 4 * nSum) * disStep / 3;        }        //-------------------------------------------------------------------------------------        private float beze_even(float t)        {            float len = t * beze_length(1);            float uc = 0;            do {                float ulen = beze_length(t);                float uspeed = beze_speed(t);                uc = t - (ulen - len) / uspeed;                if (Mathf.Abs(uc - t) < 0.0001)                    break;                t = uc;            }while(true);            return uc;        }        private float totallength = -1;        public float getTotalLength(){            if(totallength<0)                totallength = beze_length(1);            return totallength;        }        public Vector2 getPosition(float t){            return new Vector2(beze_x(t),beze_y(t));        }    }}

UGUI 绘图工具类

using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;namespace ViVi.UIExtensions{    public static class PolygonHelper    {        public static void AddUIVertexTriangles(this VertexHelper vh,UIVertex[] verts)        {            for (int i = 0; i < verts.Length; i += 3)            {                int currentVertCount = vh.currentVertCount;                for (int index = i; index < i+3; index++)                {                    vh.AddVert(verts[index].position, verts[index].color, verts[index].uv0, verts[index].uv1, verts[index].normal, verts[index].tangent);                }                vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);            }        }        public static void AddUIVertexTriangle(this VertexHelper vh,UIVertex[] verts)        {            int currentVertCount = vh.currentVertCount;            for (int index = 0; index < 3; ++index)                vh.AddVert(verts[index].position, verts[index].color, verts[index].uv0, verts[index].uv1, verts[index].normal, verts[index].tangent);            vh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);        }        private static void vertex(this List<UIVertex> vertices,float x, float y , Color color)        {            UIVertex v = UIVertex.simpleVert;            v.color = color;            v.position = new Vector2(x,y);            v.uv0 = Vector2.zero;        }        //画圆形        public static void circle (this VertexHelper vh, Vector2 pos, float radius,Color color,bool filled = false) {            circle(vh,pos.x, pos.y, radius, Mathf.Max(1, (int)(6 * Mathf.Pow(radius,1/3f))),color,filled);        }        public static void circle (this VertexHelper vh, float x, float y, float radius,Color color,bool filled = false) {            circle(vh,x, y, radius, Mathf.Max(1, (int)(6 * Mathf.Pow(radius,1/3f))),color,filled);        }        public static void circle (this VertexHelper vh, float x, float y, float radius, int segments ,Color color,bool filled = false) {            if (segments > 0){                float angle = 2 * Mathf.PI / segments;                float cos = Mathf.Cos(angle);                float sin = Mathf.Sin(angle);                float cx = radius, cy = 0;                List<UIVertex> vs = new List<UIVertex>();                segments--;                for (int i = 0; i < segments; i++) {                    vs.vertex(x, y, color);                    vs.vertex(x + cx, y + cy, color);                    float temp = cx;                    cx = cos * cx - sin * cy;                    cy = sin * temp + cos * cy;                    vs.vertex(x + cx, y + cy, color);                }                vs.vertex(x, y, color);                vs.vertex(x + cx, y + cy, color);                cx = radius;                cy = 0;                vs.vertex(x + cx, y + cy, color);                vh.AddUIVertexTriangles(vs.ToArray());            }        }        public static void DrawBeziers(this VertexHelper vh,List<Vector2> points,float segment,float width)        {            List<BezierUtils> beziers = CreateBeziers(points);            if (beziers != null) {                 for (int i = 0; i < beziers.Count; i++) {                    BezierUtils bezier = beziers[i];                    DrawBezier(vh ,bezier,segment,width);                }            }        }        public static Vector2 nor (this Vector2 vec) {            float len = vec.magnitude;            if (len != 0) {                vec.x /= len;                vec.y /= len;            }            return vec;        }        public static Vector2 rotate90 (this Vector2 vec, int dir) {            float x = vec.x;            if (dir >= 0) {                vec.x = -vec.y;                vec.y = x;            } else {                vec.x = vec.y;                vec.y = -x;            }            return vec;        }        public static Vector2 cpy (this Vector2 vec) {            return new Vector2(vec.x,vec.y);        }        private static void DrawBezier(VertexHelper vh,BezierUtils bezier,float segment,float width)        {            List<Vector2> lpos = new List<Vector2>();            List<Vector2> rpos = new List<Vector2>();            for (int i = 0; i <= segment; i++)            {                Vector2 bezierPos = new Vector2(bezier.beze_x((float)i/(float)segment),bezier.beze_y((float)i/(float)segment));                Vector2 bezierSpeed = new Vector2(bezier.beze_speed_x((float)i/(float)segment),bezier.beze_speed_y((float)i/(float)segment));                Vector2 offseta = bezierSpeed.normalized.rotate90(1) * (0.5f * width);                Vector2 offsetb = bezierSpeed.normalized.rotate90(-1) * (0.5f * width);                lpos.Add(bezierPos.cpy() + offseta);                 rpos.Add(bezierPos.cpy() + offsetb);             }            for (int j = 0; j < segment; j++)            {                vh.AddUIVertexQuad(GetQuad(lpos[j], lpos[j+1], rpos[j+1], rpos[j]));            }        }        private static UIVertex[] GetQuad (params Vector2[] vertPos) {            UIVertex[] vs = new UIVertex[4];            Vector2[] uv = new Vector2[4];            uv[0] = new Vector2(0, 0);            uv[1] = new Vector2(0, 1);            uv[2] = new Vector2(1, 0);            uv[3] = new Vector2(1, 1);            for (int i = 0; i < 4; i++) {                UIVertex v = UIVertex.simpleVert;                v.color = Color.blue;                v.position = vertPos[i];                v.uv0 = uv[i];                vs[i] = v;            }            return vs;        }        private static List<BezierUtils> CreateBeziers(List<Vector2> points)        {            float scale = 0.6f;            List<BezierUtils> beziers = new List<BezierUtils>();            int originCount = points.Count - 1;            List<Vector2> midpoints = new List<Vector2>();            for (int i = 0; i < originCount; i++) {                midpoints.Add(new Vector2(                    Mathf.Lerp(points[i].x,points[i+1].x,0.5f),                    Mathf.Lerp(points[i].y,points[i+1].y,0.5f))                );            }            List<Vector2> ctrlPoints = new List<Vector2>();            float offsetx;            float offsety;            ctrlPoints.Add(new Vector2(                points[0].x,                points[0].y            ));            for (int i = 0; i < originCount - 1; i++) {                Vector2 orginPoint = points[i + 1];                offsetx = orginPoint.x - Mathf.Lerp(midpoints[i].x, midpoints[i + 1].x, 0.5f);                offsety = orginPoint.y - Mathf.Lerp(midpoints[i].y, midpoints[i + 1].y, 0.5f);                ctrlPoints.Add(new Vector2(                    midpoints[i].x + offsetx,                    midpoints[i].y + offsety                ));                ctrlPoints.Add(new Vector2(                    midpoints[i+1].x + offsetx,                    midpoints[i+1].y + offsety                ));                ctrlPoints[i * 2 + 1] = Vector2.Lerp(orginPoint, ctrlPoints[i * 2 + 1], scale);                ctrlPoints[i * 2 + 2] = Vector2.Lerp(orginPoint, ctrlPoints[i * 2 + 2], scale);              }            ctrlPoints.Add(new Vector2(                points[points.Count - 1].x,                points[points.Count - 1].y            ));            for (int i = 0; i < originCount; i++) {                BezierUtils bezier = getBezier(points[i], ctrlPoints[i * 2], ctrlPoints[i * 2 + 1],points[i + 1]);                beziers.Add(bezier);            }            return beziers;        }        public static BezierUtils getBezier(Vector2 p0,Vector2 p1 ,Vector2 p2,Vector2 p3){            return new BezierUtils( p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);        }    }}
原创粉丝点击