UGUI绘制多点连续的平滑曲线
程序员文章站
2023-12-01 14:21:34
本文实例为大家分享了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); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: C#做线形图的方法
推荐阅读