Bsp 空间分割模拟实现

Bsp:二叉分割树,在游戏中用来分割局部空间,方便碰撞检测等的实现。
  1. 下面介绍一种简单易用的分割方法:分割步骤:一、将空间中的所有的面,加入的根部节点。二、遍历根部节点的所有面,分别找到x、y、z的最大最小值,给根节点指定一个合适的包围空间。三、在这个节点的包围空间里找到最长轴、并按这个最长轴的中间点做为新的分割点,遍历该节点的所有面将其分在其左右子节点中。四、返回第2步,直到达到一定限制条件,结束,此时空间已经被分开了。当然闲话不说,贴上实现模拟代码:
#include"stdafx.h"
  1. #include<map>
  2. #include<vector>
  3. #include<iostream>
  4. usingnamespacestd;
  5. structpoint
  6. {
  7. floatx,y,z;
  8. point():x(0.0f),y(0.0f),z(0.0f){};
  9. point(floata,floatb,floatc):x(a),y(b),z(c){}
  10. voidoperator+=(intn)
  11. {
  12. x+=n;
  13. y+=n;
  14. z+=n;
  15. }
  16. voidoperator=(point&p)
  17. {
  18. memcpy(this,(void*)&p,sizeof(*this));
  19. }
  20. };
  21. structface
  22. {
  23. pointP[3];
  24. voidoperator+=(intn)
  25. {
  26. P[0]+=n;
  27. P[1]+=n;
  28. P[2]+=n;
  29. }
  30. };
  31. structBBox
  32. {
  33. pointMin;
  34. pointMax;
  35. BBox():Min(),Max(){}
  36. };
  37. enumEAxis
  38. {
  39. Axis_X,
  40. Axis_Y,
  41. Axis_Z,
  42. };
  43. structTreeNode
  44. {
  45. TreeNode():box(),nDepth(0),pLChild(NULL),pRChild(NULL),Axis(Axis_X),Split(0.0f){vFaceId.reserve(16);}
  46. intnDepth;
  47. TreeNode*pLChild;
  48. TreeNode*pRChild;
  49. std::vector<int>vFaceId;
  50. intAxis;
  51. BBoxbox;
  52. floatSplit;
  53. };
  54. std::map<int,face>m_mFace;
  55. face*GetFaceByID(intnID)
  56. {
  57. std::map<int,face>::iteratoritr=m_mFace.find(nID);
  58. if(itr!=m_mFace.end())
  59. {
  60. return&(m_mFace[nID]);
  61. }
  62. returnNULL;
  63. }
  64. classBspTree
  65. {
  66. public:
  67. BspTree():m_pRoot(NULL){};
  68. ~BspTree()
  69. {
  70. if(m_pRoot)
  71. {
  72. DeleteNode(m_pRoot);
  73. }
  74. }
  75. //初始化树根
  76. voidInitTreeRoot(TreeNode*pNode);
  77. //释放整个树的资源
  78. voidDeleteNode(TreeNode*pNode);
  79. //生成AABB包围盒
  80. voidBuildAABB(TreeNode*pNode);
  81. //切分整个空间
  82. voidSplitSpace(TreeNode*pRoot,intnAxis,intndepth);
  83. //切分面
  84. voidSplitFace(intnFaceId,floatfSplit,intnAxis,int*pLeftNum,int*pRightNum,int*pBothNum);
  85. //遍历整个树
  86. voidErgodicTree(TreeNode*pNode);
  87. protected:
  88. private:
  89. TreeNode*m_pRoot;
  90. };
  91. voidBspTree::InitTreeRoot(TreeNode*pNode)
  92. {
  93. if(pNode==NULL)
  94. return;
  95. m_pRoot=pNode;
  96. }
  97. voidBspTree::DeleteNode(TreeNode*pNode)
  98. {
  99. if(pNode==NULL)
  100. return;
  101. DeleteNode(pNode->pLChild);
  102. DeleteNode(pNode->pRChild);
  103. deletepNode;
  104. }
  105. //遍历整个树
  106. voidBspTree::ErgodicTree(TreeNode*pNode)
  107. {
  108. if(pNode==NULL)
  109. return;
  110. ErgodicTree(pNode->pLChild);
  111. cout<<"节点深度:"<<pNode->nDepth<<"含有多少个面:"<<pNode->vFaceId.size();
  112. switch(pNode->Axis)
  113. {
  114. caseAxis_X:
  115. {
  116. cout<<"沿X轴分割"<<"分割点是:x="<<pNode->Split<<endl;
  117. break;
  118. }
  119. caseAxis_Y:
  120. {
  121. cout<<"沿Y轴分割"<<"分割点是:y="<<pNode->Split<<endl;
  122. break;
  123. }
  124. caseAxis_Z:
  125. {
  126. cout<<"沿Z轴分割"<<"分割点是:z="<<pNode->Split<<endl;
  127. break;
  128. }
  129. }
  130. ErgodicTree(pNode->pRChild);
  131. }
  132. voidBspTree::BuildAABB(TreeNode*pNode)
  133. {
  134. if(!pNode)
  135. return;
  136. pointMin(1000000,1000000,1000000);
  137. pointMax(-1000000,-1000000,-1000000);
  138. for(intn=0;n<pNode->vFaceId.size();++n)
  139. {
  140. face*pFa=GetFaceByID(n);
  141. if(pFa==NULL)
  142. continue;
  143. for(intm=0;m<3;++m)
  144. {
  145. if(pFa->P[m].x>Max.x)
  146. Max.x=pFa->P[m].x;
  147. if(pFa->P[m].y>Max.y)
  148. Max.y=pFa->P[m].y;
  149. if(pFa->P[m].z>Max.z)
  150. Max.z=pFa->P[m].z;
  151. if(pFa->P[m].x<Min.x)
  152. Min.x=pFa->P[m].x;
  153. if(pFa->P[m].y<Min.y)
  154. Min.y=pFa->P[m].y;
  155. if(pFa->P[m].z<Min.z)
  156. Min.z=pFa->P[m].z;
  157. }
  158. }
  159. pNode->box.Max=Max;
  160. pNode->box.Min=Min;
  161. }
  162. intCompareFloat(floata,floatb,floatfOff)
  163. {
  164. if(abs(a-b)<fOff)
  165. return0;
  166. if(a>b)
  167. return1;
  168. else
  169. return-1;
  170. }
  171. voidBspTree::SplitFace(intnFaceId,floatfSplit,intnAxis,int*pLeftNum,int*pRightNum,int*pBothNum)
  172. {
  173. face*pFace=GetFaceByID(nFaceId);
  174. intnLeftCount=0;
  175. intnRightCount=0;
  176. intnBothCount=0;
  177. floatt[3];
  178. switch(nAxis)
  179. {
  180. caseAxis_X:
  181. t[0]=pFace->P[0].x;
  182. t[1]=pFace->P[1].x;
  183. t[2]=pFace->P[2].x;
  184. break;
  185. caseAxis_Y:
  186. t[0]=pFace->P[0].y;
  187. t[1]=pFace->P[1].y;
  188. t[2]=pFace->P[2].y;
  189. break;
  190. caseAxis_Z:
  191. t[0]=pFace->P[0].z;
  192. t[1]=pFace->P[1].z;
  193. t[2]=pFace->P[2].z;
  194. break;
  195. }
  196. for(inti=0;i<3;i++)
  197. {
  198. intc=CompareFloat(t[i],fSplit,0.001f);
  199. if(c<0)//左边
  200. nLeftCount++;
  201. elseif(c>0)//右边
  202. nRightCount++;
  203. else//正中间
  204. nBothCount++;
  205. }
  206. *pLeftNum=nLeftCount;
  207. *pRightNum=nRightCount;
  208. *pBothNum=nBothCount;
  209. }
  210. voidBspTree::SplitSpace(TreeNode*pRoot,intnAxis,intndepth)
  211. {
  212. if(!pRoot)
  213. return;
  214. pRoot->nDepth=ndepth;
  215. pRoot->Axis=nAxis;
  216. if(pRoot->vFaceId.size()<3||ndepth>2)
  217. {
  218. pRoot->pLChild=NULL;
  219. pRoot->pRChild=NULL;
  220. return;
  221. }
  222. pRoot->pLChild=newTreeNode;
  223. pRoot->pRChild=newTreeNode;
  224. pRoot->pLChild->box.Max=pRoot->box.Max;
  225. pRoot->pLChild->box.Min=pRoot->box.Min;
  226. pRoot->pRChild->box.Max=pRoot->box.Max;
  227. pRoot->pRChild->box.Min=pRoot->box.Min;
  228. nAxis=(int)Axis_X;
  229. floatXLength=pRoot->box.Max.x-pRoot->box.Min.x;
  230. floatYLength=pRoot->box.Max.y-pRoot->box.Min.y;
  231. floatZLength=pRoot->box.Max.z-pRoot->box.Min.z;
  232. if(YLength>XLength)
  233. {
  234. nAxis=Axis_Y;
  235. XLength=YLength;
  236. }
  237. if(ZLength>XLength)
  238. {
  239. nAxis=Axis_Z;
  240. }
  241. floatfslit=0.0f;
  242. switch(nAxis)
  243. {
  244. caseAxis_X:
  245. {
  246. fslit=(pRoot->box.Max.x+pRoot->box.Min.x)/2.0;
  247. pRoot->pLChild->box.Max.x=fslit;
  248. pRoot->pRChild->box.Min.x=fslit;
  249. }break;
  250. caseAxis_Y:
  251. {
  252. fslit=(pRoot->box.Max.y+pRoot->box.Min.y)/2.0;
  253. pRoot->pLChild->box.Max.y=fslit;
  254. pRoot->pRChild->box.Min.y=fslit;
  255. }break;
  256. caseAxis_Z:
  257. {
  258. fslit=(pRoot->box.Max.z+pRoot->box.Min.z)/2.0;
  259. pRoot->pLChild->box.Max.z=fslit;
  260. pRoot->pRChild->box.Min.z=fslit;
  261. }break;
  262. }
  263. pRoot->Split=fslit;
  264. intnSize=pRoot->vFaceId.size();
  265. intnLeftCount,nRightCount,nBothCount;
  266. for(intn=0;n<nSize;++n)
  267. {
  268. SplitFace(pRoot->vFaceId.at(n),fslit,nAxis,&nLeftCount,&nRightCount,&nBothCount);
  269. //如果左边有
  270. if(nLeftCount>0||nBothCount>0)
  271. pRoot->pLChild->vFaceId.push_back(pRoot->vFaceId.at(n));
  272. if(nRightCount>0||nBothCount>0)
  273. pRoot->pRChild->vFaceId.push_back(pRoot->vFaceId.at(n));
  274. }
  275. pRoot->vFaceId.clear();
  276. //递归
  277. SplitSpace(pRoot->pLChild,nAxis,ndepth+1);
  278. SplitSpace(pRoot->pRChild,nAxis,ndepth+1);
  279. }
  280. int_tmain(intargc,_TCHAR*argv[])
  281. {
  282. BspTreebspTree;
  283. TreeNode*pRoot=newTreeNode;
  284. facefa;
  285. fa.P[0].x=-10;fa.P[0].y=-10;fa.P[0].z=-10;
  286. fa.P[1].x=2;fa.P[1].y=2;fa.P[1].z=2;
  287. fa.P[2].x=5;fa.P[2].y=5;fa.P[2].z=5;
  288. for(intn=0;n<16;++n)
  289. {
  290. if(n%5==0)
  291. fa+=2*(-n);
  292. else
  293. fa+=2*n;
  294. m_mFace[n]=fa;
  295. pRoot->vFaceId.push_back(n);
  296. }
  297. bspTree.InitTreeRoot(pRoot);
  298. bspTree.BuildAABB(pRoot);
  299. bspTree.SplitSpace(pRoot,0,0);
  300. bspTree.ErgodicTree(pRoot);
  301. getchar();
  302. return0;
  303. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值