当前位置: 移动技术网 > IT编程>开发语言>c# > UGUI绘制多点连续的平滑曲线

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

2019年07月18日  | 移动技术网IT编程  | 我要评论

本文实例为大家分享了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);
    }

  }
}

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网