引言
在3D碰撞检测中,为了加快碰撞检测的效率,减少不必要的碰撞检测,会使用基本几何体作为物体的包围体(Bounding Volume, BV)进行测试。基本包围体的碰撞检测相对来说便宜也容易的多,所以如果在基本包围体的碰撞检测中都没有通过的话,那么就没有必要进行更加复杂的碰撞检测了。
而对于不同性质,不同形状的模型,需要根据情况选择不同的包围体,一般来说,包围体分为如下的几种:
Sphere, AABB, OBB, 8-DOP, Convex Hull这几种常见的。
接下来将向大家讲述如何使用Sphere包围体。
表示方法
想要使用包围体,我们就要知道,如何的表示一个包围球体。对于球体来说,表示它很简单,如下所示:
struct Sphere
{
VECTOR3 center ;
float radious ;
};
这样,在有了中点和半径之后,我们就能唯一的确定一个包围球体了。
包围球之间的碰撞检测
对于包围球之间的碰撞检测,十分的简单,只要判断两个包围球心之间的距离是否小于他们两个的半径之和就可以了。如果小于,那么这两个包围球发生了交叉,没有的话,就相互分离。以下是进行碰撞检测的代码:
int TestSphereSphere(Sphere a, Sphere b)
{
VECTOR3 d = a.center - b.center ;
float dist2 = Dot(d, d);
float radisum = a.radious + b.radious ;
if(dist2 < radisum * radisum)
return 1 ;
else
return 0 ;
}
很简单不是嘛!由于进行开平方计算要消耗大量的CPU,所以,我们直接对球心之间距离的平方和他们半径之和的平方进行比较,结果与进行距离和半径之和的比较一致。
包围球体的计算
球形包围体的计算有很多的算法,在本篇文章中将讲述两种常见的计算方法。如果你使用DirectX,就会知道,DirectX内置了一个D3DXComputBoundingSphere的函数。这里将不会使用这个函数,而是使用我们自己创建的计算方法来进行包围球体的计算。
首先来介绍第一种包围球体的计算方法。
均值法
我们知道,在3D模型的表示中,一般都是用一系列的顶点来描述一个模型。所以,要求一个包围球体,我们就必须确定这个包围球体的球心,然后计算每一个顶点与球心的距离,选取最长的距离作为包围球体的半径。这个简单的算法就能够确定一个包围球体了。那么,有一个问题,如果的确定这个模型的球心了?
我们通过如下的简答方法来计算出这个模型的球心。我们将所有的顶点相加,然后除以顶点数,这样就能得到一个球心的位置了。
到这里,这个方法的理论就介绍完毕了,很容易不是吗???下面来看看这个方法的代码部分:
void Sphere::computeBoundingSphereAverage(VECTOR3* vertices, unsigned int vertex_num)
{
//Compute the center point
VECTOR3 total ;
total.x = 0 ;
total.y = 0 ;
total.z = 0 ;
for(int i = 0 ; i < vertex_num ; i ++)
{
total.x += vertices[i].x ;
total.y += vertices[i].y ;
total.z += vertices[i].z ;
}// end for
total.x /= vertex_num ;