Unity Mesh基礎系列(四)mesh變形(製做一個彈力球)

目錄微信

1 場景搭建函數

2 Mesh調節器性能

2.1 準備測試

2.2 頂點速度flex

3 Mesh 調節器的輸入url

3.1 輸入檢測spa

3.2 施加力.net

3.3 力偏移翻譯

4 最基礎的變形3d

4.1 將力轉換爲速度

4.2 移動頂點

5 保持形狀

5.1 彈簧

5.2 阻尼

6 處理變換

6.1 調整縮放

本章內容重點

向對象投射射線並繪製調試線。

將力轉換爲頂點速度。

用彈簧和阻尼保持形狀。

補償對象轉換。


這篇教程的主要內容是介紹一下網格變形。把網格變成一個彈力球,而後戳它。


本教程是CatLikeCoding系列的一部分,原文地址見文章底部。「原創」標識意爲原創翻譯而非原創教程。

這篇教程是基於上一篇 立方體球 的。它複用了同一個網格,並在此基礎上作增長更多的測試模型。本示例適用於Unity5.0.1及以上版本。


(施加了一些按壓操做)


1 場景搭建


咱們會從一個以單個立方體球體爲中心的場景開始。你既能夠從頭開始,也能夠複用上一章 立方體球 的場景,而後刪除全部多餘的東西。


爲了得到平滑的變形效果,球體應該包含至關數量的頂點。我把球體的網格大小設爲20,半徑設爲1。

(從一個規則的立方體球開始)


2 Mesh調節器


建立一個新的MeshDeformer腳原本處理變形。就像立方體球面組件同樣,它須要一個mesh filter組件來處理。

(添加完組件以後的展現)


這裏須要注意,和前面的章節不一樣,這裏咱們只須要mesh filter。這裏咱們不在意它是如何獲得網格數據的。而如今正在使用咱們的程序生成的 立方體球,但其實它能夠是任何網格。


2.1 準備


要進行任何的變形,咱們都須要訪問Mesh。一旦咱們有了Mesh,就能夠提取到原始的頂點位置。除此以外,還必須跟蹤變形過程當中的位移點。

在Start方法中對網格及其頂點進行賦值,並將原始頂點複製到移位點。

之因此要使用Start,是由於咱們須要在Awake時生成過程網格,由於Awake老是在Start前被調用。這種方法依賴於其餘組件在Awake時處理好他們自身的東西,Awake自己的前後順序並不能保證,因此你其實能夠在Unity的設置裏本身調節腳本執行順序,以強制執行第一和最後的腳本。


2.2 頂點速度


當網格變形是由頂點移動形成的。因此咱們還必須存儲每一個頂點的速度。

這樣咱們就有了支持網格變形的基本成分了。


3 Mesh 調節器的輸入


咱們須要一些手段來控制mesh如何變形,這裏就要用到用戶輸入,也就是交互。無論何時用戶觸碰了物體,都會給這個點施加一個力。


MeshDeformer 類會處理實際的變形邏輯,可是它並不關心輸入。咱們須要建立另一個單獨的類來處理用戶輸入。給這個組件配置一個能夠自定義輸入的力變量。

把這個組件附加到相機上,由於它表明了用戶的視角關注點。綁在其餘物體上也行,但不該該綁定到須要變形的網格對象上,由於場景中可能有不少網格對象。

(把 mesh deformer input組件綁定在攝像機上)


3.1 輸入檢測


當按住鼠標按鈕時,咱們就須要處理用戶的輸入。並根據後續的操做,能夠獲得點擊或拖動操做。

拿到鼠標事件以後,還須要找出用戶的指向位置。能夠經過把鏡頭中的光線投射到場景中來實現這一點。經過抓取場景的主攝像機,並使用它將光標位置轉換爲光線。

使用物理引擎來投射射線並存儲關於它碰撞信息。若是光線與某物發生接觸,就能夠從被擊中的對象中檢索 MeshDeformer 組件。


