AABB包圍盒算法,在2D碰撞檢測中的實現

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)
接下來咱們看下具體原理

三:碰撞體的預處理

爲何預處理?咱們看下面的兩個圖。若是咱們須要對這兩張圖片作碰撞檢測,該如何處理?

object.png圖片描述

咱們能夠基於像素的對比,判斷青蛙的像素座標有沒有出如今鑰匙的像素座標裏,若是有重疊的部分
那說明,兩個物體碰撞裏,可是仔細想一下這並非很好的辦法,假如咱們兩個照片都是600*600像素,那麼
單單這兩個物體的碰撞檢測的時間複雜度就是600^4。

很顯然不能這麼作,我麼接下來對圖片進行"描邊"。咱們就會獲得兩個矩形。那麼接下來就好處理了。

二:ABT樹的構建過程

圖片描述

假設上圖中的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爲碰撞物體的數量)。

相關文章
相關標籤/搜索