class ZXFOctree
{
public:
ZFXOctree();
virtual~ZFXOctree();
void BuildTree(const ZFXPolygon*,UINT);
void Traverse(ZFXPolylist*,ZFXPolylist*,const ZFXPlane*);
ZFXAabb GetAabb(){ return m_Aabb;}
bool GetFloor (const ZFXVector&, float *, ZFXPlane*);
bool TestCollision(const ZFXAabb&, ZFXPlane*);
bool TestCollision(const ZFXRay&, float, float*);
private:
ZFXAabb m_Aabb;
ZFXPolygon *m_pPolys; //if leaf
UINT m_NumPolys; //if leaf
ZFXOctree *m_pChild[8] ; // 8 children
ZFXOctree *m_pRoot;
ZFXOctree *m_pParent;
int m_Pos; // NO,NW
void CalcBonudingBox(const ZFXPolygon*, UINT);
void InitChildObject(int ChildID, ZFXOctree *pP);
void ChopListToMe(ZFXPolygon *,UINT);
void CreateChilds(ZFXOctree *pRoot);
void GetAabbAsPolygons(ZFXPolylist *);
bool IntersectsDownwardsRay(const ZFXVector&, float);
bool IsLeaf(){ return (m_pChild[0]==NULL);}
void SetBoundingBox(const ZFXAabb &Aabb){memcpy(&m_Aabb,&Aabb,sizeof(ZFXAabb));}
};
ZFXOctree::ZFXOctree()
{
m_NumPolys=0;
m_Pos = -1;
m_pPolys = NULL;
m_pRoot = NULL;
m_pParent = NULL;
for( int i=0;i<8;i++)m_pChild[i] = NULL;
memset(&m_Aabb, 0,sizeof(ZFXAabb));
}
ZFXOctree::~ZFXOctree()
{
m_NumPolys = 0;
SAFE_DELETE_A(m_pPolys);
for(int i=0;i<8;i++)
SAFE_DELETE(m_pChild[i]);
}
初始化子节点
void ZFXOctree::InitChildObject(int ChildID,ZFXOctree *pParent)
{
ZFXAabb aabb;
float xmin = m_Aabb.vcMin.x , xcen = m_Aabb.vcCenter.x , xmax = m_Aabb.vcMax.x;
float ymin = m_Aabb.vcMin.y , xcen = m_Aabb.vcCenter.y , xmax = m_Aabb.vcMax.y;
float zmin = m_Aabb.vcMin.z , xcen = m_Aabb.vcCenter.z , xmax = m_Aabb.vcMax.z;
switch(ChildID)
{
case UP_NW:
aabb.vcMax = ZFXVector(xcen , ymax, zmax);
aabb.vcMin = ZFXVector(xmin , ycen ,zmin);
break;
case UP_NE:
aabb.vcMax = m_Aabb.vcMax;
aabb.vcMin = m_Aabb.vcCenter;
break;
case UP_SW:
aabb.vcMax = ZFXVector(xcen , ymax, zcen);
aabb.vcMin = ZFXVector(xmin , ycen ,zmin);
break;
case UP_SE:
aabb.vcMax = ZFXVector(xmax , ymax, zcen);
aabb.vcMin = ZFXVector(xcen , ycen ,zmin);
break;
case LW_NW:
aabb.vcMax = ZFXVector(xcen , ycen, zmax);
aabb.vcMin = ZFXVector(xmin , ymin ,zcen);
break;
case LW_NE:
aabb.vcMax = ZFXVector(xmax , ycen, zmax);
aabb.vcMin = ZFXVector(xcen , ymin ,zcen);
break;
case LW_SW:
aabb.vcMax = m_Aabb.vcCenter;
aabb.vcMin = m_Aabb.vcMin;
break;
case LW_SE:
aabb.vcMax = ZFXVector(xmax , ycen, zcen);
aabb.vcMin = ZFXVector(xcen , ymin ,zmin);
break;
default: break;
}
aabb.vcCenter = (aabb.vcMax + aabb.vcMin)/2.0f;
m_pChild[ChildID] = new ZFXOctree();
m_pChild[ChildID]->SetBoundingBox(aabb);
m_pChild[ChildID]->m_Pos = ChildID;
m_pChild[ChildID]->m_pParent = pParent;
}
void ZFXOctree::BuildTree(const ZFXPolygon *pPolys, UINT Num)
{
m_pRoot = this;
if(Num<1) return;
//calculate AABB for the root node
CalcBoundingBox(pPolys,Num);
m_pPolys=new ZFXPolygon[Num];
m_NumPolys = Num;
for(UINT i=0; i<Num; i++)
m_pPolys[i].Copyof( pPolys[i]);
CreateChilds(this);
SAFE_DELETE_A(m_pPolys);
}
void ZFXOctree::CreateChilds(ZFXOctree *pRoot)
{
m_pRoot = pRoot;
if((pRoot ==this) || (m_NumPolys > POLYS_PER_LEAF))
{
for(int i=0;i<8;i++)
{
InitChildObject(i , this);
m_pChild[i]->ChopListToMe(m_pPolys, m_NumPolys);
m_pChild[i]->CreateChilds(pRoot);
}
SAFE_DELETE_A(m_pPolys);
}
else return;
}