呂宗霖 曹銳 馮秀芳
(太原理工大學軟件學院 山西省太原市 030024)
本文所研究的碰撞檢測是指在所進行的項目中,需要對在三維場景中兩個或多個物體進行檢測,判斷他們之間是否有接觸或穿透,在場景中剛體物體(具有物理特性的物體)之間的碰撞檢測主要分為兩個方面即:
(1)物體與場景地面之間;
(2)物體與物體之間。
CryEngine(下文簡稱CE)引擎是一款三維游戲開發平臺,因其高度的開源性在近年來表現出一定的開發優勢,在分析與實際調研后,確定它是可以進行三維虛擬現實項目開發的實用開發工具。通過使用CE 引擎,開發者可以輕在面對三維動作游戲、立體建筑搭載、實時畫面響應三維動畫等三維虛擬環境的交互內容設計實現[1],利用它完成虛擬流程搭建等各種應用需要。
虛擬現實仿真中的運動模擬一般是從三維場景空間出發,對物體(一般指模擬剛體對象)的運動進行了模擬,主要是從物體的運動角度出發,對物體前一姿態的基礎上進行了一次平移變換和三次旋轉變換得到的當前的姿態[1],如圖1 所示。
在CryEngine 項目的研究中,引擎使用了四元數來進一步處理三維空間中的運動問題。通過對三維空間中運動問題的研究,發現在處理這些問題方面,四元數由于其4D 屬性,會比標準角度和旋轉矩陣的效果更好(更加準確,對于后續處理碰撞檢測來說提升了檢測的準確性),雖然四元數處理的速度會比較慢一些,但相對其效果來說是值得使用的,這一點在眾多物理引擎中得到了證明,四元數在三維空間和虛擬現實等方面得到了廣泛的應用。
研究發現目前大多數3D 開發項目一般對具有剛體屬性的物體普遍會采用簡單包圍盒(球)算法進行物理碰撞檢測,包圍盒檢測法就是在網格空間中使用一個立方體或者球體包來對運動邏輯上會發生碰撞的三維物體模型進行包裹(如圖 2 所示),類似于在模型周圍設置的響應的線條,然后根據各個物理上包圍盒的形狀、大小、距離、位置等信息來計算是否發生碰撞,當根據包圍盒檢測出兩個或多個物體發生碰撞時,依據物體本身所固有的幾何特性計算其接下來所發生的運動(即加載物體的運動效果動畫)。本文在深入研究 CE 引擎搭載的各類碰撞檢測算法的基礎上,結合所進行的實際開發項目需要,優化設計,以期在碰撞檢測的密性和實時性之間取得均衡,實現開發項目在運動物體碰撞檢測方面的性能完善。
在主要對CryEngine 引擎中物理模擬模塊中的碰撞檢測內容進行分析后,進行了項目實踐之前的學習和準備工作,總結出了引擎實現物理效果的具體操作和方法。

圖1:物體的空間旋轉變化

圖2:包圍盒三維模型樣例

