呂宗霖 曹銳 馮秀芳
(太原理工大學(xué)軟件學(xué)院 山西省太原市 030024)
本文所研究的碰撞檢測是指在所進(jìn)行的項目中,需要對在三維場景中兩個或多個物體進(jìn)行檢測,判斷他們之間是否有接觸或穿透,在場景中剛體物體(具有物理特性的物體)之間的碰撞檢測主要分為兩個方面即:
(1)物體與場景地面之間;
(2)物體與物體之間。
CryEngine(下文簡稱CE)引擎是一款三維游戲開發(fā)平臺,因其高度的開源性在近年來表現(xiàn)出一定的開發(fā)優(yōu)勢,在分析與實際調(diào)研后,確定它是可以進(jìn)行三維虛擬現(xiàn)實項目開發(fā)的實用開發(fā)工具。通過使用CE 引擎,開發(fā)者可以輕在面對三維動作游戲、立體建筑搭載、實時畫面響應(yīng)三維動畫等三維虛擬環(huán)境的交互內(nèi)容設(shè)計實現(xiàn)[1],利用它完成虛擬流程搭建等各種應(yīng)用需要。
虛擬現(xiàn)實仿真中的運動模擬一般是從三維場景空間出發(fā),對物體(一般指模擬剛體對象)的運動進(jìn)行了模擬,主要是從物體的運動角度出發(fā),對物體前一姿態(tài)的基礎(chǔ)上進(jìn)行了一次平移變換和三次旋轉(zhuǎn)變換得到的當(dāng)前的姿態(tài)[1],如圖1 所示。
在CryEngine 項目的研究中,引擎使用了四元數(shù)來進(jìn)一步處理三維空間中的運動問題。通過對三維空間中運動問題的研究,發(fā)現(xiàn)在處理這些問題方面,四元數(shù)由于其4D 屬性,會比標(biāo)準(zhǔn)角度和旋轉(zhuǎn)矩陣的效果更好(更加準(zhǔn)確,對于后續(xù)處理碰撞檢測來說提升了檢測的準(zhǔn)確性),雖然四元數(shù)處理的速度會比較慢一些,但相對其效果來說是值得使用的,這一點在眾多物理引擎中得到了證明,四元數(shù)在三維空間和虛擬現(xiàn)實等方面得到了廣泛的應(yīng)用。
研究發(fā)現(xiàn)目前大多數(shù)3D 開發(fā)項目一般對具有剛體屬性的物體普遍會采用簡單包圍盒(球)算法進(jìn)行物理碰撞檢測,包圍盒檢測法就是在網(wǎng)格空間中使用一個立方體或者球體包來對運動邏輯上會發(fā)生碰撞的三維物體模型進(jìn)行包裹(如圖 2 所示),類似于在模型周圍設(shè)置的響應(yīng)的線條,然后根據(jù)各個物理上包圍盒的形狀、大小、距離、位置等信息來計算是否發(fā)生碰撞,當(dāng)根據(jù)包圍盒檢測出兩個或多個物體發(fā)生碰撞時,依據(jù)物體本身所固有的幾何特性計算其接下來所發(fā)生的運動(即加載物體的運動效果動畫)。本文在深入研究 CE 引擎搭載的各類碰撞檢測算法的基礎(chǔ)上,結(jié)合所進(jìn)行的實際開發(fā)項目需要,優(yōu)化設(shè)計,以期在碰撞檢測的密性和實時性之間取得均衡,實現(xiàn)開發(fā)項目在運動物體碰撞檢測方面的性能完善。
在主要對CryEngine 引擎中物理模擬模塊中的碰撞檢測內(nèi)容進(jìn)行分析后,進(jìn)行了項目實踐之前的學(xué)習(xí)和準(zhǔn)備工作,總結(jié)出了引擎實現(xiàn)物理效果的具體操作和方法。
圖1:物體的空間旋轉(zhuǎn)變化
圖2:包圍盒三維模型樣例
圖3:LocalGrid 的可視化視圖
在 CE 中,能檢測碰撞的發(fā)生主要依賴于LocalGrids 組件和Mesh 組件,LocalGrid 組件提供了一種在物理世界中創(chuàng)建本地模擬子空間的方法。即使空間連接到全局世界中的移動實體,它也可以像模擬空間一樣模擬該空間內(nèi)的對象。當(dāng)為一個 GameObjecet 物體添加組件以后,LocalGrid 充當(dāng)“主要實體物理”,因此必須作為唯一的物理組件添加(即,它與剛體,布娃娃,粒子,區(qū)域,車輛和衣服是互斥的)。在內(nèi)部,它實現(xiàn)了物理實體接口功能的一小部分。然后,LocalGrid 的實體可以作為子項附加到另一個物理化的“宿主”實體,例如剛體火車車廂。游戲(或AI /物理)開始后,其邊界框位于網(wǎng)格邊界內(nèi)的對象將自動分配給網(wǎng)格。退出模式后,它們將返回到全局空間,漫游角色便不會穿過這個物體,并與物體產(chǎn)生碰撞效果。一個簡單的示例可能是具有靜態(tài)物理特性的剛體部件和盒子對撞機。為了進(jìn)行一致的仿真,網(wǎng)格內(nèi)部幾何結(jié)構(gòu)的所有可能出口都必須由門戶覆蓋[2]。門戶大于實際孔的幾何形狀是可以的–這僅意味著有時實體將執(zhí)行比絕對必要更多的碰撞檢查。通過在幾何圖形的表面類型中使用射線碰撞標(biāo)記,甚至可以使門戶幾何圖形僅用于門戶射線追蹤。每當(dāng)對象觸摸門戶時,它都會通過檢查其中心是否屬于特殊的“內(nèi)部檢查”幾何來決定是在內(nèi)部網(wǎng)格還是在外部網(wǎng)格中注冊自己。如果存在觸發(fā)屬性,此時能夠檢測到漫游角色與物體的接觸,但是不會影響角色的移動。如圖3。
外部灰色–主機實體(例如火車車廂),黃色網(wǎng)格– LocalGrid實體,藍(lán)色墻壁(網(wǎng)格中)–網(wǎng)格內(nèi)的靜態(tài)碰撞實體,半透明的紅色矩形–門戶,虛線輪廓–“內(nèi)部檢查”實體,紅色箭頭– child-> parent 附件,綠色箭頭–實體鏈接。有了LocalGrids 組件再加上Mesh 組件(三維空間中的無線網(wǎng)格網(wǎng)絡(luò)),才能進(jìn)行細(xì)致的碰撞檢測。
在CE 的開發(fā)過程中,我們要用到Sandbox(沙盒)進(jìn)行開發(fā),在創(chuàng)建了Leave(關(guān)卡)后,我們進(jìn)入了網(wǎng)格模擬界面,此時要創(chuàng)建一個物體,首先要新建Objects(對象),然后轉(zhuǎn)到 Legacy Entity -> Physics -> RigidBodyEx,然后將其拖到Leave 中,默認(rèn)情況下,它應(yīng)該是一個球體,使用 Model 屬性,可以將其更改為其他名稱。隨后要對其進(jìn)行物理設(shè)置,圖4 為Objects 設(shè)置圖,其中已經(jīng)搭載了 RigidBody 和Mesh 組件。
圖4:Objects 組件設(shè)置圖
模型參數(shù)設(shè)置如下:
3.2.1 RigidBody 的屬性設(shè)置
我們需要勾選設(shè)置物體的剛體屬性,并對其類型Type 進(jìn)行設(shè)置,此時,物理引擎可以對其進(jìn)行檢測分析,判斷使用哪種算法進(jìn)行碰撞檢測,若物理為規(guī)則的球即可以使用包圍球算法,若物體為規(guī)則立方體則使用AABB 軸對稱包圍盒算法,而普遍使用的是先進(jìn)性AABB 算法后對物體細(xì)節(jié)不斷完善,使用更加貼合的OBB 有向包圍盒算法進(jìn)行,可以在引擎開發(fā)CryEngine_Win64.sln 中尋找CryPhysics 目錄下的各類碰撞算法進(jìn)行審閱。
3.2.2 Mesh 的屬性設(shè)置
首先可以設(shè)置物體Transform 屬性,設(shè)置類型如collider 的可碰撞屬性,F(xiàn)ile 的加載已經(jīng)導(dǎo)入的模型,以及材質(zhì)即模型皮膚。接下來還有Physics 屬性,設(shè)置物體質(zhì)量,還可以設(shè)置對象的密度,密度主要用于應(yīng)該漂浮的物體。但要注意,不能在同一對象上同時使用質(zhì)量和密度,如果同時使用質(zhì)量和密度,則物理引擎會將質(zhì)量優(yōu)先于密度。質(zhì)量和密度只是設(shè)置相同屬性(質(zhì)量)的不同方法。如果僅指定密度,則質(zhì)量將計算為密度乘以物理代理的體積。其中p_draw_helpers = 1 可為您提供有關(guān)物理的重要信息的兩個便捷CVar 可以激活物理代理可視化,設(shè)置 p_debug_joints = 1 可以顯示關(guān)節(jié)的權(quán)重值。
3.2.3 CVars 的屬性設(shè)置
相互碰撞的組(也稱為“島”)中解決了RigidBody,車輛和球碰撞。當(dāng)對象具有相同數(shù)量級的質(zhì)量時,這種方法最有效,但是可以針對不同的場景進(jìn)行一些求解器調(diào)整:
p_max_mc_iters–設(shè)置主求解器的迭代限制(迭代次數(shù)越多=質(zhì)量越好,但速度越慢)。
p_mass_decay–在求解器中啟用動態(tài)質(zhì)量調(diào)整,以提高高堆棧或樁的穩(wěn)定性(有一個功能頁)。
p_max_mc_mass_ratio–如果較輕的物體(至少按此比例)被困在較重的物體之間,則將該島標(biāo)記為需要額外的基于全局矩陣的全局求解器(“ LCPCG”)。
p_max_mc_vel–如果涉及速度高于此速度的對象,則將該島標(biāo)記為需要LCPCG 解算器。p_max_LCPCG_contacts–對于具有更多觸點的孤島禁用LCPCG,即使已將其標(biāo)記為需要LCPCG。
本文在對兩個物體初始加載AABB 和球包圍盒算法進(jìn)行碰撞中,一般會先加載float CAABBTree::Bulid(CGeometry *pMesh)函數(shù)來構(gòu)造簡單的AABB(軸對稱)包圍盒引擎中返回了event 值(代碼層面)反復(fù)迭代(多次的碰撞檢測)后對物體分析,加載了OBB 算法為網(wǎng)格模型構(gòu)建了OBB 樹(簡稱obbs)來適應(yīng)特定的類型,過程大概如圖5。
圖5:obbs 構(gòu)建
在引擎中obbs 的構(gòu)建函數(shù)為:float COBBTree::Bulid(CGeometry *pMesh),這就基于了Mesh 組件,在其基礎(chǔ)上獲取包圍盒(參數(shù)為四元數(shù)形式)得到所有的包圍盒以后,數(shù)據(jù)從面上就可以構(gòu)造一棵節(jié)點樹即obbs,從最大的包圍盒(樹的頂點)開始從上至下地反復(fù)地進(jìn)行分割,獲得更小得包圍盒(樹的子節(jié)點)來進(jìn)行精度的提高,當(dāng)然也可以從小到大得到最大的包圍盒。把大的包圍盒分割成小的包圍盒的過程中,因為使用了Mesh 組件,所以在網(wǎng)格空間中采用一個面(這個面垂直于包圍盒中的一條坐標(biāo)軸)來分割包圍盒上最長的軸(類似于AABB 包圍盒),然后根據(jù)多邊形處在分割軸的哪一邊把多邊形分離開來[3]。如果不能沿著最長的軸進(jìn)行分割,就沿著第二長的邊分割持續(xù)分割到包圍盒不能再被分割為止[2]。此時依據(jù)項目的精度要求(物體模型所以操作部分可以觸發(fā)碰撞檢測),物體模型細(xì)節(jié)的參數(shù)決定了何時停止分割,分割結(jié)束后得到了所有的子節(jié)點構(gòu)建出了物體的obbs[3-6]。對于物體模型創(chuàng)建樹的階段比較復(fù)雜,需要依據(jù)Mesh 組件在空間中對運動物體沿著各個軸進(jìn)行大量的運算會對實時性產(chǎn)生壓力,因該在碰撞檢測之前事先創(chuàng)建樹(一般為在沙盒中對所選Objects 搭載RigidBody 組件開始)這樣可以免去實時改變物體多邊形帶來的計算壓力。對一個復(fù)雜物體構(gòu)建了obbs,然后與一個球(包圍球碰撞演示)來進(jìn)行測試,結(jié)果如圖6 和圖7。
圖6:未加載Mesh 組件的兩物體失敗的碰撞效果
圖7:加載Mesh 組件的兩物體合理的碰撞效果
在obbs 完成后,此時的碰撞檢測會從最大的包圍盒開始檢測,判斷此物體與其他物體的最大最大的包圍盒的軸是否相交,如果相交了,則表明他們發(fā)生了碰撞,接下來需要對發(fā)生碰撞的包圍盒的樹根節(jié)點(最大的包圍盒)開始進(jìn)一步地遞歸處理,對obbs 進(jìn)行自上而下的遍歷子樹,如果沿著下一級檢測結(jié)果后發(fā)現(xiàn),子樹并沒有存在相交的情況,此時,我們停止遍歷OBB,可以得出兩個對象沒有碰撞的結(jié)論[7]。如果檢測后發(fā)現(xiàn)子樹的節(jié)點相交,則需要對子樹進(jìn)行進(jìn)一步的處理,直至遍歷各個子樹到達(dá)葉節(jié)點,最后得出結(jié)論:在檢測相交時,可以將邊界框投影到空間坐標(biāo)軸上(一般是在三維網(wǎng)格空間中),檢查它們是否線性相交。該方法具有潛在的分離坐標(biāo),在這些相應(yīng)的分離坐標(biāo)里,如果它在每個分離坐標(biāo)上重疊,則可以得出邊界框相交的結(jié)論[8]。該方法可以快速判斷兩個邊界盒是否相交,減少了復(fù)雜的建樹過程對碰撞檢測過程造成的時延,彌補了用框代替對象所帶來的計算復(fù)雜度,它提高了大型游戲中復(fù)雜物體間碰撞檢測的速度,有效地保證了游戲的穩(wěn)定性、場景的連續(xù)性和動作響應(yīng)的快速性[6]。
本文針對CryEngine 引擎項目開發(fā)過程中出現(xiàn)的需求和問題,分析了引擎提供的幾種碰撞檢測技術(shù),使用了一種加載Mesh 組件并基于OBB 的快速碰撞檢測方法,將游戲場景中的復(fù)雜的幾何物體進(jìn)行基于形狀的凸分解后進(jìn)行碰撞檢測[9],在實現(xiàn)功能的前提下保證碰撞的實時性和準(zhǔn)確性,通過構(gòu)建obbs 來進(jìn)行OBB 包圍盒的簡化來優(yōu)化項目應(yīng)用,使得場景可以更好的承載物體運動,達(dá)到了項目預(yù)計的效果。
未來可以進(jìn)一步結(jié)合整體場景項目,配和VR 硬件讓訓(xùn)練者可以在搭建的訓(xùn)練項目模擬系統(tǒng)中進(jìn)行仿真操作,進(jìn)一步提升模擬訓(xùn)練的效果。