計算多邊形之間的最近距離,才是gjk演算法原本的目的。只有兩個多邊形不相交,計算最近距離才有效。如果相交,則最近距離無效,但是可以使用epa演算法要計算碰撞深度。本文的寫作目的,主要是對gjk演算法的理解和應用。對演算法本身感興趣的朋友,可以閱讀源**的文獻。本系列gjk演算法文章共三篇,本篇是第二篇,強烈建議從第一篇開始看:
3. 小結
4. 參考
計算多邊形之間的距離,本質是在兩個多邊形上找到距離最近的邊,然後計算兩個邊之間的最近距離。計算最近距離的演算法和gjk碰撞檢測演算法類似,同樣使用閔可夫斯基差來構建單形體,使用同樣的support函式。當沒有發生碰撞的時候,距離原點最近的閔可夫斯基差集多邊形的邊,就是我們要計算最近距離的關鍵。為了方便表示,下文將該邊稱作「差集最近邊」。
gjk最近距離演算法的兩個關鍵點為:
需要注意的是,兩個多邊形最近的位置不一定是邊,也可能是頂點。不過這種情況,可以認為是長度為0的特殊邊。
/// 按步驟分解,碰撞檢測
public
bool
gjk(shape shapea,
shape shapeb)
******x.
add(p)
;// 單形體包含原點了
if(******x.
contains
(vector2.zero)
) direction =
findnextdirection()
;}computeclosetpoint()
;return
false
;}
選擇下次的迭代方向不同。上一章用的是原點到直線的垂線作為迭代方向;本章用的是原點到線段的最近向量,作為迭代方向。注意,原點到線段的最近距離不一定就是垂足,可能是線段的某個端點。
不發生碰撞的結束條件不同。上一章迭代演算法最終結束時,可能是乙個不包含原點的三角形,為了得到差集最近邊,我們可以捨棄掉距離原點較遠的那個邊。這裡我們讓演算法多迭代一次,恰好可以捨棄掉那個點,同時會額外會產生乙個重複的support點。因此只要發現support點位置重疊了,就表明迭代演算法可以結束了。
計算步驟的分解**:
最近距離就是原點到差集最近邊的距離。先求出原點到線段的最近點,然後計算原點到最近點的距離即可。設線段為ab,原點為o,先計算出ao在ab上的投影長度:
這裡有個小技巧,計算投影長度,需要將被投影向量ab單位化,也就是要求ab的長度。但是為了讓ao在ab上投影長度單位化到[0, 1]之間,需要額外除以ab的長度,因此計算投影的時候,直接就除以ab長度的平方了,就省去了計算長度時的開方運算。
vector2
getclosestpointtoorigin
(vector2 a,
vector2 b)
// 計算投影長度,並單位化到[0, 1],需要額外除以ab的長度。因此這裡就直接除以長度的平方了。
float
projection = vector2.
dot(ab, ao)
/ sqrlength;
if(projection <0)
else
if(projection >
1.0f
)else
}
我們改造一下support方法,每次將生成support點用到的兩個頂點也記錄下來。這樣通過support點,可以反向找回多邊形的邊。
設是差集最近邊為l=a
bl = ab
l=ab
,a、b是support點,構成a、b兩的頂點分別自兩個多邊形的邊e1=
aa−b
ae1 = aa - ba
e1=aa−
ba、e 2=
ab−b
be2 = ab - bb
e2=ab−
bb。則求兩個凸包的最近距離,就演變成了求e1和e2兩個邊的最近距離。
設q是原點到l的垂直向量,也就是垂足,則有:
l = b - a \\ q · l = 0 \end
r2 = -(l · a) / (l · l)\\ r1 = 1 - r2 \\ qa = aa * r1 + ba * r2 \\ qb = ab * r1 + bb * r2 \end
⎩⎪⎪⎪⎨⎪
⎪⎪⎧
r2=−
(l⋅a
)/(l
⋅l)r
1=1−
r2qa
=aa∗
r1+b
a∗r2
qb=a
b∗r1
+bb∗
r2計算最近點的偽**如下:
void
computeclosetpoint()
else
}
gjk計算多邊形之間的最近距離,本質上是使用gjk演算法求得差集最近邊。而構成差集最近邊的兩個support點,就是來自兩個多邊形的最近邊上的4個頂點。然後就將問題轉換成,計算兩條邊之間的最近距離和最近點。
本章demo使用unity3d引擎開發,demo工程已上傳github:
nxOgre物理引擎
糾結半天還是來看了nxogre引擎。最後搭建的環境是 vs2010 nxogre ogre1.74 physx2.8.4 主要是看那個 betajaen s ramblings 這兩個算是比較新的了,其它的好像是ogre1.7版本以前的相容版本,沒法在新的ogre中使用了。最後乙個是教程,需要上面兩...
物理引擎ODE
出處 russell smith 的 open dynamics engine ode 是乙個開源的物理引擎,使用它可以 鉸接式固形體運動。這樣不管我們使用哪種圖形庫 可能使用 opengl 都可以對真實物件的物理特性進行 我們可以使用 ode 來對合成環境中的各種物件進行建模,例如三維遊戲環境中的...
APE物理引擎教程
ape 物理引擎有很好的效果,重要的是類很少,簡單易學。附件是我這個物理引擎寫的乙個遊戲,也是我的第乙個遊戲看到網上這個引擎的教程還比較少,當初找的好苦,發幾個我淘來的,下面幾個教程是在做遊戲過程中看的 ape物理引擎首頁 api文件 google論壇 有介紹貼圖,碰撞檢測 如何在flex中使用引擎...