Irrlicht - AABB

Posted on 2009-08-31 17:47  活着就是幸福  阅读(478)  评论(0编辑  收藏  举报

Boundingbox的两个决定点:

//! The near edge
vector3d<T> MinEdge;
//! The far edge
vector3d<T> MaxEdge;

计算BB的中心:(返回的是BB的中心)

vector3d<T> getCenter() const
{
return (MinEdge + MaxEdge) / 2;
}

计算BB大小:(返回的是BB的对角线向量, xyz分别是BB的各边长)

vector3d<T> getExtent() const
{
return MaxEdge - MinEdge;
}

与线段的交叉检测(这时长方体的中心已经被变换到坐标系原点, 线段也已经变换到BB空间):

bool intersectsWithLine(const vector3d<T>& linemiddle,//线段中心
const vector3d<T>& linevect,//线段的单位向量
T halflength) const//一半的 线段长度
{
    const vector3d<T> e = getExtent() * (T)0.5;//一半的对角线向量
    const vector3d<T> t = getCenter() - linemiddle;//线段中心到BB中心的向量

if ((fabs(t.X) > e.X + halflength * fabs(linevect.X)) ||
(fabs(t.Y) > e.Y + halflength * fabs(linevect.Y)) ||
(fabs(t.Z) > e.Z + halflength * fabs(linevect.Z)) )
return false;

e是一半的对角线向量, e的xyz分别是长方体的一半长宽高,也就是中心到各个面的距离.

t是从线段中心指向BB中心的向量.这样很明显看出,在第一步,先简单检测, 如果

|t.x| = |Cx| > |e.x| + |LineProjOnX|/2 = |e.x| + |Wx|那么在X方向上不相交. 然后是在YZ两个方向上用相同的判断.

图:<<3D图形学中的光线和包围盒相交检测>> Pu Jiantao (pjt@cis.pku.edu.cn)

在YZ平面: 如果X方向上相交,从BB中心向线段做垂线(向量a) :

a = W X (1,0,0) = (0, Wz, - Wy);

这里W = linevect.那么a = linevect X (1,0,0) = (0, linevect.z, -linevect.y);

t在a上的投影(BB中心到线段的距离) :

d = t*a = (t.x, t.y, t.z)*(0, linevect.z, -linevect.y) = |t.y*linevect.z - t.z*linevect.y|

同理, e在平行于linevect而过点(0, hy, hz)的直线L2上有一个投影r, 这个投影的距离用来和d做判断:

r = e * linevect = e.Y * linevect.Z + e.Z * linevect.Y

如果d < r则不相交.其它两个平面上的投影也是如此计算.

T r = e.Y * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.Y);
if (fabs(t.Y*linevect.Z - t.Z*linevect.Y) > r )
return false;

r = e.X * (T)fabs(linevect.Z) + e.Z * (T)fabs(linevect.X);
if (fabs(t.Z*linevect.X - t.X*linevect.Z) > r )
return false;

r = e.X * (T)fabs(linevect.Y) + e.Y * (T)fabs(linevect.X);
if (fabs(t.X*linevect.Y - t.Y*linevect.X) > r)
return false;

return true;

}