題外話:今天在看關於Jobs發現unity2018.2很有意思,對於animation進行了很多的嘗試,相關具體可見,後續看看能不能抄到2017.4上來

Animation C# Jobs – Unity Blog?

blogs.unity3d.com
圖標
Unity-Technologies/animation-jobs-samples?

github.com

下面開始正題:

DynamicBone是一個簡單的基於模擬彈簧振子的演算法實現樹狀柔體的物理模擬插件。雖然基於模擬彈簧振子運動的演算法實現,但是DynamicBone各節點之間的距離實際上不會發生變化。比起彈簧,父子節點之間的相對運動更接近串聯的單擺

整體流程簡圖

DynamicBone模擬出的柔體特性體現在物體運動之後發生的彈性形變上。所以它的模擬自然發生在物體運動之後,再根據物體運動的結果去模擬各個節點彈性運動的過程。

下面得到的DynamicBone的整體流程非常簡單,當物體原本移動完成後,首先根據運動的當前結果模擬彈性運動,再根據模擬結果修正各節點的旋轉並且將模擬結果同步到實際節點上。

這其中,我們稱圖中(2)的物體各節點的原本移動結果為理想位置,因為有彈性的物體雖然會發生形變,但是其最終會嘗試還原到原本的形狀。而模擬運動的結果則稱之為實際位置。因為這是計算得到的結果,並且最終也會同步到附屬的節點上。

整體流程圖

為了便於區分,這裡我們稱DynamicBone的節點為節點,而實際的物體節點為附屬節點

籃框部分考慮了力的影響使用了韋爾萊積分法,紅框部分整體就是彈簧運動的模擬計算部分

預處理:附加全局位移

?在彈簧運動模擬計算開始前,DynamicBone首先會將現在所在的物體的位移乘上慣性(Inert)參數之後附加給所有節點。這段位移是不會參與到後續的運動模擬計算過程的,會直接改變當前幀和前一幀的實際位置,所以這段位移在後續計算中不會被算入速度。即

彈簧運動模擬部分1:慣性運動&受力運動

彈簧運動模擬計算的第一部分是慣性運動模擬,這部分非常好理解,就是讓節點保持速度繼續運動,而速度的值就是一次模擬內節點的實際位置的變化差值減去阻尼(damping)值,即

彈簧運動模擬計算的第二部分是受力運動模擬,DynamicBone中考慮了兩種力對節點運動的印象,分別是重力(Gravity)常駐力(Force),這兩種力對運動過程的影響方式不一樣。這裡常駐力很好理解,是無條件發揮作用的力,會直接附加到計算結果。而重力的機制比較特殊,重力本身不發揮作用,只有運動發生後的重力分量會影響運動過程。即

彈簧運動模擬部分2: 重力計算補充講解

重力計算

在初始狀態下,重力不起任何作用,但是DynamicBone會記錄重力在根節點局部坐標系內的向量。在每次計算時,DynamicBone會計算變化後的局部重力向量在初始重力向量方向的投影,最後為節點附加初始重力向量減去這個投影向量的重力。由於記錄的是根節點局部坐標系內的向量,所以只有根節點發生了旋轉才會導致重力發揮作用,而其他的節點的旋轉不會。還有隻有當局部重力投影與全局重力方向一致時,全局重力才會減去投影。如果方向相反(意味著根節點旋轉了超過180度),全局重力只會全部發揮作用,不會去加上投影長度。

彈簧運動模擬部分3:彈性運動&剛性運動

彈簧運動模擬計算的第三部分是彈性運動模擬,屬於節點自主運動,即不受力和速度的影響,並且運動結果會被視作速度(所以本質上可以視作一種內在力)。彈性運動的過程非常簡單,就是求出節點當前實際位置與理想位置的差值,並且乘上彈性(Elasticity)參數附加到實際位置。即

