Author:
bugall
Wechat:bugallF
Email:769088641@qq.com
Github: https://github.com/bugallgit
碰撞檢測是遊戲開發中經常使用到的基礎功能,一般的物理引擎中都會包含碰撞引擎.咱們今天主要介紹
的就是Dynamic AABB Tree的實現原理,AABB Tree是個二叉樹,從名字上看,像是個動態平衡樹的變種。
確實在構造AABB樹的時候是須要balance邏輯的。可是AABB的平衡不是基於數的深度的而是"面積",後面
會詳細介紹。github
爲了方便介紹,後文裏的將用ABT來表明AABB Tree算法
這個遊戲想必你們都玩過,這裏面就牽扯到一個碰撞檢測的問題,須要實時檢測用戶控制的小車是否spa
碰到了障礙物,最簡單的方法就是枚舉每個障礙物,判斷障礙物是否跟用戶控制的小車有交集。code
當障礙物少的時候,好比障礙物有100~10000個的時候枚舉是能夠解決的,可是在一些加有物理引對象
擎的場景裏,枚舉就顯然行不通了,由於須要判斷每個物體是否被其它n-1個物體碰撞。若是咱們仍是用排序
枚舉的形式來作碰撞檢測那麼時間複雜度就是n!,若是有100個物體,那麼作一次檢測的時間複雜度就已經遞歸
難以接受。遊戲
在枚舉算法作碰撞檢測的時候有存在一個很大的問題,那就是若是兩個物體距離很遠,遠到它們不可能
接觸,可是檢測中仍是會枚舉這對組合。圖片
ABT是基於二叉樹實現的,這時候咱們能大概感受到,它的時間複雜度將會從枚舉的n*n變成nlog(n)
接下來咱們看下具體原理
爲何預處理?咱們看下面的兩個圖。若是咱們須要對這兩張圖片作碰撞檢測,該如何處理?
咱們能夠基於像素的對比,判斷青蛙的像素座標有沒有出如今鑰匙的像素座標裏,若是有重疊的部分
那說明,兩個物體碰撞裏,可是仔細想一下這並非很好的辦法,假如咱們兩個照片都是600*600像素,那麼
單單這兩個物體的碰撞檢測的時間複雜度就是600^4。
很顯然不能這麼作,我麼接下來對圖片進行"描邊"。咱們就會獲得兩個矩形。那麼接下來就好處理了。
假設上圖中的A,B,C是咱們要作碰撞檢測的物體,外面的藍色框體就是咱們對物體描邊之後得到的矩形
接下來就是構建樹的過程,上面說過ABT樹中的每個節點是AABB Tree結構。咱們從左至右建樹,就像構建
二叉排序樹同樣。
step-1: 把A加入到樹結構中,做爲根節點 step-2: 把B加入到數結構中,這時須要和根節點作比較,判斷根節點的區域是否跟B有交集,若是有的話 就判斷子節點是否跟B有交集,若是都沒有就判斷B分別加入子節點區域後的面積,找到面節差最 小的,組合。若是B與根節點沒有交集,就把A和B看成一個總體從新構建輪廓(橘黃色的矩形),並 生成A,B的父節點(上圖中橘黃色的圓圈), step-3: 把C加入到樹中,判斷是否有交集,方法與step-2中同樣,最終獲得上圖中的樹 最終全部的物體將會在樹的葉節點上。 樹中除葉節點外,全部的節點存的都是本身的面積,或是說是本身的輪廓矩形的四個點的座標。這樣的話,一旦
判斷一個對象是否與樹中物體碰撞,咱們只需判斷是否與物體所在區域有交集,若是有就說明"有可能"會碰撞,而後
接着遞歸向下,直到找到與目標物體碰撞的葉節點。
整個過程當中,很想是一個二叉排序樹,給一個數字,判斷這個數字在不在二叉排序樹中。
不管是二叉排序樹也好仍是ABT算法也好,最重要的仍是它們都巧妙的使用裏二分法,不要ABT算法的二分法是將
面積進行二分,儘量的避免搜索錯誤區域。
因此ABT算法在檢測一個物體是否與其它物體碰撞的時候時間負責度是log(n)的(n爲碰撞物體的數量)。