判断两个AABB是否相交
基本思想为当两个AABB包围盒a和b的中心位置pos的距离小于两个的hafl_size的和的时候则相交。
bool AABBIntersectionTest(const Vector3& a_pos, const Vector3& b_pos,
const Vector3& a_half_size, const Vector3& b_half_size)
{
Vector3 delta = b_pos - a_pos;
Vector3 totalSize = a_half_size + b_half_size;
if (abs(delta.x) < totalSize.x &&
abs(delta.y) < totalSize.y &&
abs(delta.z) < totalSize.z) {
return true;
}
return false;
}
求碰撞信息
在通过上文中的相交测试之后,可以通过如下方法获取渗入深度 penetration 。基本思想为分别计算出 b_max - a_min 和 a_max - b_min 的值。然后求出二者各三个轴的分量(即共六个分量)中的最小值即为渗入深度。如图所示,在非高速的情况下,如果发生碰撞即能检测到,则碰撞法线所在的轴的渗入深度是一定小于其他轴的。
碰撞法线即位于最大渗入深度所出现的轴。CollisionInfo 包含的信息为a的碰撞点的local坐标,b的碰撞点的local坐标,a的local碰撞法线 normal 和渗入深度 penetration 。
bool FullAABBIntersectionTest(const Vector3& a_pos, const Vector3& b_pos, const Vector3& a_half_size, const Vector3& b_half_size, CollisionInfo& collision_info) {
if (AABBIntersectionTest(a_pos, b_pos, a_half_size, b_half_size)) {
static const Vector3 faces[6] = //a的六个面的方向
{
Vector3(-1, 0, 0), Vector3(1, 0, 0),
Vector3(0, -1, 0), Vector3(0, 1, 0),
Vector3(0, 0, -1), Vector3(0, 0, 1),
};
Vector3 a_max = a_pos + a_half_size;
Vector3 a_min = a_pos - a_half_size;
Vector3 b_max = b_pos + b_half_size;
Vector3 b_min = b_pos - b_half_size;
float distances[6] =
{
(b_max.x - a_min.x),// distance of box ’b’ to ’left ’ of ’a ’.
(a_max.x - b_min.x),// distance of box ’b’ to ’right ’ of ’a ’.
(b_max.y - a_min.y),// distance of box ’b’ to ’bottom ’ of ’a ’.
(a_max.y - b_min.y),// distance of box ’b’ to ’top ’ of ’a ’.
(b_max.z - a_min.z),// distance of box ’b’ to ’far ’ of ’a ’.
(a_max.z - b_min.z) // distance of box ’b’ to ’near ’ of ’a ’.
};
float penetration = FLT_MAX;
Vector3 best_axis;
for (int i = 0; i < 6; i++)
{
if (distances[i] < penetration) { //求渗入深度为求最小值(最小值也必为正数)
penetration = distances[i];
best_axis = faces[i];
}
}
collision_info.AddContactPoint({ 0, 0, 0 }, {0, 0, 0},
bestAxis, penetration); //由于是AABB,此处将两个AABB的碰撞点简化的设为各自的中心
return true;
}
return false;
}