Scene Management --- Collision Detection
僅供個人學習使用,請勿轉載,勿用於任何商業用途。
沒有碰撞檢測的引擎是不完整的。碰撞檢測是引擎的基礎服務之一,需要為渲染,物理模擬,AI和遊戲邏輯都等眾多子系統提供服務。由於碰撞檢測本身設計到大量數學運算,以及各個子系統對碰撞檢測需求的不同,使得它成了最難實現的部分。
碰撞檢測需要解決的問題是物體之間是否發生了碰撞,在什麼時刻發生了碰撞,碰撞位置在什麼地方以及碰撞點法線的方向,得到的碰撞資料越多,計算量也越大。考慮兩個物體碰撞檢測的問題,假設每一幀都通過遍曆2個物體中的所有三角形來判斷是否發生碰撞,那代價一定是相當大的。於是人們用一些簡單的,便於處理的幾何體近似實際模型,以減少計算量,這就是常說的包圍體BV(bounding volume)。常見的包圍體有AABB,球體,OBB,Hull等等。包圍體減少了碰撞檢測的計算量,特別是對於沒有相交的物體來說,讓他們很快就排除在後續計算之外,也就是常說的early rejection。前面所說的幾種包圍體,精度逐漸增高,所需計算量也隨之增加。可以先計算兩個物體初級包圍體(比如包圍球)是否相交,如果相交,再進一步計算精度高一級的包圍體(AABB或者OBB)是否相交,以次類推,直到滿意的精度(比如三角形層級)為止,我把這個方法稱為BV LOD。對於實際相交的物體來說,雖然這些額外的包圍盒測試會帶來負載,但考慮到情境中有大量物體且彼此之間沒有碰撞時,包圍盒可以大大減少總體計算時間。
除了上面說所的BV LOD,層次包圍盒(Bounding volume hierachies)也是常用的加速方法。BVH與quadtree局部細分的思想很類似,用多個BV來近似實際模型。以人物模型為例,第一級BV空間範圍包含了整個模型,第二級BV由多個小BV組成,每一個對應著模型的一個子部分,比如頭,手,軀幹。每個子部分又可以劃分為更多子BV,直到你滿意的細分粒度為止。對BVH來說,每級的BV類型可以不一樣也可以相同,比如第一,二級都用AABB,而第三級改用球體等等,最終的資料將是一種樹形結構。當對兩個物體進行檢測時,先從跟節點開始,然後逐步細分,檢測子BV是否相交。至於是否同時對2個物體進行細分測試,還是先對其中一個進行細分,則要根據實際情況來定。當然,BVH也可以和BV LOD結合起來一起使用。
上面介紹了基本的碰撞檢測演算法,但當物體很多時,單靠上面兩種方法還是無法滿足需要。因此,與裁剪系統一樣,需要在更高的層次對情境進行空間劃分,這也是我為什麼把碰撞檢測也歸為scene management的原因。上次說過quadtree幾乎是最適合戶外情境裁剪的結構,那麼是否對碰撞檢測也一樣呢?我相信你可能已經見過很多引擎就是把兩者合二為一的,可實際上,對裁剪有效資料結構卻並不是碰撞檢測的最優結構。對裁剪來說,如果某個網格在視錐之內,那麼這個網格內的所有物體就是可見的;而對碰撞檢測來說,需要做的是依次檢查每個網格內的所有物體之間是否有碰撞。換句話說,對於裁剪系統,網格內物體的多少基本不會影響裁剪效率,而對碰撞檢測,效能就與物體多少緊密相關。所以我們需要的是一種空間上不均勻,但能最大程度保證空間內物體均勻的資料結構,比如BSP或者K-d tree。此外,碰撞檢測還有一個非常非常重要,也是非常顯而易見的特性:永遠不需要計算靜態物體之間是否發生了碰撞!假設情境中有n個靜態物體和一個動態物體,排除靜態物體間相互碰撞可能性讓計算量從O((n+1)!)降低到了O(n)。再假設我們以K-d tree劃分情境,每個分葉節點只有n個物體,那麼每次計算這個動態物體是否發生了碰撞的時間代價幾乎就是一個可預知的常量!Wow就是這個方法的最好例子,在wow裡,動態物體(人物)之間是不會發生碰撞的,所以不管情境中有多少玩家,都不對碰撞檢測造成影響。但是如果你希望動態物體之間也能碰撞怎麼辦?大量的動態物體很有可能會破壞k-d tree的平衡性。最好的方法就是把靜態物體(情境)和動態物體(玩家)分開,放到不同的資料結構中。仍然用k-d tree來組織靜態情境,但用一些更動態結構來組織動態物體,比如動態k-d tree,ABT等等。這樣,就能仍然保證每個物體碰撞檢測的代價是一個可預測的常量。
小結:Scene management的三篇文章在很高的層次上介紹了關於遊戲引擎的一些核心技術,我的目的不是講解實現細節,而是讓對於scene management不太瞭解的人知道scene management是什麼以及如何來做。感性的說,如果你讀完之後,知道scene management = scene tree + culling tree + static object tree + danamic object tree,那麼我的目的就達到了。至於用什麼資料結構來實現這些“tree“,是否可以把其中的某些tree合并,則是你在實現scene management時應該考慮的:)
我不是Scene management方面的專家,因此如果有任何錯誤,不清楚的地方,不同觀點或者更好的想法,歡迎留言討論。