最近需要做一些碰撞檢測相關的東西。AABB是遊戲引擎中最常用的碰撞基本體了,具有各種優良的特性。其本身的自交判斷很簡單(這句話咋恁彆扭呢*~*),而且與其它形體的相交判斷也不是很複雜。求一點到AABB上的最近點對很常用,也比較簡單,代碼如下所示:
void ClosestPtPointAABB(const Point& p , const AABB& b , Point& q)
{
for (int i = 0 ; i < 3 ; ++i)
{
float v = p[i];
v = max(v , b.min[i]);
v = min(v , b.max[i]);
q[i] = v;
}
}
反過來,求一點到AABB上的最遠點呢?這個操作可能沒有求最近點常用,但是還是會有使用場合的。分析一下可以發現AABB上到另外一點間的最遠點其實就是組成其的8個點中的一個,但是該不會要逐個遍歷吧,那也太原始了。其實只需要判斷一下這個點在AABB中所處的大體位置,然後決定選用那個角點就Okay了。
void FurthestPtPointAABB(const Point& p , const AABB& b , Point& q)
{
Point minP , maxP , c;
minP = b.GetMin();
maxP = b.GetMax();
c = b.GetCenter();
// X
q.x = (dstPoint.x > center.x) ? minPos.x : maxPos.x;
// Y
q.y = (dstPoint.y > center.y) ? minPos.y : maxPos.y;
// Z
q.z = (dstPoint.z > center.z) ? minPos.z : maxPos.z;
}
另外,還有關於計算生成Bounding Sphere的問題。比如對於一個Camera,可能需要從其對應的Frustum來生成一個Sphere作一些特殊目的的使用,比如Culling等。一般的方法(且也是之前用的方法)是直接求出Frustum對應的8個頂點的Average Point,然後得到球體的中心,接着選取該中心到8個頂點中的最遠距離做爲半徑。但是某些情況下這種方法可能會得到極不好的結果,對於不均勻、不規則的Frustum可能會得到灰常巨大的Sphere,可以看下圖對於一個2D三角形的說明。
更好的一種方法是先求出包圍Frustum的AABB(當然,OBB會更好),然後從此AABB上來計算得到對應的Sphere,這樣就會得到稍優化的Sphere。
當然對於計算包圍Sphere最精確的方法就是計算出外切圓了,但是這代價就比較大了,應用會有所限制。