World ModelingEDITOR'S NOTE FoundationsThe first stage of any graphics pipeline must be the world model. This stage is responsible for representing the objects in a simulation in some way that is efficient to process into pixels. Since the subsequent stages of the pipeline will vary based on the type of rendering being done, the world model must be chosen to accomodate the style of game being built.As we shall see, the two stages which have the greatest impact on world modeling design are hidden surface removal and texture mapping. For example, if the texture mapper is limited to working with scaled vertical spans (sometimes called slivers) a la Wolfenstein 3D, then the world model will necessarily be limited in certain ways. Styles of World ModelsIf we restrict ourselves to just first person 3D primarily indoor simulations (e.g. Wolfenstein 3D, Doom, Duke Nukem 3D, Descent, Quake), there are basically four main styles of world modeling being used today:
Occupancy GridThe occupancy grid model divides the level up into a two dimensional rectangular array (often of a convenient size like 64 x 64). Each element of the array defines the contents of a square region of space in the level (often encoded into a single byte value). Each element may contain a wall or door, an impassable object such as a table or bookcase, an enemy or powerup, or just empty floor. Because of the regularity of the grid, all objects in the world are exactly the same size (e.g. four feet by four feet), and the walls are limited to right angles. Usually the simple occupancy coding does not provide for variable heights, so all walls and rooms are exactly the same height (usually about eight feet).
Another distinct advantage to the occupancy grid model is the ease of creating level editors. A basic graphic level editor needs only to support placing different object types in a rectangular grid -- essentially, this is a fancy bitmap editor. It would even be possible to use an ASCII text file for the level data, with simple codes for the map cells. Although raycasting engines are simple and efficient, they are becoming less and less common in mainstream gaming. The limitations of the world model are just too severe for adequate visual realism, and today's hardware can easily cope with more complex environments.
Sector BasedSector based models are most commonly used in the commercial 3D games available today. Sector based models are often deprecated for being "flat" -- indeed Descent's curving mineshaft architecture can not be supported by a sector based model. Most next generation games (e.g. Quake) are switching to a more flexible CSG approach.IMHO, sector based models have not quite out-lived their usefulness. They offer several advantages over more complex schemes. They are well understood and easy to work with. Level editing programs are easier to write and use than 3D CSG modeling programs. Finally, most real-world architecture is designed using a "flat" floor plan that is very similar to the sector based model. Sector based models use a 2D polygonal map annotated with height information to define a game level. The fundamental unit of modeling is a polygonal sector, which defines a flat area of the map with a given floor height, ceiling height, and usually light level. The edges of the sector polygons (often referred to as segments) form the walls of the 3D world. Unlike the coarse grained occupancy grid model, each sector and segment are defined by a list of 2D vertices in a fine grained coordinate system. Each unit of the coordinate system is on the order of one inch (or about two to four centimeters) in real world metrics.
In general, the walls (i.e. sides) that surround a sector extend from the floor to the ceiling. Whenever two adjacent sectors share a common edge, a portal exists between the two spaces. In this case, the opening extends vertically from the maximum of the two floor heights to the minimum of the two ceiling heights. As a result, two polygons are needed instead of one:
Sector Data StructuresThere are four basic data structures used to encode the level design information: Vertex, Segment, Side, and Sector:The Vertex structure simply encodes a map location in 3D world space using two coordinates x, and y. Height information (the z coordinate) is encoded separately as needed by the other data structures. struct Vertex
{
int x, y; // world coordinates
};
The Segment structure describes one line segment of a sector. Each segment
connects exactly two vertices, "from" and "to". The normal vector of the
line connecting the "from" vertex to the "to" vertex points to the interior
of the sector. This is called the "right" side. If the segment is shared
by two sectors, then the side opposite the normal vector is used to surround
the second sector. This side is called the "left" side. All segments have
at least a "right" side. Two-sided segments also have a "left" side.
struct Segment
{
Vertex* verts[2]; // "from" and "to" verts
Side* sides[2]; // "right" and "left" sides
};
The Side structure defines the textured polygons that hang on the sides
of segments. In addition to reiterating the segment information, the side
structures identify the sector that they help surround. Most importantly
they contain pointers to the textures that will be used to render the resulting
polygons.
struct Side
{
short index; // unique identifier
Vertex* verts[2]; // "from" and "to" verts
Segment* segment; // segment that side is attached to
Sector* sector; // sector that side helps surround
Texture* texture_hi; // upper texture
Texture* texture_rg; // normal texture
Texture* texture_lo; // lower texture
};
Sectors are polygonal areas of uniform height and brightness. The Sector
structure contains floor and ceiling height values as well as an ambient
brightness level. They also contain texture pointers that describe how
to render the floor and ceiling polygons. Finally, they must contain pointers
to the Side structures that define the sector boundaries. Notice that the
Sector structure does not contain its own corner vertices, as these
can be derived from the Sides and Segments.
The Sector structure shown below also contains vertical adjustments (i.e. z values) for the floor and ceiling polygons at each corner vertex. This information allows the engine to support "sloped" floors in addition to flat ones. struct Sector
{
short index; // unique identifier
short floor; // floor height
short ceil; // ceiling height
short bright; // ambient light level
Texture* tex_ceil; // ceiling texture
Texture* tex_floor; // floor texture
Side* sides[MAX_VERTS]; // sides
short vfloor[MAX_VERTS]; // vertical adjustments for
short vceil[MAX_VERTS]; // floor and ceiling vertices
Sector* next; // link for sector list
};
Extensions to the Sector ModelThe Sector data structure above shows one common extension to the basic sector model: sloped floors and ceilings. Several additional extensions are possible, and will be briefly outlined.
The Alpha engine currently uses an extended sector model including sloped floors, solid objects, and sector-over-sector. In addition, the Alpha engine allows full six degrees of freedom for the player's viewpoint, and so requires a perspective correct texture mapper.
Connected CubesThe Connected Cubes world model goes a step beyond sector based approaches to model space as a collection of connected hollow volumes. Each volume is a simple convex polyhedron of six faces and eight vertices. Each cube is connected to at least one other by sharing a common face. As in the sector based model, shared faces form portals between adjacent volumes.
typedef struct segment {
side sides[6]; // 6 sides
short children[6]; // indices of 6 children segments:
// front, left, top, right, bottom, back
short verts[8]; // vertex ids of 4 front and 4 back vertices
short objects; // index of objects in this segment
ubyte special;
byte matcen_num;
short value;
fix static_light;
short pad;
} segment;
The connected cube model offers several advantages over the simpler sector
based model. Since each vertex is truly three dimensional, the cube model
allows for much more complex level design than sector based models. All
floors, walls, and ceilings are inherently sloped, and there is no limit
to the number or organization of portals in a "wall".
At the same time the connected cube model avoids the complex and espensive preprocessing phase of 3D BSP construction that is often needed for the brush based model. The cube adjacency information is sufficent to establish a valid drawing order for all polygons and all points of view as long as all of the cubes are convex. Also, the well defined four-sided portals implicit in the connections between neighboring cubes provide for an efficient screen-space beam tree HSR approach. About the only real disadvantages to this model are that it puts more burden on the level designer, and that it is not more widely supported. The first problem is that constructing simple architectural models is generally more work because the only graphic primitive is the six-sided polyhedron. The second problem is that since the model is not more widely used, it is not very widely written about. Therefore developing an efficient graphics pipeline for this model is a more speculative exercise.
CSG or Brush BasedThe final model we will examine is considered by many to be the "most 3D" of all. This family of models is called collectively CSG (Constructive Solid Geometry) or in the case of Quake "brush" based.In the general case, CSG models combine simple 3D primitives (e.g. cubes, tetraherda, cylinders, spheres) into more complex shapes by means of regularized Boolean set operators (e.g. union, intersection, negation, etc.). CSG models are typically stored as binary trees whose leaves are primitives and whose nodes are the operators that combine the subtrees:
The Quake engine uses a much more limited world model of "brushes"
for its MAP files. The brush based model is similar to the CSG
model, except that the only Boolean operator used is "union". Each primitive
object in the Each brush is defined by a set of intersecting planes (not polygons).
The BSP compiler calculates the polygon boundaries from the 3D plane intersections.
This simplifies brush definition in that each plane can be defined by three
nocolinear points, regardless of the number of vertices needed to describe
the resulting polygon:
Each brush statement looks like this:
The Quake world model appears to allow for the translation of
each brush along any axis, but not for rotation or overall scaling.
Needless to say, constructing a complex world from a collection of polyhedral
primitives is no small task. Much of the challenge of using such a flexible
world model lies in creating efficient tools for level designers. It will
be interesting to see the solutions provided by Quake and UNREAL
level editors as they become available.
As raycasting engines die out, so one would imagine will spacial occupancy
grid models. Likewise, connected cube models have never really caught on,
despite their interesting capabilities. Most new game engines are abandoning
the venerable sector based model for some flavor of CSG. Perhaps the best
approach is some sort of hybrid. It all depends on the needs of a particular
game.
Hosted by Irth Networks - http://www.irth.net |