首页 > 编程 > C# > 正文

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

2019-10-29 19:41:04
字体:
来源:转载
供稿:网友

本文实例为大家分享了UGUI绘制平滑曲线的具体代码,供大家参考,具体内容如下

绘制

实现自定义的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);    }  }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到c#教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表