UGUI绘制多点连续的平滑曲线
更新时间:2020年6月25日 11:15 点击:1585
本文实例为大家分享了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); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。
上一篇: C#中的协变与逆变深入讲解
下一篇: WPF InkCanvas绘制矩形和椭圆
相关文章
- 这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
- 这篇文章主要为大家详细介绍了Unity3D UGUI实现翻书特效,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
Python编程使用matplotlib绘制动态圆锥曲线示例
这篇文章主要介绍了Python使用matplotlib绘制动态的圆锥曲线示例实现代码,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步...2021-10-19- 这篇文章主要为大家详细介绍了Unity3D使用UGUI开发原生虚拟摇杆,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 这篇文章主要为大家详细介绍了Unity3D UGUI特效之Image高斯模糊效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 中国政府日渐宽松的安全政策,令IBM可以通过将专利授权给中国厂商的方式,间接进入对外资IT企业来说门槛颇高的政府部门和工业核心领域的服务器市场...2016-07-04
- 这篇文章主要为大家详细介绍了UGUI实现4位验证码输入,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 这篇文章主要为大家详细介绍了C语言控制台绘制曲线的实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
- 贝塞尔曲线,又称贝兹曲线或贝济埃曲线,一般的矢量图形软件通过它来精确画出曲线,下面这篇文章主要给大家介绍了关于WPF如何绘制光滑连续贝塞尔曲线的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。...2020-06-25
- 使用UGUI提供的ScrollRect和ScrollBar组件实现基本滑动以及自己控制每次移动一页来达到滑页的效果。具体实现思路请参考下本教程...2020-06-25
- 今天小编就为大家分享一篇tensorboard实现同时显示训练曲线和测试曲线,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-22
- 这篇文章主要介绍了python基于三阶贝塞尔曲线的数据平滑算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-05-09
- 这篇文章主要为大家详细介绍了UGUI轮播图组件的实现方法,支持自动轮播、手势切换等功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 这篇文章主要为大家详细介绍了UGUI实现卡片椭圆方向滚动效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 这篇文章主要为大家详细介绍了UGUI实现随意调整字体间距的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 这篇文章主要为大家详细介绍了Unity3D基于陀螺仪实现VR相机功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
- 在本篇文章里小编给大家整理的是一篇关于python一绘制元二次方程曲线的实例分析内容,有兴趣的朋友们可以跟着学习参考下。...2021-07-04
- 作者: 阮一峰 全球最大的 IT 咨询公司高德纳(Gartner),有一个"技术热门度曲线"模型(Gartner Hype Cycle)。 该模型认为,一门技术的发展要经历五个阶段。...2017-07-06
- 这篇文章主要为大家详细介绍了C语言绘制余弦、正弦曲线的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
- 这篇文章主要为大家详细介绍了Unity UGUI控制text文字间距的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25