圖3:LocalGrid 的可視化視圖
在 CE 中,能檢測碰撞的發生主要依賴于LocalGrids 組件和Mesh 組件,LocalGrid 組件提供了一種在物理世界中創建本地模擬子空間的方法。即使空間連接到全局世界中的移動實體,它也可以像模擬空間一樣模擬該空間內的對象。當為一個 GameObjecet 物體添加組件以后,LocalGrid 充當“主要實體物理”,因此必須作為唯一的物理組件添加(即,它與剛體,布娃娃,粒子,區域,車輛和衣服是互斥的)。在內部,它實現了物理實體接口功能的一小部分。然后,LocalGrid 的實體可以作為子項附加到另一個物理化的“宿主”實體,例如剛體火車車廂。游戲(或AI /物理)開始后,其邊界框位于網格邊界內的對象將自動分配給網格。退出模式后,它們將返回到全局空間,漫游角色便不會穿過這個物體,并與物體產生碰撞效果。一個簡單的示例可能是具有靜態物理特性的剛體部件和盒子對撞機。為了進行一致的仿真,網格內部幾何結構的所有可能出口都必須由門戶覆蓋[2]。門戶大于實際孔的幾何形狀是可以的–這僅意味著有時實體將執行比絕對必要更多的碰撞檢查。通過在幾何圖形的表面類型中使用射線碰撞標記,甚至可以使門戶幾何圖形僅用于門戶射線追蹤。每當對象觸摸門戶時,它都會通過檢查其中心是否屬于特殊的“內部檢查”幾何來決定是在內部網格還是在外部網格中注冊自己。如果存在觸發屬性,此時能夠檢測到漫游角色與物體的接觸,但是不會影響角色的移動。如圖3。
外部灰色–主機實體(例如火車車廂),黃色網格– LocalGrid實體,藍色墻壁(網格中)–網格內的靜態碰撞實體,半透明的紅色矩形–門戶,虛線輪廓–“內部檢查”實體,紅色箭頭– child-> parent 附件,綠色箭頭–實體鏈接。有了LocalGrids 組件再加上Mesh 組件(三維空間中的無線網格網絡),才能進行細致的碰撞檢測。
在CE 的開發過程中,我們要用到Sandbox(沙盒)進行開發,在創建了Leave(關卡)后,我們進入了網格模擬界面,此時要創建一個物體,首先要新建Objects(對象),然后轉到 Legacy Entity -> Physics -> RigidBodyEx,然后將其拖到Leave 中,默認情況下,它應該是一個球體,使用 Model 屬性,可以將其更改為其他名稱。隨后要對其進行物理設置,圖4 為Objects 設置圖,其中已經搭載了 RigidBody 和Mesh 組件。

圖4:Objects 組件設置圖
模型參數設置如下:
3.2.1 RigidBody 的屬性設置
我們需要勾選設置物體的剛體屬性,并對其類型Type 進行設置,此時,物理引擎可以對其進行檢測分析,判斷使用哪種算法進行碰撞檢測,若物理為規則的球即可以使用包圍球算法,若物體為規則立方體則使用AABB 軸對稱包圍盒算法,而普遍使用的是先進性AABB 算法后對物體細節不斷完善,使用更加貼合的OBB 有向包圍盒算法進行,可以在引擎開發CryEngine_Win64.sln 中尋找CryPhysics 目錄下的各類碰撞算法進行審閱。
3.2.2 Mesh 的屬性設置
首先可以設置物體Transform 屬性,設置類型如collider 的可碰撞屬性,File 的加載已經導入的模型,以及材質即模型皮膚。接下來還有Physics 屬性,設置物體質量,還可以設置對象的密度,密度主要用于應該漂浮的物體。但要注意,不能在同一對象上同時使用質量和密度,如果同時使用質量和密度,則物理引擎會將質量優先于密度。質量和密度只是設置相同屬性(質量)的不同方法。如果僅指定密度,則質量將計算為密度乘以物理代理的體積。其中p_draw_helpers = 1 可為您提供有關物理的重要信息的兩個便捷CVar 可以激活物理代理可視化,設置 p_debug_joints = 1 可以顯示關節的權重值。
3.2.3 CVars 的屬性設置
相互碰撞的組(也稱為“島”)中解決了RigidBody,車輛和球碰撞。當對象具有相同數量級的質量時,這種方法最有效,但是可以針對不同的場景進行一些求解器調整:
p_max_mc_iters–設置主求解器的迭代限制(迭代次數越多=質量越好,但速度越慢)。
p_mass_decay–在求解器中啟用動態質量調整,以提高高堆棧或樁的穩定性(有一個功能頁)。
p_max_mc_mass_ratio–如果較輕的物體(至少按此比例)被困在較重的物體之間,則將該島標記為需要額外的基于全局矩陣的全局求解器(“ LCPCG”)。
p_max_mc_vel–如果涉及速度高于此速度的對象,則將該島標記為需要LCPCG 解算器。p_max_LCPCG_contacts–對于具有更多觸點的孤島禁用LCPCG,即使已將其標記為需要LCPCG。
本文在對兩個物體初始加載AABB 和球包圍盒算法進行碰撞中,一般會先加載float CAABBTree::Bulid(CGeometry *pMesh)函數來構造簡單的AABB(軸對稱)包圍盒引擎中返回了event 值(代碼層面)反復迭代(多次的碰撞檢測)后對物體分析,加載了OBB 算法為網格模型構建了OBB 樹(簡稱obbs)來適應特定的類型,過程大概如圖5。

