1. 程式人生 > >《實時碰撞檢測演算法技術》讀書筆記(七):分離軸測試

《實時碰撞檢測演算法技術》讀書筆記(七):分離軸測試

分離軸測試基於凸體:給定兩凸體集AB,若兩集合不存在交集,則必定存在一個軸使得兩凸體投影無重疊。若找不到該軸,則兩凸體集相交。

對於對稱幾何體如線段、AABBOBB、球體等,其包含中心C且為投影軸上投影區間的中心位置,只需計算其投影區間的1/2寬度或半徑,求和並於二中心投影間的距離進行比較,若和小於中心投影間距離,則物體物件處於分離。如下圖:


總體上講,多面體物件間的分離測試需要考查下列軸:

平行於物體A的面法線的軸

平行於物體B的面法線的軸

平行於物體AB各邊生成的叉積向量的軸

一旦找到分離軸,測試即可立刻退出並返回“分離”資訊。若全測試完且不存在,則物件間必定相交。

對於2D物體,只需要考查兩物體所有邊的法向量即可。

分離軸測試的健壯性:

物體間相應邊的叉積向量可以構造分離軸,但是若兩向量平行,則叉積結果為0向量,此時不適合用於分離軸。普遍採用以下方案:檢測叉積向量是否為(準)0向量。若是,則重新生成與兩個邊向量垂直的新軸,或者僅忽略該軸。

下列程式碼片段針對邊ABCD,給出健壯的分離軸測試的實現方式:

  1. //Commpute a tentative separating axis for ab and cd
  2. Vector m = Cross(ab,cd);  
  3. if(!IsZeroVector(m)) {  
  4.     //Edges ab and cd not parallel, continue with m as a potential separating axis
  5.     ...  
  6. else {  
  7.     //Edges ab and cd must be(near) parallel, and therefore lie in some plane P.
  8.     //Thus, as a separating axis try an axis perpendicular to ab and lying in P
  9.     Vector n = Cross(ab, c - a);  
  10.     m = Cross(ab, n);     
  11.     if(!IsZeroVector(m)) {  
  12.         //continue with m as a potential separating axis
  13.         ...  
  14.     }  
  15.     //ab and ac are parallel too, so edges must be on a line. Ignore testing
  16.     //the axis for this combination of edges as it won’t be a separating axis.
  17.     //(Alternatively, lest if edges overlap on this line, in which case the
  18.     //objects are overlapping.)
  19.     ...  
  20. }  


另外,若叉積向量過大,會導致計算過程中精度損失。如果並未限定輸入向量的範圍,則應在叉積計算之前對向量執行範化操作以保持相應的精度。