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: