標籤:href ber alt 協助 ret https 向量 b2c 直接
原文:【Unity】貝茲路徑關於點、長度、切線計算在 Unity中的C#實現
寫在前面
最近給項目做了個路徑編輯,基本思路是滿足幾個基本需求:
【額外說明】其實本篇和這個沒關係,可以跳過“寫在前面”這部分,跨到本文部分
編輯時:
① 隨意增減、插入、刪除路點,只要路點數量大於1,繪製曲線,曲線必定經過路點。
② 調整路點的Forward方向,控制曲線的入線切線方向、出線切線方向。這樣可以通過旋轉直接調整曲線形狀。
③ 控制Forward方向的基礎上,增添描述切線“強度”的變數,來進一步控制曲線的形狀。
④ 可以指定每段曲線的邏輯長度,程式提供一個曲線近似長度協助確定邏輯長度。
⑤ 匯出曲線的資料。
運行時,可以根絕資料:
⑥ 對路點進行從0開始的編號,使用0.01~0.99來描述在某段曲線上的位置(邏輯上的),然後轉化成為實際的座標。
⑦ 可以獲得在曲線上任意一點的切線方向。
本文
從路點、路點forward到三階貝茲路徑的四個點
關於貝茲路徑,可見下文
貝茲路徑
貝茲路徑線上示範
每兩個路點作為三階貝茲路徑的起點(第0個點P0)和終點(第3個點P3)。
起點路點的Forward方向乘以“強度”的變數,再加上起點座標,作為第1個點P1。
起點路點的Forward反方向乘以“強度”的變數,再加上起點座標,作為第2個點P2。
得到 p0~p4這四個點之後,即可使用三階貝茲路徑的相關公式了
繪製貝茲路徑,圖中紅色線條部分
三階貝茲路徑線上某點座標(Unity & C#)
三階貝茲路徑公式(來自百度百科)
形參中的 t, p0, p1, p2, p3 分別對應公式中的 t 以及 p0~p3
public Vector3 BezierPoint(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; }
三階貝茲路徑的近似長度(Unity & C#)
計算長度的思路:
在貝茲路徑上取n個點,計算點之間的直線長度,進行加和,從而取得一個曲線的近似長度。取點越多這個長度越趨向於精確。
形參中的p0, p1, p2, p3 分別對應公式中的 p0~p3。pointCount代表取點個數,預設30。
public float BezierLength(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, int pointCount = 30) { if (pointCount < 2) { return 0; } //取點 預設 30個 float length = 0.0f; Vector3 lastPoint = BezierPoint(0.0f / (float)pointCount, p0, p1, p2, p3); for (int i = 1; i <= pointCount; i++) { Vector3 point = BezierPoint((float)i/(float)pointCount, p0, p1, p2, p3); length += Vector3.Distance(point, lastPoint); lastPoint = point; } return length; }
三階貝茲路徑線上某點的切線(Unity & C#)
在已知貝茲路徑運算式的情況下,想要知道某點的切線,對曲線求導。
可得:
整理後可得
整體公式構成只有p0~p3 以及 t 和 (1-t),為了運算式更直接,不進行進一步的整理。
所以得到下面的代碼
形參中的 t, p0, p1, p2, p3 分別對應公式中的 t 以及 p0~p3
public Vector3 BezierTangent(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3) { float u = 1 - t; float uu = u * u; float tu = t * u; float tt = t * t; Vector3 P = p0 * 3 * uu * (-1.0f); P += p1 * 3 * (uu - 2 * tu); P += p2 * 3 * (2 * tu - tt); P += p3 * 3 * tt; //返回單位向量 return P.normalized; }
寫在後面
主要參照:
Unity遊戲中使用貝茲路徑
求二次、三次貝茲路徑的某個時間的位置及切線方向
轉載請註明,出自喵喵丸的部落格 (http://blog.csdn.net/u011643833/article/details/78540554)
【Unity】貝茲路徑關於點、長度、切線計算在 Unity中的C#實現