简单AABB包围盒(轴向包围盒)碰撞检测实现(C++代码)
·
1、AABB包围盒原理
AABB包围盒算法是基于轴对齐的边界框,通过在三维空间中定义一个最小的长方体来包围物体。该长方体的边与坐标轴平行,从而简化了计算过程。算法的核心在于快速判断两个物体是否可能发生碰撞,通过比较它们的AABB包围盒是否重叠来实现。如果两个包围盒在任意轴上不重叠,则可以确定这两个物体不会发生碰撞,从而避免了复杂的精确碰撞检测。这种方法在计算机图形学、物理仿真和游戏开发中广泛应用,因其高效性和简单性而备受青睐。
2、碰撞检测实现
首先,定义每个物体的AABB包围盒,即确定其最小和最大顶点坐标。接着,在每次更新物体位置时,重新计算包围盒的边界。当检测两个物体是否碰撞时,比较它们的AABB包围盒,如果其中一个包围盒的最小顶点坐标大于另一个包围盒的最大顶点坐标,或者反之,则判定为无碰撞。否则,进一步进行精确碰撞检测。此方法高效且适用于大规模场景中的粗略碰撞检测,有效减少计算量。
1、碰撞检测实现
bool IntersectsCollide(const LAABB& aabb) const
{
T xInters = T(0);
T yInters = T(0);
T zInters = T(0);
xInters = calOverOne(m_ptMax[0], m_ptMin[0], aabb.m_ptMax[0], aabb.m_ptMin[0]);
if (DIMS > 1) {
yInters = calOverOne(m_ptMax[1], m_ptMin[1], aabb.m_ptMax[1], aabb.m_ptMin[1]);
}
if (DIMS > 2) {
zInters = calOverOne(m_ptMax[2], m_ptMin[2], aabb.m_ptMax[2], aabb.m_ptMin[2]);
}
if (DIMS ==2)
{
return xInters > m_interDis && yInters > m_interDis;
}
if (DIMS == 3)
{
int count = 0;
if (xInters > m_interDis){
++count;
}
if (yInters > m_interDis)
{
++count;
}
if (zInters > m_interDis)
{
++count;
}
return count>=2;
}
}
2、重叠部分判断
T calOverOne(const T &amax,const T &amin,const T& bmax,const T &bmin)const {
T minMax = 0;
T maxMin = 0;
if (amax < bmax) {//Left
minMax = amax;
maxMin = bmin;
}
else { //Right
minMax = bmax;
maxMin = amin;
}
if (minMax > maxMin) {
return minMax - maxMin;
}
else {
return T(0);
}
}
3、完整部分代码
template<typename T, int DIMS >
class LAABB
{
public:
typedef LPoint<T, DIMS> POINT;
LAABB() {
m_ptMin = POINT();
m_ptMax = POINT();
m_interDis = 0;
}
~LAABB()
{}
LAABB(POINT& ptMin, POINT& ptMax)
{
m_ptMin = ptMin;
m_ptMax = ptMax;
}
LAABB(const LAABB& other)
{
m_ptMin = other.m_ptMin;
m_ptMax = other.m_ptMax;
}
LAABB& operator=(const LAABB& box)
{
if (this == &box)
{
return *this;
}
this->m_ptMin = box.m_ptMin;
this->m_ptMax = box.m_ptMax;
return *this;
}
public:
void SetIntersectsDis(T dis)
{
m_interDis = dis;
}
bool Intersects(const LAABB& aabb) const
{
if (aabb.m_ptMax[0] < m_ptMin[0]) return false;
if (aabb.m_ptMin[0] >= m_ptMax[0]) return false;
if (DIMS > 1) {
if (aabb.m_ptMax[1] < m_ptMin[1]) return false;
if (aabb.m_ptMin[1] >= m_ptMax[1]) return false;
}
if (DIMS > 2) {
if (aabb.m_ptMax[2] < m_ptMin[2]) return false;
if (aabb.m_ptMin[2] >= m_ptMax[2]) return false;
}
return true;
}
bool IntersectsCollide(const LAABB& aabb) const
{
T xInters = T(0);
T yInters = T(0);
T zInters = T(0);
xInters = calOverOne(m_ptMax[0], m_ptMin[0], aabb.m_ptMax[0], aabb.m_ptMin[0]);
if (DIMS > 1) {
yInters = calOverOne(m_ptMax[1], m_ptMin[1], aabb.m_ptMax[1], aabb.m_ptMin[1]);
}
if (DIMS > 2) {
zInters = calOverOne(m_ptMax[2], m_ptMin[2], aabb.m_ptMax[2], aabb.m_ptMin[2]);
}
if (DIMS ==2)
{
return xInters > m_interDis && yInters > m_interDis;
}
if (DIMS == 3)
{
int count = 0;
if (xInters > m_interDis){
++count;
}
if (yInters > m_interDis)
{
++count;
}
if (zInters > m_interDis)
{
++count;
}
return count>=2;
}
}
protected:
T calOverOne(const T &amax,const T &amin,const T& bmax,const T &bmin)const {
T minMax = 0;
T maxMin = 0;
if (amax < bmax) {//Left
minMax = amax;
maxMin = bmin;
}
else { //Right
minMax = bmax;
maxMin = amin;
}
if (minMax > maxMin) {
return minMax - maxMin;
}
else {
return T(0);
}
}
private:
POINT m_ptMin;
POINT m_ptMax;
T m_interDis;
};
注意:POINT类型可以修改为自己定义的类型。
更多推荐
所有评论(0)