八叉树

来源:互联网 发布:半实物仿真软件 编辑:程序博客网 时间:2024/05/21 20:17

#pragma once
#include "..//MFC_D3D//XD3D.h"
#include <vector>


const int BOXS8_NUM = 8;
struct BOXS8_NODE
{
 int iBoxID;
 D3DXVECTOR3 vMin;
 D3DXVECTOR3 vMax;
 D3DXVECTOR3 vPos;
 BOXS8_NODE* pChild[BOXS8_NUM];
 BOXS8_NODE()
 {
  iBoxID = -1;
  vMin = vMax = vPos = D3DXVECTOR3(0,0,0);
  for(int i=0; i<BOXS8_NUM; i++)
   pChild[i] = NULL;
 }
 BOXS8_NODE(const int in_iID,
  const D3DXVECTOR3& in_vMin,
  const D3DXVECTOR3& in_vMax,
  const D3DXVECTOR3& in_vPos)
 {
  iBoxID = in_iID;
  vMin = in_vMin;
  vMax = in_vMax;
  vPos = in_vPos;
  for(int i=0; i<BOXS8_NUM; i++)
   pChild[i] = NULL;
 }
};

class BOXS8_TREE
{
public:
 BOXS8_TREE():pBoxsTree(NULL){}
 ~BOXS8_TREE(){}

 int CheckHit(const D3DXVECTOR3& in_vPoint)
 {
  return CheckHit(in_vPoint,pBoxsTree);
 }

 void CreateBOXS8(
  const D3DXVECTOR3& in_vMin,
  const D3DXVECTOR3& in_vMax,
  const D3DXVECTOR3& in_vPos,
  const int in_iPly)
 {
  ClearBOXS8();
  int iID = 0;
  CreateBOXS8(pBoxsTree,in_vMin,in_vMax,in_vPos,in_iPly,iID);
 }

 void GetBoxPoint(std::vector<std::vector<D3DXVECTOR3>>& out_vData)
 {
  GetBoxPoint(out_vData,pBoxsTree);
 }

 void ClearBOXS8()
 {
  ClearBOXS8(pBoxsTree);
 }

 

private: 
 int CheckHit(const D3DXVECTOR3& in_vPoint, const BOXS8_NODE* pBox);
 void CreateBOXS8(BOXS8_NODE*& pBox,
  const D3DXVECTOR3& in_vMin,
  const D3DXVECTOR3& in_vMax,
  const D3DXVECTOR3& in_vPos,
  const int in_iPly,
  int& in_iIDStart);
 void GetBoxPoint(std::vector<std::vector<D3DXVECTOR3>>& out_vData,
  const BOXS8_NODE* pBox);
 void ClearBOXS8(BOXS8_NODE*& pBox);
 void GetBox(D3DXVECTOR3 o_vBox[24],
  const D3DXVECTOR3& in_vMin,
  const D3DXVECTOR3& in_vMax,
  const D3DXVECTOR3& in_vPos);

 BOXS8_NODE* pBoxsTree;
};

 

/////////////////////////////////

 

#include "BOXS8_TREE.h"

