Initial conversion to markdown
This commit is contained in:
parent
a96a114403
commit
5e10794a24
362 changed files with 67353 additions and 0 deletions
125
59-02.md
Normal file
125
59-02.md
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
------------------------ --------------------------------- --------------------
|
||||
[Previous](59-01.html) [Table of Contents](index.html) [Next](59-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
Back-to-front or front-to-back traversal in itself wouldn’t be so
|
||||
impressive—there are many ways to do that—were it not for one additional
|
||||
detail: The traversal can always be performed in linear time, as we’ll
|
||||
see later on. For instance, you can traverse, a polygon list
|
||||
back-to-front from any viewpoint simply by walking through the
|
||||
corresponding BSP tree once, visiting each node one and only one time,
|
||||
and performing only one relatively inexpensive test at each node.
|
||||
|
||||
It’s hard to get cheaper sorting than linear time, and BSP-based
|
||||
rendering stacks up well against alternatives such as z-buffering,
|
||||
octrees, z-scan sorting, and polygon sorting. Better yet, a scene
|
||||
database represented as a BSP tree can be clipped to the view pyramid
|
||||
very efficiently; huge chunks of a BSP tree can be lopped off when
|
||||
clipping to the view pyramid, because if the entire area or volume of a
|
||||
node lies entirely outside the view volume, then *all* nodes and leaves
|
||||
that are children of that node must likewise be outside the view volume,
|
||||
for reasons that will become clear as we delve into the workings of BSP
|
||||
trees.
|
||||
|
||||
\
|
||||
**Figure 59.1** *The painter’s algorithm.*
|
||||
|
||||
#### Limitations of BSP Trees {#Heading5}
|
||||
|
||||
Powerful as they are, BSP trees aren’t perfect. By far the greatest
|
||||
limitation of BSP trees is that they’re time-consuming to build, enough
|
||||
so that, for all practical purposes, BSP trees must be precalculated,
|
||||
and cannot be built dynamically at runtime. In fact, a BSP-tree compiler
|
||||
that attempts to perform some optimization (limiting the number of
|
||||
surfaces that need to be split, for example) can easily take minutes or
|
||||
even hours to process large world databases.
|
||||
|
||||
A fixed world database is fine for walkthrough or flythrough
|
||||
applications (where the viewpoint moves through a static scene), but not
|
||||
much use for games or virtual reality, where objects constantly move
|
||||
relative to one another. Consequently, various workarounds have been
|
||||
developed to allow moving objects to appear in BSP tree-based scenes.
|
||||
DOOM, for example, uses 2-D sprites mixed into BSP-based 3-D scenes;
|
||||
note, though, that this approach requires maintaining z information so
|
||||
that sprites can be drawn and occluded properly. Alternatively, movable
|
||||
objects could be represented as separate BSP trees and merged anew into
|
||||
the world BSP tree with each move. Dynamic merging may or may not be
|
||||
fast enough, depending on the scene, but merging BSP trees tends to be
|
||||
quicker than building them, because the BSP trees being merged are
|
||||
already spatially sorted.
|
||||
|
||||
Another possibility would be to generate a per-pixel z-buffer for each
|
||||
frame as it’s rendered, to allow dynamically changing objects to be
|
||||
drawn into the BSP-based world. In this scheme, the BSP tree would allow
|
||||
fast traversal and clipping of the complex, static world, and the
|
||||
z-buffer would handle the relatively localized visibility determination
|
||||
involving moving objects. The drawback of this is the need for a
|
||||
memory-hungry z-buffer; a typical 640x480 z-buffer requires a fairly
|
||||
appalling 600K, with equally appalling cache-miss implications for
|
||||
performance.
|
||||
|
||||
Yet another possibility would be to build the world so that each dynamic
|
||||
object falls entirely within a single subspace of the static BSP tree,
|
||||
rather than straddling splitting lines or planes. In this case, dynamic
|
||||
objects can be treated as points, which are then just sorted into the
|
||||
BSP tree on the fly as they move.
|
||||
|
||||
The only other drawbacks of BSP trees that I know of are the memory
|
||||
required to store the tree, which amounts to a few pointers per node,
|
||||
and the relative complexity of debugging BSP-tree compilation and usage;
|
||||
debugging a large data set being processed by recursive code (which BSP
|
||||
code tends to be) can be quite a challenge. Tools like the BSP compiler
|
||||
I’ll present in the next chapter, which visually depicts the process of
|
||||
spatial subdivision as a BSP tree is constructed, help a great deal with
|
||||
BSP debugging.
|
||||
|
||||
### Building a BSP Tree {#Heading6}
|
||||
|
||||
Now that we know a good bit about what a BSP tree is, how it helps in
|
||||
visible surface determination, and what its strengths and weaknesses
|
||||
are, let’s take a look at how a BSP tree actually works to provide
|
||||
front-to-back or back-to-front ordering. This chapter’s discussion will
|
||||
be at a conceptual level, with plenty of figures; in the next chapter
|
||||
we’ll get into mechanisms and implementation details.
|
||||
|
||||
I’m going to discuss only 2-D BSP trees from here on out, because
|
||||
they’re much easier to draw and to grasp than their 3-D counterparts.
|
||||
Don’t worry, though; the principles of 2-D BSP trees using line segments
|
||||
generalize directly to 3-D BSP trees using polygons. Also, 2-D BSP trees
|
||||
are quite powerful in their own right, as evidenced by DOOM, which is
|
||||
built around 2-D BSP trees.
|
||||
|
||||
First, let’s construct a simple BSP tree. Figure 59.2 shows a set of
|
||||
four lines that will constitute our sample world. I’ll refer to these as
|
||||
walls, because that’s one easily-visualized context in which a 2-D BSP
|
||||
tree would be useful in a game. Think of Figure 59.2 as depicting
|
||||
vertical walls viewed from directly above, so they’re lines for the
|
||||
purpose of the BSP tree. Note that each wall has a front side, denoted
|
||||
by a normal (perpendicular) vector, and a back side. To make a BSP tree
|
||||
for this sample set, we need to split the world in two, then each part
|
||||
into two again, and so on, until each wall resides in its own unique
|
||||
subspace. An obvious question, then, is how should we carve up the world
|
||||
of Figure 59.2?
|
||||
|
||||
\
|
||||
**Figure 59.2** *A sample set of walls, viewed from above.*
|
||||
|
||||
There are infinitely valid ways to carve up Figure 59.2, but the
|
||||
simplest is just to carve along the lines of the walls themselves, with
|
||||
each node containing one wall. This is not necessarily optimal, in the
|
||||
sense of producing the smallest tree, but it has the virtue of
|
||||
generating the splitting lines without expensive analysis. It also saves
|
||||
on data storage, because the data for the walls can do double duty in
|
||||
describing the splitting lines as well. (Putting one wall on each
|
||||
splitting line doesn’t actually create a unique subspace for each wall,
|
||||
but it does create a unique subspace *boundary* for each wall; as we’ll
|
||||
see, that spatial organization provides for the same unambiguous
|
||||
visibility ordering as a unique subspace would.)
|
||||
|
||||
------------------------ --------------------------------- --------------------
|
||||
[Previous](59-01.html) [Table of Contents](index.html) [Next](59-03.html)
|
||||
------------------------ --------------------------------- --------------------
|
||||
|
||||
* * * * *
|
||||
|
||||
Graphics Programming Black Book © 2001 Michael Abrash
|
||||
Loading…
Reference in a new issue