BSP

Brief of Binary Space Partitioning.

Target: examine the areas where one can draw advantages of the structure supplied and study the generating process.

Drawbacks: BSP is static and it is very expensive to modify during run-time.

 

What is BSP-tree?

In the beginning of the 90’s the main reason BSP-trees were being used was that they sorted the polygons in the scene so that you always drew back-to-front, meaning that the polygon with the lowest Z-value[*] was drawn last. There are other ways to sort the polygons so that the closest polygon is drawn last, for example the Painter’s algorithm[3], but few are as cheap as BSP-trees, because the sorting of the polygons is done during the pre-processing[*] of the map and not under run-time. The algorithm for generating a BSP-tree is actually an extension of Painter’s algorithm[5].

 

How to split?

There are several ways to split up the set of polygons into smaller subsets. For example, you can choose an arbitrary plane in space and divide the polygons by putting the ones on the positive side of the plane in the right sub tree and the polygons on the negative side in the left sub tree. The problem with this approach is that it is very difficult to find a plane that divides the polygons into two approximately equally sized sets, since there are an infinite set of planes in space. So the most common way to do this is by taking one of the polygons in the scene and dividing the polygons according to the plane that polygon defines.

 

How to choose ploygon?

When a BSP-tree is created, one has to decide whether the need is of a balanced tree, meaning that there should not be too big a difference in depth between the left and the right sub tree of each node, or try to limit the number of splits, since each split creates new polygons. If too many new polygons is created during the BSP-tree creation the graphic card will have a hard time rendering the map, thus reducing the frame rate, while a unbalanced tree will require more expensive traversal of the tree. We decided to accept a certain number of splits in order to get a more balanced tree. But the main concern was reducing the number of new polygons created.

   1: CHOOSE-DIVIDING-POLYGON
   2:  Indata:
   3:    PolygonSet – The set of polygons to search for the best dividing polygon.
   4:  Outdata:
   5:    The best dividing polygon
   6:  Effect:
   7:    Searches through the set of polygons and returns the polygons that
   8:    splits the set into the two best resulting sets. If the set is
   9:    convex no polygon can be returned.
  10:  
  11: HOOSE-DIVIDING-POLYGON (PolygonSet)
  12:   if (IS-CONVEX-SET (PolygonSet))
  13:       then return NOPOLYGON
  14:   MinRelation = MINIMUMRELATION
  15:   BestPolygon = NOPOLYGON
  16:   LeastSplits = INFINITY
  17:   BestRelation = 0
  18:   // Loop to find the polygon that best divides the set.
  19:   while(BestPolygon = NOPOLYGON)
  20:       for each polygon P1 in PolygonSet
  21:           if (Polygon P1 has not been used as divider previously
  22:               during the creation of the tree)
  23:  
  24:               // Count the number of polygons on the positive side, negative side
  25:               // of and spanning the plane defined by the current polygon.
  26: 0             NumPositive = 0, NumNegative = 0, NumSpanning = 0
  27: 1             for each polygon P2 in PolygonSet except P1
  28: 2                 Value = CALCULATE-SIDE(P1, P2)
  29: 3                 if(Value = INFRONT)
  30: 4                     NumPositive = NumPositive + 1
  31: 5                 else if(Value = BEHIND)
  32: 6                     NumNegative = NumNegative + 1
  33: 7                 else if(Value = SPANNING)
  34: 8                     NumSpanning = NumSpanning + 1
  35:  
  36:           // Calculate the relation between the number of polygons in the two
  37:           // sets divided by the current polygon.
  38: 9         if (NumPositive < NumNegative)
  39: 0             Relation = NumPositive / NumNegative
  40: 1         else
  41: 2             Relation = NumNegative / NumPositive
  42:  
  43:           // Compare the results given by the current polygon to the best this
  44:           // far. If the this polygon splits fewer polygons and the relation
  45:           // between the resulting sets is acceptable this is the new candidate
  46:           // polygon. If the current polygon splits the same amount of polygons
  47:           // as the best polygon this far and the relation between the two
  48:           // resulting sets is better -> this polygon is the new candidate
  49:           // polygon.
  50: 3         if (Relation > MinRelation && (NumSpanning < LeastSplits ||
  51:               NumSpanning = LeastSplits && Relation > BestRelation))
  52: 4            BestPolygon = P1
  53: 5            LeastSplits = NumSpanning
  54: 6            BestRelation = Relation
  55:  
  56:       // Decrease the number least acceptable relation by dividing it with
  57:       // a predefined constant.
  58: 7     MinRelation = MinRelation / MINRELATIONSCALE
  59: 8 return BestPolygon

