129 lines
7.5 KiB
Markdown
129 lines
7.5 KiB
Markdown
------------------------ --------------------------------- --------------------
|
||
[Previous](69-04.html) [Table of Contents](index.html) [Next](70-02.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
Chapter 70\
|
||
Quake: A Post-Mortem and a Glimpse into the Future {#Heading1}
|
||
---------------------------------------------------
|
||
|
||
*Why did not any of the children in the first group think of this faster
|
||
method of going across the room? It is simple. They looked at what they
|
||
were given to use for materials and, they are like all of us, they
|
||
wanted to use everything. But they did not need everything. They could
|
||
do better with less, in a different way.*
|
||
|
||
—*Frederik Pohl*, The Gold at the Starbow’s End
|
||
|
||
Eleven years ago, I started the first serious graphics article I ever
|
||
wrote with the above quote. The point I was making at the time was that
|
||
programming assumptions based on high-level languages or other
|
||
processors had to be discarded in the quest for maximum x86 performance.
|
||
While that’s certainly still true, time and the microcomputer world have
|
||
moved on, and today there’s a more important lesson 3-D game programmers
|
||
can draw from Frederik Pohl’s words. Nowadays, CPUs, 3-D hardware, 3-D
|
||
algorithms, and 3-D data structures are evolving so rapidly that the
|
||
enemy is now often the assumptions and techniques from the last
|
||
product—and sometimes the assumptions and techniques in the *current*
|
||
product. We all feel most comfortable with techniques we’ve already
|
||
mastered, but leading-edge 3-D game technology is such a delicate
|
||
balancing act between performance, features (particularly with game
|
||
designers always wanting to add more), and workflow (as we’ll see,
|
||
preprocessing that improves performance often hurts designer
|
||
productivity) that it’s never safe to stop looking for a better approach
|
||
until the game has actually shipped. Change is the rule, and we must
|
||
always be looking to “do better with less, in a different way.”
|
||
|
||
I’ve talked about Quake’s technology elsewhere in this book, However,
|
||
those chapters focused on specific areas, not overall structure.
|
||
Moreover, Quake changed in significant ways between the writing of those
|
||
chapters and the final shipping. Then, after shipping, Quake was ported
|
||
to 3-D hardware. And the post-Quake engine, code-named Trinity, is
|
||
already in development at this writing (Spring 1997), with some
|
||
promising results. So in wrapping up this book, I’ll recap Quake’s
|
||
overall structure relatively quickly, then bring you up to date on the
|
||
latest developments. And in the spirit of Frederik Pohl’s quote, I’ll
|
||
point out that we implemented and discarded at least half a dozen 3-D
|
||
engines in the course of developing Quake (and all of Quake’s code was
|
||
written from scratch, rather than using Doom code), and almost switched
|
||
to another one in the final month, as I’ll describe later. And even at
|
||
this early stage, Trinity uses almost no Quake technology.
|
||
|
||
In fact, I’ll take this opportunity to coin Carmack’s Law, as follows:
|
||
*Fight code entropy*. If you have a new fundamental assumption, throw
|
||
away your old code and rewrite it from scratch. Incremental patching and
|
||
modifying seems easier at first, and is the normal course of things in
|
||
software development, but ends up being much harder and producing
|
||
bulkier, markedly inferior code in the long run, as we’ll see when we
|
||
discuss the net code for QuakeWorld. It may seem safer to modify working
|
||
code, but the nastiest bugs arise from unexpected side effects and
|
||
incorrect assumptions, which almost always arise in patched-over code,
|
||
not in code designed from the ground up. Do the hard work up front to
|
||
make your code simple, elegant, great—and just plain *right*—and it’ll
|
||
pay off many times over in the long run.
|
||
|
||
Before I begin, I’d like to remind you that all of the Doom and Quake
|
||
material I’m presenting in this book is presented in the spirit of
|
||
sharing information to make our corner of the world a better place for
|
||
everyone. I’d like to thank John Carmack, Quake’s architect and lead
|
||
programmer, and id Software for allowing me to share this technology
|
||
with you, and I encourage you to share your own insights by posting on
|
||
the Internet and writing books and articles whenever you have the
|
||
opportunity and the right to do so. (Of course, check with your employer
|
||
first!) We’ve all benefited greatly from the shared wisdom of people
|
||
like Knuth, Foley and van Dam, Jim Blinn, Jim Kajiya, and hundreds of
|
||
others—are you ready to take a shot at making your own contribution to
|
||
the future?
|
||
|
||
### Preprocessing the World {#Heading2}
|
||
|
||
For the most part, I’ll discuss Quake’s 3-D engine in this chapter,
|
||
although I’ll touch on other areas of interest. For 3-D rendering
|
||
purposes, Quake consists of two basic sorts of objects: the world, which
|
||
is stored as a single BSP model and never changes shape or position; and
|
||
potentially moving objects, called *entities*, which are drawn in
|
||
several different ways. I’ll discuss each separately.
|
||
|
||
The world is constructed from a set of brushes, which are n-sided convex
|
||
polyhedra placed in a level by a designer using a map editor, with a
|
||
selectable texture on each face. When a level is completed, a
|
||
preprocessing program combines all brushes to form a skin around the
|
||
solid areas of the world, so there is no interpenetration of polygons,
|
||
just a continuous mesh delineating solid and empty areas. Once this is
|
||
done, the next step is generating a BSP tree for the level.
|
||
|
||
The BSP consists of splitting planes aligned with polygons, called
|
||
nodes, and of leaves, which are the convex subspaces into which all the
|
||
nodes carve space. The top node carves the world into two subspaces, and
|
||
divides the remaining polygons into two sets, splitting any polygon that
|
||
spans the node into two pieces. Each subspace is then similarly split by
|
||
one node each, and so on until all polygons have been used to create
|
||
nodes. A node’s subspace is the total space occupied by all its
|
||
children: the subspace that the node splits into two parts, and that its
|
||
children continue to subdivide. When the only polygon in a node’s
|
||
subspace is the polygon that splits the subspace—the polygon whose plane
|
||
defines the node—then the two child subspaces are called leaves, and are
|
||
not divided any further.
|
||
|
||
The BSP tree is built using the polygon that splits the fewest of the
|
||
polygons in the current node’s subspace as the heuristic for choosing
|
||
splitters, which is not an optimal solution—but an optimal solution is
|
||
NP-complete, and our heuristic adds only 10% to 15% more polygons to the
|
||
level as a result of BSP splits. Polygons are not split all the way into
|
||
leaves; rather, they are placed on the nodes with which they are
|
||
coplanar (one set on the front and one on the back, which has the
|
||
advantage of letting us reuse the BSP-walking dot product for backface
|
||
culling as well), thereby reducing splitting considerably, because
|
||
polygons are split only by parent nodes, not by child nodes (as would be
|
||
necessary if polygons were split into leaves). Eliminating polygon
|
||
splits, thus reducing the total number of polygons per level, not only
|
||
shrinks Quake’s memory footprint, but also reduces the number of
|
||
polygons that need to be processed by the 3-D pipeline, producing a
|
||
speedup of about 10% in Quake’s overall performance.
|
||
|
||
------------------------ --------------------------------- --------------------
|
||
[Previous](69-04.html) [Table of Contents](index.html) [Next](70-02.html)
|
||
------------------------ --------------------------------- --------------------
|
||
|
||
* * * * *
|
||
|
||
Graphics Programming Black Book © 2001 Michael Abrash
|