由于需要在三维空间中进行三维模型的碰撞与相交,为了加快检测的效率,考虑用三维物体包围盒。AABB与OOBB包围盒比起来原理简单,容易实现,为了更好的在三维空间中使用AABB包围盒,所以自己写了一个关于三维的AABB包围盒类AABB类,写了不同参数的构造函数,以及关于AABB包围盒的各种成员方法,虽然不是很全,但是可以满足日常的需要。
下面贴代码:
AABB.h
#pragma once
typedef struct My3DPoint//定义自己的三维点结构体
{
double X;//X坐标
double Y;//Y坐标
double Z;//Z坐标
};
typedef struct Triangle//三角形的结构体
{
My3DPoint Verters[3];//三角形的三个顶点
BOOL IsShow;//三维面是否需要显示
My3DPoint TriangleFaceNormal;//三角面片的法向量
};
class AABB
{
public:
AABB(void);//默认的无参构造函数
~AABB(void);//默认的析构函数
AABB(My3DPoint pointMin,My3DPoint pointMax);//自定义的有参构造函数,参数为两个My3DPoint结构的AABB包围盒最小最大坐标点
AABB(double m_Xmin,double m_Xmax,double m_Ymin,double m_Ymax,double m_Zmin,double m_Zmax);//自定义的有参的构造函数,参数为AABB包围盒最小最大点的坐标
AABB(Triangle a);//传进一个三角形结构体
BOOL IsOrNotInterection(AABB *a);//判断两个AABB包围盒是否相交,如果相交返回TRUE,如果不相交,返回FALSE
BOOL PointIsOrNotInAABBBoundingBox(My3DPoint pt);//判断一三维点是否落在某个AABB包围盒内
My3DPoint GetAABBBoxCeter();//求AABB包围盒的中心或者质心
BOOL IsOrNotEmpty();//判断AABB包围盒是否为空
double GetXLength();//得到X方向上的长度
double GetYLength();//得到Y方向上的长度
double GetZLength();//得到Z方向上的长度
double GetVolume();//得到AABB包围盒的体积
void DrawAABBBoundingBox();//绘制AABB包围盒
private:
double Xmin;//X的最小值
double Xmax;//X的最大值
double Ymin;//Y的最小值
double Ymax;//Y的最大值
double Zmin;//Z的最小值
double Zmax;//Z的最大值
};
AABB.cpp
#include "StdAfx.h"
#include "AABB.h"
//默认的构造函数
AABB::AABB(void)
{
}
//以AABB包围盒最小最大坐标点的My3DPoint结构体作为参数的构造函数
AABB::AABB(My3DPoint pointMin,My3DPoint pointMax)
{
Xmin=pointMin.X;
Ymin=pointMin.Y;
Zmin=pointMin.Z;
Xmax=pointMax.X;
Ymax=pointMax.Y;
Zmax=pointMax.Z;
}
//以AABB包围盒最小最大坐标点的六个坐标作为参数的构造函数
AABB::AABB(double m_Xmin,double m_Ymin,double m_Zmin,double m_Xmax,double m_Ymax,double m_Zmax)
{
Xmin=m_Xmin;
Xmax=m_Xmax;
Ymin=m_Ymin;
Ymax=m_Ymax;
Zmin=m_Zmin;
Zmax=m_Zmax;
}
//以Triangle三角形结构体作为参数的构造函数
AABB::AABB(Triangle a)
{
//用三元运算符来求出最大最小值
//求X的最小值
Xmin=a.Verters[0].X<a.Verters[1].X?a.Verters[0].X:a.Verters[1].X;
Xmin=Xmin<a.Verters[2].X?Xmin:a.Verters[3].X;
//求Y的最小值
Ymin=a.Verters[0].Y<a.Verters[1].Y?a.Verters[0].Y:a.Verters[1].Y;
Ymin=Ymin<a.Verters[2].Y?Ymin:a.Verters[3].Y;
//求Z的最小值
Zmin=a.Verters[0].Z<a.Verters[1].Z?a.Verters[0].Z:a.Verters[1].Z;
Zmin=Zmin<a.Verters[2].Z?Zmin:a.Verters[3].Z;
//求X的最大值
Xmax=a.Verters[0].X>a.Verters[1].X?a.Verters[0].X:a.Verters[1].X;
Xmax=Xmax>a.Verters[2].X?Xmax:a.Verters[2].X;
//求Y的最大值
Ymax=a.Verters[0].Y>a.Verters[1].Y?a.Verters[0].Y:a.Verters[1].Y;
Ymax=Ymax>a.Verters[2].Y?Ymax:a.Verters[2].Y;
//求Z的最大值
Zmax=a.Verters[0].Z>a.Verters[1].Z?a.Verters[0].Z:a.Verters[1].Z;
Zmax=Zmax>a.Verters[2].Z?Zmax:a.Verters[2].Z;
}
/*-----IsOrNotInterection(AABB *a,AABB *b)---------
函数功能:判断两个AABB包围盒是否相交
函数参数:a为AABB对象指针,本身对象为b包围盒
--------------------------------------------------*/
//判断两个AABB包围盒是否相交
BOOL AABB::IsOrNotInterection(AABB *a)
{
return ((Xmin >= a->Xmin && Xmin <= a->Xmax) ||
(a->Xmin >= Xmin && a->Xmin <= Xmax)) &&
((Ymin >= a->Ymin && Ymin <= a->YMax) ||
(a->Ymin >= Ymin && a->Ymin <= YMax)) &&
((Zmin >= a->Zmin && Zmin <= a->Zmax) ||
(a->Zmin >= Zmin && a->Zmin <= Zmax));
}
/*-----PointIsOrNotInAABBBoundingBox(My3DPoint pt,AABB *box)判断点是否落在AABB包围盒之内------
函数功能:判断三维点是否落在AABB包围盒之内
函数参数:pt为My3DPoint结构体,box为AABB包围盒对象指针
---------------------------------------------------------------------------------------------*/
BOOL AABB::PointIsOrNotInAABBBoundingBox(My3DPoint pt)
{
return (pt.X>=Xmin)&&(pt.X<=Xmax)&&
(pt.Y>=Ymin)&&(pt.Y<=Ymax)&&
(pt.Z>=Zmin)&&(pt.Z<=Zmax);
}
/*-----GetAABBBoxCeter()-------------------------------------------
函数功能:得到此AABB包围盒对象的质心,中心,返回一个My3DPoint结构体
-------------------------------------------------------------------*/
My3DPoint AABB::GetAABBBoxCeter()
{
My3DPoint m_point;
m_point.X=(Xmin+Xmax)*0.5;
m_point.Y=(Ymin+Ymax)*0.5;
m_point.Z=(Zmin+Zmax)*0.5;
return m_point;
}
/*-----IsOrNotEmpty()---------------------------------------------
函数功能:判断AABB包围盒是否为空,为空返回TRUE,不为空返回FALSE
------------------------------------------------------------------*/
BOOL AABB::IsOrNotEmpty()
{
return(Xmin>Xmax)||(Ymin>Ymax)||(Zmin>Zmax);
}
/*-----GetXLength()---------
函数功能:得到X方向上的长度
--------------------------*/
double AABB::GetXLength()
{
return Xmax-Xmin;
}
/*-----GetYLength()---------
函数功能:得到Y方向上的长度
--------------------------*/
double AABB::GetYLength()
{
return Ymax-Ymin;
}
/*-----GetZLength()---------
函数功能:得到Z方向上的长度
--------------------------*/
double AABB::GetZLength()
{
return Zmax-Zmin;
}
/*-----GetVolume()-------------
函数功能:得到AABB包围盒的体积
------------------------------*/
double AABB::GetVolume()
{
return (Xmax-Xmin)*(Ymax-Ymin)*(Zmax-Zmin);
}
/*-----DrawAABBBoundingBox()-------------------
函数功能:绘制AABB包围盒
-----------------------------------------------*/
void AABB::DrawAABBBoundingBox()
{
//第一根线
glBegin(GL_LINE);
glVertex3f(Xmin,Ymin,Zmin);
glVertex3f(Xmax,Ymin,Zmin);
glEnd();
//第二根线
glBegin(GL_LINE);
glVertex3f(Xmin,Ymin,Zmin);
glVertex3f(Xmin,Ymin,Zmax);
glEnd();
//第三根线
glBegin(GL_LINE);
glVertex3f(Xmin,Ymin,Zmin);
glVertex3f(Xmin,Ymax,Zmin);
glEnd();
//第四根线
glBegin(GL_LINE);
glVertex3f(Xmin,Ymin,Zmax);
glVertex3f(Xmax,Ymin,Zmax);
glEnd();
//第五根线
glBegin(GL_LINE);
glVertex3f(Xmax,Ymin,Zmin);
glVertex3f(Xmax,Ymin,Zmax);
glEnd();
//第六根线
glBegin(GL_LINE);
glVertex3f(Xmax,Ymin,Zmin);
glVertex3f(Xmax,Ymax,Zmin);
glEnd();
//第七根线
glBegin(GL_LINE);
glVertex3f(Xmax,Ymax,Zmin);
glVertex3f(Xmin,Ymax,Zmin);
glEnd();
//第八根线
glBegin(GL_LINE);
glVertex3f(Xmin,Ymax,Zmin);
glVertex3f(Xmin,Ymax,Zmax);
glEnd();
//第九根线
glBegin(GL_LINE);
glVertex3f(Xmax,Ymax,Zmin);
glVertex3f(Xmax,Ymax,Zmax);
glEnd();
//第十根线
glBegin(GL_LINE);
glVertex3f(Xmin,Ymin,Zmax);
glVertex3f(Xmin,Ymax,Zmax);
glEnd();
//第十一根线
glBegin(GL_LINE);
glVertex3f(Xmax,Ymin,Zmax);
glVertex3f(Xmax,Ymax,Zmax);
glEnd();
//第十二根线
glBegin(GL_LINE);
glVertex3f(Xmin,Ymax,Zmax);
glVertex3f(Xmax,Ymax,Zmax);
glEnd();
}
AABB::~AABB(void)
{
}
如果日后有修改会贴上修改后的代码。
如果您觉得这篇博文有用,请访问我的个人站:http://www.stubbornhuang.com,更多博文干货等着您。