Unity球形插值Slerp解析


Unity球形插值,官方有個太陽升降的例子:

http://docs.unity3d.com/ScriptReference/Vector3.Slerp.html

一開始主觀認為這個球形插值Slerp應該本來就是兩點之間畫弧線,貌似很簡單,但該官方例子實現太陽升降卻寫得很復雜,雖沒幾行代碼卻不明白做了些什么事- -

向量即既有長度同時有方向,看介紹可以知道,相比線性插值Lerp將Vector3當作空間的點,球形插值Slerp則是將Vector3當作方向,返回的Vector3的長度是兩點之前的距離插值,方向是兩個向量之間的夾角度數的插值。

注意這里的“夾角度數”,我覺得理解這個夾角度數比較重要,不然僅僅靠Slerp是在兩向量之間做距離插值的同時也對方向做插值還是不太好理解Slerp的最終效果會是個什么樣的弧線。

為了能形象的理解Slerp是怎樣在做“插值”,我將每一幀的狀態都以圖形的方式畫在了場景中,代碼如下,僅僅在官方代碼基礎上增加了畫圖功能:

 1 void Start ()
 2 {
 3     startTime = Time.time;
 4     DrawLine (sunrise.position, Color.red);
 5     DrawLine (sunset.position, Color.cyan);
 6     StartCoroutine (UpdateLine ());
 7 }
 8 
 9 IEnumerator ShowSlerp ()
10 {
11     while (Vector3.Distance (transform.position, sunset.position) > 0.05f)
12     {
13         Vector3 center = (sunrise.position + sunset.position) * 0.5F;
14         DrawLine (center, Color.yellow);
15         yield return null;
16         center -= new Vector3 (0, 1, 0);
17         DrawLine (center, Color.gray);
18         yield return null;
19 
20         Vector3 riseRelCenter = sunrise.position - center;
21         DrawLine (riseRelCenter, Color.green);
22         yield return null;
23         Vector3 setRelCenter = sunset.position - center;
24         DrawLine (setRelCenter, Color.blue);
25         yield return null;
26 
27         float fracComplete = (Time.time - startTime) / journeyTime;
28         transform.position = Vector3.Slerp (riseRelCenter, setRelCenter, fracComplete);
29         DrawLine (transform.position, Color.magenta);
30         yield return null;
31         transform.position += center;
32         DrawLine (transform.position, Color.white);
33         yield return null;
34     }
35 }

暫停然后一幀一幀運行即可看到效果,如下圖,請將線條顏色對應代碼行查看(其中曲線運動軌跡不是官方代碼,未帖進上面代碼中):

這樣代碼邏輯就顯而意見了:原本是在紅向量與淺藍(藍綠)向量間做Slerp,轉變為綠向量與藍向量間做Slerp,從而產生紫(品紅)向量尾部相連的運動軌跡,最終再形成類似太陽升降的白向量尾部相連的曲線運動軌跡。

至此基本明白Slerp代碼之外的其他代碼的作用了:sunrise與sunset兩向量如果共線則直接做Slerp運動是水平方向的曲線!由於這兩個點並未指定初始值而是用戶可以任調整的值,所以說做這些多就只是為了將任意值的起點與終點作偏移使得運動軌跡初終能更符合太陽升降的曲線。

當看到綠藍向量間做Slerp運動可以形成紫向量那樣的運動軌跡時,可能有的童鞋也可以猜到了,只要兩條向量間的夾角不是180度,Slerp的結果就不會是水平方向的弧線。看下圖:

上面那條曲線即是將起點和終點向量稍微上移之后直接進行Slerp運動時的軌跡。可見相比直接Slerp,轉換過后的曲線彎曲程度也得到了調節更符合太陽升起降落的軌跡。

由此知道兩向量直接進行Slerp球形插值時是能直接產生一個曲線弧形的軌跡,不同位置的向量可以產生不同面上的弧形,在兩向量位置固定不可變時可以像官方例子這樣調整兩向量獲得中間向量再Slerp。

官方代碼說明到此結束,至此Slerp為什么被稱作球形插值也就明白了,看下圖:

當兩向量長度相同時,Slerp的結果即是兩向量所在球形表面兩點之間的弧線!

如此,當兩向量為180度水平共線時為什么會形成水平方向的弧形了也就很顯然了,因為兩點所在球面上的弧線本來就是這樣一條弧線。


免責聲明!

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



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