UGUI繪制多點(diǎn)連續(xù)的平滑曲線
本文實(shí)例為大家分享了UGUI繪制平滑曲線的具體代碼,供大家參考,具體內(nèi)容如下
繪制
實(shí)現(xiàn)自定義的MaskableGraphic掛載在UGUI的UI節(jié)點(diǎn)上
public class UGUIObjectRender : MaskableGraphic
{
/**
* points 為需要穿過(guò)的點(diǎn)
* segments 為曲線細(xì)分度
* linewidth 為曲線粗細(xì)
*/
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.DrawBeziers(points,segments,linewidth);
}
}
需要時(shí)用的工具類在后面
二次貝塞爾工具類
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);
}
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:圖文介紹c#封裝方法
欄 目:C#教程
下一篇:利用C#編寫掃雷游戲(附源碼)
本文標(biāo)題:UGUI繪制多點(diǎn)連續(xù)的平滑曲線
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/4975.html
您可能感興趣的文章
- 01-10WinForm繪制圓角的方法
- 01-10C#繪制曲線圖的方法
- 01-10C#利用GDI繪制常見圖形和文字
- 01-10Unity UGUI教程之實(shí)現(xiàn)滑頁(yè)效果
- 01-10C#繪制飛行棋地圖小程序
- 01-10C# 繪制統(tǒng)計(jì)圖大全(柱狀圖, 折線圖, 扇形圖)
- 01-10WPF如何繪制光滑連續(xù)貝塞爾曲線示例代碼
- 01-10C#在PDF中繪制不同風(fēng)格類型的文本方法實(shí)例
- 01-10C#正方形圖片的繪制方法
- 01-10WPF InkCanvas繪制矩形和橢圓


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實(shí)例總結(jié)
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子


