java计算一个多边形的重心_2D凸多边形碰撞检测算法(二) - GJK(上)
2D凸多邊形碰撞檢測算法(二) - GJK(上)
原理
在 Narrow Phase 精細碰撞檢測中,除了 SAT ,另外一個就是 GJK(Gilbert–Johnson–Keerthi)算法。它足夠高效,且很容易了解它是如何進行碰撞檢測的。同樣的,它也只適用于 凸多邊形 間的碰撞檢測。
首先,重新回顧一下:當兩個物體碰撞,發生部分重疊的時候,我們是怎樣讓計算機知道他們發生了碰撞呢?在上一篇中,SAT 告訴我們:
如果存在一條直線,能夠將兩個物體分隔開,則兩個物體沒有發生碰撞。反之,如果兩個物體發生碰撞,則找不到這一條直線,將兩個物體分隔開。
SAT 讓我們從 分離 的角度,去思考物體間的碰撞。
而 GJK ,則是從 重疊 的角度來探索物體之間的碰撞。
為了方便理解,我們先創建兩個相互重疊的多邊形,并標記兩個多邊形重疊的部分:
目光聚焦到紅色的重疊部分,并想一想,它的幾何意義究竟是什么?
我們在中學就已經學過,兩個直線相交,會產生一個點。這個點都在這兩條直線上,這意味著,反應在坐標系上,兩條直線享有一個 共同的坐標 。而對于平面,就是無數條直線構成。兩個圖形產生了重疊,意味著他們有著一組共同的點, 共享一組坐標 。
而產生碰撞的條件是,兩個圖形必須 至少重合一個點 ,否則將不會產生碰撞。翻譯成計算機能聽懂的話:
“是否能從兩個圖形中,各自找到一個點,使得它們相減后為原點?”
這就是 GJK 算法的核心目的。當兩個圖形發生重疊時,他們 必然會有一個坐標,相減后為原點。
計算機想要“看見”兩個圖形重疊的部分,可以利用自身的計算優勢,把左邊整個圖形所包含的坐標 減去 右邊圖形所包含的坐標,并得到一系列的點。將所有計算后的點包圍起來,如果這個新生成的圖形 包含原點,則意味著兩個圖形發生了重疊,從而判斷兩個圖形發生了碰撞。我們把計算后的點稱為 閔可夫斯基差 ( Minkowski Difference ),將生成的三角形/線形稱為 單純形 ( Simplex )。
為了直觀地理解,我將兩個圖形所有坐標相減后的結果稱為 Minkowski Difference。實際上,似乎只存在 Minkowski Sum (閔可夫斯基和)這個說法。其實也可以理解為,將第二個圖形的所有坐標點取反后,加到第一個圖形的所有坐標點。將兩個圖形所有的坐標相減,顯然不是我們能夠手算的。但是,我們可以根據多邊形的特點,只需將他們的頂點相減,就可以達成我們的目的。但是這樣,排列組合后,需計算 20 個點,這顯然也不是我們想要的,并且可能會出現多余的計算結果。所以,我們需要盡量得到足夠大的單純形,這樣才會提升包含原點的幾率。
在GJK 算法中,我們定義一個名為 support 的函數。在這個例子中,它的作用是這樣的:
為了便于理解,我們創建兩個多邊形,并且規定
為藍色圖形的位置坐標, 為黃色圖形的位置坐標,從 指向 為 support 函數的起始方向。我們的目標是至少能夠算出三個點,構成一個包含三個頂點的單純形。第一次
依次按照上述步驟,我們得到這樣的一個結果:
得到黃色圖形在
方向上的最大投影點為來自于點 ,記錄坐標 ;得到藍色圖形在 方向 上的最大投影點為來自于點 ,記錄坐標 。將兩個坐標相減,得到單純形上的一個頂點 :
。第二次
然后,我們將初始方向取反,作為新的初始方向,再進行如上的步驟:
得到黃色圖形在
方向上的最大投影點為來自于點 ,記錄坐標 ;得到藍色圖形在 方向上的最大投影點為來自于點 ,記錄坐標 。將兩個坐標相減,得到單純形上的一個新的頂點 :
。第三次
之后,我們取與起始向量垂直的向量作為新的方向向量,值得注意的是,這樣的方向向量有兩個,一個是 指向原點的
,一個是 背離原點的 。我們不妨以先背離原點的
作為新的方向,重復 support 函數。得到黃色圖形在
方向上的最大投影點為來自于點 ,記錄坐標 ;得到藍色圖形在 方向 上的最大投影點為來自于點 ,記錄坐標 。將兩個坐標相減,得到單純形上的一個新的頂點 :
。構造單純形
我們得到了三個點:
,畫出單純形:我們似乎沒能構成一個包含原點的單純形。
如果我們換成
,計算后,我們將會得到一個新的點 。畫出這個新的單純形:這一次,我們 幸運地 包含了原點!
從以上幾個步驟,不難看出, GJK 是一種 迭代算法,它需要不斷地檢測單純形是否包含原點。它退出迭代的條件是:
到目前為止,我們離真正實現 GJK 碰撞檢測還有一段距離,以及碰撞之后,如何通過EPA算法,獲得它的穿透向量。這些內容,將在稍后的篇章中詳細介紹。
總結
以上是生活随笔為你收集整理的java计算一个多边形的重心_2D凸多边形碰撞检测算法(二) - GJK(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python实现kNN算法
- 下一篇: Java面试——Spring系列总结