软件编程
位置:首页>> 软件编程>> C#编程>> UGUI绘制多点连续的平滑曲线

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

作者:叫我上上  发布时间:2022-01-16 06:22:45 

标签:UGUI,曲线

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

}
}

来源:https://blog.csdn.net/vikingsc2007_1/article/details/76572916

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com