What is the complexity?

Assume that the initial value for MinRelation is 1, which is the highest possible value since the relation is always between 0 and 1, so:

1 / MINRELATIONSCALEi < 1/(n-1)
1 < MINRELATIONSCALEi/(n-1)
(n-1) < MINRELATIONSCALEi
logMINRELATIONSCALE (n-1) < i

This is no upper bound for i, but since i will be very close to logMINRELATIONSCALE (n-1) we will, for simplicity assume they are equal. Another practical assumption to make is that MINRELATIONSCALEalways should be greater than or equal to 2. Thus giving us:

logMINRELATIONSCALE (n-1) = i MINRELATIONSCALE >= 2
i = logMINRELATIONSCALE (n-1) < lg(n-1) = O(lg n)

So这个算法的时间复杂度是O(n^2 *lg n), 算法中要选择恰当的MINIMUBERELATION, MINRELATIONSCALE.

 

How to build BSP-Tree?

   1: ► GENERATE-BSP-TREE
   2: * Indata:
   3: *   Node - The sub tree to build of the type BSPTreeNode.
   4: *   PolygonSet – The set of polygons to create a BSP-tree from.
   5: * Outdata:
   6: *   A BSP-tree stored in the incoming node.
   7: * Effect:
   8: *   Generates a BSP-tree out of a set of polygons.
   9:  
  10: GENERATE-BSP-TREE (Node, PolygonSet)
  11: 1  if (IS-CONVEX-SET (PolygonSet))
  12: 2      Tree = BSPTreeNode (PolygonSet)
  13: 3  Divider = CHOOSE-DIVIDING-POLYGON (PolygonSet)
  14: 4  PositiveSet = {}
  15: 5  NegativeSet = {}
  16: 6  for each polygon P1 in PolygonSet
  17: 7      Value f CALCULATE-SIDE (Divider, P1)
  18: 8      if(Value = INFRONT)
  19: 9          PositiveSet = PositiveSet U P1
  20: 10     else if (Value = BEHIND)
  21: 11         NegativeSet = NegativeSet U P1
  22: 12     else if (Value = SPANNING)
  23: 13         Split_Polygon (P1, Divider, Front, Back)
  24: 14         PositiveSet = PositiveSet U Front
  25: 15         NegativeSet = NegativeSet U Back
  26: 16 GENERATE-BSP-TREE (Tree.RightChild, PositiveSet)
  27: 17 GENERATE-BSP-TREE (Tree.LeftChild, NegativeSet)

时间复杂度T(n) = 1/2T(1/2*n) + O(n^2lgn). 由递归树求得T(n) = O(n^2lgn)

 

Using BSP-Tree to draw the scene.

   1: DRAW-BSP-TREE
   2:  Indata:
   3:    Node – The node to draw.
   4:    Position – The viewer’s position.
   5:  Outdata:
   6:    None
   7:  Effect:
   8:    Draws the polygons contained in the node and its sub trees.
   9:  
  10: RAW-BSP-TREE (Node, Position)
  11:   if (IS-LEAF(Node))
  12:       DRAW-POLYGONS (Node.PolygonSet)
  13:       return
  14:  
  15:   // Calculate which sub tree the viewer is in.
  16:   Side = CLASSIFY-POINT (Node.Divider, Position)
  17:  
  18:   // If the viewer is in the right sub tree draw that tree before the
  19:   // left.
  20:   if (Side = INFRONT || Side = COINCIDING)
  21:       DRAW-BSP-TREE (Node.RightChild, Position)
  22:       DRAW-BSP-TREE (Node.LeftChild, Position)
  23:  
  24:   // Otherwise draw the left first.
  25:   else if(Value = BEHIND)
  26:       DRAW-BSP-TREE (Node.LeftChild, Position)
  27: 0     DRAW-BSP-TREE (Node.RightChild, Position)

REFERENCE:

http://www.devmaster.net/articles/bsp-trees/#Reference

posted @ 2011-09-17 19:52  nickolas  阅读(722)  评论(0编辑  收藏  举报