1. 程式人生 > >基於SPH的流體模擬實踐和一些技巧總結

基於SPH的流體模擬實踐和一些技巧總結



目前流體模擬中常用的2類方法,分別代表了從2種不同的方面來解釋Navier-Stokes的流體方程:

 1、Eulerian方法從空間固定點觀察該點的值得變化。

 2、Lagrangian方法則將液體看作是跟隨著流動的Particle。



Eulerian方法比較複雜,常用作離線模擬,可以產生非常逼真的流體效果,具體可以參考SIGGRAPH 2007的《FLUID SIMULATION》,作者是Bridson 和 Muller。

現在遊戲中常用的實時流體模擬通常使用Lagrangian的方法來模擬流體,也就是基於粒子的方法,而大多數採用的都是基於SPH(Smooth Particle hydrodynamic)的方法。主要參考文章為Muller的《Particle-Based Fluid Simulation for Interactive Applications》。




SPH方法非常簡單和容易實現,從我自己做過的剛體和柔體模擬的經驗來看,可以說基於SPH的流體比剛體和柔體的模擬簡單和容易實現的多。



SPH方法概括的說:

1:對每個粒子,通過它附近周圍的所有和它的距離半徑小於r的所有粒子來計算出該粒子點的密度r被稱為Smooth Length,通俗的說就是每個粒子的最大影響半徑。

2:對於每一個粒子,通過理想氣體狀態方程根據上一步計算出的密度從而算出它的壓強。

3:對於每一個粒子,根據它附近周圍距離半徑小於r的所有粒子的壓強(上一步已經計算出)來計算出該粒子由於附近壓強差而導致受到的壓力差。

4:對於每一個粒子根據它附近周圍距離半徑小於r的所有粒子的速度差來計算出該粒子由於附近速度差而導致受到的粘滯力。




對於第一步求解密度來說,
其中r代表粒子i和粒子j之間的距離,h代表前面說的Smooth Length

對於第二步來說使用公式 其中 是粒子的密度 是流體的穩定密度比如水的話一般取1000kg/立方米。



第3,4步也可以依次類推。具體請參考Muller的文章《Particle-Based Fluid Simulation for Interactive Applications》。





實現中的常用技巧



下面是一些實現中的常用技巧,希望對你有所幫助。



注意,根據上面一片文章的SPH方法,需要推導Smooth Kernel函式的梯度和拉普拉辛運算元。但Muller在文章中只給出了3個Kernel(一個計算密度,一個計算壓強差力,一個計算粘滯力)函式,並沒 有幫我們推匯出後2個函式的梯度公式和拉普拉辛運算元公式。一開始我還花
時間自己推導了下,還反覆檢查生怕推導錯了(以前大學學數學我的粗心導致1,2個符號錯誤是常有的事情)。後來發現《SPH survival kit》這片小文章裡已經幫你都推導好了。。。汗。所以你只要照抄就可以了。



為了快速定位一個粒子周圍的例子,我使用了空間Grid的資料結構,通常的說就是將空間等分成尺寸為h的立方格,這樣對於一個粒子來說只要查詢周圍3X3X3的立方格中所包含的粒子就可以了。



為了實現無限大範圍的Grid系統,我使用了空間稀疏雜湊的方法來儲存Grid,這是因為空間大部分Grid都是空著的所以使用Hash表儲存和快速定位 那些包含粒子的Grid,具體可以參考《Optimized Spatial Hashing for Collision Detection of Deformable Objects》。



每對粒子之間的力只需要計算一次就可以了(這樣提高2倍的速度),也就是說對於粒子A,B來說。A粒子由於受到B粒子作用的壓強力分量,和B粒子由於受到 A粒子作用的壓強力分量是相同的只差一個正負號而已,為了避免計算A和B所受的作用力時重複計算,我在每一楨開始模擬前,首先構造每個粒子的鄰接粒子列 表:同時要保證A和B的鄰接關係要麼只出現在A的鄰接列表中,要麼只出現在B的鄰接列表中。具體做法很簡單,首先清空Hash Grid中每個Grid中的粒子資訊,然後對於每一個粒子首先查詢周圍27個鄰接Grid中的粒子,將這些粒子中和自己的距離長度小於Kernel Smooth Length的那些例子加入自己的鄰接列表,最後將自己加入到自己所在的Grid中,這樣就能保證A和B的鄰接關係出現並且只出現一次(將會出現在後面的 那個粒子的鄰接列表中,因為對於前一個粒子來說,在統計它的鄰接粒子的時候,後一個粒子還沒有被加入到Hash Grid中~~)。



