77 lines
4.4 KiB
Markdown
77 lines
4.4 KiB
Markdown
Listing 60.1 isn't very long or complex, but it's somewhat more
|
|
complicated than it could be because it's structured to allow visual
|
|
display of the ongoing compilation process. That's because Listing 60.1
|
|
is actually just a part of a BSP compiler for Win32 that visually
|
|
depicts the progressive subdivision of space as the BSP tree is built.
|
|
(Note that Listing 60.1 might not compile as printed; I may have missed
|
|
copying some global variables that it uses.) The complete code is too
|
|
large to print here in its entirety, but it's on the CD-ROM in file
|
|
DDJBSP.ZIP.
|
|
|
|
### Optimizing the BSP Tree {#Heading7}
|
|
|
|
In the previous chapter, I promised that I'd discuss how to go about
|
|
deciding which wall to use as the splitter at each node in constructing
|
|
a BSP tree. That turns out to be a far more difficult problem than one
|
|
might think, but we can't ignore it, because the choice of splitter can
|
|
make a huge difference.
|
|
|
|
Consider, for example, a BSP in which the line or plane of the splitter
|
|
at the root node splits every single other surface in the world,
|
|
doubling the total number of surfaces to be dealt with. Contrast that
|
|
with a BSP built from the same surface set in which the initial splitter
|
|
doesn't split anything. Both trees provide a valid ordering, but one
|
|
tree is much larger than the other, with twice as many polygons after
|
|
the selection of just one node. Apply the same difference again to each
|
|
node, and the relative difference in size (and, correspondingly, in
|
|
traversal and rendering time) soon balloons astronomically. So we need
|
|
to do *something* to optimize the BSP tree—but what? Before we can try
|
|
to answer that, we need to know exactly what we'd like to optimize.
|
|
|
|
There are several possible optimization objectives in BSP compilation.
|
|
We might choose to balance the tree as evenly as possible, thereby
|
|
reducing the average depth to which the tree must be traversed.
|
|
Alternatively, we might try to approximately balance the area or volume
|
|
on either side of each splitter. That way we don't end up with huge
|
|
chunks of space in some tree branches and tiny slivers in others, and
|
|
the overall processing time will be more consistent. Or, we might choose
|
|
to select planes aligned with the major axes, because such planes can
|
|
help speed up our BSP traversal.
|
|
|
|
The BSP metric that seems most useful to me, however, is the number of
|
|
polygons that are split into two polygons in the course of building a
|
|
BSP tree. Fewer splits is better; the tree is smaller with fewer
|
|
polygons, and drawing will go faster with fewer polygons to draw, due to
|
|
per-polygon overhead. There's a problem with the fewest-splits metric,
|
|
though: There's no sure way to achieve it.
|
|
|
|
The obvious approach to minimizing polygon splits would be to try all
|
|
possible trees to find the best one. Unfortunately, the order of that
|
|
particular problem is N!, as I found to my dismay when I implemented
|
|
brute-force optimization in the first version of my BSP compiler. Take a
|
|
moment to calculate the number of operations for the 20-polygon set I
|
|
originally tried brute-force optimization on. I'll give you a hint:
|
|
There are 19 digits in 20!, and if each operation takes only one
|
|
microsecond, that's over 70,000 years (or, if you prefer, over 500,000
|
|
dog years). Now consider that a single game level might have 5,000 to
|
|
10,000 polygons; there aren't anywhere near enough dog years in the
|
|
lifetime of the universe to handle that. We're going to have to give up
|
|
on optimal compilation and come up with a decent heuristic approach, no
|
|
matter what optimization objective we select.
|
|
|
|
In Listing 60.1, I've applied the popular heuristic of choosing as the
|
|
splitter at each node the surface that splits the fewest of the other
|
|
surfaces that are being considered for that node. In other words, I
|
|
choose the wall that splits the fewest of the walls in the subspace it's
|
|
subdividing.
|
|
|
|
### BSP Optimization: an Undiscovered Country {#Heading8}
|
|
|
|
Although BSP trees have been around for at least 15 years now, they're
|
|
still only partially understood and are a ripe area for applied research
|
|
and general ingenuity. You might want to try your hand at inventing new
|
|
BSP optimization approaches; it's an interesting problem, and you might
|
|
strike paydirt. There are many things that BSP trees can't do well,
|
|
because it takes so long to build them—but what they do, they do
|
|
exceedingly well, so a better compilation approach that allowed BSP
|
|
trees to be used for more purposes would be valuable, indeed.
|