彈簧運動模擬計算的第四部分是剛性運動模擬,也屬於節點自主運動。要解釋彈性運動首先要引入理想距離,即父子節點理想位置間的距離,也就是父子節點原本距離。剛性模擬會先根據剛性(Stiffness)參數和理想距離求出節點偏離理想位置的最大距離,並且將節點限制在距離內。即

彈簧運動模擬部分3:彈性運動&剛性運動

彈簧運動模擬計算的第三部分是彈性運動模擬,屬於節點自主運動,即不受力和速度的影響,並且運動結果會被視作速度(所以本質上可以視作一種內在力)。彈性運動的過程非常簡單,就是求出節點當前實際位置與理想位置的差值,並且乘上彈性(Elasticity)參數附加到實際位置。即

彈簧運動模擬計算的第四部分是剛性運動模擬,也屬於節點自主運動。要解釋彈性運動首先要引入理想距離,即父子節點理想位置間的距離,也就是父子節點原本距離。剛性模擬會先根據剛性(Stiffness)參數和理想距離求出節點偏離理想位置的最大距離,並且將節點限制在距離內。即

碰撞檢測與恢復4

DynamicBone的碰撞檢測很簡單,就是將每個節點與每個碰撞體逐個進行碰撞檢測並且根據檢測結果進行恢復。DynamicBone提供了兩種形狀的碰撞體,球型和膠囊體型。球型的碰撞檢測非常簡單,首先求出節點與球心的距離,然後求出節點半徑與碰撞體半徑之和。如果距離大於半徑之和(在Inside模式下是小於),就移動節點保證距離等於半徑之和。

膠囊體的碰撞檢測要稍微複雜一點,首先求出膠囊體兩個球心之間的向量A,然後求出節點中心與其中一個球心的向量B,然後求A在B上的投影,根據投影結果在進行下一步判斷,即

碰撞檢測與恢復

然後,當投影方向與向量A相反,則節點相當於進行與以球心A為球心的球體做碰撞檢測與恢復;如果方向投影方向與向量A相同但是比向量A長,則節點相當於進行與以球心B為球心的球體做碰撞檢測與恢復。

如果如果方向投影方向與向量A相同並且比向量A短,則取向量B在與向量A垂直方向上的投影向量長度,如果該長度大於半徑之和,就移動節點保證距離等於半徑之和

後處理階段5:維持節點間距離

在模擬計算最後,DynamicBone有一個簡單的後處理防止父子節點之間發生拉伸或者壓縮,維持節點間理想距離。步驟很簡單,首先求出當前父節點實際距離的差向量,然後將其恢復至理想距離向量。即

後處理階段6:修正節點旋轉並且同步變換

在最後將計算得到的節點變換同步到附屬節點前,DynamicBone還會根據各級節點間的相對變換做一次旋轉修正,每對父子節點只要父節點僅有一個子節點就都會讓父節點旋轉至與子節點的相對旋轉的初始值相同的狀態。

缺陷與優化

缺陷:

DynamicBone的缺陷主要是不允許節點間距離發生變化,這導致DynamicBone不允許實際的拉伸或者壓縮發生,DynamicBone的節點之間實際上缺乏彈簧的性質。因此DynamicBone不能模擬容易發生拉伸形變的物體。

另外一方面DynamicBone所有計算都不考慮時間因素,所以同樣彈簧參數不同更新頻率參數下表現會非常不同,加大了調參難度。

優化:

最常用的LOD降頻方式或者遠處動畫

代碼C++化,測試了下相較未IL2CPP下面能快2倍

考慮同場景多個DynamicBone對象的計算情況,合併計算流程統一管理

對於差不多位置的DynamicBone進行近似計算,計算一跟復用多跟,比如飄帶,裙擺等

進行jobSystem化,放在BatchedIKPass之後

Unity中Transform只存儲了Go的local相關的信息,計算Gloabl的相關數據時候會進行各種轉換,這個也是導致耗時的主要原因


推薦閱讀:
查看原文 >>
相关文章