在Unity中使用貝塞爾曲線_02

前言

上一篇貝塞爾曲線的研究只能滿足一段曲線的生成瞄桨,今天將實(shí)現(xiàn)任意曲線生成(多節(jié)點(diǎn)連續(xù)曲線)。

設(shè)計(jì)原理

指定一段曲線的兩個(gè)端點(diǎn)(p0,p3)以及兩個(gè)控制點(diǎn)(p1坷牛,p2)然后使用三階貝塞爾公式即可生成一段連續(xù)的曲線,將這一段曲線理解成第
n個(gè)節(jié)點(diǎn)到n+1個(gè)節(jié)點(diǎn)之間的三階貝塞爾很澄。
接下來(lái)就是創(chuàng)建N個(gè)節(jié)點(diǎn)了京闰,每一個(gè)節(jié)點(diǎn)和其對(duì)應(yīng)的下一個(gè)節(jié)點(diǎn)為一組曲線颜及,最后一個(gè)節(jié)點(diǎn)不計(jì)算。

如何處理多節(jié)點(diǎn)之間的平滑過渡

每一個(gè)節(jié)點(diǎn)都有且僅有一個(gè)控制點(diǎn)蹂楣,控制點(diǎn)左邊的曲線相當(dāng)于三階貝塞爾中的p2點(diǎn)俏站,而右側(cè)則先計(jì)算其鏡像的坐標(biāo)作為公式中的p1,這樣便可以做到一個(gè)控制點(diǎn)同時(shí)調(diào)節(jié)左右曲線的曲率痊土,效果如下肄扎。

兩條曲線中間節(jié)點(diǎn)的控制點(diǎn)

設(shè)計(jì)原理

BezierNodeObject :節(jié)點(diǎn)對(duì)象,包含一個(gè)控制點(diǎn)屬性

public class BezierNodeObject : MonoBehaviour
{
    public Transform BezierOffset;

    private BezierNode bezierNode;

    public BezierNode GetBezierNode()
    {
        bezierNode.nodeOffset = BezierOffset.position;
        bezierNode.nodePos = transform.position;
        return bezierNode;
    }

    private void Update()
    {
        Debug.DrawLine(BezierOffset.position, transform.position - (BezierOffset.position - transform.position), Color.yellow);
    }
}

BezierData : 將所有節(jié)點(diǎn)和控制點(diǎn)數(shù)據(jù)保存赁酝,并提供三階貝塞爾函數(shù)接口

[CreateAssetMenu(fileName = "BezierData", menuName = "Config/BezierData")]
public class BezierData : ScriptableObject
{
    [Header("數(shù)據(jù)集名稱")]
    public string DataName;
    [Header("數(shù)據(jù)節(jié)點(diǎn)集")]
    public List<BezierNode> bezierNodes;
    [Header("精度系數(shù)犯祠,越大越平滑,性能消耗越高"), Range(10, 100)]
    public int accuracy = 10;

    /// <summary>
    /// 計(jì)算并返回指定一段曲線的坐標(biāo)位置數(shù)組
    /// </summary>
    /// <param name="region">區(qū)間下標(biāo)數(shù)值</param>
    /// <returns></returns>
    public Vector3[] GetBezierDatas(int region) {
        if (region < bezierNodes.Count) {
            Vector3[] datas = new Vector3[accuracy];
            for (int i = 0; i < accuracy; i++)
            {
                BezierMath.Bezier_3ref(
                    ref datas[i],
                    bezierNodes[region].nodePos,
                    bezierNodes[region].getReverseNodeOffset(),
                    bezierNodes[region + 1].nodeOffset,
                    bezierNodes[region + 1].nodePos,
                    i/(accuracy-1.0f)
                );
            }
            return datas;
        }
        return null;
    }
    public void SetBezierNode(List<BezierNodeObject> bezierNodeObjects) {
        if (bezierNodes == null) bezierNodes = new List<BezierNode>();
        bezierNodes.Clear();

        foreach (var item in bezierNodeObjects)
        {
            bezierNodes.Add(item.GetBezierNode());
        }
    }
}

BezierLine : 按照一定的精度從BezierData中獲取每一段曲線上的坐標(biāo)酌呆,將坐標(biāo)信息傳遞給Unity的LineRenderer并繪制出line

public class BezierDrawLine : MonoBehaviour
{
    private List<BezierNodeObject> bezierNodeObjects;
    private BezierData bezierData;
    private List<Vector3> vector3s;

    public Transform NodesRoot;

    [Header("精度系數(shù),表示每一段有多少個(gè)節(jié)點(diǎn)"),Range(10 , 100)]
    public int accuracy;

    private void Start()
    {
        bezierNodeObjects = new List<BezierNodeObject>();
        bezierData = new BezierData();
        vector3s = new List<Vector3>();
    }

    private void Update()
    {
        if (!NodesRoot) return;
        bezierNodeObjects.Clear();
        bezierNodeObjects.AddRange(NodesRoot.GetComponentsInChildren<BezierNodeObject>());
        bezierData.SetBezierNode(bezierNodeObjects);
        bezierData.accuracy = accuracy;
        drawline();
    }

    void drawline() {
        for (int i = 0; i < bezierNodeObjects.Count - 1; i++)
        {
            var lineRenderer = bezierNodeObjects[i].GetComponent<LineRenderer>();
            if (lineRenderer == null) lineRenderer = bezierNodeObjects[i].gameObject.AddComponent<LineRenderer>();
            lineRenderer.positionCount = accuracy;
            lineRenderer.SetPositions(bezierData.GetBezierDatas(i));
        }
    }
}

以上代碼僅供參考衡载,如果需要,下方將提供git項(xiàng)目地址隙袁。

實(shí)際效果展示

多節(jié)點(diǎn)貝塞爾曲線
可調(diào)細(xì)分程度

[項(xiàng)目地址:BezierTool]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痰娱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子菩收,更是在濱河造成了極大的恐慌梨睁,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坛梁,死亡現(xiàn)場(chǎng)離奇詭異而姐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)划咐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門拴念,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人褐缠,你說我怎么就攤上這事政鼠。” “怎么了队魏?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵公般,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我胡桨,道長(zhǎng)官帘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任昧谊,我火速辦了婚禮刽虹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呢诬。我一直安慰自己涌哲,他們只是感情好胖缤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著阀圾,像睡著了一般哪廓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上初烘,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天涡真,我揣著相機(jī)與錄音,去河邊找鬼账月。 笑死综膀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的局齿。 我是一名探鬼主播剧劝,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼抓歼!你這毒婦竟也來(lái)了讥此?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤谣妻,失蹤者是張志新(化名)和其女友劉穎萄喳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蹋半,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡他巨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了减江。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片染突。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖辈灼,靈堂內(nèi)的尸體忽然破棺而出份企,到底是詐尸還是另有隱情,我是刑警寧澤巡莹,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布司志,位于F島的核電站,受9級(jí)特大地震影響降宅,放射性物質(zhì)發(fā)生泄漏骂远。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一腰根、第九天 我趴在偏房一處隱蔽的房頂上張望激才。 院中可真熱鬧,春花似錦、人聲如沸贸营。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钞脂。三九已至,卻和暖如春捕儒,著一層夾襖步出監(jiān)牢的瞬間冰啃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工刘莹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阎毅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓点弯,卻偏偏與公主長(zhǎng)得像扇调,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抢肛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容