基於平均法線實現頂點網格變形控制的總結

基於平均法線實現頂點網格變形控制的總結


            頂點網格的變形功能,這在Unity官方商店的技術展示Demo中有一個案例。自己就是在這個案例的基礎上進行的學習。案例中的功能全部都是用JS實現的,自己依樣畫葫蘆,改成了C#,並對其中一些核心代碼的工作原理進行了分析與學習,最終形成了這篇總結。其中的不正之處歡迎大家批評指出。

       看到文章的標題,我們可能會想,要完成網格模型的變形,需要哪幾個要素? 簡單來說,就是兩個:頂點與法線。其中,頂點指的是網格模型的每一個頂點的座標位置(模型的自身座標系);法線指的是每一個頂點的法線(表示頂點方向的單位向量)。它們都屬於網格模型頂點屬性的範疇。有了這兩個變形的基本要素,我們便可以開始着手實現模型的變形了。在開始實現以前,先讓我們對模型變形的基本套路有個大體瞭解,這好讓我們按圖索驥,有的放矢。

        當我們在進行網格模型的變形時,通常會按照下面的幾步去做:


        1、選擇觸發條件。所謂觸發條件,是指觸發網格模型變形的前提條件,常用的有物體間的碰撞、鼠標的點擊等。


        2、進行頂點篩選。在觸發條件觸發變形後,我們需要進行頂點的篩選。所謂頂點篩選,是指通過設定某些條件,對網格模型的全部頂點進行篩選,從而獲取到所有我們需要修改的頂點。這是很重要的一步,這一步的核心是頂點的篩選算法,這個算法要根據不同的篩選條件來確定。


        3、計算變化因子。經過頂點的篩選,我們已經知道哪些頂點是需要修改的了。而所謂的變化因子,就是告訴我們,這些頂點要發生怎樣的位置變化,要怎樣修改。針對需要修改的頂點,選取合適的算法,計算它們各自的變化因子。這同樣也是一步核心操作。


        4、完成頂點變形,使修改生效。在這一步,我們需要把計算得來的變化因子應用到經過篩選的頂點上,並使這些修改最終生效,從而實現頂點網格的變形效果。

 

        接下來,讓我們根據以上總結的4個步驟,結合代碼,來具體實現頂點網格的變形功能。

        在本例中,我們使用通過鼠標點擊,實現模型變形(凹陷或凸起)的方式。因此,第一條中的觸發條件,就是鼠標的點擊。

        首先,在Update函數中檢測鼠標的左鍵是否按下,如果沒有按下,則直接返回跳出,不進行後續的處理,否則,繼續向後執行。




         通過從鼠標所在的位置發射射線,來進行碰撞檢測。如果有碰撞發生,就記錄下相關的碰撞信息(填充RaycastHit結構),並獲取碰到的網格模型的網格過濾器。然後計算碰撞點在模型自身座標空間中的位置。到這裏,我們的觸發條件部分就可以算完成了。在進入頂點篩選之前,還有一個至關重要的概念沒有介紹——什麼是平均法線法。這一部分的代碼如圖所示:


 


        那麼什麼是平均法線?頂點的法線,描述了每一個頂點的方向。我們進行頂點網格的變形,實質上就是改變了頂點的位置。那麼頂點的位置要如何變化,這需要一個方向,來描述位置的改變。我們要求取的這個平均法線,就表示了所有要改變位置的頂點的一個公共變化方向。有了這個平均法線,我們就知道頂點該向哪個方向去移動,而置於移動多少,這將在稍後說明。

        自己在初次閱讀這段求取平均法線的代碼時,心裏一直有個疑惑,就是爲何用平均法線就能近似代表頂點的變化方向呢?答案是,這是對現實的模擬。在網上看到過一篇論文《基於平均法線法自動生成汽車覆蓋件衝壓方向研究》的摘要,裏面就描述了在物體表面受力時,基於平均法線來自動獲得衝壓方向(受力方向,也就是模型的變形方向)的方法。正是看到了這裏,才讓我對平均法線的意義茅塞頓開,原來這完全是對現實情況的模擬。那麼我們該如何來求這個平均法線,這就讓我們進入第二部分,頂點篩選,來分析代碼中的DeformMesh函數。


 


        頂點的篩選,我們採用了計算每一個頂點到碰撞點距離的方式。事先設定一個變形半徑,在這個半徑內的頂點就是我們要修改的點,反之不予處理。這裏的距離比較我們採用了平方的方式,目的是爲了減少開銷。當我們已經獲取到所有需要修改的頂點,接下來就是計算它們的平均法線,也就是確定變形的方向。平均法線的計算,採用了每一個頂點的法線求取矢量和的方式,並且用了加權平均,這裏的權重因素考慮的是頂點到碰撞點的距離,因爲離碰撞點越近,受到的影響也就越大,那麼對最後得到的平均法線的影響就大。在根據距離求取權重因子的過程中,使用了線性的計算方式,公式如代碼中的LinearFallOff函數所示。好了,最後將計算得出的平均法線進行標準化,因爲我們只需要它的方向,而標準化將有助於我們的計算。代碼如圖所示:





         接下來,有了每一個頂點的位置變化方向,我們還要求出上面所說的變化距離,即在平均法線所表示的方向上移動多少,也就是求第三步中的變化因子。每一個頂點的變化因子,實質上也是一個權重,因爲頂點距離碰撞點越近,變形距離肯定越大,也就是權重越大。這裏的權重計算,我們採用了高斯模糊的方式,通過高斯分佈的二維密度函數,來計算每一個頂點的概率大小,並將此概率作爲權重來使用。不過,自己在這裏也有個問題尚未解決,那就是代碼中的高斯計算公式,是怎樣通過高斯分佈的密度函數換算過來的,因爲它並非是該密度函數的標準書寫方式。另外,對於高斯模糊的算法,自己也準備整理一篇總結,它的用處實在是太大了。代碼如圖所示:






         最後,我們只要把修改的頂點賦給mesh的頂點數組,然後執行第四步的使用修改生效,完成變形效果就可以了。

         總結寫的有些倉促,不對的地方十分歡迎大家的批評,對於自己還沒弄明白的問題,還要繼續探究。看看窗外,還是霧霾,這個大清早,又是新的一天了: )



   本文出自杜曉萌的博客,未經特殊表明皆爲本人原創,請勿用於任何商業用途,轉載請保持完整性並標明出處:http://blog.csdn.net/haohan_meng


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章