實際上Muller給出的那些公式中有不少可以提取公因式的部分,你可以仔細去研究下會發現很多可以優化速度的地方。



水面資訊抽取



上面的步驟只是完成了一個粒子系統的模擬,這樣你看到的還只是一堆水分子,在正式渲染的時候需要通過第一步計算出的密度場資訊來構造出水錶面。我這裡也是 採用Muller論文裡的Marching Cube演算法,這個演算法簡單容易實現,但是效率極低,我模擬1500個粒子在一臺Core2 4400的Intel cpu上可以達到150fps,一旦經過Marching Cube演算法後一下子掉到52fps.所以不大推薦這種方法,我個人看到過一片比較好的文章是《Interactive Water Streams with Sphere Scan Conversion》,感覺挺不錯,作者號稱速度比Marching Cube快了很多倍。不過我自己也沒有時間去做。



Marching Cube演算法的論文<<Marching Cubes:A High Resolutin 3D Surface Construction Algorithm>>,注意論文中提到的構造一個頂點資訊構造表,這個表你可以自己寫程式構造。。但是更加方便的技巧是你去下載一個叫做 “PolyVox”的開源體素構造庫,它裡面已經幫你把表格生成好了。



水體渲染

基本上需要模擬的包括水對於背景的折射效果,水面的Specular ,以及菲涅爾效果。其中前2項是最重要的,折射我使用的方法是先渲染水體以外的所以其他場景物體,然後將該Back Buffer拷到一張渲染紋理上,然後在渲染水的時候在PS裡面對這張紋理進行一些扭曲(根據法向量)。最後將畫素點寫回back buffer,同時根據計算出的菲涅爾係數將畫素點的顏色值和反射顏色值進行融合。(這個折射方法是同事教的,正好他在做畫面扭曲效 果。。)Specular的話和一般的Specular計算方法相同。,下面是幾張截圖:

這是模擬將液體注入一個盒子的過程
1.剛開始注入
注入中
注入液體一段時間後
注入完畢
靜止後
總結,SPH流體模擬主要包括3部分,水分子模擬,水面資訊抽取,水體渲染,其中第一部分,第三部分比較簡單,但是好的快速的效果需要有良好,真實地水面 資訊抽取演算法支援。Marching Cube演算法可以通過加大網格精度來不斷提高視覺效果,速度卻得不到保障,所以需要一個更加出色的演算法來解決,因此如何開發一個高效,真實的適用於流體的Surface Extraction演算法會是個很大的挑戰。

相關推薦

基於SPH流體模擬實踐一些技巧總結

目前流體模擬中常用的2類方法,分別代表了從2種不同的方面來解釋Navier-Stokes的流體方程: 1、Eulerian方法從空間固定點觀察該點的值得變化。 2、Lagrangian方法則將液體看作是跟隨著流動的Particle。Eulerian方法比較複雜,常用作離線模擬,可以產生非常逼真的流體效果,具體

特效模擬SPH流體模擬及液面重構問題

爆炸 方程 力學 壓力 大學 png sch 技術 當前 這裏是關於特效模擬算法的一些敘述,主要是流體模擬部分的研究。 目前動畫領域內的流體模擬主要是拉格朗日法無網格法和歐拉網格法,兩種方法更有利弊。 我研究的主要是拉格朗日法中的SPH模型,即光滑粒子流體動力學模型。

angular js一些個人總結技巧