Physics.Raycast 是如何工做的?

這是一個靜態的方法,用來把射線投影到3D的場景裏。它有不少個變體方法,最簡單的一個就是傳遞一個ray參數,而後返回是否擊中了對象。


咱們使用的版本有一個附加參數。它是RaycastHit類型的輸出參數。裏面包含被擊中的信息和接觸點的結構。


3.2 施加力

若是咱們擊中了一個物體,而且該某物有一個 MeshDeformer 組件的話,就可使它變形了!所以,如今須要在接觸點增長變形的力。

固然,這段代碼調用了 MeshDeformer 組件有AddDeformingForce方法。因此須要在相應的組件裏添加這個方法。

不過,咱們暫時不作任何變形。而是畫一條調試線從主攝像機到點,以便以可視化的力的狀況。

3.3 力偏移


咱們想要實現的效果是網格被用戶按壓和凹陷。

這就須要將接觸點附近的全部頂點推動表面裏。然而,變形的力並無指定內在的方向。它會平等地應用於各個方向。這將會致使平面上的頂點被向周圍推開,而不是向內推。


經過將力點從表面拉出,咱們能夠增長一個方向。一個輕微的偏移就能夠保證頂點老是被推入表面。而接觸點處的法線正好能夠做爲偏移方向。

(不一樣力的方向產生的偏移效果)


4 最基礎的變形


如今能夠開始作一些變形效果了。MeshDeformer .AddDeformingForce 必需要循環遍歷全部當前移位的頂點,並將變形力分別應用到每一個頂點才能夠。


4.1 將力轉換爲速度


一個力被施加到網格的每一個頂點以後,網格就會變形。當頂點被推入的時候,它們須要得到一個速度。隨着時間的推移,頂點就會改變它們的位置。若是全部頂點都經歷徹底相同的力的話,整個物體就會移動而不改變其形狀了。


想象一個爆炸。若是你在邊上,就必死無疑。但若是你離的遠些,可能會被氣浪撞倒。而當你在很遠的地方的時候就幾乎受到影響。


也就是說,力是會隨着距離的推移而減弱的。結合方位的差別,就會產生方向上的衰減,這也是形成物體變形的原理。


因此咱們須要知道每一個頂點變形力的方向和距離,而二者均可以從力點指向頂點位置的矢量導出。

能夠用逆平方定律找到衰減力,只需將力除以距離平方便可。

地址:https://en.wikipedia.org/wiki/Inverse-square_law

而實際上,我除以1加上距離平方。

這能夠確保當距離爲零的時候,力處於全力狀態。不然,力就會在距離1的地方達到最大的強度,而且越靠近點,它就會朝無窮遠的方向飛去。

(紅色是改良後的力衰減)

如今咱們有了力,而後能夠把它轉換成速度。實際上,力首先轉化爲加速度。

而後加速度會改變速度。

爲了計算簡單,咱們將忽略質量,就好像它是均勻分佈的,每一個頂點的都同樣。因此最後的速度變化是:

在該點上,咱們已經有了一個速度了,但尚未方向。這能夠經過規範最開始使用的法線向量來獲得。而後咱們能夠把結果加到頂點速度上。


4.2 移動頂點


頂點有速度以後,咱們就能夠移動它們了。添加一個更新方法來處理每一個頂點的位置。而後,將位移頂點分配給網格,使其實際發生變化。由於網格的形狀再也不是恆定的,咱們也必須從新計算它的法線。

更新頂點是調整其位置能夠經過:


這些頂點會一直更新下去嗎?

是的,每一個update 全部的頂點都被移位,而後分配給網格,而後法線被從新計算。即便沒有施加力,由於這個函數就是每幀執行的。可是若是用戶沒有讓網格變形,這個方法能夠被認爲是浪費性能。所以,只有當網格處於不斷變形的時候,再使用這個方法。

(累計的速度)


