欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-12-13 16:16:58
本文实例为大家分享了ugui绘制平滑曲线的具体代码,供大家参考,具体内容如下 绘制 实现自定义的maskablegraphic挂载在ugui的ui节点上...

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

  }
}

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

上一篇:

下一篇: