Point與AABB間的最遠點對

最近需要做一些碰撞檢測相關的東西。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最精確的方法就是計算出外切圓了,但是這代價就比較大了,應用會有所限制。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章