Unity游戲中使用貝塞爾曲線


孫廣東   2015.8.15

比方在3D rpg游戲中。我們想設置彈道,不同的軌跡類型!


目的:這篇文章的主要目的是要給你關於在游戲怎樣使用貝塞爾曲線的基本想法。

         貝塞爾曲線是最主要的曲線,一般用在計算機 圖形學和 圖像處理。

貝塞爾曲線能夠用來創建平滑的曲線的道路、 彎曲的路徑就像 祖瑪游戲、 彎曲型的河流等。

        一條貝塞爾曲線是由一組定義的控制點 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>();
        }
        lineRenderer.sortingLayerID = layerOrder;
        curveCount = (int)controlPoints.Length / 3;
    }

    void Update()
    {
       
        DrawCurve();

    }
    
    void DrawCurve()
    {
        for (int j = 0; j <curveCount; 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.


     不論什么控制點  可處理其對應的曲線的曲率。你能夠在不論什么時間改變曲線,通過拖動隨意控制點,例如以下所看到的:





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM