好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

dy("nrwz");

查看更多关于UGUI绘制多点连续的平滑曲线的详细内容...

  阅读:37次