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最精确的方法就是计算出外切圆了,但是这代价就比较大了,应用会有所限制。

 

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