獲取url中的網路字尾元素 function getParam(paramName) { paramValue = ""; isFound = false; if (this.location.search.indexOf("?")

HeapDumpOnOutOfMemoryError堆轉儲實踐一些分析

程式碼1在迴圈中建立long[]例項時,上次迴圈建立的long[]例項沒有被引用,可以被垃圾回收掉,所以在引數Xmx40m下,程式碼1建立佔用32M記憶體的long[]還是可以正常執行的,試圖建立佔用64M記憶體的long[]才丟擲異常;程式碼2在迴圈中建立long[]例項時,上次迴圈建立的long[]例項還

線性迴歸演算法一些技巧

1 基本概念 1.1 工作原理 做線性迴歸時,我們通常會使用“普通最小二乘法”,即將目標函式定為平方誤差 ,對w求導,令其為零得 這是當前可以估計出的w的最優解,即迴歸方程的引數。 2.1 區域性加

第五期 基於模擬器上的實踐學習規劃 《手機就是開發板》

https://blog.csdn.net/aggresss/article/details/53538575         前面三期我們分別動手實踐了AOSP,kernel和APP的編譯環境搭建,這是我們實踐的基

Laravel 5.7 最佳實踐開發技巧分享

Laravel 因可編寫出乾淨,可用可除錯的程式碼而為廣大的 PHP 開發者所熟知。它同樣也支援許許多多的功能,有時卻未能在文件中體現,或者由於某種原因它們出現過又被移除了。 我已經在生產環境中使用 Laravel 2 年了,從中我學到如何把程式碼變得更好,從我首次使用它以來我都充分發掘它

[轉]用python爬蟲抓站的一些技巧總結 zz

內容 req xxxxx pic 個數 相關 choice 都是 observe 來源網站:http://www.pythonclub.org/python-network-application/observer-spider 學用python也有3個多月了,用得最

Reporting Service 2000的一些技巧總結

總結 log blog 科學 存在 format 解決 出錯 處理 在使用Reporting Service 2000過程中,對一些特殊的地方做了一些總結,下子把它貼出來,供大家參考: 1.IIF表達式如何使用? 在很多地方,都可以使用IIF表達式來實現一些特

mxnet深度學習實戰:跑自己的資料實驗一些問題總結

用mxnet跑自己的資料 0 程式碼編譯   git clone https://github.com/dmlc/mxnet.git   git clone https://github.com/dmlc/mshadow.git   git clone https://gi

IOS JavaScriptCore 跳轉失去物件一些BUG總結

引: 以前做專案的時候也做過webview和js互動,以為會手到擒來。結果WTFK、兩天的時間來研究它。主要遇到了一個BUG,下面簡單的說一下。   下面一段程式碼注入時機的選擇,這是一個很重要的問

sklearn的一些技巧總結

1 scikit-learn基礎介紹 1.1 估計器(Estimator) 估計器,很多時候可以直接理解成分類器,主要包含兩個函式: fit():訓練演算法,設定內部引數。接收訓練集和類別兩個引數。predict():預測測試集類別,引數為測試集。 大多數scikit

Android記憶體洩漏監控優化技巧總結

前言對於Android平臺的應用程式來說,記憶體優化一直是個熱門話題,與傳統PC應

培訓講師PPT技巧總結

1    成為好的講師 好的講師需要有好的心法、技法以及呈現。 成為好講師的三個關鍵:豐富知識、正確心態和足夠技能。 完美課堂的三個座標:深入學員思考和參與,優質使用課程內容,精到動人的講授。 2    講師心法 2.1    課程目標確認 首先要確定課程名稱:符合SMAR

資料庫效能一些總結

關於資料庫效率 資料庫索引: 只有當資料查詢的結果集比較小(3%),null比較多,資料波動範圍不是很大的時候,索引的效果才明顯。 如果要解決效率低的情況,從根本上來說還是需要 分表: 例如, 江蘇  南京 江蘇  蘇州 江蘇  鹽城 不如分成兩個表: A表就一條資料: 江

用python爬蟲抓站的一些技巧總結 (轉)

用python爬蟲抓站的一些技巧總結 zz Python俱樂部 您的足跡: » 用python爬蟲抓站的一些技巧總結 zz 顯示原始檔修訂記錄最近更改索引登入Python俱樂部PythonPythonClub 首頁Python 基礎Python 常見檔案操作Python 網路

Android學習筆記:練習中用到的一些技巧總結

1,登入的時候,如果輸入有誤,則輸入框左右震動,表示輸入有誤         在res下準備一個anim資料夾,裡面包含兩個檔案,main_login_shake.xml 和 main_login_cycle_7.xml,         其中,main_login_sh

基於SPH流體模擬過程

轉載自:https://blog.csdn.net/changbaolong/article/details/13172079 http://blog.sina.com.cn/s/blog_6f638fb60100shw0.html         S

一些常用JS函數技巧總結

常用 ces 函數 ont 布爾 gin 技巧 int() js函數 1.JS原生函數parseInt(),返回字符串的第一個數字,默認是十進制。 2.!!data.success //強制轉換成布爾類型 p.p1 { margin: 0.0px 0.0px 0.0px

kvm的Pool創建基於physical disk 一些問題

CentOS-7.2 最近幾天遇到physical disk創建pool的問題,主要集中在centos7.2 1.一個是基於mbr的分區,因為小於2GB,然後磁盤上的標識是dos。在virt-manager裏,首先是創建pool,遇到問題,具體的忘記了。然後用cli創建,成功後不穩定,然後在創建