两个AABB相交测试算法详解

本文介绍了如何进行3D空间中AABB(轴对齐包围盒)的碰撞检测。首先,通过计算两AABB中心点的距离与它们半尺寸之和的比较来判断是否相交。然后,计算渗入深度,找出碰撞法线所在轴的最小渗入深度,以确定碰撞信息,包括碰撞点和碰撞法线。该方法适用于非高速情况下的碰撞检测。
摘要由CSDN通过智能技术生成

判断两个AABB是否相交

基本思想为当两个AABB包围盒ab的中心位置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_mina_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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值