89 lines
4.9 KiB
Markdown
89 lines
4.9 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](60-03.html) [Table of Contents](index.html) [Next](61-01.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
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.
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](60-03.html) [Table of Contents](index.html) [Next](61-01.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|