Unity3d遊戲中自定義貝塞爾曲線編輯器[轉]

星塵發表於2016-03-30

關於貝塞爾曲線曲線我們再前面的文章提到過《Unity 教程之-在Unity3d中使用貝塞爾曲線》,那麼本篇文章我們來深入學習下,並自定義實現貝塞爾曲線編輯器,貝塞爾曲線是最基本的曲線,一般用在計算機 圖形學和 影象處理。貝塞爾曲線可以用來建立平滑的曲線的道路、 彎曲的路徑就像 祖瑪遊戲、 彎曲型的河流等。看下效果圖 !

一條貝塞爾曲線是由一組定義的控制點 P0到 Pn,在 n 呼叫它的順序 (n = 1 為線性,2 為二次,等.)。第一個和最後一個控制點總是具有終結點的曲線;然而,中間兩個控制點 (如果有的話) 一般不會位於曲線上 。

貝塞爾曲線包含兩個控制點即 n = 2 稱為線性的貝塞爾曲線

貝塞爾曲線包含三個控制點即 n = 3 稱為二次貝塞爾曲線

貝塞爾曲線包含四個控制點即 n = 4,所以稱為三次貝塞爾曲線。

貝塞爾曲線返回點的貝塞爾函式,使用線性插值的概念作為基礎。所以,讓我們瞭解什麼首先是線性插值。

兩個點之間的線性插值的點獲取那兩個點之間,0 <= t <= 1,像 Mathf.Lerp 。

插值點,與 P 公式P0和 P1可以寫成,

P = P0+ t (P1 – P0),0 <= t <= 1

在這裡,為得到插值的點我們新增 tth指向 P 的分數與這兩個之間的距離0.所以,

For T = 0,P = P0.

For T = 1,P = P1.

For T = 0.5,P = P0和 P1間的點.

線性的貝塞爾曲線:

線性的貝塞爾曲線有兩個控制點。為給出了兩個點 P0和 P1一個線性的貝塞爾曲線是隻是這兩個點之間的直線。曲線是相當於線性插值給出,

B(t) = P0+ t (P1 – P0) = (1-t) P0 + tP1 ,0 <= t <= 1

線性貝塞爾曲線如何計算出來的是如下所示:

二次貝塞爾曲線:

二次貝塞爾曲線具有三個控制點。二次貝塞爾曲線是點對點的兩個線性貝塞爾曲線的線性插值。為給出了三個點 P0、P1和 P2一條二次貝塞爾曲線,其實是兩條線性的貝塞爾曲線,線性貝塞爾曲線的 P0和 P1和 線性貝塞爾曲線P1和 P2. 所以,給出二次貝塞爾曲線 :

B(t) = (1-t) BP0P1(t) + t BP1P2(t),0 <= t <= 1

B(t) = (1-t) [(1-t) P0 + tP1] + t [(1-t) P1+ tP2],0 <= t <= 1

通過重新排列上述方程,

B(t) = (1-t)2P0+ 2 (1-t) tP1 + t2P2, 0 <= t <= 1

二次貝塞爾曲線動畫計算如下所示:

三次貝塞爾曲線:

三次方貝塞爾曲線具有四個控制點。二次貝塞爾曲線是 點對點的兩條二次貝塞爾曲線的線性插值。對於給出的四個點 P0、P1、P2和 P3三次方貝塞爾曲線,是二次貝塞爾曲線P0、P1和 P2和 二次貝塞爾曲線P1、P2和 P3 得到的 線性插值 .所以,給出三次方貝塞爾曲線

B(t) = (1-t) BP0,P1,P2(t) + t BP1,P2,P3(t),0 <= t <= 1

B(t) = (1-t) [(1-t)2P0+ 2 (1-t) tP1 + t2P2] + t [(1-t)2P1+ 2 (1-t) tP2 + t2P3],0 <= t <= 1

通過重新排列上述方程中,

B(t) = (1-t)3P0 + 3(1-t)2tP1+ 3 (1-t) t2P2 + t3P3 0 <= t <= 1

三次貝塞爾曲線計算如下所示:

所以,一般可以作為點對點的線性插值獲得從兩個相應的貝賽爾曲線的程度 n-1 的兩個點定義程度 n 的貝塞爾曲線(就是高階的是兩個低一級的線性插值)。

在大多數應用程式使用兩種二次或三次方貝塞爾函式。然而,你總可以使用更高程度貝塞爾函式繪製更復雜的曲線,但較高程度貝塞爾函式的計算是比較複雜和增加處理開銷。所以,而不是使用更高的學位貝塞爾函式繪製更復雜的曲線,你可以多次使用兩種二次或三次方貝塞爾函式。在這裡,我建立了一個演示和繪製的∞形曲線,使用三次方貝塞爾函式中迴圈,如下所示。

若要建立一條曲線,如上所示,請建立場景,如下所示:

現在,將Bezier.cs指令碼附加到 Bezier Manager

Bezier.cs:

using UnityEngine;

using System.Collections.Generic;

[RequireComponent(typeof(LineRenderer))]

public class Bezier : MonoBehaviour

{

public Transform[] controlPoints;

public LineRenderer lineRenderer;

private int curveCount = 0;

private int layerOrder = 0;

private int SEGMENT_COUNT = 50;

void Start()

{

if (!lineRenderer)

{

lineRenderer = GetComponent();

}

lineRenderer.sortingLayerID = layerOrder;

curveCount = (int)controlPoints.Length / 3;

}

void Update()

{

DrawCurve();

}

void DrawCurve()

{

for (int j = 0; j

{

for (int i = 1; i <= SEGMENT_COUNT; i++)

{

float t = i / (float)SEGMENT_COUNT;

int nodeIndex = j * 3;

Vector3 pixel = CalculateCubicBezierPoint(t, controlPoints [nodeIndex].position, controlPoints [nodeIndex + 1].position, controlPoints [nodeIndex + 2].position, controlPoints [nodeIndex + 3].position);

lineRenderer.SetVertexCount(((j * SEGMENT_COUNT) + i));

lineRenderer.SetPosition((j * SEGMENT_COUNT) + (i - 1), pixel);

}

}

}

Vector3 CalculateCubicBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)

{

float u = 1 - t;

float tt = t * t;

float uu = u * u;

float uuu = uu * u;

float ttt = tt * t;

Vector3 p = uuu * p0;

p += 3 * uu * t * p1;

p += 3 * u * tt * p2;

p += ttt * p3;

return p;

}

}

在這裡,CalculateCubicBezierPoint 函式是 Cubiz 貝塞爾函式,我已解釋了上面執行。DrawCurve 函式繪製兩條 三次方貝塞爾曲線。

Between P0, P0- control Point1, P1- control Point1 and P1.

Between P1, P1- control Point1, P0- control Point2 and P0.

任何控制點 可處理其相應的曲線的曲率。你可以在任何時間改變曲線,通過拖動任意控制點,如下所示:

0

原文:http://www.xici.net/d224478514.htm

相關文章