新人补钙系列教程之:3D理论

1. 什么是BSP树

BSP算法的初始数据是一个多边形集,BSP在预处理的时候先在多边形集中选取一个多边形作为支持平面,然后根据这个平面将集合划分成两个部分,每个部分是一个新的子节点,递归进行该过程,直到每个子节点中的多边形都构成一个凸区域(最小凸边型),每个区域是一个叶节点,或成为cell,然后算法预计算在每个区域中可以见到哪些区域,得到PVS(潜在可见集)。

<IGNORE_JS_OP style="WORD-WRAP: break-word; WHITE-SPACE: normal; TEXT-TRANSFORM: none; WORD-SPACING: 0px; COLOR: rgb(51,51,51); FONT: 14px/21px Tahoma, Helvetica, SimSun, sans-serif; ORPHANS: 2; WIDOWS: 2; LETTER-SPACING: normal; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke- 0px">bsp.jpg 

BSP可以说是八叉树的一般化

每个节点都是一条直线.所有在直线左边的东东都在它的左子树上,所有在它右边的东东都在它的右子树上.

<IGNORE_JS_OP style="WORD-WRAP: break-word; WHITE-SPACE: normal; TEXT-TRANSFORM: none; WORD-SPACING: 0px; COLOR: rgb(51,51,51); FONT: 14px/21px Tahoma, Helvetica, SimSun, sans-serif; ORPHANS: 2; WIDOWS: 2; LETTER-SPACING: normal; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke- 0px">2010.jpg 

好,我们用BSP树来想象一幅画面.

假设玩家站在D房间里面向屏幕右方,代号为点'x'

<IGNORE_JS_OP style="WORD-WRAP: break-word; WHITE-SPACE: normal; TEXT-TRANSFORM: none; WORD-SPACING: 0px; COLOR: rgb(51,51,51); FONT: 14px/21px Tahoma, Helvetica, SimSun, sans-serif; ORPHANS: 2; WIDOWS: 2; LETTER-SPACING: normal; BACKGROUND-COLOR: rgb(255,255,255); TEXT-INDENT: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke- 0px">bsp2.jpg 

我们从树的顶端直线 f 开始.我们站在直线 f 的右边,所以我们向树的左子

树进行下去.这是因为我们想最先画最远的多边形.

我们来到了最左的节点.请在笔记本上记下节点上的东东--"a,c"

当我们不能再往下时,回到父节点.现在回到了根节点,我们还不能马上去右子树.
首先,我们看见了 f 面--写在这个节点上的.我们已经在我们列出的表上得到了
处在它后面的所有东东,我们还将看见它前面的东东,但是我们必须先把它记入我
们的表中.注意,f 面有两个表面--f' 和 f".既然我们已经知道我们处在直线 f
的右边,当然就只能看到它的右表面--所以我们在笔记本上记下 f"( 右面 ).现在本子上
写着 a,c,f".

如果我们以这个次序来画这些墙,将得到正确的图象.建议你使用3D-buffer,这样速度要快的多.

下面是搜索 BSP 树的伪代码:

  1. struct BSP_tree
  2. {
  3. plane     partition;
  4. list      polygons;
  5. BSP_tree  *front, *back;
  6. };
  7. 这个结构体定义在下面的讨论中将被一直使用。它[来源:GameRes.com]表示BSP树的一个接点,包含有一个分割平面,处于分割平面的多边形列表,以及指向子接点的指针。
  8. void Buld_BSP_Tree( BSP_tree *tree, list polygons )
  9. {
  10.     polygon *root = polygons.Get_From_List();
  11.     tree->partition = root->Get_Plane();
  12.     tree->polygons.Add_To_List( root );
  13.     list front_list, back_list;
  14.     polygon  *poly;
  15.     while( ( poly = polygons.Get_From_List() ) != 0 )
  16.     {
  17. int result = tree->partition.Classify_polygon(poly);
  18. switch( result )
  19. {
  20. case COINCIDENT: // 共面
  21.      tree->polygons.Add_To_List(poly);
  22.      break;
  23. case IN_BACK_OF:
  24.      back_list.Add_To_List(poly);
  25.      break;
  26. case IN_FRONT_OF
  27.      front_list.Add_To_List(poly);
  28.      break;
  29. case SPANNING:
  30.      polygon *front_piece, *back_piece;
  31.    split_Polygon( poly, tree->partition, front_piece, back_piece );
  32.      back_list.Add_To_List( back_piece );
  33.      front_list.Add_To_List( front_piece );
  34.      break;
  35. }
  36.        }
  37.        if( !front_list.Is->Empty_List() )
  38.        {
  39. tree->front = new BSP_tree;
  40. Build_BSP_Tree( tree->front, front_list );
  41.        }
  42.        if( !back_list->Is_Empty_List() )
  43.        {
  44. tree->back = new BSP_tree;
  45. Build_BSP_Tree( tree->back, back_list );
  46.        }
  47. }
  48. Buld_BSP_Tree函数根据以上说明的步骤递归地建立BSP树。它使用输入的多边形列表中的第一个多边形所在的平面作为分割平面,假定此列表中的每一个多边形都为凸多边形。
复制代码

代码来源于网络

原文地址:https://www.cnblogs.com/keng333/p/3170238.html