圖5:obbs 構建
在引擎中obbs 的構建函數為:float COBBTree::Bulid(CGeometry *pMesh),這就基于了Mesh 組件,在其基礎上獲取包圍盒(參數為四元數形式)得到所有的包圍盒以后,數據從面上就可以構造一棵節點樹即obbs,從最大的包圍盒(樹的頂點)開始從上至下地反復地進行分割,獲得更小得包圍盒(樹的子節點)來進行精度的提高,當然也可以從小到大得到最大的包圍盒。把大的包圍盒分割成小的包圍盒的過程中,因為使用了Mesh 組件,所以在網格空間中采用一個面(這個面垂直于包圍盒中的一條坐標軸)來分割包圍盒上最長的軸(類似于AABB 包圍盒),然后根據多邊形處在分割軸的哪一邊把多邊形分離開來[3]。如果不能沿著最長的軸進行分割,就沿著第二長的邊分割持續分割到包圍盒不能再被分割為止[2]。此時依據項目的精度要求(物體模型所以操作部分可以觸發碰撞檢測),物體模型細節的參數決定了何時停止分割,分割結束后得到了所有的子節點構建出了物體的obbs[3-6]。對于物體模型創建樹的階段比較復雜,需要依據Mesh 組件在空間中對運動物體沿著各個軸進行大量的運算會對實時性產生壓力,因該在碰撞檢測之前事先創建樹(一般為在沙盒中對所選Objects 搭載RigidBody 組件開始)這樣可以免去實時改變物體多邊形帶來的計算壓力。對一個復雜物體構建了obbs,然后與一個球(包圍球碰撞演示)來進行測試,結果如圖6 和圖7。

圖6:未加載Mesh 組件的兩物體失敗的碰撞效果

圖7:加載Mesh 組件的兩物體合理的碰撞效果
在obbs 完成后,此時的碰撞檢測會從最大的包圍盒開始檢測,判斷此物體與其他物體的最大最大的包圍盒的軸是否相交,如果相交了,則表明他們發生了碰撞,接下來需要對發生碰撞的包圍盒的樹根節點(最大的包圍盒)開始進一步地遞歸處理,對obbs 進行自上而下的遍歷子樹,如果沿著下一級檢測結果后發現,子樹并沒有存在相交的情況,此時,我們停止遍歷OBB,可以得出兩個對象沒有碰撞的結論[7]。如果檢測后發現子樹的節點相交,則需要對子樹進行進一步的處理,直至遍歷各個子樹到達葉節點,最后得出結論:在檢測相交時,可以將邊界框投影到空間坐標軸上(一般是在三維網格空間中),檢查它們是否線性相交。該方法具有潛在的分離坐標,在這些相應的分離坐標里,如果它在每個分離坐標上重疊,則可以得出邊界框相交的結論[8]。該方法可以快速判斷兩個邊界盒是否相交,減少了復雜的建樹過程對碰撞檢測過程造成的時延,彌補了用框代替對象所帶來的計算復雜度,它提高了大型游戲中復雜物體間碰撞檢測的速度,有效地保證了游戲的穩定性、場景的連續性和動作響應的快速性[6]。
本文針對CryEngine 引擎項目開發過程中出現的需求和問題,分析了引擎提供的幾種碰撞檢測技術,使用了一種加載Mesh 組件并基于OBB 的快速碰撞檢測方法,將游戲場景中的復雜的幾何物體進行基于形狀的凸分解后進行碰撞檢測[9],在實現功能的前提下保證碰撞的實時性和準確性,通過構建obbs 來進行OBB 包圍盒的簡化來優化項目應用,使得場景可以更好的承載物體運動,達到了項目預計的效果。
未來可以進一步結合整體場景項目,配和VR 硬件讓訓練者可以在搭建的訓練項目模擬系統中進行仿真操作,進一步提升模擬訓練的效果。