【碰撞檢測系統】程序員
一、固體物體本質上是固態的,它一般不會作出不可能的事情,例如穿透對方。程序員需花許多精力,才能確保不會互相穿透。這是任何遊戲引擎的核心元件之一,碰撞檢測系統(collision detection system)。算法
二、碰撞系統一般緊密地和物理引擎(physics engine)整合。遊戲引擎所所指的「物理」更精確地說應該稱爲剛體動力學(rigid body dynamics)模擬。剛體(rigid body)是理想化、無限堅硬、不變形的固體物體。動力學(dynamics)子是一個過程,計算剛體怎樣在力(force)的影響下隨時間移動及做用。緩存
三、動力學模擬需大量使用碰撞檢測系統,以正確地模擬物體的多種物理行爲。布娃娃式死亡就是使用了物理效果。性能優化
四、物理模擬是多變的,難以預測的。物理引擎的引入會對工程產生多方面的影響。用於動力學模擬的碰撞模型,可能須要比非物理驅動的模擬更細緻。數據結構
五、遊戲引擎的碰撞/物理系統可佔一個遊戲引擎源代碼中顯著的百分比。函數
六、遊戲引擎碰撞檢測系統的主要用途在於,判斷遊戲世界中的物體有否接觸(contact)。每一個邏輯對象會以一個或多個幾簡單的何形狀表明。例如球體、長方體、膠囊。也可秀更復雜的形狀。碰撞系統判斷在某指定時刻中,這些圖形是否相交。所以,本質上是幾何相交測試器。性能
七、碰撞系統不只要回答圖形是否相交,也提供接觸的想關信息。剛體動力學模擬是碰撞系統的最苛求的客戶,就算一些遊戲無物理系統,也可能會大量使用碰撞檢測引擎。一個可碰撞體一般拆分爲形狀和變換。多個可碰撞體共享一個形狀描述能節省內存空間。測試
八、碰撞系統一般會經過一個名爲碰撞世界(collision world)的數據結構,管理其全部的可碰撞實體。碰撞世界只須要包含遊戲對象中有可能碰撞的可碰撞體。那麼碰撞系統便不須要遍歷無關的數據結構。優化
九、動力學系統的「世界」數據結構一般會與碰撞系統共享,模擬中每人剛體一般會關聯至碰撞系統裏的一個可碰撞體。碰撞世界有時候稱爲碰撞/物理世界,或直接稱之爲物理世界(physics world)。spa
十、在二維空間中,形狀含其面積,而其邊界則是由1條曲線、或3條以上直線所定義。在三維空間中,形狀含體積,其邊界不是曲面即是由多邊形所組成的。
十一、凸形狀的定義是,由形狀內發射的光線不會穿越形狀表面2次或以上。碰撞原型(collision primitive)可做爲基本組件構成更復雜的形狀。
1)球體(sphere):最高效的碰撞原型
2)膠囊體(capsule)
3)軸對劉包圍盒(axis-aligned bounding box,AABB):一個矩形的體積,6個面都與座標系統的軸平行。AABB能夠方便地由兩個點定義:一個點是盒子在3個主軸上最小的座標,而另外一個則是最大的座標。AABB的主要優勢在於,能夠高速地測試和另外一AABB是否相交。而AABB的最大限制在於,它們必須一直保持與軸對齊,才能維持這個運算上的優點。
4)定向包圍盒(oriented bounding box,OBB):咱們容許對齊的盒子在其座標系中旋轉,便會獲得定向包圍盒。
5)離散定向多胞形(discrete oriented polytyope,DOP):是比AABB,OBB更泛化的形狀。DOP是凸的胞形,用來逼近物體的形狀。AABB是一個6-DOP,其各個平面法矢量與座標軸平等。OBB也是6-DOP。
6)任意凸體積(arbitrary convex volume):凸體積的相交測試比上面幾種原型都更耗時。
7)多邊形湯(polygon soup):有些碰撞系統也會支持徹底任意、非凸的形狀。這些形狀一般是由三角形或其餘簡單多邊形所構成的。多用於地形或建築物。 多邊形湯作碰撞檢測最費時。一般僅把多邊形湯用在不參與動力學模擬的物體。多邊形湯無內我之分。
8)複合形狀(compoun shape):用一組形狀來逼近物體形狀。
十二、碰撞測試
1)點與球體相交。生成一個自球心至該點的分離矢量s,而後量度該矢量的長度。若長度大於球體半徑,則該點位於球體以外,不然就是球體以內。
2)球體與球體相交。求兩球心距離,若大於r1+r2,則不相交,不然相交。
3)分享軸定理(separating axis theorem)。若能找到一個軸,兩個凸形狀於該軸上的投影不重疊,就能肯定兩個形狀不相交。若這樣的軸不存在,而且那些形狀是凸的,則能夠肯定兩個形狀相交。(若形狀爲凹的,就算找不到分離軸,形狀也可能不相交。這就是咱們偏好在碰撞系統中僅使用凸形狀的緣由之一。)其中分離線是把兩個物體分開的直線。它必須垂直由分離軸。在三維空間中,分離線成爲分離平面。計算時,須要找出每個潛在的分離軸,用於計算兩物體是否在些軸上分離。
4)AABB與AABB相交。因爲AABB的面與一組座標軸平行,因此若存在分離軸,它必然是3個座標軸之一。咱們能夠將分離軸定理應用於AABB。
5)檢測凸碰撞,GJK算法。GJK算法能夠高效地檢測任意凸多胞形(polytope)。GJK算法依賴於閔可夫斯基差(Minkowski difference):把A圖形中的全部點,與B圖形中的全部點成對相減,得出的集合即是閔可夫斯基差。用處在於,當兩個形狀相交,閔可夫斯基差會包含原點。
1三、如何實現代碼選擇合適的碰撞測試函數。許多引擎使用雙分派(double dispatch),單分派的也有(虛函數調用)。雙分派能夠實現爲二維查找表,或先調用A的虛函數,再調用B的虛函數。一般引擎中會有一個碰撞代碼,全部的碰撞都由代理來完成。
1四、當場景中包含體積小且速度快的物體時,容易發生子彈穿紙問題(bullet through paper),也叫隧穿(tunneling)。避免此問題的方法之一是掃掠形狀(swept shape)。測試相交時,由測試碰撞世界的靜態快照,改成測試形狀從上一個快照的位置及定向移動至當前快照所造成的掃掠形狀。處理隧穿問題的另外一方法爲連續碰撞檢測(continuous collision detection,CCD)。CCD的目標是對兩上移動何物於某時間區間內,求得最先的衝擊時間(time of impact,TOI)。
1五、性能優化
1)時間一致性(temporal coherency)。也稱爲幀一致性。當碰撞體以正常速率移動,在兩時步中其位置及定向一般會很接近。經過跨越多幀把結果緩存,咱們能夠避免每幀從新計算一些類型的信息。
2)空間劃分(space partitioning)。若是兩個物體分屬不一樣的區域,那麼顯然兩物體不會碰撞。經常使用法有八叉樹。
3)三階段法。粗略階段->中間階段->精確階段
1六、碰撞查詢(collision query)。或稱爲投射(cast),用於判斷若假想的物體或光線沿線段運行是否會碰到世界中的物體。投射的物體並不真正存在於碰撞世界,徹底不影響世界中的其它物體。
1七、最簡單的碰撞投射是光線投射(ray cast)。可用於角色A是否能直接看見角色B。若投射的是球體,則稱爲球體投射(sphere cast),更通常的狀況稱爲形狀投射(shape cast)。不管投射什麼類型的凸形狀,都有可能產生多個接觸點。
1八、phantom是一種虛擬碰撞體。 用於判斷碰撞體是否位於指定體積裏。phantom與正常碰撞體的惟一區別是,phantom對於碰撞世界中其餘碰撞體來講是「透明」的。
19 、碰撞過濾(collision filtering)
1)碰撞掩碼及碰撞層。爲碰撞體分類,指明哪些碰撞體之間能夠發生碰撞。
2)碰撞回調。用於程序動態決定哪些碰撞體間能夠發生碰撞。
3)碰撞材質(collision material)。把每一個碰撞表面關聯至一組屬性。能夠是音效、粒子效果、物理屬性。