5 保持形狀


一旦咱們對頂點施加了一些力,他們就會開始移動,但他們並不會停下來。若是它們不停地移動的話,物體的原始形狀就會消失。如今咱們來讓物體進行回彈以恢復到原來的形狀。


真實的固態物體,在變形的過程當中會被壓縮和拉伸,可是它們自身能抵抗這種變形。一旦不受干擾,就能夠恢復到原來的形狀。


而咱們並無真正的體積,只是一個描述表面的頂點集合而已。因此咱們不能用它來進行真實的物理模擬。但這並非問題,咱們真正須要的是看上去像就能夠了。


5.1 彈簧


在前面,咱們已經能跟蹤到每一個頂點的原始和變形位置。假設咱們在每一個頂點的兩個版本之間附加一個彈簧。每當變形的頂點被移離原始頂點時,彈簧就會把它拉回來。變形頂點越遠,彈簧的拉力就越大。

(偏移的頂點被拉回)


咱們能夠直接利用位移矢量做爲速度調整,乘以一個可配置的彈簧力。簡單,而且聽上去也不錯。

(變形後反彈)


5.2 阻尼


頂點如今抵抗變形,跳回原來的位置了。可是他們跳得太快了,並且不停地彈。這是由於彈簧力一直在拉它,而頂點卻在自我校訂,從而提升了它的速度。並且它只有在向後移動很遠後纔會減速。


這裏能夠經過不斷地減緩頂點的速度來防止這種永恆的振盪。這種阻尼效應能夠替代電阻、阻力、慣性等。是一個簡單的因素,它會隨着時間的推移而下降速度。

阻尼越高,物體的彈性就越小,表現的速度也就越慢。

(恢復到它先前的形狀)


6 處理變換


網格變形的功能如今是完整的了。可是若是咱們要對物體的transform進行變換的話,還須要一些些處理。如今全部的計算都是在局部空間進行的。移動或旋轉咱們的球體。你會發現變形力會被不正確地施加。


咱們必須補償物體的transformation。經過將變形力的位置從世界空間轉換到局部空間來實現這一點。

(正確的位置,可是不一樣的縮放)


6.1 調整縮放


力如今被施加在正確的位置,可是其餘的地方仍然是錯誤的。向上或向下均勻地縮放球體。你會注意到變形鱗片的數量是同樣的。但這是不對的。小的和大的物體應該受到一樣的物理的影響纔對。


因此過程當中就必須補償對象的縮放。首先,咱們須要知道它的統一縮放值。這能夠經過檢查一個transform的local scale軸來找到。並且每次更新都要這麼作,這樣咱們就能夠在某種程度上處理那些動態改變其規模的對象了。


若是不統一的縮放該怎麼辦?

你能夠用一個3D向量代替一個單一的值。而後分別調整每一個維度的補償。但實際上,你不會想處理不均勻的尺度。


如今修正 AddForceToVertex ,方法是經過統一標度縮放點 pointToVertex 。這確保了咱們使用正確的距離。

對Update頂點中的位移也作一樣的操做。如今咱們的速度是正確的。

對於一個沒有縮放的物體,咱們的速度如今是正確的。但因爲咱們的對象其實是縮放的,咱們也必須調整頂點的運動。這一次咱們須要除以它,而不是乘。

(不一樣的縮放值,相同的物理表現)


如今全部工做都完成了。在任意位置、旋轉和均勻比例上都能正常展現的變形網格。請記住,這是一個簡單和相對廉價的視覺效果。這並非一個軟體物理模擬。物體的碰撞也不會改變,因此物理引擎仍是不知道物體的形狀的。


歡迎掃描二維碼,查看更多精彩內容。點擊 閱讀原文 能夠跳轉原教程。










本文翻譯自 Jasper Flick的系列教程

原文地址:

https://catlikecoding.com/unity/tutorials








本文分享自微信公衆號 - 壹種念頭(OneDay1Idea)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索