void BOXS8_TREE::CreateBOXS8(BOXS8_NODE*& pBox,
 const D3DXVECTOR3& in_vMin,
 const D3DXVECTOR3& in_vMax,
 const D3DXVECTOR3& in_vPos,
 const int in_iPly,
 int& in_iIDStart)
{
 pBox = new BOXS8_NODE(in_iIDStart, in_vMin,in_vMax,in_vPos);
 if( in_iPly > 1)
 {
  D3DXVECTOR3 vMid = (in_vMin + in_vMax)/2;
  D3DXVECTOR3 vPoint[BOXS8_NUM*2] =
  {
   D3DXVECTOR3(in_vMin.x, in_vMin.y, in_vMin.z),
   D3DXVECTOR3(vMid.x, vMid.y, vMid.z),
//
   D3DXVECTOR3(vMid.x, in_vMin.y, in_vMin.z),
   D3DXVECTOR3(in_vMax.x, vMid.y, vMid.z),

   D3DXVECTOR3(in_vMin.x, vMid.y, in_vMin.z),
   D3DXVECTOR3(vMid.x, in_vMax.y, vMid.z),

   D3DXVECTOR3(in_vMin.x, in_vMin.y, vMid.z),
   D3DXVECTOR3(vMid.x, vMid.y, in_vMax.z),
//
   D3DXVECTOR3(vMid.x, vMid.y, in_vMin.z),
   D3DXVECTOR3(in_vMax.x, in_vMax.y, vMid.z),

   D3DXVECTOR3(vMid.x, in_vMin.y, vMid.z),
   D3DXVECTOR3(in_vMax.x, vMid.y, in_vMax.z),
   
   D3DXVECTOR3(in_vMin.x, vMid.y, vMid.z),
   D3DXVECTOR3(vMid.x, in_vMax.y, in_vMax.z),
//
   D3DXVECTOR3(vMid.x, vMid.y, vMid.z),
   D3DXVECTOR3(in_vMax.x, in_vMax.y, in_vMax.z),
  };
  for(int i=0; i<BOXS8_NUM; i++)
  {
   CreateBOXS8(pBox->pChild[i], vPoint[i*2],vPoint[i*2+1],in_vPos,in_iPly-1,++in_iIDStart);
  }
 }
}

void BOXS8_TREE::GetBoxPoint(std::vector<std::vector<D3DXVECTOR3>>& out_vData,
 const BOXS8_NODE* pBox)
{
 if( NULL != pBox)
 {
  D3DXVECTOR3 BOXPOINT[24];
  GetBox(BOXPOINT,pBox->vMin,pBox->vMax, pBox->vPos);
  std::vector<D3DXVECTOR3> data;
  for(int i=0; i<24; i++)
   data.push_back(BOXPOINT[i]);
  out_vData.push_back(data);
  for(int i=0; i<BOXS8_NUM; i++)
   GetBoxPoint(out_vData,(const BOXS8_NODE*)pBox->pChild[i]);
 }
}

void BOXS8_TREE::ClearBOXS8(BOXS8_NODE*& pBox)
{
 if( NULL == pBox)
  return;
 else
 {
  for(int i=0; i<BOXS8_NUM; i++)
  {
   ClearBOXS8(pBox->pChild[i]);
  }
  delete[] pBox;
  pBox = NULL;
 }
}


void BOXS8_TREE::GetBox(D3DXVECTOR3 o_vBox[24],
 const D3DXVECTOR3& in_vMin,
 const D3DXVECTOR3& in_vMax,
 const D3DXVECTOR3& in_vPos)
{
 const D3DXVECTOR3 BOX_POINT[] =
 {
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMin.z),

  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMax.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMax.z),

  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMax.z),

  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMax.z),
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMax.z),

  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMax.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMax.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMin.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMax.z),

  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMin.y, in_vPos.z + in_vMax.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMax.z),
  D3DXVECTOR3(in_vPos.x + in_vMin.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMax.z),
  D3DXVECTOR3(in_vPos.x + in_vMax.x, in_vPos.y + in_vMax.y, in_vPos.z + in_vMax.z),
 };

 memcpy(o_vBox, BOX_POINT, sizeof(BOX_POINT));
}

int BOXS8_TREE::CheckHit(const D3DXVECTOR3& in_vPoint, const BOXS8_NODE* pBox)
{
 if( NULL != pBox)
 {
  D3DXVECTOR3 vMin = pBox->vMin + pBox->vPos;
  D3DXVECTOR3 vMax = pBox->vMax + pBox->vPos;
  if( in_vPoint.x >= vMin.x
   && in_vPoint.x <= vMax.x
   && in_vPoint.y >= vMin.y
   && in_vPoint.y <= vMax.y
   && in_vPoint.z >= vMin.z
   && in_vPoint.z <= vMax.z)
  {
   for(int i=0; i<BOXS8_NUM; i++)
   {
     //有更准确的返回更准确的箱子
    int k = CheckHit(in_vPoint, (const BOXS8_NODE*)pBox->pChild[i]);
    if( -1 != k)
     return k;
   }
   //无更准确的返回当前箱子
   return pBox->iBoxID;
  }
 }
 return -1;
}