Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
89
60-04.md
Normal file
89
60-04.md
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[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
|
||||
Loading…
Reference in a new issue